@latticexyz/cli 2.0.12-main-9be2bb86 → 2.0.12-main-96e7bf43
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/{commands-F37Q2ISZ.js → commands-265RZEHD.js} +17 -17
- package/dist/commands-265RZEHD.js.map +1 -0
- package/dist/mud.js +1 -1
- package/package.json +13 -11
- package/dist/commands-F37Q2ISZ.js.map +0 -1
- package/src/build.ts +0 -32
- package/src/commands/build.ts +0 -35
- package/src/commands/deploy.ts +0 -26
- package/src/commands/dev-contracts.ts +0 -118
- package/src/commands/devnode.ts +0 -42
- package/src/commands/hello.ts +0 -28
- package/src/commands/index.ts +0 -33
- package/src/commands/set-version.ts +0 -197
- package/src/commands/tablegen.ts +0 -34
- package/src/commands/test.ts +0 -65
- package/src/commands/trace.ts +0 -120
- package/src/commands/verify.ts +0 -100
- package/src/commands/worldgen.ts +0 -58
- package/src/common.ts +0 -1
- package/src/debug.ts +0 -10
- package/src/deploy/common.ts +0 -120
- package/src/deploy/configToModules.ts +0 -75
- package/src/deploy/configToTables.ts +0 -70
- package/src/deploy/create2/README.md +0 -13
- package/src/deploy/create2/deployment.json +0 -8
- package/src/deploy/createPrepareDeploy.ts +0 -28
- package/src/deploy/debug.ts +0 -10
- package/src/deploy/deploy.ts +0 -137
- package/src/deploy/deployWorld.ts +0 -38
- package/src/deploy/ensureContract.ts +0 -66
- package/src/deploy/ensureContractsDeployed.ts +0 -33
- package/src/deploy/ensureDeployer.ts +0 -69
- package/src/deploy/ensureFunctions.ts +0 -86
- package/src/deploy/ensureModules.ts +0 -81
- package/src/deploy/ensureNamespaceOwner.ts +0 -71
- package/src/deploy/ensureSystems.ts +0 -187
- package/src/deploy/ensureTables.ts +0 -64
- package/src/deploy/ensureWorldFactory.ts +0 -30
- package/src/deploy/findLibraries.ts +0 -36
- package/src/deploy/getDeployer.ts +0 -20
- package/src/deploy/getFunctions.ts +0 -64
- package/src/deploy/getResourceAccess.ts +0 -51
- package/src/deploy/getResourceIds.ts +0 -45
- package/src/deploy/getSystems.ts +0 -47
- package/src/deploy/getTableValue.ts +0 -31
- package/src/deploy/getTables.ts +0 -59
- package/src/deploy/getWorldContracts.ts +0 -79
- package/src/deploy/getWorldDeploy.ts +0 -39
- package/src/deploy/getWorldFactoryContracts.ts +0 -27
- package/src/deploy/getWorldProxyFactoryContracts.ts +0 -27
- package/src/deploy/logsToWorldDeploy.ts +0 -49
- package/src/deploy/orderByDependencies.ts +0 -12
- package/src/deploy/resolveConfig.ts +0 -104
- package/src/index.ts +0 -1
- package/src/modules.d.ts +0 -11
- package/src/mud.ts +0 -45
- package/src/mudPackages.ts +0 -24
- package/src/runDeploy.ts +0 -181
- package/src/utils/errors.ts +0 -29
- package/src/utils/findPlaceholders.ts +0 -27
- package/src/utils/getContractArtifact.ts +0 -80
- package/src/utils/getContractData.ts +0 -38
- package/src/utils/getExistingContracts.ts +0 -12
- package/src/utils/knownModuleArtifacts.ts +0 -8
- package/src/utils/postDeploy.ts +0 -42
- package/src/utils/printMUD.ts +0 -14
- package/src/verify/verifyContract.ts +0 -23
- package/src/verify.ts +0 -174
package/src/commands/verify.ts
DELETED
@@ -1,100 +0,0 @@
|
|
1
|
-
import type { CommandModule, InferredOptionTypes } from "yargs";
|
2
|
-
import { verify } from "../verify";
|
3
|
-
import { loadConfig } from "@latticexyz/config/node";
|
4
|
-
import { World as WorldConfig } from "@latticexyz/world";
|
5
|
-
import { resolveWorldConfig } from "@latticexyz/world/internal";
|
6
|
-
import { worldToV1 } from "@latticexyz/world/config/v2";
|
7
|
-
import { getOutDirectory, getRpcUrl, getSrcDirectory } from "@latticexyz/common/foundry";
|
8
|
-
import { getExistingContracts } from "../utils/getExistingContracts";
|
9
|
-
import { getContractData } from "../utils/getContractData";
|
10
|
-
import { Hex, createWalletClient, http } from "viem";
|
11
|
-
import chalk from "chalk";
|
12
|
-
import { configToModules } from "../deploy/configToModules";
|
13
|
-
|
14
|
-
const verifyOptions = {
|
15
|
-
deployerAddress: {
|
16
|
-
type: "string",
|
17
|
-
desc: "Deploy using an existing deterministic deployer (https://github.com/Arachnid/deterministic-deployment-proxy)",
|
18
|
-
},
|
19
|
-
worldAddress: { type: "string", required: true, desc: "Verify an existing World at the given address" },
|
20
|
-
configPath: { type: "string", desc: "Path to the MUD config file" },
|
21
|
-
profile: { type: "string", desc: "The foundry profile to use" },
|
22
|
-
rpc: { type: "string", desc: "The RPC URL to use. Defaults to the RPC url from the local foundry.toml" },
|
23
|
-
rpcBatch: {
|
24
|
-
type: "boolean",
|
25
|
-
desc: "Enable batch processing of RPC requests in viem client (defaults to batch size of 100 and wait of 1s)",
|
26
|
-
},
|
27
|
-
srcDir: { type: "string", desc: "Source directory. Defaults to foundry src directory." },
|
28
|
-
verifier: { type: "string", desc: "The verifier to use. Defaults to blockscout", default: "blockscout" },
|
29
|
-
verifierUrl: {
|
30
|
-
type: "string",
|
31
|
-
desc: "The verification provider.",
|
32
|
-
},
|
33
|
-
} as const;
|
34
|
-
|
35
|
-
type Options = InferredOptionTypes<typeof verifyOptions>;
|
36
|
-
|
37
|
-
const commandModule: CommandModule<Options, Options> = {
|
38
|
-
command: "verify",
|
39
|
-
|
40
|
-
describe: "Verify contracts",
|
41
|
-
|
42
|
-
builder(yargs) {
|
43
|
-
return yargs.options(verifyOptions);
|
44
|
-
},
|
45
|
-
|
46
|
-
async handler(opts) {
|
47
|
-
const profile = opts.profile ?? process.env.FOUNDRY_PROFILE;
|
48
|
-
|
49
|
-
const configV2 = (await loadConfig(opts.configPath)) as WorldConfig;
|
50
|
-
const config = worldToV1(configV2);
|
51
|
-
|
52
|
-
const srcDir = opts.srcDir ?? (await getSrcDirectory(profile));
|
53
|
-
const outDir = await getOutDirectory(profile);
|
54
|
-
|
55
|
-
const rpc = opts.rpc ?? (await getRpcUrl(profile));
|
56
|
-
console.log(
|
57
|
-
chalk.bgBlue(
|
58
|
-
chalk.whiteBright(`\n Verifying MUD contracts${profile ? " with profile " + profile : ""} to RPC ${rpc} \n`),
|
59
|
-
),
|
60
|
-
);
|
61
|
-
|
62
|
-
const client = createWalletClient({
|
63
|
-
transport: http(rpc, {
|
64
|
-
batch: opts.rpcBatch
|
65
|
-
? {
|
66
|
-
batchSize: 100,
|
67
|
-
wait: 1000,
|
68
|
-
}
|
69
|
-
: undefined,
|
70
|
-
}),
|
71
|
-
});
|
72
|
-
|
73
|
-
const contractNames = getExistingContracts(srcDir).map(({ basename }) => basename);
|
74
|
-
const resolvedWorldConfig = resolveWorldConfig(config, contractNames);
|
75
|
-
|
76
|
-
const systems = Object.keys(resolvedWorldConfig.systems).map((name) => {
|
77
|
-
const contractData = getContractData(`${name}.sol`, name, outDir);
|
78
|
-
|
79
|
-
return {
|
80
|
-
name,
|
81
|
-
bytecode: contractData.bytecode,
|
82
|
-
};
|
83
|
-
});
|
84
|
-
|
85
|
-
const modules = await configToModules(configV2, outDir);
|
86
|
-
|
87
|
-
await verify({
|
88
|
-
client,
|
89
|
-
rpc,
|
90
|
-
systems,
|
91
|
-
modules,
|
92
|
-
deployerAddress: opts.deployerAddress as Hex | undefined,
|
93
|
-
worldAddress: opts.worldAddress as Hex,
|
94
|
-
verifier: opts.verifier,
|
95
|
-
verifierUrl: opts.verifierUrl,
|
96
|
-
});
|
97
|
-
},
|
98
|
-
};
|
99
|
-
|
100
|
-
export default commandModule;
|
package/src/commands/worldgen.ts
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
import type { CommandModule } from "yargs";
|
2
|
-
import { loadConfig } from "@latticexyz/config/node";
|
3
|
-
import { World as WorldConfig } from "@latticexyz/world";
|
4
|
-
import { worldgen } from "@latticexyz/world/node";
|
5
|
-
import { getSrcDirectory } from "@latticexyz/common/foundry";
|
6
|
-
import path from "path";
|
7
|
-
import { rmSync } from "fs";
|
8
|
-
import { getExistingContracts } from "../utils/getExistingContracts";
|
9
|
-
|
10
|
-
type Options = {
|
11
|
-
configPath?: string;
|
12
|
-
clean?: boolean;
|
13
|
-
srcDir?: string;
|
14
|
-
config?: WorldConfig;
|
15
|
-
};
|
16
|
-
|
17
|
-
const commandModule: CommandModule<Options, Options> = {
|
18
|
-
command: "worldgen",
|
19
|
-
|
20
|
-
describe: "Autogenerate interfaces for Systems and World based on existing contracts and the config file",
|
21
|
-
|
22
|
-
builder(yargs) {
|
23
|
-
return yargs.options({
|
24
|
-
configPath: { type: "string", desc: "Path to the MUD config file" },
|
25
|
-
clean: {
|
26
|
-
type: "boolean",
|
27
|
-
desc: "Clear the worldgen directory before generating new interfaces (defaults to true)",
|
28
|
-
default: true,
|
29
|
-
},
|
30
|
-
});
|
31
|
-
},
|
32
|
-
|
33
|
-
async handler(args) {
|
34
|
-
await worldgenHandler(args);
|
35
|
-
process.exit(0);
|
36
|
-
},
|
37
|
-
};
|
38
|
-
|
39
|
-
export async function worldgenHandler(args: Options) {
|
40
|
-
const srcDir = args.srcDir ?? (await getSrcDirectory());
|
41
|
-
|
42
|
-
const existingContracts = getExistingContracts(srcDir);
|
43
|
-
|
44
|
-
// Load the config
|
45
|
-
const mudConfig = args.config ?? ((await loadConfig(args.configPath)) as WorldConfig);
|
46
|
-
|
47
|
-
const outputBaseDirectory = path.join(srcDir, mudConfig.codegen.outputDirectory);
|
48
|
-
|
49
|
-
// clear the worldgen directory
|
50
|
-
if (args.clean) {
|
51
|
-
rmSync(path.join(outputBaseDirectory, mudConfig.codegen.worldgenDirectory), { recursive: true, force: true });
|
52
|
-
}
|
53
|
-
|
54
|
-
// generate new interfaces
|
55
|
-
await worldgen(mudConfig, existingContracts, outputBaseDirectory);
|
56
|
-
}
|
57
|
-
|
58
|
-
export default commandModule;
|
package/src/common.ts
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
export type MudPackages = Record<string, { localPath: string }>;
|
package/src/debug.ts
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
import createDebug from "debug";
|
2
|
-
|
3
|
-
export const debug = createDebug("mud:cli");
|
4
|
-
export const error = createDebug("mud:cli");
|
5
|
-
|
6
|
-
// Pipe debug output to stdout instead of stderr
|
7
|
-
debug.log = console.debug.bind(console);
|
8
|
-
|
9
|
-
// Pipe error output to stderr
|
10
|
-
error.log = console.error.bind(console);
|
package/src/deploy/common.ts
DELETED
@@ -1,120 +0,0 @@
|
|
1
|
-
import { Abi, Address, Hex, padHex } from "viem";
|
2
|
-
import storeConfig from "@latticexyz/store/mud.config";
|
3
|
-
import worldConfig from "@latticexyz/world/mud.config";
|
4
|
-
import IBaseWorldAbi from "@latticexyz/world/out/IBaseWorld.sol/IBaseWorld.abi.json" assert { type: "json" };
|
5
|
-
import { Tables, configToTables } from "./configToTables";
|
6
|
-
import { helloStoreEvent } from "@latticexyz/store";
|
7
|
-
import { StoreConfig } from "@latticexyz/store/internal";
|
8
|
-
import { helloWorldEvent } from "@latticexyz/world";
|
9
|
-
import { WorldConfig } from "@latticexyz/world/internal";
|
10
|
-
import { storeToV1 } from "@latticexyz/store/config/v2";
|
11
|
-
import { worldToV1 } from "@latticexyz/world/config/v2";
|
12
|
-
|
13
|
-
export const salt = padHex("0x", { size: 32 });
|
14
|
-
|
15
|
-
// https://eips.ethereum.org/EIPS/eip-170
|
16
|
-
export const contractSizeLimit = parseInt("6000", 16);
|
17
|
-
|
18
|
-
// TODO: add `as const` to mud config so these get more strongly typed (blocked by current config parsing not using readonly)
|
19
|
-
export const storeTables = configToTables(storeToV1(storeConfig));
|
20
|
-
export const worldTables = configToTables(worldToV1(worldConfig));
|
21
|
-
|
22
|
-
export const worldDeployEvents = [helloStoreEvent, helloWorldEvent] as const;
|
23
|
-
|
24
|
-
export const worldAbi = IBaseWorldAbi;
|
25
|
-
|
26
|
-
// 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.
|
27
|
-
export const supportedStoreVersions = ["2.0.0", "2.0.1", "2.0.2"];
|
28
|
-
export const supportedWorldVersions = ["2.0.0", "2.0.1", "2.0.2"];
|
29
|
-
|
30
|
-
// TODO: extend this to include factory+deployer address? so we can reuse the deployer for a world?
|
31
|
-
export type WorldDeploy = {
|
32
|
-
readonly address: Address;
|
33
|
-
readonly worldVersion: string;
|
34
|
-
readonly storeVersion: string;
|
35
|
-
/** Block number where the world was deployed */
|
36
|
-
readonly deployBlock: bigint;
|
37
|
-
/**
|
38
|
-
* Block number at the time of fetching world deploy.
|
39
|
-
* We use this block number when requesting data from the chain to align chain state
|
40
|
-
* with the same block during the introspection steps of the deploy.
|
41
|
-
*/
|
42
|
-
readonly stateBlock: bigint;
|
43
|
-
};
|
44
|
-
|
45
|
-
export type WorldFunction = {
|
46
|
-
readonly signature: string;
|
47
|
-
readonly selector: Hex;
|
48
|
-
readonly systemId: Hex;
|
49
|
-
readonly systemFunctionSignature: string;
|
50
|
-
readonly systemFunctionSelector: Hex;
|
51
|
-
};
|
52
|
-
|
53
|
-
export type LibraryPlaceholder = {
|
54
|
-
/**
|
55
|
-
* Path to library source file, e.g. `src/libraries/SomeLib.sol`
|
56
|
-
*/
|
57
|
-
path: string;
|
58
|
-
/**
|
59
|
-
* Library name, e.g. `SomeLib`
|
60
|
-
*/
|
61
|
-
name: string;
|
62
|
-
/**
|
63
|
-
* Byte offset of placeholder in bytecode
|
64
|
-
*/
|
65
|
-
start: number;
|
66
|
-
/**
|
67
|
-
* Size of placeholder to replace in bytes
|
68
|
-
*/
|
69
|
-
length: number;
|
70
|
-
};
|
71
|
-
|
72
|
-
export type DeterministicContract = {
|
73
|
-
readonly prepareDeploy: (
|
74
|
-
deployer: Address,
|
75
|
-
libraries: readonly Library[],
|
76
|
-
) => {
|
77
|
-
readonly address: Address;
|
78
|
-
readonly bytecode: Hex;
|
79
|
-
};
|
80
|
-
readonly deployedBytecodeSize: number;
|
81
|
-
readonly abi: Abi;
|
82
|
-
};
|
83
|
-
|
84
|
-
export type Library = DeterministicContract & {
|
85
|
-
/**
|
86
|
-
* Path to library source file, e.g. `src/libraries/SomeLib.sol`
|
87
|
-
*/
|
88
|
-
path: string;
|
89
|
-
/**
|
90
|
-
* Library name, e.g. `SomeLib`
|
91
|
-
*/
|
92
|
-
name: string;
|
93
|
-
};
|
94
|
-
|
95
|
-
export type System = DeterministicContract & {
|
96
|
-
readonly namespace: string;
|
97
|
-
readonly name: string;
|
98
|
-
readonly systemId: Hex;
|
99
|
-
readonly allowAll: boolean;
|
100
|
-
readonly allowedAddresses: readonly Hex[];
|
101
|
-
readonly allowedSystemIds: readonly Hex[];
|
102
|
-
readonly functions: readonly WorldFunction[];
|
103
|
-
};
|
104
|
-
|
105
|
-
export type DeployedSystem = Omit<System, "abi" | "prepareDeploy" | "deployedBytecodeSize" | "allowedSystemIds"> & {
|
106
|
-
address: Address;
|
107
|
-
};
|
108
|
-
|
109
|
-
export type Module = DeterministicContract & {
|
110
|
-
readonly name: string;
|
111
|
-
readonly installAsRoot: boolean;
|
112
|
-
readonly installData: Hex; // TODO: figure out better naming for this
|
113
|
-
};
|
114
|
-
|
115
|
-
export type ConfigInput = StoreConfig & WorldConfig;
|
116
|
-
export type Config<config extends ConfigInput> = {
|
117
|
-
readonly tables: Tables<config>;
|
118
|
-
readonly systems: readonly System[];
|
119
|
-
readonly libraries: readonly Library[];
|
120
|
-
};
|
@@ -1,75 +0,0 @@
|
|
1
|
-
import path from "node:path";
|
2
|
-
import { Module } from "./common";
|
3
|
-
import { encodeField } from "@latticexyz/protocol-parser/internal";
|
4
|
-
import { SchemaAbiType, SchemaAbiTypeToPrimitiveType } from "@latticexyz/schema-type/internal";
|
5
|
-
import { bytesToHex } from "viem";
|
6
|
-
import { createPrepareDeploy } from "./createPrepareDeploy";
|
7
|
-
import { World } from "@latticexyz/world";
|
8
|
-
import { getContractArtifact } from "../utils/getContractArtifact";
|
9
|
-
import { knownModuleArtifacts } from "../utils/knownModuleArtifacts";
|
10
|
-
import { resolveWithContext } from "@latticexyz/world/internal";
|
11
|
-
|
12
|
-
export async function configToModules<config extends World>(
|
13
|
-
config: config,
|
14
|
-
// TODO: remove/replace `forgeOutDir`
|
15
|
-
forgeOutDir: string,
|
16
|
-
): Promise<readonly Module[]> {
|
17
|
-
const modules = await Promise.all(
|
18
|
-
config.modules.map(async (mod): Promise<Module> => {
|
19
|
-
let artifactPath = mod.artifactPath;
|
20
|
-
|
21
|
-
// Backwards compatibility
|
22
|
-
// TODO: move this up a level so we don't need `forgeOutDir` in here?
|
23
|
-
if (!artifactPath) {
|
24
|
-
if (mod.name) {
|
25
|
-
artifactPath =
|
26
|
-
knownModuleArtifacts[mod.name as keyof typeof knownModuleArtifacts] ??
|
27
|
-
path.join(forgeOutDir, `${mod.name}.sol`, `${mod.name}.json`);
|
28
|
-
console.warn(
|
29
|
-
[
|
30
|
-
"",
|
31
|
-
`⚠️ Your \`mud.config.ts\` is using a module with a \`name\`, but this option is deprecated.`,
|
32
|
-
"",
|
33
|
-
"To resolve this, you can replace this:",
|
34
|
-
"",
|
35
|
-
` name: ${JSON.stringify(mod.name)}`,
|
36
|
-
"",
|
37
|
-
"with this:",
|
38
|
-
"",
|
39
|
-
` artifactPath: ${JSON.stringify(artifactPath)}`,
|
40
|
-
"",
|
41
|
-
].join("\n"),
|
42
|
-
);
|
43
|
-
} else {
|
44
|
-
throw new Error("No `artifactPath` provided for module.");
|
45
|
-
}
|
46
|
-
}
|
47
|
-
|
48
|
-
const name = path.basename(artifactPath, ".json");
|
49
|
-
const artifact = await getContractArtifact({ artifactPath });
|
50
|
-
|
51
|
-
// TODO: replace args with something more strongly typed
|
52
|
-
const installArgs = mod.args
|
53
|
-
.map((arg) => resolveWithContext(arg, { config }))
|
54
|
-
.map((arg) => {
|
55
|
-
const value = arg.value instanceof Uint8Array ? bytesToHex(arg.value) : arg.value;
|
56
|
-
return encodeField(arg.type as SchemaAbiType, value as SchemaAbiTypeToPrimitiveType<SchemaAbiType>);
|
57
|
-
});
|
58
|
-
|
59
|
-
if (installArgs.length > 1) {
|
60
|
-
throw new Error(`${name} module should only have 0-1 args, but had ${installArgs.length} args.`);
|
61
|
-
}
|
62
|
-
|
63
|
-
return {
|
64
|
-
name,
|
65
|
-
installAsRoot: mod.root,
|
66
|
-
installData: installArgs.length === 0 ? "0x" : installArgs[0],
|
67
|
-
prepareDeploy: createPrepareDeploy(artifact.bytecode, artifact.placeholders),
|
68
|
-
deployedBytecodeSize: artifact.deployedBytecodeSize,
|
69
|
-
abi: artifact.abi,
|
70
|
-
};
|
71
|
-
}),
|
72
|
-
);
|
73
|
-
|
74
|
-
return modules;
|
75
|
-
}
|
@@ -1,70 +0,0 @@
|
|
1
|
-
import { resourceToHex } from "@latticexyz/common";
|
2
|
-
import { KeySchema, ValueSchema } from "@latticexyz/protocol-parser/internal";
|
3
|
-
import { SchemaAbiType, StaticAbiType } from "@latticexyz/schema-type/internal";
|
4
|
-
import { StoreConfig, resolveUserTypes } from "@latticexyz/store/internal";
|
5
|
-
import { Hex } from "viem";
|
6
|
-
|
7
|
-
// TODO: we shouldn't need this file once our config parsing returns nicely formed tables
|
8
|
-
|
9
|
-
type UserTypes<config extends StoreConfig = StoreConfig> = config["userTypes"];
|
10
|
-
// TODO: fix strong enum types and avoid every schema getting `{ [k: string]: "uint8" }`
|
11
|
-
// type UserTypes<config extends StoreConfig = StoreConfig> = config["userTypes"] & {
|
12
|
-
// [k in keyof config["enums"]]: { internalType: "uint8" };
|
13
|
-
// };
|
14
|
-
|
15
|
-
export type TableKey<
|
16
|
-
config extends StoreConfig = StoreConfig,
|
17
|
-
table extends config["tables"][keyof config["tables"]] = config["tables"][keyof config["tables"]],
|
18
|
-
> = `${config["namespace"]}_${table["name"]}`;
|
19
|
-
|
20
|
-
export type Table<
|
21
|
-
config extends StoreConfig = StoreConfig,
|
22
|
-
table extends config["tables"][keyof config["tables"]] = config["tables"][keyof config["tables"]],
|
23
|
-
> = {
|
24
|
-
readonly namespace: config["namespace"];
|
25
|
-
readonly name: table["name"];
|
26
|
-
readonly tableId: Hex;
|
27
|
-
readonly keySchema: table["keySchema"] extends KeySchema<UserTypes<config>>
|
28
|
-
? KeySchema & {
|
29
|
-
readonly [k in keyof table["keySchema"]]: UserTypes<config>[table["keySchema"][k]]["internalType"] extends StaticAbiType
|
30
|
-
? UserTypes<config>[table["keySchema"][k]]["internalType"]
|
31
|
-
: table["keySchema"][k];
|
32
|
-
}
|
33
|
-
: KeySchema;
|
34
|
-
readonly valueSchema: table["valueSchema"] extends ValueSchema<UserTypes<config>>
|
35
|
-
? {
|
36
|
-
readonly [k in keyof table["valueSchema"]]: UserTypes<config>[table["valueSchema"][k]]["internalType"] extends SchemaAbiType
|
37
|
-
? UserTypes<config>[table["valueSchema"][k]]["internalType"]
|
38
|
-
: table["valueSchema"][k];
|
39
|
-
}
|
40
|
-
: ValueSchema;
|
41
|
-
};
|
42
|
-
|
43
|
-
export type Tables<config extends StoreConfig = StoreConfig> = {
|
44
|
-
readonly [k in keyof config["tables"] as TableKey<config, config["tables"][k]>]: Table<config, config["tables"][k]>;
|
45
|
-
};
|
46
|
-
|
47
|
-
export function configToTables<config extends StoreConfig>(config: config): Tables<config> {
|
48
|
-
const userTypes = {
|
49
|
-
...config.userTypes,
|
50
|
-
...Object.fromEntries(Object.entries(config.enums).map(([key]) => [key, { internalType: "uint8" }] as const)),
|
51
|
-
};
|
52
|
-
return Object.fromEntries(
|
53
|
-
Object.entries(config.tables).map(([tableName, table]) => [
|
54
|
-
`${config.namespace}_${tableName}` satisfies TableKey<config, config["tables"][keyof config["tables"]]>,
|
55
|
-
{
|
56
|
-
namespace: config.namespace,
|
57
|
-
name: table.name,
|
58
|
-
tableId: resourceToHex({
|
59
|
-
type: table.offchainOnly ? "offchainTable" : "table",
|
60
|
-
namespace: config.namespace,
|
61
|
-
name: table.name,
|
62
|
-
}),
|
63
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
64
|
-
keySchema: resolveUserTypes(table.keySchema, userTypes) as any,
|
65
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
66
|
-
valueSchema: resolveUserTypes(table.valueSchema, userTypes) as any,
|
67
|
-
} satisfies Table<config, config["tables"][keyof config["tables"]]>,
|
68
|
-
]),
|
69
|
-
) as Tables<config>;
|
70
|
-
}
|
@@ -1,13 +0,0 @@
|
|
1
|
-
Files generated by
|
2
|
-
|
3
|
-
```
|
4
|
-
git clone https://github.com/Arachnid/deterministic-deployment-proxy.git
|
5
|
-
cd deterministic-deployment-proxy
|
6
|
-
git checkout b3bb19c
|
7
|
-
npm install
|
8
|
-
npm run build
|
9
|
-
cd output
|
10
|
-
jq --arg bc "$(cat bytecode.txt)" '. + {creationCode: $bc}' deployment.json > deployment-with-creationCode.json
|
11
|
-
mv deployment-with-creationCode.json deployment.json
|
12
|
-
cp deployment.json ../path/to/this/dir
|
13
|
-
```
|
@@ -1,8 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"gasPrice": 100000000000,
|
3
|
-
"gasLimit": 100000,
|
4
|
-
"signerAddress": "3fab184622dc19b6109349b94811493bf2a45362",
|
5
|
-
"transaction": "f8a58085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222",
|
6
|
-
"address": "4e59b44847b379578588920ca78fbf26c0b4956c",
|
7
|
-
"creationCode": "604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3"
|
8
|
-
}
|
@@ -1,28 +0,0 @@
|
|
1
|
-
import { DeterministicContract, Library, LibraryPlaceholder, salt } from "./common";
|
2
|
-
import { spliceHex } from "@latticexyz/common";
|
3
|
-
import { Hex, getCreate2Address, Address } from "viem";
|
4
|
-
|
5
|
-
export function createPrepareDeploy(
|
6
|
-
bytecodeWithPlaceholders: Hex,
|
7
|
-
placeholders: readonly LibraryPlaceholder[],
|
8
|
-
): DeterministicContract["prepareDeploy"] {
|
9
|
-
return function prepareDeploy(deployer: Address, libraries: readonly Library[]) {
|
10
|
-
let bytecode = bytecodeWithPlaceholders;
|
11
|
-
for (const placeholder of placeholders) {
|
12
|
-
const library = libraries.find((lib) => lib.path === placeholder.path && lib.name === placeholder.name);
|
13
|
-
if (!library) {
|
14
|
-
throw new Error(`Could not find library for bytecode placeholder ${placeholder.path}:${placeholder.name}`);
|
15
|
-
}
|
16
|
-
bytecode = spliceHex(
|
17
|
-
bytecode,
|
18
|
-
placeholder.start,
|
19
|
-
placeholder.length,
|
20
|
-
library.prepareDeploy(deployer, libraries).address,
|
21
|
-
);
|
22
|
-
}
|
23
|
-
return {
|
24
|
-
bytecode,
|
25
|
-
address: getCreate2Address({ from: deployer, bytecode, salt }),
|
26
|
-
};
|
27
|
-
};
|
28
|
-
}
|
package/src/deploy/debug.ts
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
import { debug as parentDebug } from "../debug";
|
2
|
-
|
3
|
-
export const debug = parentDebug.extend("deploy");
|
4
|
-
export const error = parentDebug.extend("deploy");
|
5
|
-
|
6
|
-
// Pipe debug output to stdout instead of stderr
|
7
|
-
debug.log = console.debug.bind(console);
|
8
|
-
|
9
|
-
// Pipe error output to stderr
|
10
|
-
error.log = console.error.bind(console);
|
package/src/deploy/deploy.ts
DELETED
@@ -1,137 +0,0 @@
|
|
1
|
-
import { Account, Address, Chain, Client, Hex, Transport } from "viem";
|
2
|
-
import { ensureDeployer } from "./ensureDeployer";
|
3
|
-
import { deployWorld } from "./deployWorld";
|
4
|
-
import { ensureTables } from "./ensureTables";
|
5
|
-
import { Config, ConfigInput, Module, WorldDeploy, supportedStoreVersions, supportedWorldVersions } from "./common";
|
6
|
-
import { ensureSystems } from "./ensureSystems";
|
7
|
-
import { waitForTransactionReceipt } from "viem/actions";
|
8
|
-
import { getWorldDeploy } from "./getWorldDeploy";
|
9
|
-
import { ensureFunctions } from "./ensureFunctions";
|
10
|
-
import { ensureModules } from "./ensureModules";
|
11
|
-
import { Table } from "./configToTables";
|
12
|
-
import { ensureNamespaceOwner } from "./ensureNamespaceOwner";
|
13
|
-
import { debug } from "./debug";
|
14
|
-
import { resourceToLabel } from "@latticexyz/common";
|
15
|
-
import { ensureContractsDeployed } from "./ensureContractsDeployed";
|
16
|
-
import { randomBytes } from "crypto";
|
17
|
-
import { ensureWorldFactory } from "./ensureWorldFactory";
|
18
|
-
|
19
|
-
type DeployOptions<configInput extends ConfigInput> = {
|
20
|
-
client: Client<Transport, Chain | undefined, Account>;
|
21
|
-
config: Config<configInput>;
|
22
|
-
modules?: readonly Module[];
|
23
|
-
salt?: Hex;
|
24
|
-
worldAddress?: Address;
|
25
|
-
/**
|
26
|
-
* Address of determinstic deployment proxy: https://github.com/Arachnid/deterministic-deployment-proxy
|
27
|
-
* By default, we look for a deployment at 0x4e59b44847b379578588920ca78fbf26c0b4956c and, if not, deploy one.
|
28
|
-
* If the target chain does not support legacy transactions, we deploy the proxy bytecode anyway, but it will
|
29
|
-
* not have a deterministic address.
|
30
|
-
*/
|
31
|
-
deployerAddress?: Hex;
|
32
|
-
withWorldProxy?: boolean;
|
33
|
-
};
|
34
|
-
|
35
|
-
/**
|
36
|
-
* Given a viem client and MUD config, we attempt to introspect the world
|
37
|
-
* (or deploy a new one if no world address is provided) and do the minimal
|
38
|
-
* amount of work to make the world match the config (e.g. deploy new tables,
|
39
|
-
* replace systems, etc.)
|
40
|
-
*/
|
41
|
-
export async function deploy<configInput extends ConfigInput>({
|
42
|
-
client,
|
43
|
-
config,
|
44
|
-
modules = [],
|
45
|
-
salt,
|
46
|
-
worldAddress: existingWorldAddress,
|
47
|
-
deployerAddress: initialDeployerAddress,
|
48
|
-
withWorldProxy,
|
49
|
-
}: DeployOptions<configInput>): Promise<WorldDeploy> {
|
50
|
-
const tables = Object.values(config.tables) as Table[];
|
51
|
-
|
52
|
-
const deployerAddress = initialDeployerAddress ?? (await ensureDeployer(client));
|
53
|
-
|
54
|
-
await ensureWorldFactory(client, deployerAddress, withWorldProxy);
|
55
|
-
|
56
|
-
// deploy all dependent contracts, because system registration, module install, etc. all expect these contracts to be callable.
|
57
|
-
await ensureContractsDeployed({
|
58
|
-
client,
|
59
|
-
deployerAddress,
|
60
|
-
contracts: [
|
61
|
-
...config.libraries.map((library) => ({
|
62
|
-
bytecode: library.prepareDeploy(deployerAddress, config.libraries).bytecode,
|
63
|
-
deployedBytecodeSize: library.deployedBytecodeSize,
|
64
|
-
label: `${library.path}:${library.name} library`,
|
65
|
-
})),
|
66
|
-
...config.systems.map((system) => ({
|
67
|
-
bytecode: system.prepareDeploy(deployerAddress, config.libraries).bytecode,
|
68
|
-
deployedBytecodeSize: system.deployedBytecodeSize,
|
69
|
-
label: `${resourceToLabel(system)} system`,
|
70
|
-
})),
|
71
|
-
...modules.map((mod) => ({
|
72
|
-
bytecode: mod.prepareDeploy(deployerAddress, config.libraries).bytecode,
|
73
|
-
deployedBytecodeSize: mod.deployedBytecodeSize,
|
74
|
-
label: `${mod.name} module`,
|
75
|
-
})),
|
76
|
-
],
|
77
|
-
});
|
78
|
-
|
79
|
-
const worldDeploy = existingWorldAddress
|
80
|
-
? await getWorldDeploy(client, existingWorldAddress)
|
81
|
-
: await deployWorld(client, deployerAddress, salt ?? `0x${randomBytes(32).toString("hex")}`, withWorldProxy);
|
82
|
-
|
83
|
-
if (!supportedStoreVersions.includes(worldDeploy.storeVersion)) {
|
84
|
-
throw new Error(`Unsupported Store version: ${worldDeploy.storeVersion}`);
|
85
|
-
}
|
86
|
-
if (!supportedWorldVersions.includes(worldDeploy.worldVersion)) {
|
87
|
-
throw new Error(`Unsupported World version: ${worldDeploy.worldVersion}`);
|
88
|
-
}
|
89
|
-
|
90
|
-
const namespaceTxs = await ensureNamespaceOwner({
|
91
|
-
client,
|
92
|
-
worldDeploy,
|
93
|
-
resourceIds: [...tables.map((table) => table.tableId), ...config.systems.map((system) => system.systemId)],
|
94
|
-
});
|
95
|
-
|
96
|
-
debug("waiting for all namespace registration transactions to confirm");
|
97
|
-
for (const tx of namespaceTxs) {
|
98
|
-
await waitForTransactionReceipt(client, { hash: tx });
|
99
|
-
}
|
100
|
-
|
101
|
-
const tableTxs = await ensureTables({
|
102
|
-
client,
|
103
|
-
worldDeploy,
|
104
|
-
tables,
|
105
|
-
});
|
106
|
-
const systemTxs = await ensureSystems({
|
107
|
-
client,
|
108
|
-
deployerAddress,
|
109
|
-
libraries: config.libraries,
|
110
|
-
worldDeploy,
|
111
|
-
systems: config.systems,
|
112
|
-
});
|
113
|
-
const functionTxs = await ensureFunctions({
|
114
|
-
client,
|
115
|
-
worldDeploy,
|
116
|
-
functions: config.systems.flatMap((system) => system.functions),
|
117
|
-
});
|
118
|
-
const moduleTxs = await ensureModules({
|
119
|
-
client,
|
120
|
-
deployerAddress,
|
121
|
-
libraries: config.libraries,
|
122
|
-
worldDeploy,
|
123
|
-
modules,
|
124
|
-
});
|
125
|
-
|
126
|
-
const txs = [...tableTxs, ...systemTxs, ...functionTxs, ...moduleTxs];
|
127
|
-
|
128
|
-
// wait for each tx separately/serially, because parallelizing results in RPC errors
|
129
|
-
debug("waiting for all transactions to confirm");
|
130
|
-
for (const tx of txs) {
|
131
|
-
await waitForTransactionReceipt(client, { hash: tx });
|
132
|
-
// TODO: throw if there was a revert?
|
133
|
-
}
|
134
|
-
|
135
|
-
debug("deploy complete");
|
136
|
-
return worldDeploy;
|
137
|
-
}
|
@@ -1,38 +0,0 @@
|
|
1
|
-
import { Account, Chain, Client, Hex, Transport } from "viem";
|
2
|
-
import { waitForTransactionReceipt } from "viem/actions";
|
3
|
-
import { ensureWorldFactory } from "./ensureWorldFactory";
|
4
|
-
import WorldFactoryAbi from "@latticexyz/world/out/WorldFactory.sol/WorldFactory.abi.json" assert { type: "json" };
|
5
|
-
import { writeContract } from "@latticexyz/common";
|
6
|
-
import { debug } from "./debug";
|
7
|
-
import { logsToWorldDeploy } from "./logsToWorldDeploy";
|
8
|
-
import { WorldDeploy } from "./common";
|
9
|
-
|
10
|
-
export async function deployWorld(
|
11
|
-
client: Client<Transport, Chain | undefined, Account>,
|
12
|
-
deployerAddress: Hex,
|
13
|
-
salt: Hex,
|
14
|
-
withWorldProxy?: boolean,
|
15
|
-
): Promise<WorldDeploy> {
|
16
|
-
const worldFactory = await ensureWorldFactory(client, deployerAddress, withWorldProxy);
|
17
|
-
|
18
|
-
debug("deploying world");
|
19
|
-
const tx = await writeContract(client, {
|
20
|
-
chain: client.chain ?? null,
|
21
|
-
address: worldFactory,
|
22
|
-
abi: WorldFactoryAbi,
|
23
|
-
functionName: "deployWorld",
|
24
|
-
args: [salt],
|
25
|
-
});
|
26
|
-
|
27
|
-
debug("waiting for world deploy");
|
28
|
-
const receipt = await waitForTransactionReceipt(client, { hash: tx });
|
29
|
-
if (receipt.status !== "success") {
|
30
|
-
console.error("world deploy failed", receipt);
|
31
|
-
throw new Error("world deploy failed");
|
32
|
-
}
|
33
|
-
|
34
|
-
const deploy = logsToWorldDeploy(receipt.logs);
|
35
|
-
debug("deployed world to", deploy.address, "at block", deploy.deployBlock);
|
36
|
-
|
37
|
-
return { ...deploy, stateBlock: deploy.deployBlock };
|
38
|
-
}
|