@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/deploy.ts
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
import type { CommandModule } from "yargs";
|
2
|
-
import { logError } from "../utils/errors";
|
3
|
-
import { DeployOptions, deployOptions, runDeploy } from "../runDeploy";
|
4
|
-
|
5
|
-
const commandModule: CommandModule<typeof deployOptions, DeployOptions> = {
|
6
|
-
command: "deploy",
|
7
|
-
|
8
|
-
describe: "Deploy MUD contracts",
|
9
|
-
|
10
|
-
builder(yargs) {
|
11
|
-
return yargs.options(deployOptions);
|
12
|
-
},
|
13
|
-
|
14
|
-
async handler(opts) {
|
15
|
-
// Wrap in try/catch, because yargs seems to swallow errors
|
16
|
-
try {
|
17
|
-
await runDeploy(opts);
|
18
|
-
} catch (error) {
|
19
|
-
logError(error);
|
20
|
-
process.exit(1);
|
21
|
-
}
|
22
|
-
process.exit(0);
|
23
|
-
},
|
24
|
-
};
|
25
|
-
|
26
|
-
export default commandModule;
|
@@ -1,118 +0,0 @@
|
|
1
|
-
import type { CommandModule, InferredOptionTypes } from "yargs";
|
2
|
-
import { anvil, getScriptDirectory, getSrcDirectory } from "@latticexyz/common/foundry";
|
3
|
-
import chalk from "chalk";
|
4
|
-
import chokidar from "chokidar";
|
5
|
-
import { loadConfig, resolveConfigPath } from "@latticexyz/config/node";
|
6
|
-
import path from "path";
|
7
|
-
import { World as WorldConfig } from "@latticexyz/world";
|
8
|
-
import { homedir } from "os";
|
9
|
-
import { rmSync } from "fs";
|
10
|
-
import { deployOptions, runDeploy } from "../runDeploy";
|
11
|
-
import { BehaviorSubject, debounceTime, exhaustMap, filter } from "rxjs";
|
12
|
-
import { Address } from "viem";
|
13
|
-
import { isDefined } from "@latticexyz/common/utils";
|
14
|
-
|
15
|
-
const devOptions = {
|
16
|
-
rpc: deployOptions.rpc,
|
17
|
-
configPath: deployOptions.configPath,
|
18
|
-
alwaysRunPostDeploy: deployOptions.alwaysRunPostDeploy,
|
19
|
-
forgeScriptOptions: deployOptions.forgeScriptOptions,
|
20
|
-
worldAddress: deployOptions.worldAddress,
|
21
|
-
};
|
22
|
-
|
23
|
-
const commandModule: CommandModule<typeof devOptions, InferredOptionTypes<typeof devOptions>> = {
|
24
|
-
command: "dev-contracts",
|
25
|
-
|
26
|
-
describe: "Start a development server for MUD contracts",
|
27
|
-
|
28
|
-
builder(yargs) {
|
29
|
-
return yargs.options(devOptions);
|
30
|
-
},
|
31
|
-
|
32
|
-
async handler(opts) {
|
33
|
-
let rpc = opts.rpc;
|
34
|
-
const configPath = opts.configPath ?? (await resolveConfigPath(opts.configPath));
|
35
|
-
const srcDir = await getSrcDirectory();
|
36
|
-
const scriptDir = await getScriptDirectory();
|
37
|
-
const initialConfig = (await loadConfig(configPath)) as WorldConfig;
|
38
|
-
|
39
|
-
// Start an anvil instance in the background if no RPC url is provided
|
40
|
-
if (!opts.rpc) {
|
41
|
-
// Clean anvil cache as 1s block times can fill up the disk
|
42
|
-
// - https://github.com/foundry-rs/foundry/issues/3623
|
43
|
-
// - https://github.com/foundry-rs/foundry/issues/4989
|
44
|
-
// - https://github.com/foundry-rs/foundry/issues/3699
|
45
|
-
// - https://github.com/foundry-rs/foundry/issues/3512
|
46
|
-
console.log(chalk.gray("Cleaning devnode cache"));
|
47
|
-
const userHomeDir = homedir();
|
48
|
-
rmSync(path.join(userHomeDir, ".foundry", "anvil", "tmp"), { recursive: true, force: true });
|
49
|
-
|
50
|
-
const anvilArgs = ["--block-time", "1", "--block-base-fee-per-gas", "0"];
|
51
|
-
anvil(anvilArgs);
|
52
|
-
rpc = "http://127.0.0.1:8545";
|
53
|
-
}
|
54
|
-
|
55
|
-
// Watch for changes
|
56
|
-
const lastChange$ = new BehaviorSubject<number>(Date.now());
|
57
|
-
chokidar.watch([configPath, srcDir, scriptDir], { ignoreInitial: true }).on("all", async (_, updatePath) => {
|
58
|
-
if (updatePath.includes(configPath)) {
|
59
|
-
console.log(chalk.blue("Config changed, queuing deploy…"));
|
60
|
-
lastChange$.next(Date.now());
|
61
|
-
}
|
62
|
-
if (updatePath.includes(srcDir) || updatePath.includes(scriptDir)) {
|
63
|
-
// Ignore changes to codegen files to avoid an infinite loop
|
64
|
-
if (!updatePath.includes(initialConfig.codegen.outputDirectory)) {
|
65
|
-
console.log(chalk.blue("Contracts changed, queuing deploy…"));
|
66
|
-
lastChange$.next(Date.now());
|
67
|
-
}
|
68
|
-
}
|
69
|
-
});
|
70
|
-
|
71
|
-
let worldAddress = opts.worldAddress as Address | undefined;
|
72
|
-
|
73
|
-
const deploys$ = lastChange$.pipe(
|
74
|
-
// debounce so that a large batch of file changes only triggers a deploy after it settles down, rather than the first change it sees (and then redeploying immediately after)
|
75
|
-
debounceTime(200),
|
76
|
-
exhaustMap(async (lastChange) => {
|
77
|
-
if (worldAddress) {
|
78
|
-
console.log(chalk.blue("Rebuilding and upgrading world…"));
|
79
|
-
}
|
80
|
-
|
81
|
-
try {
|
82
|
-
const deploy = await runDeploy({
|
83
|
-
...opts,
|
84
|
-
configPath,
|
85
|
-
rpc,
|
86
|
-
rpcBatch: false,
|
87
|
-
skipBuild: false,
|
88
|
-
printConfig: false,
|
89
|
-
profile: undefined,
|
90
|
-
saveDeployment: true,
|
91
|
-
deployerAddress: undefined,
|
92
|
-
worldAddress,
|
93
|
-
srcDir,
|
94
|
-
salt: "0x",
|
95
|
-
kms: undefined,
|
96
|
-
});
|
97
|
-
worldAddress = deploy.address;
|
98
|
-
// if there were changes while we were deploying, trigger it again
|
99
|
-
if (lastChange < lastChange$.value) {
|
100
|
-
lastChange$.next(lastChange$.value);
|
101
|
-
} else {
|
102
|
-
console.log(chalk.gray("\nWaiting for file changes…\n"));
|
103
|
-
}
|
104
|
-
return deploy;
|
105
|
-
} catch (error) {
|
106
|
-
console.error(chalk.bgRed(chalk.whiteBright("\n Error while attempting deploy \n")));
|
107
|
-
console.error(error);
|
108
|
-
console.log(chalk.gray("\nWaiting for file changes…\n"));
|
109
|
-
}
|
110
|
-
}),
|
111
|
-
filter(isDefined),
|
112
|
-
);
|
113
|
-
|
114
|
-
deploys$.subscribe();
|
115
|
-
},
|
116
|
-
};
|
117
|
-
|
118
|
-
export default commandModule;
|
package/src/commands/devnode.ts
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
import { rmSync } from "fs";
|
2
|
-
import { homedir } from "os";
|
3
|
-
import path from "path";
|
4
|
-
import type { CommandModule } from "yargs";
|
5
|
-
import { execa } from "execa";
|
6
|
-
|
7
|
-
type Options = {
|
8
|
-
blocktime: number;
|
9
|
-
};
|
10
|
-
|
11
|
-
const commandModule: CommandModule<Options, Options> = {
|
12
|
-
command: "devnode",
|
13
|
-
|
14
|
-
describe: "Start a local Ethereum node for development",
|
15
|
-
|
16
|
-
builder(yargs) {
|
17
|
-
return yargs.options({
|
18
|
-
blocktime: { type: "number", default: 1, decs: "Interval in which new blocks are produced" },
|
19
|
-
});
|
20
|
-
},
|
21
|
-
|
22
|
-
async handler({ blocktime }) {
|
23
|
-
console.log("Clearing devnode history");
|
24
|
-
const userHomeDir = homedir();
|
25
|
-
rmSync(path.join(userHomeDir, ".foundry", "anvil", "tmp"), { recursive: true, force: true });
|
26
|
-
|
27
|
-
const anvilArgs = ["-b", String(blocktime), "--block-base-fee-per-gas", "0"];
|
28
|
-
console.log(`Running: anvil ${anvilArgs.join(" ")}`);
|
29
|
-
const child = execa("anvil", anvilArgs, {
|
30
|
-
stdio: ["inherit", "inherit", "inherit"],
|
31
|
-
});
|
32
|
-
|
33
|
-
process.on("SIGINT", () => {
|
34
|
-
console.log("\ngracefully shutting down from SIGINT (Crtl-C)");
|
35
|
-
child.kill();
|
36
|
-
process.exit();
|
37
|
-
});
|
38
|
-
await child;
|
39
|
-
},
|
40
|
-
};
|
41
|
-
|
42
|
-
export default commandModule;
|
package/src/commands/hello.ts
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
import type { CommandModule } from "yargs";
|
2
|
-
|
3
|
-
type Options = {
|
4
|
-
name: string;
|
5
|
-
upper: boolean | undefined;
|
6
|
-
};
|
7
|
-
|
8
|
-
const commandModule: CommandModule<Options, Options> = {
|
9
|
-
command: "hello <name>",
|
10
|
-
|
11
|
-
describe: "Greet <name> with Hello",
|
12
|
-
|
13
|
-
builder(yargs) {
|
14
|
-
return yargs
|
15
|
-
.options({
|
16
|
-
upper: { type: "boolean" },
|
17
|
-
})
|
18
|
-
.positional("name", { type: "string", demandOption: true });
|
19
|
-
},
|
20
|
-
|
21
|
-
handler({ name }) {
|
22
|
-
const greeting = `Gm, ${name}!`;
|
23
|
-
console.log(greeting);
|
24
|
-
process.exit(0);
|
25
|
-
},
|
26
|
-
};
|
27
|
-
|
28
|
-
export default commandModule;
|
package/src/commands/index.ts
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
import { CommandModule } from "yargs";
|
2
|
-
|
3
|
-
import gasReport from "@latticexyz/gas-report";
|
4
|
-
import abiTs from "@latticexyz/abi-ts";
|
5
|
-
|
6
|
-
import build from "./build";
|
7
|
-
import devnode from "./devnode";
|
8
|
-
import hello from "./hello";
|
9
|
-
import tablegen from "./tablegen";
|
10
|
-
import deploy from "./deploy";
|
11
|
-
import worldgen from "./worldgen";
|
12
|
-
import setVersion from "./set-version";
|
13
|
-
import test from "./test";
|
14
|
-
import trace from "./trace";
|
15
|
-
import devContracts from "./dev-contracts";
|
16
|
-
import verify from "./verify";
|
17
|
-
|
18
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Each command has different options
|
19
|
-
export const commands: CommandModule<any, any>[] = [
|
20
|
-
build,
|
21
|
-
deploy,
|
22
|
-
devnode,
|
23
|
-
gasReport as CommandModule,
|
24
|
-
hello,
|
25
|
-
tablegen,
|
26
|
-
worldgen,
|
27
|
-
setVersion,
|
28
|
-
test,
|
29
|
-
trace,
|
30
|
-
devContracts,
|
31
|
-
abiTs,
|
32
|
-
verify,
|
33
|
-
];
|
@@ -1,197 +0,0 @@
|
|
1
|
-
import chalk from "chalk";
|
2
|
-
import { readFileSync, writeFileSync } from "fs";
|
3
|
-
import path from "path";
|
4
|
-
import type { CommandModule } from "yargs";
|
5
|
-
import { MUDError } from "@latticexyz/common/errors";
|
6
|
-
import { logError } from "../utils/errors";
|
7
|
-
import localPackageJson from "../../package.json" assert { type: "json" };
|
8
|
-
import glob from "glob";
|
9
|
-
import { mudPackages } from "../mudPackages";
|
10
|
-
|
11
|
-
type Options = {
|
12
|
-
backup?: boolean;
|
13
|
-
force?: boolean;
|
14
|
-
restore?: boolean;
|
15
|
-
mudVersion?: string;
|
16
|
-
tag?: string;
|
17
|
-
commit?: string;
|
18
|
-
link?: string;
|
19
|
-
};
|
20
|
-
|
21
|
-
const commandModule: CommandModule<Options, Options> = {
|
22
|
-
command: "set-version",
|
23
|
-
|
24
|
-
describe: "Set MUD version in all package.json files and optionally backup the previously installed version",
|
25
|
-
|
26
|
-
builder(yargs) {
|
27
|
-
return yargs.options({
|
28
|
-
mudVersion: { alias: "v", type: "string", description: "Set MUD to the given version" },
|
29
|
-
tag: {
|
30
|
-
alias: "t",
|
31
|
-
type: "string",
|
32
|
-
description: "Set MUD to the latest version with the given tag from npm",
|
33
|
-
},
|
34
|
-
commit: {
|
35
|
-
alias: "c",
|
36
|
-
type: "string",
|
37
|
-
description: "Set MUD to the version based on a given git commit hash from npm",
|
38
|
-
},
|
39
|
-
link: { alias: "l", type: "string", description: "Relative path to the local MUD root directory to link" },
|
40
|
-
});
|
41
|
-
},
|
42
|
-
|
43
|
-
async handler(options) {
|
44
|
-
try {
|
45
|
-
const mutuallyExclusiveOptions = ["mudVersion", "link", "tag", "commit", "restore"];
|
46
|
-
const numMutuallyExclusiveOptions = mutuallyExclusiveOptions.reduce(
|
47
|
-
(acc, opt) => (options[opt] ? acc + 1 : acc),
|
48
|
-
0,
|
49
|
-
);
|
50
|
-
|
51
|
-
if (numMutuallyExclusiveOptions === 0) {
|
52
|
-
throw new MUDError(`You need to provide one these options: ${mutuallyExclusiveOptions.join(", ")}`);
|
53
|
-
}
|
54
|
-
|
55
|
-
if (numMutuallyExclusiveOptions > 1) {
|
56
|
-
throw new MUDError(`These options are mutually exclusive: ${mutuallyExclusiveOptions.join(", ")}`);
|
57
|
-
}
|
58
|
-
|
59
|
-
// If the --link flag is not set, we call resolveVersion to get the version
|
60
|
-
// Resolve the version number from available options like `tag` or `commit`
|
61
|
-
if (!options.link) {
|
62
|
-
options.mudVersion = await resolveVersion(options);
|
63
|
-
}
|
64
|
-
|
65
|
-
// Update all package.json below the current working directory (except in node_modules)
|
66
|
-
const packageJsons = glob.sync("**/package.json").filter((p) => !p.includes("node_modules"));
|
67
|
-
for (const packageJson of packageJsons) {
|
68
|
-
updatePackageJson(packageJson, options);
|
69
|
-
}
|
70
|
-
} catch (e) {
|
71
|
-
logError(e);
|
72
|
-
} finally {
|
73
|
-
process.exit(0);
|
74
|
-
}
|
75
|
-
},
|
76
|
-
};
|
77
|
-
|
78
|
-
async function resolveVersion(options: Options) {
|
79
|
-
// Backwards compatibility to previous behavior of this script where passing "canary" as the version resolved to the latest commit on main
|
80
|
-
if (options.mudVersion === "canary") options.tag = "main";
|
81
|
-
|
82
|
-
let npmResult;
|
83
|
-
try {
|
84
|
-
console.log(chalk.blue(`Fetching available versions`));
|
85
|
-
npmResult = await (await fetch(`https://registry.npmjs.org/${localPackageJson.name}`)).json();
|
86
|
-
} catch (e) {
|
87
|
-
throw new MUDError(`Could not fetch available MUD versions`);
|
88
|
-
}
|
89
|
-
|
90
|
-
if (options.tag) {
|
91
|
-
const version = npmResult["dist-tags"][options.tag];
|
92
|
-
if (!version) {
|
93
|
-
throw new MUDError(`Could not find npm version with tag "${options.tag}"`);
|
94
|
-
}
|
95
|
-
console.log(chalk.green(`Latest version with tag ${options.tag}: ${version}`));
|
96
|
-
return version;
|
97
|
-
}
|
98
|
-
|
99
|
-
if (options.commit) {
|
100
|
-
// Find a version with this commit hash
|
101
|
-
const commit = options.commit.substring(0, 8); // changesets uses the first 8 characters of the commit hash as version for prereleases/snapshot releases
|
102
|
-
const version = Object.keys(npmResult["versions"]).find((v) => (v as string).includes(commit));
|
103
|
-
if (!version) {
|
104
|
-
throw new MUDError(`Could not find npm version based on commit "${options.commit}"`);
|
105
|
-
}
|
106
|
-
console.log(chalk.green(`Version from commit ${options.commit}: ${version}`));
|
107
|
-
return version;
|
108
|
-
}
|
109
|
-
|
110
|
-
// If neither a tag nor a commit option is given, return the `mudVersion`
|
111
|
-
return options.mudVersion;
|
112
|
-
}
|
113
|
-
|
114
|
-
function updatePackageJson(filePath: string, options: Options): { workspaces?: string[] } {
|
115
|
-
const { link } = options;
|
116
|
-
let { mudVersion } = options;
|
117
|
-
|
118
|
-
const packageJson = readPackageJson(filePath);
|
119
|
-
const mudPackageNames = Object.keys(mudPackages);
|
120
|
-
|
121
|
-
// Find all MUD dependencies
|
122
|
-
const mudDependencies: Record<string, string> = {};
|
123
|
-
for (const packageName in packageJson.dependencies) {
|
124
|
-
if (mudPackageNames.includes(packageName)) {
|
125
|
-
mudDependencies[packageName] = packageJson.dependencies[packageName];
|
126
|
-
}
|
127
|
-
}
|
128
|
-
|
129
|
-
// Find all MUD devDependencies
|
130
|
-
const mudDevDependencies: Record<string, string> = {};
|
131
|
-
for (const packageName in packageJson.devDependencies) {
|
132
|
-
if (mudPackageNames.includes(packageName)) {
|
133
|
-
mudDevDependencies[packageName] = packageJson.devDependencies[packageName];
|
134
|
-
}
|
135
|
-
}
|
136
|
-
|
137
|
-
// Update the dependencies
|
138
|
-
for (const packageName in packageJson.dependencies) {
|
139
|
-
if (mudPackageNames.includes(packageName)) {
|
140
|
-
packageJson.dependencies[packageName] = resolveMudVersion(packageName, "dependencies");
|
141
|
-
}
|
142
|
-
}
|
143
|
-
|
144
|
-
// Update the devDependencies
|
145
|
-
for (const packageName in packageJson.devDependencies) {
|
146
|
-
if (mudPackageNames.includes(packageName)) {
|
147
|
-
packageJson.devDependencies[packageName] = resolveMudVersion(packageName, "devDependencies");
|
148
|
-
}
|
149
|
-
}
|
150
|
-
|
151
|
-
// Write the updated package.json
|
152
|
-
writeFileSync(filePath, JSON.stringify(packageJson, null, 2) + "\n");
|
153
|
-
|
154
|
-
console.log(`Updating ${filePath}`);
|
155
|
-
logComparison(mudDependencies, packageJson.dependencies);
|
156
|
-
logComparison(mudDevDependencies, packageJson.devDependencies);
|
157
|
-
|
158
|
-
return packageJson;
|
159
|
-
|
160
|
-
function resolveMudVersion(key: string, type: "dependencies" | "devDependencies") {
|
161
|
-
if (link) mudVersion = resolveLinkPath(filePath, link, key);
|
162
|
-
if (!mudVersion) return packageJson[type][key];
|
163
|
-
return mudVersion;
|
164
|
-
}
|
165
|
-
}
|
166
|
-
|
167
|
-
function readPackageJson(path: string): {
|
168
|
-
workspaces?: string[];
|
169
|
-
dependencies: Record<string, string>;
|
170
|
-
devDependencies: Record<string, string>;
|
171
|
-
} {
|
172
|
-
try {
|
173
|
-
const jsonString = readFileSync(path, "utf8");
|
174
|
-
return JSON.parse(jsonString);
|
175
|
-
} catch {
|
176
|
-
throw new MUDError("Could not read JSON at " + path);
|
177
|
-
}
|
178
|
-
}
|
179
|
-
|
180
|
-
function logComparison(prev: Record<string, string>, curr: Record<string, string>) {
|
181
|
-
for (const key in prev) {
|
182
|
-
if (prev[key] !== curr[key]) {
|
183
|
-
console.log(`${key}: ${chalk.red(prev[key])} -> ${chalk.green(curr[key])}`);
|
184
|
-
}
|
185
|
-
}
|
186
|
-
}
|
187
|
-
|
188
|
-
/**
|
189
|
-
* Returns path of the package to link, given a path to a local MUD clone and a package
|
190
|
-
*/
|
191
|
-
function resolveLinkPath(packageJsonPath: string, mudLinkPath: string, packageName: string) {
|
192
|
-
const packageJsonToRootPath = path.relative(path.dirname(packageJsonPath), process.cwd());
|
193
|
-
const linkPath = path.join(packageJsonToRootPath, mudLinkPath, mudPackages[packageName].localPath);
|
194
|
-
return "link:" + linkPath;
|
195
|
-
}
|
196
|
-
|
197
|
-
export default commandModule;
|
package/src/commands/tablegen.ts
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
import path from "path";
|
2
|
-
import type { CommandModule } from "yargs";
|
3
|
-
import { loadConfig } from "@latticexyz/config/node";
|
4
|
-
import { Store as StoreConfig } from "@latticexyz/store";
|
5
|
-
import { tablegen } from "@latticexyz/store/codegen";
|
6
|
-
import { getRemappings, getSrcDirectory } from "@latticexyz/common/foundry";
|
7
|
-
|
8
|
-
type Options = {
|
9
|
-
configPath?: string;
|
10
|
-
};
|
11
|
-
|
12
|
-
const commandModule: CommandModule<Options, Options> = {
|
13
|
-
command: "tablegen",
|
14
|
-
|
15
|
-
describe: "Autogenerate MUD Store table libraries based on the config file",
|
16
|
-
|
17
|
-
builder(yargs) {
|
18
|
-
return yargs.options({
|
19
|
-
configPath: { type: "string", desc: "Path to the MUD config file" },
|
20
|
-
});
|
21
|
-
},
|
22
|
-
|
23
|
-
async handler({ configPath }) {
|
24
|
-
const config = (await loadConfig(configPath)) as StoreConfig;
|
25
|
-
const srcDir = await getSrcDirectory();
|
26
|
-
const remappings = await getRemappings();
|
27
|
-
|
28
|
-
await tablegen(config, path.join(srcDir, config.codegen.outputDirectory), remappings);
|
29
|
-
|
30
|
-
process.exit(0);
|
31
|
-
},
|
32
|
-
};
|
33
|
-
|
34
|
-
export default commandModule;
|
package/src/commands/test.ts
DELETED
@@ -1,65 +0,0 @@
|
|
1
|
-
import type { CommandModule, InferredOptionTypes, Options } from "yargs";
|
2
|
-
import { anvil, forge, getRpcUrl } from "@latticexyz/common/foundry";
|
3
|
-
import chalk from "chalk";
|
4
|
-
import { deployOptions, runDeploy } from "../runDeploy";
|
5
|
-
|
6
|
-
const testOptions = {
|
7
|
-
...deployOptions,
|
8
|
-
port: { type: "number", description: "Port to run internal node for fork testing on", default: 4242 },
|
9
|
-
worldAddress: {
|
10
|
-
type: "string",
|
11
|
-
description:
|
12
|
-
"Address of an existing world contract. If provided, deployment is skipped and the RPC provided in the foundry.toml is used for fork testing.",
|
13
|
-
},
|
14
|
-
forgeOptions: { type: "string", description: "Options to pass to forge test" },
|
15
|
-
} as const satisfies Record<string, Options>;
|
16
|
-
|
17
|
-
type TestOptions = InferredOptionTypes<typeof testOptions>;
|
18
|
-
|
19
|
-
const commandModule: CommandModule<typeof testOptions, TestOptions> = {
|
20
|
-
command: "test",
|
21
|
-
|
22
|
-
describe: "Run tests in MUD contracts",
|
23
|
-
|
24
|
-
builder(yargs) {
|
25
|
-
return yargs.options(testOptions);
|
26
|
-
},
|
27
|
-
|
28
|
-
async handler(opts) {
|
29
|
-
// Start an internal anvil process if no world address is provided
|
30
|
-
if (!opts.worldAddress) {
|
31
|
-
const anvilArgs = ["--block-base-fee-per-gas", "0", "--port", String(opts.port)];
|
32
|
-
anvil(anvilArgs);
|
33
|
-
}
|
34
|
-
|
35
|
-
const forkRpc = opts.worldAddress ? await getRpcUrl(opts.profile) : `http://127.0.0.1:${opts.port}`;
|
36
|
-
|
37
|
-
const worldAddress =
|
38
|
-
opts.worldAddress ??
|
39
|
-
(
|
40
|
-
await runDeploy({
|
41
|
-
...opts,
|
42
|
-
saveDeployment: false,
|
43
|
-
rpc: forkRpc,
|
44
|
-
})
|
45
|
-
).address;
|
46
|
-
|
47
|
-
console.log(chalk.blue("World address", worldAddress));
|
48
|
-
|
49
|
-
const userOptions = opts.forgeOptions?.replaceAll("\\", "").split(" ") ?? [];
|
50
|
-
try {
|
51
|
-
await forge(["test", "--fork-url", forkRpc, ...userOptions], {
|
52
|
-
profile: opts.profile,
|
53
|
-
env: {
|
54
|
-
WORLD_ADDRESS: worldAddress,
|
55
|
-
},
|
56
|
-
});
|
57
|
-
process.exit(0);
|
58
|
-
} catch (e) {
|
59
|
-
console.error(e);
|
60
|
-
process.exit(1);
|
61
|
-
}
|
62
|
-
},
|
63
|
-
};
|
64
|
-
|
65
|
-
export default commandModule;
|
package/src/commands/trace.ts
DELETED
@@ -1,120 +0,0 @@
|
|
1
|
-
import { existsSync, readFileSync } from "fs";
|
2
|
-
import type { CommandModule } from "yargs";
|
3
|
-
import { ethers } from "ethers";
|
4
|
-
|
5
|
-
import { loadConfig } from "@latticexyz/config/node";
|
6
|
-
import { MUDError } from "@latticexyz/common/errors";
|
7
|
-
import { cast, getRpcUrl, getSrcDirectory } from "@latticexyz/common/foundry";
|
8
|
-
import { resolveWorldConfig } from "@latticexyz/world/internal";
|
9
|
-
import IBaseWorldAbi from "@latticexyz/world/out/IBaseWorld.sol/IBaseWorld.abi.json" assert { type: "json" };
|
10
|
-
import worldConfig from "@latticexyz/world/mud.config";
|
11
|
-
import { resourceToHex } from "@latticexyz/common";
|
12
|
-
import { getExistingContracts } from "../utils/getExistingContracts";
|
13
|
-
import { createClient, http } from "viem";
|
14
|
-
import { getChainId } from "viem/actions";
|
15
|
-
import { World as WorldConfig } from "@latticexyz/world";
|
16
|
-
import { worldToV1 } from "@latticexyz/world/config/v2";
|
17
|
-
|
18
|
-
// TODO account for multiple namespaces (https://github.com/latticexyz/mud/issues/994)
|
19
|
-
const systemsTableId = resourceToHex({
|
20
|
-
type: "system",
|
21
|
-
namespace: worldConfig.namespace,
|
22
|
-
name: worldConfig.tables.world__Systems.name,
|
23
|
-
});
|
24
|
-
|
25
|
-
type Options = {
|
26
|
-
tx: string;
|
27
|
-
worldAddress?: string;
|
28
|
-
configPath?: string;
|
29
|
-
profile?: string;
|
30
|
-
srcDir?: string;
|
31
|
-
rpc?: string;
|
32
|
-
};
|
33
|
-
|
34
|
-
const commandModule: CommandModule<Options, Options> = {
|
35
|
-
command: "trace",
|
36
|
-
|
37
|
-
describe: "Display the trace of a transaction",
|
38
|
-
|
39
|
-
builder(yargs) {
|
40
|
-
return yargs.options({
|
41
|
-
tx: { type: "string", required: true, description: "Transaction hash to replay" },
|
42
|
-
worldAddress: {
|
43
|
-
type: "string",
|
44
|
-
description: "World contract address. Defaults to the value from worlds.json, based on rpc's chainId",
|
45
|
-
},
|
46
|
-
configPath: { type: "string", description: "Path to the MUD config file" },
|
47
|
-
profile: { type: "string", description: "The foundry profile to use" },
|
48
|
-
srcDir: { type: "string", description: "Source directory. Defaults to foundry src directory." },
|
49
|
-
rpc: { type: "string", description: "json rpc endpoint. Defaults to foundry's configured eth_rpc_url" },
|
50
|
-
});
|
51
|
-
},
|
52
|
-
|
53
|
-
async handler(args) {
|
54
|
-
args.profile ??= process.env.FOUNDRY_PROFILE;
|
55
|
-
const { profile } = args;
|
56
|
-
args.srcDir ??= await getSrcDirectory(profile);
|
57
|
-
args.rpc ??= await getRpcUrl(profile);
|
58
|
-
const { tx, configPath, srcDir, rpc } = args;
|
59
|
-
|
60
|
-
const existingContracts = getExistingContracts(srcDir);
|
61
|
-
|
62
|
-
// Load the config
|
63
|
-
const configV2 = (await loadConfig(configPath)) as WorldConfig;
|
64
|
-
const mudConfig = worldToV1(configV2);
|
65
|
-
|
66
|
-
const resolvedConfig = resolveWorldConfig(
|
67
|
-
mudConfig,
|
68
|
-
existingContracts.map(({ basename }) => basename),
|
69
|
-
);
|
70
|
-
|
71
|
-
// Get worldAddress either from args or from worldsFile
|
72
|
-
const worldAddress = args.worldAddress ?? (await getWorldAddress(mudConfig.worldsFile, rpc));
|
73
|
-
|
74
|
-
// Create World contract instance from deployed address
|
75
|
-
const provider = new ethers.providers.StaticJsonRpcProvider(rpc);
|
76
|
-
const WorldContract = new ethers.Contract(worldAddress, IBaseWorldAbi, provider);
|
77
|
-
|
78
|
-
// TODO account for multiple namespaces (https://github.com/latticexyz/mud/issues/994)
|
79
|
-
const namespace = mudConfig.namespace;
|
80
|
-
const names = Object.values(resolvedConfig.systems).map(({ name }) => name);
|
81
|
-
|
82
|
-
// Fetch system table field layout from chain
|
83
|
-
const systemTableFieldLayout = await WorldContract.getFieldLayout(systemsTableId);
|
84
|
-
const labels: { name: string; address: string }[] = [];
|
85
|
-
for (const name of names) {
|
86
|
-
const systemSelector = resourceToHex({ type: "system", namespace, name });
|
87
|
-
// Get the first field of `Systems` table (the table maps system name to its address and other data)
|
88
|
-
const address = await WorldContract.getField(systemsTableId, [systemSelector], 0, systemTableFieldLayout);
|
89
|
-
labels.push({ name, address });
|
90
|
-
}
|
91
|
-
|
92
|
-
const result = await cast([
|
93
|
-
"run",
|
94
|
-
"--label",
|
95
|
-
`${worldAddress}:World`,
|
96
|
-
...labels.map(({ name, address }) => ["--label", `${address}:${name}`]).flat(),
|
97
|
-
`${tx}`,
|
98
|
-
]);
|
99
|
-
console.log(result);
|
100
|
-
|
101
|
-
process.exit(0);
|
102
|
-
},
|
103
|
-
};
|
104
|
-
|
105
|
-
export default commandModule;
|
106
|
-
|
107
|
-
async function getWorldAddress(worldsFile: string, rpc: string) {
|
108
|
-
if (existsSync(worldsFile)) {
|
109
|
-
const client = createClient({ transport: http(rpc) });
|
110
|
-
const chainId = await getChainId(client);
|
111
|
-
const deploys = JSON.parse(readFileSync(worldsFile, "utf-8"));
|
112
|
-
|
113
|
-
if (!deploys[chainId]) {
|
114
|
-
throw new MUDError(`chainId ${chainId} is missing in worldsFile "${worldsFile}"`);
|
115
|
-
}
|
116
|
-
return deploys[chainId].address as string;
|
117
|
-
} else {
|
118
|
-
throw new MUDError("worldAddress is not specified and worldsFile is missing");
|
119
|
-
}
|
120
|
-
}
|