Add support for multiple log emitter addresses
This commit is contained in:
parent
18275f86a2
commit
7f15a12f4a
src
|
@ -3,7 +3,8 @@ 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 "../useSourcify";
|
import { Metadata, useMultipleMetadata } from "../useSourcify";
|
||||||
|
import { SourcifySource } from "../url";
|
||||||
|
|
||||||
type LogsProps = {
|
type LogsProps = {
|
||||||
txData: TransactionData;
|
txData: TransactionData;
|
||||||
|
@ -11,22 +12,45 @@ type LogsProps = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const Logs: React.FC<LogsProps> = ({ txData, metadata }) => {
|
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 metadatas = useMultipleMetadata(
|
||||||
|
baseMetadatas,
|
||||||
|
logAddresses,
|
||||||
|
1,
|
||||||
|
SourcifySource.CUSTOM_SNAPSHOT_SERVER
|
||||||
|
);
|
||||||
const logDesc = useMemo(() => {
|
const logDesc = useMemo(() => {
|
||||||
if (!metadata || !txData) {
|
if (!metadata || !txData) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const abi = metadata.output.abi;
|
return txData.confirmedData?.logs.map((l) => {
|
||||||
const intf = new Interface(abi as any);
|
const mt = metadatas[l.address];
|
||||||
return txData.confirmedData?.logs.map((l) =>
|
if (!mt) {
|
||||||
l.address === txData.to
|
return undefined;
|
||||||
? intf.parseLog({
|
}
|
||||||
topics: l.topics,
|
|
||||||
data: l.data,
|
const abi = mt.output.abi;
|
||||||
})
|
const intf = new Interface(abi as any);
|
||||||
: undefined
|
return intf.parseLog({
|
||||||
);
|
topics: l.topics,
|
||||||
}, [metadata, txData]);
|
data: l.data,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, [metadatas, metadata, txData]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ContentFrame tabs>
|
<ContentFrame tabs>
|
||||||
|
|
|
@ -38,11 +38,38 @@ export type Metadata = {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const fetchSourcifyMetadata = async (
|
||||||
|
checksummedAddress: string,
|
||||||
|
chainId: number,
|
||||||
|
source: SourcifySource,
|
||||||
|
abortController: AbortController
|
||||||
|
): Promise<Metadata | null> => {
|
||||||
|
try {
|
||||||
|
const contractMetadataURL = sourcifyMetadata(
|
||||||
|
checksummedAddress,
|
||||||
|
chainId,
|
||||||
|
source
|
||||||
|
);
|
||||||
|
const result = await fetch(contractMetadataURL, {
|
||||||
|
signal: abortController.signal,
|
||||||
|
});
|
||||||
|
if (result.ok) {
|
||||||
|
const _metadata = await result.json();
|
||||||
|
return _metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const useSourcify = (
|
export const useSourcify = (
|
||||||
checksummedAddress: string | undefined,
|
checksummedAddress: string | undefined,
|
||||||
chainId: number | undefined,
|
chainId: number | undefined,
|
||||||
source: SourcifySource
|
source: SourcifySource
|
||||||
) => {
|
): Metadata | null | undefined => {
|
||||||
const [rawMetadata, setRawMetadata] = useState<Metadata | null | undefined>();
|
const [rawMetadata, setRawMetadata] = useState<Metadata | null | undefined>();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -53,25 +80,13 @@ export const useSourcify = (
|
||||||
|
|
||||||
const abortController = new AbortController();
|
const abortController = new AbortController();
|
||||||
const fetchMetadata = async () => {
|
const fetchMetadata = async () => {
|
||||||
try {
|
const _metadata = await fetchSourcifyMetadata(
|
||||||
const contractMetadataURL = sourcifyMetadata(
|
checksummedAddress,
|
||||||
checksummedAddress,
|
chainId,
|
||||||
chainId,
|
source,
|
||||||
source
|
abortController
|
||||||
);
|
);
|
||||||
const result = await fetch(contractMetadataURL, {
|
setRawMetadata(_metadata);
|
||||||
signal: abortController.signal,
|
|
||||||
});
|
|
||||||
if (result.ok) {
|
|
||||||
const _metadata = await result.json();
|
|
||||||
setRawMetadata(_metadata);
|
|
||||||
} else {
|
|
||||||
setRawMetadata(null);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
setRawMetadata(null);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
fetchMetadata();
|
fetchMetadata();
|
||||||
|
|
||||||
|
@ -83,6 +98,54 @@ export const useSourcify = (
|
||||||
return rawMetadata;
|
return rawMetadata;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useMultipleMetadata = (
|
||||||
|
baseMetadatas: Record<string, Metadata | null>,
|
||||||
|
checksummedAddress: (string | undefined)[],
|
||||||
|
chainId: number | undefined,
|
||||||
|
source: SourcifySource
|
||||||
|
): Record<string, Metadata | null | undefined> => {
|
||||||
|
const [rawMetadata, setRawMetadata] = useState<
|
||||||
|
Record<string, Metadata | null | undefined>
|
||||||
|
>({});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!checksummedAddress || chainId === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setRawMetadata({});
|
||||||
|
|
||||||
|
const abortController = new AbortController();
|
||||||
|
const fetchMetadata = async (addresses: string[]) => {
|
||||||
|
const promises: Promise<Metadata | null>[] = [];
|
||||||
|
for (const addr of addresses) {
|
||||||
|
promises.push(
|
||||||
|
fetchSourcifyMetadata(addr, chainId, source, abortController)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const results = await Promise.all(promises);
|
||||||
|
const metadatas: Record<string, Metadata | null> = { ...baseMetadatas };
|
||||||
|
for (let i = 0; i < results.length; i++) {
|
||||||
|
metadatas[addresses[i]] = results[i];
|
||||||
|
}
|
||||||
|
setRawMetadata(metadatas);
|
||||||
|
};
|
||||||
|
|
||||||
|
const deduped = new Set(
|
||||||
|
checksummedAddress.filter(
|
||||||
|
(a): a is string => a !== undefined && baseMetadatas[a] === undefined
|
||||||
|
)
|
||||||
|
);
|
||||||
|
fetchMetadata(Array.from(deduped));
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
abortController.abort();
|
||||||
|
};
|
||||||
|
}, [baseMetadatas, checksummedAddress, chainId, source]);
|
||||||
|
|
||||||
|
return rawMetadata;
|
||||||
|
};
|
||||||
|
|
||||||
export const useContract = (
|
export const useContract = (
|
||||||
checksummedAddress: string,
|
checksummedAddress: string,
|
||||||
networkId: number,
|
networkId: number,
|
||||||
|
|
Loading…
Reference in New Issue