From f1a9a2f65dc018f67ef805712ccc6a1f9810844a Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Thu, 24 Mar 2022 15:20:54 -0300 Subject: [PATCH] Add support for eoa/contract indicator on address input decoders; generalized indicator support by pushing it down to TransactionAddress component --- src/TokenTransferItem.tsx | 23 +---- src/TransactionPageContent.tsx | 105 +++++++++++---------- src/components/TransactionAddress.tsx | 27 ++++-- src/transaction/Details.tsx | 11 +-- src/transaction/TraceInput.tsx | 19 +--- src/transaction/decoder/AddressDecoder.tsx | 5 +- src/useBlockTagContext.tsx | 15 +++ 7 files changed, 102 insertions(+), 103 deletions(-) create mode 100644 src/useBlockTagContext.tsx diff --git a/src/TokenTransferItem.tsx b/src/TokenTransferItem.tsx index 940d9e2..0869a17 100644 --- a/src/TokenTransferItem.tsx +++ b/src/TokenTransferItem.tsx @@ -1,4 +1,4 @@ -import React, { useContext } from "react"; +import React from "react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faCaretRight } from "@fortawesome/free-solid-svg-icons/faCaretRight"; import TransactionAddress from "./components/TransactionAddress"; @@ -9,17 +9,13 @@ import { ChecksummedAddress, TokenMeta, TokenTransfer, - TransactionData, } from "./types"; -import { RuntimeContext } from "./useRuntime"; -import { useHasCode } from "./useErigonHooks"; import { Metadata } from "./sourcify/useSourcify"; type TokenTransferItemProps = { t: TokenTransfer; tokenMeta?: TokenMeta | null | undefined; metadatas: Record; - txData: TransactionData; }; // TODO: handle partial @@ -27,20 +23,7 @@ const TokenTransferItem: React.FC = ({ t, tokenMeta, metadatas, - txData, }) => { - const { provider } = useContext(RuntimeContext); - const fromHasCode = useHasCode( - provider, - t.from, - txData.confirmedData ? txData.confirmedData.blockNumber - 1 : undefined - ); - const toHasCode = useHasCode( - provider, - t.to, - txData.confirmedData ? txData.confirmedData.blockNumber - 1 : undefined - ); - return (
@@ -53,7 +36,7 @@ const TokenTransferItem: React.FC = ({ address={t.from} addressCtx={AddressContext.FROM} metadata={metadatas[t.from]} - eoa={fromHasCode === undefined ? undefined : !fromHasCode} + showCodeIndicator />
@@ -62,7 +45,7 @@ const TokenTransferItem: React.FC = ({ address={t.to} addressCtx={AddressContext.TO} metadata={metadatas[t.to]} - eoa={toHasCode === undefined ? undefined : !toHasCode} + showCodeIndicator />
diff --git a/src/TransactionPageContent.tsx b/src/TransactionPageContent.tsx index 377c345..31a7974 100644 --- a/src/TransactionPageContent.tsx +++ b/src/TransactionPageContent.tsx @@ -9,6 +9,7 @@ import { RuntimeContext } from "./useRuntime"; import { useInternalOperations, useTxData } from "./useErigonHooks"; import { SelectionContext, useSelection } from "./useSelection"; import { SelectedTransactionContext } from "./useSelectedTransaction"; +import { BlockNumberContext } from "./useBlockTagContext"; import { useETHUSDOracle } from "./usePriceOracle"; import { useAppConfigContext } from "./useAppConfig"; import { useSourcify, useTransactionDescription } from "./sourcify/useSourcify"; @@ -74,56 +75,60 @@ const TransactionPageContent: React.FC = ({ return ( - - Transaction Details - {txData === null && ( - -
- Transaction {txHash} not found. -
-
- )} - {txData && ( - - - - Overview - {txData.confirmedData?.blockNumber !== undefined && ( - - Logs - {txData && ` (${txData.confirmedData?.logs?.length ?? 0})`} - - )} - Trace - - - - - - } - /> - } - /> - } /> - - - - )} -
+ + + Transaction Details + {txData === null && ( + +
+ Transaction {txHash} not + found. +
+
+ )} + {txData && ( + + + + Overview + {txData.confirmedData?.blockNumber !== undefined && ( + + Logs + {txData && + ` (${txData.confirmedData?.logs?.length ?? 0})`} + + )} + Trace + + + + + + } + /> + } + /> + } /> + + + + )} +
+
); }; diff --git a/src/components/TransactionAddress.tsx b/src/components/TransactionAddress.tsx index 6a76dea..279dff8 100644 --- a/src/components/TransactionAddress.tsx +++ b/src/components/TransactionAddress.tsx @@ -1,27 +1,38 @@ -import React from "react"; +import React, { useContext } from "react"; import AddressHighlighter from "./AddressHighlighter"; import DecoratedAddressLink from "./DecoratedAddressLink"; import { useSelectedTransaction } from "../useSelectedTransaction"; -import { AddressContext } from "../types"; +import { useBlockNumberContext } from "../useBlockTagContext"; +import { RuntimeContext } from "../useRuntime"; +import { useHasCode } from "../useErigonHooks"; import { Metadata } from "../sourcify/useSourcify"; +import { AddressContext, ChecksummedAddress } from "../types"; type TransactionAddressProps = { - address: string; + address: ChecksummedAddress; addressCtx?: AddressContext | undefined; metadata?: Metadata | null | undefined; - eoa?: boolean | undefined; + showCodeIndicator?: boolean; }; const TransactionAddress: React.FC = ({ address, addressCtx, metadata, - eoa, + showCodeIndicator = false, }) => { const txData = useSelectedTransaction(); // TODO: push down creation coloring logic into DecoratedAddressLink const creation = address === txData?.confirmedData?.createdContractAddress; + const { provider } = useContext(RuntimeContext); + const blockNumber = useBlockNumberContext(); + const toHasCode = useHasCode( + provider, + address, + blockNumber !== undefined ? blockNumber - 1 : undefined + ); + return ( = ({ txTo={address === txData?.to || creation} creation={creation} metadata={metadata} - eoa={eoa} + eoa={ + showCodeIndicator !== undefined && blockNumber !== undefined + ? !toHasCode + : undefined + } /> ); diff --git a/src/transaction/Details.tsx b/src/transaction/Details.tsx index fd8acab..f8243f0 100644 --- a/src/transaction/Details.tsx +++ b/src/transaction/Details.tsx @@ -45,7 +45,7 @@ import { import { DevDoc, Metadata, useError, UserDoc } from "../sourcify/useSourcify"; import { RuntimeContext } from "../useRuntime"; import { useContractsMetadata } from "../hooks"; -import { useHasCode, useTransactionError } from "../useErigonHooks"; +import { useTransactionError } from "../useErigonHooks"; type DetailsProps = { txData: TransactionData; @@ -118,12 +118,6 @@ const Details: React.FC = ({ : undefined; const [expanded, setExpanded] = useState(false); - const toHasCode = useHasCode( - provider, - txData.to, - txData.confirmedData ? txData.confirmedData.blockNumber - 1 : undefined - ); - return ( @@ -270,7 +264,7 @@ const Details: React.FC = ({
@@ -314,7 +308,6 @@ const Details: React.FC = ({ t={t} tokenMeta={txData.tokenMetas[t.token]} metadatas={metadatas} - txData={txData} /> ))} diff --git a/src/transaction/TraceInput.tsx b/src/transaction/TraceInput.tsx index 68cca6c..7b917ff 100644 --- a/src/transaction/TraceInput.tsx +++ b/src/transaction/TraceInput.tsx @@ -1,4 +1,4 @@ -import React, { useContext, useState } from "react"; +import React, { useState } from "react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faBomb } from "@fortawesome/free-solid-svg-icons/faBomb"; import TransactionAddress from "../components/TransactionAddress"; @@ -6,8 +6,7 @@ import FormattedBalance from "../components/FormattedBalance"; import FunctionSignature from "./FunctionSignature"; import InputDecoder from "./decoder/InputDecoder"; import ExpanderSwitch from "../components/ExpanderSwitch"; -import { RuntimeContext } from "../useRuntime"; -import { TraceEntry, useHasCode } from "../useErigonHooks"; +import { TraceEntry } from "../useErigonHooks"; import { extract4Bytes, use4Bytes, @@ -35,15 +34,6 @@ const TraceInput: React.FC = ({ t, txData }) => { const [expanded, setExpanded] = useState(false); - const { provider } = useContext(RuntimeContext); - const toHasCode = useHasCode( - provider, - t.to, - txData.confirmedData !== undefined - ? txData.confirmedData.blockNumber - 1 - : undefined - ); - return (
= ({ t, txData }) => { ) : ( <> - + {t.type !== "CREATE" && t.type !== "CREATE2" && ( <> diff --git a/src/transaction/decoder/AddressDecoder.tsx b/src/transaction/decoder/AddressDecoder.tsx index 7c5c3ce..7c0104d 100644 --- a/src/transaction/decoder/AddressDecoder.tsx +++ b/src/transaction/decoder/AddressDecoder.tsx @@ -1,14 +1,15 @@ import React from "react"; import TransactionAddress from "../../components/TransactionAddress"; import Copy from "../../components/Copy"; +import { ChecksummedAddress } from "../../types"; type AddressDecoderProps = { - r: string; + r: ChecksummedAddress; }; const AddressDecoder: React.FC = ({ r }) => (
- +
); diff --git a/src/useBlockTagContext.tsx b/src/useBlockTagContext.tsx new file mode 100644 index 0000000..8504fca --- /dev/null +++ b/src/useBlockTagContext.tsx @@ -0,0 +1,15 @@ +import { createContext, useContext } from "react"; + +/** + * This context means child components have a temporal context expressed in + * terms of BlockTag. + * + * One obvious example is: child components want to show an UI indicator if + * the address is an EOA or contract. But if this address is currently a + * contract and it is an UI element of an existing transaction, it may be that + * at the time (block) the transaction happened it was still an EOA (create2), + * so it should be displayed as an EOA. + */ +export const BlockNumberContext = createContext(undefined); + +export const useBlockNumberContext = () => useContext(BlockNumberContext);