@latticexyz/cli 2.0.0-next.17 → 2.0.0-next.18
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 → chunk-QXUPZVZL.js} +2 -2
- package/dist/chunk-QXUPZVZL.js.map +1 -0
- package/dist/commands-MGE24C7Z.js +36 -0
- package/dist/commands-MGE24C7Z.js.map +1 -0
- package/dist/errors-MZURIB7V.js +2 -0
- package/dist/mud.js +1 -1
- package/dist/mud.js.map +1 -1
- package/package.json +16 -15
- package/src/build.ts +9 -5
- package/src/commands/build.ts +2 -3
- package/src/commands/deploy.ts +1 -1
- package/src/commands/dev-contracts.ts +6 -5
- package/src/commands/set-version.ts +1 -1
- package/src/commands/tablegen.ts +2 -2
- package/src/commands/trace.ts +7 -5
- package/src/commands/worldgen.ts +7 -6
- package/src/deploy/common.ts +54 -8
- package/src/deploy/configToTables.ts +8 -6
- package/src/deploy/create2/README.md +4 -0
- package/src/deploy/create2/deployment.json +2 -1
- package/src/deploy/createPrepareDeploy.ts +28 -0
- package/src/deploy/deploy.ts +33 -16
- package/src/deploy/deployWorld.ts +4 -3
- package/src/deploy/ensureContract.ts +12 -7
- package/src/deploy/ensureContractsDeployed.ts +9 -1
- package/src/deploy/ensureDeployer.ts +61 -22
- package/src/deploy/ensureFunctions.ts +5 -5
- package/src/deploy/ensureModules.ts +16 -10
- package/src/deploy/ensureNamespaceOwner.ts +4 -4
- package/src/deploy/ensureSystems.ts +108 -83
- package/src/deploy/ensureTables.ts +8 -9
- package/src/deploy/ensureWorldFactory.ts +79 -92
- package/src/deploy/findLibraries.ts +36 -0
- package/src/deploy/getFunctions.ts +5 -5
- package/src/deploy/getResourceAccess.ts +3 -3
- package/src/deploy/getSystems.ts +6 -7
- package/src/deploy/getTableValue.ts +1 -1
- package/src/deploy/getTables.ts +2 -2
- package/src/deploy/logsToWorldDeploy.ts +4 -4
- package/src/deploy/orderByDependencies.ts +12 -0
- package/src/deploy/resolveConfig.ts +55 -58
- package/src/mud.ts +1 -1
- package/src/mudPackages.ts +1 -1
- package/src/runDeploy.ts +28 -10
- package/src/utils/{modules/constants.ts → defaultModuleContracts.ts} +4 -0
- package/src/utils/errors.ts +1 -1
- package/src/utils/findPlaceholders.ts +27 -0
- package/src/utils/{utils/getContractData.ts → getContractData.ts} +11 -5
- package/src/utils/{utils/postDeploy.ts → postDeploy.ts} +2 -2
- package/src/utils/printMUD.ts +1 -1
- package/dist/chunk-22IIKR4S.js.map +0 -1
- package/dist/commands-3JV3U43E.js +0 -27
- package/dist/commands-3JV3U43E.js.map +0 -1
- package/dist/errors-XGN6V2Y3.js +0 -2
- package/src/deploy/resourceLabel.ts +0 -3
- /package/dist/{errors-XGN6V2Y3.js.map → errors-MZURIB7V.js.map} +0 -0
package/src/runDeploy.ts
CHANGED
@@ -5,14 +5,14 @@ import { deploy } from "./deploy/deploy";
|
|
5
5
|
import { createWalletClient, http, Hex, isHex } from "viem";
|
6
6
|
import { privateKeyToAccount } from "viem/accounts";
|
7
7
|
import { loadConfig } from "@latticexyz/config/node";
|
8
|
-
import {
|
9
|
-
import {
|
8
|
+
import { World as WorldConfig } from "@latticexyz/world";
|
9
|
+
import { worldToV1 } from "@latticexyz/world/config/v2";
|
10
10
|
import { getOutDirectory, getRpcUrl, getSrcDirectory } from "@latticexyz/common/foundry";
|
11
11
|
import chalk from "chalk";
|
12
12
|
import { MUDError } from "@latticexyz/common/errors";
|
13
13
|
import { resolveConfig } from "./deploy/resolveConfig";
|
14
14
|
import { getChainId } from "viem/actions";
|
15
|
-
import { postDeploy } from "./utils/
|
15
|
+
import { postDeploy } from "./utils/postDeploy";
|
16
16
|
import { WorldDeploy } from "./deploy/common";
|
17
17
|
import { build } from "./build";
|
18
18
|
|
@@ -22,6 +22,14 @@ export const deployOptions = {
|
|
22
22
|
profile: { type: "string", desc: "The foundry profile to use" },
|
23
23
|
saveDeployment: { type: "boolean", desc: "Save the deployment info to a file", default: true },
|
24
24
|
rpc: { type: "string", desc: "The RPC URL to use. Defaults to the RPC url from the local foundry.toml" },
|
25
|
+
rpcBatch: {
|
26
|
+
type: "boolean",
|
27
|
+
desc: "Enable batch processing of RPC requests in viem client (defaults to batch size of 100 and wait of 1s)",
|
28
|
+
},
|
29
|
+
deployerAddress: {
|
30
|
+
type: "string",
|
31
|
+
desc: "Deploy using an existing deterministic deployer (https://github.com/Arachnid/deterministic-deployment-proxy)",
|
32
|
+
},
|
25
33
|
worldAddress: { type: "string", desc: "Deploy to an existing World at the given address" },
|
26
34
|
srcDir: { type: "string", desc: "Source directory. Defaults to foundry src directory." },
|
27
35
|
skipBuild: { type: "boolean", desc: "Skip rebuilding the contracts before deploying" },
|
@@ -49,7 +57,8 @@ export async function runDeploy(opts: DeployOptions): Promise<WorldDeploy> {
|
|
49
57
|
|
50
58
|
const profile = opts.profile ?? process.env.FOUNDRY_PROFILE;
|
51
59
|
|
52
|
-
const
|
60
|
+
const configV2 = (await loadConfig(opts.configPath)) as WorldConfig;
|
61
|
+
const config = worldToV1(configV2);
|
53
62
|
if (opts.printConfig) {
|
54
63
|
console.log(chalk.green("\nResolved config:\n"), JSON.stringify(config, null, 2));
|
55
64
|
}
|
@@ -60,13 +69,13 @@ export async function runDeploy(opts: DeployOptions): Promise<WorldDeploy> {
|
|
60
69
|
const rpc = opts.rpc ?? (await getRpcUrl(profile));
|
61
70
|
console.log(
|
62
71
|
chalk.bgBlue(
|
63
|
-
chalk.whiteBright(`\n Deploying MUD contracts${profile ? " with profile " + profile : ""} to RPC ${rpc} \n`)
|
64
|
-
)
|
72
|
+
chalk.whiteBright(`\n Deploying MUD contracts${profile ? " with profile " + profile : ""} to RPC ${rpc} \n`),
|
73
|
+
),
|
65
74
|
);
|
66
75
|
|
67
76
|
// Run build
|
68
77
|
if (!opts.skipBuild) {
|
69
|
-
await build({ config, srcDir, foundryProfile: profile });
|
78
|
+
await build({ config: configV2, srcDir, foundryProfile: profile });
|
70
79
|
}
|
71
80
|
|
72
81
|
const privateKey = process.env.PRIVATE_KEY as Hex;
|
@@ -74,20 +83,29 @@ export async function runDeploy(opts: DeployOptions): Promise<WorldDeploy> {
|
|
74
83
|
throw new MUDError(
|
75
84
|
`Missing PRIVATE_KEY environment variable.
|
76
85
|
Run 'echo "PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" > .env'
|
77
|
-
in your contracts directory to use the default anvil private key
|
86
|
+
in your contracts directory to use the default anvil private key.`,
|
78
87
|
);
|
79
88
|
}
|
80
89
|
|
81
90
|
const resolvedConfig = resolveConfig({ config, forgeSourceDir: srcDir, forgeOutDir: outDir });
|
82
91
|
|
83
92
|
const client = createWalletClient({
|
84
|
-
transport: http(rpc
|
93
|
+
transport: http(rpc, {
|
94
|
+
batch: opts.rpcBatch
|
95
|
+
? {
|
96
|
+
batchSize: 100,
|
97
|
+
wait: 1000,
|
98
|
+
}
|
99
|
+
: undefined,
|
100
|
+
}),
|
85
101
|
account: privateKeyToAccount(privateKey),
|
86
102
|
});
|
103
|
+
|
87
104
|
console.log("Deploying from", client.account.address);
|
88
105
|
|
89
106
|
const startTime = Date.now();
|
90
107
|
const worldDeploy = await deploy({
|
108
|
+
deployerAddress: opts.deployerAddress as Hex | undefined,
|
91
109
|
salt,
|
92
110
|
worldAddress: opts.worldAddress as Hex | undefined,
|
93
111
|
client,
|
@@ -121,7 +139,7 @@ in your contracts directory to use the default anvil private key.`
|
|
121
139
|
writeFileSync(config.worldsFile, JSON.stringify(deploys, null, 2));
|
122
140
|
|
123
141
|
console.log(
|
124
|
-
chalk.bgGreen(chalk.whiteBright(`\n Deployment result (written to ${config.worldsFile} and ${deploysDir}): \n`))
|
142
|
+
chalk.bgGreen(chalk.whiteBright(`\n Deployment result (written to ${config.worldsFile} and ${deploysDir}): \n`)),
|
125
143
|
);
|
126
144
|
}
|
127
145
|
|
@@ -2,6 +2,7 @@ import KeysWithValueModuleData from "@latticexyz/world-modules/out/KeysWithValue
|
|
2
2
|
import KeysInTableModuleData from "@latticexyz/world-modules/out/KeysInTableModule.sol/KeysInTableModule.json" assert { type: "json" };
|
3
3
|
import UniqueEntityModuleData from "@latticexyz/world-modules/out/UniqueEntityModule.sol/UniqueEntityModule.json" assert { type: "json" };
|
4
4
|
import { Abi, Hex, size } from "viem";
|
5
|
+
import { findPlaceholders } from "./findPlaceholders";
|
5
6
|
|
6
7
|
// These modules are always deployed
|
7
8
|
export const defaultModuleContracts = [
|
@@ -9,18 +10,21 @@ export const defaultModuleContracts = [
|
|
9
10
|
name: "KeysWithValueModule",
|
10
11
|
abi: KeysWithValueModuleData.abi as Abi,
|
11
12
|
bytecode: KeysWithValueModuleData.bytecode.object as Hex,
|
13
|
+
placeholders: findPlaceholders(KeysWithValueModuleData.bytecode.linkReferences),
|
12
14
|
deployedBytecodeSize: size(KeysWithValueModuleData.deployedBytecode.object as Hex),
|
13
15
|
},
|
14
16
|
{
|
15
17
|
name: "KeysInTableModule",
|
16
18
|
abi: KeysInTableModuleData.abi as Abi,
|
17
19
|
bytecode: KeysInTableModuleData.bytecode.object as Hex,
|
20
|
+
placeholders: findPlaceholders(KeysInTableModuleData.bytecode.linkReferences),
|
18
21
|
deployedBytecodeSize: size(KeysInTableModuleData.deployedBytecode.object as Hex),
|
19
22
|
},
|
20
23
|
{
|
21
24
|
name: "UniqueEntityModule",
|
22
25
|
abi: UniqueEntityModuleData.abi as Abi,
|
23
26
|
bytecode: UniqueEntityModuleData.bytecode.object as Hex,
|
27
|
+
placeholders: findPlaceholders(UniqueEntityModuleData.bytecode.linkReferences),
|
24
28
|
deployedBytecodeSize: size(UniqueEntityModuleData.deployedBytecode.object as Hex),
|
25
29
|
},
|
26
30
|
];
|
package/src/utils/errors.ts
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import chalk from "chalk";
|
2
2
|
import { ZodError } from "zod";
|
3
3
|
import { fromZodError, ValidationError } from "zod-validation-error";
|
4
|
-
import { NotInsideProjectError } from "@latticexyz/config";
|
4
|
+
import { NotInsideProjectError } from "@latticexyz/config/library";
|
5
5
|
import { MUDError } from "@latticexyz/common/errors";
|
6
6
|
|
7
7
|
export function logError(error: unknown) {
|
@@ -0,0 +1,27 @@
|
|
1
|
+
import { LibraryPlaceholder } from "../deploy/common";
|
2
|
+
|
3
|
+
// TODO: move this to a broader solc artifact type
|
4
|
+
/** From `artifact.bytecode.linkReferences` where `artifact` is the solc JSON output of a compiled Solidity contract */
|
5
|
+
export type LinkReferences = {
|
6
|
+
[filename: string]: {
|
7
|
+
[name: string]: {
|
8
|
+
start: number;
|
9
|
+
length: number;
|
10
|
+
}[];
|
11
|
+
};
|
12
|
+
};
|
13
|
+
|
14
|
+
export function findPlaceholders(linkReferences: LinkReferences): readonly LibraryPlaceholder[] {
|
15
|
+
return Object.entries(linkReferences).flatMap(([path, contracts]) =>
|
16
|
+
Object.entries(contracts).flatMap(([contractName, locations]) =>
|
17
|
+
locations.map(
|
18
|
+
(location): LibraryPlaceholder => ({
|
19
|
+
path,
|
20
|
+
name: contractName,
|
21
|
+
start: location.start,
|
22
|
+
length: location.length,
|
23
|
+
}),
|
24
|
+
),
|
25
|
+
),
|
26
|
+
);
|
27
|
+
}
|
@@ -2,20 +2,24 @@ import { readFileSync } from "fs";
|
|
2
2
|
import path from "path";
|
3
3
|
import { MUDError } from "@latticexyz/common/errors";
|
4
4
|
import { Abi, Hex, size } from "viem";
|
5
|
+
import { LibraryPlaceholder } from "../deploy/common";
|
6
|
+
import { findPlaceholders } from "./findPlaceholders";
|
5
7
|
|
6
8
|
/**
|
7
9
|
* Load the contract's abi and bytecode from the file system
|
8
10
|
* @param contractName: Name of the contract to load
|
9
11
|
*/
|
10
12
|
export function getContractData(
|
13
|
+
filename: string,
|
11
14
|
contractName: string,
|
12
|
-
forgeOutDirectory: string
|
13
|
-
): { bytecode: Hex; abi: Abi; deployedBytecodeSize: number } {
|
15
|
+
forgeOutDirectory: string,
|
16
|
+
): { bytecode: Hex; placeholders: readonly LibraryPlaceholder[]; abi: Abi; deployedBytecodeSize: number } {
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
14
18
|
let data: any;
|
15
|
-
const contractDataPath = path.join(forgeOutDirectory,
|
19
|
+
const contractDataPath = path.join(forgeOutDirectory, filename, contractName + ".json");
|
16
20
|
try {
|
17
21
|
data = JSON.parse(readFileSync(contractDataPath, "utf8"));
|
18
|
-
} catch (error
|
22
|
+
} catch (error) {
|
19
23
|
throw new MUDError(`Error reading file at ${contractDataPath}`);
|
20
24
|
}
|
21
25
|
|
@@ -28,5 +32,7 @@ export function getContractData(
|
|
28
32
|
const abi = data?.abi;
|
29
33
|
if (!abi) throw new MUDError(`No ABI found in ${contractDataPath}`);
|
30
34
|
|
31
|
-
|
35
|
+
const placeholders = findPlaceholders(data?.bytecode?.linkReferences ?? {});
|
36
|
+
|
37
|
+
return { abi, bytecode, placeholders, deployedBytecodeSize: size(deployedBytecode as Hex) };
|
32
38
|
}
|
@@ -7,7 +7,7 @@ export async function postDeploy(
|
|
7
7
|
postDeployScript: string,
|
8
8
|
worldAddress: string,
|
9
9
|
rpc: string,
|
10
|
-
profile: string | undefined
|
10
|
+
profile: string | undefined,
|
11
11
|
): Promise<void> {
|
12
12
|
// Execute postDeploy forge script
|
13
13
|
const postDeployPath = path.join(await getScriptDirectory(), postDeployScript + ".s.sol");
|
@@ -17,7 +17,7 @@ export async function postDeploy(
|
|
17
17
|
["script", postDeployScript, "--sig", "run(address)", worldAddress, "--broadcast", "--rpc-url", rpc, "-vvv"],
|
18
18
|
{
|
19
19
|
profile: profile,
|
20
|
-
}
|
20
|
+
},
|
21
21
|
);
|
22
22
|
} else {
|
23
23
|
console.log(`No script at ${postDeployPath}, skipping post deploy hook`);
|
package/src/utils/printMUD.ts
CHANGED
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"sources":["../src/utils/errors.ts"],"sourcesContent":["import chalk from \"chalk\";\nimport { ZodError } from \"zod\";\nimport { fromZodError, ValidationError } from \"zod-validation-error\";\nimport { NotInsideProjectError } from \"@latticexyz/config\";\nimport { MUDError } from \"@latticexyz/common/errors\";\n\nexport function logError(error: unknown) {\n if (error instanceof ValidationError) {\n console.log(chalk.redBright(error.message));\n } else if (error instanceof ZodError) {\n // TODO currently this error shouldn't happen, use `fromZodErrorCustom`\n // (see https://github.com/latticexyz/mud/issues/438)\n const validationError = fromZodError(error, {\n prefixSeparator: \"\\n- \",\n issueSeparator: \"\\n- \",\n });\n console.log(chalk.redBright(validationError.message));\n } else if (error instanceof NotInsideProjectError) {\n console.log(chalk.red(error.message));\n console.log(\"\");\n // TODO add docs to the website and update the link to the specific page\n // (see https://github.com/latticexyz/mud/issues/445)\n console.log(chalk.blue(`To learn more about MUD's configuration, please go to https://mud.dev/packages/cli/`));\n } else if (error instanceof MUDError) {\n console.log(chalk.red(error));\n } else {\n console.log(error);\n }\n}\n"],"mappings":"AAAA,OAAOA,MAAW,QAClB,OAAS,YAAAC,MAAgB,MACzB,OAAS,gBAAAC,EAAc,mBAAAC,MAAuB,uBAC9C,OAAS,yBAAAC,MAA6B,qBACtC,OAAS,YAAAC,MAAgB,4BAElB,SAASC,EAASC,EAAgB,CACvC,GAAIA,aAAiBJ,EACnB,QAAQ,IAAIH,EAAM,UAAUO,EAAM,OAAO,CAAC,UACjCA,aAAiBN,EAAU,CAGpC,IAAMO,EAAkBN,EAAaK,EAAO,CAC1C,gBAAiB;AAAA,IACjB,eAAgB;AAAA,GAClB,CAAC,EACD,QAAQ,IAAIP,EAAM,UAAUQ,EAAgB,OAAO,CAAC,OAC3CD,aAAiBH,GAC1B,QAAQ,IAAIJ,EAAM,IAAIO,EAAM,OAAO,CAAC,EACpC,QAAQ,IAAI,EAAE,EAGd,QAAQ,IAAIP,EAAM,KAAK,qFAAqF,CAAC,GACpGO,aAAiBF,EAC1B,QAAQ,IAAIL,EAAM,IAAIO,CAAK,CAAC,EAE5B,QAAQ,IAAIA,CAAK,CAErB","names":["chalk","ZodError","fromZodError","ValidationError","NotInsideProjectError","MUDError","logError","error","validationError"]}
|
@@ -1,27 +0,0 @@
|
|
1
|
-
import{a as _}from"./chunk-22IIKR4S.js";import xs from"@latticexyz/gas-report";import Ss from"@latticexyz/abi-ts";import{loadConfig as Go}from"@latticexyz/config/node";import{getSrcDirectory as Yo}from"@latticexyz/common/foundry";import{existsSync as Eo,readFileSync as No,writeFileSync as zo}from"node:fs";import X from"node:path";import{tablegen as Uo}from"@latticexyz/store/codegen";import{worldgen as Vo}from"@latticexyz/world/node";import{forge as _o,getForgeConfig as Lo,getRemappings as Ko}from"@latticexyz/common/foundry";import Ro from"glob";import{basename as Ho}from"path";function I(e){return Ro.sync(`${e}/**/*.sol`).map(o=>({path:o,basename:Ho(o,".sol")}))}import ye from"debug";var M=ye("mud:cli"),$o=ye("mud:cli");M.log=console.debug.bind(console);$o.log=console.error.bind(console);import{execa as Jo}from"execa";var qo=M.extend("runDeploy");async function L({config:e,srcDir:o,foundryProfile:r=process.env.FOUNDRY_PROFILE}){let t=X.join(o,e.codegenDirectory),n=await Ko(r);await Promise.all([Uo(e,t,n),Vo(e,I(o),t)]);let s=await Lo(r);if(s.cache){let a=X.join(s.cache_path,"solidity-files-cache.json");if(Eo(a)){qo("Unsetting cached content hash of IWorld.sol to force it to regenerate");let i=JSON.parse(No(a,"utf8")),p=X.join(t,"world","IWorld.sol");i.files[p].contentHash="",zo(a,JSON.stringify(i,null,2))}}await _o(["build"],{profile:r}),await Jo("mud",["abi-ts"],{stdio:"inherit"})}var Zo={command:"build",describe:"Build contracts and generate MUD artifacts (table libraries, world interface, ABI)",builder(e){return e.options({configPath:{type:"string",desc:"Path to the config file"},profile:{type:"string",desc:"The foundry profile to use"}})},async handler({configPath:e,profile:o}){let r=await Go(e),t=await Yo();await L({config:r,srcDir:t,foundryProfile:o}),process.exit(0)}},ue=Zo;import{rmSync as Qo}from"fs";import{homedir as Xo}from"os";import et from"path";import{execa as ot}from"execa";var tt={command:"devnode",describe:"Start a local Ethereum node for development",builder(e){return e.options({blocktime:{type:"number",default:1,decs:"Interval in which new blocks are produced"}})},async handler({blocktime:e}){console.log("Clearing devnode history");let o=Xo();Qo(et.join(o,".foundry","anvil","tmp"),{recursive:!0,force:!0});let r=["-b",String(e),"--block-base-fee-per-gas","0"];console.log(`Running: anvil ${r.join(" ")}`);let t=ot("anvil",r,{stdio:["inherit","inherit","inherit"]});process.on("SIGINT",()=>{console.log(`
|
2
|
-
gracefully shutting down from SIGINT (Crtl-C)`),t.kill(),process.exit()}),await t}},ge=tt;import{FaucetServiceDefinition as rt}from"@latticexyz/services/faucet";import{createChannel as nt,createClient as st}from"nice-grpc-web";import be from"chalk";import{NodeHttpTransport as it}from"@improbable-eng/grpc-web-node-http-transport";function at(e){return st(rt,nt(e,it()))}var ct={command:"faucet",describe:"Interact with a MUD faucet",builder(e){return e.options({dripDev:{type:"boolean",desc:"Request a drip from the dev endpoint (requires faucet to have dev mode enabled)",default:!0},faucetUrl:{type:"string",desc:"URL of the MUD faucet",default:"https://faucet.testnet-mud-services.linfra.xyz"},address:{type:"string",desc:"Ethereum address to fund",required:!0}})},async handler({dripDev:e,faucetUrl:o,address:r}){let t=at(o);e&&(console.log(be.yellow("Dripping to",r)),await t.dripDev({address:r}),console.log(be.yellow("Success"))),process.exit(0)}},he=ct;var dt={command:"hello <name>",describe:"Greet <name> with Hello",builder(e){return e.options({upper:{type:"boolean"}}).positional("name",{type:"string",demandOption:!0})},handler({name:e}){let o=`Gm, ${e}!`;console.log(o),process.exit(0)}},we=dt;import lt from"path";import{loadConfig as mt}from"@latticexyz/config/node";import{tablegen as pt}from"@latticexyz/store/codegen";import{getRemappings as ft,getSrcDirectory as yt}from"@latticexyz/common/foundry";var ut={command:"tablegen",describe:"Autogenerate MUD Store table libraries based on the config file",builder(e){return e.options({configPath:{type:"string",desc:"Path to the config file"}})},async handler({configPath:e}){let o=await mt(e),r=await yt(),t=await ft();await pt(o,lt.join(r,o.codegenDirectory),t),process.exit(0)}},xe=ut;import de from"node:path";import{existsSync as cn,mkdirSync as dn,readFileSync as ln,writeFileSync as le}from"node:fs";import{getAddress as lo}from"viem";import{getBytecode as ht,sendRawTransaction as wt,sendTransaction as xt,waitForTransactionReceipt as Se}from"viem/actions";var P={gasPrice:1e11,gasLimit:1e5,signerAddress:"3fab184622dc19b6109349b94811493bf2a45362",transaction:"f8a58085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222",address:"4e59b44847b379578588920ca78fbf26c0b4956c"};var d=M.extend("deploy"),bt=M.extend("deploy");d.log=console.debug.bind(console);bt.log=console.error.bind(console);var S=`0x${P.address}`;async function Ce(e){if(await ht(e,{address:S})){d("found create2 deployer at",S);return}d("sending gas for create2 deployer to signer at",P.signerAddress);let r=await xt(e,{chain:e.chain??null,to:`0x${P.signerAddress}`,value:BigInt(P.gasLimit)*BigInt(P.gasPrice)}),t=await Se(e,{hash:r});if(t.status!=="success")throw console.error("failed to send gas to deployer signer",t),new Error("failed to send gas to deployer signer");d("deploying create2 deployer at",S);let n=await wt(e,{serializedTransaction:`0x${P.transaction}`}),s=await Se(e,{hash:n});if(s.contractAddress!==S)throw console.error("unexpected contract address for deployer",s),new Error("unexpected contract address for deployer")}import{waitForTransactionReceipt as Xt}from"viem/actions";import ke from"@latticexyz/world/out/AccessManagementSystem.sol/AccessManagementSystem.json"assert{type:"json"};import Ie from"@latticexyz/world/out/BalanceTransferSystem.sol/BalanceTransferSystem.json"assert{type:"json"};import Oe from"@latticexyz/world/out/BatchCallSystem.sol/BatchCallSystem.json"assert{type:"json"};import Be from"@latticexyz/world/out/RegistrationSystem.sol/RegistrationSystem.json"assert{type:"json"};import je from"@latticexyz/world/out/InitModule.sol/InitModule.json"assert{type:"json"};import Rt from"@latticexyz/world/out/InitModule.sol/InitModule.abi.json"assert{type:"json"};import Pe from"@latticexyz/world/out/WorldFactory.sol/WorldFactory.json"assert{type:"json"};import Ht from"@latticexyz/world/out/WorldFactory.sol/WorldFactory.abi.json"assert{type:"json"};import{getCreate2Address as W,encodeDeployData as R,size as H}from"viem";import{padHex as Ct}from"viem";import vt from"@latticexyz/store/mud.config";import Dt from"@latticexyz/world/mud.config";import Tt from"@latticexyz/world/out/IBaseWorld.sol/IBaseWorld.abi.json"assert{type:"json"};import At from"@latticexyz/world-modules/out/IModule.sol/IModule.abi.json"assert{type:"json"};import{resourceToHex as St}from"@latticexyz/common";import{resolveUserTypes as ve}from"@latticexyz/store";function z(e){let o={...e.userTypes,...Object.fromEntries(Object.entries(e.enums).map(([r])=>[r,{internalType:"uint8"}]))};return Object.fromEntries(Object.entries(e.tables).map(([r,t])=>[`${e.namespace}_${r}`,{namespace:e.namespace,name:t.name,tableId:St({type:t.offchainOnly?"offchainTable":"table",namespace:e.namespace,name:t.name}),keySchema:ve(t.keySchema,o),valueSchema:ve(t.valueSchema,o)}]))}import{helloStoreEvent as kt}from"@latticexyz/store";import{helloWorldEvent as It}from"@latticexyz/world";var D=Ct("0x",{size:32}),U=parseInt("6000",16),F=z(vt),T=z(Dt),K=[kt,It],v=[...Tt,...At],De=["1.0.0-unaudited"],Te=["1.0.0-unaudited"];import{waitForTransactionReceipt as Wt}from"viem/actions";import{concatHex as Ot,getCreate2Address as Bt}from"viem";import{getBytecode as jt}from"viem/actions";import{sendTransaction as Pt}from"@latticexyz/common";import Mt from"p-retry";import{wait as Ft}from"@latticexyz/common/utils";async function Ae({client:e,bytecode:o,deployedBytecodeSize:r,label:t="contract"}){let n=Bt({from:S,salt:D,bytecode:o});return await jt(e,{address:n,blockTag:"pending"})?(d("found",t,"at",n),[]):(r>U?console.warn(`
|
3
|
-
Bytecode for ${t} (${r} bytes) is over the contract size limit (${U} bytes). Run \`forge build --sizes\` for more info.
|
4
|
-
`):r>U*.95&&console.warn(`
|
5
|
-
Bytecode for ${t} (${r} bytes) is almost over the contract size limit (${U} bytes). Run \`forge build --sizes\` for more info.
|
6
|
-
`),d("deploying",t,"at",n),[await Mt(()=>Pt(e,{chain:e.chain??null,to:S,data:Ot([D,o])}),{retries:3,onFailedAttempt:async a=>{let i=a.attemptNumber*500;d(`failed to deploy ${t}, retrying in ${i}ms...`),await Ft(i)}})])}async function O({client:e,contracts:o}){let r=(await Promise.all(o.map(t=>Ae({client:e,...t})))).flat();if(r.length){d("waiting for contracts");for(let t of r)await Wt(e,{hash:t})}return r}var $t=H(ke.deployedBytecode.object),Me=R({bytecode:ke.bytecode.object,abi:[]}),Et=W({from:S,bytecode:Me,salt:D}),Nt=H(Ie.deployedBytecode.object),Fe=R({bytecode:Ie.bytecode.object,abi:[]}),zt=W({from:S,bytecode:Fe,salt:D}),Ut=H(Oe.deployedBytecode.object),We=R({bytecode:Oe.bytecode.object,abi:[]}),Vt=W({from:S,bytecode:We,salt:D}),_t=H(Be.deployedBytecode.object),Re=R({bytecode:Be.bytecode.object,abi:[]}),Lt=W({from:S,bytecode:Re,salt:D}),Kt=H(je.deployedBytecode.object),He=R({bytecode:je.bytecode.object,abi:Rt,args:[Et,zt,Vt,Lt]}),Jt=W({from:S,bytecode:He,salt:D}),qt=H(Pe.deployedBytecode.object),$e=R({bytecode:Pe.bytecode.object,abi:Ht,args:[Jt]}),Ee=W({from:S,bytecode:$e,salt:D}),ee=[{bytecode:Me,deployedBytecodeSize:$t,label:"access management system"},{bytecode:Fe,deployedBytecodeSize:Nt,label:"balance transfer system"},{bytecode:We,deployedBytecodeSize:Ut,label:"batch call system"},{bytecode:Re,deployedBytecodeSize:_t,label:"core registration system"},{bytecode:He,deployedBytecodeSize:Kt,label:"core module"},{bytecode:$e,deployedBytecodeSize:qt,label:"world factory"}];async function Ne(e){return await O({client:e,contracts:ee})}import er from"@latticexyz/world/out/WorldFactory.sol/WorldFactory.abi.json"assert{type:"json"};import{writeContract as or}from"@latticexyz/common";import{AbiEventSignatureNotFoundError as Gt,decodeEventLog as Yt,hexToString as ze,parseAbi as Zt,trim as Ue}from"viem";import{isDefined as Qt}from"@latticexyz/common/utils";function J(e){let o=e.map(a=>{try{return{...a,...Yt({strict:!0,abi:Zt(K),topics:a.topics,data:a.data})}}catch(i){if(i instanceof Gt)return;throw i}}).filter(Qt),{address:r,deployBlock:t,worldVersion:n,storeVersion:s}=o.reduce((a,i)=>({...a,address:i.address,deployBlock:i.blockNumber,...i.eventName==="HelloWorld"?{worldVersion:ze(Ue(i.args.worldVersion,{dir:"right"}))}:null,...i.eventName==="HelloStore"?{storeVersion:ze(Ue(i.args.storeVersion,{dir:"right"}))}:null}),{});if(r==null)throw new Error("could not find world address");if(t==null)throw new Error("could not find world deploy block number");if(n==null)throw new Error("could not find world version");if(s==null)throw new Error("could not find store version");return{address:r,deployBlock:t,worldVersion:n,storeVersion:s}}async function Ve(e,o){await Ne(e),d("deploying world");let r=await or(e,{chain:e.chain??null,address:Ee,abi:er,functionName:"deployWorld",args:[o]});d("waiting for world deploy");let t=await Xt(e,{hash:r});if(t.status!=="success")throw console.error("world deploy failed",t),new Error("world deploy failed");let n=J(t.logs.map(s=>s));return d("deployed world to",n.address,"at block",n.deployBlock),{...n,stateBlock:n.deployBlock}}import{writeContract as cr}from"@latticexyz/common";import{valueSchemaToFieldLayoutHex as dr,keySchemaToHex as lr,valueSchemaToHex as mr}from"@latticexyz/protocol-parser";function C({namespace:e,name:o}){return`${e}:${o}`}import{parseAbiItem as tr,decodeAbiParameters as _e,parseAbiParameters as Le}from"viem";import{hexToResource as rr}from"@latticexyz/common";import{storeSetRecordEvent as nr}from"@latticexyz/store";import{getLogs as sr}from"viem/actions";import{decodeKey as ir,decodeValueArgs as ar,hexToSchema as Ke}from"@latticexyz/protocol-parser";async function Je({client:e,worldDeploy:o}){d("looking up tables for",o.address);let t=(await sr(e,{strict:!0,fromBlock:o.deployBlock,toBlock:o.stateBlock,address:o.address,event:tr(nr),args:{tableId:F.store_Tables.tableId}})).map(n=>{let{tableId:s}=ir(F.store_Tables.keySchema,n.args.keyTuple),{namespace:a,name:i}=rr(s),p=ar(F.store_Tables.valueSchema,n.args),l=Ke(p.keySchema),f=Ke(p.valueSchema),y=_e(Le("string[]"),p.abiEncodedKeyNames)[0],u=_e(Le("string[]"),p.abiEncodedFieldNames)[0],m=[...f.staticFields,...f.dynamicFields],b=Object.fromEntries(l.staticFields.map((x,c)=>[y[c],x])),w=Object.fromEntries(m.map((x,c)=>[u[c],x]));return{namespace:a,name:i,tableId:s,keySchema:b,valueSchema:w}});return d("found",t.length,"tables for",o.address),t}import pr from"p-retry";import{wait as fr}from"@latticexyz/common/utils";async function qe({client:e,worldDeploy:o,tables:r}){let n=(await Je({client:e,worldDeploy:o})).map(i=>i.tableId),s=r.filter(i=>n.includes(i.tableId));s.length&&d("existing tables",s.map(C).join(", "));let a=r.filter(i=>!n.includes(i.tableId));return a.length?(d("registering tables",a.map(C).join(", ")),await Promise.all(a.map(i=>pr(()=>cr(e,{chain:e.chain??null,address:o.address,abi:v,functionName:"registerTable",args:[i.tableId,dr(i.valueSchema),lr(i.keySchema),mr(i.valueSchema),Object.keys(i.keySchema),Object.keys(i.valueSchema)]}),{retries:3,onFailedAttempt:async p=>{let l=p.attemptNumber*500;d(`failed to register table ${C(i)}, retrying in ${l}ms...`),await fr(l)}})))):[]}import{getAddress as A}from"viem";import{writeContract as oe}from"@latticexyz/common";import{parseAbiItem as yr}from"viem";import{getLogs as ur}from"viem/actions";import{storeSpliceStaticDataEvent as gr}from"@latticexyz/store";async function q({client:e,worldDeploy:o}){d("looking up resource IDs for",o.address);let t=(await ur(e,{strict:!0,address:o.address,fromBlock:o.deployBlock,toBlock:o.stateBlock,event:yr(gr),args:{tableId:F.store_ResourceIds.tableId}})).map(n=>n.args.keyTuple[0]);return d("found",t.length,"resource IDs for",o.address),t}import{hexToResource as jr}from"@latticexyz/common";import{decodeValueArgs as br,encodeKey as hr}from"@latticexyz/protocol-parser";import{readContract as wr}from"viem/actions";async function B({client:e,worldDeploy:o,table:r,key:t}){let[n,s,a]=await wr(e,{blockNumber:o.stateBlock,address:o.address,abi:v,functionName:"getRecord",args:[r.tableId,hr(r.keySchema,t)]});return br(r.valueSchema,{staticData:n,encodedLengths:s,dynamicData:a})}import{getFunctionSelector as xr,parseAbiItem as Sr}from"viem";import{storeSetRecordEvent as Cr}from"@latticexyz/store";import{getLogs as vr}from"viem/actions";import{decodeValueArgs as Dr}from"@latticexyz/protocol-parser";import{hexToResource as Tr}from"@latticexyz/common";async function G({client:e,worldDeploy:o}){d("looking up function signatures for",o.address);let t=(await vr(e,{strict:!0,fromBlock:o.deployBlock,toBlock:o.stateBlock,address:o.address,event:Sr(Cr),args:{tableId:T.world_FunctionSignatures.tableId}})).map(s=>Dr(T.world_FunctionSignatures.valueSchema,s.args).functionSignature);return d("found",t.length,"function signatures for",o.address),await Promise.all(t.map(async s=>{let a=xr(s),{systemId:i,systemFunctionSelector:p}=await B({client:e,worldDeploy:o,table:T.world_FunctionSelectors,key:{functionSelector:a}}),{namespace:l,name:f}=Tr(i),y=l===""?s:s.replace(`${l}_${f}_`,"");return{signature:s,selector:a,systemId:i,systemFunctionSignature:y,systemFunctionSelector:p}}))}import{parseAbiItem as Ar,getAddress as kr}from"viem";import{storeSpliceStaticDataEvent as Ir}from"@latticexyz/store";import{getLogs as Or}from"viem/actions";import{decodeKey as Br}from"@latticexyz/protocol-parser";async function Y({client:e,worldDeploy:o}){d("looking up resource access for",o.address);let t=(await Or(e,{strict:!0,fromBlock:o.deployBlock,toBlock:o.stateBlock,address:o.address,event:Ar(Ir),args:{tableId:T.world_ResourceAccess.tableId}})).map(s=>Br(T.world_ResourceAccess.keySchema,s.args.keyTuple)),n=(await Promise.all(t.map(async s=>[s,await B({client:e,worldDeploy:o,table:T.world_ResourceAccess,key:s})]))).filter(([,s])=>s.access).map(([s])=>({resourceId:s.resourceId,address:kr(s.caller)}));return d("found",n.length,"resource<>address access pairs"),n}async function Ge({client:e,worldDeploy:o}){let[r,t,n]=await Promise.all([q({client:e,worldDeploy:o}),G({client:e,worldDeploy:o}),Y({client:e,worldDeploy:o})]),s=r.map(jr).filter(a=>a.type==="system");return d("looking up systems",s.map(C).join(", ")),await Promise.all(s.map(async a=>{let{system:i,publicAccess:p}=await B({client:e,worldDeploy:o,table:T.world_Systems,key:{systemId:a.resourceId}}),l=t.filter(f=>f.systemId===a.resourceId);return{address:i,namespace:a.namespace,name:a.name,systemId:a.resourceId,allowAll:p,allowedAddresses:n.filter(({resourceId:f})=>f===a.resourceId).map(({address:f})=>f),functions:l}}))}import{uniqueBy as Pr,wait as te}from"@latticexyz/common/utils";import re from"p-retry";async function Ye({client:e,worldDeploy:o,systems:r}){let[t,n]=await Promise.all([Ge({client:e,worldDeploy:o}),Y({client:e,worldDeploy:o})]),s=r.map(c=>c.systemId),a=n.filter(({resourceId:c})=>s.includes(c)),i=r.flatMap(c=>c.allowedAddresses.map(g=>({resourceId:c.systemId,address:g}))),p=i.filter(c=>!a.some(({resourceId:g,address:h})=>g===c.resourceId&&A(h)===A(c.address))),l=a.filter(c=>!i.some(({resourceId:g,address:h})=>g===c.resourceId&&A(h)===A(c.address)));l.length&&d("revoking",l.length,"access grants"),p.length&&d("adding",p.length,"access grants");let f=[...l.map(c=>re(()=>oe(e,{chain:e.chain??null,address:o.address,abi:v,functionName:"revokeAccess",args:[c.resourceId,c.address]}),{retries:3,onFailedAttempt:async g=>{let h=g.attemptNumber*500;d(`failed to revoke access, retrying in ${h}ms...`),await te(h)}})),...p.map(c=>re(()=>oe(e,{chain:e.chain??null,address:o.address,abi:v,functionName:"grantAccess",args:[c.resourceId,c.address]}),{retries:3,onFailedAttempt:async g=>{let h=g.attemptNumber*500;d(`failed to grant access, retrying in ${h}ms...`),await te(h)}}))],y=r.filter(c=>t.some(g=>g.systemId===c.systemId&&A(g.address)===A(c.address)));y.length&&d("existing systems",y.map(C).join(", "));let u=y.map(c=>c.systemId),m=r.filter(c=>!u.includes(c.systemId));if(!m.length)return[];let b=m.filter(c=>t.some(g=>g.systemId===c.systemId&&A(g.address)!==A(c.address)));b.length&&d("upgrading systems",b.map(C).join(", "));let w=m.filter(c=>!t.some(g=>g.systemId===c.systemId));w.length&&d("registering new systems",w.map(C).join(", ")),await O({client:e,contracts:Pr(m,c=>A(c.address)).map(c=>({bytecode:c.bytecode,deployedBytecodeSize:c.deployedBytecodeSize,label:`${C(c)} system`}))});let x=m.map(c=>re(()=>oe(e,{chain:e.chain??null,address:o.address,abi:v,functionName:"registerSystem",args:[c.systemId,c.address,c.allowAll]}),{retries:3,onFailedAttempt:async g=>{let h=g.attemptNumber*500;d(`failed to register system ${C(c)}, retrying in ${h}ms...`),await te(h)}}));return await Promise.all([...f,...x])}import{waitForTransactionReceipt as mo}from"viem/actions";import{getAddress as Mr,parseAbi as Fr}from"viem";import{getBlockNumber as Wr,getLogs as Rr}from"viem/actions";var Ze=new Map;async function Qe(e,o){let r=Mr(o),t=Ze.get(r);if(t!=null)return t;d("looking up world deploy for",r);let n=await Wr(e),s=await Rr(e,{strict:!0,address:r,events:Fr(K),fromBlock:"earliest",toBlock:n});return t={...J(s),stateBlock:n},Ze.set(r,t),d("found world deploy for",r,"at block",t.deployBlock),t}import{hexToResource as Hr,writeContract as Xe}from"@latticexyz/common";import eo from"p-retry";import{wait as oo}from"@latticexyz/common/utils";async function to({client:e,worldDeploy:o,functions:r}){let t=await G({client:e,worldDeploy:o}),n=Object.fromEntries(t.map(i=>[i.selector,i])),s=r.filter(i=>n[i.selector]),a=r.filter(i=>!s.includes(i));if(s.length){d("functions already registered:",s.map(p=>p.signature).join(", "));let i=s.filter(p=>p.systemId!==n[p.selector]?.systemId);i.length&&console.warn("found",i.length,"functions already registered but pointing at a different system ID:",i.map(p=>p.signature).join(", "))}return a.length?(d("registering functions:",a.map(i=>i.signature).join(", ")),Promise.all(a.map(i=>{let{namespace:p}=Hr(i.systemId);return p===""?eo(()=>Xe(e,{chain:e.chain??null,address:o.address,abi:v,functionName:"registerRootFunctionSelector",args:[i.systemId,i.systemFunctionSignature,i.systemFunctionSelector]}),{retries:3,onFailedAttempt:async l=>{let f=l.attemptNumber*500;d(`failed to register function ${i.signature}, retrying in ${f}ms...`),await oo(f)}}):eo(()=>Xe(e,{chain:e.chain??null,address:o.address,abi:v,functionName:"registerFunctionSelector",args:[i.systemId,i.systemFunctionSignature]}),{retries:3,onFailedAttempt:async l=>{let f=l.attemptNumber*500;d(`failed to register function ${i.signature}, retrying in ${f}ms...`),await oo(f)}})}))):[]}import{BaseError as $r,getAddress as Er}from"viem";import{writeContract as ro}from"@latticexyz/common";import{isDefined as Nr,uniqueBy as zr,wait as Ur}from"@latticexyz/common/utils";import Vr from"p-retry";async function no({client:e,worldDeploy:o,modules:r}){return r.length?(await O({client:e,contracts:zr(r,t=>Er(t.address)).map(t=>({bytecode:t.bytecode,deployedBytecodeSize:t.deployedBytecodeSize,label:`${t.name} module`}))}),d("installing modules:",r.map(t=>t.name).join(", ")),(await Promise.all(r.map(t=>Vr(async()=>{try{return t.installAsRoot?await ro(e,{chain:e.chain??null,address:o.address,abi:v,functionName:"installRootModule",args:[t.address,t.installData]}):await ro(e,{chain:e.chain??null,address:o.address,abi:v,functionName:"installModule",args:[t.address,t.installData]})}catch(n){if(n instanceof $r&&n.message.includes("Module_AlreadyInstalled")){d(`module ${t.name} already installed`);return}throw n}},{retries:3,onFailedAttempt:async n=>{let s=n.attemptNumber*500;d(`failed to install module ${t.name}, retrying in ${s}ms...`),await Ur(s)}})))).filter(Nr)):[]}import{getAddress as so}from"viem";import{hexToResource as io,resourceToHex as ao,writeContract as _r}from"@latticexyz/common";async function co({client:e,worldDeploy:o,resourceIds:r}){let t=Array.from(new Set(r.map(y=>io(y).namespace))),n=await q({client:e,worldDeploy:o}),s=new Set(n.map(y=>io(y).namespace));s.size&&d("found",s.size,"existing namespaces:",Array.from(s).map(y=>y===""?"<root>":y).join(", "));let a=t.filter(y=>s.has(y)),p=(await Promise.all(a.map(async y=>{let{owner:u}=await B({client:e,worldDeploy:o,table:T.world_NamespaceOwner,key:{namespaceId:ao({type:"namespace",namespace:y,name:""})}});return[y,u]}))).filter(([,y])=>so(y)!==so(e.account.address)).map(([y])=>y);if(p.length)throw new Error(`You are attempting to deploy to namespaces you do not own: ${p.join(", ")}`);let l=t.filter(y=>!s.has(y));return l.length>0&&d("registering namespaces",Array.from(l).join(", ")),Promise.all(l.map(y=>_r(e,{chain:e.chain??null,address:o.address,abi:v,functionName:"registerNamespace",args:[ao({namespace:y,type:"namespace",name:""})]})))}import{uniqueBy as po}from"@latticexyz/common/utils";import{randomBytes as Lr}from"crypto";async function fo({client:e,config:o,salt:r,worldAddress:t}){let n=Object.values(o.tables),s=Object.values(o.systems);await Ce(e),await O({client:e,contracts:[...ee,...po(s,m=>lo(m.address)).map(m=>({bytecode:m.bytecode,deployedBytecodeSize:m.deployedBytecodeSize,label:`${C(m)} system`})),...po(o.modules,m=>lo(m.address)).map(m=>({bytecode:m.bytecode,deployedBytecodeSize:m.deployedBytecodeSize,label:`${m.name} module`}))]});let a=t?await Qe(e,t):await Ve(e,r||`0x${Lr(32).toString("hex")}`);if(!De.includes(a.storeVersion))throw new Error(`Unsupported Store version: ${a.storeVersion}`);if(!Te.includes(a.worldVersion))throw new Error(`Unsupported World version: ${a.worldVersion}`);let i=await co({client:e,worldDeploy:a,resourceIds:[...n.map(m=>m.tableId),...s.map(m=>m.systemId)]});d("waiting for all namespace registration transactions to confirm");for(let m of i)await mo(e,{hash:m});let p=await qe({client:e,worldDeploy:a,tables:n}),l=await Ye({client:e,worldDeploy:a,systems:s}),f=await to({client:e,worldDeploy:a,functions:s.flatMap(m=>m.functions)}),y=await no({client:e,worldDeploy:a,modules:o.modules}),u=[...p,...l,...f,...y];d("waiting for all transactions to confirm");for(let m of u)await mo(e,{hash:m});return d("deploy complete"),a}import{createWalletClient as mn,http as pn,isHex as fn}from"viem";import{privateKeyToAccount as yn}from"viem/accounts";import{loadConfig as un}from"@latticexyz/config/node";import{getOutDirectory as gn,getRpcUrl as bn,getSrcDirectory as hn}from"@latticexyz/common/foundry";import $ from"chalk";import{MUDError as xo}from"@latticexyz/common/errors";import{resolveWorldConfig as Gr}from"@latticexyz/world";import{resourceToHex as ce,hexToResource as Yr}from"@latticexyz/common";import{resolveWithContext as Zr}from"@latticexyz/config";import{encodeField as Qr}from"@latticexyz/protocol-parser";import{getFunctionSelector as uo,getCreate2Address as go,getAddress as Xr,hexToBytes as en,bytesToHex as on,getFunctionSignature as bo}from"viem";import ne from"@latticexyz/world-modules/out/KeysWithValueModule.sol/KeysWithValueModule.json"assert{type:"json"};import se from"@latticexyz/world-modules/out/KeysInTableModule.sol/KeysInTableModule.json"assert{type:"json"};import ie from"@latticexyz/world-modules/out/UniqueEntityModule.sol/UniqueEntityModule.json"assert{type:"json"};import{size as ae}from"viem";var yo=[{name:"KeysWithValueModule",abi:ne.abi,bytecode:ne.bytecode.object,deployedBytecodeSize:ae(ne.deployedBytecode.object)},{name:"KeysInTableModule",abi:se.abi,bytecode:se.bytecode.object,deployedBytecodeSize:ae(se.deployedBytecode.object)},{name:"UniqueEntityModule",abi:ie.abi,bytecode:ie.bytecode.object,deployedBytecodeSize:ae(ie.deployedBytecode.object)}];import{readFileSync as Kr}from"fs";import Jr from"path";import{MUDError as Z}from"@latticexyz/common/errors";import{size as qr}from"viem";function Q(e,o){let r,t=Jr.join(o,e+".sol",e+".json");try{r=JSON.parse(Kr(t,"utf8"))}catch{throw new Z(`Error reading file at ${t}`)}let n=r?.bytecode?.object;if(!n)throw new Z(`No bytecode found in ${t}`);let s=r?.deployedBytecode?.object;if(!s)throw new Z(`No deployed bytecode found in ${t}`);let a=r?.abi;if(!a)throw new Z(`No ABI found in ${t}`);return{abi:a,bytecode:n,deployedBytecodeSize:qr(s)}}function ho({config:e,forgeSourceDir:o,forgeOutDir:r}){let t=z(e),n=I(o).map(({basename:u})=>u),s=Gr(e,n),i=Q("System",r).abi.filter(u=>u.type==="function").map(bo),p=Object.entries(s.systems).map(([u,m])=>{let b=e.namespace,w=m.name,x=ce({type:"system",namespace:b,name:w}),c=Q(u,r),g=c.abi.filter(h=>h.type==="function").map(bo).filter(h=>!i.includes(h)).map(h=>{let fe=b===""?h:`${b}__${h}`;return{signature:fe,selector:uo(fe),systemId:x,systemFunctionSignature:h,systemFunctionSelector:uo(h)}});return{namespace:b,name:w,systemId:x,allowAll:m.openAccess,allowedAddresses:m.accessListAddresses,allowedSystemIds:m.accessListSystems.map(h=>ce({type:"system",namespace:b,name:s.systems[h].name})),address:go({from:S,bytecode:c.bytecode,salt:D}),bytecode:c.bytecode,deployedBytecodeSize:c.deployedBytecodeSize,abi:c.abi,functions:g}}),l=p.map(({allowedAddresses:u,allowedSystemIds:m,...b})=>{let w=m.map(x=>{let c=p.find(g=>g.systemId===x);if(!c)throw new Error(`System ${C(b)} wanted access to ${C(Yr(x))}, but it wasn't found in the config.`);return c.address});return{...b,allowedAddresses:Array.from(new Set([...u,...w].map(x=>Xr(x))))}}),f={tableIds:Object.fromEntries(Object.entries(e.tables).map(([u,m])=>[u,en(ce({type:m.offchainOnly?"offchainTable":"table",namespace:e.namespace,name:m.name}))]))},y=e.modules.map(u=>{let m=yo.find(w=>w.name===u.name)??Q(u.name,r),b=u.args.map(w=>Zr(w,f)).map(w=>{let x=w.value instanceof Uint8Array?on(w.value):w.value;return Qr(w.type,x)});if(b.length>1)throw new Error(`${u.name} module should only have 0-1 args, but had ${b.length} args.`);return{name:u.name,installAsRoot:u.root,installData:b.length===0?"0x":b[0],address:go({from:S,bytecode:m.bytecode,salt:D}),bytecode:m.bytecode,deployedBytecodeSize:m.deployedBytecodeSize,abi:m.abi}});return{tables:t,systems:l,modules:y}}import{getChainId as wn}from"viem/actions";import{existsSync as tn}from"fs";import rn from"path";import nn from"chalk";import{getScriptDirectory as sn,forge as an}from"@latticexyz/common/foundry";async function wo(e,o,r,t){let n=rn.join(await sn(),e+".s.sol");tn(n)?(console.log(nn.blue(`Executing post deploy script at ${n}`)),await an(["script",e,"--sig","run(address)",o,"--broadcast","--rpc-url",r,"-vvv"],{profile:t})):console.log(`No script at ${n}, skipping post deploy hook`)}var k={configPath:{type:"string",desc:"Path to the config file"},printConfig:{type:"boolean",desc:"Print the resolved config"},profile:{type:"string",desc:"The foundry profile to use"},saveDeployment:{type:"boolean",desc:"Save the deployment info to a file",default:!0},rpc:{type:"string",desc:"The RPC URL to use. Defaults to the RPC url from the local foundry.toml"},worldAddress:{type:"string",desc:"Deploy to an existing World at the given address"},srcDir:{type:"string",desc:"Source directory. Defaults to foundry src directory."},skipBuild:{type:"boolean",desc:"Skip rebuilding the contracts before deploying"},alwaysRunPostDeploy:{type:"boolean",desc:"Always run PostDeploy.s.sol after each deploy (including during upgrades). By default, PostDeploy.s.sol is only run once after a new world is deployed."},salt:{type:"string",desc:"The deployment salt to use. Defaults to a random salt."}};async function E(e){let o=e.salt;if(o!=null&&!fn(o))throw new xo("Expected hex string for salt");let r=e.profile??process.env.FOUNDRY_PROFILE,t=await un(e.configPath);e.printConfig&&console.log($.green(`
|
7
|
-
Resolved config:
|
8
|
-
`),JSON.stringify(t,null,2));let n=e.srcDir??await hn(r),s=await gn(r),a=e.rpc??await bn(r);console.log($.bgBlue($.whiteBright(`
|
9
|
-
Deploying MUD contracts${r?" with profile "+r:""} to RPC ${a}
|
10
|
-
`))),e.skipBuild||await L({config:t,srcDir:n,foundryProfile:r});let i=process.env.PRIVATE_KEY;if(!i)throw new xo(`Missing PRIVATE_KEY environment variable.
|
11
|
-
Run 'echo "PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" > .env'
|
12
|
-
in your contracts directory to use the default anvil private key.`);let p=ho({config:t,forgeSourceDir:n,forgeOutDir:s}),l=mn({transport:pn(a),account:yn(i)});console.log("Deploying from",l.account.address);let f=Date.now(),y=await fo({salt:o,worldAddress:e.worldAddress,client:l,config:p});(e.worldAddress==null||e.alwaysRunPostDeploy)&&await wo(t.postDeployScript,y.address,a,r),console.log($.green("Deployment completed in",(Date.now()-f)/1e3,"seconds"));let u={worldAddress:y.address,blockNumber:Number(y.deployBlock)};if(e.saveDeployment){let m=await wn(l),b=de.join(t.deploysDirectory,m.toString());dn(b,{recursive:!0}),le(de.join(b,"latest.json"),JSON.stringify(u,null,2)),le(de.join(b,Date.now()+".json"),JSON.stringify(u,null,2));let w=[1337,31337],x=cn(t.worldsFile)?JSON.parse(ln(t.worldsFile,"utf-8")):{};x[m]={address:u.worldAddress,blockNumber:w.includes(m)?void 0:u.blockNumber},le(t.worldsFile,JSON.stringify(x,null,2)),console.log($.bgGreen($.whiteBright(`
|
13
|
-
Deployment result (written to ${t.worldsFile} and ${b}):
|
14
|
-
`)))}return console.log(u),y}var xn={command:"deploy",describe:"Deploy MUD contracts",builder(e){return e.options(k)},async handler(e){try{await E(e)}catch(o){_(o),process.exit(1)}process.exit(0)}},So=xn;import{loadConfig as Sn}from"@latticexyz/config/node";import{worldgen as Cn}from"@latticexyz/world/node";import{getSrcDirectory as vn}from"@latticexyz/common/foundry";import Co from"path";import{rmSync as Dn}from"fs";var Tn={command:"worldgen",describe:"Autogenerate interfaces for Systems and World based on existing contracts and the config file",builder(e){return e.options({configPath:{type:"string",desc:"Path to the config file"},clean:{type:"boolean",desc:"Clear the worldgen directory before generating new interfaces (defaults to true)",default:!0}})},async handler(e){await An(e),process.exit(0)}};async function An(e){let o=e.srcDir??await vn(),r=I(o),t=e.config??await Sn(e.configPath),n=Co.join(o,t.codegenDirectory);e.clean&&Dn(Co.join(n,t.worldgenDirectory),{recursive:!0,force:!0}),await Cn(t,r,n)}var vo=Tn;import V from"chalk";import{readFileSync as jn,writeFileSync as Pn}from"fs";import pe from"path";import{MUDError as N}from"@latticexyz/common/errors";var Do={name:"@latticexyz/cli",version:"2.0.0-next.17",description:"Command line interface for mud",repository:{type:"git",url:"https://github.com/latticexyz/mud.git",directory:"packages/cli"},license:"MIT",type:"module",exports:{".":"./dist/index.js"},types:"src/index.ts",bin:{mud:"./dist/mud.js"},scripts:{build:"pnpm run build:js && pnpm run build:test-tables","build:js":"tsup && chmod +x ./dist/mud.js","build:test-tables":"tsx ./scripts/generate-test-tables.ts",clean:"pnpm run clean:js && pnpm run clean:test-tables","clean:js":"rimraf dist","clean:test-tables":"rimraf src/codegen",dev:"tsup --watch",lint:"eslint . --ext .ts",prepare:"mkdir -p ./dist && touch ./dist/mud.js",test:"tsc --noEmit && forge test","test:ci":"pnpm run test"},dependencies:{"@ethersproject/abi":"^5.7.0","@ethersproject/providers":"^5.7.2","@improbable-eng/grpc-web":"^0.15.0","@improbable-eng/grpc-web-node-http-transport":"^0.15.0","@latticexyz/abi-ts":"workspace:*","@latticexyz/common":"workspace:*","@latticexyz/config":"workspace:*","@latticexyz/gas-report":"workspace:*","@latticexyz/protocol-parser":"workspace:*","@latticexyz/schema-type":"workspace:*","@latticexyz/services":"workspace:*","@latticexyz/store":"workspace:*","@latticexyz/utils":"workspace:*","@latticexyz/world":"workspace:*","@latticexyz/world-modules":"workspace:*",chalk:"^5.0.1",chokidar:"^3.5.3",debug:"^4.3.4",dotenv:"^16.0.3",ejs:"^3.1.8",ethers:"^5.7.2",execa:"^7.0.0",glob:"^8.0.3","nice-grpc-web":"^2.0.1",openurl:"^1.1.1","p-retry":"^5.1.2",path:"^0.12.7",rxjs:"7.5.5","throttle-debounce":"^5.0.0",typescript:"5.1.6",viem:"1.14.0",yargs:"^17.7.1",zod:"^3.21.4","zod-validation-error":"^1.3.0"},devDependencies:{"@types/debug":"^4.1.7","@types/ejs":"^3.1.1","@types/glob":"^7.2.0","@types/node":"^18.15.11","@types/openurl":"^1.0.0","@types/throttle-debounce":"^5.0.0","@types/yargs":"^17.0.10","ds-test":"https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0","forge-std":"https://github.com/foundry-rs/forge-std.git#74cfb77e308dd188d2f58864aaf44963ae6b88b1",tsup:"^6.7.0",tsx:"^3.12.6",vitest:"0.34.6"},gitHead:"914a1e0ae4a573d685841ca2ea921435057deb8f"};import Mn from"glob";import{ZodError as In,z as To}from"zod";var On=To.object({MUD_PACKAGES:To.string().transform(e=>JSON.parse(e))});function Bn(){try{return On.parse({MUD_PACKAGES:'{"@latticexyz/abi-ts":{"localPath":"packages/abi-ts"},"@latticexyz/block-logs-stream":{"localPath":"packages/block-logs-stream"},"@latticexyz/cli":{"localPath":"packages/cli"},"@latticexyz/common":{"localPath":"packages/common"},"@latticexyz/config":{"localPath":"packages/config"},"create-mud":{"localPath":"packages/create-mud"},"@latticexyz/dev-tools":{"localPath":"packages/dev-tools"},"@latticexyz/faucet":{"localPath":"packages/faucet"},"@latticexyz/gas-report":{"localPath":"packages/gas-report"},"@latticexyz/noise":{"localPath":"packages/noise"},"@latticexyz/phaserx":{"localPath":"packages/phaserx"},"@latticexyz/protocol-parser":{"localPath":"packages/protocol-parser"},"@latticexyz/react":{"localPath":"packages/react"},"@latticexyz/recs":{"localPath":"packages/recs"},"@latticexyz/schema-type":{"localPath":"packages/schema-type"},"@latticexyz/services":{"localPath":"packages/services"},"solhint-config-mud":{"localPath":"packages/solhint-config-mud"},"solhint-plugin-mud":{"localPath":"packages/solhint-plugin-mud"},"@latticexyz/store-indexer":{"localPath":"packages/store-indexer"},"@latticexyz/store-sync":{"localPath":"packages/store-sync"},"@latticexyz/store":{"localPath":"packages/store"},"@latticexyz/utils":{"localPath":"packages/utils"},"@latticexyz/world-modules":{"localPath":"packages/world-modules"},"@latticexyz/world":{"localPath":"packages/world"}}'})}catch(e){if(e instanceof In){let{_errors:o,...r}=e.format();console.error(`
|
15
|
-
Missing or invalid environment variables:
|
16
|
-
|
17
|
-
${Object.keys(r).join(`
|
18
|
-
`)}
|
19
|
-
`),process.exit(1)}throw e}}var me=Bn().MUD_PACKAGES;var Fn={command:"set-version",describe:"Set MUD version in all package.json files and optionally backup the previously installed version",builder(e){return e.options({mudVersion:{alias:"v",type:"string",description:"Set MUD to the given version"},tag:{alias:"t",type:"string",description:"Set MUD to the latest version with the given tag from npm"},commit:{alias:"c",type:"string",description:"Set MUD to the version based on a given git commit hash from npm"},link:{alias:"l",type:"string",description:"Relative path to the local MUD root directory to link"}})},async handler(e){try{let o=["mudVersion","link","tag","commit","restore"],r=o.reduce((n,s)=>e[s]?n+1:n,0);if(r===0)throw new N(`You need to provide one these options: ${o.join(", ")}`);if(r>1)throw new N(`These options are mutually exclusive: ${o.join(", ")}`);e.link||(e.mudVersion=await Wn(e));let t=Mn.sync("**/package.json").filter(n=>!n.includes("node_modules"));for(let n of t)Rn(n,e)}catch(o){_(o)}finally{process.exit(0)}}};async function Wn(e){e.mudVersion==="canary"&&(e.tag="main");let o;try{console.log(V.blue("Fetching available versions")),o=await(await fetch(`https://registry.npmjs.org/${Do.name}`)).json()}catch{throw new N("Could not fetch available MUD versions")}if(e.tag){let r=o["dist-tags"][e.tag];if(!r)throw new N(`Could not find npm version with tag "${e.tag}"`);return console.log(V.green(`Latest version with tag ${e.tag}: ${r}`)),r}if(e.commit){let r=e.commit.substring(0,8),t=Object.keys(o.versions).find(n=>n.includes(r));if(!t)throw new N(`Could not find npm version based on commit "${e.commit}"`);return console.log(V.green(`Version from commit ${e.commit}: ${t}`)),t}return e.mudVersion}function Rn(e,o){let{link:r}=o,{mudVersion:t}=o,n=Hn(e),s=Object.keys(me),a={};for(let l in n.dependencies)s.includes(l)&&(a[l]=n.dependencies[l]);let i={};for(let l in n.devDependencies)s.includes(l)&&(i[l]=n.devDependencies[l]);for(let l in n.dependencies)s.includes(l)&&(n.dependencies[l]=p(l,"dependencies"));for(let l in n.devDependencies)s.includes(l)&&(n.devDependencies[l]=p(l,"devDependencies"));return Pn(e,JSON.stringify(n,null,2)+`
|
20
|
-
`),console.log(`Updating ${e}`),Ao(a,n.dependencies),Ao(i,n.devDependencies),n;function p(l,f){return r&&(t=$n(e,r,l)),t||n[f][l]}}function Hn(e){try{let o=jn(e,"utf8");return JSON.parse(o)}catch{throw new N("Could not read JSON at "+e)}}function Ao(e,o){for(let r in e)e[r]!==o[r]&&console.log(`${r}: ${V.red(e[r])} -> ${V.green(o[r])}`)}function $n(e,o,r){let t=pe.relative(pe.dirname(e),process.cwd());return"link:"+pe.join(t,o,me[r].localPath)}var ko=Fn;import{anvil as En,forge as Nn,getRpcUrl as zn}from"@latticexyz/common/foundry";import Un from"chalk";var Vn={...k,port:{type:"number",description:"Port to run internal node for fork testing on",default:4242},worldAddress:{type:"string",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."},forgeOptions:{type:"string",description:"Options to pass to forge test"}},_n={command:"test",describe:"Run tests in MUD contracts",builder(e){return e.options(Vn)},async handler(e){if(!e.worldAddress){let n=["--block-base-fee-per-gas","0","--port",String(e.port)];En(n)}let o=e.worldAddress?await zn(e.profile):`http://127.0.0.1:${e.port}`,r=e.worldAddress??(await E({...e,saveDeployment:!1,rpc:o})).address;console.log(Un.blue("World address",r));let t=e.forgeOptions?.replaceAll("\\","").split(" ")??[];try{await Nn(["test","--fork-url",o,...t],{profile:e.profile,env:{WORLD_ADDRESS:r}}),process.exit(0)}catch(n){console.error(n),process.exit(1)}}},Io=_n;import{existsSync as Ln,readFileSync as Kn}from"fs";import{ethers as Oo}from"ethers";import{loadConfig as Jn}from"@latticexyz/config/node";import{MUDError as Bo}from"@latticexyz/common/errors";import{cast as qn,getRpcUrl as Gn,getSrcDirectory as Yn}from"@latticexyz/common/foundry";import{resolveWorldConfig as Zn}from"@latticexyz/world";import Qn from"@latticexyz/world/out/IBaseWorld.sol/IBaseWorld.abi.json"assert{type:"json"};import jo from"@latticexyz/world/mud.config";import{resourceToHex as Mo}from"@latticexyz/common";import{createClient as Xn,http as es}from"viem";import{getChainId as os}from"viem/actions";var Po=Mo({type:"system",namespace:jo.namespace,name:jo.tables.Systems.name}),ts={command:"trace",describe:"Display the trace of a transaction",builder(e){return e.options({tx:{type:"string",required:!0,description:"Transaction hash to replay"},worldAddress:{type:"string",description:"World contract address. Defaults to the value from worlds.json, based on rpc's chainId"},configPath:{type:"string",description:"Path to the config file"},profile:{type:"string",description:"The foundry profile to use"},srcDir:{type:"string",description:"Source directory. Defaults to foundry src directory."},rpc:{type:"string",description:"json rpc endpoint. Defaults to foundry's configured eth_rpc_url"}})},async handler(e){e.profile??=process.env.FOUNDRY_PROFILE;let{profile:o}=e;e.srcDir??=await Yn(o),e.rpc??=await Gn(o);let{tx:r,configPath:t,srcDir:n,rpc:s}=e,a=I(n),i=await Jn(t),p=Zn(i,a.map(({basename:c})=>c)),l=e.worldAddress??await rs(i.worldsFile,s),f=new Oo.providers.StaticJsonRpcProvider(s),y=new Oo.Contract(l,Qn,f),u=i.namespace,m=Object.values(p.systems).map(({name:c})=>c),b=await y.getFieldLayout(Po),w=[];for(let c of m){let g=Mo({type:"system",namespace:u,name:c}),h=await y.getField(Po,[g],0,b);w.push({name:c,address:h})}let x=await qn(["run","--label",`${l}:World`,...w.map(({name:c,address:g})=>["--label",`${g}:${c}`]).flat(),`${r}`]);console.log(x),process.exit(0)}},Fo=ts;async function rs(e,o){if(Ln(e)){let r=Xn({transport:es(o)}),t=await os(r),n=JSON.parse(Kn(e,"utf-8"));if(!n[t])throw new Bo(`chainId ${t} is missing in worldsFile "${e}"`);return n[t].address}else throw new Bo("worldAddress is not specified and worldsFile is missing")}import{anvil as ns,getScriptDirectory as ss,getSrcDirectory as is}from"@latticexyz/common/foundry";import j from"chalk";import as from"chokidar";import{loadConfig as cs,resolveConfigPath as ds}from"@latticexyz/config/node";import ls from"path";import{homedir as ms}from"os";import{rmSync as ps}from"fs";import{BehaviorSubject as fs,debounceTime as ys,exhaustMap as us,filter as gs}from"rxjs";import{isDefined as bs}from"@latticexyz/common/utils";var hs={rpc:k.rpc,configPath:k.configPath,alwaysRunPostDeploy:k.alwaysRunPostDeploy,worldAddress:k.worldAddress},ws={command:"dev-contracts",describe:"Start a development server for MUD contracts",builder(e){return e.options(hs)},async handler(e){let o=e.rpc,r=e.configPath??await ds(e.configPath),t=await is(),n=await ss(),s=await cs(r);if(!e.rpc){console.log(j.gray("Cleaning devnode cache"));let l=ms();ps(ls.join(l,".foundry","anvil","tmp"),{recursive:!0,force:!0}),ns(["--block-time","1","--block-base-fee-per-gas","0"]),o="http://127.0.0.1:8545"}let a=new fs(Date.now());as.watch([r,t,n],{ignoreInitial:!0}).on("all",async(l,f)=>{f.includes(r)&&(console.log(j.blue("Config changed, queuing deploy\u2026")),a.next(Date.now())),(f.includes(t)||f.includes(n))&&(f.includes(s.codegenDirectory)||(console.log(j.blue("Contracts changed, queuing deploy\u2026")),a.next(Date.now())))});let i=e.worldAddress;a.pipe(ys(200),us(async l=>{i&&console.log(j.blue("Rebuilding and upgrading world\u2026"));try{let f=await E({...e,configPath:r,rpc:o,skipBuild:!1,printConfig:!1,profile:void 0,saveDeployment:!0,worldAddress:i,srcDir:t,salt:"0x"});return i=f.address,l<a.value?a.next(a.value):console.log(j.gray(`
|
21
|
-
Waiting for file changes\u2026
|
22
|
-
`)),f}catch(f){console.error(j.bgRed(j.whiteBright(`
|
23
|
-
Error while attempting deploy
|
24
|
-
`))),console.error(f),console.log(j.gray(`
|
25
|
-
Waiting for file changes\u2026
|
26
|
-
`))}}),gs(bs)).subscribe()}},Wo=ws;var Rp=[ue,So,ge,he,xs,we,xe,vo,ko,Io,Fo,Wo,Ss];export{Rp as commands};
|
27
|
-
//# sourceMappingURL=commands-3JV3U43E.js.map
|