Merge branch 'feature/fix-eoa-contract-display' into develop
This commit is contained in:
commit
4935d02e91
|
@ -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
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
16
src/hooks.ts
16
src/hooks.ts
|
@ -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,
|
||||||
|
|
|
@ -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}>
|
||||||
|
|
|
@ -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!),
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue