From ee0ea1a2e3c603fa6026a0a48cda0c093e3b3565 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Sat, 19 Feb 2022 06:17:40 -0300 Subject: [PATCH 1/9] Extract common component --- src/address/AddressTransactionResults.tsx | 64 ++++++++++------------- 1 file changed, 29 insertions(+), 35 deletions(-) diff --git a/src/address/AddressTransactionResults.tsx b/src/address/AddressTransactionResults.tsx index cc8665e..f19a43a 100644 --- a/src/address/AddressTransactionResults.tsx +++ b/src/address/AddressTransactionResults.tsx @@ -11,7 +11,7 @@ import { SelectionContext, useSelection } from "../useSelection"; import { useMultipleETHUSDOracle } from "../usePriceOracle"; import { RuntimeContext } from "../useRuntime"; import { useParams, useSearchParams } from "react-router-dom"; -import { ChecksummedAddress } from "../types"; +import { ChecksummedAddress, ProcessedTransaction } from "../types"; import { useContractsMetadata } from "../hooks"; type AddressTransactionResultsProps = { @@ -120,23 +120,7 @@ const AddressTransactionResults: React.FC = ({ return ( -
-
- {page === undefined ? ( - <>Waiting for search results... - ) : ( - <>{page.length} transactions on this page - )} -
- -
+ = ({ metadatas={metadatas} /> ))} -
-
- {page === undefined ? ( - <>Waiting for search results... - ) : ( - <>{page.length} transactions on this page - )} -
- -
+ ) : ( @@ -178,4 +146,30 @@ const AddressTransactionResults: React.FC = ({ ); }; +type NavBarProps = { + address: ChecksummedAddress; + page: ProcessedTransaction[] | undefined; + controller: SearchController | undefined; +}; + +const NavBar: React.FC = ({ address, page, controller }) => ( +
+
+ {page === undefined ? ( + <>Waiting for search results... + ) : ( + <>{page.length} transactions on this page + )} +
+ +
+); + export default AddressTransactionResults; From d00d6cba0b27eb814c707610d5c4a17d68d853cf Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Sat, 19 Feb 2022 07:42:36 -0300 Subject: [PATCH 2/9] Add contract creator panel to address overview page --- src/address/AddressTransactionResults.tsx | 64 +++++++++++++++-------- src/params.ts | 2 +- src/useErigonHooks.ts | 53 +++++++++++++++++++ 3 files changed, 96 insertions(+), 23 deletions(-) diff --git a/src/address/AddressTransactionResults.tsx b/src/address/AddressTransactionResults.tsx index f19a43a..4fd7b25 100644 --- a/src/address/AddressTransactionResults.tsx +++ b/src/address/AddressTransactionResults.tsx @@ -1,6 +1,10 @@ import React, { useContext, useEffect, useMemo, useState } from "react"; import { BlockTag } from "@ethersproject/providers"; import ContentFrame from "../ContentFrame"; +import InfoRow from "../components/InfoRow"; +import TransactionAddress from "../components/TransactionAddress"; +import Copy from "../components/Copy"; +import TransactionLink from "../components/TransactionLink"; import PendingResults from "../search/PendingResults"; import ResultHeader from "../search/ResultHeader"; import { SearchController } from "../search/search"; @@ -13,6 +17,7 @@ import { RuntimeContext } from "../useRuntime"; import { useParams, useSearchParams } from "react-router-dom"; import { ChecksummedAddress, ProcessedTransaction } from "../types"; import { useContractsMetadata } from "../hooks"; +import { useContractCreator } from "../useErigonHooks"; type AddressTransactionResultsProps = { address: ChecksummedAddress; @@ -117,31 +122,46 @@ const AddressTransactionResults: React.FC = ({ return _addresses; }, [address, page]); const metadatas = useContractsMetadata(addresses, provider); + const creator = useContractCreator(provider, address); return ( - - - {page ? ( - - {page.map((tx) => ( - - ))} - - - ) : ( - - )} + + + {creator && ( + +
+ + + at + tx: + +
+
+ )} + + + {page ? ( + <> + {page.map((tx) => ( + + ))} + + + ) : ( + + )} +
); }; diff --git a/src/params.ts b/src/params.ts index f26ef7a..26f7291 100644 --- a/src/params.ts +++ b/src/params.ts @@ -1,3 +1,3 @@ -export const MIN_API_LEVEL = 7; +export const MIN_API_LEVEL = 8; export const PAGE_SIZE = 25; diff --git a/src/useErigonHooks.ts b/src/useErigonHooks.ts index ad9b0b8..0039963 100644 --- a/src/useErigonHooks.ts +++ b/src/useErigonHooks.ts @@ -605,3 +605,56 @@ export const useTransactionBySenderAndNonce = ( } return data; }; + +type ContractCreatorKey = { + type: "cc"; + network: number; + address: ChecksummedAddress; +}; + +type ContractCreator = { + hash: string; + creator: ChecksummedAddress; +}; + +export const useContractCreator = ( + provider: JsonRpcProvider | undefined, + address: ChecksummedAddress | undefined +): ContractCreator | null | undefined => { + const { data, error } = useSWR< + ContractCreator | null | undefined, + any, + ContractCreatorKey | null + >( + provider && address + ? { + type: "cc", + network: provider.network.chainId, + address, + } + : null, + getContractCreatorFetcher(provider!) + ); + + if (error) { + return undefined; + } + return data as ContractCreator; +}; + +const getContractCreatorFetcher = + (provider: JsonRpcProvider) => + async ({ + network, + address, + }: ContractCreatorKey): Promise => { + const result = (await provider.send("ots_experimentalGetContractCreator", [ + address, + ])) as ContractCreator; + + // Empty or success + if (result) { + result.creator = provider.formatter.address(result.creator); + } + return result; + }; From 22a0bc58883729c026bbb1719b620e9d49cb002d Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Sat, 19 Feb 2022 08:01:34 -0300 Subject: [PATCH 3/9] Add current balance --- src/address/AddressTransactionResults.tsx | 10 ++++++++-- src/useErigonHooks.ts | 21 +++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/address/AddressTransactionResults.tsx b/src/address/AddressTransactionResults.tsx index 4fd7b25..48fb2d9 100644 --- a/src/address/AddressTransactionResults.tsx +++ b/src/address/AddressTransactionResults.tsx @@ -2,6 +2,7 @@ import React, { useContext, useEffect, useMemo, useState } from "react"; import { BlockTag } from "@ethersproject/providers"; import ContentFrame from "../ContentFrame"; import InfoRow from "../components/InfoRow"; +import FormattedBalance from "../components/FormattedBalance"; import TransactionAddress from "../components/TransactionAddress"; import Copy from "../components/Copy"; import TransactionLink from "../components/TransactionLink"; @@ -17,7 +18,7 @@ import { RuntimeContext } from "../useRuntime"; import { useParams, useSearchParams } from "react-router-dom"; import { ChecksummedAddress, ProcessedTransaction } from "../types"; import { useContractsMetadata } from "../hooks"; -import { useContractCreator } from "../useErigonHooks"; +import { useAddressBalance, useContractCreator } from "../useErigonHooks"; type AddressTransactionResultsProps = { address: ChecksummedAddress; @@ -122,12 +123,17 @@ const AddressTransactionResults: React.FC = ({ return _addresses; }, [address, page]); const metadatas = useContractsMetadata(addresses, provider); + const balance = useAddressBalance(provider, address); const creator = useContractCreator(provider, address); return ( - + {balance && ( + + Ether{" "} + + )} {creator && (
diff --git a/src/useErigonHooks.ts b/src/useErigonHooks.ts index 0039963..5db5ee1 100644 --- a/src/useErigonHooks.ts +++ b/src/useErigonHooks.ts @@ -658,3 +658,24 @@ const getContractCreatorFetcher = } return result; }; + +export const useAddressBalance = ( + provider: JsonRpcProvider | undefined, + address: ChecksummedAddress | undefined +): BigNumber | null | undefined => { + const [balance, setBalance] = useState(); + + useEffect(() => { + if (!provider || !address) { + return undefined; + } + + const readBalance = async () => { + const _balance = await provider.getBalance(address); + setBalance(_balance); + }; + readBalance(); + }, [provider, address]); + + return balance; +}; From 4b6910d2a1f80708d7c1be13e4b59a37c476423b Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Sat, 19 Feb 2022 15:07:28 -0300 Subject: [PATCH 4/9] Improve creator/tx display UI --- src/address/AddressTransactionResults.tsx | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/address/AddressTransactionResults.tsx b/src/address/AddressTransactionResults.tsx index 48fb2d9..88ae415 100644 --- a/src/address/AddressTransactionResults.tsx +++ b/src/address/AddressTransactionResults.tsx @@ -131,17 +131,19 @@ const AddressTransactionResults: React.FC = ({ {balance && ( - Ether{" "} + Ether )} {creator && ( -
- - - at - tx: - +
+
+ + +
+
+ +
)} From dcc125293a3e28658691123614b815faab0be99e Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Sat, 19 Feb 2022 15:19:56 -0300 Subject: [PATCH 5/9] Use standard TransactionValue component; add docs --- src/address/AddressTransactionResults.tsx | 4 ++-- src/components/FormattedBalance.tsx | 1 + src/components/TransactionValue.tsx | 10 ++++++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/address/AddressTransactionResults.tsx b/src/address/AddressTransactionResults.tsx index 88ae415..24793d0 100644 --- a/src/address/AddressTransactionResults.tsx +++ b/src/address/AddressTransactionResults.tsx @@ -2,7 +2,7 @@ import React, { useContext, useEffect, useMemo, useState } from "react"; import { BlockTag } from "@ethersproject/providers"; import ContentFrame from "../ContentFrame"; import InfoRow from "../components/InfoRow"; -import FormattedBalance from "../components/FormattedBalance"; +import TransactionValue from "../components/TransactionValue"; import TransactionAddress from "../components/TransactionAddress"; import Copy from "../components/Copy"; import TransactionLink from "../components/TransactionLink"; @@ -131,7 +131,7 @@ const AddressTransactionResults: React.FC = ({ {balance && ( - Ether + )} {creator && ( diff --git a/src/components/FormattedBalance.tsx b/src/components/FormattedBalance.tsx index 6f83163..7da298e 100644 --- a/src/components/FormattedBalance.tsx +++ b/src/components/FormattedBalance.tsx @@ -7,6 +7,7 @@ type FormatterBalanceProps = { decimals?: number; }; +// TODO: remove duplication with TransactionValue component const FormattedBalance: React.FC = ({ value, decimals = 18, diff --git a/src/components/TransactionValue.tsx b/src/components/TransactionValue.tsx index f403b4a..618ec2e 100644 --- a/src/components/TransactionValue.tsx +++ b/src/components/TransactionValue.tsx @@ -8,6 +8,16 @@ type TransactionValueProps = { hideUnit?: boolean; }; +/** + * Standard component for displaying balances. It: + * + * - Commify non-decimal parts, i.e., 1,000,000.00 + * - Light gray absolute zero values + * - Cut out decimal part is it is 0 to reduce UI clutter, i.e., show + * 123 instead of 123.00 + * + * TODO: remove duplication with FormattedBalance + */ const TransactionValue: React.FC = ({ value, decimals = 18, From 40c254756577c8cf503c83d110bc9c96d5ae58d4 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Sat, 19 Feb 2022 15:25:37 -0300 Subject: [PATCH 6/9] Extract unit name --- src/components/TransactionValue.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/TransactionValue.tsx b/src/components/TransactionValue.tsx index 618ec2e..c7a8d2c 100644 --- a/src/components/TransactionValue.tsx +++ b/src/components/TransactionValue.tsx @@ -6,6 +6,7 @@ type TransactionValueProps = { value: BigNumber; decimals?: number; hideUnit?: boolean; + unitName?: string; }; /** @@ -22,16 +23,17 @@ const TransactionValue: React.FC = ({ value, decimals = 18, hideUnit, + unitName = "ETH", }) => { const formattedValue = formatValue(value, decimals); return ( {formattedValue} - {!hideUnit && " Ether"} + {!hideUnit && ` ${unitName}`} ); }; From 60931863fa27e0e10c8a0a9d3c2ad343d8cebd62 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Sat, 19 Feb 2022 16:42:25 -0300 Subject: [PATCH 7/9] Add USD price next to ETH balance on address page --- src/PriceBox.tsx | 1 + src/address/AddressTransactionResults.tsx | 20 +++++++++++++++++--- src/components/ETH2USDValue.tsx | 7 +++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/PriceBox.tsx b/src/PriceBox.tsx index ad73d06..2ebb5d7 100644 --- a/src/PriceBox.tsx +++ b/src/PriceBox.tsx @@ -10,6 +10,7 @@ import { useLatestBlock } from "./useLatestBlock"; const ETH_FEED_DECIMALS = 8; +// TODO: reduce duplication with useETHUSDOracle const PriceBox: React.FC = () => { const { provider } = useContext(RuntimeContext); const latestBlock = useLatestBlock(provider); diff --git a/src/address/AddressTransactionResults.tsx b/src/address/AddressTransactionResults.tsx index 24793d0..1a95535 100644 --- a/src/address/AddressTransactionResults.tsx +++ b/src/address/AddressTransactionResults.tsx @@ -3,6 +3,7 @@ import { BlockTag } from "@ethersproject/providers"; import ContentFrame from "../ContentFrame"; import InfoRow from "../components/InfoRow"; import TransactionValue from "../components/TransactionValue"; +import ETH2USDValue from "../components/ETH2USDValue"; import TransactionAddress from "../components/TransactionAddress"; import Copy from "../components/Copy"; import TransactionLink from "../components/TransactionLink"; @@ -101,9 +102,12 @@ const AddressTransactionResults: React.FC = ({ // TODO: dedup blockTags const blockTags: BlockTag[] = useMemo(() => { if (!page) { - return []; + return ["latest"]; } - return page.map((t) => t.blockNumber); + + const blockTags: BlockTag[] = page.map((t) => t.blockNumber); + blockTags.push("latest"); + return blockTags; }, [page]); const priceMap = useMultipleETHUSDOracle(provider, blockTags); @@ -131,7 +135,17 @@ const AddressTransactionResults: React.FC = ({ {balance && ( - +
+ + {!balance.isZero() && priceMap["latest"] !== undefined && ( + + + + )} +
)} {creator && ( diff --git a/src/components/ETH2USDValue.tsx b/src/components/ETH2USDValue.tsx index ef131d8..53ece53 100644 --- a/src/components/ETH2USDValue.tsx +++ b/src/components/ETH2USDValue.tsx @@ -7,6 +7,13 @@ type ETH2USDValueProps = { eth2USDValue: BigNumber; }; +/** + * Basic display of ETH -> USD values WITHOUT box decoration, only + * text formatting. + * + * USD amounts are displayed commified with 2 decimals places and $ prefix, + * i.e., "$1,000.00". + */ const ETH2USDValue: React.FC = ({ ethAmount, eth2USDValue, From 48ab6940018fa1c4782e69d7b68b0c60d2cf5202 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Sat, 19 Feb 2022 16:55:27 -0300 Subject: [PATCH 8/9] Fix wrap --- src/components/Copy.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/Copy.tsx b/src/components/Copy.tsx index 86e902d..41d048e 100644 --- a/src/components/Copy.tsx +++ b/src/components/Copy.tsx @@ -22,7 +22,7 @@ const Copy: React.FC = ({ value, rounded }) => { return (