@latticexyz/cli 2.0.0-next.16 → 2.0.0-next.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands-3JV3U43E.js +27 -0
- package/dist/commands-3JV3U43E.js.map +1 -0
- package/dist/mud.js +1 -1
- package/package.json +13 -13
- package/src/commands/dev-contracts.ts +1 -0
- package/src/deploy/deploy.ts +5 -2
- package/src/deploy/deployWorld.ts +6 -2
- package/src/deploy/ensureWorldFactory.ts +20 -22
- package/src/deploy/resolveConfig.ts +1 -1
- package/src/runDeploy.ts +11 -1
- package/dist/commands-DSIRJZEM.js +0 -27
- package/dist/commands-DSIRJZEM.js.map +0 -1
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@latticexyz/cli",
|
3
|
-
"version": "2.0.0-next.
|
3
|
+
"version": "2.0.0-next.17",
|
4
4
|
"description": "Command line interface for mud",
|
5
5
|
"repository": {
|
6
6
|
"type": "git",
|
@@ -40,17 +40,17 @@
|
|
40
40
|
"yargs": "^17.7.1",
|
41
41
|
"zod": "^3.21.4",
|
42
42
|
"zod-validation-error": "^1.3.0",
|
43
|
-
"@latticexyz/abi-ts": "2.0.0-next.
|
44
|
-
"@latticexyz/common": "2.0.0-next.
|
45
|
-
"@latticexyz/config": "2.0.0-next.
|
46
|
-
"@latticexyz/gas-report": "2.0.0-next.
|
47
|
-
"@latticexyz/protocol-parser": "2.0.0-next.
|
48
|
-
"@latticexyz/schema-type": "2.0.0-next.
|
49
|
-
"@latticexyz/services": "2.0.0-next.
|
50
|
-
"@latticexyz/store": "2.0.0-next.
|
51
|
-
"@latticexyz/utils": "2.0.0-next.
|
52
|
-
"@latticexyz/world": "2.0.0-next.
|
53
|
-
"@latticexyz/world-modules": "2.0.0-next.
|
43
|
+
"@latticexyz/abi-ts": "2.0.0-next.17",
|
44
|
+
"@latticexyz/common": "2.0.0-next.17",
|
45
|
+
"@latticexyz/config": "2.0.0-next.17",
|
46
|
+
"@latticexyz/gas-report": "2.0.0-next.17",
|
47
|
+
"@latticexyz/protocol-parser": "2.0.0-next.17",
|
48
|
+
"@latticexyz/schema-type": "2.0.0-next.17",
|
49
|
+
"@latticexyz/services": "2.0.0-next.17",
|
50
|
+
"@latticexyz/store": "2.0.0-next.17",
|
51
|
+
"@latticexyz/utils": "2.0.0-next.17",
|
52
|
+
"@latticexyz/world": "2.0.0-next.17",
|
53
|
+
"@latticexyz/world-modules": "2.0.0-next.17"
|
54
54
|
},
|
55
55
|
"devDependencies": {
|
56
56
|
"@types/debug": "^4.1.7",
|
@@ -64,7 +64,7 @@
|
|
64
64
|
"forge-std": "https://github.com/foundry-rs/forge-std.git#74cfb77e308dd188d2f58864aaf44963ae6b88b1",
|
65
65
|
"tsup": "^6.7.0",
|
66
66
|
"tsx": "^3.12.6",
|
67
|
-
"vitest": "0.
|
67
|
+
"vitest": "0.34.6"
|
68
68
|
},
|
69
69
|
"gitHead": "914a1e0ae4a573d685841ca2ea921435057deb8f",
|
70
70
|
"scripts": {
|
package/src/deploy/deploy.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import { Account, Address, Chain, Client, Transport, getAddress } from "viem";
|
1
|
+
import { Account, Address, Chain, Client, Hex, Transport, getAddress } from "viem";
|
2
2
|
import { ensureDeployer } from "./ensureDeployer";
|
3
3
|
import { deployWorld } from "./deployWorld";
|
4
4
|
import { ensureTables } from "./ensureTables";
|
@@ -15,10 +15,12 @@ import { resourceLabel } from "./resourceLabel";
|
|
15
15
|
import { uniqueBy } from "@latticexyz/common/utils";
|
16
16
|
import { ensureContractsDeployed } from "./ensureContractsDeployed";
|
17
17
|
import { worldFactoryContracts } from "./ensureWorldFactory";
|
18
|
+
import { randomBytes } from "crypto";
|
18
19
|
|
19
20
|
type DeployOptions<configInput extends ConfigInput> = {
|
20
21
|
client: Client<Transport, Chain | undefined, Account>;
|
21
22
|
config: Config<configInput>;
|
23
|
+
salt?: Hex;
|
22
24
|
worldAddress?: Address;
|
23
25
|
};
|
24
26
|
|
@@ -31,6 +33,7 @@ type DeployOptions<configInput extends ConfigInput> = {
|
|
31
33
|
export async function deploy<configInput extends ConfigInput>({
|
32
34
|
client,
|
33
35
|
config,
|
36
|
+
salt,
|
34
37
|
worldAddress: existingWorldAddress,
|
35
38
|
}: DeployOptions<configInput>): Promise<WorldDeploy> {
|
36
39
|
const tables = Object.values(config.tables) as Table[];
|
@@ -58,7 +61,7 @@ export async function deploy<configInput extends ConfigInput>({
|
|
58
61
|
|
59
62
|
const worldDeploy = existingWorldAddress
|
60
63
|
? await getWorldDeploy(client, existingWorldAddress)
|
61
|
-
: await deployWorld(client);
|
64
|
+
: await deployWorld(client, salt ? salt : `0x${randomBytes(32).toString("hex")}`);
|
62
65
|
|
63
66
|
if (!supportedStoreVersions.includes(worldDeploy.storeVersion)) {
|
64
67
|
throw new Error(`Unsupported Store version: ${worldDeploy.storeVersion}`);
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { Account, Chain, Client, Log, Transport } from "viem";
|
1
|
+
import { Account, Chain, Client, Hex, Log, Transport } from "viem";
|
2
2
|
import { waitForTransactionReceipt } from "viem/actions";
|
3
3
|
import { ensureWorldFactory, worldFactory } from "./ensureWorldFactory";
|
4
4
|
import WorldFactoryAbi from "@latticexyz/world/out/WorldFactory.sol/WorldFactory.abi.json" assert { type: "json" };
|
@@ -7,7 +7,10 @@ import { debug } from "./debug";
|
|
7
7
|
import { logsToWorldDeploy } from "./logsToWorldDeploy";
|
8
8
|
import { WorldDeploy } from "./common";
|
9
9
|
|
10
|
-
export async function deployWorld(
|
10
|
+
export async function deployWorld(
|
11
|
+
client: Client<Transport, Chain | undefined, Account>,
|
12
|
+
salt: Hex
|
13
|
+
): Promise<WorldDeploy> {
|
11
14
|
await ensureWorldFactory(client);
|
12
15
|
|
13
16
|
debug("deploying world");
|
@@ -16,6 +19,7 @@ export async function deployWorld(client: Client<Transport, Chain | undefined, A
|
|
16
19
|
address: worldFactory,
|
17
20
|
abi: WorldFactoryAbi,
|
18
21
|
functionName: "deployWorld",
|
22
|
+
args: [salt],
|
19
23
|
});
|
20
24
|
|
21
25
|
debug("waiting for world deploy");
|
@@ -1,9 +1,9 @@
|
|
1
1
|
import accessManagementSystemBuild from "@latticexyz/world/out/AccessManagementSystem.sol/AccessManagementSystem.json" assert { type: "json" };
|
2
2
|
import balanceTransferSystemBuild from "@latticexyz/world/out/BalanceTransferSystem.sol/BalanceTransferSystem.json" assert { type: "json" };
|
3
3
|
import batchCallSystemBuild from "@latticexyz/world/out/BatchCallSystem.sol/BatchCallSystem.json" assert { type: "json" };
|
4
|
-
import
|
5
|
-
import
|
6
|
-
import
|
4
|
+
import registrationSystemBuild from "@latticexyz/world/out/RegistrationSystem.sol/RegistrationSystem.json" assert { type: "json" };
|
5
|
+
import initModuleBuild from "@latticexyz/world/out/InitModule.sol/InitModule.json" assert { type: "json" };
|
6
|
+
import initModuleAbi from "@latticexyz/world/out/InitModule.sol/InitModule.abi.json" assert { type: "json" };
|
7
7
|
import worldFactoryBuild from "@latticexyz/world/out/WorldFactory.sol/WorldFactory.json" assert { type: "json" };
|
8
8
|
import worldFactoryAbi from "@latticexyz/world/out/WorldFactory.sol/WorldFactory.abi.json" assert { type: "json" };
|
9
9
|
import { Client, Transport, Chain, Account, Hex, getCreate2Address, encodeDeployData, size } from "viem";
|
@@ -45,33 +45,31 @@ export const batchCallSystemBytecode = encodeDeployData({
|
|
45
45
|
});
|
46
46
|
export const batchCallSystem = getCreate2Address({ from: deployer, bytecode: batchCallSystemBytecode, salt });
|
47
47
|
|
48
|
-
export const
|
49
|
-
|
50
|
-
|
51
|
-
export const coreRegistrationSystemBytecode = encodeDeployData({
|
52
|
-
bytecode: coreRegistrationSystemBuild.bytecode.object as Hex,
|
48
|
+
export const registrationDeployedBytecodeSize = size(registrationSystemBuild.deployedBytecode.object as Hex);
|
49
|
+
export const registrationBytecode = encodeDeployData({
|
50
|
+
bytecode: registrationSystemBuild.bytecode.object as Hex,
|
53
51
|
abi: [],
|
54
52
|
});
|
55
|
-
export const
|
53
|
+
export const registration = getCreate2Address({
|
56
54
|
from: deployer,
|
57
|
-
bytecode:
|
55
|
+
bytecode: registrationBytecode,
|
58
56
|
salt,
|
59
57
|
});
|
60
58
|
|
61
|
-
export const
|
62
|
-
export const
|
63
|
-
bytecode:
|
64
|
-
abi:
|
65
|
-
args: [accessManagementSystem, balanceTransferSystem, batchCallSystem,
|
59
|
+
export const initModuleDeployedBytecodeSize = size(initModuleBuild.deployedBytecode.object as Hex);
|
60
|
+
export const initModuleBytecode = encodeDeployData({
|
61
|
+
bytecode: initModuleBuild.bytecode.object as Hex,
|
62
|
+
abi: initModuleAbi,
|
63
|
+
args: [accessManagementSystem, balanceTransferSystem, batchCallSystem, registration],
|
66
64
|
});
|
67
65
|
|
68
|
-
export const
|
66
|
+
export const initModule = getCreate2Address({ from: deployer, bytecode: initModuleBytecode, salt });
|
69
67
|
|
70
68
|
export const worldFactoryDeployedBytecodeSize = size(worldFactoryBuild.deployedBytecode.object as Hex);
|
71
69
|
export const worldFactoryBytecode = encodeDeployData({
|
72
70
|
bytecode: worldFactoryBuild.bytecode.object as Hex,
|
73
71
|
abi: worldFactoryAbi,
|
74
|
-
args: [
|
72
|
+
args: [initModule],
|
75
73
|
});
|
76
74
|
|
77
75
|
export const worldFactory = getCreate2Address({ from: deployer, bytecode: worldFactoryBytecode, salt });
|
@@ -93,13 +91,13 @@ export const worldFactoryContracts: readonly Contract[] = [
|
|
93
91
|
label: "batch call system",
|
94
92
|
},
|
95
93
|
{
|
96
|
-
bytecode:
|
97
|
-
deployedBytecodeSize:
|
94
|
+
bytecode: registrationBytecode,
|
95
|
+
deployedBytecodeSize: registrationDeployedBytecodeSize,
|
98
96
|
label: "core registration system",
|
99
97
|
},
|
100
98
|
{
|
101
|
-
bytecode:
|
102
|
-
deployedBytecodeSize:
|
99
|
+
bytecode: initModuleBytecode,
|
100
|
+
deployedBytecodeSize: initModuleDeployedBytecodeSize,
|
103
101
|
label: "core module",
|
104
102
|
},
|
105
103
|
{
|
@@ -112,7 +110,7 @@ export const worldFactoryContracts: readonly Contract[] = [
|
|
112
110
|
export async function ensureWorldFactory(
|
113
111
|
client: Client<Transport, Chain | undefined, Account>
|
114
112
|
): Promise<readonly Hex[]> {
|
115
|
-
// WorldFactory constructor doesn't call
|
113
|
+
// WorldFactory constructor doesn't call InitModule, only sets its address, so we can do these in parallel since the address is deterministic
|
116
114
|
return await ensureContractsDeployed({
|
117
115
|
client,
|
118
116
|
contracts: worldFactoryContracts,
|
@@ -54,7 +54,7 @@ export function resolveConfig<config extends ConfigInput>({
|
|
54
54
|
.filter((sig) => !baseSystemFunctions.includes(sig))
|
55
55
|
.map((sig): WorldFunction => {
|
56
56
|
// TODO: figure out how to not duplicate contract behavior (https://github.com/latticexyz/mud/issues/1708)
|
57
|
-
const worldSignature = namespace === "" ? sig : `${namespace}
|
57
|
+
const worldSignature = namespace === "" ? sig : `${namespace}__${sig}`;
|
58
58
|
return {
|
59
59
|
signature: worldSignature,
|
60
60
|
selector: getFunctionSelector(worldSignature),
|
package/src/runDeploy.ts
CHANGED
@@ -2,7 +2,7 @@ import path from "node:path";
|
|
2
2
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
3
3
|
import { InferredOptionTypes, Options } from "yargs";
|
4
4
|
import { deploy } from "./deploy/deploy";
|
5
|
-
import { createWalletClient, http, Hex } from "viem";
|
5
|
+
import { createWalletClient, http, Hex, isHex } from "viem";
|
6
6
|
import { privateKeyToAccount } from "viem/accounts";
|
7
7
|
import { loadConfig } from "@latticexyz/config/node";
|
8
8
|
import { StoreConfig } from "@latticexyz/store";
|
@@ -29,6 +29,10 @@ export const deployOptions = {
|
|
29
29
|
type: "boolean",
|
30
30
|
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.",
|
31
31
|
},
|
32
|
+
salt: {
|
33
|
+
type: "string",
|
34
|
+
desc: "The deployment salt to use. Defaults to a random salt.",
|
35
|
+
},
|
32
36
|
} as const satisfies Record<string, Options>;
|
33
37
|
|
34
38
|
export type DeployOptions = InferredOptionTypes<typeof deployOptions>;
|
@@ -38,6 +42,11 @@ export type DeployOptions = InferredOptionTypes<typeof deployOptions>;
|
|
38
42
|
* This is used by the deploy, test, and dev-contracts CLI commands.
|
39
43
|
*/
|
40
44
|
export async function runDeploy(opts: DeployOptions): Promise<WorldDeploy> {
|
45
|
+
const salt = opts.salt;
|
46
|
+
if (salt != null && !isHex(salt)) {
|
47
|
+
throw new MUDError("Expected hex string for salt");
|
48
|
+
}
|
49
|
+
|
41
50
|
const profile = opts.profile ?? process.env.FOUNDRY_PROFILE;
|
42
51
|
|
43
52
|
const config = (await loadConfig(opts.configPath)) as StoreConfig & WorldConfig;
|
@@ -79,6 +88,7 @@ in your contracts directory to use the default anvil private key.`
|
|
79
88
|
|
80
89
|
const startTime = Date.now();
|
81
90
|
const worldDeploy = await deploy({
|
91
|
+
salt,
|
82
92
|
worldAddress: opts.worldAddress as Hex | undefined,
|
83
93
|
client,
|
84
94
|
config: resolvedConfig,
|
@@ -1,27 +0,0 @@
|
|
1
|
-
import{a as _}from"./chunk-22IIKR4S.js";import hs from"@latticexyz/gas-report";import ws from"@latticexyz/abi-ts";import{loadConfig as qo}from"@latticexyz/config/node";import{getSrcDirectory as Go}from"@latticexyz/common/foundry";import{existsSync as Ho,readFileSync as Eo,writeFileSync as No}from"node:fs";import X from"node:path";import{tablegen as zo}from"@latticexyz/store/codegen";import{worldgen as Uo}from"@latticexyz/world/node";import{forge as Vo,getForgeConfig as _o,getRemappings as Lo}from"@latticexyz/common/foundry";import Wo from"glob";import{basename as Ro}from"path";function I(e){return Wo.sync(`${e}/**/*.sol`).map(o=>({path:o,basename:Ro(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 Ko}from"execa";var Jo=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 Lo(r);await Promise.all([zo(e,t,n),Uo(e,I(o),t)]);let s=await _o(r);if(s.cache){let c=X.join(s.cache_path,"solidity-files-cache.json");if(Ho(c)){Jo("Unsetting cached content hash of IWorld.sol to force it to regenerate");let i=JSON.parse(Eo(c,"utf8")),p=X.join(t,"world","IWorld.sol");i.files[p].contentHash="",No(c,JSON.stringify(i,null,2))}}await Vo(["build"],{profile:r}),await Ko("mud",["abi-ts"],{stdio:"inherit"})}var Yo={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 qo(e),t=await Go();await L({config:r,srcDir:t,foundryProfile:o}),process.exit(0)}},ue=Yo;import{rmSync as Zo}from"fs";import{homedir as Qo}from"os";import Xo from"path";import{execa as et}from"execa";var ot={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=Qo();Zo(Xo.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=et("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=ot;import{FaucetServiceDefinition as tt}from"@latticexyz/services/faucet";import{createChannel as rt,createClient as nt}from"nice-grpc-web";import be from"chalk";import{NodeHttpTransport as st}from"@improbable-eng/grpc-web-node-http-transport";function it(e){return nt(tt,rt(e,st()))}var at={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=it(o);e&&(console.log(be.yellow("Dripping to",r)),await t.dripDev({address:r}),console.log(be.yellow("Success"))),process.exit(0)}},he=at;var ct={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=ct;import dt from"path";import{loadConfig as lt}from"@latticexyz/config/node";import{tablegen as mt}from"@latticexyz/store/codegen";import{getRemappings as pt,getSrcDirectory as ft}from"@latticexyz/common/foundry";var yt={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 lt(e),r=await ft(),t=await pt();await mt(o,dt.join(r,o.codegenDirectory),t),process.exit(0)}},xe=yt;import de from"node:path";import{existsSync as sn,mkdirSync as an,readFileSync as cn,writeFileSync as le}from"node:fs";import{getAddress as lo}from"viem";import{getBytecode as bt,sendRawTransaction as ht,sendTransaction as wt,waitForTransactionReceipt as Se}from"viem/actions";var P={gasPrice:1e11,gasLimit:1e5,signerAddress:"3fab184622dc19b6109349b94811493bf2a45362",transaction:"f8a58085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222",address:"4e59b44847b379578588920ca78fbf26c0b4956c"};var d=M.extend("deploy"),gt=M.extend("deploy");d.log=console.debug.bind(console);gt.log=console.error.bind(console);var S=`0x${P.address}`;async function Ce(e){if(await bt(e,{address:S})){d("found create2 deployer at",S);return}d("sending gas for create2 deployer to signer at",P.signerAddress);let r=await wt(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 ht(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 Qt}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 je from"@latticexyz/world/out/CoreRegistrationSystem.sol/CoreRegistrationSystem.json"assert{type:"json"};import Be from"@latticexyz/world/out/CoreModule.sol/CoreModule.json"assert{type:"json"};import Wt from"@latticexyz/world/out/CoreModule.sol/CoreModule.abi.json"assert{type:"json"};import Pe from"@latticexyz/world/out/WorldFactory.sol/WorldFactory.json"assert{type:"json"};import Rt from"@latticexyz/world/out/WorldFactory.sol/WorldFactory.abi.json"assert{type:"json"};import{getCreate2Address as W,encodeDeployData as R,size as $}from"viem";import{padHex as St}from"viem";import Ct from"@latticexyz/store/mud.config";import vt from"@latticexyz/world/mud.config";import Dt from"@latticexyz/world/out/IBaseWorld.sol/IBaseWorld.abi.json"assert{type:"json"};import Tt from"@latticexyz/world-modules/out/IModule.sol/IModule.abi.json"assert{type:"json"};import{resourceToHex as xt}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:xt({type:t.offchainOnly?"offchainTable":"table",namespace:e.namespace,name:t.name}),keySchema:ve(t.keySchema,o),valueSchema:ve(t.valueSchema,o)}]))}import{helloStoreEvent as At}from"@latticexyz/store";import{helloWorldEvent as kt}from"@latticexyz/world";var D=St("0x",{size:32}),U=parseInt("6000",16),F=z(Ct),T=z(vt),K=[At,kt],v=[...Dt,...Tt],De=["1.0.0-unaudited"],Te=["1.0.0-unaudited"];import{waitForTransactionReceipt as Ft}from"viem/actions";import{concatHex as It,getCreate2Address as Ot}from"viem";import{getBytecode as jt}from"viem/actions";import{sendTransaction as Bt}from"@latticexyz/common";import Pt from"p-retry";import{wait as Mt}from"@latticexyz/common/utils";async function Ae({client:e,bytecode:o,deployedBytecodeSize:r,label:t="contract"}){let n=Ot({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 Pt(()=>Bt(e,{chain:e.chain??null,to:S,data:It([D,o])}),{retries:3,onFailedAttempt:async c=>{let i=c.attemptNumber*500;d(`failed to deploy ${t}, retrying in ${i}ms...`),await Mt(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 Ft(e,{hash:t})}return r}var $t=$(ke.deployedBytecode.object),Me=R({bytecode:ke.bytecode.object,abi:[]}),Ht=W({from:S,bytecode:Me,salt:D}),Et=$(Ie.deployedBytecode.object),Fe=R({bytecode:Ie.bytecode.object,abi:[]}),Nt=W({from:S,bytecode:Fe,salt:D}),zt=$(Oe.deployedBytecode.object),We=R({bytecode:Oe.bytecode.object,abi:[]}),Ut=W({from:S,bytecode:We,salt:D}),Vt=$(je.deployedBytecode.object),Re=R({bytecode:je.bytecode.object,abi:[]}),_t=W({from:S,bytecode:Re,salt:D}),Lt=$(Be.deployedBytecode.object),$e=R({bytecode:Be.bytecode.object,abi:Wt,args:[Ht,Nt,Ut,_t]}),Kt=W({from:S,bytecode:$e,salt:D}),Jt=$(Pe.deployedBytecode.object),He=R({bytecode:Pe.bytecode.object,abi:Rt,args:[Kt]}),Ee=W({from:S,bytecode:He,salt:D}),ee=[{bytecode:Me,deployedBytecodeSize:$t,label:"access management system"},{bytecode:Fe,deployedBytecodeSize:Et,label:"balance transfer system"},{bytecode:We,deployedBytecodeSize:zt,label:"batch call system"},{bytecode:Re,deployedBytecodeSize:Vt,label:"core registration system"},{bytecode:$e,deployedBytecodeSize:Lt,label:"core module"},{bytecode:He,deployedBytecodeSize:Jt,label:"world factory"}];async function Ne(e){return await O({client:e,contracts:ee})}import Xt from"@latticexyz/world/out/WorldFactory.sol/WorldFactory.abi.json"assert{type:"json"};import{writeContract as er}from"@latticexyz/common";import{AbiEventSignatureNotFoundError as qt,decodeEventLog as Gt,hexToString as ze,parseAbi as Yt,trim as Ue}from"viem";import{isDefined as Zt}from"@latticexyz/common/utils";function J(e){let o=e.map(c=>{try{return{...c,...Gt({strict:!0,abi:Yt(K),topics:c.topics,data:c.data})}}catch(i){if(i instanceof qt)return;throw i}}).filter(Zt),{address:r,deployBlock:t,worldVersion:n,storeVersion:s}=o.reduce((c,i)=>({...c,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){await Ne(e),d("deploying world");let o=await er(e,{chain:e.chain??null,address:Ee,abi:Xt,functionName:"deployWorld"});d("waiting for world deploy");let r=await Qt(e,{hash:o});if(r.status!=="success")throw console.error("world deploy failed",r),new Error("world deploy failed");let t=J(r.logs.map(n=>n));return d("deployed world to",t.address,"at block",t.deployBlock),{...t,stateBlock:t.deployBlock}}import{writeContract as ar}from"@latticexyz/common";import{valueSchemaToFieldLayoutHex as cr,keySchemaToHex as dr,valueSchemaToHex as lr}from"@latticexyz/protocol-parser";function C({namespace:e,name:o}){return`${e}:${o}`}import{parseAbiItem as or,decodeAbiParameters as _e,parseAbiParameters as Le}from"viem";import{hexToResource as tr}from"@latticexyz/common";import{storeSetRecordEvent as rr}from"@latticexyz/store";import{getLogs as nr}from"viem/actions";import{decodeKey as sr,decodeValueArgs as ir,hexToSchema as Ke}from"@latticexyz/protocol-parser";async function Je({client:e,worldDeploy:o}){d("looking up tables for",o.address);let t=(await nr(e,{strict:!0,fromBlock:o.deployBlock,toBlock:o.stateBlock,address:o.address,event:or(rr),args:{tableId:F.store_Tables.tableId}})).map(n=>{let{tableId:s}=sr(F.store_Tables.keySchema,n.args.keyTuple),{namespace:c,name:i}=tr(s),p=ir(F.store_Tables.valueSchema,n.args),l=Ke(p.keySchema),f=Ke(p.valueSchema),y=_e(Le("string[]"),p.abiEncodedKeyNames)[0],m=_e(Le("string[]"),p.abiEncodedFieldNames)[0],u=[...f.staticFields,...f.dynamicFields],w=Object.fromEntries(l.staticFields.map((x,a)=>[y[a],x])),b=Object.fromEntries(u.map((x,a)=>[m[a],x]));return{namespace:c,name:i,tableId:s,keySchema:w,valueSchema:b}});return d("found",t.length,"tables for",o.address),t}import mr from"p-retry";import{wait as pr}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 c=r.filter(i=>!n.includes(i.tableId));return c.length?(d("registering tables",c.map(C).join(", ")),await Promise.all(c.map(i=>mr(()=>ar(e,{chain:e.chain??null,address:o.address,abi:v,functionName:"registerTable",args:[i.tableId,cr(i.valueSchema),dr(i.keySchema),lr(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 pr(l)}})))):[]}import{getAddress as A}from"viem";import{writeContract as oe}from"@latticexyz/common";import{parseAbiItem as fr}from"viem";import{getLogs as yr}from"viem/actions";import{storeSpliceStaticDataEvent as ur}from"@latticexyz/store";async function q({client:e,worldDeploy:o}){d("looking up resource IDs for",o.address);let t=(await yr(e,{strict:!0,address:o.address,fromBlock:o.deployBlock,toBlock:o.stateBlock,event:fr(ur),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 gr,encodeKey as br}from"@latticexyz/protocol-parser";import{readContract as hr}from"viem/actions";async function j({client:e,worldDeploy:o,table:r,key:t}){let[n,s,c]=await hr(e,{blockNumber:o.stateBlock,address:o.address,abi:v,functionName:"getRecord",args:[r.tableId,br(r.keySchema,t)]});return gr(r.valueSchema,{staticData:n,encodedLengths:s,dynamicData:c})}import{getFunctionSelector as wr,parseAbiItem as xr}from"viem";import{storeSetRecordEvent as Sr}from"@latticexyz/store";import{getLogs as Cr}from"viem/actions";import{decodeValueArgs as vr}from"@latticexyz/protocol-parser";import{hexToResource as Dr}from"@latticexyz/common";async function G({client:e,worldDeploy:o}){d("looking up function signatures for",o.address);let t=(await Cr(e,{strict:!0,fromBlock:o.deployBlock,toBlock:o.stateBlock,address:o.address,event:xr(Sr),args:{tableId:T.world_FunctionSignatures.tableId}})).map(s=>vr(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 c=wr(s),{systemId:i,systemFunctionSelector:p}=await j({client:e,worldDeploy:o,table:T.world_FunctionSelectors,key:{functionSelector:c}}),{namespace:l,name:f}=Dr(i),y=l===""?s:s.replace(`${l}_${f}_`,"");return{signature:s,selector:c,systemId:i,systemFunctionSignature:y,systemFunctionSelector:p}}))}import{parseAbiItem as Tr,getAddress as Ar}from"viem";import{storeSpliceStaticDataEvent as kr}from"@latticexyz/store";import{getLogs as Ir}from"viem/actions";import{decodeKey as Or}from"@latticexyz/protocol-parser";async function Y({client:e,worldDeploy:o}){d("looking up resource access for",o.address);let t=(await Ir(e,{strict:!0,fromBlock:o.deployBlock,toBlock:o.stateBlock,address:o.address,event:Tr(kr),args:{tableId:T.world_ResourceAccess.tableId}})).map(s=>Or(T.world_ResourceAccess.keySchema,s.args.keyTuple)),n=(await Promise.all(t.map(async s=>[s,await j({client:e,worldDeploy:o,table:T.world_ResourceAccess,key:s})]))).filter(([,s])=>s.access).map(([s])=>({resourceId:s.resourceId,address:Ar(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(c=>c.type==="system");return d("looking up systems",s.map(C).join(", ")),await Promise.all(s.map(async c=>{let{system:i,publicAccess:p}=await j({client:e,worldDeploy:o,table:T.world_Systems,key:{systemId:c.resourceId}}),l=t.filter(f=>f.systemId===c.resourceId);return{address:i,namespace:c.namespace,name:c.name,systemId:c.resourceId,allowAll:p,allowedAddresses:n.filter(({resourceId:f})=>f===c.resourceId).map(({address:f})=>f),functions:l}}))}import{uniqueBy as Br,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(a=>a.systemId),c=n.filter(({resourceId:a})=>s.includes(a)),i=r.flatMap(a=>a.allowedAddresses.map(g=>({resourceId:a.systemId,address:g}))),p=i.filter(a=>!c.some(({resourceId:g,address:h})=>g===a.resourceId&&A(h)===A(a.address))),l=c.filter(a=>!i.some(({resourceId:g,address:h})=>g===a.resourceId&&A(h)===A(a.address)));l.length&&d("revoking",l.length,"access grants"),p.length&&d("adding",p.length,"access grants");let f=[...l.map(a=>re(()=>oe(e,{chain:e.chain??null,address:o.address,abi:v,functionName:"revokeAccess",args:[a.resourceId,a.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(a=>re(()=>oe(e,{chain:e.chain??null,address:o.address,abi:v,functionName:"grantAccess",args:[a.resourceId,a.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(a=>t.some(g=>g.systemId===a.systemId&&A(g.address)===A(a.address)));y.length&&d("existing systems",y.map(C).join(", "));let m=y.map(a=>a.systemId),u=r.filter(a=>!m.includes(a.systemId));if(!u.length)return[];let w=u.filter(a=>t.some(g=>g.systemId===a.systemId&&A(g.address)!==A(a.address)));w.length&&d("upgrading systems",w.map(C).join(", "));let b=u.filter(a=>!t.some(g=>g.systemId===a.systemId));b.length&&d("registering new systems",b.map(C).join(", ")),await O({client:e,contracts:Br(u,a=>A(a.address)).map(a=>({bytecode:a.bytecode,deployedBytecodeSize:a.deployedBytecodeSize,label:`${C(a)} system`}))});let x=u.map(a=>re(()=>oe(e,{chain:e.chain??null,address:o.address,abi:v,functionName:"registerSystem",args:[a.systemId,a.address,a.allowAll]}),{retries:3,onFailedAttempt:async g=>{let h=g.attemptNumber*500;d(`failed to register system ${C(a)}, retrying in ${h}ms...`),await te(h)}}));return await Promise.all([...f,...x])}import{waitForTransactionReceipt as mo}from"viem/actions";import{getAddress as Pr,parseAbi as Mr}from"viem";import{getBlockNumber as Fr,getLogs as Wr}from"viem/actions";var Ze=new Map;async function Qe(e,o){let r=Pr(o),t=Ze.get(r);if(t!=null)return t;d("looking up world deploy for",r);let n=await Fr(e),s=await Wr(e,{strict:!0,address:r,events:Mr(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 Rr,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]),c=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 c.length?(d("registering functions:",c.map(i=>i.signature).join(", ")),Promise.all(c.map(i=>{let{namespace:p}=Rr(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 Hr}from"viem";import{writeContract as ro}from"@latticexyz/common";import{isDefined as Er,uniqueBy as Nr,wait as zr}from"@latticexyz/common/utils";import Ur from"p-retry";async function no({client:e,worldDeploy:o,modules:r}){return r.length?(await O({client:e,contracts:Nr(r,t=>Hr(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=>Ur(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 zr(s)}})))).filter(Er)):[]}import{getAddress as so}from"viem";import{hexToResource as io,resourceToHex as ao,writeContract as Vr}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 c=t.filter(y=>s.has(y)),p=(await Promise.all(c.map(async y=>{let{owner:m}=await j({client:e,worldDeploy:o,table:T.world_NamespaceOwner,key:{namespaceId:ao({type:"namespace",namespace:y,name:""})}});return[y,m]}))).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=>Vr(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";async function fo({client:e,config:o,worldAddress:r}){let t=Object.values(o.tables),n=Object.values(o.systems);await Ce(e),await O({client:e,contracts:[...ee,...po(n,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 s=r?await Qe(e,r):await Ve(e);if(!De.includes(s.storeVersion))throw new Error(`Unsupported Store version: ${s.storeVersion}`);if(!Te.includes(s.worldVersion))throw new Error(`Unsupported World version: ${s.worldVersion}`);let c=await co({client:e,worldDeploy:s,resourceIds:[...t.map(m=>m.tableId),...n.map(m=>m.systemId)]});d("waiting for all namespace registration transactions to confirm");for(let m of c)await mo(e,{hash:m});let i=await qe({client:e,worldDeploy:s,tables:t}),p=await Ye({client:e,worldDeploy:s,systems:n}),l=await to({client:e,worldDeploy:s,functions:n.flatMap(m=>m.functions)}),f=await no({client:e,worldDeploy:s,modules:o.modules}),y=[...i,...p,...l,...f];d("waiting for all transactions to confirm");for(let m of y)await mo(e,{hash:m});return d("deploy complete"),s}import{createWalletClient as dn,http as ln}from"viem";import{privateKeyToAccount as mn}from"viem/accounts";import{loadConfig as pn}from"@latticexyz/config/node";import{getOutDirectory as fn,getRpcUrl as yn,getSrcDirectory as un}from"@latticexyz/common/foundry";import H from"chalk";import{MUDError as gn}from"@latticexyz/common/errors";import{resolveWorldConfig as Jr}from"@latticexyz/world";import{resourceToHex as ce,hexToResource as qr}from"@latticexyz/common";import{resolveWithContext as Gr}from"@latticexyz/config";import{encodeField as Yr}from"@latticexyz/protocol-parser";import{getFunctionSelector as uo,getCreate2Address as go,getAddress as Zr,hexToBytes as Qr,bytesToHex as Xr,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 _r}from"fs";import Lr from"path";import{MUDError as Z}from"@latticexyz/common/errors";import{size as Kr}from"viem";function Q(e,o){let r,t=Lr.join(o,e+".sol",e+".json");try{r=JSON.parse(_r(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 c=r?.abi;if(!c)throw new Z(`No ABI found in ${t}`);return{abi:c,bytecode:n,deployedBytecodeSize:Kr(s)}}function ho({config:e,forgeSourceDir:o,forgeOutDir:r}){let t=z(e),n=I(o).map(({basename:m})=>m),s=Jr(e,n),i=Q("System",r).abi.filter(m=>m.type==="function").map(bo),p=Object.entries(s.systems).map(([m,u])=>{let w=e.namespace,b=u.name,x=ce({type:"system",namespace:w,name:b}),a=Q(m,r),g=a.abi.filter(h=>h.type==="function").map(bo).filter(h=>!i.includes(h)).map(h=>{let fe=w===""?h:`${w}_${b}_${h}`;return{signature:fe,selector:uo(fe),systemId:x,systemFunctionSignature:h,systemFunctionSelector:uo(h)}});return{namespace:w,name:b,systemId:x,allowAll:u.openAccess,allowedAddresses:u.accessListAddresses,allowedSystemIds:u.accessListSystems.map(h=>ce({type:"system",namespace:w,name:s.systems[h].name})),address:go({from:S,bytecode:a.bytecode,salt:D}),bytecode:a.bytecode,deployedBytecodeSize:a.deployedBytecodeSize,abi:a.abi,functions:g}}),l=p.map(({allowedAddresses:m,allowedSystemIds:u,...w})=>{let b=u.map(x=>{let a=p.find(g=>g.systemId===x);if(!a)throw new Error(`System ${C(w)} wanted access to ${C(qr(x))}, but it wasn't found in the config.`);return a.address});return{...w,allowedAddresses:Array.from(new Set([...m,...b].map(x=>Zr(x))))}}),f={tableIds:Object.fromEntries(Object.entries(e.tables).map(([m,u])=>[m,Qr(ce({type:u.offchainOnly?"offchainTable":"table",namespace:e.namespace,name:u.name}))]))},y=e.modules.map(m=>{let u=yo.find(b=>b.name===m.name)??Q(m.name,r),w=m.args.map(b=>Gr(b,f)).map(b=>{let x=b.value instanceof Uint8Array?Xr(b.value):b.value;return Yr(b.type,x)});if(w.length>1)throw new Error(`${m.name} module should only have 0-1 args, but had ${w.length} args.`);return{name:m.name,installAsRoot:m.root,installData:w.length===0?"0x":w[0],address:go({from:S,bytecode:u.bytecode,salt:D}),bytecode:u.bytecode,deployedBytecodeSize:u.deployedBytecodeSize,abi:u.abi}});return{tables:t,systems:l,modules:y}}import{getChainId as bn}from"viem/actions";import{existsSync as en}from"fs";import on from"path";import tn from"chalk";import{getScriptDirectory as rn,forge as nn}from"@latticexyz/common/foundry";async function wo(e,o,r,t){let n=on.join(await rn(),e+".s.sol");en(n)?(console.log(tn.blue(`Executing post deploy script at ${n}`)),await nn(["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."}};async function E(e){let o=e.profile??process.env.FOUNDRY_PROFILE,r=await pn(e.configPath);e.printConfig&&console.log(H.green(`
|
7
|
-
Resolved config:
|
8
|
-
`),JSON.stringify(r,null,2));let t=e.srcDir??await un(o),n=await fn(o),s=e.rpc??await yn(o);console.log(H.bgBlue(H.whiteBright(`
|
9
|
-
Deploying MUD contracts${o?" with profile "+o:""} to RPC ${s}
|
10
|
-
`))),e.skipBuild||await L({config:r,srcDir:t,foundryProfile:o});let c=process.env.PRIVATE_KEY;if(!c)throw new gn(`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 i=ho({config:r,forgeSourceDir:t,forgeOutDir:n}),p=dn({transport:ln(s),account:mn(c)});console.log("Deploying from",p.account.address);let l=Date.now(),f=await fo({worldAddress:e.worldAddress,client:p,config:i});(e.worldAddress==null||e.alwaysRunPostDeploy)&&await wo(r.postDeployScript,f.address,s,o),console.log(H.green("Deployment completed in",(Date.now()-l)/1e3,"seconds"));let y={worldAddress:f.address,blockNumber:Number(f.deployBlock)};if(e.saveDeployment){let m=await bn(p),u=de.join(r.deploysDirectory,m.toString());an(u,{recursive:!0}),le(de.join(u,"latest.json"),JSON.stringify(y,null,2)),le(de.join(u,Date.now()+".json"),JSON.stringify(y,null,2));let w=[1337,31337],b=sn(r.worldsFile)?JSON.parse(cn(r.worldsFile,"utf-8")):{};b[m]={address:y.worldAddress,blockNumber:w.includes(m)?void 0:y.blockNumber},le(r.worldsFile,JSON.stringify(b,null,2)),console.log(H.bgGreen(H.whiteBright(`
|
13
|
-
Deployment result (written to ${r.worldsFile} and ${u}):
|
14
|
-
`)))}return console.log(y),f}var hn={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)}},xo=hn;import{loadConfig as wn}from"@latticexyz/config/node";import{worldgen as xn}from"@latticexyz/world/node";import{getSrcDirectory as Sn}from"@latticexyz/common/foundry";import So from"path";import{rmSync as Cn}from"fs";var vn={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 Dn(e),process.exit(0)}};async function Dn(e){let o=e.srcDir??await Sn(),r=I(o),t=e.config??await wn(e.configPath),n=So.join(o,t.codegenDirectory);e.clean&&Cn(So.join(n,t.worldgenDirectory),{recursive:!0,force:!0}),await xn(t,r,n)}var Co=vn;import V from"chalk";import{readFileSync as On,writeFileSync as jn}from"fs";import pe from"path";import{MUDError as N}from"@latticexyz/common/errors";var vo={name:"@latticexyz/cli",version:"2.0.0-next.16",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.31.4"},gitHead:"914a1e0ae4a573d685841ca2ea921435057deb8f"};import Bn from"glob";import{ZodError as An,z as Do}from"zod";var kn=Do.object({MUD_PACKAGES:Do.string().transform(e=>JSON.parse(e))});function In(){try{return kn.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 An){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=In().MUD_PACKAGES;var Pn={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 Mn(e));let t=Bn.sync("**/package.json").filter(n=>!n.includes("node_modules"));for(let n of t)Fn(n,e)}catch(o){_(o)}finally{process.exit(0)}}};async function Mn(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/${vo.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 Fn(e,o){let{link:r}=o,{mudVersion:t}=o,n=Wn(e),s=Object.keys(me),c={};for(let l in n.dependencies)s.includes(l)&&(c[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 jn(e,JSON.stringify(n,null,2)+`
|
20
|
-
`),console.log(`Updating ${e}`),To(c,n.dependencies),To(i,n.devDependencies),n;function p(l,f){return r&&(t=Rn(e,r,l)),t||n[f][l]}}function Wn(e){try{let o=On(e,"utf8");return JSON.parse(o)}catch{throw new N("Could not read JSON at "+e)}}function To(e,o){for(let r in e)e[r]!==o[r]&&console.log(`${r}: ${V.red(e[r])} -> ${V.green(o[r])}`)}function Rn(e,o,r){let t=pe.relative(pe.dirname(e),process.cwd());return"link:"+pe.join(t,o,me[r].localPath)}var Ao=Pn;import{anvil as $n,forge as Hn,getRpcUrl as En}from"@latticexyz/common/foundry";import Nn from"chalk";var zn={...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"}},Un={command:"test",describe:"Run tests in MUD contracts",builder(e){return e.options(zn)},async handler(e){if(!e.worldAddress){let n=["--block-base-fee-per-gas","0","--port",String(e.port)];$n(n)}let o=e.worldAddress?await En(e.profile):`http://127.0.0.1:${e.port}`,r=e.worldAddress??(await E({...e,saveDeployment:!1,rpc:o})).address;console.log(Nn.blue("World address",r));let t=e.forgeOptions?.replaceAll("\\","").split(" ")??[];try{await Hn(["test","--fork-url",o,...t],{profile:e.profile,env:{WORLD_ADDRESS:r}}),process.exit(0)}catch(n){console.error(n),process.exit(1)}}},ko=Un;import{existsSync as Vn,readFileSync as _n}from"fs";import{ethers as Io}from"ethers";import{loadConfig as Ln}from"@latticexyz/config/node";import{MUDError as Oo}from"@latticexyz/common/errors";import{cast as Kn,getRpcUrl as Jn,getSrcDirectory as qn}from"@latticexyz/common/foundry";import{resolveWorldConfig as Gn}from"@latticexyz/world";import Yn from"@latticexyz/world/out/IBaseWorld.sol/IBaseWorld.abi.json"assert{type:"json"};import jo from"@latticexyz/world/mud.config";import{resourceToHex as Po}from"@latticexyz/common";import{createClient as Zn,http as Qn}from"viem";import{getChainId as Xn}from"viem/actions";var Bo=Po({type:"system",namespace:jo.namespace,name:jo.tables.Systems.name}),es={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 qn(o),e.rpc??=await Jn(o);let{tx:r,configPath:t,srcDir:n,rpc:s}=e,c=I(n),i=await Ln(t),p=Gn(i,c.map(({basename:a})=>a)),l=e.worldAddress??await os(i.worldsFile,s),f=new Io.providers.StaticJsonRpcProvider(s),y=new Io.Contract(l,Yn,f),m=i.namespace,u=Object.values(p.systems).map(({name:a})=>a),w=await y.getFieldLayout(Bo),b=[];for(let a of u){let g=Po({type:"system",namespace:m,name:a}),h=await y.getField(Bo,[g],0,w);b.push({name:a,address:h})}let x=await Kn(["run","--label",`${l}:World`,...b.map(({name:a,address:g})=>["--label",`${g}:${a}`]).flat(),`${r}`]);console.log(x),process.exit(0)}},Mo=es;async function os(e,o){if(Vn(e)){let r=Zn({transport:Qn(o)}),t=await Xn(r),n=JSON.parse(_n(e,"utf-8"));if(!n[t])throw new Oo(`chainId ${t} is missing in worldsFile "${e}"`);return n[t].address}else throw new Oo("worldAddress is not specified and worldsFile is missing")}import{anvil as ts,getScriptDirectory as rs,getSrcDirectory as ns}from"@latticexyz/common/foundry";import B from"chalk";import ss from"chokidar";import{loadConfig as is,resolveConfigPath as as}from"@latticexyz/config/node";import cs from"path";import{homedir as ds}from"os";import{rmSync as ls}from"fs";import{BehaviorSubject as ms,debounceTime as ps,exhaustMap as fs,filter as ys}from"rxjs";import{isDefined as us}from"@latticexyz/common/utils";var gs={rpc:k.rpc,configPath:k.configPath,alwaysRunPostDeploy:k.alwaysRunPostDeploy,worldAddress:k.worldAddress},bs={command:"dev-contracts",describe:"Start a development server for MUD contracts",builder(e){return e.options(gs)},async handler(e){let o=e.rpc,r=e.configPath??await as(e.configPath),t=await ns(),n=await rs(),s=await is(r);if(!e.rpc){console.log(B.gray("Cleaning devnode cache"));let l=ds();ls(cs.join(l,".foundry","anvil","tmp"),{recursive:!0,force:!0}),ts(["--block-time","1","--block-base-fee-per-gas","0"]),o="http://127.0.0.1:8545"}let c=new ms(Date.now());ss.watch([r,t,n],{ignoreInitial:!0}).on("all",async(l,f)=>{f.includes(r)&&(console.log(B.blue("Config changed, queuing deploy\u2026")),c.next(Date.now())),(f.includes(t)||f.includes(n))&&(f.includes(s.codegenDirectory)||(console.log(B.blue("Contracts changed, queuing deploy\u2026")),c.next(Date.now())))});let i=e.worldAddress;c.pipe(ps(200),fs(async l=>{i&&console.log(B.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});return i=f.address,l<c.value?c.next(c.value):console.log(B.gray(`
|
21
|
-
Waiting for file changes\u2026
|
22
|
-
`)),f}catch(f){console.error(B.bgRed(B.whiteBright(`
|
23
|
-
Error while attempting deploy
|
24
|
-
`))),console.error(f),console.log(B.gray(`
|
25
|
-
Waiting for file changes\u2026
|
26
|
-
`))}}),ys(us)).subscribe()}},Fo=bs;var Pp=[ue,xo,ge,he,hs,we,xe,Co,Ao,ko,Mo,Fo,ws];export{Pp as commands};
|
27
|
-
//# sourceMappingURL=commands-DSIRJZEM.js.map
|