@latticexyz/cli 2.0.10-main-0d4e302f → 2.0.10-main-0ae9189c
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-QJJWDCTW.js +38 -0
- package/dist/commands-QJJWDCTW.js.map +1 -0
- package/dist/mud.js +1 -1
- package/package.json +12 -12
- package/src/deploy/getFunctions.ts +37 -31
- package/dist/commands-TCQJMIKH.js +0 -38
- package/dist/commands-TCQJMIKH.js.map +0 -1
@@ -0,0 +1,38 @@
|
|
1
|
+
import{a as K}from"./chunk-QXUPZVZL.js";import Gs from"@latticexyz/gas-report";import Qs from"@latticexyz/abi-ts";import{loadConfig as rt}from"@latticexyz/config/node";import{getSrcDirectory as nt}from"@latticexyz/common/foundry";import Go from"node:path";import{tablegen as Qo}from"@latticexyz/store/codegen";import{worldgen as Zo}from"@latticexyz/world/node";import{worldToV1 as Xo}from"@latticexyz/world/config/v2";import{forge as et,getRemappings as ot}from"@latticexyz/common/foundry";import qo from"glob";import{basename as Yo}from"path";function k(e){return qo.sync(`${e}/**/*.sol`).map(o=>({path:o,basename:Yo(o,".sol")}))}import{execa as tt}from"execa";async function J({config:e,srcDir:o,foundryProfile:n=process.env.FOUNDRY_PROFILE}){let r=Xo(e),t=Go.join(o,r.codegenDirectory),a=await ot(n);await Promise.all([Qo(e,t,a),Zo(e,k(o),t)]),await et(["build"],{profile:n}),await tt("mud",["abi-ts"],{stdio:"inherit"})}var st={command:"build",describe:"Build contracts and generate MUD artifacts (table libraries, world interface, ABI)",builder(e){return e.options({configPath:{type:"string",desc:"Path to the MUD config file"},profile:{type:"string",desc:"The foundry profile to use"}})},async handler({configPath:e,profile:o}){let n=await rt(e),r=await nt();await J({config:n,srcDir:r,foundryProfile:o}),process.exit(0)}},Ie=st;import{rmSync as at}from"fs";import{homedir as it}from"os";import dt from"path";import{execa as ct}from"execa";var lt={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=it();at(dt.join(o,".foundry","anvil","tmp"),{recursive:!0,force:!0});let n=["-b",String(e),"--block-base-fee-per-gas","0"];console.log(`Running: anvil ${n.join(" ")}`);let r=ct("anvil",n,{stdio:["inherit","inherit","inherit"]});process.on("SIGINT",()=>{console.log(`
|
2
|
+
gracefully shutting down from SIGINT (Crtl-C)`),r.kill(),process.exit()}),await r}},Pe=lt;import{FaucetServiceDefinition as mt}from"@latticexyz/services/faucet";import{createChannel as pt,createClient as ft}from"nice-grpc-web";import Oe from"chalk";import{NodeHttpTransport as yt}from"@improbable-eng/grpc-web-node-http-transport";function ut(e){return ft(mt,pt(e,yt()))}var gt={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:n}){let r=ut(o);e&&(console.log(Oe.yellow("Dripping to",n)),await r.dripDev({address:n}),console.log(Oe.yellow("Success"))),process.exit(0)}},Be=gt;var bt={command:"hello <name>",describe:"Greet <name> with Hello",builder(e){return e.options({upper:{type:"boolean"}}).positional("name",{type:"string",demandOption:!0})},handler({name:e}){let o=`Gm, ${e}!`;console.log(o),process.exit(0)}},We=bt;import ht from"path";import{loadConfig as wt}from"@latticexyz/config/node";import{tablegen as xt}from"@latticexyz/store/codegen";import{getRemappings as St,getSrcDirectory as Ct}from"@latticexyz/common/foundry";var Dt={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 MUD config file"}})},async handler({configPath:e}){let o=await wt(e),n=await Ct(),r=await St();await xt(o,ht.join(n,o.codegen.outputDirectory),r),process.exit(0)}},Me=Dt;import xe from"node:path";import{existsSync as hn,mkdirSync as wn,readFileSync as xn,writeFileSync as Se}from"node:fs";import{getBalance as Pt,sendRawTransaction as Ot,sendTransaction as Re,waitForTransactionReceipt as He}from"viem/actions";var A={gasPrice:1e11,gasLimit:1e5,signerAddress:"3fab184622dc19b6109349b94811493bf2a45362",transaction:"f8a58085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222",address:"4e59b44847b379578588920ca78fbf26c0b4956c",creationCode:"604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3"};import je from"debug";var q=je("mud:cli"),Tt=je("mud:cli");q.log=console.debug.bind(console);Tt.log=console.error.bind(console);var l=q.extend("deploy"),At=q.extend("deploy");l.log=console.debug.bind(console);At.log=console.error.bind(console);import{sliceHex as kt}from"viem";import{getBytecode as It}from"viem/actions";var Y=`0x${A.address}`;async function G(e){let o=await It(e,{address:Y});if(o)return l("found CREATE2 deployer at",Y),o!==kt(`0x${A.creationCode}`,14)&&console.warn(`
|
3
|
+
\u26A0\uFE0F Bytecode for deployer at ${Y} did not match the expected CREATE2 bytecode. You may have unexpected results.
|
4
|
+
`),Y}var ye=`0x${A.address}`;async function Fe(e){let o=await G(e);if(o!==void 0)return o;let n=BigInt(A.gasLimit)*BigInt(A.gasPrice),r=await Pt(e,{address:`0x${A.signerAddress}`}),t=n-r;if(t>0){l("sending gas for CREATE2 deployer to signer at",A.signerAddress);let s=await Re(e,{chain:e.chain??null,to:`0x${A.signerAddress}`,value:t}),d=await He(e,{hash:s});if(d.status!=="success")throw console.error("failed to send gas to deployer signer",d),new Error("failed to send gas to deployer signer")}l("deploying CREATE2 deployer at",ye);let a=await Ot(e,{serializedTransaction:`0x${A.transaction}`}).catch(s=>{if(String(s).includes("only replay-protected (EIP-155) transactions allowed over RPC"))return console.warn(`
|
5
|
+
\u26A0\uFE0F Your chain or RPC does not allow for non EIP-155 signed transactions, so your deploys will not be determinstic and contract addresses may change between deploys.
|
6
|
+
|
7
|
+
We recommend running your chain's node with \`--rpc.allow-unprotected-txs\` to enable determinstic deployments.
|
8
|
+
`),l("deploying CREATE2 deployer"),Re(e,{chain:e.chain??null,data:`0x${A.creationCode}`});throw s}),i=await He(e,{hash:a});if(!i.contractAddress)throw new Error("Deploy receipt did not have contract address, was the deployer not deployed?");return i.contractAddress!==ye&&console.warn(`
|
9
|
+
\u26A0\uFE0F CREATE2 deployer created at ${i.contractAddress} does not match the CREATE2 determinstic deployer we expected (${ye})`),i.contractAddress}import{waitForTransactionReceipt as cr}from"viem/actions";import{waitForTransactionReceipt as Jt}from"viem/actions";import{concatHex as Nt,getCreate2Address as Lt}from"viem";import{getBytecode as Ut}from"viem/actions";import{padHex as Wt}from"viem";import Mt from"@latticexyz/store/mud.config";import jt from"@latticexyz/world/mud.config";import Rt from"@latticexyz/world/out/IBaseWorld.sol/IBaseWorld.abi.json"assert{type:"json"};import Ht from"@latticexyz/world-modules/out/IModule.sol/IModule.abi.json"assert{type:"json"};import{resourceToHex as Bt}from"@latticexyz/common";import{resolveUserTypes as Ee}from"@latticexyz/store/internal";function z(e){let o={...e.userTypes,...Object.fromEntries(Object.entries(e.enums).map(([n])=>[n,{internalType:"uint8"}]))};return Object.fromEntries(Object.entries(e.tables).map(([n,r])=>[`${e.namespace}_${n}`,{namespace:e.namespace,name:r.name,tableId:Bt({type:r.offchainOnly?"offchainTable":"table",namespace:e.namespace,name:r.name}),keySchema:Ee(r.keySchema,o),valueSchema:Ee(r.valueSchema,o)}]))}import{helloStoreEvent as Ft}from"@latticexyz/store";import{helloWorldEvent as Et}from"@latticexyz/world";import{storeToV1 as $t}from"@latticexyz/store/config/v2";import{worldToV1 as zt}from"@latticexyz/world/config/v2";var C=Wt("0x",{size:32}),N=parseInt("6000",16),R=z($t(Mt)),T=z(zt(jt)),Q=[Ft,Et],D=[...Rt,...Ht],$e=["2.0.0","2.0.1","2.0.2"],ze=["2.0.0","2.0.1","2.0.2"];import{sendTransaction as Vt}from"@latticexyz/common";import _t from"p-retry";import{wait as Kt}from"@latticexyz/common/utils";async function Ne({client:e,deployerAddress:o,bytecode:n,deployedBytecodeSize:r,label:t="contract"}){if(n.includes("__$"))throw new Error(`Found unlinked public library in ${t} bytecode`);let a=Lt({from:o,salt:C,bytecode:n});return await Ut(e,{address:a,blockTag:"pending"})?(l("found",t,"at",a),[]):(r>N?console.warn(`
|
10
|
+
Bytecode for ${t} (${r} bytes) is over the contract size limit (${N} bytes). Run \`forge build --sizes\` for more info.
|
11
|
+
`):r>N*.95&&console.warn(`
|
12
|
+
Bytecode for ${t} (${r} bytes) is almost over the contract size limit (${N} bytes). Run \`forge build --sizes\` for more info.
|
13
|
+
`),l("deploying",t,"at",a),[await _t(()=>Vt(e,{chain:e.chain??null,to:o,data:Nt([C,n])}),{retries:3,onFailedAttempt:async s=>{let d=s.attemptNumber*500;l(`failed to deploy ${t}, retrying in ${d}ms...`),await Kt(d)}})])}import{uniqueBy as qt}from"@latticexyz/common/utils";async function P({client:e,deployerAddress:o,contracts:n}){let r=qt(n,a=>a.bytecode),t=(await Promise.all(r.map(a=>Ne({client:e,deployerAddress:o,...a})))).flat();if(t.length){l("waiting for contracts");for(let a of t)await Jt(e,{hash:a})}return t}import Je from"@latticexyz/world/out/WorldFactory.sol/WorldFactory.json"assert{type:"json"};import Qt from"@latticexyz/world/out/WorldFactory.sol/WorldFactory.abi.json"assert{type:"json"};import{getCreate2Address as Zt,encodeDeployData as Xt,size as er}from"viem";import Le from"@latticexyz/world/out/AccessManagementSystem.sol/AccessManagementSystem.json"assert{type:"json"};import Ue from"@latticexyz/world/out/BalanceTransferSystem.sol/BalanceTransferSystem.json"assert{type:"json"};import Ve from"@latticexyz/world/out/BatchCallSystem.sol/BatchCallSystem.json"assert{type:"json"};import _e from"@latticexyz/world/out/RegistrationSystem.sol/RegistrationSystem.json"assert{type:"json"};import Ke from"@latticexyz/world/out/InitModule.sol/InitModule.json"assert{type:"json"};import Yt from"@latticexyz/world/out/InitModule.sol/InitModule.abi.json"assert{type:"json"};import{getCreate2Address as L,encodeDeployData as Gt,size as U}from"viem";function Z(e){let o=U(Le.deployedBytecode.object),n=Le.bytecode.object,r=L({from:e,bytecode:n,salt:C}),t=U(Ue.deployedBytecode.object),a=Ue.bytecode.object,i=L({from:e,bytecode:a,salt:C}),s=U(Ve.deployedBytecode.object),d=Ve.bytecode.object,c=L({from:e,bytecode:d,salt:C}),y=U(_e.deployedBytecode.object),u=_e.bytecode.object,g=L({from:e,bytecode:u,salt:C}),b=U(Ke.deployedBytecode.object),m=Gt({bytecode:Ke.bytecode.object,abi:Yt,args:[r,i,c,g]}),p=L({from:e,bytecode:m,salt:C});return{AccessManagementSystem:{bytecode:n,deployedBytecodeSize:o,label:"access management system",address:r},BalanceTransferSystem:{bytecode:a,deployedBytecodeSize:t,label:"balance transfer system",address:i},BatchCallSystem:{bytecode:d,deployedBytecodeSize:s,label:"batch call system",address:c},RegistrationSystem:{bytecode:u,deployedBytecodeSize:y,label:"core registration system",address:g},InitModule:{bytecode:m,deployedBytecodeSize:b,label:"core module",address:p}}}function X(e){let o=Z(e),n=er(Je.deployedBytecode.object),r=Xt({bytecode:Je.bytecode.object,abi:Qt,args:[o.InitModule.address]}),t=Zt({from:e,bytecode:r,salt:C});return{...o,WorldFactory:{bytecode:r,deployedBytecodeSize:n,label:"world factory",address:t}}}import qe from"@latticexyz/world/out/WorldProxyFactory.sol/WorldProxyFactory.json"assert{type:"json"};import or from"@latticexyz/world/out/WorldProxyFactory.sol/WorldProxyFactory.abi.json"assert{type:"json"};import{getCreate2Address as tr,encodeDeployData as rr,size as nr}from"viem";function ee(e){let o=Z(e),n=nr(qe.deployedBytecode.object),r=rr({bytecode:qe.bytecode.object,abi:or,args:[o.InitModule.address]}),t=tr({from:e,bytecode:r,salt:C});return{...o,WorldProxyFactory:{bytecode:r,deployedBytecodeSize:n,label:"world proxy factory",address:t}}}async function oe(e,o,n){if(n){let t=ee(o);return await P({client:e,deployerAddress:o,contracts:Object.values(t)}),t.WorldProxyFactory.address}let r=X(o);return await P({client:e,deployerAddress:o,contracts:Object.values(r)}),r.WorldFactory.address}import lr from"@latticexyz/world/out/WorldFactory.sol/WorldFactory.abi.json"assert{type:"json"};import{writeContract as mr}from"@latticexyz/common";import{AbiEventSignatureNotFoundError as sr,decodeEventLog as ar,hexToString as Ye,parseAbi as ir}from"viem";import{isDefined as dr}from"@latticexyz/common/utils";function te(e){let o=e.map(i=>{try{return{...i,...ar({strict:!0,abi:ir(Q),topics:i.topics,data:i.data})}}catch(s){if(s instanceof sr)return;throw s}}).filter(dr),{address:n,deployBlock:r,worldVersion:t,storeVersion:a}=o.reduce((i,s)=>({...i,address:s.address,deployBlock:s.blockNumber,...s.eventName==="HelloWorld"?{worldVersion:Ye(s.args.worldVersion).replace(/\0+$/,"")}:null,...s.eventName==="HelloStore"?{storeVersion:Ye(s.args.storeVersion).replace(/\0+$/,"")}:null}),{});if(n==null)throw new Error("could not find world address");if(r==null)throw new Error("could not find world deploy block number");if(t==null)throw new Error("could not find world version");if(a==null)throw new Error("could not find store version");return{address:n,deployBlock:r,worldVersion:t,storeVersion:a}}async function Ge(e,o,n,r){let t=await oe(e,o,r);l("deploying world");let a=await mr(e,{chain:e.chain??null,address:t,abi:lr,functionName:"deployWorld",args:[n]});l("waiting for world deploy");let i=await cr(e,{hash:a});if(i.status!=="success")throw console.error("world deploy failed",i),new Error("world deploy failed");let s=te(i.logs);return l("deployed world to",s.address,"at block",s.deployBlock),{...s,stateBlock:s.deployBlock}}import{resourceToLabel as ue,writeContract as hr}from"@latticexyz/common";import{valueSchemaToFieldLayoutHex as wr,keySchemaToHex as xr,valueSchemaToHex as Sr}from"@latticexyz/protocol-parser/internal";import{parseAbiItem as pr,decodeAbiParameters as Qe,parseAbiParameters as Ze}from"viem";import{hexToResource as fr}from"@latticexyz/common";import{storeSetRecordEvent as yr}from"@latticexyz/store";import{getLogs as ur}from"viem/actions";import{decodeKey as gr,decodeValueArgs as br,hexToSchema as Xe}from"@latticexyz/protocol-parser/internal";async function eo({client:e,worldDeploy:o}){l("looking up tables for",o.address);let r=(await ur(e,{strict:!0,fromBlock:o.deployBlock,toBlock:o.stateBlock,address:o.address,event:pr(yr),args:{tableId:R.store_Tables.tableId}})).map(t=>{let{tableId:a}=gr(R.store_Tables.keySchema,t.args.keyTuple),{namespace:i,name:s}=fr(a),d=br(R.store_Tables.valueSchema,t.args),c=Xe(d.keySchema),y=Xe(d.valueSchema),u=Qe(Ze("string[]"),d.abiEncodedKeyNames)[0],g=Qe(Ze("string[]"),d.abiEncodedFieldNames)[0],b=[...y.staticFields,...y.dynamicFields],m=Object.fromEntries(c.staticFields.map((S,x)=>[u[x],S])),p=Object.fromEntries(b.map((S,x)=>[g[x],S]));return{namespace:i,name:s,tableId:a,keySchema:m,valueSchema:p}});return l("found",r.length,"tables for",o.address),r}import Cr from"p-retry";import{wait as Dr}from"@latticexyz/common/utils";async function oo({client:e,worldDeploy:o,tables:n}){let t=(await eo({client:e,worldDeploy:o})).map(s=>s.tableId),a=n.filter(s=>t.includes(s.tableId));a.length&&l("existing tables",a.map(ue).join(", "));let i=n.filter(s=>!t.includes(s.tableId));return i.length?(l("registering tables",i.map(ue).join(", ")),await Promise.all(i.map(s=>Cr(()=>hr(e,{chain:e.chain??null,address:o.address,abi:D,functionName:"registerTable",args:[s.tableId,wr(s.valueSchema),xr(s.keySchema),Sr(s.valueSchema),Object.keys(s.keySchema),Object.keys(s.valueSchema)]}),{retries:3,onFailedAttempt:async d=>{let c=d.attemptNumber*500;l(`failed to register table ${ue(s)}, retrying in ${c}ms...`),await Dr(c)}})))):[]}import{getAddress as O}from"viem";import{writeContract as ge,resourceToLabel as V}from"@latticexyz/common";import{parseAbiItem as vr,HttpRequestError as Tr}from"viem";import{getLogs as Ar}from"viem/actions";import{storeSpliceStaticDataEvent as kr}from"@latticexyz/store";import Ir from"p-retry";async function re({client:e,worldDeploy:o}){l("looking up resource IDs for",o.address);let r=(await Ir(()=>Ar(e,{strict:!0,address:o.address,fromBlock:o.deployBlock,toBlock:o.stateBlock,event:vr(kr),args:{tableId:R.store_ResourceIds.tableId}}),{retries:3,onFailedAttempt:async t=>{if(!(t instanceof Tr&&t.status===400&&t.message.includes("block is out of range")))throw t}})).map(t=>t.args.keyTuple[0]);return l("found",r.length,"resource IDs for",o.address),r}import{hexToResource as Fr,resourceToLabel as Er}from"@latticexyz/common";import{decodeValueArgs as Pr,encodeKey as Or}from"@latticexyz/protocol-parser/internal";import{readContract as Br}from"viem/actions";async function H({client:e,worldDeploy:o,table:n,key:r}){let[t,a,i]=await Br(e,{blockNumber:o.stateBlock,address:o.address,abi:D,functionName:"getRecord",args:[n.tableId,Or(n.keySchema,r)]});return Pr(n.valueSchema,{staticData:t,encodedLengths:a,dynamicData:i})}import{parseAbiItem as to}from"viem";import{storeSetRecordEvent as ro}from"@latticexyz/store";import{getLogs as no}from"viem/actions";import{decodeKey as so,decodeValueArgs as ao}from"@latticexyz/protocol-parser/internal";async function ne({client:e,worldDeploy:o}){l("looking up function selectors for",o.address);let r=(await no(e,{strict:!0,fromBlock:o.deployBlock,toBlock:o.stateBlock,address:o.address,event:to(ro),args:{tableId:T.world_FunctionSelectors.tableId}})).map(s=>({...ao(T.world_FunctionSelectors.valueSchema,s.args),...so(T.world_FunctionSelectors.keySchema,s.args.keyTuple)}));l("found",r.length,"function selectors for",o.address),l("looking up function signatures for",o.address);let t=await no(e,{strict:!0,fromBlock:o.deployBlock,toBlock:o.stateBlock,address:o.address,event:to(ro),args:{tableId:T.world_FunctionSignatures.tableId}}),a=Object.fromEntries(t.map(s=>[so(T.world_FunctionSignatures.keySchema,s.args.keyTuple).functionSelector,ao(T.world_FunctionSignatures.valueSchema,s.args).functionSignature]));return l("found",t.length,"function signatures for",o.address),r.map(({worldFunctionSelector:s,systemFunctionSelector:d,systemId:c})=>({selector:s,signature:a[s],systemFunctionSelector:d,systemFunctionSignature:a[d],systemId:c}))}import{parseAbiItem as Wr,getAddress as Mr}from"viem";import{storeSpliceStaticDataEvent as jr}from"@latticexyz/store";import{getLogs as Rr}from"viem/actions";import{decodeKey as Hr}from"@latticexyz/protocol-parser/internal";async function se({client:e,worldDeploy:o}){l("looking up resource access for",o.address);let r=(await Rr(e,{strict:!0,fromBlock:o.deployBlock,toBlock:o.stateBlock,address:o.address,event:Wr(jr),args:{tableId:T.world_ResourceAccess.tableId}})).map(a=>Hr(T.world_ResourceAccess.keySchema,a.args.keyTuple)),t=(await Promise.all(r.map(async a=>[a,await H({client:e,worldDeploy:o,table:T.world_ResourceAccess,key:a})]))).filter(([,a])=>a.access).map(([a])=>({resourceId:a.resourceId,address:Mr(a.caller)}));return l("found",t.length,"resource<>address access pairs"),t}async function io({client:e,worldDeploy:o}){let[n,r,t]=await Promise.all([re({client:e,worldDeploy:o}),ne({client:e,worldDeploy:o}),se({client:e,worldDeploy:o})]),a=n.map(Fr).filter(i=>i.type==="system");return l("looking up systems",a.map(Er).join(", ")),await Promise.all(a.map(async i=>{let{system:s,publicAccess:d}=await H({client:e,worldDeploy:o,table:T.world_Systems,key:{systemId:i.resourceId}}),c=r.filter(y=>y.systemId===i.resourceId);return{address:s,namespace:i.namespace,name:i.name,systemId:i.resourceId,allowAll:d,allowedAddresses:t.filter(({resourceId:y})=>y===i.resourceId).map(({address:y})=>y),functions:c}}))}import{wait as be}from"@latticexyz/common/utils";import he from"p-retry";async function co({client:e,deployerAddress:o,libraries:n,worldDeploy:r,systems:t}){let[a,i]=await Promise.all([io({client:e,worldDeploy:r}),se({client:e,worldDeploy:r})]),s=t.filter(f=>a.some(h=>h.systemId===f.systemId&&O(h.address)===O(f.prepareDeploy(o,n).address)));s.length&&l("existing systems",s.map(V).join(", "));let d=s.map(f=>f.systemId),c=t.filter(f=>!d.includes(f.systemId));if(!c.length)return[];let y=c.filter(f=>a.some(h=>h.systemId===f.systemId&&O(h.address)!==O(f.prepareDeploy(o,n).address)));y.length&&l("upgrading systems",y.map(V).join(", "));let u=c.filter(f=>!a.some(h=>h.systemId===f.systemId));u.length&&l("registering new systems",u.map(V).join(", ")),await P({client:e,deployerAddress:o,contracts:c.map(f=>({bytecode:f.prepareDeploy(o,n).bytecode,deployedBytecodeSize:f.deployedBytecodeSize,label:`${V(f)} system`}))});let g=await Promise.all(c.map(f=>he(()=>ge(e,{chain:e.chain??null,address:r.address,abi:D,functionName:"registerSystem",args:[f.systemId,f.prepareDeploy(o,n).address,f.allowAll]}),{retries:3,onFailedAttempt:async h=>{let w=h.attemptNumber*500;l(`failed to register system ${V(f)}, retrying in ${w}ms...`),await be(w)}}))),b=t.map(f=>f.systemId),m=i.filter(({resourceId:f})=>b.includes(f)),p=[...t.flatMap(f=>f.allowedAddresses.map(h=>({resourceId:f.systemId,address:h}))),...t.flatMap(f=>f.allowedSystemIds.map(h=>({resourceId:f.systemId,address:a.find(w=>w.systemId===h)?.address??t.find(w=>w.systemId===h)?.prepareDeploy(o,n).address})).filter(h=>h.address!=null))],S=p.filter(f=>!m.some(({resourceId:h,address:w})=>h===f.resourceId&&O(w)===O(f.address))),x=m.filter(f=>!p.some(({resourceId:h,address:w})=>h===f.resourceId&&O(w)===O(f.address)));x.length&&l("revoking",x.length,"access grants"),S.length&&l("adding",S.length,"access grants");let v=await Promise.all([...x.map(f=>he(()=>ge(e,{chain:e.chain??null,address:r.address,abi:D,functionName:"revokeAccess",args:[f.resourceId,f.address]}),{retries:3,onFailedAttempt:async h=>{let w=h.attemptNumber*500;l(`failed to revoke access, retrying in ${w}ms...`),await be(w)}})),...S.map(f=>he(()=>ge(e,{chain:e.chain??null,address:r.address,abi:D,functionName:"grantAccess",args:[f.resourceId,f.address]}),{retries:3,onFailedAttempt:async h=>{let w=h.attemptNumber*500;l(`failed to grant access, retrying in ${w}ms...`),await be(w)}}))]);return[...g,...v]}import{waitForTransactionReceipt as Co}from"viem/actions";import{getAddress as $r,parseAbi as zr}from"viem";import{getBlockNumber as Nr,getLogs as Lr}from"viem/actions";var lo=new Map;async function mo(e,o){let n=$r(o),r=lo.get(n);if(r!=null)return r;l("looking up world deploy for",n);let t=await Nr(e),a=await Lr(e,{strict:!0,address:n,events:zr(Q),fromBlock:"earliest",toBlock:t});return r={...te(a),stateBlock:t},lo.set(n,r),l("found world deploy for",n,"at block",r.deployBlock),r}import{hexToResource as Ur,writeContract as po}from"@latticexyz/common";import fo from"p-retry";import{wait as yo}from"@latticexyz/common/utils";async function uo({client:e,worldDeploy:o,functions:n}){let r=await ne({client:e,worldDeploy:o}),t=Object.fromEntries(r.map(s=>[s.selector,s])),a=n.filter(s=>t[s.selector]),i=n.filter(s=>!a.includes(s));if(a.length){l("functions already registered:",a.map(d=>d.signature).join(", "));let s=a.filter(d=>d.systemId!==t[d.selector]?.systemId);s.length&&console.warn("found",s.length,"functions already registered but pointing at a different system ID:",s.map(d=>d.signature).join(", "))}return i.length?(l("registering functions:",i.map(s=>s.signature).join(", ")),Promise.all(i.map(s=>{let{namespace:d}=Ur(s.systemId);return d===""?fo(()=>po(e,{chain:e.chain??null,address:o.address,abi:D,functionName:"registerRootFunctionSelector",args:[s.systemId,s.systemFunctionSignature,s.systemFunctionSignature]}),{retries:3,onFailedAttempt:async c=>{let y=c.attemptNumber*500;l(`failed to register function ${s.signature}, retrying in ${y}ms...`),await yo(y)}}):fo(()=>po(e,{chain:e.chain??null,address:o.address,abi:D,functionName:"registerFunctionSelector",args:[s.systemId,s.systemFunctionSignature]}),{retries:3,onFailedAttempt:async c=>{let y=c.attemptNumber*500;l(`failed to register function ${s.signature}, retrying in ${y}ms...`),await yo(y)}})}))):[]}import{BaseError as Vr}from"viem";import{writeContract as go}from"@latticexyz/common";import{isDefined as _r,wait as Kr}from"@latticexyz/common/utils";import Jr from"p-retry";async function bo({client:e,deployerAddress:o,libraries:n,worldDeploy:r,modules:t}){return t.length?(await P({client:e,deployerAddress:o,contracts:t.map(a=>({bytecode:a.prepareDeploy(o,n).bytecode,deployedBytecodeSize:a.deployedBytecodeSize,label:`${a.name} module`}))}),l("installing modules:",t.map(a=>a.name).join(", ")),(await Promise.all(t.map(a=>Jr(async()=>{try{let i=a.prepareDeploy(o,n).address;return a.installAsRoot?await go(e,{chain:e.chain??null,address:r.address,abi:D,functionName:"installRootModule",args:[i,a.installData]}):await go(e,{chain:e.chain??null,address:r.address,abi:D,functionName:"installModule",args:[i,a.installData]})}catch(i){if(i instanceof Vr&&i.message.includes("Module_AlreadyInstalled")){l(`module ${a.name} already installed`);return}throw i}},{retries:3,onFailedAttempt:async i=>{let s=i.attemptNumber*500;l(`failed to install module ${a.name}, retrying in ${s}ms...`),await Kr(s)}})))).filter(_r)):[]}import{getAddress as ho}from"viem";import{hexToResource as wo,resourceToHex as xo,writeContract as qr}from"@latticexyz/common";async function So({client:e,worldDeploy:o,resourceIds:n}){let r=Array.from(new Set(n.map(u=>wo(u).namespace))),t=await re({client:e,worldDeploy:o}),a=new Set(t.map(u=>wo(u).namespace));a.size&&l("found",a.size,"existing namespaces:",Array.from(a).map(u=>u===""?"<root>":u).join(", "));let i=r.filter(u=>a.has(u)),d=(await Promise.all(i.map(async u=>{let{owner:g}=await H({client:e,worldDeploy:o,table:T.world_NamespaceOwner,key:{namespaceId:xo({type:"namespace",namespace:u,name:""})}});return[u,g]}))).filter(([,u])=>ho(u)!==ho(e.account.address)).map(([u])=>u);if(d.length)throw new Error(`You are attempting to deploy to namespaces you do not own: ${d.join(", ")}`);let c=r.filter(u=>!a.has(u));return c.length>0&&l("registering namespaces",Array.from(c).join(", ")),Promise.all(c.map(u=>qr(e,{chain:e.chain??null,address:o.address,abi:D,functionName:"registerNamespace",args:[xo({namespace:u,type:"namespace",name:""})]})))}import{resourceToLabel as Yr}from"@latticexyz/common";import{randomBytes as Gr}from"crypto";async function Do({client:e,config:o,salt:n,worldAddress:r,deployerAddress:t,withWorldProxy:a}){let i=Object.values(o.tables),s=t??await Fe(e);await oe(e,s,a),await P({client:e,deployerAddress:s,contracts:[...o.libraries.map(p=>({bytecode:p.prepareDeploy(s,o.libraries).bytecode,deployedBytecodeSize:p.deployedBytecodeSize,label:`${p.path}:${p.name} library`})),...o.systems.map(p=>({bytecode:p.prepareDeploy(s,o.libraries).bytecode,deployedBytecodeSize:p.deployedBytecodeSize,label:`${Yr(p)} system`})),...o.modules.map(p=>({bytecode:p.prepareDeploy(s,o.libraries).bytecode,deployedBytecodeSize:p.deployedBytecodeSize,label:`${p.name} module`}))]});let d=r?await mo(e,r):await Ge(e,s,n??`0x${Gr(32).toString("hex")}`,a);if(!$e.includes(d.storeVersion))throw new Error(`Unsupported Store version: ${d.storeVersion}`);if(!ze.includes(d.worldVersion))throw new Error(`Unsupported World version: ${d.worldVersion}`);let c=await So({client:e,worldDeploy:d,resourceIds:[...i.map(p=>p.tableId),...o.systems.map(p=>p.systemId)]});l("waiting for all namespace registration transactions to confirm");for(let p of c)await Co(e,{hash:p});let y=await oo({client:e,worldDeploy:d,tables:i}),u=await co({client:e,deployerAddress:s,libraries:o.libraries,worldDeploy:d,systems:o.systems}),g=await uo({client:e,worldDeploy:d,functions:o.systems.flatMap(p=>p.functions)}),b=await bo({client:e,deployerAddress:s,libraries:o.libraries,worldDeploy:d,modules:o.modules}),m=[...y,...u,...g,...b];l("waiting for all transactions to confirm");for(let p of m)await Co(e,{hash:p});return l("deploy complete"),d}import{createWalletClient as Sn,http as Cn,isHex as Dn}from"viem";import{privateKeyToAccount as vn}from"viem/accounts";import{loadConfig as Tn}from"@latticexyz/config/node";import{worldToV1 as An}from"@latticexyz/world/config/v2";import{getOutDirectory as kn,getRpcUrl as In,getSrcDirectory as Pn}from"@latticexyz/common/foundry";import F from"chalk";import{MUDError as Ce}from"@latticexyz/common/errors";import sn from"path";import{resolveWorldConfig as an}from"@latticexyz/world/internal";import{resourceToHex as we}from"@latticexyz/common";import{resolveWithContext as dn}from"@latticexyz/config/library";import{encodeField as cn}from"@latticexyz/protocol-parser/internal";import{hexToBytes as ln,bytesToHex as mn,toFunctionSelector as Ao,toFunctionSignature as ko}from"viem";import ae from"@latticexyz/world-modules/out/KeysWithValueModule.sol/KeysWithValueModule.json"assert{type:"json"};import ie from"@latticexyz/world-modules/out/KeysInTableModule.sol/KeysInTableModule.json"assert{type:"json"};import de from"@latticexyz/world-modules/out/UniqueEntityModule.sol/UniqueEntityModule.json"assert{type:"json"};import ce from"@latticexyz/world-modules/out/Unstable_CallWithSignatureModule.sol/Unstable_CallWithSignatureModule.json"assert{type:"json"};import{size as le}from"viem";function M(e){return Object.entries(e).flatMap(([o,n])=>Object.entries(n).flatMap(([r,t])=>t.map(a=>({path:o,name:r,start:a.start,length:a.length}))))}var me=[{name:"KeysWithValueModule",abi:ae.abi,bytecode:ae.bytecode.object,placeholders:M(ae.bytecode.linkReferences),deployedBytecodeSize:le(ae.deployedBytecode.object)},{name:"KeysInTableModule",abi:ie.abi,bytecode:ie.bytecode.object,placeholders:M(ie.bytecode.linkReferences),deployedBytecodeSize:le(ie.deployedBytecode.object)},{name:"UniqueEntityModule",abi:de.abi,bytecode:de.bytecode.object,placeholders:M(de.bytecode.linkReferences),deployedBytecodeSize:le(de.deployedBytecode.object)},{name:"Unstable_CallWithSignatureModule",abi:ce.abi,bytecode:ce.bytecode.object,placeholders:M(ce.bytecode.linkReferences),deployedBytecodeSize:le(ce.deployedBytecode.object)}];import{readFileSync as Qr}from"fs";import Zr from"path";import{MUDError as pe}from"@latticexyz/common/errors";import{size as Xr}from"viem";function B(e,o,n){let r,t=Zr.join(n,e,o+".json");try{r=JSON.parse(Qr(t,"utf8"))}catch{throw new pe(`Error reading file at ${t}`)}let a=r?.bytecode?.object;if(!a)throw new pe(`No bytecode found in ${t}`);let i=r?.deployedBytecode?.object;if(!i)throw new pe(`No deployed bytecode found in ${t}`);let s=r?.abi;if(!s)throw new pe(`No ABI found in ${t}`);let d=M(r?.bytecode?.linkReferences??{});return{abi:s,bytecode:a,placeholders:d,deployedBytecodeSize:Xr(i)}}import{groupBy as pn}from"@latticexyz/common/utils";import{readFileSync as on}from"fs";import tn from"glob";import en from"toposort";function vo(e,o,n){let r=en(e.flatMap(t=>n(t).map(a=>[o(t),a])));return[...e].sort((t,a)=>r.indexOf(o(t))-r.indexOf(o(a)))}function To(e){let n=tn.sync(`${e}/**/*.json`,{ignore:"**/*.abi.json"}).map(r=>JSON.parse(on(r,"utf8"))).flatMap(r=>{if(!r.metadata)return[];let t=Object.keys(r.metadata.settings.compilationTarget)[0],a=r.metadata.settings.compilationTarget[t],i=r.bytecode.linkReferences;return Object.entries(i).flatMap(([s,d])=>Object.keys(d).map(c=>({path:s,name:c,dependentPath:t,dependentName:a})))});return vo(n,r=>`${r.path}:${r.name}`,r=>[`${r.dependentPath}:${r.dependentName}`])}import{spliceHex as rn}from"@latticexyz/common";import{getCreate2Address as nn}from"viem";function fe(e,o){return function(r,t){let a=e;for(let i of o){let s=t.find(d=>d.path===i.path&&d.name===i.name);if(!s)throw new Error(`Could not find library for bytecode placeholder ${i.path}:${i.name}`);a=rn(a,i.start,i.length,s.prepareDeploy(r,t).address)}return{bytecode:a,address:nn({from:r,bytecode:a,salt:C})}}}function Io({config:e,forgeSourceDir:o,forgeOutDir:n}){let r=To(n).map(m=>{let p=B(sn.basename(m.path),m.name,n);return{path:m.path,name:m.name,abi:p.abi,prepareDeploy:fe(p.bytecode,p.placeholders),deployedBytecodeSize:p.deployedBytecodeSize}}),t=z(e),a=k(o).map(({basename:m})=>m),i=an(e,a),d=B("System.sol","System",n).abi.filter(m=>m.type==="function").map(ko),c=Object.entries(i.systems).map(([m,p])=>{let S=e.namespace,x=p.name,v=we({type:"system",namespace:S,name:x}),f=B(`${m}.sol`,m,n),h=f.abi.filter(w=>w.type==="function").map(ko).filter(w=>!d.includes(w)).map(w=>{let ke=S===""?w:`${S}__${w}`;return{signature:ke,selector:Ao(ke),systemId:v,systemFunctionSignature:w,systemFunctionSelector:Ao(w)}});return{namespace:S,name:x,systemId:v,allowAll:p.openAccess,allowedAddresses:p.accessListAddresses,allowedSystemIds:p.accessListSystems.map(w=>we({type:"system",namespace:S,name:i.systems[w].name})),prepareDeploy:fe(f.bytecode,f.placeholders),deployedBytecodeSize:f.deployedBytecodeSize,abi:f.abi,functions:h}}),y=pn(c,m=>m.systemId),u=Array.from(y.values()).filter(m=>m.length>1).flat();if(u.length){let m=u.map(p=>p.name);throw new Error(`Found systems with overlapping system ID: ${m.join(", ")}.
|
14
|
+
|
15
|
+
System IDs are generated from the first 16 bytes of the name, so you may need to rename them to avoid the overlap.`)}let g={tableIds:Object.fromEntries(Object.entries(e.tables).map(([m,p])=>[m,ln(we({type:p.offchainOnly?"offchainTable":"table",namespace:e.namespace,name:p.name}))]))},b=e.modules.map(m=>{let p=me.find(x=>x.name===m.name)??B(`${m.name}.sol`,m.name,n),S=m.args.map(x=>dn(x,g)).map(x=>{let v=x.value instanceof Uint8Array?mn(x.value):x.value;return cn(x.type,v)});if(S.length>1)throw new Error(`${m.name} module should only have 0-1 args, but had ${S.length} args.`);return{name:m.name,installAsRoot:m.root,installData:S.length===0?"0x":S[0],prepareDeploy:fe(p.bytecode,p.placeholders),deployedBytecodeSize:p.deployedBytecodeSize,abi:p.abi}});return{tables:t,systems:c,modules:b,libraries:r}}import{getChainId as On}from"viem/actions";import{existsSync as fn}from"fs";import yn from"path";import un from"chalk";import{getScriptDirectory as gn,forge as bn}from"@latticexyz/common/foundry";async function Po(e,o,n,r,t,a){let i=t?.replaceAll("\\","").split(" ")??[],s=yn.join(await gn(),e+".s.sol");if(!fn(s)){console.log(`No script at ${s}, skipping post deploy hook`);return}console.log(un.blue(`Executing post deploy script at ${s}`)),await bn(["script",e,"--broadcast","--sig","run(address)",o,"--rpc-url",n,"-vvv",a?"--aws":"",...i],{profile:r})}import{kmsKeyToAccount as Bn}from"@latticexyz/common/kms";var I={configPath:{type:"string",desc:"Path to the MUD 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"},rpcBatch:{type:"boolean",desc:"Enable batch processing of RPC requests in viem client (defaults to batch size of 100 and wait of 1s)"},deployerAddress:{type:"string",desc:"Deploy using an existing deterministic deployer (https://github.com/Arachnid/deterministic-deployment-proxy)"},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."},forgeScriptOptions:{type:"string",description:"Options to pass to forge script PostDeploy.s.sol"},salt:{type:"string",desc:"The deployment salt to use. Defaults to a random salt."},kms:{type:"boolean",desc:"Deploy the World with an AWS KMS key instead of local private key."}};async function E(e){let o=e.salt;if(o!=null&&!Dn(o))throw new Ce("Expected hex string for salt");let n=e.profile??process.env.FOUNDRY_PROFILE,r=await Tn(e.configPath),t=An(r);e.printConfig&&console.log(F.green(`
|
16
|
+
Resolved config:
|
17
|
+
`),JSON.stringify(t,null,2));let a=e.srcDir??await Pn(n),i=await kn(n),s=e.rpc??await In(n);console.log(F.bgBlue(F.whiteBright(`
|
18
|
+
Deploying MUD contracts${n?" with profile "+n:""} to RPC ${s}
|
19
|
+
`))),e.skipBuild||await J({config:r,srcDir:a,foundryProfile:n});let d=Io({config:t,forgeSourceDir:a,forgeOutDir:i}),c=await(async()=>{if(e.kms){let m=process.env.AWS_KMS_KEY_ID;if(!m)throw new Ce("Missing `AWS_KMS_KEY_ID` environment variable. This is required when using with `--kms` option.");return await Bn({keyId:m})}else{let m=process.env.PRIVATE_KEY;if(!m)throw new Ce(`Missing PRIVATE_KEY environment variable.
|
20
|
+
Run 'echo "PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" > .env'
|
21
|
+
in your contracts directory to use the default anvil private key.`);return vn(m)}})(),y=Sn({transport:Cn(s,{batch:e.rpcBatch?{batchSize:100,wait:1e3}:void 0}),account:c});console.log("Deploying from",y.account.address);let u=Date.now(),g=await Do({deployerAddress:e.deployerAddress,salt:o,worldAddress:e.worldAddress,client:y,config:d,withWorldProxy:r.deploy.upgradeableWorldImplementation});(e.worldAddress==null||e.alwaysRunPostDeploy)&&await Po(t.postDeployScript,g.address,s,n,e.forgeScriptOptions,!!e.kms),console.log(F.green("Deployment completed in",(Date.now()-u)/1e3,"seconds"));let b={worldAddress:g.address,blockNumber:Number(g.deployBlock)};if(e.saveDeployment){let m=await On(y),p=xe.join(t.deploysDirectory,m.toString());wn(p,{recursive:!0}),Se(xe.join(p,"latest.json"),JSON.stringify(b,null,2)),Se(xe.join(p,Date.now()+".json"),JSON.stringify(b,null,2));let S=[1337,31337],x=hn(t.worldsFile)?JSON.parse(xn(t.worldsFile,"utf-8")):{};x[m]={address:b.worldAddress,blockNumber:S.includes(m)?void 0:b.blockNumber},Se(t.worldsFile,JSON.stringify(x,null,2)),console.log(F.bgGreen(F.whiteBright(`
|
22
|
+
Deployment result (written to ${t.worldsFile} and ${p}):
|
23
|
+
`)))}return console.log(b),g}var Wn={command:"deploy",describe:"Deploy MUD contracts",builder(e){return e.options(I)},async handler(e){try{await E(e)}catch(o){K(o),process.exit(1)}process.exit(0)}},Oo=Wn;import{loadConfig as Mn}from"@latticexyz/config/node";import{worldgen as jn}from"@latticexyz/world/node";import{getSrcDirectory as Rn}from"@latticexyz/common/foundry";import Bo from"path";import{rmSync as Hn}from"fs";var Fn={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 MUD config file"},clean:{type:"boolean",desc:"Clear the worldgen directory before generating new interfaces (defaults to true)",default:!0}})},async handler(e){await En(e),process.exit(0)}};async function En(e){let o=e.srcDir??await Rn(),n=k(o),r=e.config??await Mn(e.configPath),t=Bo.join(o,r.codegen.outputDirectory);e.clean&&Hn(Bo.join(t,r.codegen.worldgenDirectory),{recursive:!0,force:!0}),await jn(r,n,t)}var Wo=Fn;import _ from"chalk";import{readFileSync as Un,writeFileSync as Vn}from"fs";import ve from"path";import{MUDError as $}from"@latticexyz/common/errors";var Mo={name:"@latticexyz/cli",version:"2.0.9",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:{"@aws-sdk/client-kms":"^3.556.0","@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:*","asn1.js":"^5.4.1",chalk:"^5.0.1",chokidar:"^3.5.3",debug:"^4.3.4",dotenv:"^16.0.3",ethers:"^5.7.2",execa:"^7.0.0",glob:"^8.0.3","nice-grpc-web":"^2.0.1",openurl:"^1.1.1","p-queue":"^7.4.1","p-retry":"^5.1.2",path:"^0.12.7",rxjs:"7.5.5","throttle-debounce":"^5.0.0",toposort:"^2.0.2",typescript:"5.4.2",viem:"2.9.20",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/toposort":"^2.0.6","@types/yargs":"^17.0.10","ds-test":"https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0","forge-std":"https://github.com/foundry-rs/forge-std.git#74cfb77e308dd188d2f58864aaf44963ae6b88b1",tsup:"^6.7.0",tsx:"^3.12.6",vitest:"0.34.6"}};import _n from"glob";import{ZodError as zn,z as jo}from"zod";var Nn=jo.object({MUD_PACKAGES:jo.string().transform(e=>JSON.parse(e))});function Ln(){try{return Nn.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/protocol-parser":{"localPath":"packages/protocol-parser"},"@latticexyz/query":{"localPath":"packages/query"},"@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 zn){let{...o}=e.format();console.error(`
|
24
|
+
Missing or invalid environment variables:
|
25
|
+
|
26
|
+
${Object.keys(o).join(`
|
27
|
+
`)}
|
28
|
+
`),process.exit(1)}throw e}}var De=Ln().MUD_PACKAGES;var Kn={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"],n=o.reduce((t,a)=>e[a]?t+1:t,0);if(n===0)throw new $(`You need to provide one these options: ${o.join(", ")}`);if(n>1)throw new $(`These options are mutually exclusive: ${o.join(", ")}`);e.link||(e.mudVersion=await Jn(e));let r=_n.sync("**/package.json").filter(t=>!t.includes("node_modules"));for(let t of r)qn(t,e)}catch(o){K(o)}finally{process.exit(0)}}};async function Jn(e){e.mudVersion==="canary"&&(e.tag="main");let o;try{console.log(_.blue("Fetching available versions")),o=await(await fetch(`https://registry.npmjs.org/${Mo.name}`)).json()}catch{throw new $("Could not fetch available MUD versions")}if(e.tag){let n=o["dist-tags"][e.tag];if(!n)throw new $(`Could not find npm version with tag "${e.tag}"`);return console.log(_.green(`Latest version with tag ${e.tag}: ${n}`)),n}if(e.commit){let n=e.commit.substring(0,8),r=Object.keys(o.versions).find(t=>t.includes(n));if(!r)throw new $(`Could not find npm version based on commit "${e.commit}"`);return console.log(_.green(`Version from commit ${e.commit}: ${r}`)),r}return e.mudVersion}function qn(e,o){let{link:n}=o,{mudVersion:r}=o,t=Yn(e),a=Object.keys(De),i={};for(let c in t.dependencies)a.includes(c)&&(i[c]=t.dependencies[c]);let s={};for(let c in t.devDependencies)a.includes(c)&&(s[c]=t.devDependencies[c]);for(let c in t.dependencies)a.includes(c)&&(t.dependencies[c]=d(c,"dependencies"));for(let c in t.devDependencies)a.includes(c)&&(t.devDependencies[c]=d(c,"devDependencies"));return Vn(e,JSON.stringify(t,null,2)+`
|
29
|
+
`),console.log(`Updating ${e}`),Ro(i,t.dependencies),Ro(s,t.devDependencies),t;function d(c,y){return n&&(r=Gn(e,n,c)),r||t[y][c]}}function Yn(e){try{let o=Un(e,"utf8");return JSON.parse(o)}catch{throw new $("Could not read JSON at "+e)}}function Ro(e,o){for(let n in e)e[n]!==o[n]&&console.log(`${n}: ${_.red(e[n])} -> ${_.green(o[n])}`)}function Gn(e,o,n){let r=ve.relative(ve.dirname(e),process.cwd());return"link:"+ve.join(r,o,De[n].localPath)}var Ho=Kn;import{anvil as Qn,forge as Zn,getRpcUrl as Xn}from"@latticexyz/common/foundry";import es from"chalk";var os={...I,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"}},ts={command:"test",describe:"Run tests in MUD contracts",builder(e){return e.options(os)},async handler(e){if(!e.worldAddress){let t=["--block-base-fee-per-gas","0","--port",String(e.port)];Qn(t)}let o=e.worldAddress?await Xn(e.profile):`http://127.0.0.1:${e.port}`,n=e.worldAddress??(await E({...e,saveDeployment:!1,rpc:o})).address;console.log(es.blue("World address",n));let r=e.forgeOptions?.replaceAll("\\","").split(" ")??[];try{await Zn(["test","--fork-url",o,...r],{profile:e.profile,env:{WORLD_ADDRESS:n}}),process.exit(0)}catch(t){console.error(t),process.exit(1)}}},Fo=ts;import{existsSync as rs,readFileSync as ns}from"fs";import{ethers as Eo}from"ethers";import{loadConfig as ss}from"@latticexyz/config/node";import{MUDError as $o}from"@latticexyz/common/errors";import{cast as as,getRpcUrl as is,getSrcDirectory as ds}from"@latticexyz/common/foundry";import{resolveWorldConfig as cs}from"@latticexyz/world/internal";import ls from"@latticexyz/world/out/IBaseWorld.sol/IBaseWorld.abi.json"assert{type:"json"};import zo from"@latticexyz/world/mud.config";import{resourceToHex as Lo}from"@latticexyz/common";import{createClient as ms,http as ps}from"viem";import{getChainId as fs}from"viem/actions";import{worldToV1 as ys}from"@latticexyz/world/config/v2";var No=Lo({type:"system",namespace:zo.namespace,name:zo.tables.world__Systems.name}),us={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 MUD 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 ds(o),e.rpc??=await is(o);let{tx:n,configPath:r,srcDir:t,rpc:a}=e,i=k(t),s=await ss(r),d=ys(s),c=cs(d,i.map(({basename:v})=>v)),y=e.worldAddress??await gs(d.worldsFile,a),u=new Eo.providers.StaticJsonRpcProvider(a),g=new Eo.Contract(y,ls,u),b=d.namespace,m=Object.values(c.systems).map(({name:v})=>v),p=await g.getFieldLayout(No),S=[];for(let v of m){let f=Lo({type:"system",namespace:b,name:v}),h=await g.getField(No,[f],0,p);S.push({name:v,address:h})}let x=await as(["run","--label",`${y}:World`,...S.map(({name:v,address:f})=>["--label",`${f}:${v}`]).flat(),`${n}`]);console.log(x),process.exit(0)}},Uo=us;async function gs(e,o){if(rs(e)){let n=ms({transport:ps(o)}),r=await fs(n),t=JSON.parse(ns(e,"utf-8"));if(!t[r])throw new $o(`chainId ${r} is missing in worldsFile "${e}"`);return t[r].address}else throw new $o("worldAddress is not specified and worldsFile is missing")}import{anvil as bs,getScriptDirectory as hs,getSrcDirectory as ws}from"@latticexyz/common/foundry";import W from"chalk";import xs from"chokidar";import{loadConfig as Ss,resolveConfigPath as Cs}from"@latticexyz/config/node";import Ds from"path";import{homedir as vs}from"os";import{rmSync as Ts}from"fs";import{BehaviorSubject as As,debounceTime as ks,exhaustMap as Is,filter as Ps}from"rxjs";import{isDefined as Os}from"@latticexyz/common/utils";var Bs={rpc:I.rpc,configPath:I.configPath,alwaysRunPostDeploy:I.alwaysRunPostDeploy,forgeScriptOptions:I.forgeScriptOptions,worldAddress:I.worldAddress},Ws={command:"dev-contracts",describe:"Start a development server for MUD contracts",builder(e){return e.options(Bs)},async handler(e){let o=e.rpc,n=e.configPath??await Cs(e.configPath),r=await ws(),t=await hs(),a=await Ss(n);if(!e.rpc){console.log(W.gray("Cleaning devnode cache"));let c=vs();Ts(Ds.join(c,".foundry","anvil","tmp"),{recursive:!0,force:!0}),bs(["--block-time","1","--block-base-fee-per-gas","0"]),o="http://127.0.0.1:8545"}let i=new As(Date.now());xs.watch([n,r,t],{ignoreInitial:!0}).on("all",async(c,y)=>{y.includes(n)&&(console.log(W.blue("Config changed, queuing deploy\u2026")),i.next(Date.now())),(y.includes(r)||y.includes(t))&&(y.includes(a.codegen.outputDirectory)||(console.log(W.blue("Contracts changed, queuing deploy\u2026")),i.next(Date.now())))});let s=e.worldAddress;i.pipe(ks(200),Is(async c=>{s&&console.log(W.blue("Rebuilding and upgrading world\u2026"));try{let y=await E({...e,configPath:n,rpc:o,rpcBatch:!1,skipBuild:!1,printConfig:!1,profile:void 0,saveDeployment:!0,deployerAddress:void 0,worldAddress:s,srcDir:r,salt:"0x",kms:void 0});return s=y.address,c<i.value?i.next(i.value):console.log(W.gray(`
|
30
|
+
Waiting for file changes\u2026
|
31
|
+
`)),y}catch(y){console.error(W.bgRed(W.whiteBright(`
|
32
|
+
Error while attempting deploy
|
33
|
+
`))),console.error(y),console.log(W.gray(`
|
34
|
+
Waiting for file changes\u2026
|
35
|
+
`))}}),Ps(Os)).subscribe()}},Vo=Ws;import{getCreate2Address as Te,sliceHex as js,zeroHash as Rs}from"viem";import{forge as Ms}from"@latticexyz/common/foundry";async function j(e){let o=["verify-contract",e.address,e.name,"--rpc-url",e.rpc];e.verifier&&o.push("--verifier",e.verifier),e.verifierUrl&&o.push("--verifier-url",e.verifierUrl),await Ms(o,{cwd:e.cwd})}import Hs from"p-queue";import{MUDError as Fs}from"@latticexyz/common/errors";import{getStorageAt as Es}from"viem/actions";import{execa as Ae}from"execa";var $s="0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc";async function _o({client:e,rpc:o,systems:n,modules:r,worldAddress:t,deployerAddress:a,verifier:i,verifierUrl:s}){let d=a??await G(e);if(!d)throw new Fs("No deployer");let c=await Es(e,{address:t,slot:$s}),y=c&&c!==Rs,u=new Hs({concurrency:4});if(n.map(({name:g,bytecode:b})=>u.add(()=>j({name:g,rpc:o,verifier:i,verifierUrl:s,address:Te({from:d,bytecode:b,salt:C})}).catch(m=>{console.error(`Error verifying system contract ${g}:`,m)}))),i==="sourcify")if(await Ae("npm",["install"],{cwd:"node_modules/@latticexyz/store"}),await Ae("npm",["install"],{cwd:"node_modules/@latticexyz/world"}),await Ae("npm",["install"],{cwd:"node_modules/@latticexyz/world-modules"}),Object.entries(y?ee(d):X(d)).map(([g,{bytecode:b}])=>u.add(()=>j({cwd:"node_modules/@latticexyz/world",name:g,rpc:o,verifier:i,verifierUrl:s,address:Te({from:d,bytecode:b,salt:C})}).catch(m=>{console.error(`Error verifying world factory contract ${g}:`,m)}))),r.map(({name:g,bytecode:b})=>u.add(()=>j({cwd:"node_modules/@latticexyz/world-modules",name:g,rpc:o,verifier:i,verifierUrl:s,address:Te({from:d,bytecode:b,salt:C})}).catch(m=>{console.error(`Error verifying module contract ${g}:`,m)}))),y){let g=js(c,-20);u.add(()=>j({cwd:"node_modules/@latticexyz/world",name:"WorldProxy",rpc:o,verifier:i,verifierUrl:s,address:t}).catch(b=>{console.error("Error verifying WorldProxy contract:",b)})),u.add(()=>j({cwd:"node_modules/@latticexyz/world",name:"World",rpc:o,verifier:i,verifierUrl:s,address:g}).catch(b=>{console.error("Error verifying World contract:",b)}))}else u.add(()=>j({cwd:"node_modules/@latticexyz/world",name:"World",rpc:o,verifier:i,verifierUrl:s,address:t}).catch(g=>{console.error("Error verifying World contract:",g)}));else console.log(""),console.log(`Note: MUD is currently unable to verify store, world, and world-modules contracts with ${i}. We are planning to expand support in a future version.`),console.log("")}import{loadConfig as zs}from"@latticexyz/config/node";import{resolveWorldConfig as Ns}from"@latticexyz/world/internal";import{worldToV1 as Ls}from"@latticexyz/world/config/v2";import{getOutDirectory as Us,getRpcUrl as Vs,getSrcDirectory as _s}from"@latticexyz/common/foundry";import{createWalletClient as Ks,http as Js}from"viem";import Ko from"chalk";var qs={deployerAddress:{type:"string",desc:"Deploy using an existing deterministic deployer (https://github.com/Arachnid/deterministic-deployment-proxy)"},worldAddress:{type:"string",required:!0,desc:"Verify an existing World at the given address"},configPath:{type:"string",desc:"Path to the MUD config file"},profile:{type:"string",desc:"The foundry profile to use"},rpc:{type:"string",desc:"The RPC URL to use. Defaults to the RPC url from the local foundry.toml"},rpcBatch:{type:"boolean",desc:"Enable batch processing of RPC requests in viem client (defaults to batch size of 100 and wait of 1s)"},srcDir:{type:"string",desc:"Source directory. Defaults to foundry src directory."},verifier:{type:"string",desc:"The verifier to use. Defaults to blockscout",default:"blockscout"},verifierUrl:{type:"string",desc:"The verification provider."}},Ys={command:"verify",describe:"Verify contracts",builder(e){return e.options(qs)},async handler(e){let o=e.profile??process.env.FOUNDRY_PROFILE,n=await zs(e.configPath),r=Ls(n),t=e.srcDir??await _s(o),a=await Us(o),i=e.rpc??await Vs(o);console.log(Ko.bgBlue(Ko.whiteBright(`
|
36
|
+
Verifying MUD contracts${o?" with profile "+o:""} to RPC ${i}
|
37
|
+
`)));let s=Ks({transport:Js(i,{batch:e.rpcBatch?{batchSize:100,wait:1e3}:void 0})}),d=k(t).map(({basename:g})=>g),c=Ns(r,d),y=Object.keys(c.systems).map(g=>{let b=B(`${g}.sol`,g,a);return{name:g,bytecode:b.bytecode}}),u=r.modules.map(g=>{let b=me.find(m=>m.name===g.name)??B(`${g.name}.sol`,g.name,a);return{name:g.name,bytecode:b.bytecode}});await _o({client:s,rpc:i,systems:y,modules:u,deployerAddress:e.deployerAddress,worldAddress:e.worldAddress,verifier:e.verifier,verifierUrl:e.verifierUrl})}},Jo=Ys;var uy=[Ie,Oo,Pe,Be,Gs,We,Me,Wo,Ho,Fo,Uo,Vo,Qs,Jo];export{uy as commands};
|
38
|
+
//# sourceMappingURL=commands-QJJWDCTW.js.map
|