@latticexyz/cli 2.0.0-main-aa5b2272 → 2.0.0-main-d844cd44

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@latticexyz/cli",
3
- "version": "2.0.0-main-aa5b2272",
3
+ "version": "2.0.0-main-d844cd44",
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-aa5b2272",
44
- "@latticexyz/common": "2.0.0-main-aa5b2272",
45
- "@latticexyz/config": "2.0.0-main-aa5b2272",
46
- "@latticexyz/gas-report": "2.0.0-main-aa5b2272",
47
- "@latticexyz/protocol-parser": "2.0.0-main-aa5b2272",
48
- "@latticexyz/schema-type": "2.0.0-main-aa5b2272",
49
- "@latticexyz/services": "2.0.0-main-aa5b2272",
50
- "@latticexyz/store": "2.0.0-main-aa5b2272",
51
- "@latticexyz/utils": "2.0.0-main-aa5b2272",
52
- "@latticexyz/world": "2.0.0-main-aa5b2272",
53
- "@latticexyz/world-modules": "2.0.0-main-aa5b2272"
43
+ "@latticexyz/abi-ts": "2.0.0-main-d844cd44",
44
+ "@latticexyz/common": "2.0.0-main-d844cd44",
45
+ "@latticexyz/config": "2.0.0-main-d844cd44",
46
+ "@latticexyz/gas-report": "2.0.0-main-d844cd44",
47
+ "@latticexyz/protocol-parser": "2.0.0-main-d844cd44",
48
+ "@latticexyz/schema-type": "2.0.0-main-d844cd44",
49
+ "@latticexyz/services": "2.0.0-main-d844cd44",
50
+ "@latticexyz/store": "2.0.0-main-d844cd44",
51
+ "@latticexyz/utils": "2.0.0-main-d844cd44",
52
+ "@latticexyz/world": "2.0.0-main-d844cd44",
53
+ "@latticexyz/world-modules": "2.0.0-main-d844cd44"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@types/debug": "^4.1.7",
@@ -17,6 +17,10 @@ export const worldDeployEvents = [helloStoreEvent, helloWorldEvent] as const;
17
17
 
18
18
  export const worldAbi = [...IBaseWorldAbi, ...IModuleAbi] as const;
19
19
 
20
+ // Ideally, this should be an append-only list. Before adding more versions here, be sure to add backwards-compatible support for old Store/World versions.
21
+ export const supportedStoreVersions = ["1.0.0-unaudited"];
22
+ export const supportedWorldVersions = ["1.0.0-unaudited"];
23
+
20
24
  export type WorldDeploy = {
21
25
  readonly address: Address;
22
26
  readonly worldVersion: string;
@@ -66,7 +70,3 @@ export type Config<config extends ConfigInput> = {
66
70
  readonly systems: readonly System[];
67
71
  readonly modules: readonly Module[];
68
72
  };
69
-
70
- // Ideally, this should be an append-only list. Before adding more versions here, be sure to add backwards-compatible support for old Store/World versions.
71
- export const supportedStoreVersions = ["1.0.0-unaudited"];
72
- export const supportedWorldVersions = ["1.0.0-unaudited"];
@@ -1,4 +1,4 @@
1
- import { Account, Address, Chain, Client, Transport } from "viem";
1
+ import { Account, Address, Chain, Client, Transport, getAddress } from "viem";
2
2
  import { ensureDeployer } from "./ensureDeployer";
3
3
  import { deployWorld } from "./deployWorld";
4
4
  import { ensureTables } from "./ensureTables";
@@ -14,6 +14,8 @@ import { debug } from "./debug";
14
14
  import { resourceLabel } from "./resourceLabel";
15
15
  import { ensureContract } from "./ensureContract";
16
16
  import { uniqueBy } from "@latticexyz/common/utils";
17
+ import { ensureContractsDeployed } from "./ensureContractsDeployed";
18
+ import { coreModuleBytecode, worldFactoryBytecode } from "./ensureWorldFactory";
17
19
 
18
20
  type DeployOptions<configInput extends ConfigInput> = {
19
21
  client: Client<Transport, Chain | undefined, Account>;
@@ -32,8 +34,28 @@ export async function deploy<configInput extends ConfigInput>({
32
34
  config,
33
35
  worldAddress: existingWorldAddress,
34
36
  }: DeployOptions<configInput>): Promise<WorldDeploy> {
37
+ const tables = Object.values(config.tables) as Table[];
38
+ const systems = Object.values(config.systems);
39
+
35
40
  await ensureDeployer(client);
36
41
 
42
+ // deploy all dependent contracts, because system registration, module install, etc. all expect these contracts to be callable.
43
+ await ensureContractsDeployed({
44
+ client,
45
+ contracts: [
46
+ { bytecode: coreModuleBytecode, label: "core module" },
47
+ { bytecode: worldFactoryBytecode, label: "world factory" },
48
+ ...uniqueBy(systems, (system) => getAddress(system.address)).map((system) => ({
49
+ bytecode: system.bytecode,
50
+ label: `${resourceLabel(system)} system`,
51
+ })),
52
+ ...uniqueBy(config.modules, (mod) => getAddress(mod.address)).map((mod) => ({
53
+ bytecode: mod.bytecode,
54
+ label: `${mod.name} module`,
55
+ })),
56
+ ],
57
+ });
58
+
37
59
  const worldDeploy = existingWorldAddress
38
60
  ? await getWorldDeploy(client, existingWorldAddress)
39
61
  : await deployWorld(client);
@@ -45,36 +67,12 @@ export async function deploy<configInput extends ConfigInput>({
45
67
  throw new Error(`Unsupported World version: ${worldDeploy.worldVersion}`);
46
68
  }
47
69
 
48
- const tables = Object.values(config.tables) as Table[];
49
- const systems = Object.values(config.systems);
50
-
51
70
  await assertNamespaceOwner({
52
71
  client,
53
72
  worldDeploy,
54
73
  resourceIds: [...tables.map((table) => table.tableId), ...systems.map((system) => system.systemId)],
55
74
  });
56
75
 
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
-
78
76
  const tableTxs = await ensureTables({
79
77
  client,
80
78
  worldDeploy,
@@ -7,15 +7,18 @@ import { debug } from "./debug";
7
7
  import pRetry from "p-retry";
8
8
  import { wait } from "@latticexyz/common/utils";
9
9
 
10
+ export type Contract = {
11
+ bytecode: Hex;
12
+ label?: string;
13
+ };
14
+
10
15
  export async function ensureContract({
11
16
  client,
12
17
  bytecode,
13
18
  label = "contract",
14
19
  }: {
15
20
  readonly client: Client<Transport, Chain | undefined, Account>;
16
- readonly bytecode: Hex;
17
- readonly label?: string;
18
- }): Promise<readonly Hex[]> {
21
+ } & Contract): Promise<readonly Hex[]> {
19
22
  const address = getCreate2Address({ from: deployer, salt, bytecode });
20
23
 
21
24
  const contractCode = await getBytecode(client, { address, blockTag: "pending" });
@@ -0,0 +1,25 @@
1
+ import { Client, Transport, Chain, Account, Hex } from "viem";
2
+ import { waitForTransactionReceipt } from "viem/actions";
3
+ import { debug } from "./debug";
4
+ import { Contract, ensureContract } from "./ensureContract";
5
+
6
+ export async function ensureContractsDeployed({
7
+ client,
8
+ contracts,
9
+ }: {
10
+ readonly client: Client<Transport, Chain | undefined, Account>;
11
+ readonly contracts: readonly Contract[];
12
+ }): Promise<readonly Hex[]> {
13
+ const txs = (await Promise.all(contracts.map((contract) => ensureContract({ client, ...contract })))).flat();
14
+
15
+ if (txs.length) {
16
+ debug("waiting for contracts");
17
+ // wait for each tx separately/serially, because parallelizing results in RPC errors
18
+ for (const tx of txs) {
19
+ await waitForTransactionReceipt(client, { hash: tx });
20
+ // TODO: throw if there was a revert?
21
+ }
22
+ }
23
+
24
+ return txs;
25
+ }
@@ -1,9 +1,10 @@
1
- import { Client, Transport, Chain, Account, Hex, BaseError } from "viem";
1
+ import { Client, Transport, Chain, Account, Hex, BaseError, getAddress } from "viem";
2
2
  import { writeContract } from "@latticexyz/common";
3
3
  import { Module, WorldDeploy, worldAbi } from "./common";
4
4
  import { debug } from "./debug";
5
- import { isDefined, wait } from "@latticexyz/common/utils";
5
+ import { isDefined, uniqueBy, wait } from "@latticexyz/common/utils";
6
6
  import pRetry from "p-retry";
7
+ import { ensureContractsDeployed } from "./ensureContractsDeployed";
7
8
 
8
9
  export async function ensureModules({
9
10
  client,
@@ -16,6 +17,14 @@ export async function ensureModules({
16
17
  }): Promise<readonly Hex[]> {
17
18
  if (!modules.length) return [];
18
19
 
20
+ await ensureContractsDeployed({
21
+ client,
22
+ contracts: uniqueBy(modules, (mod) => getAddress(mod.address)).map((mod) => ({
23
+ bytecode: mod.bytecode,
24
+ label: `${mod.name} module`,
25
+ })),
26
+ });
27
+
19
28
  debug("installing modules:", modules.map((mod) => mod.name).join(", "));
20
29
  return (
21
30
  await Promise.all(
@@ -5,8 +5,9 @@ import { debug } from "./debug";
5
5
  import { resourceLabel } from "./resourceLabel";
6
6
  import { getSystems } from "./getSystems";
7
7
  import { getResourceAccess } from "./getResourceAccess";
8
- import { wait } from "@latticexyz/common/utils";
8
+ import { uniqueBy, wait } from "@latticexyz/common/utils";
9
9
  import pRetry from "p-retry";
10
+ import { ensureContractsDeployed } from "./ensureContractsDeployed";
10
11
 
11
12
  export async function ensureSystems({
12
13
  client,
@@ -126,6 +127,14 @@ export async function ensureSystems({
126
127
  debug("registering new systems", systemsToAdd.map(resourceLabel).join(", "));
127
128
  }
128
129
 
130
+ await ensureContractsDeployed({
131
+ client,
132
+ contracts: uniqueBy(missingSystems, (system) => getAddress(system.address)).map((system) => ({
133
+ bytecode: system.bytecode,
134
+ label: `${resourceLabel(system)} system`,
135
+ })),
136
+ });
137
+
129
138
  const registerTxs = missingSystems.map((system) =>
130
139
  pRetry(
131
140
  () =>
@@ -1,18 +1,18 @@
1
1
  import coreModuleBuild from "@latticexyz/world/out/CoreModule.sol/CoreModule.json" assert { type: "json" };
2
2
  import worldFactoryBuild from "@latticexyz/world/out/WorldFactory.sol/WorldFactory.json" assert { type: "json" };
3
3
  import { Client, Transport, Chain, Account, Hex, parseAbi, getCreate2Address, encodeDeployData } from "viem";
4
- import { ensureContract } from "./ensureContract";
5
4
  import { deployer } from "./ensureDeployer";
6
5
  import { salt } from "./common";
6
+ import { ensureContractsDeployed } from "./ensureContractsDeployed";
7
7
 
8
- const coreModuleBytecode = encodeDeployData({
8
+ export const coreModuleBytecode = encodeDeployData({
9
9
  bytecode: coreModuleBuild.bytecode.object as Hex,
10
10
  abi: [],
11
11
  });
12
12
 
13
- const coreModule = getCreate2Address({ from: deployer, bytecode: coreModuleBytecode, salt });
13
+ export const coreModule = getCreate2Address({ from: deployer, bytecode: coreModuleBytecode, salt });
14
14
 
15
- const worldFactoryBytecode = encodeDeployData({
15
+ export const worldFactoryBytecode = encodeDeployData({
16
16
  bytecode: worldFactoryBuild.bytecode.object as Hex,
17
17
  abi: parseAbi(["constructor(address)"]),
18
18
  args: [coreModule],
@@ -24,10 +24,11 @@ export async function ensureWorldFactory(
24
24
  client: Client<Transport, Chain | undefined, Account>
25
25
  ): Promise<readonly Hex[]> {
26
26
  // WorldFactory constructor doesn't call CoreModule, only sets its address, so we can do these in parallel since the address is deterministic
27
- return (
28
- await Promise.all([
29
- ensureContract({ client, bytecode: coreModuleBytecode, label: "core module" }),
30
- ensureContract({ client, bytecode: worldFactoryBytecode, label: "world factory" }),
31
- ])
32
- ).flat();
27
+ return await ensureContractsDeployed({
28
+ client,
29
+ contracts: [
30
+ { bytecode: coreModuleBytecode, label: "core module" },
31
+ { bytecode: worldFactoryBytecode, label: "world factory" },
32
+ ],
33
+ });
33
34
  }
package/src/runDeploy.ts CHANGED
@@ -61,7 +61,7 @@ export async function runDeploy(opts: DeployOptions): Promise<WorldDeploy> {
61
61
  if (!opts.skipBuild) {
62
62
  const outPath = path.join(srcDir, config.codegenDirectory);
63
63
  await tablegen(config, outPath, remappings);
64
- await forge(["build", "--skip", "test", "script"], { profile });
64
+ await forge(["build"], { profile });
65
65
  await execa("mud", ["abi-ts"], { stdio: "inherit" });
66
66
  }
67
67