@latticexyz/cli 2.0.0-main-e1dc88eb → 2.0.0-main-ccc21e91
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/mud.js +11 -11
- package/dist/mud.js.map +1 -1
- package/package.json +12 -12
- package/src/commands/dev-contracts.ts +2 -0
- package/src/deploy/common.ts +8 -8
- package/src/deploy/deploy.ts +25 -1
- package/src/deploy/ensureModules.ts +2 -11
- package/src/deploy/ensureSystems.ts +23 -34
- package/src/runDeploy.ts +5 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@latticexyz/cli",
|
|
3
|
-
"version": "2.0.0-main-
|
|
3
|
+
"version": "2.0.0-main-ccc21e91",
|
|
4
4
|
"description": "Command line interface for mud",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -40,17 +40,17 @@
|
|
|
40
40
|
"yargs": "^17.7.1",
|
|
41
41
|
"zod": "^3.21.4",
|
|
42
42
|
"zod-validation-error": "^1.3.0",
|
|
43
|
-
"@latticexyz/abi-ts": "2.0.0-main-
|
|
44
|
-
"@latticexyz/common": "2.0.0-main-
|
|
45
|
-
"@latticexyz/config": "2.0.0-main-
|
|
46
|
-
"@latticexyz/gas-report": "2.0.0-main-
|
|
47
|
-
"@latticexyz/protocol-parser": "2.0.0-main-
|
|
48
|
-
"@latticexyz/schema-type": "2.0.0-main-
|
|
49
|
-
"@latticexyz/services": "2.0.0-main-
|
|
50
|
-
"@latticexyz/store": "2.0.0-main-
|
|
51
|
-
"@latticexyz/utils": "2.0.0-main-
|
|
52
|
-
"@latticexyz/world": "2.0.0-main-
|
|
53
|
-
"@latticexyz/world-modules": "2.0.0-main-
|
|
43
|
+
"@latticexyz/abi-ts": "2.0.0-main-ccc21e91",
|
|
44
|
+
"@latticexyz/common": "2.0.0-main-ccc21e91",
|
|
45
|
+
"@latticexyz/config": "2.0.0-main-ccc21e91",
|
|
46
|
+
"@latticexyz/gas-report": "2.0.0-main-ccc21e91",
|
|
47
|
+
"@latticexyz/protocol-parser": "2.0.0-main-ccc21e91",
|
|
48
|
+
"@latticexyz/schema-type": "2.0.0-main-ccc21e91",
|
|
49
|
+
"@latticexyz/services": "2.0.0-main-ccc21e91",
|
|
50
|
+
"@latticexyz/store": "2.0.0-main-ccc21e91",
|
|
51
|
+
"@latticexyz/utils": "2.0.0-main-ccc21e91",
|
|
52
|
+
"@latticexyz/world": "2.0.0-main-ccc21e91",
|
|
53
|
+
"@latticexyz/world-modules": "2.0.0-main-ccc21e91"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@types/debug": "^4.1.7",
|
|
@@ -15,6 +15,7 @@ import { Address } from "viem";
|
|
|
15
15
|
const devOptions = {
|
|
16
16
|
rpc: deployOptions.rpc,
|
|
17
17
|
configPath: deployOptions.configPath,
|
|
18
|
+
alwaysRunPostDeploy: deployOptions.alwaysRunPostDeploy,
|
|
18
19
|
};
|
|
19
20
|
|
|
20
21
|
const commandModule: CommandModule<typeof devOptions, InferredOptionTypes<typeof devOptions>> = {
|
|
@@ -74,6 +75,7 @@ const commandModule: CommandModule<typeof devOptions, InferredOptionTypes<typeof
|
|
|
74
75
|
}
|
|
75
76
|
// TODO: handle errors
|
|
76
77
|
const deploy = await runDeploy({
|
|
78
|
+
...opts,
|
|
77
79
|
configPath,
|
|
78
80
|
rpc,
|
|
79
81
|
skipBuild: false,
|
package/src/deploy/common.ts
CHANGED
|
@@ -38,25 +38,25 @@ export type WorldFunction = {
|
|
|
38
38
|
readonly systemFunctionSelector: Hex;
|
|
39
39
|
};
|
|
40
40
|
|
|
41
|
-
export type
|
|
41
|
+
export type DeterministicContract = {
|
|
42
|
+
readonly address: Address;
|
|
43
|
+
readonly bytecode: Hex;
|
|
44
|
+
readonly abi: Abi;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export type System = DeterministicContract & {
|
|
42
48
|
readonly namespace: string;
|
|
43
49
|
readonly name: string;
|
|
44
50
|
readonly systemId: Hex;
|
|
45
51
|
readonly allowAll: boolean;
|
|
46
52
|
readonly allowedAddresses: readonly Hex[];
|
|
47
|
-
readonly address: Address;
|
|
48
|
-
readonly bytecode: Hex;
|
|
49
|
-
readonly abi: Abi;
|
|
50
53
|
readonly functions: readonly WorldFunction[];
|
|
51
54
|
};
|
|
52
55
|
|
|
53
|
-
export type Module = {
|
|
56
|
+
export type Module = DeterministicContract & {
|
|
54
57
|
readonly name: string;
|
|
55
58
|
readonly installAsRoot: boolean;
|
|
56
59
|
readonly installData: Hex; // TODO: figure out better naming for this
|
|
57
|
-
readonly address: Address;
|
|
58
|
-
readonly bytecode: Hex;
|
|
59
|
-
readonly abi: Abi;
|
|
60
60
|
};
|
|
61
61
|
|
|
62
62
|
export type ConfigInput = StoreConfig & WorldConfig;
|
package/src/deploy/deploy.ts
CHANGED
|
@@ -11,6 +11,9 @@ import { ensureModules } from "./ensureModules";
|
|
|
11
11
|
import { Table } from "./configToTables";
|
|
12
12
|
import { assertNamespaceOwner } from "./assertNamespaceOwner";
|
|
13
13
|
import { debug } from "./debug";
|
|
14
|
+
import { resourceLabel } from "./resourceLabel";
|
|
15
|
+
import { ensureContract } from "./ensureContract";
|
|
16
|
+
import { uniqueBy } from "@latticexyz/common/utils";
|
|
14
17
|
|
|
15
18
|
type DeployOptions<configInput extends ConfigInput> = {
|
|
16
19
|
client: Client<Transport, Chain | undefined, Account>;
|
|
@@ -51,6 +54,27 @@ export async function deploy<configInput extends ConfigInput>({
|
|
|
51
54
|
resourceIds: [...tables.map((table) => table.tableId), ...systems.map((system) => system.systemId)],
|
|
52
55
|
});
|
|
53
56
|
|
|
57
|
+
// deploy all dependent contracts, because system registration, module install, etc. all expect these contracts to be callable.
|
|
58
|
+
const contractTxs = (
|
|
59
|
+
await Promise.all([
|
|
60
|
+
...uniqueBy(systems, (system) => system.address).map((system) =>
|
|
61
|
+
ensureContract({ client, bytecode: system.bytecode, label: `${resourceLabel(system)} system` })
|
|
62
|
+
),
|
|
63
|
+
...uniqueBy(config.modules, (mod) => mod.address).map((mod) =>
|
|
64
|
+
ensureContract({ client, bytecode: mod.bytecode, label: `${mod.name} module` })
|
|
65
|
+
),
|
|
66
|
+
])
|
|
67
|
+
).flat();
|
|
68
|
+
|
|
69
|
+
if (contractTxs.length) {
|
|
70
|
+
debug("waiting for contracts");
|
|
71
|
+
// wait for each tx separately/serially, because parallelizing results in RPC errors
|
|
72
|
+
for (const tx of contractTxs) {
|
|
73
|
+
await waitForTransactionReceipt(client, { hash: tx });
|
|
74
|
+
// TODO: throw if there was a revert?
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
54
78
|
const tableTxs = await ensureTables({
|
|
55
79
|
client,
|
|
56
80
|
worldDeploy,
|
|
@@ -75,7 +99,7 @@ export async function deploy<configInput extends ConfigInput>({
|
|
|
75
99
|
const txs = [...tableTxs, ...systemTxs, ...functionTxs, ...moduleTxs];
|
|
76
100
|
|
|
77
101
|
// wait for each tx separately/serially, because parallelizing results in RPC errors
|
|
78
|
-
debug("waiting for transactions to confirm");
|
|
102
|
+
debug("waiting for all transactions to confirm");
|
|
79
103
|
for (const tx of txs) {
|
|
80
104
|
await waitForTransactionReceipt(client, { hash: tx });
|
|
81
105
|
// TODO: throw if there was a revert?
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { Client, Transport, Chain, Account, Hex } from "viem";
|
|
2
2
|
import { writeContract } from "@latticexyz/common";
|
|
3
3
|
import { Module, WorldDeploy, worldAbi } from "./common";
|
|
4
|
-
import { ensureContract } from "./ensureContract";
|
|
5
4
|
import { debug } from "./debug";
|
|
6
|
-
import {
|
|
5
|
+
import { wait } from "@latticexyz/common/utils";
|
|
7
6
|
import pRetry from "p-retry";
|
|
8
7
|
|
|
9
8
|
export async function ensureModules({
|
|
@@ -17,14 +16,6 @@ export async function ensureModules({
|
|
|
17
16
|
}): Promise<readonly Hex[]> {
|
|
18
17
|
if (!modules.length) return [];
|
|
19
18
|
|
|
20
|
-
// kick off contract deployments first, otherwise installing modules can fail
|
|
21
|
-
const contractTxs = await Promise.all(
|
|
22
|
-
uniqueBy(modules, (mod) => mod.address).map((mod) =>
|
|
23
|
-
ensureContract({ client, bytecode: mod.bytecode, label: `${mod.name} module` })
|
|
24
|
-
)
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
// then start installing modules
|
|
28
19
|
debug("installing modules:", modules.map((mod) => mod.name).join(", "));
|
|
29
20
|
const installTxs = await Promise.all(
|
|
30
21
|
modules.map((mod) =>
|
|
@@ -70,5 +61,5 @@ export async function ensureModules({
|
|
|
70
61
|
)
|
|
71
62
|
);
|
|
72
63
|
|
|
73
|
-
return
|
|
64
|
+
return await Promise.all(installTxs);
|
|
74
65
|
}
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { Client, Transport, Chain, Account, Hex, getAddress } from "viem";
|
|
2
2
|
import { writeContract } from "@latticexyz/common";
|
|
3
3
|
import { System, WorldDeploy, worldAbi } from "./common";
|
|
4
|
-
import { ensureContract } from "./ensureContract";
|
|
5
4
|
import { debug } from "./debug";
|
|
6
5
|
import { resourceLabel } from "./resourceLabel";
|
|
7
6
|
import { getSystems } from "./getSystems";
|
|
8
7
|
import { getResourceAccess } from "./getResourceAccess";
|
|
9
|
-
import {
|
|
8
|
+
import { wait } from "@latticexyz/common/utils";
|
|
10
9
|
import pRetry from "p-retry";
|
|
11
10
|
|
|
12
11
|
export async function ensureSystems({
|
|
@@ -53,7 +52,7 @@ export async function ensureSystems({
|
|
|
53
52
|
debug("adding", accessToAdd.length, "access grants");
|
|
54
53
|
}
|
|
55
54
|
|
|
56
|
-
const accessTxs =
|
|
55
|
+
const accessTxs = [
|
|
57
56
|
...accessToRemove.map((access) =>
|
|
58
57
|
pRetry(
|
|
59
58
|
() =>
|
|
@@ -94,7 +93,7 @@ export async function ensureSystems({
|
|
|
94
93
|
}
|
|
95
94
|
)
|
|
96
95
|
),
|
|
97
|
-
]
|
|
96
|
+
];
|
|
98
97
|
|
|
99
98
|
const existingSystems = systems.filter((system) =>
|
|
100
99
|
worldSystems.some(
|
|
@@ -127,37 +126,27 @@ export async function ensureSystems({
|
|
|
127
126
|
debug("registering new systems", systemsToAdd.map(resourceLabel).join(", "));
|
|
128
127
|
}
|
|
129
128
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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
|
-
},
|
|
157
|
-
}
|
|
158
|
-
)
|
|
129
|
+
const registerTxs = missingSystems.map((system) =>
|
|
130
|
+
pRetry(
|
|
131
|
+
() =>
|
|
132
|
+
writeContract(client, {
|
|
133
|
+
chain: client.chain ?? null,
|
|
134
|
+
address: worldDeploy.address,
|
|
135
|
+
abi: worldAbi,
|
|
136
|
+
// TODO: replace with batchCall (https://github.com/latticexyz/mud/issues/1645)
|
|
137
|
+
functionName: "registerSystem",
|
|
138
|
+
args: [system.systemId, system.address, system.allowAll],
|
|
139
|
+
}),
|
|
140
|
+
{
|
|
141
|
+
retries: 3,
|
|
142
|
+
onFailedAttempt: async (error) => {
|
|
143
|
+
const delay = error.attemptNumber * 500;
|
|
144
|
+
debug(`failed to register system ${resourceLabel(system)}, retrying in ${delay}ms...`);
|
|
145
|
+
await wait(delay);
|
|
146
|
+
},
|
|
147
|
+
}
|
|
159
148
|
)
|
|
160
149
|
);
|
|
161
150
|
|
|
162
|
-
return
|
|
151
|
+
return await Promise.all([...accessTxs, ...registerTxs]);
|
|
163
152
|
}
|
package/src/runDeploy.ts
CHANGED
|
@@ -26,6 +26,10 @@ export const deployOptions = {
|
|
|
26
26
|
worldAddress: { type: "string", desc: "Deploy to an existing World at the given address" },
|
|
27
27
|
srcDir: { type: "string", desc: "Source directory. Defaults to foundry src directory." },
|
|
28
28
|
skipBuild: { type: "boolean", desc: "Skip rebuilding the contracts before deploying" },
|
|
29
|
+
alwaysRunPostDeploy: {
|
|
30
|
+
type: "boolean",
|
|
31
|
+
desc: "Always run PostDeploy.s.sol after each deploy (including during upgrades). By default, PostDeploy.s.sol is only run once after a new world is deployed.",
|
|
32
|
+
},
|
|
29
33
|
} as const satisfies Record<string, Options>;
|
|
30
34
|
|
|
31
35
|
export type DeployOptions = InferredOptionTypes<typeof deployOptions>;
|
|
@@ -84,7 +88,7 @@ in your contracts directory to use the default anvil private key.`
|
|
|
84
88
|
client,
|
|
85
89
|
config: resolvedConfig,
|
|
86
90
|
});
|
|
87
|
-
if (opts.worldAddress == null) {
|
|
91
|
+
if (opts.worldAddress == null || opts.alwaysRunPostDeploy) {
|
|
88
92
|
await postDeploy(config.postDeployScript, worldDeploy.address, rpc, profile);
|
|
89
93
|
}
|
|
90
94
|
console.log(chalk.green("Deployment completed in", (Date.now() - startTime) / 1000, "seconds"));
|