-
Notifications
You must be signed in to change notification settings - Fork 221
Expand file tree
/
Copy pathgetSystemAbis.ts
More file actions
89 lines (83 loc) · 2.82 KB
/
Copy pathgetSystemAbis.ts
File metadata and controls
89 lines (83 loc) · 2.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import { Client, Abi, Address, Hex, hexToString, parseAbi, stringToHex, toFunctionSelector } from "viem";
import metadataConfig from "@latticexyz/world-module-metadata/mud.config";
import { getRecords } from "../getRecords";
import { getFunctions } from "./getFunctions";
import { groupBy, isNotNull } from "@latticexyz/common/utils";
import { functionSignatureToAbiItem } from "./functionSignatureToAbiItem";
import { hexToResource } from "@latticexyz/common";
import { isAbiFunction } from "./common";
export async function getSystemAbis({
client,
worldAddress,
systemIds,
fromBlock,
toBlock,
indexerUrl,
chainId,
}: {
readonly client: Client;
readonly worldAddress: Address;
readonly systemIds?: Hex[];
readonly fromBlock?: bigint;
readonly toBlock?: bigint;
readonly indexerUrl?: string;
readonly chainId?: number;
}): Promise<{ readonly [systemId: Hex]: Abi }> {
const [worldFunctions, { records: metadataRecords }] = await Promise.all([
getFunctions({
client,
worldAddress,
fromBlock,
toBlock,
indexerUrl,
chainId,
}),
getRecords({
table: metadataConfig.tables.metadata__ResourceTag,
worldAddress,
chainId,
indexerUrl,
client,
fromBlock,
toBlock,
}),
]);
const systemAbis = Object.fromEntries(
metadataRecords
.filter(({ resource, tag }) => {
const isAbiTag = tag === stringToHex("abi", { size: 32 });
const matchesSystemId = systemIds ? systemIds.includes(resource) : hexToResource(resource).type === "system";
return isAbiTag && matchesSystemId;
})
.map(({ resource, value }) => {
try {
const abi = value === "0x" ? [] : parseAbi(hexToString(value).split("\n"));
return [resource, abi] as const;
} catch (error) {
console.error("error parsing system abi", error);
return [resource, []] as const;
}
})
.filter(isNotNull),
);
const systemFunctions = Object.fromEntries(
Array.from(
groupBy(
worldFunctions.filter(({ systemId }) => (systemIds ? systemIds.includes(systemId) : true)),
({ systemId }) => systemId,
).entries(),
).map(([systemId, functions]) => {
return [systemId, functions.map((func) => functionSignatureToAbiItem(func.systemFunctionSignature))];
}),
);
const ids = Array.from(new Set(systemIds ?? [...Object.keys(systemAbis), ...Object.keys(systemFunctions)]));
const abis = Object.fromEntries(
ids.map((systemId) => {
const abi = systemAbis[systemId] ?? [];
const abiSelectors = new Set(abi.filter(isAbiFunction).map(toFunctionSelector));
const functions = systemFunctions[systemId] ?? [];
return [systemId, [...abi, ...functions.filter((item) => !abiSelectors.has(toFunctionSelector(item)))]];
}),
);
return abis;
}