Add new eoa/contract legend to addresses in search results list/tx details page
This commit is contained in:
parent
8f78380521
commit
6220d230fa
|
@ -9,12 +9,14 @@ type TransactionAddressProps = {
|
|||
address: string;
|
||||
addressCtx?: AddressContext | undefined;
|
||||
metadata?: Metadata | null | undefined;
|
||||
eoa?: boolean | undefined;
|
||||
};
|
||||
|
||||
const TransactionAddress: React.FC<TransactionAddressProps> = ({
|
||||
address,
|
||||
addressCtx,
|
||||
metadata,
|
||||
eoa,
|
||||
}) => {
|
||||
const txData = useSelectedTransaction();
|
||||
// TODO: push down creation coloring logic into DecoratedAddressLink
|
||||
|
@ -30,6 +32,7 @@ const TransactionAddress: React.FC<TransactionAddressProps> = ({
|
|||
txTo={address === txData?.to || creation}
|
||||
creation={creation}
|
||||
metadata={metadata}
|
||||
eoa={eoa}
|
||||
/>
|
||||
</AddressHighlighter>
|
||||
);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React from "react";
|
||||
import React, { useContext } from "react";
|
||||
import { BlockTag } from "@ethersproject/abstract-provider";
|
||||
import { BigNumber } from "@ethersproject/bignumber";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
|
@ -16,6 +16,8 @@ import TransactionDirection, {
|
|||
import TransactionValue from "../components/TransactionValue";
|
||||
import { ChecksummedAddress, ProcessedTransaction } from "../types";
|
||||
import { FeeDisplay } from "./useFeeToggler";
|
||||
import { RuntimeContext } from "../useRuntime";
|
||||
import { useHasCode } from "../useErigonHooks";
|
||||
import { formatValue } from "../components/formatter";
|
||||
import ETH2USDValue from "../components/ETH2USDValue";
|
||||
import { Metadata } from "../sourcify/useSourcify";
|
||||
|
@ -35,6 +37,13 @@ const TransactionItem: React.FC<TransactionItemProps> = ({
|
|||
priceMap,
|
||||
metadatas,
|
||||
}) => {
|
||||
const { provider } = useContext(RuntimeContext);
|
||||
const toHasCode = useHasCode(
|
||||
provider,
|
||||
tx.to ?? undefined,
|
||||
tx.blockNumber - 1
|
||||
);
|
||||
|
||||
let direction: Direction | undefined;
|
||||
if (selectedAddress) {
|
||||
if (tx.from === selectedAddress && tx.to === selectedAddress) {
|
||||
|
@ -107,6 +116,7 @@ const TransactionItem: React.FC<TransactionItemProps> = ({
|
|||
selectedAddress={selectedAddress}
|
||||
miner={tx.miner === tx.to}
|
||||
metadata={metadatas[tx.to]}
|
||||
eoa={toHasCode === undefined ? undefined : !toHasCode}
|
||||
/>
|
||||
</AddressHighlighter>
|
||||
) : (
|
||||
|
@ -116,6 +126,7 @@ const TransactionItem: React.FC<TransactionItemProps> = ({
|
|||
selectedAddress={selectedAddress}
|
||||
creation
|
||||
metadata={metadatas[tx.createdContractAddress!]}
|
||||
eoa={false}
|
||||
/>
|
||||
</AddressHighlighter>
|
||||
)}
|
||||
|
|
|
@ -45,7 +45,7 @@ import {
|
|||
import { DevDoc, Metadata, useError, UserDoc } from "../sourcify/useSourcify";
|
||||
import { RuntimeContext } from "../useRuntime";
|
||||
import { useContractsMetadata } from "../hooks";
|
||||
import { useTransactionError } from "../useErigonHooks";
|
||||
import { useHasCode, useTransactionError } from "../useErigonHooks";
|
||||
|
||||
type DetailsProps = {
|
||||
txData: TransactionData;
|
||||
|
@ -118,6 +118,12 @@ const Details: React.FC<DetailsProps> = ({
|
|||
: undefined;
|
||||
const [expanded, setExpanded] = useState<boolean>(false);
|
||||
|
||||
const toHasCode = useHasCode(
|
||||
provider,
|
||||
txData.to,
|
||||
txData.confirmedData ? txData.confirmedData.blockNumber - 1 : undefined
|
||||
);
|
||||
|
||||
return (
|
||||
<ContentFrame tabs>
|
||||
<InfoRow title="Transaction Hash">
|
||||
|
@ -264,6 +270,7 @@ const Details: React.FC<DetailsProps> = ({
|
|||
<TransactionAddress
|
||||
address={txData.to}
|
||||
metadata={metadatas?.[txData.to]}
|
||||
eoa={toHasCode === undefined ? undefined : !toHasCode}
|
||||
/>
|
||||
<Copy value={txData.to} />
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
import { useState, useEffect } from "react";
|
||||
import { Block, BlockWithTransactions } from "@ethersproject/abstract-provider";
|
||||
import {
|
||||
Block,
|
||||
BlockWithTransactions,
|
||||
BlockTag,
|
||||
} from "@ethersproject/abstract-provider";
|
||||
import { JsonRpcProvider } from "@ethersproject/providers";
|
||||
import { getAddress } from "@ethersproject/address";
|
||||
import { Contract } from "@ethersproject/contracts";
|
||||
|
@ -679,3 +683,40 @@ export const useAddressBalance = (
|
|||
|
||||
return balance;
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a generic fetch for SWR, where the key is an array, whose
|
||||
* element 0 is the JSON-RPC method, and the remaining are the method
|
||||
* arguments.
|
||||
*/
|
||||
export const providerFetcher =
|
||||
(provider: JsonRpcProvider | undefined) =>
|
||||
async (...key: any[]): Promise<any | undefined> => {
|
||||
if (provider === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
for (const a of key) {
|
||||
if (a === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
const method = key[0];
|
||||
const args = key.slice(1);
|
||||
const result = await provider.send(method, args);
|
||||
// console.log(`providerFetcher: ${method} ${args} === ${result}`);
|
||||
return result;
|
||||
};
|
||||
|
||||
export const useHasCode = (
|
||||
provider: JsonRpcProvider | undefined,
|
||||
address: ChecksummedAddress | undefined,
|
||||
blockTag: BlockTag = "latest"
|
||||
): boolean | undefined => {
|
||||
const fetcher = providerFetcher(provider);
|
||||
const { data, error } = useSWR(["ots_hasCode", address, blockTag], fetcher);
|
||||
if (error) {
|
||||
return undefined;
|
||||
}
|
||||
return data as boolean | undefined;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue