Merge branch 'feature/fix-eoa-contract-display' into develop

This commit is contained in:
Willian Mitsuda 2021-12-04 17:22:50 -03:00
commit 4935d02e91
10 changed files with 107 additions and 71 deletions

View File

@ -1,4 +1,4 @@
import React, { useEffect, useContext, useCallback } from "react"; import React, { useEffect, useContext, useCallback, useMemo } from "react";
import { import {
useParams, useParams,
useNavigate, useNavigate,
@ -21,8 +21,9 @@ import Contracts from "./address/Contracts";
import { RuntimeContext } from "./useRuntime"; import { RuntimeContext } from "./useRuntime";
import { useAppConfigContext } from "./useAppConfig"; import { useAppConfigContext } from "./useAppConfig";
import { useAddressOrENSFromURL } from "./useResolvedAddresses"; import { useAddressOrENSFromURL } from "./useResolvedAddresses";
import { useSingleMetadata } from "./sourcify/useSourcify"; import { useMultipleMetadata } from "./sourcify/useSourcify";
import { ChecksummedAddress } from "./types"; import { ChecksummedAddress } from "./types";
import { useAddressesWithCode } from "./useErigonHooks";
const AddressTransactions: React.FC = () => { const AddressTransactions: React.FC = () => {
const { provider } = useContext(RuntimeContext); const { provider } = useContext(RuntimeContext);
@ -58,11 +59,24 @@ const AddressTransactions: React.FC = () => {
}, [addressOrName, checksummedAddress, isENS]); }, [addressOrName, checksummedAddress, isENS]);
const { sourcifySource } = useAppConfigContext(); const { sourcifySource } = useAppConfigContext();
const addressMetadata = useSingleMetadata( const checksummedAddressAsArray = useMemo(
checksummedAddress, () => (checksummedAddress !== undefined ? [checksummedAddress] : []),
[checksummedAddress]
);
const contractAddresses = useAddressesWithCode(
provider,
checksummedAddressAsArray
);
const metadatas = useMultipleMetadata(
undefined,
contractAddresses,
provider?.network.chainId, provider?.network.chainId,
sourcifySource sourcifySource
); );
const addressMetadata =
checksummedAddress !== undefined
? metadatas[checksummedAddress]
: undefined;
return ( return (
<StandardFrame> <StandardFrame>
@ -94,34 +108,34 @@ const AddressTransactions: React.FC = () => {
</StandardSubtitle> </StandardSubtitle>
<Tab.Group> <Tab.Group>
<Tab.List className="flex space-x-2 border-l border-r border-t rounded-t-lg bg-white"> <Tab.List className="flex space-x-2 border-l border-r border-t rounded-t-lg bg-white">
<NavTab href={`/address/${checksummedAddress}`}> <NavTab href={`/address/${addressOrName}`}>Overview</NavTab>
Overview {(contractAddresses?.length ?? 0) > 0 && (
</NavTab> <NavTab href={`/address/${addressOrName}/contract`}>
<NavTab href={`/address/${checksummedAddress}/contract`}> <span
<span className={`flex items-baseline space-x-2 ${
className={`flex items-baseline space-x-2 ${ addressMetadata === undefined ? "italic opacity-50" : ""
addressMetadata === undefined ? "italic opacity-50" : "" }`}
}`} >
> <span>Contract</span>
<span>Contract</span> {addressMetadata === undefined ? (
{addressMetadata === undefined ? ( <span className="self-center">
<span className="self-center"> <FontAwesomeIcon
<FontAwesomeIcon className="animate-spin"
className="animate-spin" icon={faCircleNotch}
icon={faCircleNotch} />
/> </span>
</span> ) : addressMetadata === null ? (
) : addressMetadata === null ? ( <span className="self-center text-red-500">
<span className="self-center text-red-500"> <FontAwesomeIcon icon={faQuestionCircle} />
<FontAwesomeIcon icon={faQuestionCircle} /> </span>
</span> ) : (
) : ( <span className="self-center">
<span className="self-center"> <SourcifyLogo />
<SourcifyLogo /> </span>
</span> )}
)} </span>
</span> </NavTab>
</NavTab> )}
</Tab.List> </Tab.List>
<Tab.Panels> <Tab.Panels>
<Routes> <Routes>
@ -142,7 +156,12 @@ const AddressTransactions: React.FC = () => {
element={ element={
<Contracts <Contracts
checksummedAddress={checksummedAddress} checksummedAddress={checksummedAddress}
rawMetadata={addressMetadata} rawMetadata={
contractAddresses !== undefined &&
contractAddresses.length === 0
? null
: addressMetadata
}
/> />
} }
/> />

View File

@ -114,6 +114,9 @@ const AddressTransactionResults: React.FC<AddressTransactionResultsProps> = ({
if (t.to) { if (t.to) {
_addresses.push(t.to); _addresses.push(t.to);
} }
if (t.createdContractAddress) {
_addresses.push(t.createdContractAddress);
}
} }
} }
return _addresses; return _addresses;

View File

@ -40,7 +40,16 @@ const BlockTransactionResults: React.FC<BlockTransactionResultsProps> = ({
return []; return [];
} }
return page.map((t) => t.to).filter((to): to is string => to !== undefined); const _addresses: ChecksummedAddress[] = [];
for (const t of page) {
if (t.to) {
_addresses.push(t.to);
}
if (t.createdContractAddress) {
_addresses.push(t.createdContractAddress);
}
}
return _addresses;
}, [page]); }, [page]);
const metadatas = useContractsMetadata(addresses, provider); const metadatas = useContractsMetadata(addresses, provider);

View File

@ -1,13 +1,19 @@
import { useMemo } from "react";
import { JsonRpcProvider } from "@ethersproject/providers"; import { JsonRpcProvider } from "@ethersproject/providers";
import { ChecksummedAddress } from "./types"; import { ChecksummedAddress } from "./types";
import { import { Metadata, useMultipleMetadata } from "./sourcify/useSourcify";
Metadata,
useDedupedAddresses,
useMultipleMetadata,
} from "./sourcify/useSourcify";
import { useAppConfigContext } from "./useAppConfig"; import { useAppConfigContext } from "./useAppConfig";
import { useAddressesWithCode } from "./useErigonHooks"; import { useAddressesWithCode } from "./useErigonHooks";
export const useDedupedAddresses = (
addresses: ChecksummedAddress[]
): ChecksummedAddress[] => {
return useMemo(() => {
const deduped = new Set(addresses);
return [...deduped];
}, [addresses]);
};
export const useContractsMetadata = ( export const useContractsMetadata = (
addresses: ChecksummedAddress[], addresses: ChecksummedAddress[],
provider: JsonRpcProvider | undefined, provider: JsonRpcProvider | undefined,

View File

@ -99,7 +99,10 @@ const TransactionItem: React.FC<TransactionItemProps> = ({
/> />
</span> </span>
</span> </span>
<span className="col-span-2 flex items-baseline" title={tx.to}> <span
className="col-span-2 flex items-baseline"
title={tx.to ?? tx.createdContractAddress}
>
<span className="truncate"> <span className="truncate">
{tx.to ? ( {tx.to ? (
<AddressHighlighter address={tx.to}> <AddressHighlighter address={tx.to}>

View File

@ -52,7 +52,7 @@ export class SearchController {
idx: _receipt.transactionIndex, idx: _receipt.transactionIndex,
hash: t.hash, hash: t.hash,
from: t.from, from: t.from,
to: t.to, to: t.to ?? null,
createdContractAddress: _receipt.contractAddress, createdContractAddress: _receipt.contractAddress,
value: t.value, value: t.value,
fee: _receipt.gasUsed.mul(t.gasPrice!), fee: _receipt.gasUsed.mul(t.gasPrice!),

View File

@ -121,25 +121,6 @@ export const useSourcify = (
return rawMetadata; return rawMetadata;
}; };
export const useSingleMetadata = (
address: ChecksummedAddress | undefined,
chainId: number | undefined,
source: SourcifySource
) => {
const addresses = useMemo(() => (address ? [address] : []), [address]);
const metadatas = useMultipleMetadata(undefined, addresses, chainId, source);
return address !== undefined ? metadatas[address] : undefined;
};
export const useDedupedAddresses = (
addresses: ChecksummedAddress[]
): ChecksummedAddress[] => {
return useMemo(() => {
const deduped = new Set(addresses);
return [...deduped];
}, [addresses]);
};
export const useMultipleMetadata = ( export const useMultipleMetadata = (
baseMetadatas: Record<string, Metadata | null> | undefined, baseMetadatas: Record<string, Metadata | null> | undefined,
addresses: ChecksummedAddress[] | undefined, addresses: ChecksummedAddress[] | undefined,

View File

@ -16,7 +16,7 @@ export type ProcessedTransaction = {
idx: number; idx: number;
hash: string; hash: string;
from?: string; from?: string;
to?: string; to: string | null;
createdContractAddress?: string; createdContractAddress?: string;
internalMinerInteraction?: boolean; internalMinerInteraction?: boolean;
value: BigNumber; value: BigNumber;

View File

@ -95,33 +95,38 @@ export const useBlockTransactions = (
const _receipts = result.receipts; const _receipts = result.receipts;
const rawTxs = _block.transactions const rawTxs = _block.transactions
.map( .map((t, i): ProcessedTransaction => {
(t, i): ProcessedTransaction => ({ const _rawReceipt = _receipts[i];
// Empty logs on purpose because of ethers formatter requires it
_rawReceipt.logs = [];
const _receipt = provider.formatter.receipt(_rawReceipt);
return {
blockNumber: blockNumber, blockNumber: blockNumber,
timestamp: _block.timestamp, timestamp: _block.timestamp,
miner: _block.miner, miner: _block.miner,
idx: i, idx: i,
hash: t.hash, hash: t.hash,
from: t.from, from: t.from,
to: t.to, to: t.to ?? null,
createdContractAddress: _receipts[i].contractAddress, createdContractAddress: _receipt.contractAddress,
value: t.value, value: t.value,
fee: fee:
t.type !== 2 t.type !== 2
? provider.formatter ? provider.formatter
.bigNumber(_receipts[i].gasUsed) .bigNumber(_receipt.gasUsed)
.mul(t.gasPrice!) .mul(t.gasPrice!)
: provider.formatter : provider.formatter
.bigNumber(_receipts[i].gasUsed) .bigNumber(_receipt.gasUsed)
.mul(t.maxPriorityFeePerGas!.add(_block.baseFeePerGas!)), .mul(t.maxPriorityFeePerGas!.add(_block.baseFeePerGas!)),
gasPrice: gasPrice:
t.type !== 2 t.type !== 2
? t.gasPrice! ? t.gasPrice!
: t.maxPriorityFeePerGas!.add(_block.baseFeePerGas!), : t.maxPriorityFeePerGas!.add(_block.baseFeePerGas!),
data: t.data, data: t.data,
status: provider.formatter.number(_receipts[i].status), status: provider.formatter.number(_receipt.status),
}) };
) })
.reverse(); .reverse();
setTxs(rawTxs); setTxs(rawTxs);
setTotalTxs(result.fullblock.transactionCount); setTotalTxs(result.fullblock.transactionCount);
@ -457,8 +462,10 @@ export const useAddressesWithCode = (
const [results, setResults] = useState<ChecksummedAddress[] | undefined>(); const [results, setResults] = useState<ChecksummedAddress[] | undefined>();
useEffect(() => { useEffect(() => {
// Reset
setResults(undefined);
if (provider === undefined) { if (provider === undefined) {
setResults(undefined);
return; return;
} }

View File

@ -27,6 +27,11 @@ export const useAddressOrENSFromURL = (
// If it looks like it is an ENS name, try to resolve it // If it looks like it is an ENS name, try to resolve it
useEffect(() => { useEffect(() => {
// Reset
setENS(false);
setError(false);
setChecksummedAddress(undefined);
// TODO: handle and offer fallback to bad checksummed addresses // TODO: handle and offer fallback to bad checksummed addresses
if (isAddress(addressOrName)) { if (isAddress(addressOrName)) {
// Normalize to checksummed address // Normalize to checksummed address
@ -81,6 +86,9 @@ export const pageCollector =
if (tx.to) { if (tx.to) {
uniqueAddresses.add(tx.to); uniqueAddresses.add(tx.to);
} }
if (tx.createdContractAddress) {
uniqueAddresses.add(tx.createdContractAddress);
}
} }
return Array.from(uniqueAddresses); return Array.from(uniqueAddresses);