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;
|
address: string;
|
||||||
addressCtx?: AddressContext | undefined;
|
addressCtx?: AddressContext | undefined;
|
||||||
metadata?: Metadata | null | undefined;
|
metadata?: Metadata | null | undefined;
|
||||||
|
eoa?: boolean | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
const TransactionAddress: React.FC<TransactionAddressProps> = ({
|
const TransactionAddress: React.FC<TransactionAddressProps> = ({
|
||||||
address,
|
address,
|
||||||
addressCtx,
|
addressCtx,
|
||||||
metadata,
|
metadata,
|
||||||
|
eoa,
|
||||||
}) => {
|
}) => {
|
||||||
const txData = useSelectedTransaction();
|
const txData = useSelectedTransaction();
|
||||||
// TODO: push down creation coloring logic into DecoratedAddressLink
|
// TODO: push down creation coloring logic into DecoratedAddressLink
|
||||||
|
@ -30,6 +32,7 @@ const TransactionAddress: React.FC<TransactionAddressProps> = ({
|
||||||
txTo={address === txData?.to || creation}
|
txTo={address === txData?.to || creation}
|
||||||
creation={creation}
|
creation={creation}
|
||||||
metadata={metadata}
|
metadata={metadata}
|
||||||
|
eoa={eoa}
|
||||||
/>
|
/>
|
||||||
</AddressHighlighter>
|
</AddressHighlighter>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React from "react";
|
import React, { useContext } from "react";
|
||||||
import { BlockTag } from "@ethersproject/abstract-provider";
|
import { BlockTag } from "@ethersproject/abstract-provider";
|
||||||
import { BigNumber } from "@ethersproject/bignumber";
|
import { BigNumber } from "@ethersproject/bignumber";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
@ -16,6 +16,8 @@ import TransactionDirection, {
|
||||||
import TransactionValue from "../components/TransactionValue";
|
import TransactionValue from "../components/TransactionValue";
|
||||||
import { ChecksummedAddress, ProcessedTransaction } from "../types";
|
import { ChecksummedAddress, ProcessedTransaction } from "../types";
|
||||||
import { FeeDisplay } from "./useFeeToggler";
|
import { FeeDisplay } from "./useFeeToggler";
|
||||||
|
import { RuntimeContext } from "../useRuntime";
|
||||||
|
import { useHasCode } from "../useErigonHooks";
|
||||||
import { formatValue } from "../components/formatter";
|
import { formatValue } from "../components/formatter";
|
||||||
import ETH2USDValue from "../components/ETH2USDValue";
|
import ETH2USDValue from "../components/ETH2USDValue";
|
||||||
import { Metadata } from "../sourcify/useSourcify";
|
import { Metadata } from "../sourcify/useSourcify";
|
||||||
|
@ -35,6 +37,13 @@ const TransactionItem: React.FC<TransactionItemProps> = ({
|
||||||
priceMap,
|
priceMap,
|
||||||
metadatas,
|
metadatas,
|
||||||
}) => {
|
}) => {
|
||||||
|
const { provider } = useContext(RuntimeContext);
|
||||||
|
const toHasCode = useHasCode(
|
||||||
|
provider,
|
||||||
|
tx.to ?? undefined,
|
||||||
|
tx.blockNumber - 1
|
||||||
|
);
|
||||||
|
|
||||||
let direction: Direction | undefined;
|
let direction: Direction | undefined;
|
||||||
if (selectedAddress) {
|
if (selectedAddress) {
|
||||||
if (tx.from === selectedAddress && tx.to === selectedAddress) {
|
if (tx.from === selectedAddress && tx.to === selectedAddress) {
|
||||||
|
@ -107,6 +116,7 @@ const TransactionItem: React.FC<TransactionItemProps> = ({
|
||||||
selectedAddress={selectedAddress}
|
selectedAddress={selectedAddress}
|
||||||
miner={tx.miner === tx.to}
|
miner={tx.miner === tx.to}
|
||||||
metadata={metadatas[tx.to]}
|
metadata={metadatas[tx.to]}
|
||||||
|
eoa={toHasCode === undefined ? undefined : !toHasCode}
|
||||||
/>
|
/>
|
||||||
</AddressHighlighter>
|
</AddressHighlighter>
|
||||||
) : (
|
) : (
|
||||||
|
@ -116,6 +126,7 @@ const TransactionItem: React.FC<TransactionItemProps> = ({
|
||||||
selectedAddress={selectedAddress}
|
selectedAddress={selectedAddress}
|
||||||
creation
|
creation
|
||||||
metadata={metadatas[tx.createdContractAddress!]}
|
metadata={metadatas[tx.createdContractAddress!]}
|
||||||
|
eoa={false}
|
||||||
/>
|
/>
|
||||||
</AddressHighlighter>
|
</AddressHighlighter>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -45,7 +45,7 @@ import {
|
||||||
import { DevDoc, Metadata, useError, UserDoc } from "../sourcify/useSourcify";
|
import { DevDoc, Metadata, useError, UserDoc } from "../sourcify/useSourcify";
|
||||||
import { RuntimeContext } from "../useRuntime";
|
import { RuntimeContext } from "../useRuntime";
|
||||||
import { useContractsMetadata } from "../hooks";
|
import { useContractsMetadata } from "../hooks";
|
||||||
import { useTransactionError } from "../useErigonHooks";
|
import { useHasCode, useTransactionError } from "../useErigonHooks";
|
||||||
|
|
||||||
type DetailsProps = {
|
type DetailsProps = {
|
||||||
txData: TransactionData;
|
txData: TransactionData;
|
||||||
|
@ -118,6 +118,12 @@ const Details: React.FC<DetailsProps> = ({
|
||||||
: undefined;
|
: undefined;
|
||||||
const [expanded, setExpanded] = useState<boolean>(false);
|
const [expanded, setExpanded] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const toHasCode = useHasCode(
|
||||||
|
provider,
|
||||||
|
txData.to,
|
||||||
|
txData.confirmedData ? txData.confirmedData.blockNumber - 1 : undefined
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContentFrame tabs>
|
<ContentFrame tabs>
|
||||||
<InfoRow title="Transaction Hash">
|
<InfoRow title="Transaction Hash">
|
||||||
|
@ -264,6 +270,7 @@ const Details: React.FC<DetailsProps> = ({
|
||||||
<TransactionAddress
|
<TransactionAddress
|
||||||
address={txData.to}
|
address={txData.to}
|
||||||
metadata={metadatas?.[txData.to]}
|
metadata={metadatas?.[txData.to]}
|
||||||
|
eoa={toHasCode === undefined ? undefined : !toHasCode}
|
||||||
/>
|
/>
|
||||||
<Copy value={txData.to} />
|
<Copy value={txData.to} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
import { useState, useEffect } from "react";
|
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 { JsonRpcProvider } from "@ethersproject/providers";
|
||||||
import { getAddress } from "@ethersproject/address";
|
import { getAddress } from "@ethersproject/address";
|
||||||
import { Contract } from "@ethersproject/contracts";
|
import { Contract } from "@ethersproject/contracts";
|
||||||
|
@ -679,3 +683,40 @@ export const useAddressBalance = (
|
||||||
|
|
||||||
return balance;
|
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