@latticexyz/cli 2.0.0-skystrife-playtest-9e9511d4 → 2.0.0-transaction-context-324984c5
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/chunk-22IIKR4S.js +4 -0
- package/dist/chunk-22IIKR4S.js.map +1 -0
- package/dist/commands-3JV3U43E.js +27 -0
- package/dist/commands-3JV3U43E.js.map +1 -0
- package/dist/errors-XGN6V2Y3.js +2 -0
- package/dist/errors-XGN6V2Y3.js.map +1 -0
- package/dist/index.js +0 -1
- package/dist/mud.js +1 -14
- package/dist/mud.js.map +1 -1
- package/package.json +20 -13
- package/src/build.ts +44 -0
- package/src/commands/build.ts +36 -0
- package/src/commands/deploy.ts +7 -30
- package/src/commands/dev-contracts.ts +76 -128
- package/src/commands/index.ts +2 -0
- package/src/commands/set-version.ts +23 -61
- package/src/commands/tablegen.ts +3 -2
- package/src/commands/test.ts +30 -36
- package/src/commands/trace.ts +13 -6
- package/src/commands/worldgen.ts +1 -1
- package/src/common.ts +1 -0
- package/src/debug.ts +10 -0
- package/src/deploy/common.ts +76 -0
- package/src/deploy/configToTables.ts +68 -0
- package/src/deploy/create2/README.md +9 -0
- package/src/deploy/create2/deployment.json +7 -0
- package/src/deploy/debug.ts +10 -0
- package/src/deploy/deploy.ts +116 -0
- package/src/deploy/deployWorld.ts +37 -0
- package/src/deploy/ensureContract.ts +61 -0
- package/src/deploy/ensureContractsDeployed.ts +25 -0
- package/src/deploy/ensureDeployer.ts +36 -0
- package/src/deploy/ensureFunctions.ts +86 -0
- package/src/deploy/ensureModules.ts +73 -0
- package/src/deploy/ensureNamespaceOwner.ts +71 -0
- package/src/deploy/ensureSystems.ts +162 -0
- package/src/deploy/ensureTables.ts +65 -0
- package/src/deploy/ensureWorldFactory.ts +118 -0
- package/src/deploy/getFunctions.ts +58 -0
- package/src/deploy/getResourceAccess.ts +51 -0
- package/src/deploy/getResourceIds.ts +31 -0
- package/src/deploy/getSystems.ts +48 -0
- package/src/deploy/getTableValue.ts +30 -0
- package/src/deploy/getTables.ts +59 -0
- package/src/deploy/getWorldDeploy.ts +39 -0
- package/src/deploy/logsToWorldDeploy.ts +49 -0
- package/src/deploy/resolveConfig.ts +151 -0
- package/src/deploy/resourceLabel.ts +3 -0
- package/src/index.ts +1 -1
- package/src/mud.ts +37 -31
- package/src/mudPackages.ts +24 -0
- package/src/runDeploy.ts +131 -0
- package/src/utils/modules/constants.ts +26 -0
- package/src/utils/utils/getContractData.ts +32 -0
- package/src/utils/utils/postDeploy.ts +25 -0
- package/dist/chunk-OJAPOMSC.js +0 -11
- package/dist/chunk-OJAPOMSC.js.map +0 -1
- package/src/utils/deploy.ts +0 -620
- package/src/utils/deployHandler.ts +0 -93
- package/src/utils/getChainId.ts +0 -10
- package/src/utils/index.ts +0 -6
@@ -1,166 +1,114 @@
|
|
1
|
-
import type { CommandModule } from "yargs";
|
2
|
-
import { anvil,
|
1
|
+
import type { CommandModule, InferredOptionTypes } from "yargs";
|
2
|
+
import { anvil, getScriptDirectory, getSrcDirectory } from "@latticexyz/common/foundry";
|
3
3
|
import chalk from "chalk";
|
4
4
|
import chokidar from "chokidar";
|
5
5
|
import { loadConfig, resolveConfigPath } from "@latticexyz/config/node";
|
6
6
|
import { StoreConfig } from "@latticexyz/store";
|
7
|
-
import { tablegen } from "@latticexyz/store/codegen";
|
8
7
|
import path from "path";
|
9
|
-
import { debounce } from "throttle-debounce";
|
10
|
-
import { worldgenHandler } from "./worldgen";
|
11
8
|
import { WorldConfig } from "@latticexyz/world";
|
12
|
-
import { deployHandler, logError, printMUD } from "../utils";
|
13
9
|
import { homedir } from "os";
|
14
10
|
import { rmSync } from "fs";
|
15
|
-
import {
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
11
|
+
import { deployOptions, runDeploy } from "../runDeploy";
|
12
|
+
import { BehaviorSubject, debounceTime, exhaustMap, filter } from "rxjs";
|
13
|
+
import { Address } from "viem";
|
14
|
+
import { isDefined } from "@latticexyz/common/utils";
|
15
|
+
|
16
|
+
const devOptions = {
|
17
|
+
rpc: deployOptions.rpc,
|
18
|
+
configPath: deployOptions.configPath,
|
19
|
+
alwaysRunPostDeploy: deployOptions.alwaysRunPostDeploy,
|
20
|
+
worldAddress: deployOptions.worldAddress,
|
20
21
|
};
|
21
22
|
|
22
|
-
const commandModule: CommandModule<
|
23
|
+
const commandModule: CommandModule<typeof devOptions, InferredOptionTypes<typeof devOptions>> = {
|
23
24
|
command: "dev-contracts",
|
24
25
|
|
25
26
|
describe: "Start a development server for MUD contracts",
|
26
27
|
|
27
28
|
builder(yargs) {
|
28
|
-
return yargs.options(
|
29
|
-
rpc: {
|
30
|
-
type: "string",
|
31
|
-
decs: "RPC endpoint of the development node. If none is provided, an anvil instance is spawned in the background on port 8545.",
|
32
|
-
},
|
33
|
-
configPath: {
|
34
|
-
type: "string",
|
35
|
-
decs: "Path to MUD config",
|
36
|
-
},
|
37
|
-
});
|
29
|
+
return yargs.options(devOptions);
|
38
30
|
},
|
39
31
|
|
40
|
-
async handler(
|
41
|
-
|
42
|
-
await
|
43
|
-
|
44
|
-
const
|
45
|
-
const configPath = args.configPath ?? (await resolveConfigPath(args.configPath));
|
46
|
-
const srcDirectory = await getSrcDirectory();
|
47
|
-
const scriptDirectory = await getScriptDirectory();
|
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();
|
48
37
|
const initialConfig = (await loadConfig(configPath)) as StoreConfig & WorldConfig;
|
49
38
|
|
50
|
-
// Initial run of all codegen steps before starting anvil
|
51
|
-
// (so clients can wait for everything to be ready before starting)
|
52
|
-
await handleConfigChange(initialConfig);
|
53
|
-
await handleContractsChange(initialConfig);
|
54
|
-
|
55
39
|
// Start an anvil instance in the background if no RPC url is provided
|
56
|
-
if (!
|
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
|
57
46
|
console.log(chalk.gray("Cleaning devnode cache"));
|
58
47
|
const userHomeDir = homedir();
|
59
48
|
rmSync(path.join(userHomeDir, ".foundry", "anvil", "tmp"), { recursive: true, force: true });
|
60
49
|
|
61
50
|
const anvilArgs = ["--block-time", "1", "--block-base-fee-per-gas", "0"];
|
62
51
|
anvil(anvilArgs);
|
52
|
+
rpc = "http://127.0.0.1:8545";
|
63
53
|
}
|
64
54
|
|
65
|
-
const changedSinceLastHandled = {
|
66
|
-
config: false,
|
67
|
-
contracts: false,
|
68
|
-
};
|
69
|
-
|
70
|
-
const changeInProgress = {
|
71
|
-
current: false,
|
72
|
-
};
|
73
|
-
|
74
55
|
// Watch for changes
|
75
|
-
const
|
76
|
-
|
56
|
+
const lastChange$ = new BehaviorSubject<number>(Date.now());
|
57
|
+
chokidar.watch([configPath, srcDir, scriptDir], { ignoreInitial: true }).on("all", async (_, updatePath) => {
|
77
58
|
if (updatePath.includes(configPath)) {
|
78
|
-
|
79
|
-
|
80
|
-
// listening to changes in the codegen directory to avoid an infinite loop
|
81
|
-
changedSinceLastHandled.contracts = true;
|
59
|
+
console.log(chalk.blue("Config changed, queuing deploy…"));
|
60
|
+
lastChange$.next(Date.now());
|
82
61
|
}
|
83
|
-
|
84
|
-
if (updatePath.includes(srcDirectory) || updatePath.includes(scriptDirectory)) {
|
62
|
+
if (updatePath.includes(srcDir) || updatePath.includes(scriptDir)) {
|
85
63
|
// Ignore changes to codegen files to avoid an infinite loop
|
86
|
-
if (updatePath.includes(initialConfig.codegenDirectory))
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
// Trigger debounced onChange
|
91
|
-
handleChange();
|
92
|
-
});
|
93
|
-
|
94
|
-
const handleChange = debounce(100, async () => {
|
95
|
-
// Avoid handling changes multiple times in parallel
|
96
|
-
if (changeInProgress.current) return;
|
97
|
-
changeInProgress.current = true;
|
98
|
-
|
99
|
-
// Reset dirty flags
|
100
|
-
const { config, contracts } = changedSinceLastHandled;
|
101
|
-
changedSinceLastHandled.config = false;
|
102
|
-
changedSinceLastHandled.contracts = false;
|
103
|
-
|
104
|
-
try {
|
105
|
-
// Load latest config
|
106
|
-
const mudConfig = (await loadConfig(configPath)) as StoreConfig & WorldConfig;
|
107
|
-
|
108
|
-
// Handle changes
|
109
|
-
if (config) await handleConfigChange(mudConfig);
|
110
|
-
if (contracts) await handleContractsChange(mudConfig);
|
111
|
-
|
112
|
-
await deploy();
|
113
|
-
} catch (error) {
|
114
|
-
console.error(chalk.red("MUD dev-contracts watcher failed to deploy config or contracts changes\n"));
|
115
|
-
logError(error);
|
116
|
-
}
|
117
|
-
|
118
|
-
changeInProgress.current = false;
|
119
|
-
if (changedSinceLastHandled.config || changedSinceLastHandled.contracts) {
|
120
|
-
console.log("Detected change while handling the previous change");
|
121
|
-
handleChange();
|
64
|
+
if (!updatePath.includes(initialConfig.codegenDirectory)) {
|
65
|
+
console.log(chalk.blue("Contracts changed, queuing deploy…"));
|
66
|
+
lastChange$.next(Date.now());
|
67
|
+
}
|
122
68
|
}
|
123
|
-
|
124
|
-
printMUD();
|
125
|
-
console.log("MUD watching for changes...");
|
126
69
|
});
|
127
70
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
//
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
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
|
+
skipBuild: false,
|
87
|
+
printConfig: false,
|
88
|
+
profile: undefined,
|
89
|
+
saveDeployment: true,
|
90
|
+
worldAddress,
|
91
|
+
srcDir,
|
92
|
+
salt: "0x",
|
93
|
+
});
|
94
|
+
worldAddress = deploy.address;
|
95
|
+
// if there were changes while we were deploying, trigger it again
|
96
|
+
if (lastChange < lastChange$.value) {
|
97
|
+
lastChange$.next(lastChange$.value);
|
98
|
+
} else {
|
99
|
+
console.log(chalk.gray("\nWaiting for file changes…\n"));
|
100
|
+
}
|
101
|
+
return deploy;
|
102
|
+
} catch (error) {
|
103
|
+
console.error(chalk.bgRed(chalk.whiteBright("\n Error while attempting deploy \n")));
|
104
|
+
console.error(error);
|
105
|
+
console.log(chalk.gray("\nWaiting for file changes…\n"));
|
106
|
+
}
|
107
|
+
}),
|
108
|
+
filter(isDefined)
|
109
|
+
);
|
110
|
+
|
111
|
+
deploys$.subscribe();
|
164
112
|
},
|
165
113
|
};
|
166
114
|
|
package/src/commands/index.ts
CHANGED
@@ -3,6 +3,7 @@ import { CommandModule } from "yargs";
|
|
3
3
|
import gasReport from "@latticexyz/gas-report";
|
4
4
|
import abiTs from "@latticexyz/abi-ts";
|
5
5
|
|
6
|
+
import build from "./build";
|
6
7
|
import devnode from "./devnode";
|
7
8
|
import faucet from "./faucet";
|
8
9
|
import hello from "./hello";
|
@@ -16,6 +17,7 @@ import devContracts from "./dev-contracts";
|
|
16
17
|
|
17
18
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Each command has different options
|
18
19
|
export const commands: CommandModule<any, any>[] = [
|
20
|
+
build,
|
19
21
|
deploy,
|
20
22
|
devnode,
|
21
23
|
faucet,
|
@@ -1,11 +1,12 @@
|
|
1
1
|
import chalk from "chalk";
|
2
|
-
import {
|
2
|
+
import { readFileSync, writeFileSync } from "fs";
|
3
3
|
import path from "path";
|
4
4
|
import type { CommandModule } from "yargs";
|
5
5
|
import { MUDError } from "@latticexyz/common/errors";
|
6
6
|
import { logError } from "../utils/errors";
|
7
7
|
import localPackageJson from "../../package.json" assert { type: "json" };
|
8
8
|
import glob from "glob";
|
9
|
+
import { mudPackages } from "../mudPackages";
|
9
10
|
|
10
11
|
type Options = {
|
11
12
|
backup?: boolean;
|
@@ -17,9 +18,6 @@ type Options = {
|
|
17
18
|
link?: string;
|
18
19
|
};
|
19
20
|
|
20
|
-
const BACKUP_FILE = ".mudbackup";
|
21
|
-
const MUD_PREFIX = "@latticexyz";
|
22
|
-
|
23
21
|
const commandModule: CommandModule<Options, Options> = {
|
24
22
|
command: "set-version",
|
25
23
|
|
@@ -27,12 +25,6 @@ const commandModule: CommandModule<Options, Options> = {
|
|
27
25
|
|
28
26
|
builder(yargs) {
|
29
27
|
return yargs.options({
|
30
|
-
backup: { type: "boolean", description: `Back up the current MUD versions to "${BACKUP_FILE}"` },
|
31
|
-
force: {
|
32
|
-
type: "boolean",
|
33
|
-
description: `Backup fails if a "${BACKUP_FILE}" file is found, unless --force is provided`,
|
34
|
-
},
|
35
|
-
restore: { type: "boolean", description: `Restore the previous MUD versions from "${BACKUP_FILE}"` },
|
36
28
|
mudVersion: { alias: "v", type: "string", description: "Set MUD to the given version" },
|
37
29
|
tag: {
|
38
30
|
alias: "t",
|
@@ -64,8 +56,11 @@ const commandModule: CommandModule<Options, Options> = {
|
|
64
56
|
throw new MUDError(`These options are mutually exclusive: ${mutuallyExclusiveOptions.join(", ")}`);
|
65
57
|
}
|
66
58
|
|
59
|
+
// If the --link flag is not set, we call resolveVersion to get the version
|
67
60
|
// Resolve the version number from available options like `tag` or `commit`
|
68
|
-
|
61
|
+
if (!options.link) {
|
62
|
+
options.mudVersion = await resolveVersion(options);
|
63
|
+
}
|
69
64
|
|
70
65
|
// Update all package.json below the current working directory (except in node_modules)
|
71
66
|
const packageJsons = glob.sync("**/package.json").filter((p) => !p.includes("node_modules"));
|
@@ -117,63 +112,39 @@ async function resolveVersion(options: Options) {
|
|
117
112
|
}
|
118
113
|
|
119
114
|
function updatePackageJson(filePath: string, options: Options): { workspaces?: string[] } {
|
120
|
-
const {
|
121
|
-
let {
|
122
|
-
|
123
|
-
const backupFilePath = path.join(path.dirname(filePath), BACKUP_FILE);
|
124
|
-
const backupFileExists = existsSync(backupFilePath);
|
125
|
-
|
126
|
-
// Create a backup file for previous MUD versions by default if linking to local MUD
|
127
|
-
if (link && !backupFileExists) backup = true;
|
128
|
-
|
129
|
-
// If `backup` is true and force not set, check if a backup file already exists and throw an error if it does
|
130
|
-
if (backup && !force && backupFileExists) {
|
131
|
-
throw new MUDError(
|
132
|
-
`A backup file already exists at ${backupFilePath}.\nUse --force to overwrite it or --restore to restore it.`
|
133
|
-
);
|
134
|
-
}
|
115
|
+
const { link } = options;
|
116
|
+
let { mudVersion } = options;
|
135
117
|
|
136
118
|
const packageJson = readPackageJson(filePath);
|
137
|
-
|
138
|
-
// Load .mudbackup if `restore` is true
|
139
|
-
const backupJson = restore ? readPackageJson(backupFilePath) : undefined;
|
119
|
+
const mudPackageNames = Object.keys(mudPackages);
|
140
120
|
|
141
121
|
// Find all MUD dependencies
|
142
122
|
const mudDependencies: Record<string, string> = {};
|
143
|
-
for (const
|
144
|
-
if (
|
145
|
-
mudDependencies[
|
123
|
+
for (const packageName in packageJson.dependencies) {
|
124
|
+
if (mudPackageNames.includes(packageName)) {
|
125
|
+
mudDependencies[packageName] = packageJson.dependencies[packageName];
|
146
126
|
}
|
147
127
|
}
|
148
128
|
|
149
129
|
// Find all MUD devDependencies
|
150
130
|
const mudDevDependencies: Record<string, string> = {};
|
151
|
-
for (const
|
152
|
-
if (
|
153
|
-
mudDevDependencies[
|
131
|
+
for (const packageName in packageJson.devDependencies) {
|
132
|
+
if (mudPackageNames.includes(packageName)) {
|
133
|
+
mudDevDependencies[packageName] = packageJson.devDependencies[packageName];
|
154
134
|
}
|
155
135
|
}
|
156
136
|
|
157
|
-
// Back up the current dependencies if `backup` is true
|
158
|
-
if (backup) {
|
159
|
-
writeFileSync(
|
160
|
-
backupFilePath,
|
161
|
-
JSON.stringify({ dependencies: mudDependencies, devDependencies: mudDevDependencies }, null, 2)
|
162
|
-
);
|
163
|
-
console.log(chalk.green(`Backed up MUD dependencies from ${filePath} to ${backupFilePath}`));
|
164
|
-
}
|
165
|
-
|
166
137
|
// Update the dependencies
|
167
|
-
for (const
|
168
|
-
if (
|
169
|
-
packageJson.dependencies[
|
138
|
+
for (const packageName in packageJson.dependencies) {
|
139
|
+
if (mudPackageNames.includes(packageName)) {
|
140
|
+
packageJson.dependencies[packageName] = resolveMudVersion(packageName, "dependencies");
|
170
141
|
}
|
171
142
|
}
|
172
143
|
|
173
144
|
// Update the devDependencies
|
174
|
-
for (const
|
175
|
-
if (
|
176
|
-
packageJson.devDependencies[
|
145
|
+
for (const packageName in packageJson.devDependencies) {
|
146
|
+
if (mudPackageNames.includes(packageName)) {
|
147
|
+
packageJson.devDependencies[packageName] = resolveMudVersion(packageName, "devDependencies");
|
177
148
|
}
|
178
149
|
}
|
179
150
|
|
@@ -184,17 +155,9 @@ function updatePackageJson(filePath: string, options: Options): { workspaces?: s
|
|
184
155
|
logComparison(mudDependencies, packageJson.dependencies);
|
185
156
|
logComparison(mudDevDependencies, packageJson.devDependencies);
|
186
157
|
|
187
|
-
// Remove the backup file if `restore` is true and `backup` is false
|
188
|
-
// because the old backup file is no longer needed
|
189
|
-
if (restore && !backup) {
|
190
|
-
rmSync(backupFilePath);
|
191
|
-
console.log(chalk.green(`Cleaned up ${backupFilePath}`));
|
192
|
-
}
|
193
|
-
|
194
158
|
return packageJson;
|
195
159
|
|
196
160
|
function resolveMudVersion(key: string, type: "dependencies" | "devDependencies") {
|
197
|
-
if (restore && backupJson) return backupJson[type][key];
|
198
161
|
if (link) mudVersion = resolveLinkPath(filePath, link, key);
|
199
162
|
if (!mudVersion) return packageJson[type][key];
|
200
163
|
return mudVersion;
|
@@ -225,10 +188,9 @@ function logComparison(prev: Record<string, string>, curr: Record<string, string
|
|
225
188
|
/**
|
226
189
|
* Returns path of the package to link, given a path to a local MUD clone and a package
|
227
190
|
*/
|
228
|
-
function resolveLinkPath(packageJsonPath: string, mudLinkPath: string,
|
229
|
-
const pkgName = pkg.replace(MUD_PREFIX, "");
|
191
|
+
function resolveLinkPath(packageJsonPath: string, mudLinkPath: string, packageName: string) {
|
230
192
|
const packageJsonToRootPath = path.relative(path.dirname(packageJsonPath), process.cwd());
|
231
|
-
const linkPath = path.join(packageJsonToRootPath, mudLinkPath,
|
193
|
+
const linkPath = path.join(packageJsonToRootPath, mudLinkPath, mudPackages[packageName].localPath);
|
232
194
|
return "link:" + linkPath;
|
233
195
|
}
|
234
196
|
|
package/src/commands/tablegen.ts
CHANGED
@@ -3,7 +3,7 @@ import type { CommandModule } from "yargs";
|
|
3
3
|
import { loadConfig } from "@latticexyz/config/node";
|
4
4
|
import { StoreConfig } from "@latticexyz/store";
|
5
5
|
import { tablegen } from "@latticexyz/store/codegen";
|
6
|
-
import { getSrcDirectory } from "@latticexyz/common/foundry";
|
6
|
+
import { getRemappings, getSrcDirectory } from "@latticexyz/common/foundry";
|
7
7
|
|
8
8
|
type Options = {
|
9
9
|
configPath?: string;
|
@@ -23,8 +23,9 @@ const commandModule: CommandModule<Options, Options> = {
|
|
23
23
|
async handler({ configPath }) {
|
24
24
|
const config = (await loadConfig(configPath)) as StoreConfig;
|
25
25
|
const srcDir = await getSrcDirectory();
|
26
|
+
const remappings = await getRemappings();
|
26
27
|
|
27
|
-
await tablegen(config, path.join(srcDir, config.codegenDirectory));
|
28
|
+
await tablegen(config, path.join(srcDir, config.codegenDirectory), remappings);
|
28
29
|
|
29
30
|
process.exit(0);
|
30
31
|
},
|
package/src/commands/test.ts
CHANGED
@@ -1,70 +1,64 @@
|
|
1
|
-
import type { CommandModule } from "yargs";
|
1
|
+
import type { CommandModule, InferredOptionTypes, Options } from "yargs";
|
2
2
|
import { anvil, forge, getRpcUrl } from "@latticexyz/common/foundry";
|
3
3
|
import chalk from "chalk";
|
4
|
-
import {
|
5
|
-
import { yDeployOptions } from "./deploy";
|
6
|
-
import { deployHandler, DeployOptions } from "../utils";
|
4
|
+
import { deployOptions, runDeploy } from "../runDeploy";
|
7
5
|
|
8
|
-
|
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>;
|
9
16
|
|
10
|
-
|
17
|
+
type TestOptions = InferredOptionTypes<typeof testOptions>;
|
11
18
|
|
12
|
-
const commandModule: CommandModule<
|
19
|
+
const commandModule: CommandModule<typeof testOptions, TestOptions> = {
|
13
20
|
command: "test",
|
14
21
|
|
15
22
|
describe: "Run tests in MUD contracts",
|
16
23
|
|
17
24
|
builder(yargs) {
|
18
|
-
return yargs.options(
|
19
|
-
...yDeployOptions,
|
20
|
-
port: { type: "number", description: "Port to run internal node for fork testing on", default: 4242 },
|
21
|
-
worldAddress: {
|
22
|
-
type: "string",
|
23
|
-
description:
|
24
|
-
"Address of an existing world contract. If provided, deployment is skipped and the RPC provided in the foundry.toml is used for fork testing.",
|
25
|
-
},
|
26
|
-
forgeOptions: { type: "string", description: "Options to pass to forge test" },
|
27
|
-
});
|
25
|
+
return yargs.options(testOptions);
|
28
26
|
},
|
29
27
|
|
30
|
-
async handler(
|
28
|
+
async handler(opts) {
|
31
29
|
// Start an internal anvil process if no world address is provided
|
32
|
-
if (!
|
33
|
-
const anvilArgs = ["--block-base-fee-per-gas", "0", "--port", String(
|
30
|
+
if (!opts.worldAddress) {
|
31
|
+
const anvilArgs = ["--block-base-fee-per-gas", "0", "--port", String(opts.port)];
|
34
32
|
anvil(anvilArgs);
|
35
33
|
}
|
36
34
|
|
37
|
-
const forkRpc =
|
35
|
+
const forkRpc = opts.worldAddress ? await getRpcUrl(opts.profile) : `http://127.0.0.1:${opts.port}`;
|
38
36
|
|
39
37
|
const worldAddress =
|
40
|
-
|
38
|
+
opts.worldAddress ??
|
41
39
|
(
|
42
|
-
await
|
43
|
-
...
|
40
|
+
await runDeploy({
|
41
|
+
...opts,
|
44
42
|
saveDeployment: false,
|
45
43
|
rpc: forkRpc,
|
46
44
|
})
|
47
|
-
).
|
45
|
+
).address;
|
48
46
|
|
49
47
|
console.log(chalk.blue("World address", worldAddress));
|
50
48
|
|
51
|
-
|
52
|
-
writeFileSync(WORLD_ADDRESS_FILE, worldAddress);
|
53
|
-
|
54
|
-
const userOptions = args.forgeOptions?.replaceAll("\\", "").split(" ") ?? [];
|
49
|
+
const userOptions = opts.forgeOptions?.replaceAll("\\", "").split(" ") ?? [];
|
55
50
|
try {
|
56
|
-
|
57
|
-
profile:
|
51
|
+
await forge(["test", "--fork-url", forkRpc, ...userOptions], {
|
52
|
+
profile: opts.profile,
|
53
|
+
env: {
|
54
|
+
WORLD_ADDRESS: worldAddress,
|
55
|
+
},
|
58
56
|
});
|
59
|
-
|
57
|
+
process.exit(0);
|
60
58
|
} catch (e) {
|
61
59
|
console.error(e);
|
62
|
-
rmSync(WORLD_ADDRESS_FILE);
|
63
60
|
process.exit(1);
|
64
61
|
}
|
65
|
-
|
66
|
-
rmSync(WORLD_ADDRESS_FILE);
|
67
|
-
process.exit(0);
|
68
62
|
},
|
69
63
|
};
|
70
64
|
|
package/src/commands/trace.ts
CHANGED
@@ -8,12 +8,18 @@ import { cast, getRpcUrl, getSrcDirectory } from "@latticexyz/common/foundry";
|
|
8
8
|
import { StoreConfig } from "@latticexyz/store";
|
9
9
|
import { resolveWorldConfig, WorldConfig } from "@latticexyz/world";
|
10
10
|
import IBaseWorldAbi from "@latticexyz/world/out/IBaseWorld.sol/IBaseWorld.abi.json" assert { type: "json" };
|
11
|
-
import worldConfig from "@latticexyz/world/mud.config
|
12
|
-
import {
|
13
|
-
import {
|
11
|
+
import worldConfig from "@latticexyz/world/mud.config";
|
12
|
+
import { resourceToHex } from "@latticexyz/common";
|
13
|
+
import { getExistingContracts } from "../utils/getExistingContracts";
|
14
|
+
import { createClient, http } from "viem";
|
15
|
+
import { getChainId } from "viem/actions";
|
14
16
|
|
15
17
|
// TODO account for multiple namespaces (https://github.com/latticexyz/mud/issues/994)
|
16
|
-
const systemsTableId =
|
18
|
+
const systemsTableId = resourceToHex({
|
19
|
+
type: "system",
|
20
|
+
namespace: worldConfig.namespace,
|
21
|
+
name: worldConfig.tables.Systems.name,
|
22
|
+
});
|
17
23
|
|
18
24
|
type Options = {
|
19
25
|
tx: string;
|
@@ -75,7 +81,7 @@ const commandModule: CommandModule<Options, Options> = {
|
|
75
81
|
const systemTableFieldLayout = await WorldContract.getFieldLayout(systemsTableId);
|
76
82
|
const labels: { name: string; address: string }[] = [];
|
77
83
|
for (const name of names) {
|
78
|
-
const systemSelector =
|
84
|
+
const systemSelector = resourceToHex({ type: "system", namespace, name });
|
79
85
|
// Get the first field of `Systems` table (the table maps system name to its address and other data)
|
80
86
|
const address = await WorldContract.getField(systemsTableId, [systemSelector], 0, systemTableFieldLayout);
|
81
87
|
labels.push({ name, address });
|
@@ -98,7 +104,8 @@ export default commandModule;
|
|
98
104
|
|
99
105
|
async function getWorldAddress(worldsFile: string, rpc: string) {
|
100
106
|
if (existsSync(worldsFile)) {
|
101
|
-
const
|
107
|
+
const client = createClient({ transport: http(rpc) });
|
108
|
+
const chainId = await getChainId(client);
|
102
109
|
const deploys = JSON.parse(readFileSync(worldsFile, "utf-8"));
|
103
110
|
|
104
111
|
if (!deploys[chainId]) {
|
package/src/commands/worldgen.ts
CHANGED
@@ -6,7 +6,7 @@ import { worldgen } from "@latticexyz/world/node";
|
|
6
6
|
import { getSrcDirectory } from "@latticexyz/common/foundry";
|
7
7
|
import path from "path";
|
8
8
|
import { rmSync } from "fs";
|
9
|
-
import { getExistingContracts } from "../utils";
|
9
|
+
import { getExistingContracts } from "../utils/getExistingContracts";
|
10
10
|
|
11
11
|
type Options = {
|
12
12
|
configPath?: string;
|
package/src/common.ts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
export type MudPackages = Record<string, { localPath: string }>;
|
package/src/debug.ts
ADDED
@@ -0,0 +1,10 @@
|
|
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);
|