From 092cb34745c03b22e0882a36b798a307b5afd905 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Aug 2021 05:11:30 +0000 Subject: [PATCH 01/25] Bump typescript from 4.3.5 to 4.4.2 (#55) --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index ca530a0..e249c45 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41,7 +41,7 @@ "react-router-dom": "^5.2.0", "react-scripts": "4.0.3", "serve": "^12.0.0", - "typescript": "^4.3.5", + "typescript": "^4.4.2", "use-keyboard-shortcut": "^1.0.6", "web-vitals": "^1.0.1" }, @@ -17936,9 +17936,9 @@ } }, "node_modules/typescript": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", - "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.2.tgz", + "integrity": "sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -31456,9 +31456,9 @@ } }, "typescript": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", - "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==" + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.2.tgz", + "integrity": "sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ==" }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4" diff --git a/package.json b/package.json index 31ea1ac..a7855e2 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "react-router-dom": "^5.2.0", "react-scripts": "4.0.3", "serve": "^12.0.0", - "typescript": "^4.3.5", + "typescript": "^4.4.2", "use-keyboard-shortcut": "^1.0.6", "web-vitals": "^1.0.1" }, From 21242ef85d0aff09f31f3d162b6724c28809c83c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Aug 2021 05:16:05 +0000 Subject: [PATCH 02/25] Bump @types/react from 17.0.17 to 17.0.19 (#51) --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index e249c45..6f20282 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,7 +25,7 @@ "@testing-library/user-event": "^12.1.10", "@types/jest": "^26.0.24", "@types/node": "^14.17.5", - "@types/react": "^17.0.17", + "@types/react": "^17.0.19", "@types/react-blockies": "^1.4.1", "@types/react-dom": "^17.0.9", "@types/react-router-dom": "^5.1.8", @@ -3063,9 +3063,9 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "17.0.17", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.17.tgz", - "integrity": "sha512-nrfi7I13cAmrd0wje8czYpf5SFbryczCtPzFc6ijqvdjKcyA3tCvGxwchOUlxb2ucBPuJ9Y3oUqKrRqZvrz0lw==", + "version": "17.0.19", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.19.tgz", + "integrity": "sha512-sX1HisdB1/ZESixMTGnMxH9TDe8Sk709734fEQZzCV/4lSu9kJCPbo2PbTRoZM+53Pp0P10hYVyReUueGwUi4A==", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -21377,9 +21377,9 @@ "version": "1.5.4" }, "@types/react": { - "version": "17.0.17", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.17.tgz", - "integrity": "sha512-nrfi7I13cAmrd0wje8czYpf5SFbryczCtPzFc6ijqvdjKcyA3tCvGxwchOUlxb2ucBPuJ9Y3oUqKrRqZvrz0lw==", + "version": "17.0.19", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.19.tgz", + "integrity": "sha512-sX1HisdB1/ZESixMTGnMxH9TDe8Sk709734fEQZzCV/4lSu9kJCPbo2PbTRoZM+53Pp0P10hYVyReUueGwUi4A==", "requires": { "@types/prop-types": "*", "@types/scheduler": "*", diff --git a/package.json b/package.json index a7855e2..bc42e0e 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "@testing-library/user-event": "^12.1.10", "@types/jest": "^26.0.24", "@types/node": "^14.17.5", - "@types/react": "^17.0.17", + "@types/react": "^17.0.19", "@types/react-blockies": "^1.4.1", "@types/react-dom": "^17.0.9", "@types/react-router-dom": "^5.1.8", From 6fa8e2b907a99811bcec4d2225064434513b517d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Aug 2021 05:16:17 +0000 Subject: [PATCH 03/25] Bump @fontsource/fira-code from 4.5.0 to 4.5.1 (#53) --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6f20282..7408f27 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "dependencies": { "@chainlink/contracts": "^0.2.1", "@craco/craco": "^6.2.0", - "@fontsource/fira-code": "^4.5.0", + "@fontsource/fira-code": "^4.5.1", "@fontsource/roboto": "^4.5.0", "@fontsource/roboto-mono": "^4.5.0", "@fontsource/space-grotesk": "^4.5.0", @@ -1993,9 +1993,9 @@ } }, "node_modules/@fontsource/fira-code": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/@fontsource/fira-code/-/fira-code-4.5.0.tgz", - "integrity": "sha512-fxRV3qt0eJaIXZvICXZMhXVR0lSyxZTC0cnM+1Ma/1JShGrIjCQ3yJ0W05rwaEoF3cAbpU2lKMrXfE7Of/zpIA==" + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@fontsource/fira-code/-/fira-code-4.5.1.tgz", + "integrity": "sha512-8KTCsfs5m3UgICpHLglIKAS7vc2FFOu7/vvpWcE/42SWbh+9X8EJbEyJp6W96kU5iDVlAlUv4Cqc36Z9XUpLmA==" }, "node_modules/@fontsource/roboto": { "version": "4.5.0", @@ -20678,9 +20678,9 @@ } }, "@fontsource/fira-code": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/@fontsource/fira-code/-/fira-code-4.5.0.tgz", - "integrity": "sha512-fxRV3qt0eJaIXZvICXZMhXVR0lSyxZTC0cnM+1Ma/1JShGrIjCQ3yJ0W05rwaEoF3cAbpU2lKMrXfE7Of/zpIA==" + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@fontsource/fira-code/-/fira-code-4.5.1.tgz", + "integrity": "sha512-8KTCsfs5m3UgICpHLglIKAS7vc2FFOu7/vvpWcE/42SWbh+9X8EJbEyJp6W96kU5iDVlAlUv4Cqc36Z9XUpLmA==" }, "@fontsource/roboto": { "version": "4.5.0", diff --git a/package.json b/package.json index bc42e0e..dbe2154 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "dependencies": { "@chainlink/contracts": "^0.2.1", "@craco/craco": "^6.2.0", - "@fontsource/fira-code": "^4.5.0", + "@fontsource/fira-code": "^4.5.1", "@fontsource/roboto": "^4.5.0", "@fontsource/roboto-mono": "^4.5.0", "@fontsource/space-grotesk": "^4.5.0", From 472ea10142b8492736bb45a041536a260d8b4135 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Aug 2021 05:17:03 +0000 Subject: [PATCH 04/25] Bump chart.js from 3.5.0 to 3.5.1 (#50) --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7408f27..1859ef2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,7 +29,7 @@ "@types/react-blockies": "^1.4.1", "@types/react-dom": "^17.0.9", "@types/react-router-dom": "^5.1.8", - "chart.js": "^3.5.0", + "chart.js": "^3.5.1", "ethers": "^5.4.1", "query-string": "^7.0.1", "react": "^17.0.2", @@ -5530,9 +5530,9 @@ } }, "node_modules/chart.js": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.5.0.tgz", - "integrity": "sha512-J1a4EAb1Gi/KbhwDRmoovHTRuqT8qdF0kZ4XgwxpGethJHUdDrkqyPYwke0a+BuvSeUxPf8Cos6AX2AB8H8GLA==" + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.5.1.tgz", + "integrity": "sha512-m5kzt72I1WQ9LILwQC4syla/LD/N413RYv2Dx2nnTkRS9iv/ey1xLTt0DnPc/eWV4zI+BgEgDYBIzbQhZHc/PQ==" }, "node_modules/check-types": { "version": "11.1.2", @@ -23101,9 +23101,9 @@ "version": "1.0.2" }, "chart.js": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.5.0.tgz", - "integrity": "sha512-J1a4EAb1Gi/KbhwDRmoovHTRuqT8qdF0kZ4XgwxpGethJHUdDrkqyPYwke0a+BuvSeUxPf8Cos6AX2AB8H8GLA==" + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.5.1.tgz", + "integrity": "sha512-m5kzt72I1WQ9LILwQC4syla/LD/N413RYv2Dx2nnTkRS9iv/ey1xLTt0DnPc/eWV4zI+BgEgDYBIzbQhZHc/PQ==" }, "check-types": { "version": "11.1.2" diff --git a/package.json b/package.json index dbe2154..8a752e4 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "@types/react-blockies": "^1.4.1", "@types/react-dom": "^17.0.9", "@types/react-router-dom": "^5.1.8", - "chart.js": "^3.5.0", + "chart.js": "^3.5.1", "ethers": "^5.4.1", "query-string": "^7.0.1", "react": "^17.0.2", From 8396e91bb1bde34f1237265a16f9bb5a4e053143 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Mon, 30 Aug 2021 02:18:58 -0300 Subject: [PATCH 05/25] npm i --- package-lock.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package-lock.json b/package-lock.json index 1859ef2..245d201 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,6 +5,7 @@ "requires": true, "packages": { "": { + "name": "otterscan", "version": "0.1.0", "license": "MIT", "dependencies": { From 0ba7ad0cff87052b067058509ced84ee8a13f96d Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Sun, 15 Aug 2021 00:45:24 -0300 Subject: [PATCH 06/25] Fixes for miner fee reward display post-london --- src/Block.tsx | 14 ++++---------- src/useErigonHooks.ts | 3 +-- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/Block.tsx b/src/Block.tsx index 875d2f4..9f3a652 100644 --- a/src/Block.tsx +++ b/src/Block.tsx @@ -48,7 +48,7 @@ const Block: React.FC = () => { }, [block]); const burntFees = block?.baseFeePerGas && block.baseFeePerGas.mul(block.gasUsed); - const netFeeReward = block && block.feeReward.sub(burntFees ?? 0); + const netFeeReward = block?.feeReward ?? BigNumber.from(0); const gasUsedPerc = block && block.gasUsed.mul(10000).div(block.gasLimit).toNumber() / 100; @@ -91,18 +91,12 @@ const Block: React.FC = () => { - - {!block.feeReward.isZero() && ( + + {!netFeeReward.isZero() && ( <> {" "} ( +{" "} - - ) + ) )} diff --git a/src/useErigonHooks.ts b/src/useErigonHooks.ts index 4067f4c..48bc5ac 100644 --- a/src/useErigonHooks.ts +++ b/src/useErigonHooks.ts @@ -48,12 +48,11 @@ export const readBlock = async ( const _rawBlock = await blockPromise; const _block = provider.formatter.block(_rawBlock.block); const _rawIssuance = _rawBlock.issuance; - const fees = provider.formatter.bigNumber(_rawBlock.totalFees); const extBlock: ExtendedBlock = { blockReward: provider.formatter.bigNumber(_rawIssuance.blockReward ?? 0), unclesReward: provider.formatter.bigNumber(_rawIssuance.uncleReward ?? 0), - feeReward: fees, + feeReward: provider.formatter.bigNumber(_rawBlock.totalFees), size: provider.formatter.number(_rawBlock.block.size), sha3Uncles: _rawBlock.block.sha3Uncles, stateRoot: _rawBlock.block.stateRoot, From 64275a6b31b069630e8850dccd3f28656903eb3d Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Mon, 30 Aug 2021 02:51:27 -0300 Subject: [PATCH 07/25] Update 4bytes signatures --- 4bytes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/4bytes b/4bytes index 7996531..1cc7e25 160000 --- a/4bytes +++ b/4bytes @@ -1 +1 @@ -Subproject commit 79965318da56eed67366cf399ee5661b51af49cb +Subproject commit 1cc7e25c840ae9d985c12768b0cbd0ece3fc5400 From 0f6401cc07abd7ba76ea04893cf9feda36198070 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Mon, 30 Aug 2021 02:52:29 -0300 Subject: [PATCH 08/25] Update trustwallet assets --- trustwallet | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trustwallet b/trustwallet index 9bc40f3..7bfa06a 160000 --- a/trustwallet +++ b/trustwallet @@ -1 +1 @@ -Subproject commit 9bc40f37d95234810bc7e176513c8366c81080ce +Subproject commit 7bfa06acc125a4874d86bc1fa8e4547a46846e31 From 859761f2ba154b12c871c918eec4c9906eb29de3 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Tue, 31 Aug 2021 02:56:05 -0300 Subject: [PATCH 09/25] Squash initial implementation of usd prices --- src/Block.tsx | 19 ++++++++++++++- src/Transaction.tsx | 4 ++++ src/components/ETH2USDValue.tsx | 26 ++++++++++++++++++++ src/components/USDValue.tsx | 29 +++++++++++++++++++++++ src/transaction/Details.tsx | 29 ++++++++++++++++++----- src/usePriceOracle.ts | 42 +++++++++++++++++++++++++++++++++ 6 files changed, 142 insertions(+), 7 deletions(-) create mode 100644 src/components/ETH2USDValue.tsx create mode 100644 src/components/USDValue.tsx create mode 100644 src/usePriceOracle.ts diff --git a/src/Block.tsx b/src/Block.tsx index 9f3a652..caa309b 100644 --- a/src/Block.tsx +++ b/src/Block.tsx @@ -17,11 +17,14 @@ import BlockLink from "./components/BlockLink"; import DecoratedAddressLink from "./components/DecoratedAddressLink"; import TransactionValue from "./components/TransactionValue"; import FormattedBalance from "./components/FormattedBalance"; +import ETH2USDValue from "./components/ETH2USDValue"; +import USDValue from "./components/USDValue"; import HexValue from "./components/HexValue"; import { RuntimeContext } from "./useRuntime"; import { useLatestBlockNumber } from "./useLatestBlock"; import { blockTxsURL } from "./url"; import { useBlockData } from "./useErigonHooks"; +import { useETHUSDOracle } from "./usePriceOracle"; type BlockParams = { blockNumberOrHash: string; @@ -53,6 +56,7 @@ const Block: React.FC = () => { block && block.gasUsed.mul(10000).div(block.gasLimit).toNumber() / 100; const latestBlockNumber = useLatestBlockNumber(provider); + const blockETHUSDPrice = useETHUSDOracle(provider, block?.number); return ( @@ -99,6 +103,17 @@ const Block: React.FC = () => { ) )} + {blockETHUSDPrice && ( + <> + {" "} + + + + + )} @@ -147,7 +162,9 @@ const Block: React.FC = () => { {extraStr} (Hex:{" "} {block.extraData}) - N/A + + + {commify(block.difficulty)} {commify(block.totalDifficulty.toString())} diff --git a/src/Transaction.tsx b/src/Transaction.tsx index cb5a4e1..94f998f 100644 --- a/src/Transaction.tsx +++ b/src/Transaction.tsx @@ -8,6 +8,7 @@ import Logs from "./transaction/Logs"; import { RuntimeContext } from "./useRuntime"; import { SelectionContext, useSelection } from "./useSelection"; import { useInternalOperations, useTxData } from "./useErigonHooks"; +import { useETHUSDOracle } from "./usePriceOracle"; type TransactionParams = { txhash: string; @@ -36,6 +37,8 @@ const Transaction: React.FC = () => { const selectionCtx = useSelection(); + const blockETHUSDPrice = useETHUSDOracle(provider, txData?.blockNumber); + return ( Transaction Details @@ -53,6 +56,7 @@ const Transaction: React.FC = () => { txData={txData} internalOps={internalOps} sendsEthToMiner={sendsEthToMiner} + ethUSDPrice={blockETHUSDPrice} /> diff --git a/src/components/ETH2USDValue.tsx b/src/components/ETH2USDValue.tsx new file mode 100644 index 0000000..ef131d8 --- /dev/null +++ b/src/components/ETH2USDValue.tsx @@ -0,0 +1,26 @@ +import React from "react"; +import { BigNumber, FixedNumber } from "@ethersproject/bignumber"; +import { commify } from "@ethersproject/units"; + +type ETH2USDValueProps = { + ethAmount: BigNumber; + eth2USDValue: BigNumber; +}; + +const ETH2USDValue: React.FC = ({ + ethAmount, + eth2USDValue, +}) => { + const value = ethAmount.mul(eth2USDValue).div(10 ** 8); + + return ( + + $ + + {commify(FixedNumber.fromValue(value, 18).round(2).toString())} + + + ); +}; + +export default React.memo(ETH2USDValue); diff --git a/src/components/USDValue.tsx b/src/components/USDValue.tsx new file mode 100644 index 0000000..e488d25 --- /dev/null +++ b/src/components/USDValue.tsx @@ -0,0 +1,29 @@ +import React from "react"; +import { BigNumber, FixedNumber } from "@ethersproject/bignumber"; +import { commify } from "@ethersproject/units"; + +const ETH_FEED_DECIMALS = 8; + +type USDValueProps = { + value: BigNumber | undefined; +}; + +const USDValue: React.FC = ({ value }) => ( + + {value ? ( + <> + $ + + {commify( + FixedNumber.fromValue(value, ETH_FEED_DECIMALS).round(2).toString() + )} + {" "} + / ETH + + ) : ( + "N/A" + )} + +); + +export default React.memo(USDValue); diff --git a/src/transaction/Details.tsx b/src/transaction/Details.tsx index 500d45e..1f3cd65 100644 --- a/src/transaction/Details.tsx +++ b/src/transaction/Details.tsx @@ -1,5 +1,5 @@ import React, { useMemo, useState } from "react"; -import { formatEther } from "@ethersproject/units"; +import { BigNumber } from "@ethersproject/bignumber"; import { toUtf8String } from "@ethersproject/strings"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faCheckCircle } from "@fortawesome/free-solid-svg-icons/faCheckCircle"; @@ -19,7 +19,9 @@ import MethodName from "../components/MethodName"; import TransactionType from "../components/TransactionType"; import RewardSplit from "./RewardSplit"; import GasValue from "../components/GasValue"; +import USDValue from "../components/USDValue"; import FormattedBalance from "../components/FormattedBalance"; +import ETH2USDValue from "../components/ETH2USDValue"; import TokenTransferItem from "../TokenTransferItem"; import { TransactionData, InternalOperation } from "../types"; import PercentageBar from "../components/PercentageBar"; @@ -31,12 +33,14 @@ type DetailsProps = { txData: TransactionData; internalOps?: InternalOperation[]; sendsEthToMiner: boolean; + ethUSDPrice: BigNumber | undefined; }; const Details: React.FC = ({ txData, internalOps, sendsEthToMiner, + ethUSDPrice, }) => { const hasEIP1559 = txData.blockBaseFeePerGas !== undefined && @@ -170,9 +174,12 @@ const Details: React.FC = ({ )} - - {formatEther(txData.value)} Ether - + Ether{" "} + {!txData.value.isZero() && ethUSDPrice && ( + + + + )} = ({
- Ether + Ether{" "} + {ethUSDPrice && ( + + + + )}
{hasEIP1559 && }
- N/A + + +
diff --git a/src/usePriceOracle.ts b/src/usePriceOracle.ts new file mode 100644 index 0000000..e318a47 --- /dev/null +++ b/src/usePriceOracle.ts @@ -0,0 +1,42 @@ +import { useEffect, useMemo, useState } from "react"; +import { JsonRpcProvider, BlockTag } from "@ethersproject/providers"; +import { Contract } from "@ethersproject/contracts"; +import { BigNumber } from "@ethersproject/bignumber"; +import AggregatorV3Interface from "@chainlink/contracts/abi/v0.8/AggregatorV3Interface.json"; + +export const useETHUSDOracle = ( + provider: JsonRpcProvider | undefined, + blockTag: BlockTag | undefined +) => { + const ethFeed = useMemo(() => { + if (!provider || provider.network.chainId !== 1) { + return undefined; + } + + try { + return new Contract("eth-usd.data.eth", AggregatorV3Interface, provider); + } catch (err) { + console.error(err); + return undefined; + } + }, [provider]); + + const [latestPriceData, setLatestPriceData] = useState(); + useEffect(() => { + if (!ethFeed || !blockTag) { + return; + } + + const readData = async () => { + try { + const priceData = await ethFeed.latestRoundData({ blockTag }); + setLatestPriceData(BigNumber.from(priceData.answer)); + } catch (err) { + console.error(err); + } + }; + readData(); + }, [ethFeed, blockTag]); + + return latestPriceData; +}; From f65849913993a53f0c7b52acd9539d0b6f67a49c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Aug 2021 05:57:30 +0000 Subject: [PATCH 10/25] Bump react-router-dom from 5.2.0 to 5.2.1 (#58) --- package-lock.json | 38 +++++++++++++++++++------------------- package.json | 2 +- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/package-lock.json b/package-lock.json index 245d201..d843c31 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,7 +39,7 @@ "react-dom": "^17.0.2", "react-error-boundary": "^3.1.3", "react-image": "^4.0.3", - "react-router-dom": "^5.2.0", + "react-router-dom": "^5.2.1", "react-scripts": "4.0.3", "serve": "^12.0.0", "typescript": "^4.4.2", @@ -14396,11 +14396,11 @@ } }, "node_modules/react-router": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz", - "integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.1.tgz", + "integrity": "sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ==", "dependencies": { - "@babel/runtime": "^7.1.2", + "@babel/runtime": "^7.12.13", "history": "^4.9.0", "hoist-non-react-statics": "^3.1.0", "loose-envify": "^1.3.1", @@ -14416,15 +14416,15 @@ } }, "node_modules/react-router-dom": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.0.tgz", - "integrity": "sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.1.tgz", + "integrity": "sha512-xhFFkBGVcIVPbWM2KEYzED+nuHQPmulVa7sqIs3ESxzYd1pYg8N8rxPnQ4T2o1zu/2QeDUWcaqST131SO1LR3w==", "dependencies": { - "@babel/runtime": "^7.1.2", + "@babel/runtime": "^7.12.13", "history": "^4.9.0", "loose-envify": "^1.3.1", "prop-types": "^15.6.2", - "react-router": "5.2.0", + "react-router": "5.2.1", "tiny-invariant": "^1.0.2", "tiny-warning": "^1.0.0" }, @@ -28993,11 +28993,11 @@ "version": "0.8.3" }, "react-router": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz", - "integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.1.tgz", + "integrity": "sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ==", "requires": { - "@babel/runtime": "^7.1.2", + "@babel/runtime": "^7.12.13", "history": "^4.9.0", "hoist-non-react-statics": "^3.1.0", "loose-envify": "^1.3.1", @@ -29030,15 +29030,15 @@ } }, "react-router-dom": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.0.tgz", - "integrity": "sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.1.tgz", + "integrity": "sha512-xhFFkBGVcIVPbWM2KEYzED+nuHQPmulVa7sqIs3ESxzYd1pYg8N8rxPnQ4T2o1zu/2QeDUWcaqST131SO1LR3w==", "requires": { - "@babel/runtime": "^7.1.2", + "@babel/runtime": "^7.12.13", "history": "^4.9.0", "loose-envify": "^1.3.1", "prop-types": "^15.6.2", - "react-router": "5.2.0", + "react-router": "5.2.1", "tiny-invariant": "^1.0.2", "tiny-warning": "^1.0.0" } diff --git a/package.json b/package.json index 8a752e4..962ffa5 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "react-dom": "^17.0.2", "react-error-boundary": "^3.1.3", "react-image": "^4.0.3", - "react-router-dom": "^5.2.0", + "react-router-dom": "^5.2.1", "react-scripts": "4.0.3", "serve": "^12.0.0", "typescript": "^4.4.2", From 9147cc226b05cac242372a61f873058769040596 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Aug 2021 05:57:58 +0000 Subject: [PATCH 11/25] Bump @headlessui/react from 1.4.0 to 1.4.1 (#57) --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index d843c31..e0422fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "@fortawesome/free-regular-svg-icons": "^5.15.4", "@fortawesome/free-solid-svg-icons": "^5.15.4", "@fortawesome/react-fontawesome": "^0.1.15", - "@headlessui/react": "^1.4.0", + "@headlessui/react": "^1.4.1", "@testing-library/jest-dom": "^5.14.1", "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", @@ -2112,9 +2112,9 @@ } }, "node_modules/@headlessui/react": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.4.0.tgz", - "integrity": "sha512-C+FmBVF6YGvqcEI5fa2dfVbEaXr2RGR6Kw1E5HXIISIZEfsrH/yuCgsjWw5nlRF9vbCxmQ/EKs64GAdKeb8gCw==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.4.1.tgz", + "integrity": "sha512-gL6Ns5xQM57cZBzX6IVv6L7nsam8rDEpRhs5fg28SN64ikfmuuMgunc+Rw5C1cMScnvFM+cz32ueVrlSFEVlSg==", "engines": { "node": ">=10" }, @@ -20768,9 +20768,9 @@ } }, "@headlessui/react": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.4.0.tgz", - "integrity": "sha512-C+FmBVF6YGvqcEI5fa2dfVbEaXr2RGR6Kw1E5HXIISIZEfsrH/yuCgsjWw5nlRF9vbCxmQ/EKs64GAdKeb8gCw==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.4.1.tgz", + "integrity": "sha512-gL6Ns5xQM57cZBzX6IVv6L7nsam8rDEpRhs5fg28SN64ikfmuuMgunc+Rw5C1cMScnvFM+cz32ueVrlSFEVlSg==", "requires": {} }, "@istanbuljs/load-nyc-config": { diff --git a/package.json b/package.json index 962ffa5..938ff28 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "@fortawesome/free-regular-svg-icons": "^5.15.4", "@fortawesome/free-solid-svg-icons": "^5.15.4", "@fortawesome/react-fontawesome": "^0.1.15", - "@headlessui/react": "^1.4.0", + "@headlessui/react": "^1.4.1", "@testing-library/jest-dom": "^5.14.1", "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", From 5f9ec5e9927ea83612cdf8c35b2077ee76a0d1f3 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Tue, 31 Aug 2021 03:44:26 -0300 Subject: [PATCH 12/25] Start theme extraction work; extract from/to colors --- src/components/DecoratedAddressLink.tsx | 12 +++++++----- src/index.css | 9 +++++++++ src/transaction/Details.tsx | 4 ++-- tailwind.config.js | 25 +++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/components/DecoratedAddressLink.tsx b/src/components/DecoratedAddressLink.tsx index a325343..0b38fab 100644 --- a/src/components/DecoratedAddressLink.tsx +++ b/src/components/DecoratedAddressLink.tsx @@ -41,11 +41,13 @@ const DecoratedAddresssLink: React.FC = ({ return (
{creation && ( diff --git a/src/index.css b/src/index.css index b5c61c9..9333e63 100644 --- a/src/index.css +++ b/src/index.css @@ -1,3 +1,12 @@ @tailwind base; @tailwind components; @tailwind utilities; + +@layer base { + :root { + --color-from-border: 254, 226, 226; + --color-from-text: 220, 38, 38; + --color-from-fill: 254, 242, 242; + --color-to-fill: 236, 253, 245; + } +} diff --git a/src/transaction/Details.tsx b/src/transaction/Details.tsx index 1f3cd65..6f46e7f 100644 --- a/src/transaction/Details.tsx +++ b/src/transaction/Details.tsx @@ -176,7 +176,7 @@ const Details: React.FC = ({ Ether{" "} {!txData.value.isZero() && ethUSDPrice && ( - + )} @@ -266,7 +266,7 @@ const Details: React.FC = ({
Ether{" "} {ethUSDPrice && ( - + { + if (opacityValue !== undefined) { + return `rgba(var(${variableName}), ${opacityValue})`; + } + return `rgb(var(${variableName}))`; + }; +} + module.exports = { purge: ["./src/**/*.{js,jsx,ts,tsx}", "./public/index.html"], darkMode: false, // or 'media' or 'class' @@ -19,6 +28,22 @@ module.exports = { balance: ["Fira Code"], blocknum: ["Roboto"], }, + borderColor: { + skin: { + from: withOpacity("--color-from-border"), + }, + }, + textColor: { + skin: { + from: withOpacity("--color-from-text"), + }, + }, + backgroundColor: { + skin: { + from: withOpacity("--color-from-fill"), + to: withOpacity("--color-to-fill"), + }, + }, }, }, variants: { From 9f778e6eba97312e5cce72d985cea19f8f51eaff Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Tue, 31 Aug 2021 04:02:26 -0300 Subject: [PATCH 13/25] Extract table bg hover theme color --- src/index.css | 2 ++ src/search/TransactionItem.tsx | 4 +++- src/special/london/BlockRow.tsx | 2 +- tailwind.config.js | 1 + 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/index.css b/src/index.css index 9333e63..6088bfb 100644 --- a/src/index.css +++ b/src/index.css @@ -8,5 +8,7 @@ --color-from-text: 220, 38, 38; --color-from-fill: 254, 242, 242; --color-to-fill: 236, 253, 245; + + --color-table-row-hover: 243, 244, 246; } } diff --git a/src/search/TransactionItem.tsx b/src/search/TransactionItem.tsx index 32aab32..f5196d8 100644 --- a/src/search/TransactionItem.tsx +++ b/src/search/TransactionItem.tsx @@ -56,7 +56,9 @@ const TransactionItem: React.FC = ({ return (
diff --git a/src/special/london/BlockRow.tsx b/src/special/london/BlockRow.tsx index 8915417..df22a85 100644 --- a/src/special/london/BlockRow.tsx +++ b/src/special/london/BlockRow.tsx @@ -22,7 +22,7 @@ const BlockRow: React.FC = ({ now, block, baseFeeDelta }) => { const totalReward = block.blockReward.add(netFeeReward ?? 0); return ( -
+
diff --git a/tailwind.config.js b/tailwind.config.js index 4289294..48964a3 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -42,6 +42,7 @@ module.exports = { skin: { from: withOpacity("--color-from-fill"), to: withOpacity("--color-to-fill"), + "table-hover": withOpacity("--color-table-row-hover"), }, }, }, From 8624c70877eabf423ab032f6cf4edeb2939b78b5 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Tue, 31 Aug 2021 15:06:26 -0300 Subject: [PATCH 14/25] Generalize implementation to support multiple block queries --- src/usePriceOracle.ts | 51 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/src/usePriceOracle.ts b/src/usePriceOracle.ts index e318a47..0fc909a 100644 --- a/src/usePriceOracle.ts +++ b/src/usePriceOracle.ts @@ -7,6 +7,18 @@ import AggregatorV3Interface from "@chainlink/contracts/abi/v0.8/AggregatorV3Int export const useETHUSDOracle = ( provider: JsonRpcProvider | undefined, blockTag: BlockTag | undefined +) => { + const priceMap = useMultipleETHUSDOracle(provider, [blockTag]); + + if (blockTag === undefined) { + return undefined; + } + return priceMap[blockTag]; +}; + +export const useMultipleETHUSDOracle = ( + provider: JsonRpcProvider | undefined, + blockTags: (BlockTag | undefined)[] ) => { const ethFeed = useMemo(() => { if (!provider || provider.network.chainId !== 1) { @@ -21,22 +33,45 @@ export const useETHUSDOracle = ( } }, [provider]); - const [latestPriceData, setLatestPriceData] = useState(); + const [latestPriceData, setLatestPriceData] = useState< + Record + >({}); useEffect(() => { - if (!ethFeed || !blockTag) { + if (!ethFeed) { return; } + const priceReaders: Promise[] = []; + for (const blockTag of blockTags) { + priceReaders.push( + (async () => { + try { + const priceData = await ethFeed.latestRoundData({ blockTag }); + return BigNumber.from(priceData.answer); + } catch (err) { + console.error(err); + return undefined; + } + })() + ); + } const readData = async () => { - try { - const priceData = await ethFeed.latestRoundData({ blockTag }); - setLatestPriceData(BigNumber.from(priceData.answer)); - } catch (err) { - console.error(err); + const results = await Promise.all(priceReaders); + const priceMap: Record = {}; + for (let i = 0; i < blockTags.length; i++) { + const blockTag = blockTags[i]; + const result = results[i]; + if (blockTag === undefined || result === undefined) { + continue; + } + + priceMap[blockTag] = result; } + + setLatestPriceData(priceMap); }; readData(); - }, [ethFeed, blockTag]); + }, [ethFeed, blockTags]); return latestPriceData; }; From 7a43a56e26a1528f97807faf095e1fea155c7b9c Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Tue, 31 Aug 2021 16:49:52 -0300 Subject: [PATCH 15/25] Apply usd price on search results --- src/AddressTransactions.tsx | 11 +++++++++++ src/BlockTransactions.tsx | 1 + src/block/BlockTransactionResults.tsx | 6 ++++++ src/search/ResultHeader.tsx | 4 +++- src/search/TransactionItem.tsx | 19 ++++++++++++++++--- src/search/useFeeToggler.ts | 8 ++++---- 6 files changed, 41 insertions(+), 8 deletions(-) diff --git a/src/AddressTransactions.tsx b/src/AddressTransactions.tsx index e79253e..f4fd2ff 100644 --- a/src/AddressTransactions.tsx +++ b/src/AddressTransactions.tsx @@ -1,5 +1,6 @@ import React, { useState, useEffect, useMemo, useContext } from "react"; import { useParams, useLocation, useHistory } from "react-router-dom"; +import { BlockTag } from "@ethersproject/abstract-provider"; import { getAddress, isAddress } from "@ethersproject/address"; import queryString from "query-string"; import Blockies from "react-blockies"; @@ -16,6 +17,7 @@ import { RuntimeContext } from "./useRuntime"; import { useENSCache } from "./useReverseCache"; import { useFeeToggler } from "./search/useFeeToggler"; import { SelectionContext, useSelection } from "./useSelection"; +import { useMultipleETHUSDOracle } from "./usePriceOracle"; type BlockParams = { addressOrName: string; @@ -150,6 +152,14 @@ const AddressTransactions: React.FC = () => { const page = useMemo(() => controller?.getPage(), [controller]); const reverseCache = useENSCache(provider, page); + const blockTags: BlockTag[] = useMemo(() => { + if (!page) { + return []; + } + return page.map((p) => p.blockNumber); + }, [page]); + const priceMap = useMultipleETHUSDOracle(provider, blockTags); + document.title = `Address ${params.addressOrName} | Otterscan`; const [feeDisplay, feeDisplayToggler] = useFeeToggler(); @@ -215,6 +225,7 @@ const AddressTransactions: React.FC = () => { ensCache={reverseCache} selectedAddress={checksummedAddress} feeDisplay={feeDisplay} + priceMap={priceMap} /> ))}
diff --git a/src/BlockTransactions.tsx b/src/BlockTransactions.tsx index 5a7209f..ed9b2c7 100644 --- a/src/BlockTransactions.tsx +++ b/src/BlockTransactions.tsx @@ -47,6 +47,7 @@ const BlockTransactions: React.FC = () => { = ({ + blockTag, page, total, pageNumber, @@ -26,6 +30,7 @@ const BlockTransactionResults: React.FC = ({ const [feeDisplay, feeDisplayToggler] = useFeeToggler(); const { provider } = useContext(RuntimeContext); const reverseCache = useENSCache(provider, page); + const priceMap = useMultipleETHUSDOracle(provider, [blockTag]); return ( @@ -55,6 +60,7 @@ const BlockTransactionResults: React.FC = ({ tx={tx} ensCache={reverseCache} feeDisplay={feeDisplay} + priceMap={priceMap} /> ))}
diff --git a/src/search/ResultHeader.tsx b/src/search/ResultHeader.tsx index 13880bd..5fbcbc2 100644 --- a/src/search/ResultHeader.tsx +++ b/src/search/ResultHeader.tsx @@ -23,7 +23,9 @@ const ResultHeader: React.FC = ({ className="text-link-blue hover:text-link-blue-hover" onClick={feeDisplayToggler} > - {feeDisplay === FeeDisplay.TX_FEE ? "Txn Fee" : "Gas Price"} + {feeDisplay === FeeDisplay.TX_FEE && "Txn Fee"} + {feeDisplay === FeeDisplay.TX_FEE_USD && "Txn Fee (USD)"} + {feeDisplay === FeeDisplay.GAS_PRICE && "Gas Price"}
diff --git a/src/search/TransactionItem.tsx b/src/search/TransactionItem.tsx index f5196d8..ffafc09 100644 --- a/src/search/TransactionItem.tsx +++ b/src/search/TransactionItem.tsx @@ -1,4 +1,6 @@ import React from "react"; +import { BlockTag } from "@ethersproject/abstract-provider"; +import { BigNumber } from "@ethersproject/bignumber"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faExclamationCircle } from "@fortawesome/free-solid-svg-icons/faExclamationCircle"; import MethodName from "../components/MethodName"; @@ -15,12 +17,14 @@ import TransactionValue from "../components/TransactionValue"; import { ENSReverseCache, ProcessedTransaction } from "../types"; import { FeeDisplay } from "./useFeeToggler"; import { formatValue } from "../components/formatter"; +import ETH2USDValue from "../components/ETH2USDValue"; type TransactionItemProps = { tx: ProcessedTransaction; ensCache?: ENSReverseCache; selectedAddress?: string; feeDisplay: FeeDisplay; + priceMap: Record; }; const TransactionItem: React.FC = ({ @@ -28,6 +32,7 @@ const TransactionItem: React.FC = ({ ensCache, selectedAddress, feeDisplay, + priceMap, }) => { let direction: Direction | undefined; if (selectedAddress) { @@ -123,9 +128,17 @@ const TransactionItem: React.FC = ({ - {feeDisplay === FeeDisplay.TX_FEE - ? formatValue(tx.fee, 18) - : formatValue(tx.gasPrice, 9)} + {feeDisplay === FeeDisplay.TX_FEE && formatValue(tx.fee, 18)} + {feeDisplay === FeeDisplay.TX_FEE_USD && + (priceMap[tx.blockNumber] ? ( + + ) : ( + "N/A" + ))} + {feeDisplay === FeeDisplay.GAS_PRICE && formatValue(tx.gasPrice, 9)}
); diff --git a/src/search/useFeeToggler.ts b/src/search/useFeeToggler.ts index 7a82a9c..722221c 100644 --- a/src/search/useFeeToggler.ts +++ b/src/search/useFeeToggler.ts @@ -2,16 +2,16 @@ import { useState } from "react"; export enum FeeDisplay { TX_FEE, + TX_FEE_USD, GAS_PRICE, } export const useFeeToggler = (): [FeeDisplay, () => void] => { const [feeDisplay, setFeeDisplay] = useState(FeeDisplay.TX_FEE); const feeDisplayToggler = () => { - if (feeDisplay === FeeDisplay.TX_FEE) { - setFeeDisplay(FeeDisplay.GAS_PRICE); - } else { - setFeeDisplay(FeeDisplay.TX_FEE); + setFeeDisplay(feeDisplay + 1); + if (feeDisplay === FeeDisplay.GAS_PRICE) { + setFeeDisplay(0); } }; From 72d66aace98e8437b21c4fef84a376aab27bb759 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Wed, 1 Sep 2021 05:53:57 -0300 Subject: [PATCH 16/25] Fix infinite refresh --- src/usePriceOracle.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/usePriceOracle.ts b/src/usePriceOracle.ts index 0fc909a..f41a1be 100644 --- a/src/usePriceOracle.ts +++ b/src/usePriceOracle.ts @@ -8,7 +8,8 @@ export const useETHUSDOracle = ( provider: JsonRpcProvider | undefined, blockTag: BlockTag | undefined ) => { - const priceMap = useMultipleETHUSDOracle(provider, [blockTag]); + const blockTags = useMemo(() => [blockTag], [blockTag]); + const priceMap = useMultipleETHUSDOracle(provider, blockTags); if (blockTag === undefined) { return undefined; From b9954a5fe5c0a30cb37d6c33870e748ae9d95f2e Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Wed, 1 Sep 2021 07:19:36 -0300 Subject: [PATCH 17/25] Fix infinite refresh --- src/block/BlockTransactionResults.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/block/BlockTransactionResults.tsx b/src/block/BlockTransactionResults.tsx index 922b50d..b911013 100644 --- a/src/block/BlockTransactionResults.tsx +++ b/src/block/BlockTransactionResults.tsx @@ -1,4 +1,4 @@ -import React, { useContext } from "react"; +import React, { useContext, useMemo } from "react"; import { BlockTag } from "@ethersproject/abstract-provider"; import ContentFrame from "../ContentFrame"; import PageControl from "../search/PageControl"; @@ -30,7 +30,8 @@ const BlockTransactionResults: React.FC = ({ const [feeDisplay, feeDisplayToggler] = useFeeToggler(); const { provider } = useContext(RuntimeContext); const reverseCache = useENSCache(provider, page); - const priceMap = useMultipleETHUSDOracle(provider, [blockTag]); + const blockTags = useMemo(() => [blockTag], [blockTag]); + const priceMap = useMultipleETHUSDOracle(provider, blockTags); return ( From 0bba63330d813202e7074979384d196468c50a7a Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Wed, 1 Sep 2021 06:33:42 -0300 Subject: [PATCH 18/25] First working prototype --- package-lock.json | 90 +++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + src/Title.tsx | 42 ++++++++++++++++++++++ 3 files changed, 133 insertions(+) diff --git a/package-lock.json b/package-lock.json index e0422fc..21ccd93 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.1.0", "license": "MIT", "dependencies": { + "@blackbox-vision/react-qr-reader": "^5.0.0", "@chainlink/contracts": "^0.2.1", "@craco/craco": "^6.2.0", "@fontsource/fira-code": "^4.5.1", @@ -1209,6 +1210,19 @@ "version": "0.2.3", "license": "MIT" }, + "node_modules/@blackbox-vision/react-qr-reader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@blackbox-vision/react-qr-reader/-/react-qr-reader-5.0.0.tgz", + "integrity": "sha512-VLNKwwJTv4UX1inUNgt2aGC2yIhKBYptW9EOhn7Nq//WzjD5KvHG7WR48HTzGUZ2s/EA0XlxZSfKOarHV1Vb/A==", + "dependencies": { + "@zxing/browser": "0.0.7", + "@zxing/library": "^0.18.3" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + } + }, "node_modules/@chainlink/contracts": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/@chainlink/contracts/-/contracts-0.2.1.tgz", @@ -3512,6 +3526,37 @@ "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.6.0.tgz", "integrity": "sha512-uUrgZ8AxS+Lio0fZKAipJjAh415JyrOZowliZAzmnJSsf7piVL5w+G0+gFJ0KSu3QRhvui/7zuvpLz03YjXAhg==" }, + "node_modules/@zxing/browser": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@zxing/browser/-/browser-0.0.7.tgz", + "integrity": "sha512-AepzMgDnD6EjxewqmXpHJsi4S3Gw9ilZJLIbTf6fWuWySEcHBodnGu3p7FWlgq1Sd5QyfPhTum5z3CBkkhMVng==", + "optionalDependencies": { + "@zxing/text-encoding": "^0.9.0" + }, + "peerDependencies": { + "@zxing/library": "^0.18.3" + } + }, + "node_modules/@zxing/library": { + "version": "0.18.6", + "resolved": "https://registry.npmjs.org/@zxing/library/-/library-0.18.6.tgz", + "integrity": "sha512-bulZ9JHoLFd9W36pi+7e7DnEYNJhljYjZ1UTsKPOoLMU3qtC+REHITeCRNx40zTRJZx18W5TBRXt5pq2Uopjsw==", + "dependencies": { + "ts-custom-error": "^3.0.0" + }, + "engines": { + "node": ">= 10.4.0" + }, + "optionalDependencies": { + "@zxing/text-encoding": "~0.9.0" + } + }, + "node_modules/@zxing/text-encoding": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz", + "integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==", + "optional": true + }, "node_modules/abab": { "version": "2.0.5", "license": "BSD-3-Clause" @@ -17825,6 +17870,14 @@ "version": "1.0.1", "license": "MIT" }, + "node_modules/ts-custom-error": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ts-custom-error/-/ts-custom-error-3.2.0.tgz", + "integrity": "sha512-cBvC2QjtvJ9JfWLvstVnI45Y46Y5dMxIaG1TDMGAD/R87hpvqFL+7LhvUDhnRCfOnx/xitollFWWvUKKKhbN0A==", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/ts-pnp": { "version": "1.2.0", "license": "MIT", @@ -20240,6 +20293,15 @@ "@bcoe/v8-coverage": { "version": "0.2.3" }, + "@blackbox-vision/react-qr-reader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@blackbox-vision/react-qr-reader/-/react-qr-reader-5.0.0.tgz", + "integrity": "sha512-VLNKwwJTv4UX1inUNgt2aGC2yIhKBYptW9EOhn7Nq//WzjD5KvHG7WR48HTzGUZ2s/EA0XlxZSfKOarHV1Vb/A==", + "requires": { + "@zxing/browser": "0.0.7", + "@zxing/library": "^0.18.3" + } + }, "@chainlink/contracts": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/@chainlink/contracts/-/contracts-0.2.1.tgz", @@ -21700,6 +21762,29 @@ "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.6.0.tgz", "integrity": "sha512-uUrgZ8AxS+Lio0fZKAipJjAh415JyrOZowliZAzmnJSsf7piVL5w+G0+gFJ0KSu3QRhvui/7zuvpLz03YjXAhg==" }, + "@zxing/browser": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@zxing/browser/-/browser-0.0.7.tgz", + "integrity": "sha512-AepzMgDnD6EjxewqmXpHJsi4S3Gw9ilZJLIbTf6fWuWySEcHBodnGu3p7FWlgq1Sd5QyfPhTum5z3CBkkhMVng==", + "requires": { + "@zxing/text-encoding": "^0.9.0" + } + }, + "@zxing/library": { + "version": "0.18.6", + "resolved": "https://registry.npmjs.org/@zxing/library/-/library-0.18.6.tgz", + "integrity": "sha512-bulZ9JHoLFd9W36pi+7e7DnEYNJhljYjZ1UTsKPOoLMU3qtC+REHITeCRNx40zTRJZx18W5TBRXt5pq2Uopjsw==", + "requires": { + "@zxing/text-encoding": "~0.9.0", + "ts-custom-error": "^3.0.0" + } + }, + "@zxing/text-encoding": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz", + "integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==", + "optional": true + }, "abab": { "version": "2.0.5" }, @@ -31387,6 +31472,11 @@ "tryer": { "version": "1.0.1" }, + "ts-custom-error": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ts-custom-error/-/ts-custom-error-3.2.0.tgz", + "integrity": "sha512-cBvC2QjtvJ9JfWLvstVnI45Y46Y5dMxIaG1TDMGAD/R87hpvqFL+7LhvUDhnRCfOnx/xitollFWWvUKKKhbN0A==" + }, "ts-pnp": { "version": "1.2.0" }, diff --git a/package.json b/package.json index 938ff28..fb6e41e 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "private": true, "license": "MIT", "dependencies": { + "@blackbox-vision/react-qr-reader": "^5.0.0", "@chainlink/contracts": "^0.2.1", "@craco/craco": "^6.2.0", "@fontsource/fira-code": "^4.5.1", diff --git a/src/Title.tsx b/src/Title.tsx index 46e1e5c..0a017f7 100644 --- a/src/Title.tsx +++ b/src/Title.tsx @@ -1,5 +1,11 @@ import React, { useState, useRef, useContext } from "react"; +import { isAddress } from "@ethersproject/address"; import { Link, useHistory } from "react-router-dom"; +import { QrReader } from "@blackbox-vision/react-qr-reader"; +import { OnResultFunction } from "@blackbox-vision/react-qr-reader/dist-types/types"; +import { BarcodeFormat } from "@zxing/library"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faQrcode } from "@fortawesome/free-solid-svg-icons/faQrcode"; import useKeyboardShortcut from "use-keyboard-shortcut"; import PriceBox from "./PriceBox"; import { RuntimeContext } from "./useRuntime"; @@ -29,6 +35,28 @@ const Title: React.FC = () => { searchRef.current?.focus(); }); + const [isScanning, setScanning] = useState(); + const onScan = () => { + setScanning(!isScanning); + }; + const evaluateScan: OnResultFunction = (result, error, codeReader) => { + console.log("scan"); + if (!error && result?.getBarcodeFormat() === BarcodeFormat.QR_CODE) { + const text = result.getText(); + console.log(`Scanned: ${text}`); + if (!isAddress(text)) { + console.log("Not an ETH address"); + return; + } + + if (searchRef.current) { + searchRef.current.value = text; + searchRef.current.dispatchEvent(new Event("input", { bubbles: true })); + } + setScanning(false); + } + }; + return (
@@ -60,6 +88,20 @@ const Title: React.FC = () => { onChange={handleChange} ref={searchRef} /> + + {isScanning && ( + + )} - {isScanning && ( + <> + setScanning(false)} + > +
+ + + Point an ETH address QR code to camera + +
- )} -
+
+
+ +
+ An otter scanning + Otterscan +
+ +
+ {provider?.network.chainId === 1 && } + - Search - - + + + + +
-
+ ); }; From 51b18b763fa4c4752fcd24d3f7b090d04cbd6972 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Wed, 1 Sep 2021 17:40:42 -0300 Subject: [PATCH 20/25] Extract common camera scan code; apply it to home also --- src/Home.tsx | 30 ++++++++++++++------ src/Title.tsx | 46 +++--------------------------- src/search/CameraScanner.tsx | 54 ++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 50 deletions(-) create mode 100644 src/search/CameraScanner.tsx diff --git a/src/Home.tsx b/src/Home.tsx index 31ecb9a..6fb58c8 100644 --- a/src/Home.tsx +++ b/src/Home.tsx @@ -3,7 +3,9 @@ import { NavLink, useHistory } from "react-router-dom"; import { commify } from "@ethersproject/units"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faBurn } from "@fortawesome/free-solid-svg-icons/faBurn"; +import { faQrcode } from "@fortawesome/free-solid-svg-icons/faQrcode"; import Logo from "./Logo"; +import CameraScanner from "./search/CameraScanner"; import Timestamp from "./components/Timestamp"; import { RuntimeContext } from "./useRuntime"; import { useLatestBlock } from "./useLatestBlock"; @@ -30,11 +32,13 @@ const Home: React.FC = () => { }; const latestBlock = useLatestBlock(provider); + const [isScanning, setScanning] = useState(false); document.title = "Home | Otterscan"; return (
+ {isScanning && setScanning(false)} />}
{ autoComplete="off" spellCheck={false} > - +
+ + +
diff --git a/src/search/CameraScanner.tsx b/src/search/CameraScanner.tsx new file mode 100644 index 0000000..b32d707 --- /dev/null +++ b/src/search/CameraScanner.tsx @@ -0,0 +1,54 @@ +import React from "react"; +import { useHistory } from "react-router-dom"; +import { isAddress } from "@ethersproject/address"; +import { QrReader } from "@blackbox-vision/react-qr-reader"; +import { OnResultFunction } from "@blackbox-vision/react-qr-reader/dist-types/types"; +import { BarcodeFormat } from "@zxing/library"; +import { Dialog } from "@headlessui/react"; + +type CameraScannerProps = { + turnOffScan: () => void; +}; + +const CameraScanner: React.FC = ({ turnOffScan }) => { + const history = useHistory(); + + const evaluateScan: OnResultFunction = (result, error, codeReader) => { + console.log("scan"); + if (!error && result?.getBarcodeFormat() === BarcodeFormat.QR_CODE) { + const text = result.getText(); + console.log(`Scanned: ${text}`); + if (!isAddress(text)) { + console.warn("Not an ETH address"); + return; + } + + history.push(`/search?q=${text}`); + turnOffScan(); + } + }; + + return ( + +
+ + + Point an ETH address QR code to camera + +
+ +
+
+
+ ); +}; + +export default CameraScanner; From b204c7cf55e7813380ca56b031990003883fa26e Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Wed, 1 Sep 2021 17:56:12 -0300 Subject: [PATCH 21/25] Create test theme --- src/index.css | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/index.css b/src/index.css index 6088bfb..4cd29ee 100644 --- a/src/index.css +++ b/src/index.css @@ -11,4 +11,12 @@ --color-table-row-hover: 243, 244, 246; } + .test-theme { + --color-from-border: 251, 146, 60; + --color-from-text: 249, 115, 22; + --color-from-fill: 254, 215, 170; + --color-to-fill: 125, 211, 252; + + --color-table-row-hover: 2, 132, 199; + } } From 54f5c9e6c7757eab5f81917bb7d4817fa943747a Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Wed, 1 Sep 2021 18:12:35 -0300 Subject: [PATCH 22/25] Extract action button theme --- src/Home.tsx | 4 ++-- src/Title.tsx | 4 ++-- src/index.css | 8 ++++++++ tailwind.config.js | 5 +++++ 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/Home.tsx b/src/Home.tsx index 6fb58c8..650c86c 100644 --- a/src/Home.tsx +++ b/src/Home.tsx @@ -56,7 +56,7 @@ const Home: React.FC = () => { autoFocus />