@latticexyz/cli 2.0.0-alpha.49 → 2.0.0-alpha.50
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-Q7D3SKYJ.js → chunk-5SNB3NQM.js} +1 -1
- package/dist/{chunk-SLIMIO4Z.js → chunk-FFY7VTYB.js} +1 -1
- package/dist/{chunk-ATAWDHWC.js → chunk-FPG73MVN.js} +5 -1
- package/dist/mud.js +112 -55
- package/dist/utils/deprecated/index.js +2 -2
- package/dist/utils/index.d.ts +7 -1
- package/dist/utils/index.js +4 -2
- package/package.json +7 -7
- package/src/commands/deploy-v2.ts +73 -61
- package/src/commands/index.ts +2 -0
- package/src/commands/test-v2.ts +71 -0
- package/src/utils/foundry.ts +9 -0
|
@@ -54,6 +54,9 @@ async function cast(args, options) {
|
|
|
54
54
|
env: { FOUNDRY_PROFILE: options?.profile }
|
|
55
55
|
});
|
|
56
56
|
}
|
|
57
|
+
async function anvil(args) {
|
|
58
|
+
return execLog("anvil", args);
|
|
59
|
+
}
|
|
57
60
|
|
|
58
61
|
export {
|
|
59
62
|
getForgeConfig,
|
|
@@ -63,5 +66,6 @@ export {
|
|
|
63
66
|
getOutDirectory,
|
|
64
67
|
getRpcUrl,
|
|
65
68
|
forge,
|
|
66
|
-
cast
|
|
69
|
+
cast,
|
|
70
|
+
anvil
|
|
67
71
|
};
|
package/dist/mud.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env -S TS_NODE_COMPILER_OPTIONS={\"module\":\"esnext\"} node --loader=ts-node/esm --no-warnings
|
|
2
2
|
import {
|
|
3
3
|
deploy
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-5SNB3NQM.js";
|
|
5
5
|
import {
|
|
6
6
|
MUDError,
|
|
7
7
|
loadStoreConfig,
|
|
@@ -21,13 +21,14 @@ import {
|
|
|
21
21
|
keccak256,
|
|
22
22
|
resetLibDeploy,
|
|
23
23
|
systemsDir
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-FFY7VTYB.js";
|
|
25
25
|
import {
|
|
26
|
+
anvil,
|
|
26
27
|
forge,
|
|
27
28
|
getRpcUrl,
|
|
28
29
|
getSrcDirectory,
|
|
29
30
|
getTestDirectory
|
|
30
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-FPG73MVN.js";
|
|
31
32
|
import {
|
|
32
33
|
renderArguments,
|
|
33
34
|
renderImports,
|
|
@@ -11451,49 +11452,47 @@ async function getChainId(rpc) {
|
|
|
11451
11452
|
}
|
|
11452
11453
|
|
|
11453
11454
|
// src/commands/deploy-v2.ts
|
|
11454
|
-
var
|
|
11455
|
-
|
|
11456
|
-
|
|
11457
|
-
|
|
11458
|
-
|
|
11459
|
-
|
|
11460
|
-
|
|
11461
|
-
|
|
11462
|
-
|
|
11463
|
-
|
|
11464
|
-
priorityFeeMultiplier: {
|
|
11465
|
-
type: "number",
|
|
11466
|
-
desc: "Multiply the estimated priority fee by the provided factor",
|
|
11467
|
-
default: 1
|
|
11468
|
-
}
|
|
11469
|
-
});
|
|
11455
|
+
var yDeployOptions = {
|
|
11456
|
+
configPath: { type: "string", desc: "Path to the config file" },
|
|
11457
|
+
clean: { type: "boolean", desc: "Remove the build forge artifacts and cache directories before building" },
|
|
11458
|
+
printConfig: { type: "boolean", desc: "Print the resolved config" },
|
|
11459
|
+
profile: { type: "string", desc: "The foundry profile to use" },
|
|
11460
|
+
debug: { type: "boolean", desc: "Print debug logs, like full error messages" },
|
|
11461
|
+
priorityFeeMultiplier: {
|
|
11462
|
+
type: "number",
|
|
11463
|
+
desc: "Multiply the estimated priority fee by the provided factor",
|
|
11464
|
+
default: 1
|
|
11470
11465
|
},
|
|
11471
|
-
|
|
11472
|
-
|
|
11473
|
-
|
|
11474
|
-
|
|
11475
|
-
|
|
11476
|
-
|
|
11477
|
-
|
|
11466
|
+
saveDeployment: { type: "boolean", desc: "Save the deployment info to a file", default: true },
|
|
11467
|
+
rpc: { type: "string", desc: "The RPC URL to use. Defaults to the RPC url from the local foundry.toml" }
|
|
11468
|
+
};
|
|
11469
|
+
async function deployHandler(args) {
|
|
11470
|
+
args.profile = args.profile ?? process.env.FOUNDRY_PROFILE;
|
|
11471
|
+
const { configPath, printConfig, profile, clean } = args;
|
|
11472
|
+
const rpc = args.rpc ?? await getRpcUrl(profile);
|
|
11473
|
+
console.log(
|
|
11474
|
+
chalk4.bgBlue(
|
|
11475
|
+
chalk4.whiteBright(`
|
|
11478
11476
|
Deploying MUD v2 contracts${profile ? " with profile " + profile : ""} to RPC ${rpc}
|
|
11479
11477
|
`)
|
|
11480
|
-
|
|
11481
|
-
|
|
11482
|
-
|
|
11483
|
-
|
|
11484
|
-
|
|
11485
|
-
|
|
11486
|
-
|
|
11487
|
-
|
|
11488
|
-
|
|
11489
|
-
|
|
11490
|
-
|
|
11491
|
-
|
|
11492
|
-
|
|
11493
|
-
|
|
11494
|
-
|
|
11495
|
-
|
|
11496
|
-
|
|
11478
|
+
)
|
|
11479
|
+
);
|
|
11480
|
+
if (clean)
|
|
11481
|
+
await forge(["clean"], { profile });
|
|
11482
|
+
await forge(["build"], { profile });
|
|
11483
|
+
const srcDir = await getSrcDirectory();
|
|
11484
|
+
const existingContracts = glob.sync(`${srcDir}/**/*.sol`).map((path9) => basename(path9, ".sol"));
|
|
11485
|
+
const worldConfig = await loadWorldConfig(configPath, existingContracts);
|
|
11486
|
+
const storeConfig = await loadStoreConfig(configPath);
|
|
11487
|
+
const mudConfig = { ...worldConfig, ...storeConfig };
|
|
11488
|
+
if (printConfig)
|
|
11489
|
+
console.log(chalk4.green("\nResolved config:\n"), JSON.stringify(mudConfig, null, 2));
|
|
11490
|
+
try {
|
|
11491
|
+
const privateKey = process.env.PRIVATE_KEY;
|
|
11492
|
+
if (!privateKey)
|
|
11493
|
+
throw new MUDError("Missing PRIVATE_KEY environment variable");
|
|
11494
|
+
const deploymentInfo = await deploy(mudConfig, { ...args, rpc, privateKey });
|
|
11495
|
+
if (args.saveDeployment) {
|
|
11497
11496
|
const chainId = await getChainId(rpc);
|
|
11498
11497
|
const outputDir = path5.join(mudConfig.deploysDirectory, chainId.toString());
|
|
11499
11498
|
mkdirSync(outputDir, { recursive: true });
|
|
@@ -11502,11 +11501,22 @@ var commandModule15 = {
|
|
|
11502
11501
|
console.log(chalk4.bgGreen(chalk4.whiteBright(`
|
|
11503
11502
|
Deployment result (written to ${outputDir}):
|
|
11504
11503
|
`)));
|
|
11505
|
-
console.log(deploymentInfo);
|
|
11506
|
-
} catch (error) {
|
|
11507
|
-
logError(error);
|
|
11508
|
-
process.exit(1);
|
|
11509
11504
|
}
|
|
11505
|
+
console.log(deploymentInfo);
|
|
11506
|
+
return deploymentInfo;
|
|
11507
|
+
} catch (error) {
|
|
11508
|
+
logError(error);
|
|
11509
|
+
process.exit(1);
|
|
11510
|
+
}
|
|
11511
|
+
}
|
|
11512
|
+
var commandModule15 = {
|
|
11513
|
+
command: "deploy-v2",
|
|
11514
|
+
describe: "Deploy MUD v2 contracts",
|
|
11515
|
+
builder(yargs2) {
|
|
11516
|
+
return yargs2.options(yDeployOptions);
|
|
11517
|
+
},
|
|
11518
|
+
async handler(args) {
|
|
11519
|
+
await deployHandler(args);
|
|
11510
11520
|
process.exit(0);
|
|
11511
11521
|
}
|
|
11512
11522
|
};
|
|
@@ -11749,7 +11759,7 @@ import path8 from "path";
|
|
|
11749
11759
|
// package.json
|
|
11750
11760
|
var package_default = {
|
|
11751
11761
|
name: "@latticexyz/cli",
|
|
11752
|
-
version: "2.0.0-alpha.
|
|
11762
|
+
version: "2.0.0-alpha.50+d6be8b08",
|
|
11753
11763
|
description: "Command line interface for mud",
|
|
11754
11764
|
main: "dist/index.js",
|
|
11755
11765
|
types: "dist/index.d.ts",
|
|
@@ -11776,7 +11786,7 @@ var package_default = {
|
|
|
11776
11786
|
release: "npm publish --access=public"
|
|
11777
11787
|
},
|
|
11778
11788
|
devDependencies: {
|
|
11779
|
-
"@latticexyz/store": "^2.0.0-alpha.
|
|
11789
|
+
"@latticexyz/store": "^2.0.0-alpha.50+d6be8b08",
|
|
11780
11790
|
"@types/ejs": "^3.1.1",
|
|
11781
11791
|
"@types/glob": "^7.2.0",
|
|
11782
11792
|
"@types/node": "^17.0.34",
|
|
@@ -11789,10 +11799,10 @@ var package_default = {
|
|
|
11789
11799
|
dependencies: {
|
|
11790
11800
|
"@improbable-eng/grpc-web": "^0.15.0",
|
|
11791
11801
|
"@improbable-eng/grpc-web-node-http-transport": "^0.15.0",
|
|
11792
|
-
"@latticexyz/schema-type": "^2.0.0-alpha.
|
|
11793
|
-
"@latticexyz/services": "^2.0.0-alpha.
|
|
11794
|
-
"@latticexyz/solecs": "^2.0.0-alpha.
|
|
11795
|
-
"@latticexyz/std-contracts": "^2.0.0-alpha.
|
|
11802
|
+
"@latticexyz/schema-type": "^2.0.0-alpha.50+d6be8b08",
|
|
11803
|
+
"@latticexyz/services": "^2.0.0-alpha.50+d6be8b08",
|
|
11804
|
+
"@latticexyz/solecs": "^2.0.0-alpha.50+d6be8b08",
|
|
11805
|
+
"@latticexyz/std-contracts": "^2.0.0-alpha.50+d6be8b08",
|
|
11796
11806
|
"@solidity-parser/parser": "^0.16.0",
|
|
11797
11807
|
"@typechain/ethers-v5": "^10.1.1",
|
|
11798
11808
|
chalk: "^5.0.1",
|
|
@@ -11819,7 +11829,7 @@ var package_default = {
|
|
|
11819
11829
|
zod: "^3.21.4",
|
|
11820
11830
|
"zod-validation-error": "^1.0.1"
|
|
11821
11831
|
},
|
|
11822
|
-
gitHead: "
|
|
11832
|
+
gitHead: "d6be8b08d0eeae3b10eb9e7bffb6d4dd2fc58aa0"
|
|
11823
11833
|
};
|
|
11824
11834
|
|
|
11825
11835
|
// src/commands/set-version.ts
|
|
@@ -11938,6 +11948,52 @@ function logComparison(prev, curr) {
|
|
|
11938
11948
|
}
|
|
11939
11949
|
var set_version_default = commandModule17;
|
|
11940
11950
|
|
|
11951
|
+
// src/commands/test-v2.ts
|
|
11952
|
+
import chalk6 from "chalk";
|
|
11953
|
+
import { rmSync as rmSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
11954
|
+
var WORLD_ADDRESS_FILE = ".mudtest";
|
|
11955
|
+
var commandModule18 = {
|
|
11956
|
+
command: "test-v2",
|
|
11957
|
+
describe: "Run tests in MUD v2 contracts",
|
|
11958
|
+
builder(yargs2) {
|
|
11959
|
+
return yargs2.options({
|
|
11960
|
+
...yDeployOptions,
|
|
11961
|
+
port: { type: "number", description: "Port to run internal node for fork testing on", default: 4242 },
|
|
11962
|
+
worldAddress: {
|
|
11963
|
+
type: "string",
|
|
11964
|
+
description: "Address of an existing world contract. If provided, deployment is skipped and the RPC provided in the foundry.toml is used for fork testing."
|
|
11965
|
+
},
|
|
11966
|
+
forgeOptions: { type: "string", description: "Options to pass to forge test" }
|
|
11967
|
+
});
|
|
11968
|
+
},
|
|
11969
|
+
async handler(args) {
|
|
11970
|
+
if (!args.worldAddress) {
|
|
11971
|
+
const anvilArgs = ["--block-base-fee-per-gas", "0", "--port", String(args.port)];
|
|
11972
|
+
anvil(anvilArgs);
|
|
11973
|
+
}
|
|
11974
|
+
const forkRpc = args.worldAddress ? await getRpcUrl(args.profile) : `http://127.0.0.1:${args.port}`;
|
|
11975
|
+
const worldAddress = args.worldAddress ?? (await deployHandler({
|
|
11976
|
+
...args,
|
|
11977
|
+
saveDeployment: false,
|
|
11978
|
+
rpc: forkRpc
|
|
11979
|
+
})).worldAddress;
|
|
11980
|
+
console.log(chalk6.blue("World address", worldAddress));
|
|
11981
|
+
writeFileSync4(WORLD_ADDRESS_FILE, worldAddress);
|
|
11982
|
+
const userOptions = args.forgeOptions?.replaceAll("\\", "").split(" ") ?? [];
|
|
11983
|
+
try {
|
|
11984
|
+
const testResult = await forge(["test", "--fork-url", forkRpc, ...userOptions], {
|
|
11985
|
+
profile: args.profile
|
|
11986
|
+
});
|
|
11987
|
+
console.log(testResult);
|
|
11988
|
+
} catch (e) {
|
|
11989
|
+
console.error(e);
|
|
11990
|
+
}
|
|
11991
|
+
rmSync5(WORLD_ADDRESS_FILE);
|
|
11992
|
+
process.exit(0);
|
|
11993
|
+
}
|
|
11994
|
+
};
|
|
11995
|
+
var test_v2_default = commandModule18;
|
|
11996
|
+
|
|
11941
11997
|
// src/commands/index.ts
|
|
11942
11998
|
var commands = [
|
|
11943
11999
|
bulkupload_default,
|
|
@@ -11956,7 +12012,8 @@ var commands = [
|
|
|
11956
12012
|
trace_default,
|
|
11957
12013
|
types_default,
|
|
11958
12014
|
worldgen_default,
|
|
11959
|
-
set_version_default
|
|
12015
|
+
set_version_default,
|
|
12016
|
+
test_v2_default
|
|
11960
12017
|
];
|
|
11961
12018
|
|
|
11962
12019
|
// src/mud.ts
|
|
@@ -14,8 +14,8 @@ import {
|
|
|
14
14
|
hsr,
|
|
15
15
|
keccak256,
|
|
16
16
|
resetLibDeploy
|
|
17
|
-
} from "../../chunk-
|
|
18
|
-
import "../../chunk-
|
|
17
|
+
} from "../../chunk-FFY7VTYB.js";
|
|
18
|
+
import "../../chunk-FPG73MVN.js";
|
|
19
19
|
import "../../chunk-O6HOO6WA.js";
|
|
20
20
|
export {
|
|
21
21
|
IDregex,
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -75,6 +75,12 @@ declare function forge(args: string[], options?: {
|
|
|
75
75
|
declare function cast(args: string[], options?: {
|
|
76
76
|
profile?: string;
|
|
77
77
|
}): Promise<string>;
|
|
78
|
+
/**
|
|
79
|
+
* Start an anvil chain
|
|
80
|
+
* @param args The arguments to pass to anvil
|
|
81
|
+
* @returns Stdout of the command
|
|
82
|
+
*/
|
|
83
|
+
declare function anvil(args: string[]): Promise<string>;
|
|
78
84
|
|
|
79
85
|
declare function formatSolidity(content: string, prettierConfigPath?: string): Promise<string>;
|
|
80
86
|
declare function formatTypescript(content: string): Promise<string>;
|
|
@@ -95,4 +101,4 @@ interface DeploymentInfo {
|
|
|
95
101
|
}
|
|
96
102
|
declare function deploy(mudConfig: MUDConfig, deployConfig: DeployConfig): Promise<DeploymentInfo>;
|
|
97
103
|
|
|
98
|
-
export { DeployConfig, DeploymentInfo, ForgeConfig, MUDError, NotESMConfigError, NotInsideProjectError, UnrecognizedSystemErrorFactory, cast, deploy, forge, formatAndWriteSolidity, formatAndWriteTypescript, formatSolidity, formatTypescript, fromZodErrorCustom, getForgeConfig, getOutDirectory, getRpcUrl, getScriptDirectory, getSrcDirectory, getTestDirectory, logError };
|
|
104
|
+
export { DeployConfig, DeploymentInfo, ForgeConfig, MUDError, NotESMConfigError, NotInsideProjectError, UnrecognizedSystemErrorFactory, anvil, cast, deploy, forge, formatAndWriteSolidity, formatAndWriteTypescript, formatSolidity, formatTypescript, fromZodErrorCustom, getForgeConfig, getOutDirectory, getRpcUrl, getScriptDirectory, getSrcDirectory, getTestDirectory, logError };
|
package/dist/utils/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
deploy
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-5SNB3NQM.js";
|
|
4
4
|
import {
|
|
5
5
|
MUDError,
|
|
6
6
|
NotESMConfigError,
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
logError
|
|
11
11
|
} from "../chunk-LPWKZQUI.js";
|
|
12
12
|
import {
|
|
13
|
+
anvil,
|
|
13
14
|
cast,
|
|
14
15
|
forge,
|
|
15
16
|
getForgeConfig,
|
|
@@ -18,7 +19,7 @@ import {
|
|
|
18
19
|
getScriptDirectory,
|
|
19
20
|
getSrcDirectory,
|
|
20
21
|
getTestDirectory
|
|
21
|
-
} from "../chunk-
|
|
22
|
+
} from "../chunk-FPG73MVN.js";
|
|
22
23
|
import {
|
|
23
24
|
formatAndWriteSolidity,
|
|
24
25
|
formatAndWriteTypescript,
|
|
@@ -32,6 +33,7 @@ export {
|
|
|
32
33
|
NotESMConfigError,
|
|
33
34
|
NotInsideProjectError,
|
|
34
35
|
UnrecognizedSystemErrorFactory,
|
|
36
|
+
anvil,
|
|
35
37
|
cast,
|
|
36
38
|
deploy,
|
|
37
39
|
forge,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@latticexyz/cli",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.50+d6be8b08",
|
|
4
4
|
"description": "Command line interface for mud",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"release": "npm publish --access=public"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@latticexyz/store": "^2.0.0-alpha.
|
|
30
|
+
"@latticexyz/store": "^2.0.0-alpha.50+d6be8b08",
|
|
31
31
|
"@types/ejs": "^3.1.1",
|
|
32
32
|
"@types/glob": "^7.2.0",
|
|
33
33
|
"@types/node": "^17.0.34",
|
|
@@ -40,10 +40,10 @@
|
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@improbable-eng/grpc-web": "^0.15.0",
|
|
42
42
|
"@improbable-eng/grpc-web-node-http-transport": "^0.15.0",
|
|
43
|
-
"@latticexyz/schema-type": "^2.0.0-alpha.
|
|
44
|
-
"@latticexyz/services": "^2.0.0-alpha.
|
|
45
|
-
"@latticexyz/solecs": "^2.0.0-alpha.
|
|
46
|
-
"@latticexyz/std-contracts": "^2.0.0-alpha.
|
|
43
|
+
"@latticexyz/schema-type": "^2.0.0-alpha.50+d6be8b08",
|
|
44
|
+
"@latticexyz/services": "^2.0.0-alpha.50+d6be8b08",
|
|
45
|
+
"@latticexyz/solecs": "^2.0.0-alpha.50+d6be8b08",
|
|
46
|
+
"@latticexyz/std-contracts": "^2.0.0-alpha.50+d6be8b08",
|
|
47
47
|
"@solidity-parser/parser": "^0.16.0",
|
|
48
48
|
"@typechain/ethers-v5": "^10.1.1",
|
|
49
49
|
"chalk": "^5.0.1",
|
|
@@ -70,5 +70,5 @@
|
|
|
70
70
|
"zod": "^3.21.4",
|
|
71
71
|
"zod-validation-error": "^1.0.1"
|
|
72
72
|
},
|
|
73
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "d6be8b08d0eeae3b10eb9e7bffb6d4dd2fc58aa0"
|
|
74
74
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import glob from "glob";
|
|
3
3
|
import path, { basename } from "path";
|
|
4
|
-
import type { CommandModule } from "yargs";
|
|
4
|
+
import type { CommandModule, Options } from "yargs";
|
|
5
5
|
import { loadWorldConfig } from "../config/world/index.js";
|
|
6
6
|
import { deploy } from "../utils/deploy-v2.js";
|
|
7
7
|
import { logError, MUDError } from "../utils/errors.js";
|
|
@@ -10,71 +10,68 @@ import { mkdirSync, writeFileSync } from "fs";
|
|
|
10
10
|
import { loadStoreConfig } from "../config/loadStoreConfig.js";
|
|
11
11
|
import { getChainId } from "../utils/getChainId.js";
|
|
12
12
|
|
|
13
|
-
type
|
|
13
|
+
export type DeployOptions = {
|
|
14
14
|
configPath?: string;
|
|
15
15
|
printConfig?: boolean;
|
|
16
16
|
profile?: string;
|
|
17
|
-
privateKey: string;
|
|
18
17
|
priorityFeeMultiplier: number;
|
|
19
18
|
clean?: boolean;
|
|
20
19
|
debug?: boolean;
|
|
20
|
+
saveDeployment?: boolean;
|
|
21
|
+
rpc?: string;
|
|
21
22
|
};
|
|
22
23
|
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
profile: { type: "string", desc: "The foundry profile to use" },
|
|
34
|
-
debug: { type: "boolean", desc: "Print debug logs, like full error messages" },
|
|
35
|
-
priorityFeeMultiplier: {
|
|
36
|
-
type: "number",
|
|
37
|
-
desc: "Multiply the estimated priority fee by the provided factor",
|
|
38
|
-
default: 1,
|
|
39
|
-
},
|
|
40
|
-
});
|
|
24
|
+
export const yDeployOptions = {
|
|
25
|
+
configPath: { type: "string", desc: "Path to the config file" },
|
|
26
|
+
clean: { type: "boolean", desc: "Remove the build forge artifacts and cache directories before building" },
|
|
27
|
+
printConfig: { type: "boolean", desc: "Print the resolved config" },
|
|
28
|
+
profile: { type: "string", desc: "The foundry profile to use" },
|
|
29
|
+
debug: { type: "boolean", desc: "Print debug logs, like full error messages" },
|
|
30
|
+
priorityFeeMultiplier: {
|
|
31
|
+
type: "number",
|
|
32
|
+
desc: "Multiply the estimated priority fee by the provided factor",
|
|
33
|
+
default: 1,
|
|
41
34
|
},
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
//
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
35
|
+
saveDeployment: { type: "boolean", desc: "Save the deployment info to a file", default: true },
|
|
36
|
+
rpc: { type: "string", desc: "The RPC URL to use. Defaults to the RPC url from the local foundry.toml" },
|
|
37
|
+
} satisfies Record<keyof DeployOptions, Options>;
|
|
38
|
+
|
|
39
|
+
export async function deployHandler(args: Parameters<(typeof commandModule)["handler"]>[0]) {
|
|
40
|
+
args.profile = args.profile ?? process.env.FOUNDRY_PROFILE;
|
|
41
|
+
const { configPath, printConfig, profile, clean } = args;
|
|
42
|
+
|
|
43
|
+
const rpc = args.rpc ?? (await getRpcUrl(profile));
|
|
44
|
+
console.log(
|
|
45
|
+
chalk.bgBlue(
|
|
46
|
+
chalk.whiteBright(`\n Deploying MUD v2 contracts${profile ? " with profile " + profile : ""} to RPC ${rpc} \n`)
|
|
47
|
+
)
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
if (clean) await forge(["clean"], { profile });
|
|
51
|
+
|
|
52
|
+
// Run forge build
|
|
53
|
+
await forge(["build"], { profile });
|
|
54
|
+
|
|
55
|
+
// Get a list of all contract names
|
|
56
|
+
const srcDir = await getSrcDirectory();
|
|
57
|
+
const existingContracts = glob
|
|
58
|
+
.sync(`${srcDir}/**/*.sol`)
|
|
59
|
+
// Get the basename of the file
|
|
60
|
+
.map((path) => basename(path, ".sol"));
|
|
61
|
+
|
|
62
|
+
// Load and resolve the config
|
|
63
|
+
const worldConfig = await loadWorldConfig(configPath, existingContracts);
|
|
64
|
+
const storeConfig = await loadStoreConfig(configPath);
|
|
65
|
+
const mudConfig = { ...worldConfig, ...storeConfig };
|
|
66
|
+
|
|
67
|
+
if (printConfig) console.log(chalk.green("\nResolved config:\n"), JSON.stringify(mudConfig, null, 2));
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
const privateKey = process.env.PRIVATE_KEY;
|
|
71
|
+
if (!privateKey) throw new MUDError("Missing PRIVATE_KEY environment variable");
|
|
72
|
+
const deploymentInfo = await deploy(mudConfig, { ...args, rpc, privateKey });
|
|
73
|
+
|
|
74
|
+
if (args.saveDeployment) {
|
|
78
75
|
// Write deployment result to file (latest and timestamp)
|
|
79
76
|
const chainId = await getChainId(rpc);
|
|
80
77
|
const outputDir = path.join(mudConfig.deploysDirectory, chainId.toString());
|
|
@@ -83,12 +80,27 @@ const commandModule: CommandModule<Options, Options> = {
|
|
|
83
80
|
writeFileSync(path.join(outputDir, Date.now() + ".json"), JSON.stringify(deploymentInfo, null, 2));
|
|
84
81
|
|
|
85
82
|
console.log(chalk.bgGreen(chalk.whiteBright(`\n Deployment result (written to ${outputDir}): \n`)));
|
|
86
|
-
console.log(deploymentInfo);
|
|
87
|
-
} catch (error: any) {
|
|
88
|
-
logError(error);
|
|
89
|
-
process.exit(1);
|
|
90
83
|
}
|
|
91
84
|
|
|
85
|
+
console.log(deploymentInfo);
|
|
86
|
+
return deploymentInfo;
|
|
87
|
+
} catch (error: any) {
|
|
88
|
+
logError(error);
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const commandModule: CommandModule<DeployOptions, DeployOptions> = {
|
|
94
|
+
command: "deploy-v2",
|
|
95
|
+
|
|
96
|
+
describe: "Deploy MUD v2 contracts",
|
|
97
|
+
|
|
98
|
+
builder(yargs) {
|
|
99
|
+
return yargs.options(yDeployOptions);
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
async handler(args) {
|
|
103
|
+
await deployHandler(args);
|
|
92
104
|
process.exit(0);
|
|
93
105
|
},
|
|
94
106
|
};
|
package/src/commands/index.ts
CHANGED
|
@@ -18,6 +18,7 @@ import tsgen from "./tsgen.js";
|
|
|
18
18
|
import deployV2 from "./deploy-v2.js";
|
|
19
19
|
import worldgen from "./worldgen.js";
|
|
20
20
|
import setVersion from "./set-version.js";
|
|
21
|
+
import testV2 from "./test-v2.js";
|
|
21
22
|
|
|
22
23
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Each command has different options
|
|
23
24
|
export const commands: CommandModule<any, any>[] = [
|
|
@@ -38,4 +39,5 @@ export const commands: CommandModule<any, any>[] = [
|
|
|
38
39
|
types,
|
|
39
40
|
worldgen,
|
|
40
41
|
setVersion,
|
|
42
|
+
testV2,
|
|
41
43
|
];
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { CommandModule } from "yargs";
|
|
2
|
+
import { deployHandler, DeployOptions } from "./deploy-v2.js";
|
|
3
|
+
import { yDeployOptions } from "./deploy-v2.js";
|
|
4
|
+
import { anvil, forge, getRpcUrl, getTestDirectory } from "../utils/foundry.js";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
import { rmSync, writeFileSync } from "fs";
|
|
7
|
+
import path from "path";
|
|
8
|
+
|
|
9
|
+
type Options = DeployOptions & { port?: number; worldAddress?: string; forgeOptions?: string };
|
|
10
|
+
|
|
11
|
+
const WORLD_ADDRESS_FILE = ".mudtest";
|
|
12
|
+
|
|
13
|
+
const commandModule: CommandModule<Options, Options> = {
|
|
14
|
+
command: "test-v2",
|
|
15
|
+
|
|
16
|
+
describe: "Run tests in MUD v2 contracts",
|
|
17
|
+
|
|
18
|
+
builder(yargs) {
|
|
19
|
+
return yargs.options({
|
|
20
|
+
...yDeployOptions,
|
|
21
|
+
port: { type: "number", description: "Port to run internal node for fork testing on", default: 4242 },
|
|
22
|
+
worldAddress: {
|
|
23
|
+
type: "string",
|
|
24
|
+
description:
|
|
25
|
+
"Address of an existing world contract. If provided, deployment is skipped and the RPC provided in the foundry.toml is used for fork testing.",
|
|
26
|
+
},
|
|
27
|
+
forgeOptions: { type: "string", description: "Options to pass to forge test" },
|
|
28
|
+
});
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
async handler(args) {
|
|
32
|
+
// Start an internal anvil process if no world address is provided
|
|
33
|
+
if (!args.worldAddress) {
|
|
34
|
+
const anvilArgs = ["--block-base-fee-per-gas", "0", "--port", String(args.port)];
|
|
35
|
+
anvil(anvilArgs);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const forkRpc = args.worldAddress ? await getRpcUrl(args.profile) : `http://127.0.0.1:${args.port}`;
|
|
39
|
+
|
|
40
|
+
const worldAddress =
|
|
41
|
+
args.worldAddress ??
|
|
42
|
+
(
|
|
43
|
+
await deployHandler({
|
|
44
|
+
...args,
|
|
45
|
+
saveDeployment: false,
|
|
46
|
+
rpc: forkRpc,
|
|
47
|
+
})
|
|
48
|
+
).worldAddress;
|
|
49
|
+
|
|
50
|
+
console.log(chalk.blue("World address", worldAddress));
|
|
51
|
+
|
|
52
|
+
// Create a temporary file to pass the world address to the tests
|
|
53
|
+
writeFileSync(WORLD_ADDRESS_FILE, worldAddress);
|
|
54
|
+
|
|
55
|
+
const userOptions = args.forgeOptions?.replaceAll("\\", "").split(" ") ?? [];
|
|
56
|
+
try {
|
|
57
|
+
const testResult = await forge(["test", "--fork-url", forkRpc, ...userOptions], {
|
|
58
|
+
profile: args.profile,
|
|
59
|
+
});
|
|
60
|
+
console.log(testResult);
|
|
61
|
+
} catch (e) {
|
|
62
|
+
console.error(e);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
rmSync(WORLD_ADDRESS_FILE);
|
|
66
|
+
|
|
67
|
+
process.exit(0);
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export default commandModule;
|
package/src/utils/foundry.ts
CHANGED
|
@@ -92,3 +92,12 @@ export async function cast(args: string[], options?: { profile?: string }): Prom
|
|
|
92
92
|
env: { FOUNDRY_PROFILE: options?.profile },
|
|
93
93
|
});
|
|
94
94
|
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Start an anvil chain
|
|
98
|
+
* @param args The arguments to pass to anvil
|
|
99
|
+
* @returns Stdout of the command
|
|
100
|
+
*/
|
|
101
|
+
export async function anvil(args: string[]): Promise<string> {
|
|
102
|
+
return execLog("anvil", args);
|
|
103
|
+
}
|