@latticexyz/cli 2.0.0-next.14 → 2.0.0-next.15
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-ORXW7F62.js +27 -0
- package/dist/commands-ORXW7F62.js.map +1 -0
- package/dist/mud.js +1 -1
- package/package.json +12 -12
- package/src/build.ts +44 -0
- package/src/commands/build.ts +36 -0
- package/src/commands/index.ts +2 -0
- package/src/commands/set-version.ts +4 -1
- package/src/debug.ts +7 -0
- package/src/deploy/debug.ts +7 -0
- package/src/runDeploy.ts +3 -10
- package/dist/commands-UYAATBY6.js +0 -27
- package/dist/commands-UYAATBY6.js.map +0 -1
package/src/build.ts
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
2
|
+
import path from "node:path";
|
3
|
+
import { tablegen } from "@latticexyz/store/codegen";
|
4
|
+
import { worldgen } from "@latticexyz/world/node";
|
5
|
+
import { StoreConfig } from "@latticexyz/store";
|
6
|
+
import { WorldConfig } from "@latticexyz/world";
|
7
|
+
import { forge, getForgeConfig, getRemappings } from "@latticexyz/common/foundry";
|
8
|
+
import { getExistingContracts } from "./utils/getExistingContracts";
|
9
|
+
import { debug as parentDebug } from "./debug";
|
10
|
+
import { execa } from "execa";
|
11
|
+
|
12
|
+
const debug = parentDebug.extend("runDeploy");
|
13
|
+
|
14
|
+
type BuildOptions = {
|
15
|
+
foundryProfile?: string;
|
16
|
+
srcDir: string;
|
17
|
+
config: StoreConfig & WorldConfig;
|
18
|
+
};
|
19
|
+
|
20
|
+
export async function build({
|
21
|
+
config,
|
22
|
+
srcDir,
|
23
|
+
foundryProfile = process.env.FOUNDRY_PROFILE,
|
24
|
+
}: BuildOptions): Promise<void> {
|
25
|
+
const outPath = path.join(srcDir, config.codegenDirectory);
|
26
|
+
const remappings = await getRemappings(foundryProfile);
|
27
|
+
await Promise.all([tablegen(config, outPath, remappings), worldgen(config, getExistingContracts(srcDir), outPath)]);
|
28
|
+
|
29
|
+
// TODO remove when https://github.com/foundry-rs/foundry/issues/6241 is resolved
|
30
|
+
const forgeConfig = await getForgeConfig(foundryProfile);
|
31
|
+
if (forgeConfig.cache) {
|
32
|
+
const cacheFilePath = path.join(forgeConfig.cache_path, "solidity-files-cache.json");
|
33
|
+
if (existsSync(cacheFilePath)) {
|
34
|
+
debug("Unsetting cached content hash of IWorld.sol to force it to regenerate");
|
35
|
+
const solidityFilesCache = JSON.parse(readFileSync(cacheFilePath, "utf8"));
|
36
|
+
const worldInterfacePath = path.join(outPath, "world", "IWorld.sol");
|
37
|
+
solidityFilesCache["files"][worldInterfacePath]["contentHash"] = "";
|
38
|
+
writeFileSync(cacheFilePath, JSON.stringify(solidityFilesCache, null, 2));
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
await forge(["build"], { profile: foundryProfile });
|
43
|
+
await execa("mud", ["abi-ts"], { stdio: "inherit" });
|
44
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
import type { CommandModule } from "yargs";
|
2
|
+
import { loadConfig } from "@latticexyz/config/node";
|
3
|
+
import { StoreConfig } from "@latticexyz/store";
|
4
|
+
import { WorldConfig } from "@latticexyz/world";
|
5
|
+
|
6
|
+
import { getSrcDirectory } from "@latticexyz/common/foundry";
|
7
|
+
import { build } from "../build";
|
8
|
+
|
9
|
+
type Options = {
|
10
|
+
configPath?: string;
|
11
|
+
profile?: string;
|
12
|
+
};
|
13
|
+
|
14
|
+
const commandModule: CommandModule<Options, Options> = {
|
15
|
+
command: "build",
|
16
|
+
|
17
|
+
describe: "Build contracts and generate MUD artifacts (table libraries, world interface, ABI)",
|
18
|
+
|
19
|
+
builder(yargs) {
|
20
|
+
return yargs.options({
|
21
|
+
configPath: { type: "string", desc: "Path to the config file" },
|
22
|
+
profile: { type: "string", desc: "The foundry profile to use" },
|
23
|
+
});
|
24
|
+
},
|
25
|
+
|
26
|
+
async handler({ configPath, profile }) {
|
27
|
+
const config = (await loadConfig(configPath)) as StoreConfig & WorldConfig;
|
28
|
+
const srcDir = await getSrcDirectory();
|
29
|
+
|
30
|
+
await build({ config, srcDir, foundryProfile: profile });
|
31
|
+
|
32
|
+
process.exit(0);
|
33
|
+
},
|
34
|
+
};
|
35
|
+
|
36
|
+
export default commandModule;
|
package/src/commands/index.ts
CHANGED
@@ -3,6 +3,7 @@ import { CommandModule } from "yargs";
|
|
3
3
|
import gasReport from "@latticexyz/gas-report";
|
4
4
|
import abiTs from "@latticexyz/abi-ts";
|
5
5
|
|
6
|
+
import build from "./build";
|
6
7
|
import devnode from "./devnode";
|
7
8
|
import faucet from "./faucet";
|
8
9
|
import hello from "./hello";
|
@@ -16,6 +17,7 @@ import devContracts from "./dev-contracts";
|
|
16
17
|
|
17
18
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Each command has different options
|
18
19
|
export const commands: CommandModule<any, any>[] = [
|
20
|
+
build,
|
19
21
|
deploy,
|
20
22
|
devnode,
|
21
23
|
faucet,
|
@@ -56,8 +56,11 @@ const commandModule: CommandModule<Options, Options> = {
|
|
56
56
|
throw new MUDError(`These options are mutually exclusive: ${mutuallyExclusiveOptions.join(", ")}`);
|
57
57
|
}
|
58
58
|
|
59
|
+
// If the --link flag is not set, we call resolveVersion to get the version
|
59
60
|
// Resolve the version number from available options like `tag` or `commit`
|
60
|
-
|
61
|
+
if (!options.link) {
|
62
|
+
options.mudVersion = await resolveVersion(options);
|
63
|
+
}
|
61
64
|
|
62
65
|
// Update all package.json below the current working directory (except in node_modules)
|
63
66
|
const packageJsons = glob.sync("**/package.json").filter((p) => !p.includes("node_modules"));
|
package/src/debug.ts
CHANGED
@@ -1,3 +1,10 @@
|
|
1
1
|
import createDebug from "debug";
|
2
2
|
|
3
3
|
export const debug = createDebug("mud:cli");
|
4
|
+
export const error = createDebug("mud:cli");
|
5
|
+
|
6
|
+
// Pipe debug output to stdout instead of stderr
|
7
|
+
debug.log = console.debug.bind(console);
|
8
|
+
|
9
|
+
// Pipe error output to stderr
|
10
|
+
error.log = console.error.bind(console);
|
package/src/deploy/debug.ts
CHANGED
@@ -1,3 +1,10 @@
|
|
1
1
|
import { debug as parentDebug } from "../debug";
|
2
2
|
|
3
3
|
export const debug = parentDebug.extend("deploy");
|
4
|
+
export const error = parentDebug.extend("deploy");
|
5
|
+
|
6
|
+
// Pipe debug output to stdout instead of stderr
|
7
|
+
debug.log = console.debug.bind(console);
|
8
|
+
|
9
|
+
// Pipe error output to stderr
|
10
|
+
error.log = console.error.bind(console);
|
package/src/runDeploy.ts
CHANGED
@@ -7,17 +7,14 @@ import { privateKeyToAccount } from "viem/accounts";
|
|
7
7
|
import { loadConfig } from "@latticexyz/config/node";
|
8
8
|
import { StoreConfig } from "@latticexyz/store";
|
9
9
|
import { WorldConfig } from "@latticexyz/world";
|
10
|
-
import {
|
10
|
+
import { getOutDirectory, getRpcUrl, getSrcDirectory } from "@latticexyz/common/foundry";
|
11
11
|
import chalk from "chalk";
|
12
|
-
import { execa } from "execa";
|
13
12
|
import { MUDError } from "@latticexyz/common/errors";
|
14
13
|
import { resolveConfig } from "./deploy/resolveConfig";
|
15
14
|
import { getChainId } from "viem/actions";
|
16
15
|
import { postDeploy } from "./utils/utils/postDeploy";
|
17
16
|
import { WorldDeploy } from "./deploy/common";
|
18
|
-
import {
|
19
|
-
import { worldgen } from "@latticexyz/world/node";
|
20
|
-
import { getExistingContracts } from "./utils/getExistingContracts";
|
17
|
+
import { build } from "./build";
|
21
18
|
|
22
19
|
export const deployOptions = {
|
23
20
|
configPath: { type: "string", desc: "Path to the config file" },
|
@@ -50,7 +47,6 @@ export async function runDeploy(opts: DeployOptions): Promise<WorldDeploy> {
|
|
50
47
|
|
51
48
|
const srcDir = opts.srcDir ?? (await getSrcDirectory(profile));
|
52
49
|
const outDir = await getOutDirectory(profile);
|
53
|
-
const remappings = await getRemappings();
|
54
50
|
|
55
51
|
const rpc = opts.rpc ?? (await getRpcUrl(profile));
|
56
52
|
console.log(
|
@@ -61,10 +57,7 @@ export async function runDeploy(opts: DeployOptions): Promise<WorldDeploy> {
|
|
61
57
|
|
62
58
|
// Run build
|
63
59
|
if (!opts.skipBuild) {
|
64
|
-
|
65
|
-
await Promise.all([tablegen(config, outPath, remappings), worldgen(config, getExistingContracts(srcDir), outPath)]);
|
66
|
-
await forge(["build"], { profile });
|
67
|
-
await execa("mud", ["abi-ts"], { stdio: "inherit" });
|
60
|
+
await build({ config, srcDir, foundryProfile: profile });
|
68
61
|
}
|
69
62
|
|
70
63
|
const privateKey = process.env.PRIVATE_KEY as Hex;
|
@@ -1,27 +0,0 @@
|
|
1
|
-
import{a as N}from"./chunk-22IIKR4S.js";import zn from"@latticexyz/gas-report";import Vn from"@latticexyz/abi-ts";import{rmSync as So}from"fs";import{homedir as Co}from"os";import vo from"path";import{execa as Do}from"execa";var To={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=Co();So(vo.join(o,".foundry","anvil","tmp"),{recursive:!0,force:!0});let t=["-b",String(e),"--block-base-fee-per-gas","0"];console.log(`Running: anvil ${t.join(" ")}`);let r=Do("anvil",t,{stdio:["inherit","inherit","inherit"]});process.on("SIGINT",()=>{console.log(`
|
2
|
-
gracefully shutting down from SIGINT (Crtl-C)`),r.kill(),process.exit()}),await r}},ce=To;import{FaucetServiceDefinition as Ao}from"@latticexyz/services/faucet";import{createChannel as ko,createClient as Io}from"nice-grpc-web";import de from"chalk";import{NodeHttpTransport as Oo}from"@improbable-eng/grpc-web-node-http-transport";function Po(e){return Io(Ao,ko(e,Oo()))}var jo={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:t}){let r=Po(o);e&&(console.log(de.yellow("Dripping to",t)),await r.dripDev({address:t}),console.log(de.yellow("Success"))),process.exit(0)}},le=jo;var Bo={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)}},me=Bo;import Fo from"path";import{loadConfig as Mo}from"@latticexyz/config/node";import{tablegen as Wo}from"@latticexyz/store/codegen";import{getRemappings as Ro,getSrcDirectory as $o}from"@latticexyz/common/foundry";var Eo={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 Mo(e),t=await $o(),r=await Ro();await Wo(o,Fo.join(t,o.codegenDirectory),r),process.exit(0)}},pe=Eo;import q from"node:path";import{existsSync as vr,mkdirSync as Dr,readFileSync as Tr,writeFileSync as ne}from"node:fs";import{getAddress as Ye}from"viem";import{getBytecode as zo,sendRawTransaction as Vo,sendTransaction as Uo,waitForTransactionReceipt as ye}from"viem/actions";var B={gasPrice:1e11,gasLimit:1e5,signerAddress:"3fab184622dc19b6109349b94811493bf2a45362",transaction:"f8a58085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222",address:"4e59b44847b379578588920ca78fbf26c0b4956c"};import No from"debug";var fe=No("mud:cli");var l=fe.extend("deploy");var v=`0x${B.address}`;async function ue(e){if(await zo(e,{address:v})){l("found create2 deployer at",v);return}l("sending gas for create2 deployer to signer at",B.signerAddress);let t=await Uo(e,{chain:e.chain??null,to:`0x${B.signerAddress}`,value:BigInt(B.gasLimit)*BigInt(B.gasPrice)}),r=await ye(e,{hash:t});if(r.status!=="success")throw console.error("failed to send gas to deployer signer",r),new Error("failed to send gas to deployer signer");l("deploying create2 deployer at",v);let n=await Vo(e,{serializedTransaction:`0x${B.transaction}`}),s=await ye(e,{hash:n});if(s.contractAddress!==v)throw console.error("unexpected contract address for deployer",s),new Error("unexpected contract address for deployer")}import{waitForTransactionReceipt as ft}from"viem/actions";import xe from"@latticexyz/world/out/CoreModule.sol/CoreModule.json"assert{type:"json"};import Se from"@latticexyz/world/out/WorldFactory.sol/WorldFactory.json"assert{type:"json"};import{parseAbi as st,getCreate2Address as Ce,encodeDeployData as ve,size as De}from"viem";import{padHex as _o}from"viem";import Ko from"@latticexyz/store/mud.config";import Jo from"@latticexyz/world/mud.config";import qo from"@latticexyz/world/out/IBaseWorld.sol/IBaseWorld.abi.json"assert{type:"json"};import Go from"@latticexyz/world-modules/out/IModule.sol/IModule.abi.json"assert{type:"json"};import{resourceToHex as Lo}from"@latticexyz/common";import{resolveUserTypes as ge}from"@latticexyz/store";function $(e){let o={...e.userTypes,...Object.fromEntries(Object.entries(e.enums).map(([t])=>[t,{internalType:"uint8"}]))};return Object.fromEntries(Object.entries(e.tables).map(([t,r])=>[`${e.namespace}_${t}`,{namespace:e.namespace,name:r.name,tableId:Lo({type:r.offchainOnly?"offchainTable":"table",namespace:e.namespace,name:r.name}),keySchema:ge(r.keySchema,o),valueSchema:ge(r.valueSchema,o)}]))}import{helloStoreEvent as Yo}from"@latticexyz/store";import{helloWorldEvent as Zo}from"@latticexyz/world";var T=_o("0x",{size:32}),E=parseInt("6000",16),F=$(Ko),D=$(Jo),z=[Yo,Zo],C=[...qo,...Go],be=["1.0.0-unaudited"],he=["1.0.0-unaudited"];import{waitForTransactionReceipt as nt}from"viem/actions";import{concatHex as Qo,getCreate2Address as Xo}from"viem";import{getBytecode as et}from"viem/actions";import{sendTransaction as ot}from"@latticexyz/common";import tt from"p-retry";import{wait as rt}from"@latticexyz/common/utils";async function we({client:e,bytecode:o,deployedBytecodeSize:t,label:r="contract"}){let n=Xo({from:v,salt:T,bytecode:o});return await et(e,{address:n,blockTag:"pending"})?(l("found",r,"at",n),[]):(t>E?console.warn(`
|
3
|
-
Bytecode for ${r} (${t} bytes) is over the contract size limit (${E} bytes). Run \`forge build --sizes\` for more info.
|
4
|
-
`):t>E*.95&&console.warn(`
|
5
|
-
Bytecode for ${r} (${t} bytes) is almost over the contract size limit (${E} bytes). Run \`forge build --sizes\` for more info.
|
6
|
-
`),l("deploying",r,"at",n),[await tt(()=>ot(e,{chain:e.chain??null,to:v,data:Qo([T,o])}),{retries:3,onFailedAttempt:async d=>{let i=d.attemptNumber*500;l(`failed to deploy ${r}, retrying in ${i}ms...`),await rt(i)}})])}async function I({client:e,contracts:o}){let t=(await Promise.all(o.map(r=>we({client:e,...r})))).flat();if(t.length){l("waiting for contracts");for(let r of t)await nt(e,{hash:r})}return t}var it=De(xe.deployedBytecode.object),Te=ve({bytecode:xe.bytecode.object,abi:[]}),at=Ce({from:v,bytecode:Te,salt:T}),ct=De(Se.deployedBytecode.object),Ae=ve({bytecode:Se.bytecode.object,abi:st(["constructor(address)"]),args:[at]}),ke=Ce({from:v,bytecode:Ae,salt:T}),G=[{bytecode:Te,deployedBytecodeSize:it,label:"core module"},{bytecode:Ae,deployedBytecodeSize:ct,label:"world factory"}];async function Ie(e){return await I({client:e,contracts:G})}import yt from"@latticexyz/world/out/WorldFactory.sol/WorldFactory.abi.json"assert{type:"json"};import{writeContract as ut}from"@latticexyz/common";import{AbiEventSignatureNotFoundError as dt,decodeEventLog as lt,hexToString as Oe,parseAbi as mt,trim as Pe}from"viem";import{isDefined as pt}from"@latticexyz/common/utils";function V(e){let o=e.map(d=>{try{return{...d,...lt({strict:!0,abi:mt(z),topics:d.topics,data:d.data})}}catch(i){if(i instanceof dt)return;throw i}}).filter(pt),{address:t,deployBlock:r,worldVersion:n,storeVersion:s}=o.reduce((d,i)=>({...d,address:i.address,deployBlock:i.blockNumber,...i.eventName==="HelloWorld"?{worldVersion:Oe(Pe(i.args.worldVersion,{dir:"right"}))}:null,...i.eventName==="HelloStore"?{storeVersion:Oe(Pe(i.args.storeVersion,{dir:"right"}))}:null}),{});if(t==null)throw new Error("could not find world address");if(r==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:t,deployBlock:r,worldVersion:n,storeVersion:s}}async function je(e){await Ie(e),l("deploying world");let o=await ut(e,{chain:e.chain??null,address:ke,abi:yt,functionName:"deployWorld"});l("waiting for world deploy");let t=await ft(e,{hash:o});if(t.status!=="success")throw console.error("world deploy failed",t),new Error("world deploy failed");let r=V(t.logs.map(n=>n));return l("deployed world to",r.address,"at block",r.deployBlock),{...r,stateBlock:r.deployBlock}}import{writeContract as Ct}from"@latticexyz/common";import{valueSchemaToFieldLayoutHex as vt,keySchemaToHex as Dt,valueSchemaToHex as Tt}from"@latticexyz/protocol-parser";function S({namespace:e,name:o}){return`${e}:${o}`}import{parseAbiItem as gt,decodeAbiParameters as Be,parseAbiParameters as Fe}from"viem";import{hexToResource as bt}from"@latticexyz/common";import{storeSetRecordEvent as ht}from"@latticexyz/store";import{getLogs as wt}from"viem/actions";import{decodeKey as xt,decodeValueArgs as St,hexToSchema as Me}from"@latticexyz/protocol-parser";async function We({client:e,worldDeploy:o}){l("looking up tables for",o.address);let r=(await wt(e,{strict:!0,fromBlock:o.deployBlock,toBlock:o.stateBlock,address:o.address,event:gt(ht),args:{tableId:F.store_Tables.tableId}})).map(n=>{let{tableId:s}=xt(F.store_Tables.keySchema,n.args.keyTuple),{namespace:d,name:i}=bt(s),p=St(F.store_Tables.valueSchema,n.args),a=Me(p.keySchema),m=Me(p.valueSchema),f=Be(Fe("string[]"),p.abiEncodedKeyNames)[0],u=Be(Fe("string[]"),p.abiEncodedFieldNames)[0],y=[...m.staticFields,...m.dynamicFields],b=Object.fromEntries(a.staticFields.map((x,c)=>[f[c],x])),w=Object.fromEntries(y.map((x,c)=>[u[c],x]));return{namespace:d,name:i,tableId:s,keySchema:b,valueSchema:w}});return l("found",r.length,"tables for",o.address),r}import At from"p-retry";import{wait as kt}from"@latticexyz/common/utils";async function Re({client:e,worldDeploy:o,tables:t}){let n=(await We({client:e,worldDeploy:o})).map(i=>i.tableId),s=t.filter(i=>n.includes(i.tableId));s.length&&l("existing tables",s.map(S).join(", "));let d=t.filter(i=>!n.includes(i.tableId));return d.length?(l("registering tables",d.map(S).join(", ")),await Promise.all(d.map(i=>At(()=>Ct(e,{chain:e.chain??null,address:o.address,abi:C,functionName:"registerTable",args:[i.tableId,vt(i.valueSchema),Dt(i.keySchema),Tt(i.valueSchema),Object.keys(i.keySchema),Object.keys(i.valueSchema)]}),{retries:3,onFailedAttempt:async p=>{let a=p.attemptNumber*500;l(`failed to register table ${S(i)}, retrying in ${a}ms...`),await kt(a)}})))):[]}import{getAddress as A}from"viem";import{writeContract as Y}from"@latticexyz/common";import{parseAbiItem as It}from"viem";import{getLogs as Ot}from"viem/actions";import{storeSpliceStaticDataEvent as Pt}from"@latticexyz/store";async function U({client:e,worldDeploy:o}){l("looking up resource IDs for",o.address);let r=(await Ot(e,{strict:!0,address:o.address,fromBlock:o.deployBlock,toBlock:o.stateBlock,event:It(Pt),args:{tableId:F.store_ResourceIds.tableId}})).map(n=>n.args.keyTuple[0]);return l("found",r.length,"resource IDs for",o.address),r}import{hexToResource as _t}from"@latticexyz/common";import{decodeValueArgs as jt,encodeKey as Bt}from"@latticexyz/protocol-parser";import{readContract as Ft}from"viem/actions";async function O({client:e,worldDeploy:o,table:t,key:r}){let[n,s,d]=await Ft(e,{blockNumber:o.stateBlock,address:o.address,abi:C,functionName:"getRecord",args:[t.tableId,Bt(t.keySchema,r)]});return jt(t.valueSchema,{staticData:n,encodedLengths:s,dynamicData:d})}import{getFunctionSelector as Mt,parseAbiItem as Wt}from"viem";import{storeSetRecordEvent as Rt}from"@latticexyz/store";import{getLogs as $t}from"viem/actions";import{decodeValueArgs as Et}from"@latticexyz/protocol-parser";import{hexToResource as Ht}from"@latticexyz/common";async function L({client:e,worldDeploy:o}){l("looking up function signatures for",o.address);let r=(await $t(e,{strict:!0,fromBlock:o.deployBlock,toBlock:o.stateBlock,address:o.address,event:Wt(Rt),args:{tableId:D.world_FunctionSignatures.tableId}})).map(s=>Et(D.world_FunctionSignatures.valueSchema,s.args).functionSignature);return l("found",r.length,"function signatures for",o.address),await Promise.all(r.map(async s=>{let d=Mt(s),{systemId:i,systemFunctionSelector:p}=await O({client:e,worldDeploy:o,table:D.world_FunctionSelectors,key:{functionSelector:d}}),{namespace:a,name:m}=Ht(i),f=a===""?s:s.replace(`${a}_${m}_`,"");return{signature:s,selector:d,systemId:i,systemFunctionSignature:f,systemFunctionSelector:p}}))}import{parseAbiItem as Nt,getAddress as zt}from"viem";import{storeSpliceStaticDataEvent as Vt}from"@latticexyz/store";import{getLogs as Ut}from"viem/actions";import{decodeKey as Lt}from"@latticexyz/protocol-parser";async function _({client:e,worldDeploy:o}){l("looking up resource access for",o.address);let r=(await Ut(e,{strict:!0,fromBlock:o.deployBlock,toBlock:o.stateBlock,address:o.address,event:Nt(Vt),args:{tableId:D.world_ResourceAccess.tableId}})).map(s=>Lt(D.world_ResourceAccess.keySchema,s.args.keyTuple)),n=(await Promise.all(r.map(async s=>[s,await O({client:e,worldDeploy:o,table:D.world_ResourceAccess,key:s})]))).filter(([,s])=>s.access).map(([s])=>({resourceId:s.resourceId,address:zt(s.caller)}));return l("found",n.length,"resource<>address access pairs"),n}async function $e({client:e,worldDeploy:o}){let[t,r,n]=await Promise.all([U({client:e,worldDeploy:o}),L({client:e,worldDeploy:o}),_({client:e,worldDeploy:o})]),s=t.map(_t).filter(d=>d.type==="system");return l("looking up systems",s.map(S).join(", ")),await Promise.all(s.map(async d=>{let{system:i,publicAccess:p}=await O({client:e,worldDeploy:o,table:D.world_Systems,key:{systemId:d.resourceId}}),a=r.filter(m=>m.systemId===d.resourceId);return{address:i,namespace:d.namespace,name:d.name,systemId:d.resourceId,allowAll:p,allowedAddresses:n.filter(({resourceId:m})=>m===d.resourceId).map(({address:m})=>m),functions:a}}))}import{uniqueBy as Kt,wait as Z}from"@latticexyz/common/utils";import Q from"p-retry";async function Ee({client:e,worldDeploy:o,systems:t}){let[r,n]=await Promise.all([$e({client:e,worldDeploy:o}),_({client:e,worldDeploy:o})]),s=t.map(c=>c.systemId),d=n.filter(({resourceId:c})=>s.includes(c)),i=t.flatMap(c=>c.allowedAddresses.map(g=>({resourceId:c.systemId,address:g}))),p=i.filter(c=>!d.some(({resourceId:g,address:h})=>g===c.resourceId&&A(h)===A(c.address))),a=d.filter(c=>!i.some(({resourceId:g,address:h})=>g===c.resourceId&&A(h)===A(c.address)));a.length&&l("revoking",a.length,"access grants"),p.length&&l("adding",p.length,"access grants");let m=[...a.map(c=>Q(()=>Y(e,{chain:e.chain??null,address:o.address,abi:C,functionName:"revokeAccess",args:[c.resourceId,c.address]}),{retries:3,onFailedAttempt:async g=>{let h=g.attemptNumber*500;l(`failed to revoke access, retrying in ${h}ms...`),await Z(h)}})),...p.map(c=>Q(()=>Y(e,{chain:e.chain??null,address:o.address,abi:C,functionName:"grantAccess",args:[c.resourceId,c.address]}),{retries:3,onFailedAttempt:async g=>{let h=g.attemptNumber*500;l(`failed to grant access, retrying in ${h}ms...`),await Z(h)}}))],f=t.filter(c=>r.some(g=>g.systemId===c.systemId&&A(g.address)===A(c.address)));f.length&&l("existing systems",f.map(S).join(", "));let u=f.map(c=>c.systemId),y=t.filter(c=>!u.includes(c.systemId));if(!y.length)return[];let b=y.filter(c=>r.some(g=>g.systemId===c.systemId&&A(g.address)!==A(c.address)));b.length&&l("upgrading systems",b.map(S).join(", "));let w=y.filter(c=>!r.some(g=>g.systemId===c.systemId));w.length&&l("registering new systems",w.map(S).join(", ")),await I({client:e,contracts:Kt(y,c=>A(c.address)).map(c=>({bytecode:c.bytecode,deployedBytecodeSize:c.deployedBytecodeSize,label:`${S(c)} system`}))});let x=y.map(c=>Q(()=>Y(e,{chain:e.chain??null,address:o.address,abi:C,functionName:"registerSystem",args:[c.systemId,c.address,c.allowAll]}),{retries:3,onFailedAttempt:async g=>{let h=g.attemptNumber*500;l(`failed to register system ${S(c)}, retrying in ${h}ms...`),await Z(h)}}));return await Promise.all([...m,...x])}import{waitForTransactionReceipt as sr}from"viem/actions";import{getAddress as Jt,parseAbi as qt}from"viem";import{getBlockNumber as Gt,getLogs as Yt}from"viem/actions";var He=new Map;async function Ne(e,o){let t=Jt(o),r=He.get(t);if(r!=null)return r;l("looking up world deploy for",t);let n=await Gt(e),s=await Yt(e,{strict:!0,address:t,events:qt(z),fromBlock:"earliest",toBlock:n});return r={...V(s),stateBlock:n},He.set(t,r),l("found world deploy for",t,"at block",r.deployBlock),r}import{hexToResource as Zt,writeContract as ze}from"@latticexyz/common";import Ve from"p-retry";import{wait as Ue}from"@latticexyz/common/utils";async function Le({client:e,worldDeploy:o,functions:t}){let r=await L({client:e,worldDeploy:o}),n=Object.fromEntries(r.map(i=>[i.selector,i])),s=t.filter(i=>n[i.selector]),d=t.filter(i=>!s.includes(i));if(s.length){l("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 d.length?(l("registering functions:",d.map(i=>i.signature).join(", ")),Promise.all(d.map(i=>{let{namespace:p}=Zt(i.systemId);return p===""?Ve(()=>ze(e,{chain:e.chain??null,address:o.address,abi:C,functionName:"registerRootFunctionSelector",args:[i.systemId,i.systemFunctionSignature,i.systemFunctionSelector]}),{retries:3,onFailedAttempt:async a=>{let m=a.attemptNumber*500;l(`failed to register function ${i.signature}, retrying in ${m}ms...`),await Ue(m)}}):Ve(()=>ze(e,{chain:e.chain??null,address:o.address,abi:C,functionName:"registerFunctionSelector",args:[i.systemId,i.systemFunctionSignature]}),{retries:3,onFailedAttempt:async a=>{let m=a.attemptNumber*500;l(`failed to register function ${i.signature}, retrying in ${m}ms...`),await Ue(m)}})}))):[]}import{BaseError as Qt,getAddress as Xt}from"viem";import{writeContract as _e}from"@latticexyz/common";import{isDefined as er,uniqueBy as or,wait as tr}from"@latticexyz/common/utils";import rr from"p-retry";async function Ke({client:e,worldDeploy:o,modules:t}){return t.length?(await I({client:e,contracts:or(t,r=>Xt(r.address)).map(r=>({bytecode:r.bytecode,deployedBytecodeSize:r.deployedBytecodeSize,label:`${r.name} module`}))}),l("installing modules:",t.map(r=>r.name).join(", ")),(await Promise.all(t.map(r=>rr(async()=>{try{return r.installAsRoot?await _e(e,{chain:e.chain??null,address:o.address,abi:C,functionName:"installRootModule",args:[r.address,r.installData]}):await _e(e,{chain:e.chain??null,address:o.address,abi:C,functionName:"installModule",args:[r.address,r.installData]})}catch(n){if(n instanceof Qt&&n.message.includes("Module_AlreadyInstalled")){l(`module ${r.name} already installed`);return}throw n}},{retries:3,onFailedAttempt:async n=>{let s=n.attemptNumber*500;l(`failed to install module ${r.name}, retrying in ${s}ms...`),await tr(s)}})))).filter(er)):[]}import{getAddress as Je}from"viem";import{hexToResource as qe,resourceToHex as nr}from"@latticexyz/common";async function Ge({client:e,worldDeploy:o,resourceIds:t}){let r=Array.from(new Set(t.map(a=>qe(a).namespace))),n=await U({client:e,worldDeploy:o}),s=Array.from(new Set(n.map(a=>qe(a).namespace))),d=r.filter(a=>s.includes(a)),p=(await Promise.all(d.map(async a=>{let{owner:m}=await O({client:e,worldDeploy:o,table:D.world_NamespaceOwner,key:{namespaceId:nr({type:"namespace",namespace:a,name:""})}});return[a,m]}))).filter(([,a])=>Je(a)!==Je(e.account.address)).map(([a])=>a);if(p.length)throw new Error(`You are attempting to deploy to namespaces you do not own: ${p.join(", ")}`)}import{uniqueBy as Ze}from"@latticexyz/common/utils";async function Qe({client:e,config:o,worldAddress:t}){let r=Object.values(o.tables),n=Object.values(o.systems);await ue(e),await I({client:e,contracts:[...G,...Ze(n,f=>Ye(f.address)).map(f=>({bytecode:f.bytecode,deployedBytecodeSize:f.deployedBytecodeSize,label:`${S(f)} system`})),...Ze(o.modules,f=>Ye(f.address)).map(f=>({bytecode:f.bytecode,deployedBytecodeSize:f.deployedBytecodeSize,label:`${f.name} module`}))]});let s=t?await Ne(e,t):await je(e);if(!be.includes(s.storeVersion))throw new Error(`Unsupported Store version: ${s.storeVersion}`);if(!he.includes(s.worldVersion))throw new Error(`Unsupported World version: ${s.worldVersion}`);await Ge({client:e,worldDeploy:s,resourceIds:[...r.map(f=>f.tableId),...n.map(f=>f.systemId)]});let d=await Re({client:e,worldDeploy:s,tables:r}),i=await Ee({client:e,worldDeploy:s,systems:n}),p=await Le({client:e,worldDeploy:s,functions:n.flatMap(f=>f.functions)}),a=await Ke({client:e,worldDeploy:s,modules:o.modules}),m=[...d,...i,...p,...a];l("waiting for all transactions to confirm");for(let f of m)await sr(e,{hash:f});return l("deploy complete"),s}import{createWalletClient as Ar,http as kr}from"viem";import{privateKeyToAccount as Ir}from"viem/accounts";import{loadConfig as Or}from"@latticexyz/config/node";import{forge as Pr,getOutDirectory as jr,getRemappings as Br,getRpcUrl as Fr,getSrcDirectory as Mr}from"@latticexyz/common/foundry";import M from"chalk";import{execa as Wr}from"execa";import{MUDError as Rr}from"@latticexyz/common/errors";import{resolveWorldConfig as mr}from"@latticexyz/world";import{resourceToHex as re,hexToResource as pr}from"@latticexyz/common";import{resolveWithContext as fr}from"@latticexyz/config";import{encodeField as yr}from"@latticexyz/protocol-parser";import{getFunctionSelector as eo,getCreate2Address as oo,getAddress as ur,hexToBytes as gr,bytesToHex as br,getFunctionSignature as to}from"viem";import ir from"glob";import{basename as ar}from"path";function P(e){return ir.sync(`${e}/**/*.sol`).map(o=>({path:o,basename:ar(o,".sol")}))}import X from"@latticexyz/world-modules/out/KeysWithValueModule.sol/KeysWithValueModule.json"assert{type:"json"};import ee from"@latticexyz/world-modules/out/KeysInTableModule.sol/KeysInTableModule.json"assert{type:"json"};import oe from"@latticexyz/world-modules/out/UniqueEntityModule.sol/UniqueEntityModule.json"assert{type:"json"};import{size as te}from"viem";var Xe=[{name:"KeysWithValueModule",abi:X.abi,bytecode:X.bytecode.object,deployedBytecodeSize:te(X.deployedBytecode.object)},{name:"KeysInTableModule",abi:ee.abi,bytecode:ee.bytecode.object,deployedBytecodeSize:te(ee.deployedBytecode.object)},{name:"UniqueEntityModule",abi:oe.abi,bytecode:oe.bytecode.object,deployedBytecodeSize:te(oe.deployedBytecode.object)}];import{readFileSync as cr}from"fs";import dr from"path";import{MUDError as K}from"@latticexyz/common/errors";import{size as lr}from"viem";function J(e,o){let t,r=dr.join(o,e+".sol",e+".json");try{t=JSON.parse(cr(r,"utf8"))}catch{throw new K(`Error reading file at ${r}`)}let n=t?.bytecode?.object;if(!n)throw new K(`No bytecode found in ${r}`);let s=t?.deployedBytecode?.object;if(!s)throw new K(`No deployed bytecode found in ${r}`);let d=t?.abi;if(!d)throw new K(`No ABI found in ${r}`);return{abi:d,bytecode:n,deployedBytecodeSize:lr(s)}}function ro({config:e,forgeSourceDir:o,forgeOutDir:t}){let r=$(e),n=P(o).map(({basename:u})=>u),s=mr(e,n),i=J("System",t).abi.filter(u=>u.type==="function").map(to),p=Object.entries(s.systems).map(([u,y])=>{let b=e.namespace,w=y.name,x=re({type:"system",namespace:b,name:w}),c=J(u,t),g=c.abi.filter(h=>h.type==="function").map(to).filter(h=>!i.includes(h)).map(h=>{let ae=b===""?h:`${b}_${w}_${h}`;return{signature:ae,selector:eo(ae),systemId:x,systemFunctionSignature:h,systemFunctionSelector:eo(h)}});return{namespace:b,name:w,systemId:x,allowAll:y.openAccess,allowedAddresses:y.accessListAddresses,allowedSystemIds:y.accessListSystems.map(h=>re({type:"system",namespace:b,name:s.systems[h].name})),address:oo({from:v,bytecode:c.bytecode,salt:T}),bytecode:c.bytecode,deployedBytecodeSize:c.deployedBytecodeSize,abi:c.abi,functions:g}}),a=p.map(({allowedAddresses:u,allowedSystemIds:y,...b})=>{let w=y.map(x=>{let c=p.find(g=>g.systemId===x);if(!c)throw new Error(`System ${S(b)} wanted access to ${S(pr(x))}, but it wasn't found in the config.`);return c.address});return{...b,allowedAddresses:Array.from(new Set([...u,...w].map(x=>ur(x))))}}),m={tableIds:Object.fromEntries(Object.entries(e.tables).map(([u,y])=>[u,gr(re({type:y.offchainOnly?"offchainTable":"table",namespace:e.namespace,name:y.name}))]))},f=e.modules.map(u=>{let y=Xe.find(w=>w.name===u.name)??J(u.name,t),b=u.args.map(w=>fr(w,m)).map(w=>{let x=w.value instanceof Uint8Array?br(w.value):w.value;return yr(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:oo({from:v,bytecode:y.bytecode,salt:T}),bytecode:y.bytecode,deployedBytecodeSize:y.deployedBytecodeSize,abi:y.abi}});return{tables:r,systems:a,modules:f}}import{getChainId as $r}from"viem/actions";import{existsSync as hr}from"fs";import wr from"path";import xr from"chalk";import{getScriptDirectory as Sr,forge as Cr}from"@latticexyz/common/foundry";async function no(e,o,t,r){let n=wr.join(await Sr(),e+".s.sol");hr(n)?(console.log(xr.blue(`Executing post deploy script at ${n}`)),await Cr(["script",e,"--sig","run(address)",o,"--broadcast","--rpc-url",t,"-vvv"],{profile:r})):console.log(`No script at ${n}, skipping post deploy hook`)}import{tablegen as Er}from"@latticexyz/store/codegen";import{worldgen as Hr}from"@latticexyz/world/node";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 W(e){let o=e.profile??process.env.FOUNDRY_PROFILE,t=await Or(e.configPath);e.printConfig&&console.log(M.green(`
|
7
|
-
Resolved config:
|
8
|
-
`),JSON.stringify(t,null,2));let r=e.srcDir??await Mr(o),n=await jr(o),s=await Br(),d=e.rpc??await Fr(o);if(console.log(M.bgBlue(M.whiteBright(`
|
9
|
-
Deploying MUD contracts${o?" with profile "+o:""} to RPC ${d}
|
10
|
-
`))),!e.skipBuild){let y=q.join(r,t.codegenDirectory);await Promise.all([Er(t,y,s),Hr(t,P(r),y)]),await Pr(["build"],{profile:o}),await Wr("mud",["abi-ts"],{stdio:"inherit"})}let i=process.env.PRIVATE_KEY;if(!i)throw new Rr(`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=ro({config:t,forgeSourceDir:r,forgeOutDir:n}),a=Ar({transport:kr(d),account:Ir(i)});console.log("Deploying from",a.account.address);let m=Date.now(),f=await Qe({worldAddress:e.worldAddress,client:a,config:p});(e.worldAddress==null||e.alwaysRunPostDeploy)&&await no(t.postDeployScript,f.address,d,o),console.log(M.green("Deployment completed in",(Date.now()-m)/1e3,"seconds"));let u={worldAddress:f.address,blockNumber:Number(f.deployBlock)};if(e.saveDeployment){let y=await $r(a),b=q.join(t.deploysDirectory,y.toString());Dr(b,{recursive:!0}),ne(q.join(b,"latest.json"),JSON.stringify(u,null,2)),ne(q.join(b,Date.now()+".json"),JSON.stringify(u,null,2));let w=[1337,31337],x=vr(t.worldsFile)?JSON.parse(Tr(t.worldsFile,"utf-8")):{};x[y]={address:u.worldAddress,blockNumber:w.includes(y)?void 0:u.blockNumber},ne(t.worldsFile,JSON.stringify(x,null,2)),console.log(M.bgGreen(M.whiteBright(`
|
13
|
-
Deployment result (written to ${t.worldsFile} and ${b}):
|
14
|
-
`)))}return console.log(u),f}var Nr={command:"deploy",describe:"Deploy MUD contracts",builder(e){return e.options(k)},async handler(e){try{await W(e)}catch(o){N(o),process.exit(1)}process.exit(0)}},so=Nr;import{loadConfig as zr}from"@latticexyz/config/node";import{worldgen as Vr}from"@latticexyz/world/node";import{getSrcDirectory as Ur}from"@latticexyz/common/foundry";import io from"path";import{rmSync as Lr}from"fs";var _r={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 Kr(e),process.exit(0)}};async function Kr(e){let o=e.srcDir??await Ur(),t=P(o),r=e.config??await zr(e.configPath),n=io.join(o,r.codegenDirectory);e.clean&&Lr(io.join(n,r.worldgenDirectory),{recursive:!0,force:!0}),await Vr(r,t,n)}var ao=_r;import H from"chalk";import{readFileSync as Zr,writeFileSync as Qr}from"fs";import ie from"path";import{MUDError as R}from"@latticexyz/common/errors";var co={name:"@latticexyz/cli",version:"2.0.0-next.14",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 Xr from"glob";import{ZodError as qr,z as lo}from"zod";var Gr=lo.object({MUD_PACKAGES:lo.string().transform(e=>JSON.parse(e))});function Yr(){try{return Gr.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 qr){let{_errors:o,...t}=e.format();console.error(`
|
15
|
-
Missing or invalid environment variables:
|
16
|
-
|
17
|
-
${Object.keys(t).join(`
|
18
|
-
`)}
|
19
|
-
`),process.exit(1)}throw e}}var se=Yr().MUD_PACKAGES;var en={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"],t=o.reduce((n,s)=>e[s]?n+1:n,0);if(t===0)throw new R(`You need to provide one these options: ${o.join(", ")}`);if(t>1)throw new R(`These options are mutually exclusive: ${o.join(", ")}`);e.mudVersion=await on(e);let r=Xr.sync("**/package.json").filter(n=>!n.includes("node_modules"));for(let n of r)tn(n,e)}catch(o){N(o)}finally{process.exit(0)}}};async function on(e){e.mudVersion==="canary"&&(e.tag="main");let o;try{console.log(H.blue("Fetching available versions")),o=await(await fetch(`https://registry.npmjs.org/${co.name}`)).json()}catch{throw new R("Could not fetch available MUD versions")}if(e.tag){let t=o["dist-tags"][e.tag];if(!t)throw new R(`Could not find npm version with tag "${e.tag}"`);return console.log(H.green(`Latest version with tag ${e.tag}: ${t}`)),t}if(e.commit){let t=e.commit.substring(0,8),r=Object.keys(o.versions).find(n=>n.includes(t));if(!r)throw new R(`Could not find npm version based on commit "${e.commit}"`);return console.log(H.green(`Version from commit ${e.commit}: ${r}`)),r}return e.mudVersion}function tn(e,o){let{link:t}=o,{mudVersion:r}=o,n=rn(e),s=Object.keys(se),d={};for(let a in n.dependencies)s.includes(a)&&(d[a]=n.dependencies[a]);let i={};for(let a in n.devDependencies)s.includes(a)&&(i[a]=n.devDependencies[a]);for(let a in n.dependencies)s.includes(a)&&(n.dependencies[a]=p(a,"dependencies"));for(let a in n.devDependencies)s.includes(a)&&(n.devDependencies[a]=p(a,"devDependencies"));return Qr(e,JSON.stringify(n,null,2)+`
|
20
|
-
`),console.log(`Updating ${e}`),mo(d,n.dependencies),mo(i,n.devDependencies),n;function p(a,m){return t&&(r=nn(e,t,a)),r||n[m][a]}}function rn(e){try{let o=Zr(e,"utf8");return JSON.parse(o)}catch{throw new R("Could not read JSON at "+e)}}function mo(e,o){for(let t in e)e[t]!==o[t]&&console.log(`${t}: ${H.red(e[t])} -> ${H.green(o[t])}`)}function nn(e,o,t){let r=ie.relative(ie.dirname(e),process.cwd());return"link:"+ie.join(r,o,se[t].localPath)}var po=en;import{anvil as sn,forge as an,getRpcUrl as cn}from"@latticexyz/common/foundry";import dn from"chalk";var ln={...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"}},mn={command:"test",describe:"Run tests in MUD contracts",builder(e){return e.options(ln)},async handler(e){if(!e.worldAddress){let n=["--block-base-fee-per-gas","0","--port",String(e.port)];sn(n)}let o=e.worldAddress?await cn(e.profile):`http://127.0.0.1:${e.port}`,t=e.worldAddress??(await W({...e,saveDeployment:!1,rpc:o})).address;console.log(dn.blue("World address",t));let r=e.forgeOptions?.replaceAll("\\","").split(" ")??[];try{await an(["test","--fork-url",o,...r],{profile:e.profile,env:{WORLD_ADDRESS:t}}),process.exit(0)}catch(n){console.error(n),process.exit(1)}}},fo=mn;import{existsSync as pn,readFileSync as fn}from"fs";import{ethers as yo}from"ethers";import{loadConfig as yn}from"@latticexyz/config/node";import{MUDError as uo}from"@latticexyz/common/errors";import{cast as un,getRpcUrl as gn,getSrcDirectory as bn}from"@latticexyz/common/foundry";import{resolveWorldConfig as hn}from"@latticexyz/world";import wn from"@latticexyz/world/out/IBaseWorld.sol/IBaseWorld.abi.json"assert{type:"json"};import go from"@latticexyz/world/mud.config";import{resourceToHex as ho}from"@latticexyz/common";import{createClient as xn,http as Sn}from"viem";import{getChainId as Cn}from"viem/actions";var bo=ho({type:"system",namespace:go.namespace,name:go.tables.Systems.name}),vn={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 bn(o),e.rpc??=await gn(o);let{tx:t,configPath:r,srcDir:n,rpc:s}=e,d=P(n),i=await yn(r),p=hn(i,d.map(({basename:c})=>c)),a=e.worldAddress??await Dn(i.worldsFile,s),m=new yo.providers.StaticJsonRpcProvider(s),f=new yo.Contract(a,wn,m),u=i.namespace,y=Object.values(p.systems).map(({name:c})=>c),b=await f.getFieldLayout(bo),w=[];for(let c of y){let g=ho({type:"system",namespace:u,name:c}),h=await f.getField(bo,[g],0,b);w.push({name:c,address:h})}let x=await un(["run","--label",`${a}:World`,...w.map(({name:c,address:g})=>["--label",`${g}:${c}`]).flat(),`${t}`]);console.log(x),process.exit(0)}},wo=vn;async function Dn(e,o){if(pn(e)){let t=xn({transport:Sn(o)}),r=await Cn(t),n=JSON.parse(fn(e,"utf-8"));if(!n[r])throw new uo(`chainId ${r} is missing in worldsFile "${e}"`);return n[r].address}else throw new uo("worldAddress is not specified and worldsFile is missing")}import{anvil as Tn,getScriptDirectory as An,getSrcDirectory as kn}from"@latticexyz/common/foundry";import j from"chalk";import In from"chokidar";import{loadConfig as On,resolveConfigPath as Pn}from"@latticexyz/config/node";import jn from"path";import{homedir as Bn}from"os";import{rmSync as Fn}from"fs";import{BehaviorSubject as Mn,debounceTime as Wn,exhaustMap as Rn,filter as $n}from"rxjs";import{isDefined as En}from"@latticexyz/common/utils";var Hn={rpc:k.rpc,configPath:k.configPath,alwaysRunPostDeploy:k.alwaysRunPostDeploy,worldAddress:k.worldAddress},Nn={command:"dev-contracts",describe:"Start a development server for MUD contracts",builder(e){return e.options(Hn)},async handler(e){let o=e.rpc,t=e.configPath??await Pn(e.configPath),r=await kn(),n=await An(),s=await On(t);if(!e.rpc){console.log(j.gray("Cleaning devnode cache"));let a=Bn();Fn(jn.join(a,".foundry","anvil","tmp"),{recursive:!0,force:!0}),Tn(["--block-time","1","--block-base-fee-per-gas","0"]),o="http://127.0.0.1:8545"}let d=new Mn(Date.now());In.watch([t,r,n],{ignoreInitial:!0}).on("all",async(a,m)=>{m.includes(t)&&(console.log(j.blue("Config changed, queuing deploy\u2026")),d.next(Date.now())),(m.includes(r)||m.includes(n))&&(m.includes(s.codegenDirectory)||(console.log(j.blue("Contracts changed, queuing deploy\u2026")),d.next(Date.now())))});let i=e.worldAddress;d.pipe(Wn(200),Rn(async a=>{i&&console.log(j.blue("Rebuilding and upgrading world\u2026"));try{let m=await W({...e,configPath:t,rpc:o,skipBuild:!1,printConfig:!1,profile:void 0,saveDeployment:!0,worldAddress:i,srcDir:r});return i=m.address,a<d.value?d.next(d.value):console.log(j.gray(`
|
21
|
-
Waiting for file changes\u2026
|
22
|
-
`)),m}catch(m){console.error(j.bgRed(j.whiteBright(`
|
23
|
-
Error while attempting deploy
|
24
|
-
`))),console.error(m),console.log(j.gray(`
|
25
|
-
Waiting for file changes\u2026
|
26
|
-
`))}}),$n(En)).subscribe()}},xo=Nn;var Hm=[so,ce,le,zn,me,pe,ao,po,fo,wo,xo,Vn];export{Hm as commands};
|
27
|
-
//# sourceMappingURL=commands-UYAATBY6.js.map
|