@latticexyz/cli 2.0.0-transaction-context-324984c5 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-22IIKR4S.js → chunk-QXUPZVZL.js} +2 -2
- package/dist/chunk-QXUPZVZL.js.map +1 -0
- package/dist/commands-WWEJJZV4.js +36 -0
- package/dist/commands-WWEJJZV4.js.map +1 -0
- package/dist/errors-MZURIB7V.js +2 -0
- package/dist/mud.js +1 -1
- package/dist/mud.js.map +1 -1
- package/package.json +16 -15
- package/src/build.ts +9 -5
- package/src/commands/build.ts +2 -3
- package/src/commands/deploy.ts +1 -1
- package/src/commands/dev-contracts.ts +6 -5
- package/src/commands/set-version.ts +1 -1
- package/src/commands/tablegen.ts +2 -2
- package/src/commands/trace.ts +7 -5
- package/src/commands/worldgen.ts +7 -6
- package/src/deploy/common.ts +54 -8
- package/src/deploy/configToTables.ts +8 -6
- package/src/deploy/create2/README.md +4 -0
- package/src/deploy/create2/deployment.json +2 -1
- package/src/deploy/createPrepareDeploy.ts +28 -0
- package/src/deploy/deploy.ts +33 -16
- package/src/deploy/deployWorld.ts +4 -3
- package/src/deploy/ensureContract.ts +12 -7
- package/src/deploy/ensureContractsDeployed.ts +9 -1
- package/src/deploy/ensureDeployer.ts +61 -22
- package/src/deploy/ensureFunctions.ts +5 -5
- package/src/deploy/ensureModules.ts +16 -10
- package/src/deploy/ensureNamespaceOwner.ts +4 -4
- package/src/deploy/ensureSystems.ts +108 -83
- package/src/deploy/ensureTables.ts +8 -9
- package/src/deploy/ensureWorldFactory.ts +79 -92
- package/src/deploy/findLibraries.ts +36 -0
- package/src/deploy/getFunctions.ts +5 -5
- package/src/deploy/getResourceAccess.ts +3 -3
- package/src/deploy/getSystems.ts +6 -7
- package/src/deploy/getTableValue.ts +1 -1
- package/src/deploy/getTables.ts +2 -2
- package/src/deploy/logsToWorldDeploy.ts +4 -4
- package/src/deploy/orderByDependencies.ts +12 -0
- package/src/deploy/resolveConfig.ts +55 -58
- package/src/mud.ts +1 -1
- package/src/mudPackages.ts +1 -1
- package/src/runDeploy.ts +28 -10
- package/src/utils/{modules/constants.ts → defaultModuleContracts.ts} +4 -0
- package/src/utils/errors.ts +1 -1
- package/src/utils/findPlaceholders.ts +27 -0
- package/src/utils/{utils/getContractData.ts → getContractData.ts} +11 -5
- package/src/utils/{utils/postDeploy.ts → postDeploy.ts} +2 -2
- package/src/utils/printMUD.ts +1 -1
- package/dist/chunk-22IIKR4S.js.map +0 -1
- package/dist/commands-3JV3U43E.js +0 -27
- package/dist/commands-3JV3U43E.js.map +0 -1
- package/dist/errors-XGN6V2Y3.js +0 -2
- package/src/deploy/resourceLabel.ts +0 -3
- /package/dist/{errors-XGN6V2Y3.js.map → errors-MZURIB7V.js.map} +0 -0
@@ -1,36 +1,75 @@
|
|
1
|
-
import { Account, Chain, Client, Transport } from "viem";
|
2
|
-
import { getBytecode, sendRawTransaction, sendTransaction, waitForTransactionReceipt } from "viem/actions";
|
1
|
+
import { Account, Address, Chain, Client, Transport } from "viem";
|
2
|
+
import { getBalance, getBytecode, sendRawTransaction, sendTransaction, waitForTransactionReceipt } from "viem/actions";
|
3
3
|
import deployment from "./create2/deployment.json";
|
4
4
|
import { debug } from "./debug";
|
5
5
|
|
6
|
-
|
6
|
+
const deployer = `0x${deployment.address}` as const;
|
7
|
+
const deployerBytecode = `0x${deployment.bytecode}` as const;
|
7
8
|
|
8
|
-
export async function ensureDeployer(client: Client<Transport, Chain | undefined, Account>): Promise<
|
9
|
+
export async function ensureDeployer(client: Client<Transport, Chain | undefined, Account>): Promise<Address> {
|
9
10
|
const bytecode = await getBytecode(client, { address: deployer });
|
10
11
|
if (bytecode) {
|
11
|
-
debug("found
|
12
|
-
|
12
|
+
debug("found CREATE2 deployer at", deployer);
|
13
|
+
if (bytecode !== deployerBytecode) {
|
14
|
+
console.warn(
|
15
|
+
`\n ⚠️ Bytecode for deployer at ${deployer} did not match the expected CREATE2 bytecode. You may have unexpected results.\n`,
|
16
|
+
);
|
17
|
+
}
|
18
|
+
return deployer;
|
13
19
|
}
|
14
20
|
|
15
|
-
//
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
});
|
22
|
-
const
|
23
|
-
if (
|
24
|
-
|
25
|
-
|
21
|
+
// There's not really a way to simulate a pre-EIP-155 (no chain ID) transaction,
|
22
|
+
// so we have to attempt to create the deployer first and, if it fails, fall back
|
23
|
+
// to a regular deploy.
|
24
|
+
|
25
|
+
// Send gas to deployment signer
|
26
|
+
const gasRequired = BigInt(deployment.gasLimit) * BigInt(deployment.gasPrice);
|
27
|
+
const currentBalance = await getBalance(client, { address: `0x${deployment.signerAddress}` });
|
28
|
+
const gasNeeded = gasRequired - currentBalance;
|
29
|
+
if (gasNeeded > 0) {
|
30
|
+
debug("sending gas for CREATE2 deployer to signer at", deployment.signerAddress);
|
31
|
+
const gasTx = await sendTransaction(client, {
|
32
|
+
chain: client.chain ?? null,
|
33
|
+
to: `0x${deployment.signerAddress}`,
|
34
|
+
value: gasNeeded,
|
35
|
+
});
|
36
|
+
const gasReceipt = await waitForTransactionReceipt(client, { hash: gasTx });
|
37
|
+
if (gasReceipt.status !== "success") {
|
38
|
+
console.error("failed to send gas to deployer signer", gasReceipt);
|
39
|
+
throw new Error("failed to send gas to deployer signer");
|
40
|
+
}
|
26
41
|
}
|
27
42
|
|
28
|
-
//
|
29
|
-
debug("deploying
|
30
|
-
const deployTx = await sendRawTransaction(client, { serializedTransaction: `0x${deployment.transaction}` })
|
43
|
+
// Deploy the deployer
|
44
|
+
debug("deploying CREATE2 deployer at", deployer);
|
45
|
+
const deployTx = await sendRawTransaction(client, { serializedTransaction: `0x${deployment.transaction}` }).catch(
|
46
|
+
(error) => {
|
47
|
+
// Do a regular contract create if the presigned transaction doesn't work due to replay protection
|
48
|
+
if (String(error).includes("only replay-protected (EIP-155) transactions allowed over RPC")) {
|
49
|
+
console.warn(
|
50
|
+
// eslint-disable-next-line max-len
|
51
|
+
`\n ⚠️ Your chain or RPC does not allow for non EIP-155 signed transactions, so your deploys will not be determinstic and contract addresses may change between deploys.\n\n We recommend running your chain's node with \`--rpc.allow-unprotected-txs\` to enable determinstic deployments.\n`,
|
52
|
+
);
|
53
|
+
debug("deploying CREATE2 deployer");
|
54
|
+
return sendTransaction(client, {
|
55
|
+
chain: client.chain ?? null,
|
56
|
+
data: deployerBytecode,
|
57
|
+
});
|
58
|
+
}
|
59
|
+
throw error;
|
60
|
+
},
|
61
|
+
);
|
62
|
+
|
31
63
|
const deployReceipt = await waitForTransactionReceipt(client, { hash: deployTx });
|
64
|
+
if (!deployReceipt.contractAddress) {
|
65
|
+
throw new Error("Deploy receipt did not have contract address, was the deployer not deployed?");
|
66
|
+
}
|
67
|
+
|
32
68
|
if (deployReceipt.contractAddress !== deployer) {
|
33
|
-
console.
|
34
|
-
|
69
|
+
console.warn(
|
70
|
+
`\n ⚠️ CREATE2 deployer created at ${deployReceipt.contractAddress} does not match the CREATE2 determinstic deployer we expected (${deployer})`,
|
71
|
+
);
|
35
72
|
}
|
73
|
+
|
74
|
+
return deployReceipt.contractAddress;
|
36
75
|
}
|
@@ -29,7 +29,7 @@ export async function ensureFunctions({
|
|
29
29
|
"found",
|
30
30
|
wrongSystem.length,
|
31
31
|
"functions already registered but pointing at a different system ID:",
|
32
|
-
wrongSystem.map((func) => func.signature).join(", ")
|
32
|
+
wrongSystem.map((func) => func.signature).join(", "),
|
33
33
|
);
|
34
34
|
}
|
35
35
|
}
|
@@ -50,7 +50,7 @@ export async function ensureFunctions({
|
|
50
50
|
abi: worldAbi,
|
51
51
|
// TODO: replace with batchCall (https://github.com/latticexyz/mud/issues/1645)
|
52
52
|
functionName: "registerRootFunctionSelector",
|
53
|
-
args: [func.systemId, func.systemFunctionSignature, func.
|
53
|
+
args: [func.systemId, func.systemFunctionSignature, func.systemFunctionSignature],
|
54
54
|
}),
|
55
55
|
{
|
56
56
|
retries: 3,
|
@@ -59,7 +59,7 @@ export async function ensureFunctions({
|
|
59
59
|
debug(`failed to register function ${func.signature}, retrying in ${delay}ms...`);
|
60
60
|
await wait(delay);
|
61
61
|
},
|
62
|
-
}
|
62
|
+
},
|
63
63
|
);
|
64
64
|
}
|
65
65
|
return pRetry(
|
@@ -79,8 +79,8 @@ export async function ensureFunctions({
|
|
79
79
|
debug(`failed to register function ${func.signature}, retrying in ${delay}ms...`);
|
80
80
|
await wait(delay);
|
81
81
|
},
|
82
|
-
}
|
82
|
+
},
|
83
83
|
);
|
84
|
-
})
|
84
|
+
}),
|
85
85
|
);
|
86
86
|
}
|
@@ -1,17 +1,21 @@
|
|
1
|
-
import { Client, Transport, Chain, Account, Hex, BaseError
|
1
|
+
import { Client, Transport, Chain, Account, Hex, BaseError } from "viem";
|
2
2
|
import { writeContract } from "@latticexyz/common";
|
3
|
-
import { Module, WorldDeploy, worldAbi } from "./common";
|
3
|
+
import { Library, Module, WorldDeploy, worldAbi } from "./common";
|
4
4
|
import { debug } from "./debug";
|
5
|
-
import { isDefined,
|
5
|
+
import { isDefined, wait } from "@latticexyz/common/utils";
|
6
6
|
import pRetry from "p-retry";
|
7
7
|
import { ensureContractsDeployed } from "./ensureContractsDeployed";
|
8
8
|
|
9
9
|
export async function ensureModules({
|
10
10
|
client,
|
11
|
+
deployerAddress,
|
12
|
+
libraries,
|
11
13
|
worldDeploy,
|
12
14
|
modules,
|
13
15
|
}: {
|
14
16
|
readonly client: Client<Transport, Chain | undefined, Account>;
|
17
|
+
readonly deployerAddress: Hex;
|
18
|
+
readonly libraries: readonly Library[];
|
15
19
|
readonly worldDeploy: WorldDeploy;
|
16
20
|
readonly modules: readonly Module[];
|
17
21
|
}): Promise<readonly Hex[]> {
|
@@ -19,8 +23,9 @@ export async function ensureModules({
|
|
19
23
|
|
20
24
|
await ensureContractsDeployed({
|
21
25
|
client,
|
22
|
-
|
23
|
-
|
26
|
+
deployerAddress,
|
27
|
+
contracts: modules.map((mod) => ({
|
28
|
+
bytecode: mod.prepareDeploy(deployerAddress, libraries).bytecode,
|
24
29
|
deployedBytecodeSize: mod.deployedBytecodeSize,
|
25
30
|
label: `${mod.name} module`,
|
26
31
|
})),
|
@@ -33,6 +38,7 @@ export async function ensureModules({
|
|
33
38
|
pRetry(
|
34
39
|
async () => {
|
35
40
|
try {
|
41
|
+
const moduleAddress = mod.prepareDeploy(deployerAddress, libraries).address;
|
36
42
|
return mod.installAsRoot
|
37
43
|
? await writeContract(client, {
|
38
44
|
chain: client.chain ?? null,
|
@@ -40,7 +46,7 @@ export async function ensureModules({
|
|
40
46
|
abi: worldAbi,
|
41
47
|
// TODO: replace with batchCall (https://github.com/latticexyz/mud/issues/1645)
|
42
48
|
functionName: "installRootModule",
|
43
|
-
args: [
|
49
|
+
args: [moduleAddress, mod.installData],
|
44
50
|
})
|
45
51
|
: await writeContract(client, {
|
46
52
|
chain: client.chain ?? null,
|
@@ -48,7 +54,7 @@ export async function ensureModules({
|
|
48
54
|
abi: worldAbi,
|
49
55
|
// TODO: replace with batchCall (https://github.com/latticexyz/mud/issues/1645)
|
50
56
|
functionName: "installModule",
|
51
|
-
args: [
|
57
|
+
args: [moduleAddress, mod.installData],
|
52
58
|
});
|
53
59
|
} catch (error) {
|
54
60
|
if (error instanceof BaseError && error.message.includes("Module_AlreadyInstalled")) {
|
@@ -65,9 +71,9 @@ export async function ensureModules({
|
|
65
71
|
debug(`failed to install module ${mod.name}, retrying in ${delay}ms...`);
|
66
72
|
await wait(delay);
|
67
73
|
},
|
68
|
-
}
|
69
|
-
)
|
70
|
-
)
|
74
|
+
},
|
75
|
+
),
|
76
|
+
),
|
71
77
|
)
|
72
78
|
).filter(isDefined);
|
73
79
|
}
|
@@ -24,7 +24,7 @@ export async function ensureNamespaceOwner({
|
|
24
24
|
"existing namespaces:",
|
25
25
|
Array.from(existingNamespaces)
|
26
26
|
.map((namespace) => (namespace === "" ? "<root>" : namespace))
|
27
|
-
.join(", ")
|
27
|
+
.join(", "),
|
28
28
|
);
|
29
29
|
}
|
30
30
|
|
@@ -39,7 +39,7 @@ export async function ensureNamespaceOwner({
|
|
39
39
|
key: { namespaceId: resourceToHex({ type: "namespace", namespace, name: "" }) },
|
40
40
|
});
|
41
41
|
return [namespace, owner];
|
42
|
-
})
|
42
|
+
}),
|
43
43
|
);
|
44
44
|
|
45
45
|
const unauthorizedNamespaces = namespaceOwners
|
@@ -63,8 +63,8 @@ export async function ensureNamespaceOwner({
|
|
63
63
|
abi: worldAbi,
|
64
64
|
functionName: "registerNamespace",
|
65
65
|
args: [resourceToHex({ namespace, type: "namespace", name: "" })],
|
66
|
-
})
|
67
|
-
)
|
66
|
+
}),
|
67
|
+
),
|
68
68
|
);
|
69
69
|
|
70
70
|
return registrationTxs;
|
@@ -1,20 +1,25 @@
|
|
1
|
-
import { Client, Transport, Chain, Account, Hex, getAddress } from "viem";
|
2
|
-
import { writeContract } from "@latticexyz/common";
|
3
|
-
import { System, WorldDeploy, worldAbi } from "./common";
|
1
|
+
import { Client, Transport, Chain, Account, Hex, getAddress, Address } from "viem";
|
2
|
+
import { writeContract, resourceToLabel } from "@latticexyz/common";
|
3
|
+
import { Library, System, WorldDeploy, worldAbi } from "./common";
|
4
4
|
import { debug } from "./debug";
|
5
|
-
import { resourceLabel } from "./resourceLabel";
|
6
5
|
import { getSystems } from "./getSystems";
|
7
6
|
import { getResourceAccess } from "./getResourceAccess";
|
8
|
-
import {
|
7
|
+
import { wait } from "@latticexyz/common/utils";
|
9
8
|
import pRetry from "p-retry";
|
10
9
|
import { ensureContractsDeployed } from "./ensureContractsDeployed";
|
11
10
|
|
11
|
+
// TODO: move each system registration+access to batch call to be atomic
|
12
|
+
|
12
13
|
export async function ensureSystems({
|
13
14
|
client,
|
15
|
+
deployerAddress,
|
16
|
+
libraries,
|
14
17
|
worldDeploy,
|
15
18
|
systems,
|
16
19
|
}: {
|
17
20
|
readonly client: Client<Transport, Chain | undefined, Account>;
|
21
|
+
readonly deployerAddress: Hex;
|
22
|
+
readonly libraries: readonly Library[];
|
18
23
|
readonly worldDeploy: WorldDeploy;
|
19
24
|
readonly systems: readonly System[];
|
20
25
|
}): Promise<readonly Hex[]> {
|
@@ -22,30 +27,112 @@ export async function ensureSystems({
|
|
22
27
|
getSystems({ client, worldDeploy }),
|
23
28
|
getResourceAccess({ client, worldDeploy }),
|
24
29
|
]);
|
30
|
+
|
31
|
+
// Register or replace systems
|
32
|
+
|
33
|
+
const existingSystems = systems.filter((system) =>
|
34
|
+
worldSystems.some(
|
35
|
+
(worldSystem) =>
|
36
|
+
worldSystem.systemId === system.systemId &&
|
37
|
+
getAddress(worldSystem.address) === getAddress(system.prepareDeploy(deployerAddress, libraries).address),
|
38
|
+
),
|
39
|
+
);
|
40
|
+
if (existingSystems.length) {
|
41
|
+
debug("existing systems", existingSystems.map(resourceToLabel).join(", "));
|
42
|
+
}
|
43
|
+
const existingSystemIds = existingSystems.map((system) => system.systemId);
|
44
|
+
|
45
|
+
const missingSystems = systems.filter((system) => !existingSystemIds.includes(system.systemId));
|
46
|
+
if (!missingSystems.length) return [];
|
47
|
+
|
48
|
+
const systemsToUpgrade = missingSystems.filter((system) =>
|
49
|
+
worldSystems.some(
|
50
|
+
(worldSystem) =>
|
51
|
+
worldSystem.systemId === system.systemId &&
|
52
|
+
getAddress(worldSystem.address) !== getAddress(system.prepareDeploy(deployerAddress, libraries).address),
|
53
|
+
),
|
54
|
+
);
|
55
|
+
if (systemsToUpgrade.length) {
|
56
|
+
debug("upgrading systems", systemsToUpgrade.map(resourceToLabel).join(", "));
|
57
|
+
}
|
58
|
+
|
59
|
+
const systemsToAdd = missingSystems.filter(
|
60
|
+
(system) => !worldSystems.some((worldSystem) => worldSystem.systemId === system.systemId),
|
61
|
+
);
|
62
|
+
if (systemsToAdd.length) {
|
63
|
+
debug("registering new systems", systemsToAdd.map(resourceToLabel).join(", "));
|
64
|
+
}
|
65
|
+
|
66
|
+
await ensureContractsDeployed({
|
67
|
+
client,
|
68
|
+
deployerAddress,
|
69
|
+
contracts: missingSystems.map((system) => ({
|
70
|
+
bytecode: system.prepareDeploy(deployerAddress, libraries).bytecode,
|
71
|
+
deployedBytecodeSize: system.deployedBytecodeSize,
|
72
|
+
label: `${resourceToLabel(system)} system`,
|
73
|
+
})),
|
74
|
+
});
|
75
|
+
|
76
|
+
const registerTxs = await Promise.all(
|
77
|
+
missingSystems.map((system) =>
|
78
|
+
pRetry(
|
79
|
+
() =>
|
80
|
+
writeContract(client, {
|
81
|
+
chain: client.chain ?? null,
|
82
|
+
address: worldDeploy.address,
|
83
|
+
abi: worldAbi,
|
84
|
+
// TODO: replace with batchCall (https://github.com/latticexyz/mud/issues/1645)
|
85
|
+
functionName: "registerSystem",
|
86
|
+
args: [system.systemId, system.prepareDeploy(deployerAddress, libraries).address, system.allowAll],
|
87
|
+
}),
|
88
|
+
{
|
89
|
+
retries: 3,
|
90
|
+
onFailedAttempt: async (error) => {
|
91
|
+
const delay = error.attemptNumber * 500;
|
92
|
+
debug(`failed to register system ${resourceToLabel(system)}, retrying in ${delay}ms...`);
|
93
|
+
await wait(delay);
|
94
|
+
},
|
95
|
+
},
|
96
|
+
),
|
97
|
+
),
|
98
|
+
);
|
99
|
+
|
100
|
+
// Adjust system access
|
101
|
+
|
25
102
|
const systemIds = systems.map((system) => system.systemId);
|
26
103
|
const currentAccess = worldAccess.filter(({ resourceId }) => systemIds.includes(resourceId));
|
27
|
-
const desiredAccess =
|
28
|
-
|
29
|
-
|
104
|
+
const desiredAccess = [
|
105
|
+
...systems.flatMap((system) =>
|
106
|
+
system.allowedAddresses.map((address) => ({ resourceId: system.systemId, address })),
|
107
|
+
),
|
108
|
+
...systems.flatMap((system) =>
|
109
|
+
system.allowedSystemIds
|
110
|
+
.map((systemId) => ({
|
111
|
+
resourceId: system.systemId,
|
112
|
+
address:
|
113
|
+
worldSystems.find((s) => s.systemId === systemId)?.address ??
|
114
|
+
systems.find((s) => s.systemId === systemId)?.prepareDeploy(deployerAddress, libraries).address,
|
115
|
+
}))
|
116
|
+
.filter((access): access is typeof access & { address: Address } => access.address != null),
|
117
|
+
),
|
118
|
+
];
|
30
119
|
|
31
120
|
const accessToAdd = desiredAccess.filter(
|
32
121
|
(access) =>
|
33
122
|
!currentAccess.some(
|
34
123
|
({ resourceId, address }) =>
|
35
|
-
resourceId === access.resourceId && getAddress(address) === getAddress(access.address)
|
36
|
-
)
|
124
|
+
resourceId === access.resourceId && getAddress(address) === getAddress(access.address),
|
125
|
+
),
|
37
126
|
);
|
38
127
|
|
39
128
|
const accessToRemove = currentAccess.filter(
|
40
129
|
(access) =>
|
41
130
|
!desiredAccess.some(
|
42
131
|
({ resourceId, address }) =>
|
43
|
-
resourceId === access.resourceId && getAddress(address) === getAddress(access.address)
|
44
|
-
)
|
132
|
+
resourceId === access.resourceId && getAddress(address) === getAddress(access.address),
|
133
|
+
),
|
45
134
|
);
|
46
135
|
|
47
|
-
// TODO: move each system access+registration to batch call to be atomic
|
48
|
-
|
49
136
|
if (accessToRemove.length) {
|
50
137
|
debug("revoking", accessToRemove.length, "access grants");
|
51
138
|
}
|
@@ -53,7 +140,7 @@ export async function ensureSystems({
|
|
53
140
|
debug("adding", accessToAdd.length, "access grants");
|
54
141
|
}
|
55
142
|
|
56
|
-
const accessTxs = [
|
143
|
+
const accessTxs = await Promise.all([
|
57
144
|
...accessToRemove.map((access) =>
|
58
145
|
pRetry(
|
59
146
|
() =>
|
@@ -71,8 +158,8 @@ export async function ensureSystems({
|
|
71
158
|
debug(`failed to revoke access, retrying in ${delay}ms...`);
|
72
159
|
await wait(delay);
|
73
160
|
},
|
74
|
-
}
|
75
|
-
)
|
161
|
+
},
|
162
|
+
),
|
76
163
|
),
|
77
164
|
...accessToAdd.map((access) =>
|
78
165
|
pRetry(
|
@@ -91,72 +178,10 @@ export async function ensureSystems({
|
|
91
178
|
debug(`failed to grant access, retrying in ${delay}ms...`);
|
92
179
|
await wait(delay);
|
93
180
|
},
|
94
|
-
}
|
95
|
-
)
|
96
|
-
),
|
97
|
-
];
|
98
|
-
|
99
|
-
const existingSystems = systems.filter((system) =>
|
100
|
-
worldSystems.some(
|
101
|
-
(worldSystem) =>
|
102
|
-
worldSystem.systemId === system.systemId && getAddress(worldSystem.address) === getAddress(system.address)
|
103
|
-
)
|
104
|
-
);
|
105
|
-
if (existingSystems.length) {
|
106
|
-
debug("existing systems", existingSystems.map(resourceLabel).join(", "));
|
107
|
-
}
|
108
|
-
const existingSystemIds = existingSystems.map((system) => system.systemId);
|
109
|
-
|
110
|
-
const missingSystems = systems.filter((system) => !existingSystemIds.includes(system.systemId));
|
111
|
-
if (!missingSystems.length) return [];
|
112
|
-
|
113
|
-
const systemsToUpgrade = missingSystems.filter((system) =>
|
114
|
-
worldSystems.some(
|
115
|
-
(worldSystem) =>
|
116
|
-
worldSystem.systemId === system.systemId && getAddress(worldSystem.address) !== getAddress(system.address)
|
117
|
-
)
|
118
|
-
);
|
119
|
-
if (systemsToUpgrade.length) {
|
120
|
-
debug("upgrading systems", systemsToUpgrade.map(resourceLabel).join(", "));
|
121
|
-
}
|
122
|
-
|
123
|
-
const systemsToAdd = missingSystems.filter(
|
124
|
-
(system) => !worldSystems.some((worldSystem) => worldSystem.systemId === system.systemId)
|
125
|
-
);
|
126
|
-
if (systemsToAdd.length) {
|
127
|
-
debug("registering new systems", systemsToAdd.map(resourceLabel).join(", "));
|
128
|
-
}
|
129
|
-
|
130
|
-
await ensureContractsDeployed({
|
131
|
-
client,
|
132
|
-
contracts: uniqueBy(missingSystems, (system) => getAddress(system.address)).map((system) => ({
|
133
|
-
bytecode: system.bytecode,
|
134
|
-
deployedBytecodeSize: system.deployedBytecodeSize,
|
135
|
-
label: `${resourceLabel(system)} system`,
|
136
|
-
})),
|
137
|
-
});
|
138
|
-
|
139
|
-
const registerTxs = missingSystems.map((system) =>
|
140
|
-
pRetry(
|
141
|
-
() =>
|
142
|
-
writeContract(client, {
|
143
|
-
chain: client.chain ?? null,
|
144
|
-
address: worldDeploy.address,
|
145
|
-
abi: worldAbi,
|
146
|
-
// TODO: replace with batchCall (https://github.com/latticexyz/mud/issues/1645)
|
147
|
-
functionName: "registerSystem",
|
148
|
-
args: [system.systemId, system.address, system.allowAll],
|
149
|
-
}),
|
150
|
-
{
|
151
|
-
retries: 3,
|
152
|
-
onFailedAttempt: async (error) => {
|
153
|
-
const delay = error.attemptNumber * 500;
|
154
|
-
debug(`failed to register system ${resourceLabel(system)}, retrying in ${delay}ms...`);
|
155
|
-
await wait(delay);
|
156
181
|
},
|
157
|
-
|
158
|
-
)
|
159
|
-
);
|
182
|
+
),
|
183
|
+
),
|
184
|
+
]);
|
160
185
|
|
161
|
-
return
|
186
|
+
return [...registerTxs, ...accessTxs];
|
162
187
|
}
|
@@ -1,10 +1,9 @@
|
|
1
1
|
import { Client, Transport, Chain, Account, Hex } from "viem";
|
2
2
|
import { Table } from "./configToTables";
|
3
|
-
import { writeContract } from "@latticexyz/common";
|
3
|
+
import { resourceToLabel, writeContract } from "@latticexyz/common";
|
4
4
|
import { WorldDeploy, worldAbi } from "./common";
|
5
|
-
import { valueSchemaToFieldLayoutHex, keySchemaToHex, valueSchemaToHex } from "@latticexyz/protocol-parser";
|
5
|
+
import { valueSchemaToFieldLayoutHex, keySchemaToHex, valueSchemaToHex } from "@latticexyz/protocol-parser/internal";
|
6
6
|
import { debug } from "./debug";
|
7
|
-
import { resourceLabel } from "./resourceLabel";
|
8
7
|
import { getTables } from "./getTables";
|
9
8
|
import pRetry from "p-retry";
|
10
9
|
import { wait } from "@latticexyz/common/utils";
|
@@ -23,12 +22,12 @@ export async function ensureTables({
|
|
23
22
|
|
24
23
|
const existingTables = tables.filter((table) => worldTableIds.includes(table.tableId));
|
25
24
|
if (existingTables.length) {
|
26
|
-
debug("existing tables", existingTables.map(
|
25
|
+
debug("existing tables", existingTables.map(resourceToLabel).join(", "));
|
27
26
|
}
|
28
27
|
|
29
28
|
const missingTables = tables.filter((table) => !worldTableIds.includes(table.tableId));
|
30
29
|
if (missingTables.length) {
|
31
|
-
debug("registering tables", missingTables.map(
|
30
|
+
debug("registering tables", missingTables.map(resourceToLabel).join(", "));
|
32
31
|
return await Promise.all(
|
33
32
|
missingTables.map((table) =>
|
34
33
|
pRetry(
|
@@ -52,12 +51,12 @@ export async function ensureTables({
|
|
52
51
|
retries: 3,
|
53
52
|
onFailedAttempt: async (error) => {
|
54
53
|
const delay = error.attemptNumber * 500;
|
55
|
-
debug(`failed to register table ${
|
54
|
+
debug(`failed to register table ${resourceToLabel(table)}, retrying in ${delay}ms...`);
|
56
55
|
await wait(delay);
|
57
56
|
},
|
58
|
-
}
|
59
|
-
)
|
60
|
-
)
|
57
|
+
},
|
58
|
+
),
|
59
|
+
),
|
61
60
|
);
|
62
61
|
}
|
63
62
|
|