Replace useMultipleMetadata by SWR
This commit is contained in:
parent
17d44433ca
commit
a2c2403d05
@ -23,7 +23,7 @@ import Contracts from "./address/Contracts";
|
|||||||
import { RuntimeContext } from "./useRuntime";
|
import { RuntimeContext } from "./useRuntime";
|
||||||
import { useAppConfigContext } from "./useAppConfig";
|
import { useAppConfigContext } from "./useAppConfig";
|
||||||
import { useAddressOrENS } from "./useResolvedAddresses";
|
import { useAddressOrENS } from "./useResolvedAddresses";
|
||||||
import { useMultipleMetadata } from "./sourcify/useSourcify";
|
import { useSourcifyMetadata } from "./sourcify/useSourcify";
|
||||||
import { ChecksummedAddress } from "./types";
|
import { ChecksummedAddress } from "./types";
|
||||||
import { useAddressesWithCode } from "./useErigonHooks";
|
import { useAddressesWithCode } from "./useErigonHooks";
|
||||||
import { useChainInfo } from "./useChainInfo";
|
import { useChainInfo } from "./useChainInfo";
|
||||||
@ -65,7 +65,6 @@ const Address: React.FC = () => {
|
|||||||
}
|
}
|
||||||
}, [addressOrName, checksummedAddress, isENS]);
|
}, [addressOrName, checksummedAddress, isENS]);
|
||||||
|
|
||||||
const { sourcifySource } = useAppConfigContext();
|
|
||||||
const checksummedAddressAsArray = useMemo(
|
const checksummedAddressAsArray = useMemo(
|
||||||
() => (checksummedAddress !== undefined ? [checksummedAddress] : []),
|
() => (checksummedAddress !== undefined ? [checksummedAddress] : []),
|
||||||
[checksummedAddress]
|
[checksummedAddress]
|
||||||
@ -74,16 +73,13 @@ const Address: React.FC = () => {
|
|||||||
provider,
|
provider,
|
||||||
checksummedAddressAsArray
|
checksummedAddressAsArray
|
||||||
);
|
);
|
||||||
const metadatas = useMultipleMetadata(
|
// TODO: restore filter to only check Sourcify metadata if the address is a contract (hasCode)
|
||||||
undefined,
|
const { sourcifySource } = useAppConfigContext();
|
||||||
contractAddresses,
|
const addressMetadata = useSourcifyMetadata(
|
||||||
|
checksummedAddress,
|
||||||
provider?.network.chainId,
|
provider?.network.chainId,
|
||||||
sourcifySource
|
sourcifySource
|
||||||
);
|
);
|
||||||
const addressMetadata =
|
|
||||||
checksummedAddress !== undefined
|
|
||||||
? metadatas[checksummedAddress]
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
const { network, faucets } = useChainInfo();
|
const { network, faucets } = useChainInfo();
|
||||||
|
|
||||||
|
@ -98,10 +98,7 @@ const TransactionPageContent: React.FC<TransactionPageContentProps> = ({
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route path="logs" element={<Logs txData={txData} />} />
|
||||||
path="logs"
|
|
||||||
element={<Logs txData={txData} metadata={metadata} />}
|
|
||||||
/>
|
|
||||||
<Route path="trace" element={<Trace txData={txData} />} />
|
<Route path="trace" element={<Trace txData={txData} />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</React.Suspense>
|
</React.Suspense>
|
||||||
|
33
src/hooks.ts
33
src/hooks.ts
@ -1,33 +0,0 @@
|
|||||||
import { useMemo } from "react";
|
|
||||||
import { JsonRpcProvider } from "@ethersproject/providers";
|
|
||||||
import { ChecksummedAddress } from "./types";
|
|
||||||
import { Metadata, useMultipleMetadata } from "./sourcify/useSourcify";
|
|
||||||
import { useAppConfigContext } from "./useAppConfig";
|
|
||||||
import { useAddressesWithCode } from "./useErigonHooks";
|
|
||||||
|
|
||||||
const useDedupedAddresses = (
|
|
||||||
addresses: ChecksummedAddress[]
|
|
||||||
): ChecksummedAddress[] => {
|
|
||||||
return useMemo(() => {
|
|
||||||
const deduped = new Set(addresses);
|
|
||||||
return [...deduped];
|
|
||||||
}, [addresses]);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useContractsMetadata = (
|
|
||||||
addresses: ChecksummedAddress[],
|
|
||||||
provider: JsonRpcProvider | undefined,
|
|
||||||
baseMetadatas?: Record<string, Metadata | null>
|
|
||||||
) => {
|
|
||||||
const deduped = useDedupedAddresses(addresses);
|
|
||||||
const contracts = useAddressesWithCode(provider, deduped);
|
|
||||||
const { sourcifySource } = useAppConfigContext();
|
|
||||||
const metadatas = useMultipleMetadata(
|
|
||||||
baseMetadatas,
|
|
||||||
contracts,
|
|
||||||
provider?.network.chainId,
|
|
||||||
sourcifySource
|
|
||||||
);
|
|
||||||
|
|
||||||
return metadatas;
|
|
||||||
};
|
|
@ -121,55 +121,6 @@ export const useSourcifyMetadata = (
|
|||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useMultipleMetadata = (
|
|
||||||
baseMetadatas: Record<string, Metadata | null> | undefined,
|
|
||||||
addresses: ChecksummedAddress[] | undefined,
|
|
||||||
chainId: number | undefined,
|
|
||||||
source: SourcifySource
|
|
||||||
): Record<ChecksummedAddress, Metadata | null | undefined> => {
|
|
||||||
const [rawMetadata, setRawMetadata] = useState<
|
|
||||||
Record<string, Metadata | null | undefined>
|
|
||||||
>({});
|
|
||||||
useEffect(() => {
|
|
||||||
if (addresses === undefined || chainId === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setRawMetadata({});
|
|
||||||
|
|
||||||
const abortController = new AbortController();
|
|
||||||
const fetchMetadata = async (_addresses: string[]) => {
|
|
||||||
const fetchers: Promise<Metadata | null>[] = [];
|
|
||||||
for (const address of _addresses) {
|
|
||||||
fetchers.push(
|
|
||||||
fetchSourcifyMetadata(address, chainId, source, abortController)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const results = await Promise.all(fetchers);
|
|
||||||
if (abortController.signal.aborted) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let metadatas: Record<string, Metadata | null> = {};
|
|
||||||
if (baseMetadatas) {
|
|
||||||
metadatas = { ...baseMetadatas };
|
|
||||||
}
|
|
||||||
for (let i = 0; i < results.length; i++) {
|
|
||||||
metadatas[_addresses[i]] = results[i];
|
|
||||||
}
|
|
||||||
setRawMetadata(metadatas);
|
|
||||||
};
|
|
||||||
|
|
||||||
const filtered = addresses.filter((a) => baseMetadatas?.[a] === undefined);
|
|
||||||
fetchMetadata(filtered);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
abortController.abort();
|
|
||||||
};
|
|
||||||
}, [baseMetadatas, addresses, chainId, source]);
|
|
||||||
|
|
||||||
return rawMetadata;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useContract = (
|
export const useContract = (
|
||||||
checksummedAddress: string,
|
checksummedAddress: string,
|
||||||
networkId: number,
|
networkId: number,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { useMemo } from "react";
|
import React, { useContext, useMemo } from "react";
|
||||||
import { Log } from "@ethersproject/abstract-provider";
|
import { Log } from "@ethersproject/abstract-provider";
|
||||||
import { Fragment, Interface, LogDescription } from "@ethersproject/abi";
|
import { Fragment, Interface } from "@ethersproject/abi";
|
||||||
import { Tab } from "@headlessui/react";
|
import { Tab } from "@headlessui/react";
|
||||||
import TransactionAddress from "../components/TransactionAddress";
|
import TransactionAddress from "../components/TransactionAddress";
|
||||||
import Copy from "../components/Copy";
|
import Copy from "../components/Copy";
|
||||||
@ -8,15 +8,41 @@ import ModeTab from "../components/ModeTab";
|
|||||||
import DecodedParamsTable from "./decoder/DecodedParamsTable";
|
import DecodedParamsTable from "./decoder/DecodedParamsTable";
|
||||||
import DecodedLogSignature from "./decoder/DecodedLogSignature";
|
import DecodedLogSignature from "./decoder/DecodedLogSignature";
|
||||||
import { useTopic0 } from "../useTopic0";
|
import { useTopic0 } from "../useTopic0";
|
||||||
import { ChecksummedAddress } from "../types";
|
import { RuntimeContext } from "../useRuntime";
|
||||||
import { Metadata } from "../sourcify/useSourcify";
|
import { useAppConfigContext } from "../useAppConfig";
|
||||||
|
import { useSourcifyMetadata } from "../sourcify/useSourcify";
|
||||||
|
|
||||||
type LogEntryProps = {
|
type LogEntryProps = {
|
||||||
log: Log;
|
log: Log;
|
||||||
logDesc: LogDescription | null | undefined;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const LogEntry: React.FC<LogEntryProps> = ({ log, logDesc }) => {
|
const LogEntry: React.FC<LogEntryProps> = ({ log }) => {
|
||||||
|
const { provider } = useContext(RuntimeContext);
|
||||||
|
const { sourcifySource } = useAppConfigContext();
|
||||||
|
const metadata = useSourcifyMetadata(
|
||||||
|
log.address,
|
||||||
|
provider?.network.chainId,
|
||||||
|
sourcifySource
|
||||||
|
);
|
||||||
|
|
||||||
|
const logDesc = useMemo(() => {
|
||||||
|
if (!metadata) {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
const abi = metadata.output.abi;
|
||||||
|
const intf = new Interface(abi as any);
|
||||||
|
try {
|
||||||
|
return intf.parseLog({
|
||||||
|
topics: log.topics,
|
||||||
|
data: log.data,
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.warn("Couldn't find function signature", err);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}, [log, metadata]);
|
||||||
|
|
||||||
const rawTopic0 = log.topics[0];
|
const rawTopic0 = log.topics[0];
|
||||||
const topic0 = useTopic0(rawTopic0);
|
const topic0 = useTopic0(rawTopic0);
|
||||||
|
|
||||||
|
@ -1,77 +1,28 @@
|
|||||||
import React, { useContext, useMemo } from "react";
|
import React from "react";
|
||||||
import { Interface } from "@ethersproject/abi";
|
|
||||||
import ContentFrame from "../ContentFrame";
|
import ContentFrame from "../ContentFrame";
|
||||||
import LogEntry from "./LogEntry";
|
import LogEntry from "./LogEntry";
|
||||||
import { TransactionData } from "../types";
|
import { TransactionData } from "../types";
|
||||||
import { Metadata } from "../sourcify/useSourcify";
|
|
||||||
import { RuntimeContext } from "../useRuntime";
|
|
||||||
import { useContractsMetadata } from "../hooks";
|
|
||||||
|
|
||||||
type LogsProps = {
|
type LogsProps = {
|
||||||
txData: TransactionData;
|
txData: TransactionData;
|
||||||
metadata: Metadata | null | undefined;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const Logs: React.FC<LogsProps> = ({ txData, metadata }) => {
|
const Logs: React.FC<LogsProps> = ({ txData }) => (
|
||||||
const baseMetadatas = useMemo((): Record<string, Metadata | null> => {
|
<ContentFrame tabs>
|
||||||
if (!txData.to || metadata === undefined) {
|
{txData.confirmedData && (
|
||||||
return {};
|
<>
|
||||||
}
|
{txData.confirmedData.logs.length > 0 ? (
|
||||||
|
<>
|
||||||
const md: Record<string, Metadata | null> = {};
|
{txData.confirmedData.logs.map((l, i) => (
|
||||||
md[txData.to] = metadata;
|
<LogEntry key={i} log={l} />
|
||||||
return md;
|
))}
|
||||||
}, [txData.to, metadata]);
|
</>
|
||||||
|
) : (
|
||||||
const logAddresses = useMemo(
|
<div className="text-sm py-4">Transaction didn't emit any logs</div>
|
||||||
() => txData.confirmedData?.logs.map((l) => l.address) ?? [],
|
)}
|
||||||
[txData]
|
</>
|
||||||
);
|
)}
|
||||||
const { provider } = useContext(RuntimeContext);
|
</ContentFrame>
|
||||||
const metadatas = useContractsMetadata(logAddresses, provider, baseMetadatas);
|
);
|
||||||
|
|
||||||
const logDescs = useMemo(() => {
|
|
||||||
if (!txData) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
return txData.confirmedData?.logs.map((l) => {
|
|
||||||
const mt = metadatas[l.address];
|
|
||||||
if (!mt) {
|
|
||||||
return mt;
|
|
||||||
}
|
|
||||||
|
|
||||||
const abi = mt.output.abi;
|
|
||||||
const intf = new Interface(abi as any);
|
|
||||||
try {
|
|
||||||
return intf.parseLog({
|
|
||||||
topics: l.topics,
|
|
||||||
data: l.data,
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
console.warn("Couldn't find function signature", err);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, [metadatas, txData]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ContentFrame tabs>
|
|
||||||
{txData.confirmedData && (
|
|
||||||
<>
|
|
||||||
{txData.confirmedData.logs.length > 0 ? (
|
|
||||||
<>
|
|
||||||
{txData.confirmedData.logs.map((l, i) => (
|
|
||||||
<LogEntry key={i} log={l} logDesc={logDescs?.[i]} />
|
|
||||||
))}
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<div className="text-sm py-4">Transaction didn't emit any logs</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</ContentFrame>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default React.memo(Logs);
|
export default React.memo(Logs);
|
||||||
|
Loading…
Reference in New Issue
Block a user