@latticexyz/cli 2.0.0-next.11 → 2.0.0-next.12

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.
Files changed (61) hide show
  1. package/dist/index.js +0 -1
  2. package/dist/mud.js +19 -13
  3. package/dist/mud.js.map +1 -1
  4. package/package.json +16 -12
  5. package/src/commands/deploy.ts +7 -30
  6. package/src/commands/dev-contracts.ts +74 -138
  7. package/src/commands/test.ts +30 -36
  8. package/src/commands/trace.ts +7 -5
  9. package/src/debug.ts +3 -0
  10. package/src/deploy/assertNamespaceOwner.ts +42 -0
  11. package/src/deploy/common.ts +72 -0
  12. package/src/deploy/configToTables.ts +68 -0
  13. package/src/deploy/create2/README.md +9 -0
  14. package/src/deploy/create2/deployment.json +7 -0
  15. package/src/deploy/debug.ts +3 -0
  16. package/src/deploy/deploy.ts +108 -0
  17. package/src/deploy/deployWorld.ts +33 -0
  18. package/src/deploy/ensureContract.ts +49 -0
  19. package/src/deploy/ensureContractsDeployed.ts +25 -0
  20. package/src/deploy/ensureDeployer.ts +36 -0
  21. package/src/deploy/ensureFunctions.ts +86 -0
  22. package/src/deploy/ensureModules.ts +72 -0
  23. package/src/deploy/ensureSystems.ts +161 -0
  24. package/src/deploy/ensureTables.ts +65 -0
  25. package/src/deploy/ensureWorldFactory.ts +34 -0
  26. package/src/deploy/getFunctions.ts +58 -0
  27. package/src/deploy/getResourceAccess.ts +51 -0
  28. package/src/deploy/getResourceIds.ts +31 -0
  29. package/src/deploy/getSystems.ts +48 -0
  30. package/src/deploy/getTableValue.ts +30 -0
  31. package/src/deploy/getTables.ts +59 -0
  32. package/src/deploy/getWorldDeploy.ts +39 -0
  33. package/src/deploy/logsToWorldDeploy.ts +49 -0
  34. package/src/deploy/resolveConfig.ts +154 -0
  35. package/src/deploy/resourceLabel.ts +3 -0
  36. package/src/index.ts +1 -1
  37. package/src/runDeploy.ts +128 -0
  38. package/src/utils/modules/constants.ts +1 -2
  39. package/src/utils/utils/getContractData.ts +2 -5
  40. package/dist/chunk-TW3YGZ4D.js +0 -11
  41. package/dist/chunk-TW3YGZ4D.js.map +0 -1
  42. package/src/utils/deploy.ts +0 -254
  43. package/src/utils/deployHandler.ts +0 -93
  44. package/src/utils/modules/getInstallModuleCallData.ts +0 -27
  45. package/src/utils/modules/getUserModules.ts +0 -5
  46. package/src/utils/modules/types.ts +0 -14
  47. package/src/utils/systems/getGrantAccessCallData.ts +0 -29
  48. package/src/utils/systems/getRegisterFunctionSelectorsCallData.ts +0 -57
  49. package/src/utils/systems/getRegisterSystemCallData.ts +0 -17
  50. package/src/utils/systems/types.ts +0 -9
  51. package/src/utils/systems/utils.ts +0 -42
  52. package/src/utils/tables/getRegisterTableCallData.ts +0 -49
  53. package/src/utils/tables/getTableIds.ts +0 -18
  54. package/src/utils/tables/types.ts +0 -12
  55. package/src/utils/utils/confirmNonce.ts +0 -24
  56. package/src/utils/utils/deployContract.ts +0 -33
  57. package/src/utils/utils/fastTxExecute.ts +0 -56
  58. package/src/utils/utils/getChainId.ts +0 -10
  59. package/src/utils/utils/setInternalFeePerGas.ts +0 -49
  60. package/src/utils/utils/types.ts +0 -21
  61. package/src/utils/world.ts +0 -28
package/dist/index.js CHANGED
@@ -1,2 +1 @@
1
- import{c as o}from"./chunk-TW3YGZ4D.js";export{o as deployHandler};
2
1
  //# sourceMappingURL=index.js.map
package/dist/mud.js CHANGED
@@ -1,20 +1,26 @@
1
1
  #!/usr/bin/env node
2
- import{a as k,b as R,c as y}from"./chunk-TW3YGZ4D.js";import Oo from"yargs";import{hideBin as Po}from"yargs/helpers";import Mo from"@latticexyz/gas-report";import So from"@latticexyz/abi-ts";import{rmSync as ae}from"fs";import{homedir as ce}from"os";import de from"path";import{execa as le}from"execa";var pe={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=ce();ae(de.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 n=le("anvil",t,{stdio:["inherit","inherit","inherit"]});process.on("SIGINT",()=>{console.log(`
3
- gracefully shutting down from SIGINT (Crtl-C)`),n.kill(),process.exit()}),await n}},A=pe;import{FaucetServiceDefinition as me}from"@latticexyz/services/faucet";import{createChannel as fe,createClient as ge}from"nice-grpc-web";import E from"chalk";import{NodeHttpTransport as ue}from"@improbable-eng/grpc-web-node-http-transport";function ye(e){return ge(me,fe(e,ue()))}var he={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 n=ye(o);e&&(console.log(E.yellow("Dripping to",t)),await n.dripDev({address:t}),console.log(E.yellow("Success"))),process.exit(0)}},W=he;var be={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)}},$=be;import we from"path";import{loadConfig as ve}from"@latticexyz/config/node";import{tablegen as De}from"@latticexyz/store/codegen";import{getRemappings as Ce,getSrcDirectory as ke}from"@latticexyz/common/foundry";var xe={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 ve(e),t=await ke(),n=await Ce();await De(o,we.join(t,o.codegenDirectory),n),process.exit(0)}},I=xe;import w from"chalk";import{ZodError as Me}from"zod";import{fromZodError as Se,ValidationError as Oe}from"zod-validation-error";import{NotInsideProjectError as Pe}from"@latticexyz/config";import{MUDError as je}from"@latticexyz/common/errors";function f(e){if(e instanceof Oe)console.log(w.redBright(e.message));else if(e instanceof Me){let o=Se(e,{prefixSeparator:`
2
+ import zn from"yargs";import{hideBin as Jn}from"yargs/helpers";import Ln from"@latticexyz/gas-report";import Kn from"@latticexyz/abi-ts";import{rmSync as xo}from"fs";import{homedir as Co}from"os";import So from"path";import{execa as vo}from"execa";var Do={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();xo(So.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=vo("anvil",t,{stdio:["inherit","inherit","inherit"]});process.on("SIGINT",()=>{console.log(`
3
+ gracefully shutting down from SIGINT (Crtl-C)`),r.kill(),process.exit()}),await r}},ie=Do;import{FaucetServiceDefinition as To}from"@latticexyz/services/faucet";import{createChannel as ko,createClient as Ao}from"nice-grpc-web";import ae from"chalk";import{NodeHttpTransport as Io}from"@improbable-eng/grpc-web-node-http-transport";function Oo(e){return Ao(To,ko(e,Io()))}var Po={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=Oo(o);e&&(console.log(ae.yellow("Dripping to",t)),await r.dripDev({address:t}),console.log(ae.yellow("Success"))),process.exit(0)}},ce=Po;var Mo={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)}},le=Mo;import Wo from"path";import{loadConfig as jo}from"@latticexyz/config/node";import{tablegen as Fo}from"@latticexyz/store/codegen";import{getRemappings as Ro,getSrcDirectory as Eo}from"@latticexyz/common/foundry";var $o={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 jo(e),t=await Eo(),r=await Ro();await Fo(o,Wo.join(t,o.codegenDirectory),r),process.exit(0)}},de=$o;import B from"chalk";import{ZodError as No}from"zod";import{fromZodError as Bo,ValidationError as Ho}from"zod-validation-error";import{NotInsideProjectError as Uo}from"@latticexyz/config";import{MUDError as Vo}from"@latticexyz/common/errors";function F(e){if(e instanceof Ho)console.log(B.redBright(e.message));else if(e instanceof No){let o=Bo(e,{prefixSeparator:`
4
4
  - `,issueSeparator:`
5
- - `});console.log(w.redBright(o.message))}else e instanceof Pe?(console.log(w.red(e.message)),console.log(""),console.log(w.blue("To learn more about MUD's configuration, please go to https://mud.dev/packages/cli/"))):e instanceof je?console.log(w.red(e)):console.log(e)}var S={configPath:{type:"string",desc:"Path to the config file"},clean:{type:"boolean",desc:"Remove the build forge artifacts and cache directories before building"},printConfig:{type:"boolean",desc:"Print the resolved config"},profile:{type:"string",desc:"The foundry profile to use"},debug:{type:"boolean",desc:"Print debug logs, like full error messages"},priorityFeeMultiplier:{type:"number",desc:"Multiply the estimated priority fee by the provided factor",default:1},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."},disableTxWait:{type:"boolean",desc:"Disable waiting for transactions to be confirmed.",default:!1},pollInterval:{type:"number",desc:"Interval in miliseconds to use to poll for transaction receipts / block inclusion",default:1e3},skipBuild:{type:"boolean",desc:"Skip rebuilding the contracts before deploying"}},Ue={command:"deploy",describe:"Deploy MUD contracts",builder(e){return e.options(S)},async handler(e){try{await y(e)}catch(o){f(o),process.exit(1)}process.exit(0)}},z=Ue;import{loadConfig as Re}from"@latticexyz/config/node";import{worldgen as Ae}from"@latticexyz/world/node";import{getSrcDirectory as Ee}from"@latticexyz/common/foundry";import T from"path";import{rmSync as We}from"fs";var $e={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 O(e),process.exit(0)}};async function O(e){let o=e.srcDir??await Ee(),t=k(o),n=e.config??await Re(e.configPath),r=T.join(o,n.codegenDirectory);e.clean&&We(T.join(r,n.worldgenDirectory),{recursive:!0,force:!0}),await Ae(n,t,r)}var F=$e;import v from"chalk";import{readFileSync as Ne,writeFileSync as _e}from"fs";import j from"path";import{MUDError as h}from"@latticexyz/common/errors";var N={name:"@latticexyz/cli",version:"2.0.0-next.11",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",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",path:"^0.12.7","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/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 Je from"glob";import{ZodError as ze,z as _}from"zod";var Te=_.object({MUD_PACKAGES:_.string().transform(e=>JSON.parse(e))});function Fe(){try{return Te.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 ze){let{_errors:o,...t}=e.format();console.error(`
5
+ - `});console.log(B.redBright(o.message))}else e instanceof Uo?(console.log(B.red(e.message)),console.log(""),console.log(B.blue("To learn more about MUD's configuration, please go to https://mud.dev/packages/cli/"))):e instanceof Vo?console.log(B.red(e)):console.log(e)}import Y from"node:path";import{existsSync as kr,mkdirSync as Ar,readFileSync as Ir,writeFileSync as te}from"node:fs";import{getAddress as _e}from"viem";import{getBytecode as Ko,sendRawTransaction as zo,sendTransaction as Jo,waitForTransactionReceipt as pe}from"viem/actions";var j={gasPrice:1e11,gasLimit:1e5,signerAddress:"3fab184622dc19b6109349b94811493bf2a45362",transaction:"f8a58085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222",address:"4e59b44847b379578588920ca78fbf26c0b4956c"};import Lo from"debug";var me=Lo("mud:cli");var d=me.extend("deploy");var v=`0x${j.address}`;async function fe(e){if(await Ko(e,{address:v})){d("found create2 deployer at",v);return}d("sending gas for create2 deployer to signer at",j.signerAddress);let t=await Jo(e,{chain:e.chain??null,to:`0x${j.signerAddress}`,value:BigInt(j.gasLimit)*BigInt(j.gasPrice)}),r=await pe(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");d("deploying create2 deployer at",v);let n=await zo(e,{serializedTransaction:`0x${j.transaction}`}),s=await pe(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 bt}from"viem/actions";import lt from"@latticexyz/world/out/CoreModule.sol/CoreModule.json"assert{type:"json"};import dt from"@latticexyz/world/out/WorldFactory.sol/WorldFactory.json"assert{type:"json"};import{parseAbi as mt,getCreate2Address as he,encodeDeployData as we}from"viem";import{padHex as Go}from"viem";import Yo from"@latticexyz/store/mud.config.js";import Zo from"@latticexyz/world/mud.config.js";import Qo from"@latticexyz/world/out/IBaseWorld.sol/IBaseWorld.abi.json"assert{type:"json"};import Xo from"@latticexyz/world-modules/out/IModule.sol/IModule.abi.json"assert{type:"json"};import{resourceToHex as qo}from"@latticexyz/common";import{resolveUserTypes as ue}from"@latticexyz/store";function H(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:qo({type:r.offchainOnly?"offchainTable":"table",namespace:e.namespace,name:r.name}),keySchema:ue(r.keySchema,o),valueSchema:ue(r.valueSchema,o)}]))}import{helloStoreEvent as et}from"@latticexyz/store";import{helloWorldEvent as ot}from"@latticexyz/world";var k=Go("0x",{size:32}),R=H(Yo),D=H(Zo),V=[et,ot],C=[...Qo,...Xo],ye=["1.0.0-unaudited"],ge=["1.0.0-unaudited"];import{waitForTransactionReceipt as ct}from"viem/actions";import{concatHex as tt,getCreate2Address as rt}from"viem";import{getBytecode as nt}from"viem/actions";import{sendTransaction as st}from"@latticexyz/common";import it from"p-retry";import{wait as at}from"@latticexyz/common/utils";async function be({client:e,bytecode:o,label:t="contract"}){let r=rt({from:v,salt:k,bytecode:o});return await nt(e,{address:r,blockTag:"pending"})?(d("found",t,"at",r),[]):(d("deploying",t,"at",r),[await it(()=>st(e,{chain:e.chain??null,to:v,data:tt([k,o])}),{retries:3,onFailedAttempt:async s=>{let l=s.attemptNumber*500;d(`failed to deploy ${t}, retrying in ${l}ms...`),await at(l)}})])}async function I({client:e,contracts:o}){let t=(await Promise.all(o.map(r=>be({client:e,...r})))).flat();if(t.length){d("waiting for contracts");for(let r of t)await ct(e,{hash:r})}return t}var _=we({bytecode:lt.bytecode.object,abi:[]}),pt=he({from:v,bytecode:_,salt:k}),L=we({bytecode:dt.bytecode.object,abi:mt(["constructor(address)"]),args:[pt]}),xe=he({from:v,bytecode:L,salt:k});async function Ce(e){return await I({client:e,contracts:[{bytecode:_,label:"core module"},{bytecode:L,label:"world factory"}]})}import ht from"@latticexyz/world/out/WorldFactory.sol/WorldFactory.abi.json"assert{type:"json"};import{writeContract as wt}from"@latticexyz/common";import{AbiEventSignatureNotFoundError as ft,decodeEventLog as ut,hexToString as Se,parseAbi as yt,trim as ve}from"viem";import{isDefined as gt}from"@latticexyz/common/utils";function K(e){let o=e.map(l=>{try{return{...l,...ut({strict:!0,abi:yt(V),topics:l.topics,data:l.data})}}catch(i){if(i instanceof ft)return;throw i}}).filter(gt),{address:t,deployBlock:r,worldVersion:n,storeVersion:s}=o.reduce((l,i)=>({...l,address:i.address,deployBlock:i.blockNumber,...i.eventName==="HelloWorld"?{worldVersion:Se(ve(i.args.worldVersion,{dir:"right"}))}:null,...i.eventName==="HelloStore"?{storeVersion:Se(ve(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 De(e){await Ce(e),d("deploying world");let o=await wt(e,{chain:e.chain??null,address:xe,abi:ht,functionName:"deployWorld"});d("waiting for world deploy");let t=await bt(e,{hash:o});if(t.status!=="success")throw console.error("world deploy failed",t),new Error("world deploy failed");let r=K(t.logs.map(n=>n));return d("deployed world to",r.address,"at block",r.deployBlock),{...r,stateBlock:r.deployBlock}}import{writeContract as kt}from"@latticexyz/common";import{valueSchemaToFieldLayoutHex as At,keySchemaToHex as It,valueSchemaToHex as Ot}from"@latticexyz/protocol-parser";function x({namespace:e,name:o}){return`${e}:${o}`}import{parseAbiItem as xt,decodeAbiParameters as Te,parseAbiParameters as ke}from"viem";import{hexToResource as Ct}from"@latticexyz/common";import{storeSetRecordEvent as St}from"@latticexyz/store";import{getLogs as vt}from"viem/actions";import{decodeKey as Dt,decodeValueArgs as Tt,hexToSchema as Ae}from"@latticexyz/protocol-parser";async function Ie({client:e,worldDeploy:o}){d("looking up tables for",o.address);let r=(await vt(e,{strict:!0,fromBlock:o.deployBlock,toBlock:o.stateBlock,address:o.address,event:xt(St),args:{tableId:R.store_Tables.tableId}})).map(n=>{let{tableId:s}=Dt(R.store_Tables.keySchema,n.args.keyTuple),{namespace:l,name:i}=Ct(s),p=Tt(R.store_Tables.valueSchema,n.args),a=Ae(p.keySchema),m=Ae(p.valueSchema),u=Te(ke("string[]"),p.abiEncodedKeyNames)[0],S=Te(ke("string[]"),p.abiEncodedFieldNames)[0],f=[...m.staticFields,...m.dynamicFields],g=Object.fromEntries(a.staticFields.map((b,c)=>[u[c],b])),h=Object.fromEntries(f.map((b,c)=>[S[c],b]));return{namespace:l,name:i,tableId:s,keySchema:g,valueSchema:h}});return d("found",r.length,"tables for",o.address),r}import Pt from"p-retry";import{wait as Mt}from"@latticexyz/common/utils";async function Oe({client:e,worldDeploy:o,tables:t}){let n=(await Ie({client:e,worldDeploy:o})).map(i=>i.tableId),s=t.filter(i=>n.includes(i.tableId));s.length&&d("existing tables",s.map(x).join(", "));let l=t.filter(i=>!n.includes(i.tableId));return l.length?(d("registering tables",l.map(x).join(", ")),await Promise.all(l.map(i=>Pt(()=>kt(e,{chain:e.chain??null,address:o.address,abi:C,functionName:"registerTable",args:[i.tableId,At(i.valueSchema),It(i.keySchema),Ot(i.valueSchema),Object.keys(i.keySchema),Object.keys(i.valueSchema)]}),{retries:3,onFailedAttempt:async p=>{let a=p.attemptNumber*500;d(`failed to register table ${x(i)}, retrying in ${a}ms...`),await Mt(a)}})))):[]}import{getAddress as A}from"viem";import{writeContract as Z}from"@latticexyz/common";import{parseAbiItem as Wt}from"viem";import{getLogs as jt}from"viem/actions";import{storeSpliceStaticDataEvent as Ft}from"@latticexyz/store";async function z({client:e,worldDeploy:o}){d("looking up resource IDs for",o.address);let r=(await jt(e,{strict:!0,address:o.address,fromBlock:o.deployBlock,toBlock:o.stateBlock,event:Wt(Ft),args:{tableId:R.store_ResourceIds.tableId}})).map(n=>n.args.keyTuple[0]);return d("found",r.length,"resource IDs for",o.address),r}import{hexToResource as Gt}from"@latticexyz/common";import{decodeValueArgs as Rt,encodeKey as Et}from"@latticexyz/protocol-parser";import{readContract as $t}from"viem/actions";async function O({client:e,worldDeploy:o,table:t,key:r}){let[n,s,l]=await $t(e,{blockNumber:o.stateBlock,address:o.address,abi:C,functionName:"getRecord",args:[t.tableId,Et(t.keySchema,r)]});return Rt(t.valueSchema,{staticData:n,encodedLengths:s,dynamicData:l})}import{getFunctionSelector as Nt,parseAbiItem as Bt}from"viem";import{storeSetRecordEvent as Ht}from"@latticexyz/store";import{getLogs as Ut}from"viem/actions";import{decodeValueArgs as Vt}from"@latticexyz/protocol-parser";import{hexToResource as _t}from"@latticexyz/common";async function J({client:e,worldDeploy:o}){d("looking up function signatures for",o.address);let r=(await Ut(e,{strict:!0,fromBlock:o.deployBlock,toBlock:o.stateBlock,address:o.address,event:Bt(Ht),args:{tableId:D.world_FunctionSignatures.tableId}})).map(s=>Vt(D.world_FunctionSignatures.valueSchema,s.args).functionSignature);return d("found",r.length,"function signatures for",o.address),await Promise.all(r.map(async s=>{let l=Nt(s),{systemId:i,systemFunctionSelector:p}=await O({client:e,worldDeploy:o,table:D.world_FunctionSelectors,key:{functionSelector:l}}),{namespace:a,name:m}=_t(i),u=a===""?s:s.replace(`${a}_${m}_`,"");return{signature:s,selector:l,systemId:i,systemFunctionSignature:u,systemFunctionSelector:p}}))}import{parseAbiItem as Lt,getAddress as Kt}from"viem";import{storeSpliceStaticDataEvent as zt}from"@latticexyz/store";import{getLogs as Jt}from"viem/actions";import{decodeKey as qt}from"@latticexyz/protocol-parser";async function q({client:e,worldDeploy:o}){d("looking up resource access for",o.address);let r=(await Jt(e,{strict:!0,fromBlock:o.deployBlock,toBlock:o.stateBlock,address:o.address,event:Lt(zt),args:{tableId:D.world_ResourceAccess.tableId}})).map(s=>qt(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:Kt(s.caller)}));return d("found",n.length,"resource<>address access pairs"),n}async function Pe({client:e,worldDeploy:o}){let[t,r,n]=await Promise.all([z({client:e,worldDeploy:o}),J({client:e,worldDeploy:o}),q({client:e,worldDeploy:o})]),s=t.map(Gt).filter(l=>l.type==="system");return d("looking up systems",s.map(x).join(", ")),await Promise.all(s.map(async l=>{let{system:i,publicAccess:p}=await O({client:e,worldDeploy:o,table:D.world_Systems,key:{systemId:l.resourceId}}),a=r.filter(m=>m.systemId===l.resourceId);return{address:i,namespace:l.namespace,name:l.name,systemId:l.resourceId,allowAll:p,allowedAddresses:n.filter(({resourceId:m})=>m===l.resourceId).map(({address:m})=>m),functions:a}}))}import{uniqueBy as Yt,wait as Q}from"@latticexyz/common/utils";import X from"p-retry";async function Me({client:e,worldDeploy:o,systems:t}){let[r,n]=await Promise.all([Pe({client:e,worldDeploy:o}),q({client:e,worldDeploy:o})]),s=t.map(c=>c.systemId),l=n.filter(({resourceId:c})=>s.includes(c)),i=t.flatMap(c=>c.allowedAddresses.map(y=>({resourceId:c.systemId,address:y}))),p=i.filter(c=>!l.some(({resourceId:y,address:w})=>y===c.resourceId&&A(w)===A(c.address))),a=l.filter(c=>!i.some(({resourceId:y,address:w})=>y===c.resourceId&&A(w)===A(c.address)));a.length&&d("revoking",a.length,"access grants"),p.length&&d("adding",p.length,"access grants");let m=[...a.map(c=>X(()=>Z(e,{chain:e.chain??null,address:o.address,abi:C,functionName:"revokeAccess",args:[c.resourceId,c.address]}),{retries:3,onFailedAttempt:async y=>{let w=y.attemptNumber*500;d(`failed to revoke access, retrying in ${w}ms...`),await Q(w)}})),...p.map(c=>X(()=>Z(e,{chain:e.chain??null,address:o.address,abi:C,functionName:"grantAccess",args:[c.resourceId,c.address]}),{retries:3,onFailedAttempt:async y=>{let w=y.attemptNumber*500;d(`failed to grant access, retrying in ${w}ms...`),await Q(w)}}))],u=t.filter(c=>r.some(y=>y.systemId===c.systemId&&A(y.address)===A(c.address)));u.length&&d("existing systems",u.map(x).join(", "));let S=u.map(c=>c.systemId),f=t.filter(c=>!S.includes(c.systemId));if(!f.length)return[];let g=f.filter(c=>r.some(y=>y.systemId===c.systemId&&A(y.address)!==A(c.address)));g.length&&d("upgrading systems",g.map(x).join(", "));let h=f.filter(c=>!r.some(y=>y.systemId===c.systemId));h.length&&d("registering new systems",h.map(x).join(", ")),await I({client:e,contracts:Yt(f,c=>A(c.address)).map(c=>({bytecode:c.bytecode,label:`${x(c)} system`}))});let b=f.map(c=>X(()=>Z(e,{chain:e.chain??null,address:o.address,abi:C,functionName:"registerSystem",args:[c.systemId,c.address,c.allowAll]}),{retries:3,onFailedAttempt:async y=>{let w=y.attemptNumber*500;d(`failed to register system ${x(c)}, retrying in ${w}ms...`),await Q(w)}}));return await Promise.all([...m,...b])}import{waitForTransactionReceipt as lr}from"viem/actions";import{getAddress as Zt,parseAbi as Qt}from"viem";import{getBlockNumber as Xt,getLogs as er}from"viem/actions";var We=new Map;async function je(e,o){let t=Zt(o),r=We.get(t);if(r!=null)return r;d("looking up world deploy for",t);let n=await Xt(e),s=await er(e,{strict:!0,address:t,events:Qt(V),fromBlock:"earliest",toBlock:n});return r={...K(s),stateBlock:n},We.set(t,r),d("found world deploy for",t,"at block",r.deployBlock),r}import{hexToResource as or,writeContract as Fe}from"@latticexyz/common";import Re from"p-retry";import{wait as Ee}from"@latticexyz/common/utils";async function $e({client:e,worldDeploy:o,functions:t}){let r=await J({client:e,worldDeploy:o}),n=Object.fromEntries(r.map(i=>[i.selector,i])),s=t.filter(i=>n[i.selector]),l=t.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 l.length?(d("registering functions:",l.map(i=>i.signature).join(", ")),Promise.all(l.map(i=>{let{namespace:p}=or(i.systemId);return p===""?Re(()=>Fe(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;d(`failed to register function ${i.signature}, retrying in ${m}ms...`),await Ee(m)}}):Re(()=>Fe(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;d(`failed to register function ${i.signature}, retrying in ${m}ms...`),await Ee(m)}})}))):[]}import{BaseError as tr,getAddress as rr}from"viem";import{writeContract as Ne}from"@latticexyz/common";import{isDefined as nr,uniqueBy as sr,wait as ir}from"@latticexyz/common/utils";import ar from"p-retry";async function Be({client:e,worldDeploy:o,modules:t}){return t.length?(await I({client:e,contracts:sr(t,r=>rr(r.address)).map(r=>({bytecode:r.bytecode,label:`${r.name} module`}))}),d("installing modules:",t.map(r=>r.name).join(", ")),(await Promise.all(t.map(r=>ar(async()=>{try{return r.installAsRoot?await Ne(e,{chain:e.chain??null,address:o.address,abi:C,functionName:"installRootModule",args:[r.address,r.installData]}):await Ne(e,{chain:e.chain??null,address:o.address,abi:C,functionName:"installModule",args:[r.address,r.installData]})}catch(n){if(n instanceof tr&&n.message.includes("Module_AlreadyInstalled")){d(`module ${r.name} already installed`);return}throw n}},{retries:3,onFailedAttempt:async n=>{let s=n.attemptNumber*500;d(`failed to install module ${r.name}, retrying in ${s}ms...`),await ir(s)}})))).filter(nr)):[]}import{getAddress as He}from"viem";import{hexToResource as Ue,resourceToHex as cr}from"@latticexyz/common";async function Ve({client:e,worldDeploy:o,resourceIds:t}){let r=Array.from(new Set(t.map(a=>Ue(a).namespace))),n=await z({client:e,worldDeploy:o}),s=Array.from(new Set(n.map(a=>Ue(a).namespace))),l=r.filter(a=>s.includes(a)),p=(await Promise.all(l.map(async a=>{let{owner:m}=await O({client:e,worldDeploy:o,table:D.world_NamespaceOwner,key:{namespaceId:cr({type:"namespace",namespace:a,name:""})}});return[a,m]}))).filter(([,a])=>He(a)!==He(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 Le}from"@latticexyz/common/utils";async function Ke({client:e,config:o,worldAddress:t}){let r=Object.values(o.tables),n=Object.values(o.systems);await fe(e),await I({client:e,contracts:[{bytecode:_,label:"core module"},{bytecode:L,label:"world factory"},...Le(n,u=>_e(u.address)).map(u=>({bytecode:u.bytecode,label:`${x(u)} system`})),...Le(o.modules,u=>_e(u.address)).map(u=>({bytecode:u.bytecode,label:`${u.name} module`}))]});let s=t?await je(e,t):await De(e);if(!ye.includes(s.storeVersion))throw new Error(`Unsupported Store version: ${s.storeVersion}`);if(!ge.includes(s.worldVersion))throw new Error(`Unsupported World version: ${s.worldVersion}`);await Ve({client:e,worldDeploy:s,resourceIds:[...r.map(u=>u.tableId),...n.map(u=>u.systemId)]});let l=await Oe({client:e,worldDeploy:s,tables:r}),i=await Me({client:e,worldDeploy:s,systems:n}),p=await $e({client:e,worldDeploy:s,functions:n.flatMap(u=>u.functions)}),a=await Be({client:e,worldDeploy:s,modules:o.modules}),m=[...l,...i,...p,...a];d("waiting for all transactions to confirm");for(let u of m)await lr(e,{hash:u});return d("deploy complete"),s}import{createWalletClient as Or,http as Pr}from"viem";import{privateKeyToAccount as Mr}from"viem/accounts";import{loadConfig as Wr}from"@latticexyz/config/node";import{forge as jr,getOutDirectory as Fr,getRemappings as Rr,getRpcUrl as Er,getSrcDirectory as $r}from"@latticexyz/common/foundry";import E from"chalk";import{execa as Nr}from"execa";import{MUDError as Br}from"@latticexyz/common/errors";import{resolveWorldConfig as ur}from"@latticexyz/world";import{resourceToHex as oe,hexToResource as yr}from"@latticexyz/common";import{resolveWithContext as gr}from"@latticexyz/config";import{encodeField as br}from"@latticexyz/protocol-parser";import{getFunctionSelector as Ye,getCreate2Address as Ze,getAddress as hr,hexToBytes as wr,bytesToHex as xr,getFunctionSignature as Qe}from"viem";import dr from"glob";import{basename as mr}from"path";function P(e){return dr.sync(`${e}/**/*.sol`).map(o=>({path:o,basename:mr(o,".sol")}))}import ze from"@latticexyz/world-modules/out/KeysWithValueModule.sol/KeysWithValueModule.json"assert{type:"json"};import Je from"@latticexyz/world-modules/out/KeysInTableModule.sol/KeysInTableModule.json"assert{type:"json"};import qe from"@latticexyz/world-modules/out/UniqueEntityModule.sol/UniqueEntityModule.json"assert{type:"json"};var Ge=[{name:"KeysWithValueModule",abi:ze.abi,bytecode:ze.bytecode},{name:"KeysInTableModule",abi:Je.abi,bytecode:Je.bytecode},{name:"UniqueEntityModule",abi:qe.abi,bytecode:qe.bytecode}];import{readFileSync as pr}from"fs";import fr from"path";import{MUDError as ee}from"@latticexyz/common/errors";function G(e,o){let t,r=fr.join(o,e+".sol",e+".json");try{t=JSON.parse(pr(r,"utf8"))}catch{throw new ee(`Error reading file at ${r}`)}let n=t?.bytecode?.object;if(!n)throw new ee(`No bytecode found in ${r}`);let s=t?.abi;if(!s)throw new ee(`No ABI found in ${r}`);return{abi:s,bytecode:n}}function Xe({config:e,forgeSourceDir:o,forgeOutDir:t}){let r=H(e),n=P(o).map(({basename:f})=>f),s=ur(e,n),i=G("System",t).abi.filter(f=>f.type==="function").map(Qe),p=Object.entries(s.systems).map(([f,g])=>{let h=e.namespace,b=g.name,c=oe({type:"system",namespace:h,name:b}),y=G(f,t),w=y.abi.filter(T=>T.type==="function").map(Qe).filter(T=>!i.includes(T)).map(T=>{let se=h===""?T:`${h}_${b}_${T}`;return{signature:se,selector:Ye(se),systemId:c,systemFunctionSignature:T,systemFunctionSelector:Ye(T)}});return{namespace:h,name:b,systemId:c,allowAll:g.openAccess,allowedAddresses:g.accessListAddresses,allowedSystemIds:g.accessListSystems.map(T=>oe({type:"system",namespace:h,name:s.systems[T].name})),address:Ze({from:v,bytecode:y.bytecode,salt:k}),bytecode:y.bytecode,abi:y.abi,functions:w}}),a=p.map(({allowedAddresses:f,allowedSystemIds:g,...h})=>{let b=g.map(c=>{let y=p.find(w=>w.systemId===c);if(!y)throw new Error(`System ${x(h)} wanted access to ${x(yr(c))}, but it wasn't found in the config.`);return y.address});return{...h,allowedAddresses:Array.from(new Set([...f,...b].map(c=>hr(c))))}}),m={tableIds:Object.fromEntries(Object.entries(e.tables).map(([f,g])=>[f,wr(oe({type:g.offchainOnly?"offchainTable":"table",namespace:e.namespace,name:g.name}))]))},u=Ge.map(f=>({name:f.name,bytecode:typeof f.bytecode=="string"?f.bytecode:f.bytecode.object,abi:f.abi})),S=e.modules.map(f=>{let g=u.find(b=>b.name===f.name)??G(f.name,t),h=f.args.map(b=>gr(b,m)).map(b=>{let c=b.value instanceof Uint8Array?xr(b.value):b.value;return br(b.type,c)});if(h.length>1)throw new Error(`${f.name} module should only have 0-1 args, but had ${h.length} args.`);return{name:f.name,installAsRoot:f.root,installData:h.length===0?"0x":h[0],address:Ze({from:v,bytecode:g.bytecode,salt:k}),bytecode:g.bytecode,abi:g.abi}});return{tables:r,systems:a,modules:S}}import{getChainId as Hr}from"viem/actions";import{existsSync as Cr}from"fs";import Sr from"path";import vr from"chalk";import{getScriptDirectory as Dr,forge as Tr}from"@latticexyz/common/foundry";async function eo(e,o,t,r){let n=Sr.join(await Dr(),e+".s.sol");Cr(n)?(console.log(vr.blue(`Executing post deploy script at ${n}`)),await Tr(["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 Ur}from"@latticexyz/store/codegen";import{worldgen as Vr}from"@latticexyz/world/node";var M={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){let o=e.profile??process.env.FOUNDRY_PROFILE,t=await Wr(e.configPath);e.printConfig&&console.log(E.green(`
6
+ Resolved config:
7
+ `),JSON.stringify(t,null,2));let r=e.srcDir??await $r(o),n=await Fr(o),s=await Rr(),l=e.rpc??await Er(o);if(console.log(E.bgBlue(E.whiteBright(`
8
+ Deploying MUD contracts${o?" with profile "+o:""} to RPC ${l}
9
+ `))),!e.skipBuild){let f=Y.join(r,t.codegenDirectory);await Promise.all([Ur(t,f,s),Vr(t,P(r),f)]),await jr(["build"],{profile:o}),await Nr("mud",["abi-ts"],{stdio:"inherit"})}let i=process.env.PRIVATE_KEY;if(!i)throw new Br(`Missing PRIVATE_KEY environment variable.
10
+ Run 'echo "PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" > .env'
11
+ in your contracts directory to use the default anvil private key.`);let p=Xe({config:t,forgeSourceDir:r,forgeOutDir:n}),a=Or({transport:Pr(l),account:Mr(i)});console.log("Deploying from",a.account.address);let m=Date.now(),u=await Ke({worldAddress:e.worldAddress,client:a,config:p});(e.worldAddress==null||e.alwaysRunPostDeploy)&&await eo(t.postDeployScript,u.address,l,o),console.log(E.green("Deployment completed in",(Date.now()-m)/1e3,"seconds"));let S={worldAddress:u.address,blockNumber:Number(u.deployBlock)};if(e.saveDeployment){let f=await Hr(a),g=Y.join(t.deploysDirectory,f.toString());Ar(g,{recursive:!0}),te(Y.join(g,"latest.json"),JSON.stringify(S,null,2)),te(Y.join(g,Date.now()+".json"),JSON.stringify(S,null,2));let h=[1337,31337],b=kr(t.worldsFile)?JSON.parse(Ir(t.worldsFile,"utf-8")):{};b[f]={address:S.worldAddress,blockNumber:h.includes(f)?void 0:S.blockNumber},te(t.worldsFile,JSON.stringify(b,null,2)),console.log(E.bgGreen(E.whiteBright(`
12
+ Deployment result (written to ${t.worldsFile} and ${g}):
13
+ `)))}return console.log(S),u}var _r={command:"deploy",describe:"Deploy MUD contracts",builder(e){return e.options(M)},async handler(e){try{await $(e)}catch(o){F(o),process.exit(1)}process.exit(0)}},oo=_r;import{loadConfig as Lr}from"@latticexyz/config/node";import{worldgen as Kr}from"@latticexyz/world/node";import{getSrcDirectory as zr}from"@latticexyz/common/foundry";import to from"path";import{rmSync as Jr}from"fs";var qr={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 Gr(e),process.exit(0)}};async function Gr(e){let o=e.srcDir??await zr(),t=P(o),r=e.config??await Lr(e.configPath),n=to.join(o,r.codegenDirectory);e.clean&&Jr(to.join(n,r.worldgenDirectory),{recursive:!0,force:!0}),await Kr(r,t,n)}var ro=qr;import U from"chalk";import{readFileSync as en,writeFileSync as on}from"fs";import ne from"path";import{MUDError as N}from"@latticexyz/common/errors";var no={name:"@latticexyz/cli",version:"2.0.0-next.12",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 tn from"glob";import{ZodError as Zr,z as so}from"zod";var Qr=so.object({MUD_PACKAGES:so.string().transform(e=>JSON.parse(e))});function Xr(){try{return Qr.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 Zr){let{_errors:o,...t}=e.format();console.error(`
6
14
  Missing or invalid environment variables:
7
15
 
8
16
  ${Object.keys(t).join(`
9
17
  `)}
10
- `),process.exit(1)}throw e}}var P=Fe().MUD_PACKAGES;var Ve={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((r,c)=>e[c]?r+1:r,0);if(t===0)throw new h(`You need to provide one these options: ${o.join(", ")}`);if(t>1)throw new h(`These options are mutually exclusive: ${o.join(", ")}`);e.mudVersion=await He(e);let n=Je.sync("**/package.json").filter(r=>!r.includes("node_modules"));for(let r of n)Le(r,e)}catch(o){f(o)}finally{process.exit(0)}}};async function He(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/${N.name}`)).json()}catch{throw new h("Could not fetch available MUD versions")}if(e.tag){let t=o["dist-tags"][e.tag];if(!t)throw new h(`Could not find npm version with tag "${e.tag}"`);return console.log(v.green(`Latest version with tag ${e.tag}: ${t}`)),t}if(e.commit){let t=e.commit.substring(0,8),n=Object.keys(o.versions).find(r=>r.includes(t));if(!n)throw new h(`Could not find npm version based on commit "${e.commit}"`);return console.log(v.green(`Version from commit ${e.commit}: ${n}`)),n}return e.mudVersion}function Le(e,o){let{link:t}=o,{mudVersion:n}=o,r=Ge(e),c=Object.keys(P),l={};for(let i in r.dependencies)c.includes(i)&&(l[i]=r.dependencies[i]);let s={};for(let i in r.devDependencies)c.includes(i)&&(s[i]=r.devDependencies[i]);for(let i in r.dependencies)c.includes(i)&&(r.dependencies[i]=p(i,"dependencies"));for(let i in r.devDependencies)c.includes(i)&&(r.devDependencies[i]=p(i,"devDependencies"));return _e(e,JSON.stringify(r,null,2)+`
11
- `),console.log(`Updating ${e}`),J(l,r.dependencies),J(s,r.devDependencies),r;function p(i,g){return t&&(n=Be(e,t,i)),n||r[g][i]}}function Ge(e){try{let o=Ne(e,"utf8");return JSON.parse(o)}catch{throw new h("Could not read JSON at "+e)}}function J(e,o){for(let t in e)e[t]!==o[t]&&console.log(`${t}: ${v.red(e[t])} -> ${v.green(o[t])}`)}function Be(e,o,t){let n=j.relative(j.dirname(e),process.cwd());return"link:"+j.join(n,o,P[t].localPath)}var V=Ve;import{anvil as qe,forge as Ke,getRpcUrl as Ze}from"@latticexyz/common/foundry";import Ye from"chalk";import{rmSync as H,writeFileSync as Qe}from"fs";var U=".mudtest",Xe={command:"test",describe:"Run tests in MUD contracts",builder(e){return e.options({...S,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"}})},async handler(e){if(!e.worldAddress){let r=["--block-base-fee-per-gas","0","--port",String(e.port)];qe(r)}let o=e.worldAddress?await Ze(e.profile):`http://127.0.0.1:${e.port}`,t=e.worldAddress??(await y({...e,saveDeployment:!1,rpc:o})).worldAddress;console.log(Ye.blue("World address",t)),Qe(U,t);let n=e.forgeOptions?.replaceAll("\\","").split(" ")??[];try{let r=await Ke(["test","--fork-url",o,...n],{profile:e.profile});console.log(r)}catch(r){console.error(r),H(U),process.exit(1)}H(U),process.exit(0)}},L=Xe;import{existsSync as eo,readFileSync as oo}from"fs";import{ethers as G}from"ethers";import{loadConfig as to}from"@latticexyz/config/node";import{MUDError as B}from"@latticexyz/common/errors";import{cast as ro,getRpcUrl as no,getSrcDirectory as io}from"@latticexyz/common/foundry";import{resolveWorldConfig as so}from"@latticexyz/world";import ao from"@latticexyz/world/out/IBaseWorld.sol/IBaseWorld.abi.json"assert{type:"json"};import q from"@latticexyz/world/mud.config.js";import{resourceIdToHex as Z}from"@latticexyz/common";var K=Z({type:"system",namespace:q.namespace,name:q.tables.Systems.name}),co={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 io(o),e.rpc??=await no(o);let{tx:t,configPath:n,srcDir:r,rpc:c}=e,l=k(r),s=await to(n),p=so(s,l.map(({basename:m})=>m)),i=e.worldAddress??await lo(s.worldsFile,c),g=new G.providers.StaticJsonRpcProvider(c),b=new G.Contract(i,ao,g),C=s.namespace,x=Object.values(p.systems).map(({name:m})=>m),d=await b.getFieldLayout(K),a=[];for(let m of x){let M=Z({type:"system",namespace:C,name:m}),se=await b.getField(K,[M],0,d);a.push({name:m,address:se})}let u=await ro(["run","--label",`${i}:World`,...a.map(({name:m,address:M})=>["--label",`${M}:${m}`]).flat(),`${t}`]);console.log(u),process.exit(0)}},Y=co;async function lo(e,o){if(eo(e)){let t=await R(o),n=JSON.parse(oo(e,"utf-8"));if(!n[t])throw new B(`chainId ${t} is missing in worldsFile "${e}"`);return n[t].address}else throw new B("worldAddress is not specified and worldsFile is missing")}import{anvil as mo,forge as X,getRemappings as fo,getRpcUrl as go,getScriptDirectory as uo,getSrcDirectory as yo}from"@latticexyz/common/foundry";import D from"chalk";import ho from"chokidar";import{loadConfig as ee,resolveConfigPath as bo}from"@latticexyz/config/node";import{tablegen as wo}from"@latticexyz/store/codegen";import oe from"path";import{debounce as vo}from"throttle-debounce";import{homedir as Do}from"os";import{rmSync as Co}from"fs";import{execa as ko}from"execa";import po from"chalk";function Q(){console.log(po.yellow(`
12
- .------..------..------.
13
- |M.--. ||U.--. ||D.--. |
14
- | (\\/) || (\\/) || :/\\: |
15
- | :\\/: || :\\/: || (__) |
16
- | '--'M|| '--'U|| '--'D|
17
- '------''------''------'
18
- `))}var xo={command:"dev-contracts",describe:"Start a development server for MUD contracts",builder(e){return e.options({rpc:{type:"string",decs:"RPC endpoint of the development node. If none is provided, an anvil instance is spawned in the background on port 8545."},configPath:{type:"string",decs:"Path to MUD config"}})},async handler(e){await X(["clean"]);let o=e.rpc??await go(),t=e.configPath??await bo(e.configPath),n=await yo(),r=await uo(),c=await fo(),l=await ee(t);if(await b(l),await C(l),!e.rpc){console.log(D.gray("Cleaning devnode cache"));let d=Do();Co(oe.join(d,".foundry","anvil","tmp"),{recursive:!0,force:!0}),mo(["--block-time","1","--block-base-fee-per-gas","0"])}let s={config:!1,contracts:!1},p={current:!1};ho.watch([t,n]).on("all",async(d,a)=>{if(a.includes(t)&&(s.config=!0,s.contracts=!0),a.includes(n)||a.includes(r)){if(a.includes(l.codegenDirectory))return;s.contracts=!0}g()});let g=vo(100,async()=>{if(p.current)return;p.current=!0;let{config:d,contracts:a}=s;s.config=!1,s.contracts=!1;try{let u=await ee(t);d&&await b(u),a&&await C(u),await x()}catch(u){console.error(D.red(`MUD dev-contracts watcher failed to deploy config or contracts changes
19
- `)),f(u)}p.current=!1,(s.config||s.contracts)&&(console.log("Detected change while handling the previous change"),g()),Q(),console.log("MUD watching for changes...")});async function b(d){console.log(D.blue("mud.config.ts changed - regenerating tables and recs types"));let a=oe.join(n,d.codegenDirectory);await wo(d,a,c)}async function C(d){console.log(D.blue("contracts changed - regenerating interfaces and contract types")),await O({config:d,clean:!0,srcDir:n}),await X(["build","--skip","test","script"]),await ko("mud",["abi-ts"],{stdio:"inherit"})}async function x(){console.log(D.blue("redeploying World")),await y({configPath:t,skipBuild:!0,priorityFeeMultiplier:1,disableTxWait:!0,pollInterval:1e3,saveDeployment:!0,srcDir:n,rpc:o})}}},te=xo;var re=[z,A,W,Mo,$,I,F,V,L,Y,te,So];import*as ie from"dotenv";import ne from"chalk";ie.config();Oo(Po(process.argv)).scriptName("mud").command(re).strict().fail((e,o)=>{console.error(ne.red(e)),e.includes("Missing required argument")&&console.log(ne.yellow(`Run 'pnpm mud ${process.argv[2]} --help' for a list of available and required arguments.`)),console.log(""),o!=null&&(f(o),console.log("")),process.exit(1)}).alias({h:"help"}).argv;
18
+ `),process.exit(1)}throw e}}var re=Xr().MUD_PACKAGES;var rn={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 N(`You need to provide one these options: ${o.join(", ")}`);if(t>1)throw new N(`These options are mutually exclusive: ${o.join(", ")}`);e.mudVersion=await nn(e);let r=tn.sync("**/package.json").filter(n=>!n.includes("node_modules"));for(let n of r)sn(n,e)}catch(o){F(o)}finally{process.exit(0)}}};async function nn(e){e.mudVersion==="canary"&&(e.tag="main");let o;try{console.log(U.blue("Fetching available versions")),o=await(await fetch(`https://registry.npmjs.org/${no.name}`)).json()}catch{throw new N("Could not fetch available MUD versions")}if(e.tag){let t=o["dist-tags"][e.tag];if(!t)throw new N(`Could not find npm version with tag "${e.tag}"`);return console.log(U.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 N(`Could not find npm version based on commit "${e.commit}"`);return console.log(U.green(`Version from commit ${e.commit}: ${r}`)),r}return e.mudVersion}function sn(e,o){let{link:t}=o,{mudVersion:r}=o,n=an(e),s=Object.keys(re),l={};for(let a in n.dependencies)s.includes(a)&&(l[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 on(e,JSON.stringify(n,null,2)+`
19
+ `),console.log(`Updating ${e}`),io(l,n.dependencies),io(i,n.devDependencies),n;function p(a,m){return t&&(r=cn(e,t,a)),r||n[m][a]}}function an(e){try{let o=en(e,"utf8");return JSON.parse(o)}catch{throw new N("Could not read JSON at "+e)}}function io(e,o){for(let t in e)e[t]!==o[t]&&console.log(`${t}: ${U.red(e[t])} -> ${U.green(o[t])}`)}function cn(e,o,t){let r=ne.relative(ne.dirname(e),process.cwd());return"link:"+ne.join(r,o,re[t].localPath)}var ao=rn;import{anvil as ln,forge as dn,getRpcUrl as mn}from"@latticexyz/common/foundry";import pn from"chalk";var fn={...M,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(fn)},async handler(e){if(!e.worldAddress){let n=["--block-base-fee-per-gas","0","--port",String(e.port)];ln(n)}let o=e.worldAddress?await mn(e.profile):`http://127.0.0.1:${e.port}`,t=e.worldAddress??(await $({...e,saveDeployment:!1,rpc:o})).address;console.log(pn.blue("World address",t));let r=e.forgeOptions?.replaceAll("\\","").split(" ")??[];try{await dn(["test","--fork-url",o,...r],{profile:e.profile,env:{WORLD_ADDRESS:t}}),process.exit(0)}catch(n){console.error(n),process.exit(1)}}},co=un;import{existsSync as yn,readFileSync as gn}from"fs";import{ethers as lo}from"ethers";import{loadConfig as bn}from"@latticexyz/config/node";import{MUDError as mo}from"@latticexyz/common/errors";import{cast as hn,getRpcUrl as wn,getSrcDirectory as xn}from"@latticexyz/common/foundry";import{resolveWorldConfig as Cn}from"@latticexyz/world";import Sn from"@latticexyz/world/out/IBaseWorld.sol/IBaseWorld.abi.json"assert{type:"json"};import po from"@latticexyz/world/mud.config.js";import{resourceToHex as uo}from"@latticexyz/common";import{createClient as vn,http as Dn}from"viem";import{getChainId as Tn}from"viem/actions";var fo=uo({type:"system",namespace:po.namespace,name:po.tables.Systems.name}),kn={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 xn(o),e.rpc??=await wn(o);let{tx:t,configPath:r,srcDir:n,rpc:s}=e,l=P(n),i=await bn(r),p=Cn(i,l.map(({basename:c})=>c)),a=e.worldAddress??await An(i.worldsFile,s),m=new lo.providers.StaticJsonRpcProvider(s),u=new lo.Contract(a,Sn,m),S=i.namespace,f=Object.values(p.systems).map(({name:c})=>c),g=await u.getFieldLayout(fo),h=[];for(let c of f){let y=uo({type:"system",namespace:S,name:c}),w=await u.getField(fo,[y],0,g);h.push({name:c,address:w})}let b=await hn(["run","--label",`${a}:World`,...h.map(({name:c,address:y})=>["--label",`${y}:${c}`]).flat(),`${t}`]);console.log(b),process.exit(0)}},yo=kn;async function An(e,o){if(yn(e)){let t=vn({transport:Dn(o)}),r=await Tn(t),n=JSON.parse(gn(e,"utf-8"));if(!n[r])throw new mo(`chainId ${r} is missing in worldsFile "${e}"`);return n[r].address}else throw new mo("worldAddress is not specified and worldsFile is missing")}import{anvil as In,getScriptDirectory as On,getSrcDirectory as Pn}from"@latticexyz/common/foundry";import W from"chalk";import Mn from"chokidar";import{loadConfig as Wn,resolveConfigPath as jn}from"@latticexyz/config/node";import Fn from"path";import{homedir as Rn}from"os";import{rmSync as En}from"fs";import{BehaviorSubject as $n,debounceTime as Nn,exhaustMap as Bn,filter as Hn}from"rxjs";import{isDefined as Un}from"@latticexyz/common/utils";var Vn={rpc:M.rpc,configPath:M.configPath,alwaysRunPostDeploy:M.alwaysRunPostDeploy},_n={command:"dev-contracts",describe:"Start a development server for MUD contracts",builder(e){return e.options(Vn)},async handler(e){let o=e.rpc,t=e.configPath??await jn(e.configPath),r=await Pn(),n=await On(),s=await Wn(t);if(!e.rpc){console.log(W.gray("Cleaning devnode cache"));let a=Rn();En(Fn.join(a,".foundry","anvil","tmp"),{recursive:!0,force:!0}),In(["--block-time","1","--block-base-fee-per-gas","0"]),o="http://127.0.0.1:8545"}let l=new $n(Date.now());Mn.watch([t,r,n],{ignoreInitial:!0}).on("all",async(a,m)=>{m.includes(t)&&(console.log(W.blue("Config changed, queuing deploy\u2026")),l.next(Date.now())),(m.includes(r)||m.includes(n))&&(m.includes(s.codegenDirectory)||(console.log(W.blue("Contracts changed, queuing deploy\u2026")),l.next(Date.now())))});let i;l.pipe(Nn(200),Bn(async a=>{i&&console.log(W.blue("Rebuilding and upgrading world\u2026"));try{let m=await $({...e,configPath:t,rpc:o,skipBuild:!1,printConfig:!1,profile:void 0,saveDeployment:!0,worldAddress:i,srcDir:r});return i=m.address,a<l.value?l.next(l.value):console.log(W.gray(`
20
+ Waiting for file changes\u2026
21
+ `)),m}catch(m){console.error(W.bgRed(W.whiteBright(`
22
+ Error while attempting deploy
23
+ `))),console.error(m),console.log(W.gray(`
24
+ Waiting for file changes\u2026
25
+ `))}}),Hn(Un)).subscribe()}},go=_n;var bo=[oo,ie,ce,Ln,le,de,ro,ao,co,yo,go,Kn];import*as wo from"dotenv";import ho from"chalk";wo.config();zn(Jn(process.argv)).scriptName("mud").command(bo).strict().fail((e,o)=>{console.error(ho.red(e)),e.includes("Missing required argument")&&console.log(ho.yellow(`Run 'pnpm mud ${process.argv[2]} --help' for a list of available and required arguments.`)),console.log(""),o!=null&&(F(o),console.log("")),process.exit(1)}).alias({h:"help"}).argv;
20
26
  //# sourceMappingURL=mud.js.map