@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.
Files changed (56) hide show
  1. package/dist/{chunk-22IIKR4S.js → chunk-QXUPZVZL.js} +2 -2
  2. package/dist/chunk-QXUPZVZL.js.map +1 -0
  3. package/dist/commands-WWEJJZV4.js +36 -0
  4. package/dist/commands-WWEJJZV4.js.map +1 -0
  5. package/dist/errors-MZURIB7V.js +2 -0
  6. package/dist/mud.js +1 -1
  7. package/dist/mud.js.map +1 -1
  8. package/package.json +16 -15
  9. package/src/build.ts +9 -5
  10. package/src/commands/build.ts +2 -3
  11. package/src/commands/deploy.ts +1 -1
  12. package/src/commands/dev-contracts.ts +6 -5
  13. package/src/commands/set-version.ts +1 -1
  14. package/src/commands/tablegen.ts +2 -2
  15. package/src/commands/trace.ts +7 -5
  16. package/src/commands/worldgen.ts +7 -6
  17. package/src/deploy/common.ts +54 -8
  18. package/src/deploy/configToTables.ts +8 -6
  19. package/src/deploy/create2/README.md +4 -0
  20. package/src/deploy/create2/deployment.json +2 -1
  21. package/src/deploy/createPrepareDeploy.ts +28 -0
  22. package/src/deploy/deploy.ts +33 -16
  23. package/src/deploy/deployWorld.ts +4 -3
  24. package/src/deploy/ensureContract.ts +12 -7
  25. package/src/deploy/ensureContractsDeployed.ts +9 -1
  26. package/src/deploy/ensureDeployer.ts +61 -22
  27. package/src/deploy/ensureFunctions.ts +5 -5
  28. package/src/deploy/ensureModules.ts +16 -10
  29. package/src/deploy/ensureNamespaceOwner.ts +4 -4
  30. package/src/deploy/ensureSystems.ts +108 -83
  31. package/src/deploy/ensureTables.ts +8 -9
  32. package/src/deploy/ensureWorldFactory.ts +79 -92
  33. package/src/deploy/findLibraries.ts +36 -0
  34. package/src/deploy/getFunctions.ts +5 -5
  35. package/src/deploy/getResourceAccess.ts +3 -3
  36. package/src/deploy/getSystems.ts +6 -7
  37. package/src/deploy/getTableValue.ts +1 -1
  38. package/src/deploy/getTables.ts +2 -2
  39. package/src/deploy/logsToWorldDeploy.ts +4 -4
  40. package/src/deploy/orderByDependencies.ts +12 -0
  41. package/src/deploy/resolveConfig.ts +55 -58
  42. package/src/mud.ts +1 -1
  43. package/src/mudPackages.ts +1 -1
  44. package/src/runDeploy.ts +28 -10
  45. package/src/utils/{modules/constants.ts → defaultModuleContracts.ts} +4 -0
  46. package/src/utils/errors.ts +1 -1
  47. package/src/utils/findPlaceholders.ts +27 -0
  48. package/src/utils/{utils/getContractData.ts → getContractData.ts} +11 -5
  49. package/src/utils/{utils/postDeploy.ts → postDeploy.ts} +2 -2
  50. package/src/utils/printMUD.ts +1 -1
  51. package/dist/chunk-22IIKR4S.js.map +0 -1
  52. package/dist/commands-3JV3U43E.js +0 -27
  53. package/dist/commands-3JV3U43E.js.map +0 -1
  54. package/dist/errors-XGN6V2Y3.js +0 -2
  55. package/src/deploy/resourceLabel.ts +0 -3
  56. /package/dist/{errors-XGN6V2Y3.js.map → errors-MZURIB7V.js.map} +0 -0
@@ -6,113 +6,100 @@ import initModuleBuild from "@latticexyz/world/out/InitModule.sol/InitModule.jso
6
6
  import initModuleAbi from "@latticexyz/world/out/InitModule.sol/InitModule.abi.json" assert { type: "json" };
7
7
  import worldFactoryBuild from "@latticexyz/world/out/WorldFactory.sol/WorldFactory.json" assert { type: "json" };
8
8
  import worldFactoryAbi from "@latticexyz/world/out/WorldFactory.sol/WorldFactory.abi.json" assert { type: "json" };
9
- import { Client, Transport, Chain, Account, Hex, getCreate2Address, encodeDeployData, size } from "viem";
10
- import { deployer } from "./ensureDeployer";
9
+ import { Client, Transport, Chain, Account, Hex, getCreate2Address, encodeDeployData, size, Address } from "viem";
11
10
  import { salt } from "./common";
12
11
  import { ensureContractsDeployed } from "./ensureContractsDeployed";
13
12
  import { Contract } from "./ensureContract";
14
13
 
15
- export const accessManagementSystemDeployedBytecodeSize = size(
16
- accessManagementSystemBuild.deployedBytecode.object as Hex
17
- );
18
- export const accessManagementSystemBytecode = encodeDeployData({
19
- bytecode: accessManagementSystemBuild.bytecode.object as Hex,
20
- abi: [],
21
- });
22
- export const accessManagementSystem = getCreate2Address({
23
- from: deployer,
24
- bytecode: accessManagementSystemBytecode,
25
- salt,
26
- });
14
+ export async function ensureWorldFactory(
15
+ client: Client<Transport, Chain | undefined, Account>,
16
+ deployerAddress: Hex,
17
+ ): Promise<Address> {
18
+ const accessManagementSystemDeployedBytecodeSize = size(accessManagementSystemBuild.deployedBytecode.object as Hex);
19
+ const accessManagementSystemBytecode = accessManagementSystemBuild.bytecode.object as Hex;
20
+ const accessManagementSystem = getCreate2Address({
21
+ from: deployerAddress,
22
+ bytecode: accessManagementSystemBytecode,
23
+ salt,
24
+ });
27
25
 
28
- export const balanceTransferSystemDeployedBytecodeSize = size(
29
- balanceTransferSystemBuild.deployedBytecode.object as Hex
30
- );
31
- export const balanceTransferSystemBytecode = encodeDeployData({
32
- bytecode: balanceTransferSystemBuild.bytecode.object as Hex,
33
- abi: [],
34
- });
35
- export const balanceTransferSystem = getCreate2Address({
36
- from: deployer,
37
- bytecode: balanceTransferSystemBytecode,
38
- salt,
39
- });
26
+ const balanceTransferSystemDeployedBytecodeSize = size(balanceTransferSystemBuild.deployedBytecode.object as Hex);
27
+ const balanceTransferSystemBytecode = balanceTransferSystemBuild.bytecode.object as Hex;
28
+ const balanceTransferSystem = getCreate2Address({
29
+ from: deployerAddress,
30
+ bytecode: balanceTransferSystemBytecode,
31
+ salt,
32
+ });
40
33
 
41
- export const batchCallSystemDeployedBytecodeSize = size(batchCallSystemBuild.deployedBytecode.object as Hex);
42
- export const batchCallSystemBytecode = encodeDeployData({
43
- bytecode: batchCallSystemBuild.bytecode.object as Hex,
44
- abi: [],
45
- });
46
- export const batchCallSystem = getCreate2Address({ from: deployer, bytecode: batchCallSystemBytecode, salt });
34
+ const batchCallSystemDeployedBytecodeSize = size(batchCallSystemBuild.deployedBytecode.object as Hex);
35
+ const batchCallSystemBytecode = batchCallSystemBuild.bytecode.object as Hex;
36
+ const batchCallSystem = getCreate2Address({ from: deployerAddress, bytecode: batchCallSystemBytecode, salt });
47
37
 
48
- export const registrationDeployedBytecodeSize = size(registrationSystemBuild.deployedBytecode.object as Hex);
49
- export const registrationBytecode = encodeDeployData({
50
- bytecode: registrationSystemBuild.bytecode.object as Hex,
51
- abi: [],
52
- });
53
- export const registration = getCreate2Address({
54
- from: deployer,
55
- bytecode: registrationBytecode,
56
- salt,
57
- });
38
+ const registrationDeployedBytecodeSize = size(registrationSystemBuild.deployedBytecode.object as Hex);
39
+ const registrationBytecode = registrationSystemBuild.bytecode.object as Hex;
40
+ const registration = getCreate2Address({
41
+ from: deployerAddress,
42
+ bytecode: registrationBytecode,
43
+ salt,
44
+ });
58
45
 
59
- export const initModuleDeployedBytecodeSize = size(initModuleBuild.deployedBytecode.object as Hex);
60
- export const initModuleBytecode = encodeDeployData({
61
- bytecode: initModuleBuild.bytecode.object as Hex,
62
- abi: initModuleAbi,
63
- args: [accessManagementSystem, balanceTransferSystem, batchCallSystem, registration],
64
- });
46
+ const initModuleDeployedBytecodeSize = size(initModuleBuild.deployedBytecode.object as Hex);
47
+ const initModuleBytecode = encodeDeployData({
48
+ bytecode: initModuleBuild.bytecode.object as Hex,
49
+ abi: initModuleAbi,
50
+ args: [accessManagementSystem, balanceTransferSystem, batchCallSystem, registration],
51
+ });
65
52
 
66
- export const initModule = getCreate2Address({ from: deployer, bytecode: initModuleBytecode, salt });
53
+ const initModule = getCreate2Address({ from: deployerAddress, bytecode: initModuleBytecode, salt });
67
54
 
68
- export const worldFactoryDeployedBytecodeSize = size(worldFactoryBuild.deployedBytecode.object as Hex);
69
- export const worldFactoryBytecode = encodeDeployData({
70
- bytecode: worldFactoryBuild.bytecode.object as Hex,
71
- abi: worldFactoryAbi,
72
- args: [initModule],
73
- });
55
+ const worldFactoryDeployedBytecodeSize = size(worldFactoryBuild.deployedBytecode.object as Hex);
56
+ const worldFactoryBytecode = encodeDeployData({
57
+ bytecode: worldFactoryBuild.bytecode.object as Hex,
58
+ abi: worldFactoryAbi,
59
+ args: [initModule],
60
+ });
74
61
 
75
- export const worldFactory = getCreate2Address({ from: deployer, bytecode: worldFactoryBytecode, salt });
62
+ const worldFactory = getCreate2Address({ from: deployerAddress, bytecode: worldFactoryBytecode, salt });
76
63
 
77
- export const worldFactoryContracts: readonly Contract[] = [
78
- {
79
- bytecode: accessManagementSystemBytecode,
80
- deployedBytecodeSize: accessManagementSystemDeployedBytecodeSize,
81
- label: "access management system",
82
- },
83
- {
84
- bytecode: balanceTransferSystemBytecode,
85
- deployedBytecodeSize: balanceTransferSystemDeployedBytecodeSize,
86
- label: "balance transfer system",
87
- },
88
- {
89
- bytecode: batchCallSystemBytecode,
90
- deployedBytecodeSize: batchCallSystemDeployedBytecodeSize,
91
- label: "batch call system",
92
- },
93
- {
94
- bytecode: registrationBytecode,
95
- deployedBytecodeSize: registrationDeployedBytecodeSize,
96
- label: "core registration system",
97
- },
98
- {
99
- bytecode: initModuleBytecode,
100
- deployedBytecodeSize: initModuleDeployedBytecodeSize,
101
- label: "core module",
102
- },
103
- {
104
- bytecode: worldFactoryBytecode,
105
- deployedBytecodeSize: worldFactoryDeployedBytecodeSize,
106
- label: "world factory",
107
- },
108
- ];
64
+ const worldFactoryContracts: readonly Contract[] = [
65
+ {
66
+ bytecode: accessManagementSystemBytecode,
67
+ deployedBytecodeSize: accessManagementSystemDeployedBytecodeSize,
68
+ label: "access management system",
69
+ },
70
+ {
71
+ bytecode: balanceTransferSystemBytecode,
72
+ deployedBytecodeSize: balanceTransferSystemDeployedBytecodeSize,
73
+ label: "balance transfer system",
74
+ },
75
+ {
76
+ bytecode: batchCallSystemBytecode,
77
+ deployedBytecodeSize: batchCallSystemDeployedBytecodeSize,
78
+ label: "batch call system",
79
+ },
80
+ {
81
+ bytecode: registrationBytecode,
82
+ deployedBytecodeSize: registrationDeployedBytecodeSize,
83
+ label: "core registration system",
84
+ },
85
+ {
86
+ bytecode: initModuleBytecode,
87
+ deployedBytecodeSize: initModuleDeployedBytecodeSize,
88
+ label: "core module",
89
+ },
90
+ {
91
+ bytecode: worldFactoryBytecode,
92
+ deployedBytecodeSize: worldFactoryDeployedBytecodeSize,
93
+ label: "world factory",
94
+ },
95
+ ];
109
96
 
110
- export async function ensureWorldFactory(
111
- client: Client<Transport, Chain | undefined, Account>
112
- ): Promise<readonly Hex[]> {
113
97
  // WorldFactory constructor doesn't call InitModule, only sets its address, so we can do these in parallel since the address is deterministic
114
- return await ensureContractsDeployed({
98
+ await ensureContractsDeployed({
115
99
  client,
100
+ deployerAddress,
116
101
  contracts: worldFactoryContracts,
117
102
  });
103
+
104
+ return worldFactory;
118
105
  }
@@ -0,0 +1,36 @@
1
+ import { readFileSync } from "fs";
2
+ import glob from "glob";
3
+ import { orderByDependencies } from "./orderByDependencies";
4
+ import { LinkReferences } from "../utils/findPlaceholders";
5
+
6
+ export function findLibraries(forgeOutDir: string): readonly {
7
+ readonly path: string;
8
+ readonly name: string;
9
+ }[] {
10
+ const artifacts = glob
11
+ .sync(`${forgeOutDir}/**/*.json`, { ignore: "**/*.abi.json" })
12
+ .map((path) => JSON.parse(readFileSync(path, "utf8")));
13
+
14
+ const libraries = artifacts.flatMap((artifact) => {
15
+ if (!artifact.metadata) return [];
16
+
17
+ const contractPath = Object.keys(artifact.metadata.settings.compilationTarget)[0];
18
+ const contractName = artifact.metadata.settings.compilationTarget[contractPath];
19
+ const linkReferences = artifact.bytecode.linkReferences as LinkReferences;
20
+
21
+ return Object.entries(linkReferences).flatMap(([libraryPath, reference]) =>
22
+ Object.keys(reference).map((libraryName) => ({
23
+ path: libraryPath,
24
+ name: libraryName,
25
+ dependentPath: contractPath,
26
+ dependentName: contractName,
27
+ })),
28
+ );
29
+ });
30
+
31
+ return orderByDependencies(
32
+ libraries,
33
+ (lib) => `${lib.path}:${lib.name}`,
34
+ (lib) => [`${lib.dependentPath}:${lib.dependentName}`],
35
+ );
36
+ }
@@ -1,9 +1,9 @@
1
- import { Client, getFunctionSelector, parseAbiItem } from "viem";
1
+ import { Client, toFunctionSelector, parseAbiItem } from "viem";
2
2
  import { WorldDeploy, WorldFunction, worldTables } from "./common";
3
3
  import { debug } from "./debug";
4
4
  import { storeSetRecordEvent } from "@latticexyz/store";
5
5
  import { getLogs } from "viem/actions";
6
- import { decodeValueArgs } from "@latticexyz/protocol-parser";
6
+ import { decodeValueArgs } from "@latticexyz/protocol-parser/internal";
7
7
  import { getTableValue } from "./getTableValue";
8
8
  import { hexToResource } from "@latticexyz/common";
9
9
 
@@ -34,12 +34,12 @@ export async function getFunctions({
34
34
  // TODO: parallelize with a bulk getRecords
35
35
  const functions = await Promise.all(
36
36
  signatures.map(async (signature) => {
37
- const selector = getFunctionSelector(signature);
37
+ const selector = toFunctionSelector(signature);
38
38
  const { systemId, systemFunctionSelector } = await getTableValue({
39
39
  client,
40
40
  worldDeploy,
41
41
  table: worldTables.world_FunctionSelectors,
42
- key: { functionSelector: selector },
42
+ key: { worldFunctionSelector: selector },
43
43
  });
44
44
  const { namespace, name } = hexToResource(systemId);
45
45
  // TODO: find away around undoing contract logic (https://github.com/latticexyz/mud/issues/1708)
@@ -51,7 +51,7 @@ export async function getFunctions({
51
51
  systemFunctionSignature,
52
52
  systemFunctionSelector,
53
53
  };
54
- })
54
+ }),
55
55
  );
56
56
 
57
57
  return functions;
@@ -3,7 +3,7 @@ import { WorldDeploy, worldTables } from "./common";
3
3
  import { debug } from "./debug";
4
4
  import { storeSpliceStaticDataEvent } from "@latticexyz/store";
5
5
  import { getLogs } from "viem/actions";
6
- import { decodeKey } from "@latticexyz/protocol-parser";
6
+ import { decodeKey } from "@latticexyz/protocol-parser/internal";
7
7
  import { getTableValue } from "./getTableValue";
8
8
 
9
9
  export async function getResourceAccess({
@@ -35,8 +35,8 @@ export async function getResourceAccess({
35
35
  await Promise.all(
36
36
  keys.map(
37
37
  async (key) =>
38
- [key, await getTableValue({ client, worldDeploy, table: worldTables.world_ResourceAccess, key })] as const
39
- )
38
+ [key, await getTableValue({ client, worldDeploy, table: worldTables.world_ResourceAccess, key })] as const,
39
+ ),
40
40
  )
41
41
  )
42
42
  .filter(([, value]) => value.access)
@@ -1,10 +1,9 @@
1
- import { System, WorldDeploy, worldTables } from "./common";
1
+ import { DeployedSystem, WorldDeploy, worldTables } from "./common";
2
2
  import { Client } from "viem";
3
3
  import { getResourceIds } from "./getResourceIds";
4
- import { hexToResource } from "@latticexyz/common";
4
+ import { hexToResource, resourceToLabel } from "@latticexyz/common";
5
5
  import { getTableValue } from "./getTableValue";
6
6
  import { debug } from "./debug";
7
- import { resourceLabel } from "./resourceLabel";
8
7
  import { getFunctions } from "./getFunctions";
9
8
  import { getResourceAccess } from "./getResourceAccess";
10
9
 
@@ -14,7 +13,7 @@ export async function getSystems({
14
13
  }: {
15
14
  readonly client: Client;
16
15
  readonly worldDeploy: WorldDeploy;
17
- }): Promise<readonly Omit<System, "abi" | "bytecode" | "deployedBytecodeSize">[]> {
16
+ }): Promise<readonly DeployedSystem[]> {
18
17
  const [resourceIds, functions, resourceAccess] = await Promise.all([
19
18
  getResourceIds({ client, worldDeploy }),
20
19
  getFunctions({ client, worldDeploy }),
@@ -22,9 +21,9 @@ export async function getSystems({
22
21
  ]);
23
22
  const systems = resourceIds.map(hexToResource).filter((resource) => resource.type === "system");
24
23
 
25
- debug("looking up systems", systems.map(resourceLabel).join(", "));
24
+ debug("looking up systems", systems.map(resourceToLabel).join(", "));
26
25
  return await Promise.all(
27
- systems.map(async (system) => {
26
+ systems.map(async (system): Promise<DeployedSystem> => {
28
27
  const { system: address, publicAccess } = await getTableValue({
29
28
  client,
30
29
  worldDeploy,
@@ -43,6 +42,6 @@ export async function getSystems({
43
42
  .map(({ address }) => address),
44
43
  functions: systemFunctions,
45
44
  };
46
- })
45
+ }),
47
46
  );
48
47
  }
@@ -1,4 +1,4 @@
1
- import { SchemaToPrimitives, decodeValueArgs, encodeKey } from "@latticexyz/protocol-parser";
1
+ import { SchemaToPrimitives, decodeValueArgs, encodeKey } from "@latticexyz/protocol-parser/internal";
2
2
  import { WorldDeploy, worldAbi } from "./common";
3
3
  import { Client } from "viem";
4
4
  import { readContract } from "viem/actions";
@@ -5,7 +5,7 @@ import { WorldDeploy, storeTables } from "./common";
5
5
  import { debug } from "./debug";
6
6
  import { storeSetRecordEvent } from "@latticexyz/store";
7
7
  import { getLogs } from "viem/actions";
8
- import { KeySchema, ValueSchema, decodeKey, decodeValueArgs, hexToSchema } from "@latticexyz/protocol-parser";
8
+ import { KeySchema, ValueSchema, decodeKey, decodeValueArgs, hexToSchema } from "@latticexyz/protocol-parser/internal";
9
9
 
10
10
  export async function getTables({
11
11
  client,
@@ -45,7 +45,7 @@ export async function getTables({
45
45
  const valueAbiTypes = [...valueSchemaFields.staticFields, ...valueSchemaFields.dynamicFields];
46
46
 
47
47
  const keySchema = Object.fromEntries(
48
- keySchemaFields.staticFields.map((abiType, i) => [keyNames[i], abiType])
48
+ keySchemaFields.staticFields.map((abiType, i) => [keyNames[i], abiType]),
49
49
  ) as KeySchema;
50
50
  const valueSchema = Object.fromEntries(valueAbiTypes.map((abiType, i) => [fieldNames[i], abiType])) as ValueSchema;
51
51
 
@@ -1,4 +1,4 @@
1
- import { AbiEventSignatureNotFoundError, Log, decodeEventLog, hexToString, parseAbi, trim } from "viem";
1
+ import { AbiEventSignatureNotFoundError, Log, decodeEventLog, hexToString, parseAbi } from "viem";
2
2
  import { WorldDeploy, worldDeployEvents } from "./common";
3
3
  import { isDefined } from "@latticexyz/common/utils";
4
4
 
@@ -31,13 +31,13 @@ export function logsToWorldDeploy(logs: readonly Log<bigint, number, false>[]):
31
31
  address: log.address,
32
32
  deployBlock: log.blockNumber,
33
33
  ...(log.eventName === "HelloWorld"
34
- ? { worldVersion: hexToString(trim(log.args.worldVersion, { dir: "right" })) }
34
+ ? { worldVersion: hexToString(log.args.worldVersion).replace(/\0+$/, "") }
35
35
  : null),
36
36
  ...(log.eventName === "HelloStore"
37
- ? { storeVersion: hexToString(trim(log.args.storeVersion, { dir: "right" })) }
37
+ ? { storeVersion: hexToString(log.args.storeVersion).replace(/\0+$/, "") }
38
38
  : null),
39
39
  }),
40
- {}
40
+ {},
41
41
  );
42
42
 
43
43
  if (address == null) throw new Error("could not find world address");
@@ -0,0 +1,12 @@
1
+ import toposort from "toposort";
2
+
3
+ export function orderByDependencies<T>(
4
+ items: readonly T[],
5
+ itemKey: (item: T) => string,
6
+ dependencyKeys: (item: T) => string[],
7
+ ): readonly T[] {
8
+ const dependencyOrder = toposort(
9
+ items.flatMap((item) => dependencyKeys(item).map((dependency) => [itemKey(item), dependency] as [string, string])),
10
+ );
11
+ return [...items].sort((a, b) => dependencyOrder.indexOf(itemKey(a)) - dependencyOrder.indexOf(itemKey(b)));
12
+ }
@@ -1,25 +1,18 @@
1
- import { resolveWorldConfig } from "@latticexyz/world";
2
- import { Config, ConfigInput, WorldFunction, salt } from "./common";
3
- import { resourceToHex, hexToResource } from "@latticexyz/common";
4
- import { resolveWithContext } from "@latticexyz/config";
5
- import { encodeField } from "@latticexyz/protocol-parser";
6
- import { SchemaAbiType, SchemaAbiTypeToPrimitiveType } from "@latticexyz/schema-type";
7
- import {
8
- getFunctionSelector,
9
- Hex,
10
- getCreate2Address,
11
- getAddress,
12
- hexToBytes,
13
- Abi,
14
- bytesToHex,
15
- getFunctionSignature,
16
- } from "viem";
1
+ import path from "path";
2
+ import { resolveWorldConfig } from "@latticexyz/world/internal";
3
+ import { Config, ConfigInput, Library, Module, System, WorldFunction } from "./common";
4
+ import { resourceToHex } from "@latticexyz/common";
5
+ import { resolveWithContext } from "@latticexyz/config/library";
6
+ import { encodeField } from "@latticexyz/protocol-parser/internal";
7
+ import { SchemaAbiType, SchemaAbiTypeToPrimitiveType } from "@latticexyz/schema-type/internal";
8
+ import { Hex, hexToBytes, bytesToHex, toFunctionSelector, toFunctionSignature } from "viem";
17
9
  import { getExistingContracts } from "../utils/getExistingContracts";
18
- import { defaultModuleContracts } from "../utils/modules/constants";
19
- import { getContractData } from "../utils/utils/getContractData";
10
+ import { defaultModuleContracts } from "../utils/defaultModuleContracts";
11
+ import { getContractData } from "../utils/getContractData";
20
12
  import { configToTables } from "./configToTables";
21
- import { deployer } from "./ensureDeployer";
22
- import { resourceLabel } from "./resourceLabel";
13
+ import { groupBy } from "@latticexyz/common/utils";
14
+ import { findLibraries } from "./findLibraries";
15
+ import { createPrepareDeploy } from "./createPrepareDeploy";
23
16
 
24
17
  // TODO: this should be replaced by https://github.com/latticexyz/mud/issues/1668
25
18
 
@@ -32,35 +25,47 @@ export function resolveConfig<config extends ConfigInput>({
32
25
  forgeSourceDir: string;
33
26
  forgeOutDir: string;
34
27
  }): Config<config> {
28
+ const libraries = findLibraries(forgeOutDir).map((library): Library => {
29
+ // foundry/solc flattens artifacts, so we just use the path basename
30
+ const contractData = getContractData(path.basename(library.path), library.name, forgeOutDir);
31
+ return {
32
+ path: library.path,
33
+ name: library.name,
34
+ abi: contractData.abi,
35
+ prepareDeploy: createPrepareDeploy(contractData.bytecode, contractData.placeholders),
36
+ deployedBytecodeSize: contractData.deployedBytecodeSize,
37
+ };
38
+ });
39
+
35
40
  const tables = configToTables(config);
36
41
 
37
42
  // TODO: should the config parser/loader help with resolving systems?
38
43
  const contractNames = getExistingContracts(forgeSourceDir).map(({ basename }) => basename);
39
44
  const resolvedConfig = resolveWorldConfig(config, contractNames);
40
- const baseSystemContractData = getContractData("System", forgeOutDir);
45
+ const baseSystemContractData = getContractData("System.sol", "System", forgeOutDir);
41
46
  const baseSystemFunctions = baseSystemContractData.abi
42
47
  .filter((item): item is typeof item & { type: "function" } => item.type === "function")
43
- .map(getFunctionSignature);
48
+ .map(toFunctionSignature);
44
49
 
45
- const systems = Object.entries(resolvedConfig.systems).map(([systemName, system]) => {
50
+ const systems = Object.entries(resolvedConfig.systems).map(([systemName, system]): System => {
46
51
  const namespace = config.namespace;
47
52
  const name = system.name;
48
53
  const systemId = resourceToHex({ type: "system", namespace, name });
49
- const contractData = getContractData(systemName, forgeOutDir);
54
+ const contractData = getContractData(`${systemName}.sol`, systemName, forgeOutDir);
50
55
 
51
56
  const systemFunctions = contractData.abi
52
57
  .filter((item): item is typeof item & { type: "function" } => item.type === "function")
53
- .map(getFunctionSignature)
58
+ .map(toFunctionSignature)
54
59
  .filter((sig) => !baseSystemFunctions.includes(sig))
55
60
  .map((sig): WorldFunction => {
56
61
  // TODO: figure out how to not duplicate contract behavior (https://github.com/latticexyz/mud/issues/1708)
57
62
  const worldSignature = namespace === "" ? sig : `${namespace}__${sig}`;
58
63
  return {
59
64
  signature: worldSignature,
60
- selector: getFunctionSelector(worldSignature),
65
+ selector: toFunctionSelector(worldSignature),
61
66
  systemId,
62
67
  systemFunctionSignature: sig,
63
- systemFunctionSelector: getFunctionSelector(sig),
68
+ systemFunctionSelector: toFunctionSelector(sig),
64
69
  };
65
70
  });
66
71
 
@@ -71,37 +76,29 @@ export function resolveConfig<config extends ConfigInput>({
71
76
  allowAll: system.openAccess,
72
77
  allowedAddresses: system.accessListAddresses as Hex[],
73
78
  allowedSystemIds: system.accessListSystems.map((name) =>
74
- resourceToHex({ type: "system", namespace, name: resolvedConfig.systems[name].name })
79
+ resourceToHex({ type: "system", namespace, name: resolvedConfig.systems[name].name }),
75
80
  ),
76
- address: getCreate2Address({ from: deployer, bytecode: contractData.bytecode, salt }),
77
- bytecode: contractData.bytecode,
81
+ prepareDeploy: createPrepareDeploy(contractData.bytecode, contractData.placeholders),
78
82
  deployedBytecodeSize: contractData.deployedBytecodeSize,
79
83
  abi: contractData.abi,
80
84
  functions: systemFunctions,
81
85
  };
82
86
  });
83
87
 
84
- // resolve allowedSystemIds
85
- // TODO: resolve this at deploy time so we can allow for arbitrary system IDs registered in the world as the source-of-truth rather than config
86
- const systemsWithAccess = systems.map(({ allowedAddresses, allowedSystemIds, ...system }) => {
87
- const allowedSystemAddresses = allowedSystemIds.map((systemId) => {
88
- const targetSystem = systems.find((s) => s.systemId === systemId);
89
- if (!targetSystem) {
90
- throw new Error(
91
- `System ${resourceLabel(system)} wanted access to ${resourceLabel(
92
- hexToResource(systemId)
93
- )}, but it wasn't found in the config.`
94
- );
95
- }
96
- return targetSystem.address;
97
- });
98
- return {
99
- ...system,
100
- allowedAddresses: Array.from(
101
- new Set([...allowedAddresses, ...allowedSystemAddresses].map((addr) => getAddress(addr)))
102
- ),
103
- };
104
- });
88
+ // Check for overlapping system IDs (since names get truncated when turning into IDs)
89
+ // TODO: move this into the world config resolve step once it resolves system IDs
90
+ const systemsById = groupBy(systems, (system) => system.systemId);
91
+ const overlappingSystems = Array.from(systemsById.values())
92
+ .filter((matches) => matches.length > 1)
93
+ .flat();
94
+ if (overlappingSystems.length) {
95
+ const names = overlappingSystems.map((system) => system.name);
96
+ throw new Error(
97
+ `Found systems with overlapping system ID: ${names.join(
98
+ ", ",
99
+ )}.\n\nSystem IDs are generated from the first 16 bytes of the name, so you may need to rename them to avoid the overlap.`,
100
+ );
101
+ }
105
102
 
106
103
  // ugh (https://github.com/latticexyz/mud/issues/1668)
107
104
  const resolveContext = {
@@ -113,16 +110,16 @@ export function resolveConfig<config extends ConfigInput>({
113
110
  type: table.offchainOnly ? "offchainTable" : "table",
114
111
  namespace: config.namespace,
115
112
  name: table.name,
116
- })
113
+ }),
117
114
  ),
118
- ])
115
+ ]),
119
116
  ),
120
117
  };
121
118
 
122
- const modules = config.modules.map((mod) => {
119
+ const modules = config.modules.map((mod): Module => {
123
120
  const contractData =
124
121
  defaultModuleContracts.find((defaultMod) => defaultMod.name === mod.name) ??
125
- getContractData(mod.name, forgeOutDir);
122
+ getContractData(`${mod.name}.sol`, mod.name, forgeOutDir);
126
123
  const installArgs = mod.args
127
124
  .map((arg) => resolveWithContext(arg, resolveContext))
128
125
  .map((arg) => {
@@ -136,8 +133,7 @@ export function resolveConfig<config extends ConfigInput>({
136
133
  name: mod.name,
137
134
  installAsRoot: mod.root,
138
135
  installData: installArgs.length === 0 ? "0x" : installArgs[0],
139
- address: getCreate2Address({ from: deployer, bytecode: contractData.bytecode, salt }),
140
- bytecode: contractData.bytecode,
136
+ prepareDeploy: createPrepareDeploy(contractData.bytecode, contractData.placeholders),
141
137
  deployedBytecodeSize: contractData.deployedBytecodeSize,
142
138
  abi: contractData.abi,
143
139
  };
@@ -145,7 +141,8 @@ export function resolveConfig<config extends ConfigInput>({
145
141
 
146
142
  return {
147
143
  tables,
148
- systems: systemsWithAccess,
144
+ systems,
149
145
  modules,
146
+ libraries,
150
147
  };
151
148
  }
package/src/mud.ts CHANGED
@@ -26,7 +26,7 @@ async function run() {
26
26
  console.error(chalk.red(msg));
27
27
  if (msg.includes("Missing required argument")) {
28
28
  console.log(
29
- chalk.yellow(`Run 'pnpm mud ${process.argv[2]} --help' for a list of available and required arguments.`)
29
+ chalk.yellow(`Run 'pnpm mud ${process.argv[2]} --help' for a list of available and required arguments.`),
30
30
  );
31
31
  }
32
32
  console.log("");
@@ -13,7 +13,7 @@ function parseEnv(): z.infer<typeof envSchema> {
13
13
  });
14
14
  } catch (error) {
15
15
  if (error instanceof ZodError) {
16
- const { _errors, ...invalidEnvVars } = error.format();
16
+ const { ...invalidEnvVars } = error.format();
17
17
  console.error(`\nMissing or invalid environment variables:\n\n ${Object.keys(invalidEnvVars).join("\n ")}\n`);
18
18
  process.exit(1);
19
19
  }