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 { useAppConfigContext } from "./useAppConfig";
|
||||
import { useAddressOrENS } from "./useResolvedAddresses";
|
||||
import { useMultipleMetadata } from "./sourcify/useSourcify";
|
||||
import { useSourcifyMetadata } from "./sourcify/useSourcify";
|
||||
import { ChecksummedAddress } from "./types";
|
||||
import { useAddressesWithCode } from "./useErigonHooks";
|
||||
import { useChainInfo } from "./useChainInfo";
|
||||
@ -65,7 +65,6 @@ const Address: React.FC = () => {
|
||||
}
|
||||
}, [addressOrName, checksummedAddress, isENS]);
|
||||
|
||||
const { sourcifySource } = useAppConfigContext();
|
||||
const checksummedAddressAsArray = useMemo(
|
||||
() => (checksummedAddress !== undefined ? [checksummedAddress] : []),
|
||||
[checksummedAddress]
|
||||
@ -74,16 +73,13 @@ const Address: React.FC = () => {
|
||||
provider,
|
||||
checksummedAddressAsArray
|
||||
);
|
||||
const metadatas = useMultipleMetadata(
|
||||
undefined,
|
||||
contractAddresses,
|
||||
// TODO: restore filter to only check Sourcify metadata if the address is a contract (hasCode)
|
||||
const { sourcifySource } = useAppConfigContext();
|
||||
const addressMetadata = useSourcifyMetadata(
|
||||
checksummedAddress,
|
||||
provider?.network.chainId,
|
||||
sourcifySource
|
||||
);
|
||||
const addressMetadata =
|
||||
checksummedAddress !== undefined
|
||||
? metadatas[checksummedAddress]
|
||||
: undefined;
|
||||
|
||||
const { network, faucets } = useChainInfo();
|
||||
|
||||
|
@ -98,10 +98,7 @@ const TransactionPageContent: React.FC<TransactionPageContentProps> = ({
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="logs"
|
||||
element={<Logs txData={txData} metadata={metadata} />}
|
||||
/>
|
||||
<Route path="logs" element={<Logs txData={txData} />} />
|
||||
<Route path="trace" element={<Trace txData={txData} />} />
|
||||
</Routes>
|
||||
</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;
|
||||
};
|
||||
|
||||
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 = (
|
||||
checksummedAddress: string,
|
||||
networkId: number,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { useMemo } from "react";
|
||||
import React, { useContext, useMemo } from "react";
|
||||
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 TransactionAddress from "../components/TransactionAddress";
|
||||
import Copy from "../components/Copy";
|
||||
@ -8,15 +8,41 @@ import ModeTab from "../components/ModeTab";
|
||||
import DecodedParamsTable from "./decoder/DecodedParamsTable";
|
||||
import DecodedLogSignature from "./decoder/DecodedLogSignature";
|
||||
import { useTopic0 } from "../useTopic0";
|
||||
import { ChecksummedAddress } from "../types";
|
||||
import { Metadata } from "../sourcify/useSourcify";
|
||||
import { RuntimeContext } from "../useRuntime";
|
||||
import { useAppConfigContext } from "../useAppConfig";
|
||||
import { useSourcifyMetadata } from "../sourcify/useSourcify";
|
||||
|
||||
type LogEntryProps = {
|
||||
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 topic0 = useTopic0(rawTopic0);
|
||||
|
||||
|
@ -1,77 +1,28 @@
|
||||
import React, { useContext, useMemo } from "react";
|
||||
import { Interface } from "@ethersproject/abi";
|
||||
import React from "react";
|
||||
import ContentFrame from "../ContentFrame";
|
||||
import LogEntry from "./LogEntry";
|
||||
import { TransactionData } from "../types";
|
||||
import { Metadata } from "../sourcify/useSourcify";
|
||||
import { RuntimeContext } from "../useRuntime";
|
||||
import { useContractsMetadata } from "../hooks";
|
||||
|
||||
type LogsProps = {
|
||||
txData: TransactionData;
|
||||
metadata: Metadata | null | undefined;
|
||||
};
|
||||
|
||||
const Logs: React.FC<LogsProps> = ({ txData, metadata }) => {
|
||||
const baseMetadatas = useMemo((): Record<string, Metadata | null> => {
|
||||
if (!txData.to || metadata === undefined) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const md: Record<string, Metadata | null> = {};
|
||||
md[txData.to] = metadata;
|
||||
return md;
|
||||
}, [txData.to, metadata]);
|
||||
|
||||
const logAddresses = useMemo(
|
||||
() => txData.confirmedData?.logs.map((l) => l.address) ?? [],
|
||||
[txData]
|
||||
);
|
||||
const { provider } = useContext(RuntimeContext);
|
||||
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>
|
||||
);
|
||||
};
|
||||
const Logs: React.FC<LogsProps> = ({ txData }) => (
|
||||
<ContentFrame tabs>
|
||||
{txData.confirmedData && (
|
||||
<>
|
||||
{txData.confirmedData.logs.length > 0 ? (
|
||||
<>
|
||||
{txData.confirmedData.logs.map((l, i) => (
|
||||
<LogEntry key={i} log={l} />
|
||||
))}
|
||||
</>
|
||||
) : (
|
||||
<div className="text-sm py-4">Transaction didn't emit any logs</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</ContentFrame>
|
||||
);
|
||||
|
||||
export default React.memo(Logs);
|
||||
|
Loading…
Reference in New Issue
Block a user