@latticexyz/cli 2.2.3-main-5277399692c805c8b2b80274888bad3a7e527048 → 2.2.4-main-d3acd9242da44d201ea99e04c1631ed687d30a80
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-UEYQ6ADX.js +42 -0
- package/dist/commands-UEYQ6ADX.js.map +1 -0
- package/dist/mud.js +1 -1
- package/package.json +11 -11
- package/dist/commands-ZNAGFNIJ.js +0 -42
- package/dist/commands-ZNAGFNIJ.js.map +0 -1
@@ -0,0 +1,42 @@
|
|
1
|
+
import{a as Y}from"./chunk-JXC4VYGI.js";import Pa from"@latticexyz/gas-report";import Ma from"@latticexyz/abi-ts";import{loadConfig as ot,resolveConfigPath as tt}from"@latticexyz/config/node";import{tablegen as Go}from"@latticexyz/store/codegen";import{buildSystemsManifest as Qo,worldgen as Zo}from"@latticexyz/world/node";import{forge as Xo}from"@latticexyz/common/foundry";import{execa as et}from"execa";async function G({rootDir:e,config:o,foundryProfile:t=process.env.FOUNDRY_PROFILE}){await Promise.all([Go({rootDir:e,config:o}),Zo({rootDir:e,config:o})]),await Xo(["build"],{profile:t}),await Qo({rootDir:e,config:o}),await et("mud",["abi-ts"],{stdio:"inherit"})}import rt from"node:path";var nt={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(e){let o=await tt(e.configPath),t=await ot(o);await G({rootDir:rt.dirname(o),config:t,foundryProfile:e.profile}),process.exit(0)}},ke=nt;import{rmSync as st}from"fs";import{homedir as at}from"os";import it from"path";import{execa as dt}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=at();st(it.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=dt("anvil",t,{stdio:["inherit","inherit","inherit"]});process.on("SIGINT",()=>{console.log(`
|
2
|
+
gracefully shutting down from SIGINT (Crtl-C)`),r.kill(),process.exit()}),await r}},Pe=lt;var ct={command:"hello <name>",describe:"Greet <name> with Hello",builder(e){return e.options({upper:{type:"boolean"}}).positional("name",{type:"string",demandOption:!0})},handler({name:e}){let o=`Gm, ${e}!`;console.log(o),process.exit(0)}},Me=ct;import{loadConfig as mt,resolveConfigPath as pt}from"@latticexyz/config/node";import{tablegen as ft}from"@latticexyz/store/codegen";import yt from"node:path";var ut={command:"tablegen",describe:"Autogenerate MUD Store table libraries based on the config file",builder(e){return e.options({configPath:{type:"string",desc:"Path to the MUD config file"}})},async handler(e){let o=await pt(e.configPath),t=await mt(o);await ft({rootDir:yt.dirname(o),config:t}),process.exit(0)}},We=ut;import me from"node:path";import{existsSync as Gn,mkdirSync as Qn,readFileSync as Zn,writeFileSync as Ce}from"node:fs";import{stringToHex as wn}from"viem";import{getBalance as xt,sendRawTransaction as Ct,sendTransaction as Ie,waitForTransactionReceipt as Oe}from"viem/actions";var D={gasPrice:1e11,gasLimit:1e5,signerAddress:"3fab184622dc19b6109349b94811493bf2a45362",transaction:"f8a58085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222",address:"4e59b44847b379578588920ca78fbf26c0b4956c",creationCode:"604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3"};import Be from"debug";var B=Be("mud:cli"),pe=Be("mud:cli");B.log=console.debug.bind(console);pe.log=console.error.bind(console);var m=B.extend("deploy"),bt=B.extend("deploy");m.log=console.debug.bind(console);bt.log=console.error.bind(console);import{sliceHex as ht}from"viem";import{getBytecode as wt}from"viem/actions";var Q=`0x${D.address}`;async function Z(e){let o=await wt(e,{address:Q});if(o)return m("found CREATE2 deployer at",Q),o!==ht(`0x${D.creationCode}`,14)&&console.warn(`
|
3
|
+
\u26A0\uFE0F Bytecode for deployer at ${Q} did not match the expected CREATE2 bytecode. You may have unexpected results.
|
4
|
+
`),Q}var fe=`0x${D.address}`;async function He(e){let o=await Z(e);if(o!==void 0)return o;let t=BigInt(D.gasLimit)*BigInt(D.gasPrice),r=await xt(e,{address:`0x${D.signerAddress}`}),n=t-r;if(n>0){m("sending gas for CREATE2 deployer to signer at",D.signerAddress);let i=await Ie(e,{chain:e.chain??null,to:`0x${D.signerAddress}`,value:n}),c=await Oe(e,{hash:i});if(c.status!=="success")throw console.error("failed to send gas to deployer signer",c),new Error("failed to send gas to deployer signer")}m("deploying CREATE2 deployer at",fe);let s=await Ct(e,{serializedTransaction:`0x${D.transaction}`}).catch(i=>{if(String(i).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
|
+
`),m("deploying CREATE2 deployer"),Ie(e,{chain:e.chain??null,data:`0x${D.creationCode}`});throw i}),a=await Oe(e,{hash:s});if(!a.contractAddress)throw new Error("Deploy receipt did not have contract address, was the deployer not deployed?");return a.contractAddress!==fe&&console.warn(`
|
9
|
+
\u26A0\uFE0F CREATE2 deployer created at ${a.contractAddress} does not match the CREATE2 determinstic deployer we expected (${fe})`),a.contractAddress}import{waitForTransactionReceipt as Jt}from"viem/actions";import{concatHex as Tt,getCreate2Address as kt}from"viem";import{getBytecode as Pt}from"viem/actions";import{padHex as At}from"viem";import vt from"@latticexyz/world/out/IBaseWorld.sol/IBaseWorld.abi.json"assert{type:"json"};import{helloStoreEvent as St}from"@latticexyz/store";import{helloWorldEvent as Dt}from"@latticexyz/world";var C=At("0x",{size:32}),V=parseInt("6000",16),X=[St,Dt],x=vt,Re=["2.0.0","2.0.1","2.0.2"],je=["2.0.0","2.0.1","2.0.2"];import{sendTransaction as Mt}from"@latticexyz/common";import Wt from"p-retry";async function $e({client:e,deployerAddress:o,bytecode:t,deployedBytecodeSize:r,debugLabel:n="contract"}){if(t.includes("__$"))throw new Error(`Found unlinked public library in ${n} bytecode`);let s=kt({from:o,salt:C,bytecode:t});return await Pt(e,{address:s,blockTag:"pending"})?(m("found",n,"at",s),[]):(r!=null&&(r>V?console.warn(`
|
10
|
+
Bytecode for ${n} (${r} bytes) is over the contract size limit (${V} bytes). Run \`forge build --sizes\` for more info.
|
11
|
+
`):r>V*.95&&console.warn(`
|
12
|
+
Bytecode for ${n} (${r} bytes) is almost over the contract size limit (${V} bytes). Run \`forge build --sizes\` for more info.
|
13
|
+
`)),m("deploying",n,"at",s),[await Wt(()=>Mt(e,{chain:e.chain??null,to:o,data:Tt([C,t])}),{retries:3,onFailedAttempt:()=>m(`failed to deploy ${n}, retrying...`)})])}import{uniqueBy as It}from"@latticexyz/common/utils";import{waitForTransactionReceipt as Bt}from"viem/actions";async function P({client:e,hashes:o,debugLabel:t="transactions"}){if(o.length){m(`waiting for ${t} to confirm`);for(let r of o)if((await Bt(e,{hash:r})).status==="reverted")throw new Error(`Transaction reverted: ${r}`)}}async function T({client:e,deployerAddress:o,contracts:t}){let r=It(t,s=>s.bytecode),n=(await Promise.all(r.map(s=>$e({client:e,deployerAddress:o,...s})))).flat();return await P({client:e,hashes:n,debugLabel:"contract deploys"}),n}import Ve from"@latticexyz/world/out/WorldFactory.sol/WorldFactory.json"assert{type:"json"};import Rt from"@latticexyz/world/out/WorldFactory.sol/WorldFactory.abi.json"assert{type:"json"};import{getCreate2Address as jt,encodeDeployData as $t,size as Et}from"viem";import Ee from"@latticexyz/world/out/AccessManagementSystem.sol/AccessManagementSystem.json"assert{type:"json"};import Fe from"@latticexyz/world/out/BalanceTransferSystem.sol/BalanceTransferSystem.json"assert{type:"json"};import ze from"@latticexyz/world/out/BatchCallSystem.sol/BatchCallSystem.json"assert{type:"json"};import Le from"@latticexyz/world/out/RegistrationSystem.sol/RegistrationSystem.json"assert{type:"json"};import Ne from"@latticexyz/world/out/InitModule.sol/InitModule.json"assert{type:"json"};import Ot from"@latticexyz/world/out/InitModule.sol/InitModule.abi.json"assert{type:"json"};import{getCreate2Address as U,encodeDeployData as Ht,size as _}from"viem";function j(e){let o=_(Ee.deployedBytecode.object),t=Ee.bytecode.object,r=U({from:e,bytecode:t,salt:C}),n=_(Fe.deployedBytecode.object),s=Fe.bytecode.object,a=U({from:e,bytecode:s,salt:C}),i=_(ze.deployedBytecode.object),c=ze.bytecode.object,l=U({from:e,bytecode:c,salt:C}),f=_(Le.deployedBytecode.object),d=Le.bytecode.object,y=U({from:e,bytecode:d,salt:C}),b=_(Ne.deployedBytecode.object),w=Ht({bytecode:Ne.bytecode.object,abi:Ot,args:[r,a,l,y]}),v=U({from:e,bytecode:w,salt:C});return{AccessManagementSystem:{bytecode:t,deployedBytecodeSize:o,debugLabel:"access management system",address:r},BalanceTransferSystem:{bytecode:s,deployedBytecodeSize:n,debugLabel:"balance transfer system",address:a},BatchCallSystem:{bytecode:c,deployedBytecodeSize:i,debugLabel:"batch call system",address:l},RegistrationSystem:{bytecode:d,deployedBytecodeSize:f,debugLabel:"core registration system",address:y},InitModule:{bytecode:w,deployedBytecodeSize:b,debugLabel:"core module",address:v}}}function ee(e){let o=j(e),t=Et(Ve.deployedBytecode.object),r=$t({bytecode:Ve.bytecode.object,abi:Rt,args:[o.InitModule.address]}),n=jt({from:e,bytecode:r,salt:C});return{...o,WorldFactory:{bytecode:r,deployedBytecodeSize:t,debugLabel:"world factory",address:n}}}import Ue from"@latticexyz/world/out/WorldProxyFactory.sol/WorldProxyFactory.json"assert{type:"json"};import Ft from"@latticexyz/world/out/WorldProxyFactory.sol/WorldProxyFactory.abi.json"assert{type:"json"};import{getCreate2Address as zt,encodeDeployData as Lt,size as Nt}from"viem";function oe(e){let o=j(e),t=Nt(Ue.deployedBytecode.object),r=Lt({bytecode:Ue.bytecode.object,abi:Ft,args:[o.InitModule.address]}),n=zt({from:e,bytecode:r,salt:C});return{...o,WorldProxyFactory:{bytecode:r,deployedBytecodeSize:t,debugLabel:"world proxy factory",address:n}}}async function te(e,o,t){if(t){let n=oe(o);return await T({client:e,deployerAddress:o,contracts:Object.values(n)}),n.WorldProxyFactory.address}let r=ee(o);return await T({client:e,deployerAddress:o,contracts:Object.values(r)}),r.WorldFactory.address}import qt from"@latticexyz/world/out/WorldFactory.sol/WorldFactory.abi.json"assert{type:"json"};import{writeContract as Yt}from"@latticexyz/common";import{AbiEventSignatureNotFoundError as Vt,decodeEventLog as Ut,hexToString as _e,parseAbi as _t}from"viem";import{isDefined as Kt}from"@latticexyz/common/utils";function $(e){let o=e.map(a=>{try{return{...a,...Ut({strict:!0,abi:_t(X),topics:a.topics,data:a.data})}}catch(i){if(i instanceof Vt)return;throw i}}).filter(Kt),{address:t,deployBlock:r,worldVersion:n,storeVersion:s}=o.reduce((a,i)=>({...a,address:i.address,deployBlock:i.blockNumber,...i.eventName==="HelloWorld"?{worldVersion:_e(i.args.worldVersion).replace(/\0+$/,"")}:null,...i.eventName==="HelloStore"?{storeVersion:_e(i.args.storeVersion).replace(/\0+$/,"")}: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 Ke(e,o,t,r){let n=await te(e,o,r);m("deploying world");let s=await Yt(e,{chain:e.chain??null,address:n,abi:qt,functionName:"deployWorld",args:[t]});m("waiting for world deploy");let a=await Jt(e,{hash:s});if(a.status!=="success")throw console.error("world deploy failed",a),new Error("world deploy failed");let i=$(a.logs);return m("deployed world to",i.address,"at block",i.deployBlock),{...i,stateBlock:i.deployBlock}}import{resourceToLabel as ue,writeContract as nr}from"@latticexyz/common";import{valueSchemaToFieldLayoutHex as sr,keySchemaToHex as ar,valueSchemaToHex as ir,getSchemaTypes as Ze,getValueSchema as dr,getKeySchema as lr}from"@latticexyz/protocol-parser/internal";import{parseAbiItem as Gt,decodeAbiParameters as Je,parseAbiParameters as qe}from"viem";import{hexToResource as Qt}from"@latticexyz/common";import{storeSetRecordEvent as Zt}from"@latticexyz/store";import{getLogs as Xt}from"viem/actions";import{decodeKey as er,decodeValueArgs as or,getKeySchema as tr,getSchemaTypes as Ye,getValueSchema as rr,hexToSchema as Ge}from"@latticexyz/protocol-parser/internal";import ye from"@latticexyz/store/mud.config";async function Qe({client:e,worldDeploy:o}){m("looking up tables for",o.address);let r=(await Xt(e,{strict:!0,fromBlock:o.deployBlock,toBlock:o.stateBlock,address:o.address,event:Gt(Zt),args:{tableId:ye.namespaces.store.tables.Tables.tableId}})).map(n=>{let{tableId:s}=er(Ye(tr(ye.namespaces.store.tables.Tables)),n.args.keyTuple),{type:a,namespace:i,name:c}=Qt(s),l=or(Ye(rr(ye.namespaces.store.tables.Tables)),n.args),f=Ge(l.keySchema),d=Ge(l.valueSchema),y=Je(qe("string[]"),l.abiEncodedKeyNames)[0],b=Je(qe("string[]"),l.abiEncodedFieldNames)[0],w=[...d.staticFields,...d.dynamicFields],v=Object.fromEntries(f.staticFields.map((g,A)=>[y[A],{type:g,internalType:g}])),k=Object.fromEntries(w.map((g,A)=>[b[A],{type:g,internalType:g}]));return{type:a,namespace:i,name:c,tableId:s,schema:{...v,...k},key:Object.keys(v)}});return m("found",r.length,"tables for",o.address),r}import cr from"p-retry";async function Xe({client:e,worldDeploy:o,tables:t}){let n=(await Qe({client:e,worldDeploy:o})).map(i=>i.tableId),s=t.filter(i=>n.includes(i.tableId));s.length&&m("existing tables:",s.map(ue).join(", "));let a=t.filter(i=>!n.includes(i.tableId));return a.length?(m("registering tables:",a.map(ue).join(", ")),await Promise.all(a.map(i=>{let c=Ze(lr(i)),l=Ze(dr(i));return cr(()=>nr(e,{chain:e.chain??null,address:o.address,abi:x,functionName:"registerTable",args:[i.tableId,sr(l),ar(c),ir(l),Object.keys(c),Object.keys(l)]}),{retries:3,onFailedAttempt:()=>m(`failed to register table ${ue(i)}, retrying...`)})}))):[]}import{getAddress as I}from"viem";import{writeContract as be,resourceToLabel as K}from"@latticexyz/common";import{hexToResource as Mr,resourceToLabel as Wr}from"@latticexyz/common";import{getFunctions as Br}from"@latticexyz/world/internal";import{parseAbiItem as mr,HttpRequestError as pr}from"viem";import{getLogs as fr}from"viem/actions";import{storeSpliceStaticDataEvent as yr}from"@latticexyz/store";import ur from"p-retry";import gr from"@latticexyz/store/mud.config";async function re({client:e,worldDeploy:o}){m("looking up resource IDs for",o.address);let r=(await ur(()=>fr(e,{strict:!0,address:o.address,fromBlock:o.deployBlock,toBlock:o.stateBlock,event:mr(yr),args:{tableId:gr.namespaces.store.tables.ResourceIds.tableId}}),{retries:3,onFailedAttempt:async n=>{if(!(n instanceof pr&&n.status===400&&n.message.includes("block is out of range")))throw n}})).map(n=>n.args.keyTuple[0]);return m("found",r.length,"resource IDs for",o.address),r}import{decodeValueArgs as br,encodeKey as hr,getKeySchema as wr,getSchemaTypes as eo,getValueSchema as xr}from"@latticexyz/protocol-parser/internal";import{readContract as Cr}from"viem/actions";async function E({client:e,worldDeploy:o,table:t,key:r}){let[n,s,a]=await Cr(e,{blockNumber:o.stateBlock,address:o.address,abi:x,functionName:"getRecord",args:[t.tableId,hr(eo(wr(t)),r)]});return br(eo(xr(t)),{staticData:n,encodedLengths:s,dynamicData:a})}import{parseAbiItem as Ar,getAddress as vr}from"viem";import{storeSpliceStaticDataEvent as Sr}from"@latticexyz/store";import{getLogs as Dr}from"viem/actions";import{decodeKey as Tr,getKeySchema as kr,getSchemaTypes as Pr}from"@latticexyz/protocol-parser/internal";import ge from"@latticexyz/world/mud.config";async function ne({client:e,worldDeploy:o}){m("looking up resource access for",o.address);let r=(await Dr(e,{strict:!0,fromBlock:o.deployBlock,toBlock:o.stateBlock,address:o.address,event:Ar(Sr),args:{tableId:ge.namespaces.world.tables.ResourceAccess.tableId}})).map(s=>Tr(Pr(kr(ge.namespaces.world.tables.ResourceAccess)),s.args.keyTuple)),n=(await Promise.all(r.map(async s=>[s,await E({client:e,worldDeploy:o,table:ge.namespaces.world.tables.ResourceAccess,key:s})]))).filter(([,s])=>s.access).map(([s])=>({resourceId:s.resourceId,address:vr(s.caller)}));return m("found",n.length,"resource<>address access pairs"),n}import Ir from"@latticexyz/world/mud.config";async function oo({client:e,worldDeploy:o}){let[t,r,n]=await Promise.all([re({client:e,worldDeploy:o}),Br({client:e,worldAddress:o.address,fromBlock:o.deployBlock,toBlock:o.stateBlock}),ne({client:e,worldDeploy:o})]),s=t.map(Mr).filter(a=>a.type==="system");return m("looking up systems:",s.map(Wr).join(", ")),await Promise.all(s.map(async a=>{let{system:i,publicAccess:c}=await E({client:e,worldDeploy:o,table:Ir.namespaces.world.tables.Systems,key:{systemId:a.resourceId}}),l=r.filter(f=>f.systemId===a.resourceId);return{address:i,namespace:a.namespace,name:a.name,systemId:a.resourceId,allowAll:c,allowedAddresses:n.filter(({resourceId:f})=>f===a.resourceId).map(({address:f})=>f),worldFunctions:l}}))}import he from"p-retry";async function to({client:e,deployerAddress:o,libraries:t,worldDeploy:r,systems:n}){let[s,a]=await Promise.all([oo({client:e,worldDeploy:r}),ne({client:e,worldDeploy:r})]),i=n.filter(p=>s.some(h=>h.systemId===p.systemId&&I(h.address)===I(p.prepareDeploy(o,t).address)));i.length&&m("existing systems:",i.map(K).join(", "));let c=i.map(p=>p.systemId),l=n.filter(p=>!c.includes(p.systemId));if(!l.length)return[];let f=l.filter(p=>s.some(h=>h.systemId===p.systemId&&I(h.address)!==I(p.prepareDeploy(o,t).address)));f.length&&m("upgrading systems:",f.map(K).join(", "));let d=l.filter(p=>!s.some(h=>h.systemId===p.systemId));d.length&&m("registering new systems:",d.map(K).join(", ")),await T({client:e,deployerAddress:o,contracts:l.map(p=>({bytecode:p.prepareDeploy(o,t).bytecode,deployedBytecodeSize:p.deployedBytecodeSize,debugLabel:`${K(p)} system`}))});let y=await Promise.all(l.map(p=>he(()=>be(e,{chain:e.chain??null,address:r.address,abi:x,functionName:"registerSystem",args:[p.systemId,p.prepareDeploy(o,t).address,p.allowAll]}),{retries:3,onFailedAttempt:()=>m(`failed to register system ${K(p)}, retrying...`)}))),b=n.map(p=>p.systemId),w=a.filter(({resourceId:p})=>b.includes(p)),v=[...n.flatMap(p=>p.allowedAddresses.map(h=>({resourceId:p.systemId,address:h}))),...n.flatMap(p=>p.allowedSystemIds.map(h=>({resourceId:p.systemId,address:s.find(u=>u.systemId===h)?.address??n.find(u=>u.systemId===h)?.prepareDeploy(o,t).address})).filter(h=>h.address!=null))],k=v.filter(p=>!w.some(({resourceId:h,address:u})=>h===p.resourceId&&I(u)===I(p.address))),g=w.filter(p=>!v.some(({resourceId:h,address:u})=>h===p.resourceId&&I(u)===I(p.address)));g.length&&m("revoking",g.length,"access grants"),k.length&&m("adding",k.length,"access grants");let A=await Promise.all([...g.map(p=>he(()=>be(e,{chain:e.chain??null,address:r.address,abi:x,functionName:"revokeAccess",args:[p.resourceId,p.address]}),{retries:3,onFailedAttempt:()=>m("failed to revoke access, retrying...")})),...k.map(p=>he(()=>be(e,{chain:e.chain??null,address:r.address,abi:x,functionName:"grantAccess",args:[p.resourceId,p.address]}),{retries:3,onFailedAttempt:()=>m("failed to grant access, retrying...")}))]);return[...y,...A]}import{getAddress as Or,parseAbi as Hr}from"viem";import{getBlockNumber as Rr,getLogs as jr}from"viem/actions";var ro=new Map;async function no(e,o){let t=Or(o),r=ro.get(t);if(r!=null)return r;m("looking up world deploy for",t);let n=await Rr(e),s=await jr(e,{strict:!0,address:t,events:Hr(X),fromBlock:"earliest",toBlock:n});return r={...$(s),stateBlock:n},ro.set(t,r),m("found world deploy for",t,"at block",r.deployBlock),r}import{hexToResource as $r,writeContract as Er}from"@latticexyz/common";import{getFunctions as Fr}from"@latticexyz/world/internal";import zr from"p-retry";async function so({client:e,worldDeploy:o,functions:t}){let r=await Fr({client:e,worldAddress:o.address,fromBlock:o.deployBlock,toBlock:o.stateBlock}),n=Object.fromEntries(r.map(i=>[i.selector,i])),s=t.filter(i=>n[i.selector]),a=t.filter(i=>!s.includes(i));if(s.length){m("functions already registered:",s.map(c=>c.signature).join(", "));let i=s.filter(c=>c.systemId!==n[c.selector]?.systemId);i.length&&console.warn("found",i.length,"functions already registered but pointing at a different system ID:",i.map(c=>c.signature).join(", "))}return a.length?(m("registering functions:",a.map(i=>i.signature).join(", ")),Promise.all(a.map(i=>{let{namespace:c}=$r(i.systemId),l=c===""?{functionName:"registerRootFunctionSelector",args:[i.systemId,i.systemFunctionSignature,i.systemFunctionSignature]}:{functionName:"registerFunctionSelector",args:[i.systemId,i.systemFunctionSignature]};return zr(()=>Er(e,{chain:e.chain??null,address:o.address,abi:x,...l}),{retries:3,onFailedAttempt:()=>m(`failed to register function ${i.signature}, retrying...`)})}))):[]}import{BaseError as Lr}from"viem";import{writeContract as Nr}from"@latticexyz/common";import{isDefined as Vr}from"@latticexyz/common/utils";import Ur from"p-retry";async function se({client:e,deployerAddress:o,libraries:t,worldDeploy:r,modules:n}){return n.length?(await T({client:e,deployerAddress:o,contracts:n.map(s=>({bytecode:s.prepareDeploy(o,t).bytecode,deployedBytecodeSize:s.deployedBytecodeSize,debugLabel:`${s.name} module`}))}),m("installing modules:",n.map(s=>s.name).join(", ")),(await Promise.all(n.map(s=>Ur(async()=>{try{let a=[...x,...s.abi],i=s.prepareDeploy(o,t).address,c=s.installAsRoot?{functionName:"installRootModule",args:[i,s.installData]}:{functionName:"installModule",args:[i,s.installData]};return await Nr(e,{chain:e.chain??null,address:r.address,abi:a,...c})}catch(a){if(a instanceof Lr&&a.message.includes("Module_AlreadyInstalled")){m(`module ${s.name} already installed`);return}if(s.optional){m(`optional module ${s.name} install failed, skipping`),m(a);return}throw a}},{retries:3,onFailedAttempt:()=>m(`failed to install module ${s.name}, retrying...`)})))).filter(Vr)):[]}import{getAddress as ao}from"viem";import{hexToResource as io,resourceToHex as lo,writeContract as _r}from"@latticexyz/common";import Kr from"@latticexyz/world/mud.config";async function co({client:e,worldDeploy:o,resourceIds:t}){let r=Array.from(new Set(t.map(d=>io(d).namespace))),n=await re({client:e,worldDeploy:o}),s=new Set(n.map(d=>io(d).namespace));s.size&&m("found",s.size,"existing namespaces:",Array.from(s).map(d=>d===""?"<root>":d).join(", "));let a=r.filter(d=>s.has(d)),c=(await Promise.all(a.map(async d=>{let{owner:y}=await E({client:e,worldDeploy:o,table:Kr.namespaces.world.tables.NamespaceOwner,key:{namespaceId:lo({type:"namespace",namespace:d,name:""})}});return[d,y]}))).filter(([,d])=>ao(d)!==ao(e.account.address)).map(([d])=>d);if(c.length)throw new Error(`You are attempting to deploy to namespaces you do not own: ${c.join(", ")}`);let l=r.filter(d=>!s.has(d));return l.length>0&&m("registering namespaces:",Array.from(l).join(", ")),Promise.all(l.map(d=>_r(e,{chain:e.chain??null,address:o.address,abi:x,functionName:"registerNamespace",args:[lo({namespace:d,type:"namespace",name:""})]})))}import{resourceToHex as xn,resourceToLabel as Cn}from"@latticexyz/common";import{randomBytes as An}from"crypto";import{stringToHex as fo,BaseError as sn}from"viem";import{hexToResource as an,writeContract as dn}from"@latticexyz/common";import{identity as ln,isDefined as yo}from"@latticexyz/common/utils";import cn from"@latticexyz/world-module-metadata/mud.config";import mn from"@latticexyz/world-module-metadata/out/IMetadataSystem.sol/IMetadataSystem.abi.json"assert{type:"json"};import{decodeValueArgs as Jr,getKeyTuple as qr,getSchemaTypes as Yr,getValueSchema as Gr}from"@latticexyz/protocol-parser/internal";import{readContract as Qr}from"viem/actions";import{mapObject as Zr}from"@latticexyz/common/utils";async function mo({client:e,worldDeploy:o,table:t,key:r}){let[n,s,a]=await Qr(e,{blockNumber:o.stateBlock,address:o.address,abi:x,functionName:"getRecord",args:[t.tableId,qr(t,r)]}),i={...r,...Jr(Yr(Gr(t)),{staticData:n,encodedLengths:s,dynamicData:a})};return Zr(t.schema,(c,l)=>i[l])}import pn from"@latticexyz/world-module-metadata/out/MetadataModule.sol/MetadataModule.json"assert{type:"json"};import{isHex as Xr,size as en}from"viem";function ae(e){return Object.entries(e).flatMap(([o,t])=>Object.entries(t).flatMap(([r,n])=>n.map(s=>({path:o,name:r,start:s.start,length:s.length}))))}import{z as W}from"zod";import{Abi as on}from"abitype/zod";var po=W.object({object:W.string().refine(Xr),linkReferences:W.record(W.record(W.array(W.object({start:W.number(),length:W.number()}))))}),tn=W.object({bytecode:po,deployedBytecode:po,abi:on});function ie(e){let o=tn.parse(e),t=ae(o.bytecode.linkReferences);return{abi:o.abi,bytecode:o.bytecode.object,placeholders:t,deployedBytecodeSize:en(o.deployedBytecode.object)}}import{spliceHex as rn}from"@latticexyz/common";import{getCreate2Address as nn}from"viem";function H(e,o){return function(r,n){let s=e;for(let a of o){let i=n.find(c=>c.path===a.path&&c.name===a.name);if(!i)throw new Error(`Could not find library for bytecode placeholder ${a.path}:${a.name}`);s=rn(s,a.start,a.length,i.prepareDeploy(r,n).address)}return{bytecode:s,address:nn({from:r,bytecode:s,salt:C})}}}var de=ie(pn);async function uo({client:e,deployerAddress:o,libraries:t,worldDeploy:r,tags:n,valueToHex:s=ln}){let a=(await Promise.all(n.map(async c=>{let{value:l}=await mo({client:e,worldDeploy:r,table:cn.tables.metadata__ResourceTag,key:{resource:c.resourceId,tag:fo(c.tag,{size:32})}});if(l!==s(c.value))return c}))).filter(yo);if(a.length===0)return[];let i=await se({client:e,deployerAddress:o,worldDeploy:r,libraries:t,modules:[{optional:!0,name:"MetadataModule",installAsRoot:!1,installData:"0x",prepareDeploy:H(de.bytecode,de.placeholders),deployedBytecodeSize:de.deployedBytecodeSize,abi:de.abi}]});return await P({client:e,hashes:i,debugLabel:"metadata module installation"}),m("setting",a.length,"resource tags"),(await Promise.all(a.map(async c=>{let l=an(c.resourceId),f=`${l.type}:${l.namespace}:${l.name}`;m(`tagging ${f} with ${c.tag}: ${JSON.stringify(c.value)}`);try{return await dn(e,{chain:e.chain??null,address:r.address,abi:mn,functionName:"metadata__setResourceTag",args:[c.resourceId,fo(c.tag,{size:32}),s(c.value)]})}catch(d){m(`failed to set resource tag for ${f}, skipping
|
14
|
+
${d instanceof sn?d.shortMessage:d}`)}}))).filter(yo)}import{concatHex as fn,encodeDeployData as yn,getCreate2Address as un,isHex as bo}from"viem";import{waitForTransactionReceipt as gn}from"viem/actions";import{resourceToHex as bn,sendTransaction as hn,writeContract as go}from"@latticexyz/common";function xe(e,o){let t=o.find(r=>r.sourcePath===e.sourcePath&&r.name===e.name);if(!t)throw new Error(`Could not find referenced artifact at "${e.sourcePath}:${e.name}".`);return t}function ho(e,o){return e.bytecode.filter(t=>!bo(t)).flatMap(t=>ho(xe(t,o),o))}function we(e,o,t){return fn(o.bytecode.map(r=>bo(r)?r:un({from:e,salt:C,bytecode:we(e,xe(r,t),t)})))}async function wo({client:e,deployerAddress:o,artifacts:t,customWorld:r}){let n=j(o);await T({client:e,deployerAddress:o,contracts:Object.values(n)});let s=xe(r,t),a=ho(s,t);a.length&&(m(`deploying ${a.length} world dependencies`),await T({client:e,deployerAddress:o,contracts:a.map(d=>we(o,d,t)).reverse().map(d=>({bytecode:d}))})),m("deploying custom world");let i=await hn(e,{chain:e.chain??null,data:yn({abi:s.abi,args:[],bytecode:we(o,s,t)})});m("waiting for custom world deploy");let c=await gn(e,{hash:i});if(c.status!=="success")throw console.error("world deploy failed",c),new Error("world deploy failed");let l=$(c.logs);m("deployed custom world to",l.address,"at block",l.deployBlock);let f=await Promise.all([go(e,{chain:e.chain??null,address:l.address,abi:x,functionName:"initialize",args:[n.InitModule.address]}),go(e,{chain:e.chain??null,address:l.address,abi:x,functionName:"transferOwnership",args:[bn({type:"namespace",namespace:"",name:""}),e.account.address]})]);return await P({client:e,hashes:f,debugLabel:"world init"}),{...l,stateBlock:l.deployBlock}}import{uniqueBy as vn}from"@latticexyz/common/utils";async function xo({config:e,client:o,tables:t,systems:r,libraries:n,modules:s=[],artifacts:a,salt:i,worldAddress:c,deployerAddress:l}){let f=l??await He(o);await te(o,f,e.deploy.upgradeableWorldImplementation),await T({client:o,deployerAddress:f,contracts:[...n.map(u=>({bytecode:u.prepareDeploy(f,n).bytecode,deployedBytecodeSize:u.deployedBytecodeSize,debugLabel:`${u.path}:${u.name} library`})),...r.map(u=>({bytecode:u.prepareDeploy(f,n).bytecode,deployedBytecodeSize:u.deployedBytecodeSize,debugLabel:`${Cn(u)} system`})),...s.map(u=>({bytecode:u.prepareDeploy(f,n).bytecode,deployedBytecodeSize:u.deployedBytecodeSize,debugLabel:`${u.name} module`}))]});let d=c?await no(o,c):e.deploy.customWorld?await wo({client:o,deployerAddress:f,artifacts:a,customWorld:e.deploy.customWorld}):await Ke(o,f,i??`0x${An(32).toString("hex")}`,e.deploy.upgradeableWorldImplementation);if(!Re.includes(d.storeVersion))throw new Error(`Unsupported Store version: ${d.storeVersion}`);if(!je.includes(d.worldVersion))throw new Error(`Unsupported World version: ${d.worldVersion}`);let y=await co({client:o,worldDeploy:d,resourceIds:[...t.map(({tableId:u})=>u),...r.map(({systemId:u})=>u)]});await P({client:o,hashes:y,debugLabel:"namespace registrations"});let b=await Xe({client:o,worldDeploy:d,tables:t}),w=await to({client:o,deployerAddress:f,libraries:n,worldDeploy:d,systems:r});await P({client:o,hashes:[...b,...w],debugLabel:"table and system registrations"});let v=await so({client:o,worldDeploy:d,functions:r.flatMap(u=>u.worldFunctions)}),k=await se({client:o,deployerAddress:f,libraries:n,worldDeploy:d,modules:s}),g=vn([...t,...r].filter(({namespace:u,namespaceLabel:S})=>S!==u).map(({namespace:u,namespaceLabel:S})=>({resourceId:xn({type:"namespace",namespace:u,name:""}),tag:"label",value:S})),u=>u.resourceId),A=t.filter(u=>u.label!==u.name).map(({tableId:u,label:S})=>({resourceId:u,tag:"label",value:S})),p=r.flatMap(({name:u,systemId:S,label:Te,abi:qo,worldAbi:Yo})=>[...Te!==u?[{resourceId:S,tag:"label",value:Te}]:[],{resourceId:S,tag:"abi",value:qo.join(`
|
15
|
+
`)},{resourceId:S,tag:"worldAbi",value:Yo.join(`
|
16
|
+
`)}]),h=await uo({client:o,deployerAddress:f,libraries:n,worldDeploy:d,tags:[...g,...A,...p],valueToHex:wn});return await P({client:o,hashes:[...v,...k,...h],debugLabel:"remaining transactions"}),m("deploy complete"),d}import{createWalletClient as Xn,http as es,isHex as os}from"viem";import{privateKeyToAccount as ts}from"viem/accounts";import{loadConfig as rs,resolveConfigPath as ns}from"@latticexyz/config/node";import{getOutDirectory as ss,getRpcUrl as as}from"@latticexyz/common/foundry";import z from"chalk";import{MUDError as Ae}from"@latticexyz/common/errors";import Wn from"path";import{loadSystemsManifest as Bn,resolveSystems as In}from"@latticexyz/world/node";import{isHex as vo,toFunctionSelector as So,toFunctionSignature as Do}from"viem";import{readFileSync as Sn}from"fs";import Dn from"path";import{MUDError as le}from"@latticexyz/common/errors";import{size as Tn}from"viem";function F(e,o,t){let r,n=Dn.join(t,e,o+".json");try{r=JSON.parse(Sn(n,"utf8"))}catch{throw new le(`Error reading file at ${n}`)}let s=r?.bytecode?.object;if(!s)throw new le(`No bytecode found in ${n}`);let a=r?.deployedBytecode?.object;if(!a)throw new le(`No deployed bytecode found in ${n}`);let i=r?.abi;if(!i)throw new le(`No ABI found in ${n}`);let c=ae(r?.bytecode?.linkReferences??{});return{abi:i,bytecode:s,placeholders:c,deployedBytecodeSize:Tn(a)}}import{groupBy as On}from"@latticexyz/common/utils";import{readFileSync as Pn}from"fs";import{globSync as Mn}from"glob";import kn from"toposort";function Co(e,o,t){let r=kn(e.flatMap(n=>t(n).map(s=>[o(n),s])));return[...e].sort((n,s)=>r.indexOf(o(n))-r.indexOf(o(s)))}function Ao(e){let t=Mn(`${e}/**/*.json`,{ignore:"**/*.abi.json"}).sort().map(r=>JSON.parse(Pn(r,"utf8"))).flatMap(r=>{if(!r.metadata)return[];let n=Object.keys(r.metadata.settings.compilationTarget)[0],s=r.metadata.settings.compilationTarget[n],a=r.bytecode.linkReferences;return Object.entries(a).flatMap(([i,c])=>Object.keys(c).map(l=>({path:i,name:l,dependentPath:n,dependentName:s})))});return Co(t,r=>`${r.path}:${r.name}`,r=>[`${r.dependentPath}:${r.dependentName}`])}async function To({rootDir:e,config:o,forgeOutDir:t}){let r=Ao(t).map(d=>{let y=F(Wn.basename(d.path),d.name,t);return{path:d.path,name:d.name,abi:y.abi,prepareDeploy:H(y.bytecode,y.placeholders),deployedBytecodeSize:y.deployedBytecodeSize}}),s=F("System.sol","System",t).abi.filter(d=>d.type==="function").map(Do),a=await In({rootDir:e,config:o}),i=await Bn({rootDir:e,config:o}),c=a.filter(d=>!d.deploy.disabled).map(d=>{let y=i.systems.find(({systemId:g})=>g===d.systemId);if(!y)throw new Error(`System "${d.label}" not found in systems manifest. Run \`mud build\` before trying again.`);let b=F(`${d.label}.sol`,d.label,t),w=d.deploy.registerWorldFunctions?b.abi.filter(g=>g.type==="function").map(Do).filter(g=>!s.includes(g)).map(g=>{let A=d.namespace===""?g:`${d.namespace}__${g}`;return{signature:A,selector:So(A),systemId:d.systemId,systemFunctionSignature:g,systemFunctionSelector:So(g)}}):[],v=d.accessList.filter(g=>vo(g)),k=d.accessList.filter(g=>!vo(g)).map(g=>a.find(p=>p.label===g).systemId);return{...d,allowAll:d.openAccess,allowedAddresses:v,allowedSystemIds:k,prepareDeploy:H(b.bytecode,b.placeholders),deployedBytecodeSize:b.deployedBytecodeSize,worldFunctions:w,abi:y.abi,worldAbi:y.worldAbi}}),l=On(c,d=>d.systemId),f=Array.from(l.values()).filter(d=>d.length>1).flat();if(f.length){let d=f.map(y=>y.name);throw new Error(`Found systems with overlapping system ID: ${d.join(", ")}.
|
17
|
+
|
18
|
+
System IDs are generated from the first 16 bytes of the name, so you may need to rename them to avoid the overlap.`)}return{systems:c,libraries:r}}import{getChainId as is}from"viem/actions";import{existsSync as Hn}from"fs";import Rn from"path";import jn from"chalk";import{getScriptDirectory as $n,forge as En}from"@latticexyz/common/foundry";async function ko(e,o,t,r,n,s){let a=n?.replaceAll("\\","").split(" ")??[],i=Rn.join(await $n(),e+".s.sol");if(!Hn(i)){console.log(`No script at ${i}, skipping post deploy hook`);return}console.log(jn.blue(`Executing post deploy script at ${i}`)),await En(["script",e,"--broadcast","--sig","run(address)",o,"--rpc-url",t,"-vvv",s?"--aws":"",...a],{profile:r})}import{kmsKeyToAccount as ds}from"@latticexyz/common/kms";import Mo from"node:path";import{encodeField as Ln}from"@latticexyz/protocol-parser/internal";import{bytesToHex as Nn}from"viem";import{createRequire as Fn}from"node:module";import{findUp as zn}from"find-up";async function Po({packageJsonPath:e,artifactPath:o}){let t;try{let r=e??await zn("package.json",{cwd:process.cwd()});if(!r)throw new Error("Could not find package.json to import relative to.");t=Fn(r)(o)}catch(r){throw console.error(),console.error("Could not import contract artifact at",o),console.error(),r}return ie(t)}import{resolveWithContext as Vn}from"@latticexyz/world/internal";var Un={KeysWithValueModule:"@latticexyz/world-modules/out/KeysWithValueModule.sol/KeysWithValueModule.json",KeysInTableModule:"@latticexyz/world-modules/out/KeysInTableModule.sol/KeysInTableModule.json",UniqueEntityModule:"@latticexyz/world-modules/out/UniqueEntityModule.sol/UniqueEntityModule.json",Unstable_CallWithSignatureModule:"@latticexyz/world-modules/out/Unstable_CallWithSignatureModule.sol/Unstable_CallWithSignatureModule.json"};async function ce(e,o){return await Promise.all(e.modules.map(async r=>{let n=r.artifactPath;if(!n)if(r.name)n=Un[r.name]??Mo.join(o,`${r.name}.sol`,`${r.name}.json`),console.warn(["","\u26A0\uFE0F Your `mud.config.ts` is using a module with a `name`, but this option is deprecated.","","To resolve this, you can replace this:","",` name: ${JSON.stringify(r.name)}`,"","with this:","",` artifactPath: ${JSON.stringify(n)}`,""].join(`
|
19
|
+
`));else throw new Error("No `artifactPath` provided for module.");let s=Mo.basename(n,".json"),a=await Po({artifactPath:n}),i=r.args.map(c=>Vn(c,{config:e})).map(c=>{let l=c.value instanceof Uint8Array?Nn(c.value):c.value;return Ln(c.type,l)});if(i.length>1)throw new Error(`${s} module should only have 0-1 args, but had ${i.length} args.`);return{name:s,installAsRoot:r.root,installData:i.length===0?"0x":i[0],prepareDeploy:H(a.bytecode,a.placeholders),deployedBytecodeSize:a.deployedBytecodeSize,abi:a.abi}}))}import{findContractArtifacts as ls}from"@latticexyz/world/node";import{getAutomine as _n,getBlock as Wo,setAutomine as Kn,setIntervalMining as Jn}from"viem/actions";import{getAction as J}from"viem/utils";async function Io(e){try{B("Enabling automine");let o=await qn(e);return await Bo(e,{type:"automine"}),{reset:()=>(B("Disabling automine"),Bo(e,o))}}catch(o){return B("Skipping automine"),pe(o),{reset:async()=>{}}}}async function qn(e){let o={mode:"anvil",...e};return await J(o,_n,"getAutomine")({})?{type:"automine"}:{type:"interval",blockTime:await Yn(e)}}async function Bo(e,o){o.type==="automine"?await J(e,Kn,"setAutomine")(!0):await J(e,Jn,"setIntervalMining")({interval:o.blockTime})}async function Yn(e){let o=await J(e,Wo,"getBlock")({blockTag:"latest"}),t=await J(e,Wo,"getBlock")({blockNumber:o.number-1n}),r=o.timestamp-t.timestamp;return Number(r)}var M={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"},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 L(e){let o=e.salt;if(o!=null&&!os(o))throw new Ae("Expected hex string for salt");let t=e.profile??process.env.FOUNDRY_PROFILE,r=await ns(e.configPath),n=await rs(r),s=me.dirname(r);e.printConfig&&console.log(z.green(`
|
20
|
+
Resolved config:
|
21
|
+
`),JSON.stringify(n,null,2));let a=await ss(t),i=e.rpc??await as(t);console.log(z.bgBlue(z.whiteBright(`
|
22
|
+
Deploying MUD contracts${t?" with profile "+t:""} to RPC ${i}
|
23
|
+
`))),e.skipBuild||await G({rootDir:s,config:n,foundryProfile:t});let{systems:c,libraries:l}=await To({rootDir:s,config:n,forgeOutDir:a}),f=await ls({forgeOutDir:a}),d=await ce(n,a),y=Object.values(n.namespaces).flatMap(p=>Object.values(p.tables)).filter(p=>!p.deploy.disabled),b=await(async()=>{if(e.kms){let p=process.env.AWS_KMS_KEY_ID;if(!p)throw new Ae("Missing `AWS_KMS_KEY_ID` environment variable. This is required when using with `--kms` option.");return await ds({keyId:p})}else{let p=process.env.PRIVATE_KEY;if(!p)throw new Ae(`Missing PRIVATE_KEY environment variable.
|
24
|
+
Run 'echo "PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" > .env'
|
25
|
+
in your contracts directory to use the default anvil private key.`);return ts(p)}})(),w=Xn({transport:es(i,{batch:e.rpcBatch?{batchSize:100,wait:1e3}:void 0}),account:b});console.log("Deploying from",w.account.address);let{reset:v}=await Io(w),k=Date.now(),g=await xo({config:n,deployerAddress:e.deployerAddress,salt:o,worldAddress:e.worldAddress,client:w,tables:y,systems:c,libraries:l,modules:d,artifacts:f});(e.worldAddress==null||e.alwaysRunPostDeploy)&&await ko(n.deploy.postDeployScript,g.address,i,t,e.forgeScriptOptions,!!e.kms),await v(),console.log(z.green("Deployment completed in",(Date.now()-k)/1e3,"seconds"));let A={worldAddress:g.address,blockNumber:Number(g.deployBlock)};if(e.saveDeployment){let p=await is(w),h=me.join(n.deploy.deploysDirectory,p.toString());Qn(h,{recursive:!0}),Ce(me.join(h,"latest.json"),JSON.stringify(A,null,2)),Ce(me.join(h,Date.now()+".json"),JSON.stringify(A,null,2));let u=[1337,31337],S=Gn(n.deploy.worldsFile)?JSON.parse(Zn(n.deploy.worldsFile,"utf-8")):{};S[p]={address:A.worldAddress,blockNumber:u.includes(p)?void 0:A.blockNumber},Ce(n.deploy.worldsFile,JSON.stringify(S,null,2)),console.log(z.bgGreen(z.whiteBright(`
|
26
|
+
Deployment result (written to ${n.deploy.worldsFile} and ${h}):
|
27
|
+
`)))}return console.log(A),g}var cs={command:"deploy",describe:"Deploy MUD contracts",builder(e){return e.options(M)},async handler(e){try{await L(e)}catch(o){Y(o),process.exit(1)}process.exit(0)}},Oo=cs;import ms from"node:path";import{loadConfig as ps,resolveConfigPath as fs}from"@latticexyz/config/node";import{worldgen as ys}from"@latticexyz/world/node";var us={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 gs(e),process.exit(0)}};async function gs(e){let o=await fs(e.configPath),t=await ps(o),r=ms.dirname(o);await ys({rootDir:r,config:t,clean:e.clean})}var Ho=us;import q from"chalk";import{readFileSync as Cs,writeFileSync as As}from"fs";import Se from"path";import{MUDError as N}from"@latticexyz/common/errors";var Ro={name:"@latticexyz/cli",version:"2.2.3",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"},typesVersions:{"*":{index:["./dist/index.d.ts"]}},bin:{mud:"./bin/mud.js"},files:["bin","dist"],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":"shx rm -rf dist","clean:test-tables":"shx rm -rf src/**/codegen",dev:"tsup --watch",lint:"eslint . --ext .ts",test:"tsc --noEmit && forge test","test:ci":"pnpm run test"},dependencies:{"@ark/util":"catalog:","@aws-sdk/client-kms":"^3.556.0","@latticexyz/abi-ts":"workspace:*","@latticexyz/common":"workspace:*","@latticexyz/config":"workspace:*","@latticexyz/gas-report":"workspace:*","@latticexyz/protocol-parser":"workspace:*","@latticexyz/schema-type":"workspace:*","@latticexyz/store":"workspace:*","@latticexyz/utils":"workspace:*","@latticexyz/world":"workspace:*","@latticexyz/world-module-metadata":"workspace:*",abitype:"catalog:","asn1.js":"^5.4.1",chalk:"^5.0.1",chokidar:"^3.5.3",debug:"^4.3.4",dotenv:"^16.0.3",execa:"^7.0.0","find-up":"^6.3.0",glob:"^10.4.2",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:"catalog:",yargs:"^17.7.1",zod:"3.23.8","zod-validation-error":"^1.3.0"},devDependencies:{"@types/debug":"^4.1.7","@types/ejs":"^3.1.1","@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{globSync as vs}from"glob";import{ZodError as hs,z as jo}from"zod";var ws=jo.object({MUD_PACKAGES:jo.string().transform(e=>JSON.parse(e))});function xs(){try{return ws.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/explorer":{"localPath":"packages/explorer"},"@latticexyz/faucet":{"localPath":"packages/faucet"},"@latticexyz/gas-report":{"localPath":"packages/gas-report"},"@latticexyz/protocol-parser":{"localPath":"packages/protocol-parser"},"@latticexyz/react":{"localPath":"packages/react"},"@latticexyz/recs":{"localPath":"packages/recs"},"@latticexyz/schema-type":{"localPath":"packages/schema-type"},"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-module-metadata":{"localPath":"packages/world-module-metadata"},"@latticexyz/world-modules":{"localPath":"packages/world-modules"},"@latticexyz/world":{"localPath":"packages/world"}}'})}catch(e){if(e instanceof hs){let{...o}=e.format();console.error(`
|
28
|
+
Missing or invalid environment variables:
|
29
|
+
|
30
|
+
${Object.keys(o).join(`
|
31
|
+
`)}
|
32
|
+
`),process.exit(1)}throw e}}var ve=xs().MUD_PACKAGES;var Ss={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.link||(e.mudVersion=await Ds(e));let r=vs("**/package.json").sort().filter(n=>!n.includes("node_modules"));for(let n of r)Ts(n,e)}catch(o){Y(o)}finally{process.exit(0)}}};async function Ds(e){e.mudVersion==="canary"&&(e.tag="main");let o;try{console.log(q.blue("Fetching available versions")),o=await(await fetch(`https://registry.npmjs.org/${Ro.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(q.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(q.green(`Version from commit ${e.commit}: ${r}`)),r}return e.mudVersion}function Ts(e,o){let{link:t}=o,{mudVersion:r}=o,n=ks(e),s=Object.keys(ve),a={};for(let l in n.dependencies)s.includes(l)&&(a[l]=n.dependencies[l]);let i={};for(let l in n.devDependencies)s.includes(l)&&(i[l]=n.devDependencies[l]);for(let l in n.dependencies)s.includes(l)&&(n.dependencies[l]=c(l,"dependencies"));for(let l in n.devDependencies)s.includes(l)&&(n.devDependencies[l]=c(l,"devDependencies"));return As(e,JSON.stringify(n,null,2)+`
|
33
|
+
`),console.log(`Updating ${e}`),$o(a,n.dependencies),$o(i,n.devDependencies),n;function c(l,f){return t&&(r=Ps(e,t,l)),r||n[f][l]}}function ks(e){try{let o=Cs(e,"utf8");return JSON.parse(o)}catch{throw new N("Could not read JSON at "+e)}}function $o(e,o){for(let t in e)e[t]!==o[t]&&console.log(`${t}: ${q.red(e[t])} -> ${q.green(o[t])}`)}function Ps(e,o,t){let r=Se.relative(Se.dirname(e),process.cwd());return"link:"+Se.join(r,o,ve[t].localPath)}var Eo=Ss;import{anvil as Ms,forge as Ws,getRpcUrl as Bs}from"@latticexyz/common/foundry";import Is from"chalk";var Os={...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"}},Hs={command:"test",describe:"Run tests in MUD contracts",builder(e){return e.options(Os)},async handler(e){if(!e.worldAddress){let n=["--block-base-fee-per-gas","0","--port",String(e.port)];Ms(n)}let o=e.worldAddress?await Bs(e.profile):`http://127.0.0.1:${e.port}`,t=e.worldAddress??(await L({...e,saveDeployment:!1,rpc:o})).address;console.log(Is.blue("World address",t));let r=e.forgeOptions?.replaceAll("\\","").split(" ")??[];try{await Ws(["test","--fork-url",o,...r],{profile:e.profile,env:{WORLD_ADDRESS:t}}),process.exit(0)}catch(n){console.error(n),process.exit(1)}}},Fo=Hs;import Rs from"node:path";import zo from"node:fs";import{loadConfig as js,resolveConfigPath as $s}from"@latticexyz/config/node";import{MUDError as Lo}from"@latticexyz/common/errors";import{cast as Es,getRpcUrl as Fs}from"@latticexyz/common/foundry";import zs from"@latticexyz/world/mud.config";import{createClient as Ls,http as Ns}from"viem";import{getChainId as Vs,readContract as Us}from"viem/actions";import{resolveSystems as _s}from"@latticexyz/world/node";var Ks=zs.namespaces.world.tables.Systems.tableId;function Js(e,o){if(!zo.existsSync(e))throw new Lo(`Missing expected worlds.json file at "${e}"`);let t=JSON.parse(zo.readFileSync(e,"utf-8"));if(!t[o])throw new Lo(`Missing chain ID ${o} in "${e}"`);return t[o].address}var qs={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"},rpc:{type:"string",description:"json rpc endpoint. Defaults to foundry's configured eth_rpc_url"}})},async handler(e){let o=await $s(e.configPath),t=Rs.dirname(o),r=e.profile??process.env.FOUNDRY_PROFILE,n=e.rpc??await Fs(r),s=await js(o),a=Ls({transport:Ns(n)}),i=await Vs(a),c=e.worldAddress??Js(s.deploy.worldsFile,i),l=await _s({rootDir:t,config:s}),f=await Promise.all(l.map(async y=>({label:y.label,address:await Us(a,{abi:x,address:c,functionName:"getField",args:[Ks,[y.systemId],0]})}))),d=await Es(["run","--label",`${c}:World`,...f.map(({label:y,address:b})=>["--label",`${b}:${y}`]).flat(),`${e.tx}`]);console.log(d),process.exit(0)}},No=qs;import{anvil as Ys,getScriptDirectory as Gs,getSrcDirectory as Qs}from"@latticexyz/common/foundry";import O from"chalk";import Zs from"chokidar";import{loadConfig as Xs,resolveConfigPath as ea}from"@latticexyz/config/node";import oa from"path";import{homedir as ta}from"os";import{rmSync as ra}from"fs";import{BehaviorSubject as na,debounceTime as sa,exhaustMap as aa,filter as ia}from"rxjs";import{isDefined as da}from"@latticexyz/common/utils";var la={rpc:M.rpc,configPath:M.configPath,alwaysRunPostDeploy:M.alwaysRunPostDeploy,forgeScriptOptions:M.forgeScriptOptions,worldAddress:M.worldAddress},ca={command:"dev-contracts",describe:"Start a development server for MUD contracts",builder(e){return e.options(la)},async handler(e){let o=e.rpc,t=e.configPath??await ea(e.configPath),r=await Qs(),n=await Gs(),s=await Xs(t);if(!e.rpc){console.log(O.gray("Cleaning devnode cache"));let l=ta();ra(oa.join(l,".foundry","anvil","tmp"),{recursive:!0,force:!0}),Ys(["--block-time","1","--block-base-fee-per-gas","0"]),o="http://127.0.0.1:8545"}let a=new na(Date.now());Zs.watch([t,r,n],{ignoreInitial:!0}).on("all",async(l,f)=>{f.includes(t)&&(console.log(O.blue("Config changed, queuing deploy\u2026")),a.next(Date.now())),(f.includes(r)||f.includes(n))&&(f.includes(s.codegen.outputDirectory)||(console.log(O.blue("Contracts changed, queuing deploy\u2026")),a.next(Date.now())))});let i=e.worldAddress;a.pipe(sa(200),aa(async l=>{i&&console.log(O.blue("Rebuilding and upgrading world\u2026"));try{let f=await L({...e,configPath:t,rpc:o,rpcBatch:!1,skipBuild:!1,printConfig:!1,profile:void 0,saveDeployment:!0,deployerAddress:void 0,worldAddress:i,salt:"0x",kms:void 0});return i=f.address,l<a.value?a.next(a.value):console.log(O.gray(`
|
34
|
+
Waiting for file changes\u2026
|
35
|
+
`)),f}catch(f){console.error(O.bgRed(O.whiteBright(`
|
36
|
+
Error while attempting deploy
|
37
|
+
`))),console.error(f),console.log(O.gray(`
|
38
|
+
Waiting for file changes\u2026
|
39
|
+
`))}}),ia(da)).subscribe()}},Vo=ca;import{getCreate2Address as Uo,sliceHex as pa,zeroHash as fa}from"viem";import{forge as ma}from"@latticexyz/common/foundry";async function R(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 ma(o,{cwd:e.cwd})}import ya from"p-queue";import{MUDError as ua}from"@latticexyz/common/errors";import{getStorageAt as ga}from"viem/actions";import{execa as De}from"execa";var ba="0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc";async function _o({client:e,rpc:o,systems:t,modules:r,worldAddress:n,deployerAddress:s,verifier:a,verifierUrl:i}){let c=s??await Z(e);if(!c)throw new ua("No deployer address provided or found.");let l=await ga(e,{address:n,slot:ba}),f=l&&l!==fa,d=new ya({concurrency:4});if(t.map(({name:y,bytecode:b})=>d.add(()=>R({name:y,rpc:o,verifier:a,verifierUrl:i,address:Uo({from:c,bytecode:b,salt:C})}).catch(w=>{console.error(`Error verifying system contract ${y}:`,w)}))),a==="sourcify")if(await De("npm",["install"],{cwd:"node_modules/@latticexyz/store"}),await De("npm",["install"],{cwd:"node_modules/@latticexyz/world"}),await De("npm",["install"],{cwd:"node_modules/@latticexyz/world-modules"}),Object.entries(f?oe(c):ee(c)).map(([y,{bytecode:b}])=>d.add(()=>R({cwd:"node_modules/@latticexyz/world",name:y,rpc:o,verifier:a,verifierUrl:i,address:Uo({from:c,bytecode:b,salt:C})}).catch(w=>{console.error(`Error verifying world factory contract ${y}:`,w)}))),r.map(({name:y,prepareDeploy:b})=>{let{address:w}=b(c,[]);return d.add(()=>R({cwd:"node_modules/@latticexyz/world-modules",name:y,rpc:o,verifier:a,verifierUrl:i,address:w}).catch(v=>{console.error(`Error verifying module contract ${y}:`,v)}))}),f){let y=pa(l,-20);d.add(()=>R({cwd:"node_modules/@latticexyz/world",name:"WorldProxy",rpc:o,verifier:a,verifierUrl:i,address:n}).catch(b=>{console.error("Error verifying WorldProxy contract:",b)})),d.add(()=>R({cwd:"node_modules/@latticexyz/world",name:"World",rpc:o,verifier:a,verifierUrl:i,address:y}).catch(b=>{console.error("Error verifying World contract:",b)}))}else d.add(()=>R({cwd:"node_modules/@latticexyz/world",name:"World",rpc:o,verifier:a,verifierUrl:i,address:n}).catch(y=>{console.error("Error verifying World contract:",y)}));else console.log(""),console.log(`Note: MUD is currently unable to verify store, world, and world-modules contracts with ${a}. We are planning to expand support in a future version.`),console.log("")}import{loadConfig as ha,resolveConfigPath as wa}from"@latticexyz/config/node";import{resolveSystems as xa}from"@latticexyz/world/node";import{getOutDirectory as Ca,getRpcUrl as Aa}from"@latticexyz/common/foundry";import{createWalletClient as va,http as Sa}from"viem";import Ko from"chalk";import Da from"node:path";var Ta={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)"},verifier:{type:"string",desc:"The verifier to use. Defaults to blockscout",default:"blockscout"},verifierUrl:{type:"string",desc:"The verification provider."}},ka={command:"verify",describe:"Verify contracts",builder(e){return e.options(Ta)},async handler(e){let o=e.profile??process.env.FOUNDRY_PROFILE,t=await wa(e.configPath),r=Da.dirname(t),n=await ha(t),s=await Ca(o),a=e.rpc??await Aa(o);console.log(Ko.bgBlue(Ko.whiteBright(`
|
40
|
+
Verifying MUD contracts${o?" with profile "+o:""} to RPC ${a}
|
41
|
+
`)));let i=va({transport:Sa(a,{batch:e.rpcBatch?{batchSize:100,wait:1e3}:void 0})}),l=(await xa({rootDir:r,config:n})).map(d=>{let y=F(`${d.name}.sol`,d.name,s);return{name:d.name,bytecode:y.bytecode}}),f=await ce(n,s);await _o({client:i,rpc:a,systems:l,modules:f,deployerAddress:e.deployerAddress,worldAddress:e.worldAddress,verifier:e.verifier,verifierUrl:e.verifierUrl})}},Jo=ka;var cu=[ke,Oo,Pe,Pa,Me,We,Ho,Eo,Fo,No,Vo,Ma,Jo];export{cu as commands};
|
42
|
+
//# sourceMappingURL=commands-UEYQ6ADX.js.map
|