midnight-wallet-cli 0.6.0-rc.8 → 0.6.0-rc.9
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/mcp-server.js +385 -385
- package/dist/wallet.js +375 -369
- package/docs/SKILL.md +2 -2
- package/package.json +2 -1
package/dist/mcp-server.js
CHANGED
|
@@ -1,52 +1,52 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{createRequire as
|
|
2
|
+
import{createRequire as Fm}from"node:module";var $m=Object.defineProperty;var Om=(e)=>e;function Mm(e,t){this[e]=Om.bind(null,t)}var ve=(e,t)=>{for(var r in t)$m(e,r,{get:t[r],enumerable:!0,configurable:!0,set:Mm.bind(t,r)})};var E=(e,t,r)=>()=>{if(e)try{t=e(e=0)}catch(n){r=[n]}if(r)throw r[0];return t};var La=Fm(import.meta.url);function Ba(e){return e instanceof R}var R;var ue=E(()=>{R=class R extends Error{constructor(e){super(e);this.name="UsageError",Object.setPrototypeOf(this,R.prototype)}}});function C(e,t){let r=e.flags[t];if(r===void 0)return;if(r===!0)throw new R(`--${t} needs a value, e.g. --${t} <value>`);return r}function D(e,t){return t in e.flags}function ze(e){return D(e,"verbose")}function Ct(e){return D(e,Wn)&&!D(e,qr)}function ur(e){if(D(e,"no-cache"))throw Error(`--no-cache is not supported on write commands (transfer, airdrop, dust register, serve).
|
|
3
3
|
`+`Writes always use the cache — the SDK's fresh-sync is too slow on hosted networks.
|
|
4
|
-
`+"To reset: midnight cache clear --wallet <name> --network <name>")}function zr(e,t,r){let n=
|
|
5
|
-
`;if(
|
|
4
|
+
`+"To reset: midnight cache clear --wallet <name> --network <name>")}function zr(e,t,r){let n=C(e,t);if(n===void 0)throw Error(`Missing required flag: --${t} <${r}>`);return n}var Wn="_minimal",qr="_full";var re=E(()=>{ue()});function xo(e){Co=e}function I(e){let t=JSON.stringify(e)+`
|
|
5
|
+
`;if(Co)Co(t);else process.stdout.write(t)}var Co=null;function Hn(e){if(Ba(e))return{exitCode:Wa,errorCode:q.INVALID_ARGS};let t=e.code;if(typeof t==="string"&&Bm.has(t))return{exitCode:jn,errorCode:t};if(t===q.UNSUPPORTED_NODE)return{exitCode:Eo,errorCode:q.UNSUPPORTED_NODE};if(t===q.NO_ACCOUNT)return{exitCode:Eo,errorCode:q.NO_ACCOUNT};if(t===q.DUST_GENERATING)return{exitCode:Ao,errorCode:q.DUST_GENERATING};if(t===q.CHAIN_CLOCK_BEHIND)return{exitCode:jn,errorCode:q.CHAIN_CLOCK_BEHIND};let r=(e.message??"").toLowerCase();if(r.includes("operation cancelled")||r.includes("operation aborted")||r==="cancelled"||r==="aborted")return{exitCode:Lm,errorCode:q.CANCELLED};if(r.includes("wallet file not found")||r.includes("wallet")&&r.includes("not found"))return{exitCode:Um,errorCode:q.WALLET_NOT_FOUND};if(r.includes("missing required flag")||r.includes("missing amount")||r.includes("missing recipient")||r.includes("missing config key")||r.includes("missing or invalid subcommand")||r.includes("unknown command")||r.includes("cannot specify both")||r.includes("invalid bip-39")||r.includes("seed must be")||r.includes("key index must be")||r.includes("shielded balances are private")||r.includes("shielded is unavailable")||r.includes("belongs to")&&r.includes("--network is")||r.includes("usage:"))return{exitCode:Wa,errorCode:q.INVALID_ARGS};if(r.includes("proof")&&r.includes("timeout"))return{exitCode:pr,errorCode:q.PROOF_TIMEOUT};if(r.includes("stale utxo")||r.includes("error code 115")||r.includes("errorcode: 115"))return{exitCode:pr,errorCode:q.STALE_UTXO};if(r.includes("error 170")||r.includes("errorcode: 170")||r.includes("invaliddustspendproof"))return{exitCode:pr,errorCode:q.INVALID_DUST_PROOF};if(r.includes("stale cache")||r.includes("chain reset")||r.includes("chainid mismatch")||r.includes("applied > highest")||r.includes("inserted non-linearly"))return{exitCode:pr,errorCode:q.STALE_CACHE};if(r.includes("failed to prove"))return{exitCode:pr,errorCode:q.PROOF_FAILURE};if(r.includes("wallet sync timed out")||r.includes("sync timed out")||r.includes("timed out waiting for dust")||r.includes("did not respond within")||r.includes("did not produce a block")||r.includes("did not report funds"))return{exitCode:jn,errorCode:q.SYNC_TIMEOUT};if(r.includes("no dust")||r.includes("dust")&&(r.includes("required")||r.includes("available")||r.includes("insufficient")))return{exitCode:Ao,errorCode:q.DUST_REQUIRED};if(r.includes("insufficient")||r.includes("not enough"))return{exitCode:Ao,errorCode:q.INSUFFICIENT_BALANCE};if(r.includes("rejected")||r.includes("transaction failed"))return{exitCode:pr,errorCode:q.TX_REJECTED};if(r.includes("econnrefused")||r.includes("enotfound")||r.includes("etimedout")||r.includes("websocket")||r.includes("connection refused")||r.includes("request to ")&&r.includes(" failed, reason:")||r.includes("network")&&r.includes("error"))return{exitCode:jn,errorCode:q.NETWORK_ERROR};return{exitCode:Eo,errorCode:q.UNKNOWN}}var Eo=1,Wa=2,Um=3,jn=4,Ao=5,pr=6,Lm=7,q,Bm;var To=E(()=>{ue();q={INVALID_ARGS:"INVALID_ARGS",WALLET_NOT_FOUND:"WALLET_NOT_FOUND",NETWORK_ERROR:"NETWORK_ERROR",INSUFFICIENT_BALANCE:"INSUFFICIENT_BALANCE",TX_REJECTED:"TX_REJECTED",STALE_UTXO:"STALE_UTXO",STALE_CACHE:"STALE_CACHE",PROOF_TIMEOUT:"PROOF_TIMEOUT",PROOF_FAILURE:"PROOF_FAILURE",INVALID_DUST_PROOF:"INVALID_DUST_PROOF",DUST_REQUIRED:"DUST_REQUIRED",DUST_GENERATING:"DUST_GENERATING",CHAIN_CLOCK_BEHIND:"CHAIN_CLOCK_BEHIND",SYNC_TIMEOUT:"SYNC_TIMEOUT",CANCELLED:"CANCELLED",UNSUPPORTED_LEDGER:"UNSUPPORTED_LEDGER",LOCALNET_UNAVAILABLE:"LOCALNET_UNAVAILABLE",LOCAL_STACK_UNREACHABLE:"LOCAL_STACK_UNREACHABLE",AMBIGUOUS_LOCAL_STACKS:"AMBIGUOUS_LOCAL_STACKS",UNSUPPORTED_NODE:"UNSUPPORTED_NODE",NO_ACCOUNT:"NO_ACCOUNT",BLOCKFROST_PROJECT_ID_REQUIRED:"BLOCKFROST_PROJECT_ID_REQUIRED",BLOCKFROST_PROJECT_ID_REJECTED:"BLOCKFROST_PROJECT_ID_REJECTED",BLOCKFROST_LIMIT_REACHED:"BLOCKFROST_LIMIT_REACHED",ENDPOINT_SHUT_DOWN:"ENDPOINT_SHUT_DOWN",UNKNOWN:"UNKNOWN"},Bm=new Set([q.UNSUPPORTED_LEDGER,q.LOCALNET_UNAVAILABLE,q.LOCAL_STACK_UNREACHABLE,q.AMBIGUOUS_LOCAL_STACKS,q.BLOCKFROST_PROJECT_ID_REQUIRED,q.BLOCKFROST_PROJECT_ID_REJECTED,q.BLOCKFROST_LIMIT_REACHED,q.ENDPOINT_SHUT_DOWN])});function Wt(e){if(!e||e!==e.trim())return!1;if(/[\/\\]/.test(e))return!1;if(e.endsWith(".json"))return!1;if(e==="."||e==="..")return!1;if(/[\x00-\x1f]/.test(e))return!1;return!0}var ut="0000000000000000000000000000000000000000000000000000000000000001",Lt="0000000000000000000000000000000000000000000000000000000000000000",Kn="/api/v4/graphql",Yr="/api/v4/graphql/ws",Ro=6,Bt=1e6,Ga=300000000000000n,Ka=5,Xr=900000000000000n,Ja=5000000000n,Va=8267n,qa=10800n,za=300000,Jn=30000,Ya=1e4,Do=120000,Vn=300000,Io=60000,Xa=16384,Za=0.7,Qa=512,qn=10,ec=3,tc=600000,_o=15000,rc=115,te=".midnight",zn="wallet.json",nc="config.json",be=448,Te=384,Po="localnet",$o=2,Oe="cache",Yn="wallets",Oo="default",Mo=10,Zr=3000,sc=120000,Qr=9932,Xn="https://midnight-comp-tracker.vercel.app";function Qn(e){return Object.hasOwn(pt,e)}function fr(){return Object.keys(pt)}function mr(e){return fr().find((t)=>e.startsWith(pt[t].prefix))}function es(e){let t=e.trim(),r=/^[A-Za-z0-9]+$/.test(t)?mr(t):void 0;if(r===void 0){let n=fr().map((s)=>`"${pt[s].prefix}" (${s})`).join(", ");throw new R(`That is not a Blockfrost project id mn can use: it should start with ${n}. Project ids are per network; create a project for the Midnight network you need at ${Zn}.`)}return{projectId:t,network:r}}function Bo(e,t){let{host:r}=pt[e],n=t===void 0?"":`?${en}=${t}`;return{indexer:`https://${r}/api/v0${n}`,indexerWS:`wss://${r}/api/v0/ws${n}`,node:`wss://rpc.${r}${n}`}}function ts(e){try{return new URL(e)}catch{return}}function lc(e){return fr().find((t)=>{let{host:r}=pt[t];return e.hostname===r||e.hostname===`rpc.${r}`})}function Wo(e){let t=ts(e)?.hostname;return t!==void 0&&(t==="blockfrost.io"||t.endsWith(".blockfrost.io"))}function uc(e){return e instanceof jt||e instanceof rs||e instanceof ns||e instanceof tn}function ke(e){let t=ts(e);if(t===void 0)return;if(Object.hasOwn(dc,t.hostname))throw new tn(e);let r=lc(t);if(r!==void 0&&!t.searchParams.get(en))throw new jt(r)}function Ht(e,t){if(t===410)return new tn(e);let r=ts(e);if(r===void 0||!Wo(e))return;let n=lc(r)??"this network";if(t===403)return r.searchParams.get(en)?new rs(n):new jt(n);if(t===402||t===429)return new ns(t);return}function gr(e,t){let r=/Unexpected server response: (\d{3})/.exec(t instanceof Error?t.message:String(t))?.[1];return r===void 0?void 0:Ht(e,Number(r))}function ss(e){return e.replace(Xm,`$1${cc}`).replace(Zm,`$1${cc}`)}function jo(e){return e.includes(`${en}=`)||Object.values(pt).some(({prefix:t})=>e.includes(t))}function pc(e){let t=mr(e);return`${t===void 0?"":pt[t].prefix}…${e.slice(-4)}`}var pt,en="project_id",Zn="https://blockfrost.io",Lo="midnight config set blockfrost-project-id <project id>",dc,jt,rs,ns,tn,Xm,Zm,cc="***";var Me=E(()=>{ue();pt={preprod:{host:"midnight-preprod.blockfrost.io",prefix:"nightpreprod"}},dc={"indexer.preprod.midnight.network":"2026-10-09"};jt=class jt extends Error{code="BLOCKFROST_PROJECT_ID_REQUIRED";constructor(e){super(`${e}'s indexer and node are served by Blockfrost, which needs your own project id on every request, and none is set.
|
|
6
6
|
Create a project for Midnight ${e} at ${Zn} and set its id once:
|
|
7
7
|
${Lo}`);this.name="BlockfrostProjectIdRequiredError",Object.setPrototypeOf(this,jt.prototype)}};rs=class rs extends Error{code="BLOCKFROST_PROJECT_ID_REJECTED";constructor(e){super(`Blockfrost refused the project id set for ${e} (HTTP 403).
|
|
8
8
|
Check it at ${Zn}: it must be the id of a Midnight ${e} project. Then set it again:
|
|
9
9
|
${Lo}`);this.name="BlockfrostProjectIdRejectedError",Object.setPrototypeOf(this,rs.prototype)}};ns=class ns extends Error{code="BLOCKFROST_LIMIT_REACHED";constructor(e){super(`Blockfrost answered HTTP ${e}, which its API uses for `+(e===402?"a project that has used up its plan's daily requests":"too many requests in a short time")+`.
|
|
10
|
-
Wait and run the command again, or see the project's usage and plan at ${Zn}.`);this.name="BlockfrostLimitError",Object.setPrototypeOf(this,ns.prototype)}};tn=class tn extends Error{code="ENDPOINT_SHUT_DOWN";constructor(e){let t=ts(e)?.hostname??ss(e),r=
|
|
10
|
+
Wait and run the command again, or see the project's usage and plan at ${Zn}.`);this.name="BlockfrostLimitError",Object.setPrototypeOf(this,ns.prototype)}};tn=class tn extends Error{code="ENDPOINT_SHUT_DOWN";constructor(e){let t=ts(e)?.hostname??ss(e),r=dc[t];super(`${t} was shut down${r===void 0?"":` on ${r}`}: it no longer serves the network.
|
|
11
11
|
It is set as an endpoint, by a flag or with "midnight config set". Remove it (midnight config unset indexer-ws, or node) to use the network's current endpoints; preprod's are Blockfrost's and need a project id:
|
|
12
|
-
${Lo}`);this.name="EndpointShutDownError",Object.setPrototypeOf(this,tn.prototype)}};
|
|
13
|
-
`)){if(!n)continue;let[s="",o=""]=n.split("|"),i=(a)=>[...o.matchAll(new RegExp(`:(\\d+)->${a}/tcp`,"g"))].map((c)=>parseInt(c[1],10));if(s.includes("indexer"))i(8088).forEach((a)=>t.indexer.add(a));if(s.includes("midnight-node"))i(9944).forEach((a)=>t.node.add(a));if(s.includes("proof-server"))i(6300).forEach((a)=>t.proofServer.add(a))}let r=(n)=>[...n].sort((s,o)=>s-o);return{node:r(t.node),indexer:r(t.indexer),proofServer:r(t.proofServer)}}function
|
|
12
|
+
${Lo}`);this.name="EndpointShutDownError",Object.setPrototypeOf(this,tn.prototype)}};Xm=new RegExp(`([?&]${en}=)[A-Za-z0-9_.~%-]+`,"g"),Zm=new RegExp(`\\b(${Object.values(pt).map(({prefix:e})=>e).join("|")})[A-Za-z0-9]{12,}\\b`,"g")});import{execSync as eg}from"child_process";import{ProtocolVersion as tg}from"@midnightntwrk/wallet-sdk";function De(e){return hc.includes(e)}function Ho(e){return{...rg[e]}}function rn(){return hc}function ng(e){let t={node:new Set,indexer:new Set,proofServer:new Set};for(let n of e.split(`
|
|
13
|
+
`)){if(!n)continue;let[s="",o=""]=n.split("|"),i=(a)=>[...o.matchAll(new RegExp(`:(\\d+)->${a}/tcp`,"g"))].map((c)=>parseInt(c[1],10));if(s.includes("indexer"))i(8088).forEach((a)=>t.indexer.add(a));if(s.includes("midnight-node"))i(9944).forEach((a)=>t.node.add(a));if(s.includes("proof-server"))i(6300).forEach((a)=>t.proofServer.add(a))}let r=(n)=>[...n].sort((s,o)=>s-o);return{node:r(t.node),indexer:r(t.indexer),proofServer:r(t.proofServer)}}function og(e,t=sg){if(t.node&&e.node.length>1||t.indexer&&e.indexer.length>1||t.proofServer&&e.proofServer.length>1)throw new wc(e);return{nodePort:t.node?e.node[0]:void 0,indexerPort:t.indexer?e.indexer[0]:void 0,proofServerPort:t.proofServer?e.proofServer[0]:void 0}}function ig(){if(process.env.MN_NO_LOCAL_DETECT==="1")return{node:[],indexer:[],proofServer:[]};try{return ng(eg('docker ps --format "{{.Image}}|{{.Ports}}"',{encoding:"utf-8",timeout:5000,stdio:["ignore","pipe","ignore"]}))}catch{return{node:[],indexer:[],proofServer:[]}}}function os(e,t={}){let r=Ho(e);if(Qn(e))Object.assign(r,Bo(e,t.blockfrostProjectId));let n=t.given??{},s={node:n.node===void 0,indexer:n.indexerWS===void 0,proofServer:n.proofServer===void 0};if(e==="undeployed"&&(s.node||s.indexer||s.proofServer)){let o=og((t.detect??ig)(),s);if(o.indexerPort)r.indexer=`http://localhost:${o.indexerPort}${Kn}`,r.indexerWS=`ws://localhost:${o.indexerPort}${Yr}`;if(o.nodePort)r.node=`ws://localhost:${o.nodePort}`;if(o.proofServerPort)r.proofServer=`http://localhost:${o.proofServerPort}`}if(n.node!==void 0)r.node=n.node;if(n.proofServer!==void 0)r.proofServer=n.proofServer;if(n.indexerWS!==void 0)r.indexerWS=n.indexerWS,r.indexer=yc(n.indexerWS);return r}function yc(e){let t=e.indexOf("?"),[r,n]=t===-1?[e,""]:[e.slice(0,t),e.slice(t)];return r.replace(/^wss:/,"https:").replace(/^ws:/,"http:").replace(/\/ws$/,"")+n}function is(e){let t={};if(e.node!==void 0)t.node=e.node;if(e.indexerWS!==void 0)t["indexer-ws"]=e.indexerWS;if(e.proofServer!==void 0)t["proof-server"]=e.proofServer;return t}function Le(e,t,r,n){let s=Ne(n),o=nn(s,r);if(e.proofServer=t.proofServer??o["proof-server"]??e.proofServer,e.node=t.node??o.node??e.node,e.indexerWS=t.indexerWS??o["indexer-ws"]??e.indexerWS,t.indexerWS??o["indexer-ws"])e.indexer=yc(e.indexerWS);return e}var ft,rg,hc,wc,sg;var Ce=E(()=>{Me();Gt();ft=tg.V9NativeForkSchedule,rg={preprod:{...Bo("preprod",void 0),proofServer:"http://localhost:6300",networkId:"PreProd"},preview:{indexer:`https://indexer.preview.midnight.network${Kn}`,indexerWS:`wss://indexer.preview.midnight.network${Yr}`,node:"wss://rpc.preview.midnight.network",proofServer:"http://localhost:6300",networkId:"Preview"},undeployed:{indexer:`http://localhost:8088${Kn}`,indexerWS:`ws://localhost:8088${Yr}`,node:"ws://localhost:9944",proofServer:"http://localhost:6300",networkId:"Undeployed"}},hc=["preprod","preview","undeployed"];wc=class wc extends Error{code="AMBIGUOUS_LOCAL_STACKS";constructor(e){super(`Several local Midnight stacks are running (node ${e.node.join(", ")}; indexer ${e.indexer.join(", ")}; proof-server ${e.proofServer.join(", ")}), and mn won't guess which one to use.
|
|
14
14
|
Pick one per command: --node ws://localhost:<port> --indexer-ws ws://localhost:<port>${Yr} --proof-server http://localhost:<port>
|
|
15
15
|
or once: midnight config set network undeployed, then midnight config set node / indexer-ws / proof-server <url>
|
|
16
|
-
Commands without endpoint flags (cache, test, dev) use the saved config. MN_NO_LOCAL_DETECT=1 turns detection off.`);this.name="AmbiguousLocalStacksError"}};
|
|
17
|
-
`,{mode:
|
|
18
|
-
Valid keys: ${as.join(", ")}`)}function
|
|
19
|
-
Valid networks: preprod, preview, undeployed`);
|
|
20
|
-
Wallet name must be a simple name (no path separators, .json suffix, or special characters).`);o.wallet=t}else if(s==="account-build"){if(t.trim()==="")throw Error("Invalid account-build: give the directory of the account build.");o["account-build"]=on.resolve(t)}else if(s===Ye){let{projectId:i,network:a}=es(t);if(n!==void 0&&n!==a)throw new R(`That is a ${a} project id, and --network says ${n}.`);o.networks={...o.networks??{},[a]:{...o.networks?.[a]??{},[Ye]:i}}}else if(Kt.has(s)){if(!
|
|
16
|
+
Commands without endpoint flags (cache, test, dev) use the saved config. MN_NO_LOCAL_DETECT=1 turns detection off.`);this.name="AmbiguousLocalStacksError"}};sg={node:!0,indexer:!0,proofServer:!0}});import*as mt from"fs";import*as on from"path";import{homedir as ag}from"os";function Go(e){return cg[e]??e}function dg(e){return/^(https?|wss?):\/\/\S+/.test(e)}function Sc(e){return e??on.join(ag(),te)}function bc(e){return on.join(Sc(e),nc)}function lg(e){let t=Sc(e);if(!mt.existsSync(t))mt.mkdirSync(t,{recursive:!0,mode:be})}function Ne(e){let t=bc(e);if(!mt.existsSync(t))return{...sn};let r;try{r=mt.readFileSync(t,"utf-8")}catch{return{...sn}}let n;try{n=JSON.parse(r)}catch{return{...sn}}let s={network:n.network&&De(n.network)?n.network:sn.network};if(n["proof-server"]&&typeof n["proof-server"]==="string")s["proof-server"]=n["proof-server"];if(n.node&&typeof n.node==="string")s.node=n.node;if(n["indexer-ws"]&&typeof n["indexer-ws"]==="string")s["indexer-ws"]=n["indexer-ws"];if(n.wallet&&typeof n.wallet==="string")s.wallet=n.wallet;if(n["account-build"]&&typeof n["account-build"]==="string")s["account-build"]=n["account-build"];if(n.networks&&typeof n.networks==="object"){let o={};for(let[i,a]of Object.entries(n.networks)){if(!De(i)||!a||typeof a!=="object")continue;let c={};for(let u of Kt){let l=a[u];if(l&&typeof l==="string")c[u]=l}let d=a[Ye];if(typeof d==="string"&&mr(d)===i)c[Ye]=d;if(Object.keys(c).length>0)o[i]=c}if(Object.keys(o).length>0)s.networks=o}return s}function nn(e,t){let r=e.networks?.[t]??{},n=t===e.network;return{"proof-server":r["proof-server"]??(n?e["proof-server"]:void 0),node:r.node??(n?e.node:void 0),"indexer-ws":r["indexer-ws"]??(n?e["indexer-ws"]:void 0)}}function Ko(e,t){return e.networks?.[t]?.[Ye]}function cs(e,t){lg(t);let r=bc(t);mt.writeFileSync(r,JSON.stringify(e,null,2)+`
|
|
17
|
+
`,{mode:Te})}function Jo(e,t,r){let n=Go(e),s=Ne(t);if(Vo(n,r),n==="network")return s.network;if(n==="wallet")return s.wallet??"(not set)";if(n==="account-build")return s["account-build"]??"(not set)";if(n===Ye){let o=fr().filter((i)=>r===void 0||r===i).flatMap((i)=>{let a=Ko(s,i);return a===void 0?[]:[`${pc(a)} (${i})`]});return o.length>0?o.join(", "):"(not set)"}if(Kt.has(n)){let i=nn(s,r??s.network)[n];return typeof i==="string"?i:"(not set)"}throw Error(`Unknown config key: "${e}"
|
|
18
|
+
Valid keys: ${as.join(", ")}`)}function ug(e,t){let r={...e.networks?.[t]??{}},n=!1;for(let s of Kt){let o=s,i=e[o];if(i&&typeof i==="string"){if(!r[o])r[o]=i;delete e[o],n=!0}}if(n)e.networks={...e.networks??{},[t]:r}}function vc(e,t,r,n){let s=Go(e),o=Ne(r);if(Vo(s,n),s==="network"){if(!De(t))throw Error(`Invalid network: "${t}"
|
|
19
|
+
Valid networks: preprod, preview, undeployed`);ug(o,o.network),o.network=t}else if(s==="wallet"){if(!Wt(t))throw Error(`Invalid wallet name: "${t}"
|
|
20
|
+
Wallet name must be a simple name (no path separators, .json suffix, or special characters).`);o.wallet=t}else if(s==="account-build"){if(t.trim()==="")throw Error("Invalid account-build: give the directory of the account build.");o["account-build"]=on.resolve(t)}else if(s===Ye){let{projectId:i,network:a}=es(t);if(n!==void 0&&n!==a)throw new R(`That is a ${a} project id, and --network says ${n}.`);o.networks={...o.networks??{},[a]:{...o.networks?.[a]??{},[Ye]:i}}}else if(Kt.has(s)){if(!dg(t))throw Error(`Invalid URL for "${e}": "${t}"
|
|
21
21
|
Must start with http://, https://, ws://, or wss://`);let i=s,a=n??o.network,c={...o.networks?.[a]??{}};if(c[i]=t,o.networks={...o.networks??{},[a]:c},a===o.network)delete o[i]}else throw Error(`Unknown config key: "${e}"
|
|
22
|
-
Valid keys: ${as.join(", ")}`);cs(o,r)}function
|
|
23
|
-
Valid keys: ${as.join(", ")}`);cs(s,t)}function
|
|
24
|
-
Valid networks: ${rn().join(", ")}`);return t}let r=Ne(e.configDir);if(r.network&&De(r.network))return r.network;return"undeployed"}function zo(e,t,r=process.env){if(!Qn(e))return;let n=r[
|
|
25
|
-
`,{mode:
|
|
22
|
+
Valid keys: ${as.join(", ")}`);cs(o,r)}function kc(e,t,r){let n=Go(e),s=Ne(t);if(Vo(n,r),n==="network")s.network=sn.network;else if(n==="wallet")delete s.wallet;else if(n==="account-build")delete s["account-build"];else if(n===Ye){for(let o of fr()){if(r!==void 0&&r!==o)continue;let i=s.networks?.[o];if(!i)continue;if(delete i[Ye],Object.keys(i).length===0)delete s.networks[o]}if(s.networks&&Object.keys(s.networks).length===0)delete s.networks}else if(Kt.has(n)){let o=n,i=r??s.network;if(i===s.network)delete s[o];let a=s.networks?.[i];if(a){if(delete a[o],Object.keys(a).length===0){if(delete s.networks[i],Object.keys(s.networks).length===0)delete s.networks}}}else throw Error(`Unknown config key: "${e}"
|
|
23
|
+
Valid keys: ${as.join(", ")}`);cs(s,t)}function Vo(e,t){if(t!==void 0&&!Kt.has(e)&&e!==Ye)throw new R(`--network only applies to the endpoint keys (${[...Kt].join(", ")}) and ${Ye}, not "${e}".`)}function qo(){return as}var Ye="blockfrost-project-id",sn,as,cg,Kt;var Gt=E(()=>{Me();Ce();ue();sn={network:"undeployed"},as=["network","proof-server","node","indexer-ws","wallet","account-build",Ye],cg={"network-id":"network"};Kt=new Set(["proof-server","node","indexer-ws"])});function xe(e){let t=C(e.args,"network");if(t!==void 0){if(!De(t))throw Error(`Invalid network: "${t}"
|
|
24
|
+
Valid networks: ${rn().join(", ")}`);return t}let r=Ne(e.configDir);if(r.network&&De(r.network))return r.network;return"undeployed"}function zo(e,t,r=process.env){if(!Qn(e))return;let n=r[pg]?.trim();if(n){let{projectId:o,network:i}=es(n);if(i===e)return o}let s=r[fg]?.trim();if(s&&/^[A-Za-z0-9]+$/.test(s)&&mr(s)===e)return s;return Ko(Ne(t),e)}function me(e){let t=xe(e),r=nn(Ne(e.configDir),t),n={node:C(e.args,"node")??r.node,indexerWS:C(e.args,"indexer-ws")??r["indexer-ws"],proofServer:C(e.args,"proof-server")??r["proof-server"]},s=os(t,{given:n,blockfrostProjectId:zo(t,e.configDir)});return{name:t,config:s}}var pg="MN_BLOCKFROST_PROJECT_ID",fg="BLOCKFROST_PROJECT_ID";var Ee=E(()=>{re();Ce();Me();Gt()});import{HDWallet as mg,Roles as Yo}from"@midnightntwrk/wallet-sdk/hd";function Xo(e,t){let r=mg.fromSeed(e);if(r.type!=="seedOk")throw Error("Invalid seed for HD wallet");let n=r.hdWallet.selectAccount(0).selectRole(t).deriveKeyAt(0);if(n.type==="keyOutOfBounds")throw Error("Key derivation out of bounds");return n.key}function Jt(e){return Xo(e,Yo.Zswap)}function Cc(e){return Xo(e,Yo.NightExternal)}function xt(e){return Xo(e,Yo.Dust)}var Vt=()=>{};import{NetworkId as hr}from"@midnightntwrk/wallet-sdk";function He(e){let t=gg[e];if(t===void 0)throw Error(`Unknown networkId: ${e}`);return t}function wr(e){return hg[e]}var gg,hg;var gt=E(()=>{gg={PreProd:hr.NetworkId.PreProd,Preview:hr.NetworkId.Preview,Undeployed:hr.NetworkId.Undeployed},hg={preprod:hr.NetworkId.PreProd,preview:hr.NetworkId.Preview,undeployed:hr.NetworkId.Undeployed}});import{HDWallet as wg,Roles as yg}from"@midnightntwrk/wallet-sdk/hd";import{createKeystore as Sg,PublicKey as bg}from"@midnightntwrk/wallet-sdk/unshielded";import{MidnightBech32m as vg,ShieldedAddress as kg,ShieldedCoinPublicKey as Cg,ShieldedEncryptionPublicKey as xg}from"@midnightntwrk/wallet-sdk/address-format";import*as xc from"@midnightntwrk/ledger-v9";function Ie(e,t,r=0){let n=wr(t),s=wg.fromSeed(e);if(s.type!=="seedOk")throw Error("Invalid seed for HD wallet");let o=s.hdWallet.selectAccount(0).selectRole(yg.NightExternal).deriveKeyAt(r);if(o.type==="keyOutOfBounds")throw Error(`Key index ${r} out of bounds`);let i=Sg({kind:"schnorr",secret:o.key},n);return bg.fromKeyStore(i).address}function qt(e,t=0){let r={};for(let n of rn())r[n]=Ie(e,n,t);return r}function an(e){let t=cn(e),r={};for(let n of rn()){let s=wr(n);r[n]=vg.encode(s,t).asString()}return r}function cn(e){let t=Jt(e),r=xc.ZswapSecretKeys.fromSeed(t);return new kg(new Cg(Buffer.from(r.coinPublicKey,"hex")),new xg(Buffer.from(r.encryptionPublicKey,"hex")))}var Xe=E(()=>{Ce();Vt();gt()});import*as ne from"fs";import*as _e from"path";import{homedir as Eg}from"os";function yr(e,t,r){let n=_e.resolve(e);if(!ne.existsSync(n))return;try{let s=JSON.parse(ne.readFileSync(n,"utf-8")),o=s.shieldedAddresses&&typeof s.shieldedAddresses==="object"?s.shieldedAddresses:{};if(o[t]=r,s.shieldedAddresses=o,s.shieldedAddress&&s.shieldedAddress===r)delete s.shieldedAddress;ne.writeFileSync(n,JSON.stringify(s,null,2)+`
|
|
25
|
+
`,{mode:Te})}catch{}}function Zo(){return _e.join(Eg(),te)}function dn(){return _e.join(Zo(),Yn)}function Ac(){return _e.join(Zo(),zn)}function Ag(){let e=Zo();if(!ne.existsSync(e))ne.mkdirSync(e,{recursive:!0,mode:be})}function Tg(e){return e.includes("/")||e.includes("\\")||e.endsWith(".json")}function oe(e){if(e!==void 0){if(Tg(e))return _e.resolve(e);return _e.join(dn(),`${e}.json`)}let r=Ne().wallet??Oo;return _e.join(dn(),`${r}.json`)}function Et(){return Ne().wallet??Oo}function Qo(e){if(!Wt(e))throw Error(`Invalid wallet name: "${e}"
|
|
26
26
|
Wallet name must be a simple name (no path separators, .json suffix, or special characters).`);let t=_e.join(dn(),`${e}.json`);if(!ne.existsSync(t))throw Error(`Wallet "${e}" not found.
|
|
27
|
-
Run "midnight wallet list" to see available wallets.`);let r=Ne();r.wallet=e,cs(r)}function ei(){let e=dn();if(!ne.existsSync(e))return[];let t=Et();return ne.readdirSync(e).filter((n)=>n.endsWith(".json")).sort().map((n)=>{let s=n.replace(/\.json$/,""),o=_e.join(e,n);try{let i=JSON.parse(ne.readFileSync(o,"utf-8")),a;if(i.addresses)a=i.addresses;else if(i.address&&i.seed)try{let d=Buffer.from(i.seed,"hex");a=qt(d)}catch{a={undeployed:i.address,preprod:"(unknown)",preview:"(unknown)"}}else a={undeployed:"(unknown)",preprod:"(unknown)",preview:"(unknown)"};let c;if(i.shieldedAddresses&&typeof i.shieldedAddresses==="object")c=i.shieldedAddresses;else if(i.seed)try{c=an(Buffer.from(i.seed,"hex"))}catch{}return{name:s,addresses:a,shieldedAddresses:c,isActive:s===t,createdAt:typeof i.createdAt==="string"?i.createdAt:void 0,file:o}}catch{return{name:s,addresses:{undeployed:"(invalid)",preprod:"(invalid)",preview:"(invalid)"},isActive:s===t,file:o}}})}function
|
|
27
|
+
Run "midnight wallet list" to see available wallets.`);let r=Ne();r.wallet=e,cs(r)}function ei(){let e=dn();if(!ne.existsSync(e))return[];let t=Et();return ne.readdirSync(e).filter((n)=>n.endsWith(".json")).sort().map((n)=>{let s=n.replace(/\.json$/,""),o=_e.join(e,n);try{let i=JSON.parse(ne.readFileSync(o,"utf-8")),a;if(i.addresses)a=i.addresses;else if(i.address&&i.seed)try{let d=Buffer.from(i.seed,"hex");a=qt(d)}catch{a={undeployed:i.address,preprod:"(unknown)",preview:"(unknown)"}}else a={undeployed:"(unknown)",preprod:"(unknown)",preview:"(unknown)"};let c;if(i.shieldedAddresses&&typeof i.shieldedAddresses==="object")c=i.shieldedAddresses;else if(i.seed)try{c=an(Buffer.from(i.seed,"hex"))}catch{}return{name:s,addresses:a,shieldedAddresses:c,isActive:s===t,createdAt:typeof i.createdAt==="string"?i.createdAt:void 0,file:o}}catch{return{name:s,addresses:{undeployed:"(invalid)",preprod:"(invalid)",preview:"(invalid)"},isActive:s===t,file:o}}})}function Ng(e,t){for(let r of e){for(let[n,s]of Object.entries(r.addresses))if(s===t)return{wallet:r,network:n};if(r.shieldedAddresses){for(let[n,s]of Object.entries(r.shieldedAddresses))if(s===t)return{wallet:r,network:n}}}return}function Tc(e){return Ng(ei(),e)}function Nc(e){if(!Wt(e))throw Error(`Invalid wallet name: "${e}"
|
|
28
28
|
Wallet name must be a simple name (no path separators, .json suffix, or special characters).`);let t=dn(),r=_e.join(t,`${e}.json`);if(!ne.existsSync(r))throw Error(`Wallet "${e}" not found.
|
|
29
29
|
Run "midnight wallet list" to see available wallets.`);let n=Et();if(e===n)throw Error(`Cannot remove the active wallet "${e}".
|
|
30
30
|
Switch to another wallet first: midnight wallet use <other-wallet>`);if(ne.readdirSync(t).filter((o)=>o.endsWith(".json")).length<=1)throw Error(`Cannot remove "${e}" — it is the only wallet.
|
|
31
|
-
`+"Create another wallet first: midnight wallet generate <name>");ne.unlinkSync(r)}function ce(e){let t=e?_e.resolve(e):
|
|
31
|
+
`+"Create another wallet first: midnight wallet generate <name>");ne.unlinkSync(r)}function ce(e){let t=e?_e.resolve(e):Ac();if(!ne.existsSync(t))throw Error(`Wallet file not found: ${t}
|
|
32
32
|
Generate a wallet first: midnight wallet generate <name> --network <name>`);let r;try{r=ne.readFileSync(t,"utf-8")}catch(c){throw Error(`Failed to read wallet file: ${t}
|
|
33
|
-
${c.message}`)}let n;try{n=JSON.parse(r)}catch{throw Error(`Invalid JSON in wallet file: ${t}`)}if(!n.seed||!n.createdAt){let c=["seed","createdAt"];if(!n.addresses)c.push("address");let d=c.filter((u)=>!n[u]);if(d.length>0)throw Error(`Wallet file is missing required fields (${d.join(", ")}): ${t}`)}if(!/^[0-9a-fA-F]+$/.test(n.seed))throw Error(`Invalid seed format in wallet file (expected hex string): ${t}`);if(!n.addresses){if(!n.address)throw Error(`Wallet file is missing required fields (address): ${t}`);let c=Buffer.from(n.seed,"hex"),d=qt(c),u={seed:n.seed,addresses:d,createdAt:n.createdAt};if(n.mnemonic)u.mnemonic=n.mnemonic;let l=
|
|
34
|
-
`,{mode:
|
|
35
|
-
`,{mode:
|
|
36
|
-
`,{mode:
|
|
37
|
-
`);for(let f of p)o.push(...
|
|
38
|
-
`)}function
|
|
39
|
-
`)}var
|
|
33
|
+
${c.message}`)}let n;try{n=JSON.parse(r)}catch{throw Error(`Invalid JSON in wallet file: ${t}`)}if(!n.seed||!n.createdAt){let c=["seed","createdAt"];if(!n.addresses)c.push("address");let d=c.filter((u)=>!n[u]);if(d.length>0)throw Error(`Wallet file is missing required fields (${d.join(", ")}): ${t}`)}if(!/^[0-9a-fA-F]+$/.test(n.seed))throw Error(`Invalid seed format in wallet file (expected hex string): ${t}`);if(!n.addresses){if(!n.address)throw Error(`Wallet file is missing required fields (address): ${t}`);let c=Buffer.from(n.seed,"hex"),d=qt(c),u={seed:n.seed,addresses:d,createdAt:n.createdAt};if(n.mnemonic)u.mnemonic=n.mnemonic;let l=Ec(n,c);if(l)u.shieldedAddresses=l;let p={...n,addresses:d};if(l)p.shieldedAddresses=l,delete p.shieldedAddress;return ne.writeFileSync(t,JSON.stringify(p,null,2)+`
|
|
34
|
+
`,{mode:Te}),u}if(typeof n.addresses!=="object")throw Error(`Wallet file has invalid addresses field: ${t}`);let s={seed:n.seed,addresses:n.addresses,createdAt:n.createdAt};if(n.mnemonic)s.mnemonic=n.mnemonic;let o=Buffer.from(n.seed,"hex"),i=Ec(n,o);if(i)s.shieldedAddresses=i;if(i&&(!n.shieldedAddresses||typeof n.shieldedAddresses!=="object"||Object.keys(n.shieldedAddresses).length<Object.keys(i).length))try{let c={...n,shieldedAddresses:i};delete c.shieldedAddress,ne.writeFileSync(t,JSON.stringify(c,null,2)+`
|
|
35
|
+
`,{mode:Te})}catch{}return s}function Ec(e,t){let r;try{r=an(t)}catch{}let n=e.shieldedAddresses,s=n&&typeof n==="object"?n:null,o=s?Object.fromEntries(Object.entries(s).filter(([,i])=>typeof i==="string"&&i.length>0)):{};if(!r)return Object.keys(o).length>0?o:void 0;return{...r,...o}}function ds(e,t){let r=t?_e.resolve(t):Ac();if(!t)Ag();else{let n=_e.dirname(r);if(!ne.existsSync(n))ne.mkdirSync(n,{recursive:!0,mode:be})}return ne.writeFileSync(r,JSON.stringify(e,null,2)+`
|
|
36
|
+
`,{mode:Te}),r}var Pe=E(()=>{Gt();Xe()});function ln(){return!("NO_COLOR"in process.env)}function un(e,t){if(!ln())return e;return`\x1B[38;5;${t}m${e}\x1B[0m`}function P(e){if(!ln())return e;return`\x1B[1m${e}\x1B[0m`}function g(e){if(!ln())return e;return`\x1B[2m${e}\x1B[0m`}function X(e){return un(e,38)}function he(e){return un(e,196)}function z(e){return un(e,40)}function ee(e){return un(e,226)}function pn(e){return un(e,245)}function B(e,t=Rc){let r=` ${e} `,n=t-r.length;if(n<=0)return P(r);let s=Math.floor(n/2),o=n-s;return P("═".repeat(s)+r+"═".repeat(o))}function Z(e=Rc){return g("─".repeat(e))}function A(e,t,r=16){let n=(e+":").padEnd(r);return` ${pn(n)}${t}`}function zt(e){let t=e<0n,r=t?-e:e,n=BigInt(10**Ro),s=r/n,i=(r%n).toString().padStart(Ro,"0");return`${t?"-":""}${s}.${i}`}function br(e){return`${zt(e)} NIGHT`}function pe(e){let t=e<0n,r=t?-e:e,n=10n**BigInt(ti),s=r/n,a=(r%n).toString().padStart(ti,"0").replace(/0+$/,"").padEnd(6,"0");return`${t?"-":""}${s}.${a}`}function At(e,t=!1){let r=10n**BigInt(ti-2),n=e/r+(t&&e%r>0n?1n:0n);return`${n/100n}.${(n%100n).toString().padStart(2,"0")}`}function Yt(e){return`${pe(e)} DUST`}function se(e,t=!1){let r=t&&e.length>20?e.slice(0,10)+"…"+e.slice(-8):e;return X(r)}function Rg(e,t){let r=[],n="",s=0,o=!1,i=0;while(i<e.length){let a=/^\x1b\[[0-9;]*m/.exec(e.slice(i));if(a){n+=a[0],o=!0,i+=a[0].length;continue}if(s===t)r.push(o?n+"\x1B[0m":n),n="",s=0,o=!1;n+=e[i],s+=1,i+=1}if(n.length>0)r.push(o?n+"\x1B[0m":n);return r}function Dg(e,t){if(Sr(e).length<=t)return[e];let n=e.split(/(\s+)/).flatMap((a)=>Sr(a).length>t?Rg(a,t):[a]),s=[],o="",i=0;for(let a of n){let c=Sr(a).length;if(i+c>t&&i>0)s.push(o),o=a.trimStart(),i=Sr(o).length;else o+=a,i+=c}if(o.length>0)s.push(o);return s}function Dc(e,t="light",r=70){let n=t==="heavy"?{tl:"╔",tr:"╗",bl:"╚",br:"╝",h:"═",v:"║"}:{tl:"┌",tr:"┐",bl:"└",br:"┘",h:"─",v:"│"},s=r-4,o=[];for(let l of e){let p=l.split(`
|
|
37
|
+
`);for(let f of p)o.push(...Dg(f,s))}let i=Math.max(...o.map((l)=>Sr(l).length)),a=Math.max(i+2,20),c=n.tl+n.h.repeat(a)+n.tr,d=n.bl+n.h.repeat(a)+n.br,u=o.map((l)=>{let p=Sr(l).length,f=a-p-2;return`${n.v} ${l}${" ".repeat(Math.max(0,f))} ${n.v}`});return[c,...u,d].join(`
|
|
38
|
+
`)}function Tt(e,t){let n=[`${z("✓")} ${e}`];if(t)n.push(A("Transaction",X(t)));return n.join(`
|
|
39
|
+
`)}var Rc=60,ti=15,Sr=(e)=>e.replace(/\x1b\[[0-9;]*m/g,"");var de=()=>{};function Ic(e,t){let r=(a)=>t.reduce((c,d)=>c+a(d),0n),n=r((a)=>a.dust.generatedNow),s=r((a)=>a.dust.rate),o=r((a)=>a.dust.maxCap),i;if(n>=e)i=0;else if(o<e||s<=0n)i=null;else i=Number(((e-n)*1000n+s-1n)/s);return{fee:e,generated:n,ratePerSecond:s,cap:o,waitMs:i}}function Ge(e){if(e<60000){let r=Math.max(1,Math.ceil(e/1000));return`about ${r} second${r===1?"":"s"}`}let t=Math.ceil(e/60000);if(t<2)return"about a minute";if(t<120)return`about ${t} minutes`;return`about ${Math.round(t/60)} hours`}var ls;var fn=E(()=>{de();ls=class ls extends Error{code="DUST_GENERATING";constructor(e,t){let r=`Registering for Dust costs a ${pe(e.fee)} DUST fee, paid from the Dust this wallet's NIGHT generates`,n=`It has generated ${pe(e.generated)} DUST so far`;super(e.waitMs===null?`${r}, but it can never generate that much: its NIGHT holds at most ${pe(e.cap)} DUST. ${n}. Add more NIGHT (on undeployed: midnight airdrop 1000), then run: midnight dust register`:`${r}. ${n}, so the fee is covered in ${Ge(e.waitMs)} (around ${new Date(t.getTime()+e.waitMs).toISOString()}). Run midnight dust register again then, or add more NIGHT to register sooner (on undeployed: midnight airdrop 1000).`);this.name="DustFeeNotGeneratedError",Object.setPrototypeOf(this,ls.prototype)}}});function Ig(e){let t=e;while(t){let r=String(t?.message??"").toLowerCase();if(r.includes("submission error"))return!0;if(r.includes("transaction")&&r.includes("invalid"))return!0;if(r.includes("138"))return!0;let n=t?._tag;if(n==="TransactionInvalidError"||n==="SubmissionError")return!0;t=t.cause}return!1}function ri(e){let t=new Set,r=[e];while(r.length>0){let n=r.pop();if(!n||typeof n!=="object"||t.has(n))continue;t.add(n);let s=n;if(s._tag==="Wallet.InsufficientFunds"&&s.tokenType==="dust")return!0;if(typeof s.message==="string"&&/no dust tokens|dust.*unavailable/i.test(s.message))return!0;r.push(s.cause,s[_c],s.error,s.defect,s.left,s.right)}return!1}function ni(e,t){return Object.assign(e,{[Pc]:t})}function $c(e){let t=new Set,r=[e];while(r.length>0){let n=r.pop();if(!n||typeof n!=="object"||t.has(n))continue;t.add(n);let s=n,o=s[Pc];if(o&&typeof o.needed==="bigint"&&typeof o.available==="bigint")return o;r.push(s.cause,s[_c],s.error,s.defect,s.left,s.right)}return}function us(e){let t=e?.message?.toLowerCase()??"";return t.includes("not enough dust")||t.includes("dust generated")||t.includes("insufficient generated dust")||t.includes("insufficient funds")||t.includes("no dust tokens")||Ig(e)}function Oc(e){let t=e?.message?.toLowerCase()??"";if(e?._tag==="Wallet.InsufficientFunds")return!0;return t==="insufficient funds"||t.startsWith("insufficient funds")}function ps(e){return Oc(e)&&!ri(e)}var _c,Pc="dustShortfall";var Xt=E(()=>{_c=Symbol.for("effect/Runtime/FiberFailure/Cause")});function Fc(e,t,r,n){let s=(a)=>e.balance(new Date(r.getTime()+a*1000));if(s(0)>=t)return 0;let o=Math.ceil(n/1000);if(s(o)<t)return null;let i=0;while(o-i>1){let a=Math.floor((i+o)/2);if(s(a)>=t)o=a;else i=a}return o*1000}function Uc(e,t,r){let n=r===null?"This wallet's registered NIGHT won't generate that within a day: register more NIGHT (midnight dust register).":`This wallet's NIGHT generates that in ${Ge(r)}; retry then.`;return Error(`Insufficient dust for transaction fees.
|
|
40
40
|
Available: ${pe(e)} DUST, need ≥${pe(t)} DUST.
|
|
41
|
-
${n}`)}async function ms(e,t,r,n){let s=new Date,o=e.balance(s);if(o===0n||o>=t)return;let i=
|
|
42
|
-
`)}var
|
|
43
|
-
`),f=await d()}}else U("facade","No cache, building fresh"),f=await d();if(!a||!c)throw Error("Wallet facade was built without its shielded or dust wallet");return{facade:f,keystore:o,seeds:s,seedStartable:{shielded:a,dust:c},restoredFromCache:p,indexerHttpUrl:t.indexer,indexerWsUrl:t.indexerWS}}async function
|
|
41
|
+
${n}`)}async function ms(e,t,r,n){let s=new Date,o=e.balance(s);if(o===0n||o>=t)return;let i=Fc(e,t,s,Mc);if(i===null||i>mn)throw Uc(o,t,i);r?.(`Waiting ${Ge(i)} for Dust to cover the fee (${pe(o)} of ${pe(t)} DUST)...`),await Zt(i,n)}function si(e,t,r){let n=$c(e);if(!n||n.available>=n.needed)return;let{needed:s,available:o}=n,i=t.balance(r)+(s-o)*102n/100n,a=Fc(t,i,r,Mc);return{have:o,needed:s,waitMs:a===null?null:Math.max(a,Zr)}}async function Lc(e,t,r){let n=0;for(;;)try{return await e()}catch(s){let o=si(s,t,new Date);if(!o)throw s;if(o.waitMs===null||n+o.waitMs>r.maxWaitMs)throw Uc(o.have,o.needed,o.waitMs);r.onStatus?.(`Waiting ${Ge(o.waitMs)} for Dust to cover the fee (${At(o.have)} of ${At(o.needed,!0)} DUST)...`),await Zt(o.waitMs,r.signal),n+=o.waitMs}}function Zt(e,t){if(t?.aborted)return Promise.reject(Error("Operation cancelled"));return new Promise((r,n)=>{let s=()=>{clearTimeout(o),n(Error("Operation cancelled"))},o=setTimeout(()=>{t?.removeEventListener("abort",s),r()},e);t?.addEventListener("abort",s,{once:!0})})}var mn=120000,fs=300000,Mc=86400000;var vr=E(()=>{fn();Xt();de()});function Bc(e,t,r){let n;for(let s of e)if(s.value>=t&&(n===void 0||s.value<n.value))n=s;return n===void 0?r(t):[n]}function Wc({owed:e,coinCount:t,choose:r,feeWith:n}){let s=e;for(let o=0;o<=t*2;o++){let i=s>0n?r(s):[];if(i===void 0)return{kind:"short",atFirstChoice:o===0};let a=n(i),c=i.reduce((d,u)=>d+u.value,0n);if(a<=c)return{kind:"covered",fee:a,inputs:i};s=a}return{kind:"short",atFirstChoice:!1}}function jc(e,t){let r=t;return e.map((n)=>{let s=r>=n.value?n.value:r;return r-=s,{...n,value:s}})}import*as Kc from"@midnightntwrk/ledger-v9";import{Imbalances as _g,InsufficientFundsError as Hc,getBalanceRecipe as Pg,makeIndexerChainVersionProbe as $g}from"@midnightntwrk/wallet-sdk/capabilities";import{CustomForkingDustWallet as Og,asV8DustParameters as Mg}from"@midnightntwrk/wallet-sdk/dust";import{V1Builder as Fg}from"@midnightntwrk/wallet-sdk/dust/v1";import{Migration as Ug,Transacting as Gc,V2Builder as Lg,WalletError as Bg}from"@midnightntwrk/wallet-sdk/dust/v2";import{LedgerOps as oi}from"@midnightntwrk/wallet-sdk/utilities";function ii(e){let t=e.dustParameters??Kc.LedgerParameters.initialParameters().dust,r={...e,chainVersionProbe:e.chainVersionProbe??$g(e)};return Og(r,{builder:new Fg().withDefaults(),configuration:{...e,dustParameters:Mg(t)}},{builder:new Lg().withDefaults().withTransacting(Wg).withMigration(()=>Ug.makeCrossLedgerMigration({dustParameters:t})),configuration:e})}var Jc,Wg=(e,t)=>new Jc(e.networkId,e.costParameters,()=>t().coinSelection,()=>t().coinsAndBalancesCapability,()=>t().keysCapability);var Vc=E(()=>{Xt();Jc=class Jc extends Gc.TransactingCapabilityImplementation{computeBalancingRecipe(...e){let[t,r,n,s,o,i]=e,a;try{let d=-n.reduce((l,p)=>l+Gc.TransactingCapabilityImplementation.feeImbalance(p,this.calculateFee(p,i)),0n),u=this.getCoins().getAvailableCoinsWithGeneratedDust(r,o);a=Wc({owed:d,coinCount:u.length,choose:(l)=>Bc(u,l,(p)=>this.#t(u,p)),feeWith:(l)=>this.dryRunFee(l,n,t,r,s,o,i)})}catch(d){return oi.ledgerTry(()=>{throw d})}if(a.kind==="covered"){let{fee:d,inputs:u}=a;return oi.ledgerTry(()=>({fee:d,recipeInputs:jc(u,d)}))}let c=this.#e(e);if(a.atFirstChoice){let d=super.computeBalancingRecipe(...e);if(c&&d._tag==="Left")ni(d.left,c);return d}return oi.ledgerTry(()=>{let d=new Bg.InsufficientFundsError({message:new Hc("dust").message,tokenType:"dust"});throw c?ni(d,c):d})}#e([e,t,r,n,s,o]){try{let i=this.getCoins().getAvailableCoinsWithGeneratedDust(t,s);if(i.length===0)return;let a=i.map(({token:c,value:d})=>({token:c,value:d}));return{needed:this.dryRunFee(a,r,e,t,n,s,o),available:a.reduce((c,d)=>c+d.value,0n)}}catch{return}}#t(e,t){try{return Pg({coins:e.map((n)=>({type:"dust",value:n.value,token:n.token})),initialImbalances:_g.fromEntry("dust",-t),feeTokenType:"dust",coinSelection:this.getCoinSelection(),transactionCostModel:{inputFeeOverhead:0n,outputFeeOverhead:0n},createOutput:(n)=>n,isCoinEqual:(n,s)=>n.token.nonce===s.token.nonce}).inputs.map(({token:n,value:s})=>({token:n,value:s}))}catch(r){if(r instanceof Hc)return;throw r}}}});import{existsSync as gn,mkdirSync as jg,writeFileSync as Hg,readFileSync as qc,unlinkSync as gs,readdirSync as ai,renameSync as Gg}from"node:fs";import{join as Qt,dirname as Kg}from"node:path";import{homedir as zc}from"node:os";import{randomBytes as Jg}from"node:crypto";import*as hs from"@midnightntwrk/ledger-v9";function ci(e){return e.toString(16).padStart(64,"0")}function Ze(e){let t=xt(e),r=hs.DustSecretKey.fromSeed(t);return ci(r.publicKey)}function di(e,t){let r=t??Qt(zc(),te,Oe);return Qt(r,e)}function li(e,t,r){let n=t.slice(0,20);return Qt(di(e,r),`dust-${n}.json`)}function kr(e,t,r){let n=li(e,t,r);if(!gn(n))return null;try{let s=JSON.parse(qc(n,"utf-8"));if(s.version!==Yc)return null;if(s.network!==e)return null;if(s.dustPublicKeyHex!==t)return null;if(typeof s.lastAppliedEventId!=="number")return null;if(typeof s.dustState!=="string")return null;if(!Array.isArray(s.ownedGenerationIndices))return null;if(typeof s.generationFrontier!=="number")return null;let o=Buffer.from(s.dustState,"hex");return{state:hs.DustLocalState.deserialize(o),lastAppliedEventId:s.lastAppliedEventId,retention:{ownedGenerationIndices:s.ownedGenerationIndices,generationFrontier:s.generationFrontier}}}catch{return null}}function ui(e,t,r,n,s,o,i=Vg){let a={version:Yc,network:e,dustPublicKeyHex:t,lastAppliedEventId:n,timestamp:new Date().toISOString(),dustState:Buffer.from(r.serialize()).toString("hex"),ownedGenerationIndices:i.ownedGenerationIndices,generationFrontier:i.generationFrontier,...o?{chainId:o}:{}},c=li(e,t,s),d=Kg(c);if(!gn(d))jg(d,{recursive:!0,mode:be});let u=c+`.tmp.${Jg(4).toString("hex")}`;try{Hg(u,JSON.stringify(a),{mode:Te}),Gg(u,c)}catch(l){try{gs(u)}catch{}throw l}}function Xc(e,t,r){if(!t)return[];let n=di(e,r);if(!gn(n))return[];let s=[],o;try{o=ai(n)}catch{return[]}for(let i of o){if(!i.startsWith("dust-")||!i.endsWith(".json"))continue;let a=Qt(n,i);try{let c=JSON.parse(qc(a,"utf-8"));if(!c.chainId)continue;if(c.chainId!==t)gs(a),s.push(a)}catch{}}return s}function ht(e,t,r){let n=r??Qt(zc(),te,Oe);if(e&&t){let o=li(e,t,r);try{gs(o)}catch{}return}let s=(o)=>{if(!gn(o))return;try{for(let i of ai(o))if(i.startsWith("dust-")&&i.endsWith(".json"))try{gs(Qt(o,i))}catch{}}catch{}};if(e){s(di(e,r));return}if(!gn(n))return;try{for(let o of ai(n))s(Qt(n,o))}catch{}}var Yc=3,Vg;var er=E(()=>{Vt();Vg={ownedGenerationIndices:[],generationFrontier:0}});function Qe(){Zc=!0}function U(e,t){if(!Zc)return;let r=new Date().toISOString().slice(11,23);process.stderr.write(g(` [${r}] ${e}: ${t}`)+`
|
|
42
|
+
`)}var Zc=!1;var Nt=()=>{};async function Qc(e,t=fetch){for(let s of[e.indexer,e.indexerWS,e.node])ke(s);if(!Wo(e.indexer))return;let r;try{r=(await t(e.indexer,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({query:"{ __typename }"}),signal:AbortSignal.timeout(qg)})).status}catch{return}let n=Ht(e.indexer,r);if(n!==void 0)throw n}var qg=1e4;var ed=E(()=>{Me()});import zg from"ws";function Cr(e,t){let{query:r,variables:n,onNext:s,buildResult:o,timeoutMs:i,idleMs:a,idleBeforeFirstEvent:c,initialSilenceMs:d,signal:u}=t;return new Promise((l,p)=>{ke(e);let f=new zg(e,["graphql-transport-ws"]),h=!1,m=!1,y,w,S,k=()=>{if(clearTimeout(y),w)clearTimeout(w);if(S)clearTimeout(S);try{f.close()}catch{}u?.removeEventListener("abort",L)},T=(Y,V)=>{if(m)return;m=!0,k();try{l(o(V,Y))}catch(M){p(M instanceof Error?M:Error(String(M)))}},N=(Y)=>{if(m)return;m=!0,k(),p(Y)},L=()=>N(Error("Operation cancelled"));u?.addEventListener("abort",L,{once:!0});let J=()=>{if(w)clearTimeout(w);w=setTimeout(()=>{if(!m&&(h||c))T("idle",!1)},a)};f.on("open",()=>{f.send(JSON.stringify({type:"connection_init"}))}),f.on("message",(Y)=>{let V;try{V=JSON.parse(Y.toString())}catch{return}if(V.type==="connection_ack"){if(f.send(JSON.stringify({id:"1",type:"subscribe",payload:{query:r,variables:n}})),c)J();if(d&&d>0)S=setTimeout(()=>{if(!h&&!m)T("initial-silence",!1)},d);return}if(V.type==="error"){N(Error(`GraphQL subscription error: ${JSON.stringify(V.payload)?.slice(0,300)}`));return}if(V.type!=="next")return;if(V.payload?.errors){N(Error(`GraphQL error: ${V.payload.errors[0]?.message||"unknown"}`));return}if(h=!0,S)clearTimeout(S),S=void 0;let M;try{M=s(V.payload?.data)}catch(O){N(O instanceof Error?O:Error(String(O)));return}if(J(),M)T("caught-up",!1)}),f.on("error",(Y)=>N(gr(e,Y)??Error(`WebSocket error: ${Y.message}`))),f.on("close",()=>{if(m)return;T(h?"closed-early":"graceful-close",h)}),y=setTimeout(()=>T("timeout",!0),i)})}var ws=E(()=>{Me()});function td(e,t){let r=Yg[t],n=null;return Cr(e,{query:`subscription { ${r}(id: 0) { id maxId } }`,variables:{},onNext:(s)=>{let o=s[r]?.maxId;if(typeof o==="number")n=o;return n!==null},buildResult:(s,o)=>({tip:n,reason:o}),timeoutMs:1e4,idleMs:3000,idleBeforeFirstEvent:!0})}async function ys(e,t){try{return(await td(e,t)).tip}catch{return null}}async function pi(e,t){try{let{tip:r,reason:n}=await td(e,t);return r===null&&n==="idle"}catch{return!1}}function Ss(e,t){return t!==null&&e>t}var Yg;var bs=E(()=>{ws();Yg={dust:"dustLedgerEvents",zswap:"zswapLedgerEvents"}});import{ShieldedWallet as rd}from"@midnightntwrk/wallet-sdk/shielded";import{UnshieldedWallet as nd,createKeystore as Xg,PublicKey as Zg}from"@midnightntwrk/wallet-sdk/unshielded";import{WalletFacade as sd,WalletEntrySchema as Qg,mergeWalletEntries as eh}from"@midnightntwrk/wallet-sdk/facade";import*as od from"@midnightntwrk/ledger-v9";import{InMemoryTransactionHistoryStorage as th}from"@midnightntwrk/wallet-sdk";import*as Be from"rxjs";async function et(e,t,r){let n=He(t.networkId);await Qc(t),U("facade",`Building facade for network ${t.networkId}`),U("facade",`Node: ${t.node}`),U("facade",`Indexer: ${t.indexerWS}`),U("facade",`Proof server: ${t.proofServer}`);let s={shielded:Jt(e),unshielded:Cc(e),dust:xt(e)},o=Xg({kind:"schnorr",secret:s.unshielded},n),i={networkId:n,forks:ft,indexerClientConnection:{indexerHttpUrl:t.indexer,indexerWsUrl:t.indexerWS},costParameters:{additionalFeeOverhead:Ga,feeBlocksMargin:Ka},txHistoryStorage:new th(Qg,eh),provingServerUrl:new URL(t.proofServer),relayURL:new URL(t.node)},a,c,d=()=>sd.init({configuration:i,shielded:async(h)=>a=await rd(h).startWithSeed(s.shielded),unshielded:(h)=>nd(h).startWithPublicKey(Zg.fromKeyStore(o)),dust:async(h)=>c=await ii(h).startWithSeed(s.dust)}),u=od.DustSecretKey.fromSeed(s.dust).publicKey,l=r?nh(r,t,u):null,p=!1,f;if(l){U("facade","Restoring from cache...");try{f=await sd.init({configuration:i,shielded:(h)=>a=rd(h).restore(l.shielded),unshielded:(h)=>nd(h).restore(l.unshielded),dust:(h)=>c=ii(h).restore(l.dust)}),p=!0,U("facade","Cache restore successful")}catch(h){U("facade",`Cache restore failed: ${h.message}`),process.stderr.write(` Cache restore failed, building from scratch: ${h.message}
|
|
43
|
+
`),f=await d()}}else U("facade","No cache, building fresh"),f=await d();if(!a||!c)throw Error("Wallet facade was built without its shielded or dust wallet");return{facade:f,keystore:o,seeds:s,seedStartable:{shielded:a,dust:c},restoredFromCache:p,indexerHttpUrl:t.indexer,indexerWsUrl:t.indexerWS}}async function rh(e){let{facade:t,seeds:r,seedStartable:n}=e;if(!e.restoredFromCache){await t.start(r);return}await Promise.all([n.shielded.startWithSeed(r.shielded),t.unshielded.start(),n.dust.startWithSeed(r.dust),t.pendingTransactionsService.start()])}function wn(e,t){let r=JSON.parse(e);if(BigInt(r.protocolVersion)<ft.v9)throw Error(`Can't put a ledger-9 dust state into a snapshot at protocol version ${r.protocolVersion}: the wallet would read it as ledger 8 (fork at ${ft.v9}).`);return r.state=Buffer.from(t.state.serialize()).toString("hex"),r.offset=t.lastAppliedEventId.toString(),JSON.stringify(r)}function nh(e,t,r){try{let n=t.networkId.toLowerCase(),s=ci(r),o=kr(n,s);if(!o)return e;let i=JSON.parse(e.dust),a=i.offset!==void 0?Number(i.offset):-1;if(a>=o.lastAppliedEventId)return U("facade",`Facade dust offset=${a} >= dust-direct offset=${o.lastAppliedEventId}; skipping bridge`),e;return U("facade",`Bridged dust-direct cache (facade offset ${a} → dust-direct offset ${o.lastAppliedEventId})`),{...e,dust:wn(e.dust,o)}}catch(n){return U("facade",`Dust-direct bridge skipped: ${n.message}`),e}}function ad(e,t,r){if(e.isStrictlyComplete())return!0;if(e.highestRelevantWalletIndex>0n&&e.appliedIndex>=e.highestRelevantWalletIndex)return!0;return r&&cd(e)&&t}function cd(e){return e.highestRelevantWalletIndex===0n&&e.appliedIndex===0n}function hn(e,t="full",r=id){let n=e.unshielded.progress.isStrictlyComplete(),s=t==="no-dust"||ad(e.dust.progress,n,r.dust);if(t==="lite")return n&&s;let o=e.shielded.progress;return(o.isStrictlyComplete()||r.zswap&&n&&cd(o))&&n&&s}function sh(e,t){return!ad(e.dust.progress,e.unshielded.progress.isStrictlyComplete(),t.dust)}async function oh(e,t){if(!e)return id;let[r,n]=await Promise.all([t==="lite"?!1:pi(e,"zswap"),t==="no-dust"?!1:pi(e,"dust")]);return{zswap:r,dust:n}}async function Rt(e,t={}){let{onProgress:r,onSyncDetail:n,timeoutMs:s,syncMode:o="full",requireStrictSync:i=!1}=t,{facade:a}=e;U("sync","Starting facade (connecting to node and indexer)...");let[,c]=await Promise.all([rh(e),oh(e.indexerWsUrl,o)]);if(e.emptyStreams=c,c.zswap||c.dust)U("sync",`The chain has no events in: ${[c.zswap&&"zswap",c.dust&&"dust"].filter(Boolean).join(", ")}`);U("sync","Facade started, subscribing to state...");let d=s??za;U("sync",`Sync timeout: ${d/1000}s, mode: ${o}`);let u=!i&&e.restoredFromCache,l=Date.now();return new Promise((p,f)=>{let h=!1,m=0,y="",w=null,S=setTimeout(()=>{if(!h){if(U("sync",`Sync timed out after ${d/1000}s (${m} emissions)`),w)try{let k=w.unshielded.progress;U("sync",` unshielded: applied=${k.appliedId} highest=${k.highestTransactionId} complete=${k.isStrictlyComplete()}`);let T=w.dust.progress;if(U("sync",` dust: applied=${T.appliedIndex} highest=${T.highestRelevantWalletIndex} complete=${T.isStrictlyComplete()} connected=${T.isConnected}`),o==="full"){let N=w.shielded.progress;U("sync",` shielded: complete=${N.isStrictlyComplete()}`)}}catch{}f(Error("Wallet sync timed out"))}},d);e.keepAlive=a.state().subscribe({next:(k)=>{if(h)return;if(m++,w=k,e.restoredFromCache){let N=ah(k);if(N){h=!0,clearTimeout(S),U("sync",`Stale cache detected: ${N}`),f(new vs(N));return}}if(r){let N=k.unshielded.progress;if(N){let L=Number(N.appliedId),J=Number(N.highestTransactionId);r(Math.min(L,J),J)}}let T=[];try{if((o==="full"||o==="no-dust")&&!k.shielded.progress.isStrictlyComplete())T.push("shielded");if(o!=="no-dust"&&sh(k,c))T.push("dust");if(!k.unshielded.progress.isStrictlyComplete())T.push("unshielded")}catch{}if(T.length>0){n?.(T.join(", "));let N=T.join(",");if(m===1||N!==y||m%100===0)U("sync",`Waiting on: ${T.join(", ")} (emission #${m})`),y=N}if(hn(k,o,c)){h=!0,clearTimeout(S),U("sync",`Sync complete after ${m} emissions`),p(k);return}if(u){let N=Date.now()-l;if(N>=ih&&hn(k,"no-dust",c))h=!0,clearTimeout(S),U("sync",`Sync resolved via cached-restore grace (${N}ms, ${m} emissions)`),p(k)}},error:(k)=>{if(!h)U("sync",`Sync error: ${k.message}`),clearTimeout(S),f(k)}})})}function ah(e){let{appliedId:t,highestTransactionId:r}=e.unshielded.progress;if(r>0n&&t>r)return`unshielded cache applied=${t} but chain highest=${r}.`;return}async function dd(e){let t=(r)=>{let n=r.unshielded.progress.isStrictlyComplete(),s=r.dust.progress.isStrictlyComplete();return n&&s};try{return await Be.firstValueFrom(e.facade.state().pipe(Be.filter(t),Be.timeout(15000)))}catch{return await Be.firstValueFrom(e.facade.state())}}function tr(e){return e.dust.availableCoins.length>0||e.dust.balance(new Date)>0n}async function ks(e,t=60000){try{return await Be.firstValueFrom(e.facade.state().pipe(Be.filter(tr),Be.timeout(t)))}catch{return await Be.firstValueFrom(e.facade.state())}}async function fi(e,t="full"){return Be.firstValueFrom(e.facade.state().pipe(Be.filter((r)=>hn(r,t,e.emptyStreams)),Be.timeout(Ya)))}async function We(e){e.keepAlive?.unsubscribe(),await Promise.race([e.facade.stop(),new Promise((t)=>setTimeout(t,5000))])}function Fe(e){let t=(n)=>{let s=n?._tag;if(typeof s==="string"&&s.startsWith("Wallet.")){let o=n?.message??"transient error";e?.(s,o);return}r("Unhandled rejection:",n),process.exit(1)},r=console.error;return console.error=(...n)=>{let s=n[0];if(typeof s==="object"&&s?._tag?.startsWith("Wallet.")){e?.(s._tag,s?.message??"transient error");return}if(typeof s==="string"&&s.startsWith("Wallet.")){e?.("Wallet.Sync","transient error");return}r(...n)},process.on("unhandledRejection",t),()=>{process.removeListener("unhandledRejection",t),console.error=r}}var id,ih=1e4,vs;var tt=E(()=>{Vc();Ce();gt();Vt();er();Nt();ed();bs();id={zswap:!1,dust:!1};vs=class vs extends Error{code="STALE_CACHE";constructor(e){super(`Cached wallet state is stale (from a previous chain). ${e}
|
|
44
44
|
Run: midnight cache clear --wallet <name> --network <name>
|
|
45
|
-
Or: midnight cache clear (wipe all caches)`);this.name="StaleCacheError"}}});import{existsSync as Sn,mkdirSync as
|
|
45
|
+
Or: midnight cache clear (wipe all caches)`);this.name="StaleCacheError"}}});import{existsSync as Sn,mkdirSync as ch,writeFileSync as dh,readFileSync as ld,unlinkSync as yn,readdirSync as Cs,renameSync as lh}from"node:fs";import{join as it,dirname as uh}from"node:path";import{homedir as mi}from"node:os";import{randomBytes as ph}from"node:crypto";function gi(e,t,r){let n=r??it(mi(),te,Oe),s=e.slice(0,20);return it(n,t,`${s}.json`)}function Dt(e,t,r){let n=gi(e,t,r);if(!Sn(n))return null;try{let s=ld(n,"utf-8"),o=JSON.parse(s);if(o.version!==$o)return null;if(o.network!==t)return null;if(o.address!==e)return null;if(!o.wallets||typeof o.wallets.shielded!=="string"||typeof o.wallets.unshielded!=="string"||typeof o.wallets.dust!=="string")return null;return o.wallets}catch{return null}}async function wt(e,t,r,n,s){let[o,i,a]=await Promise.all([r.shielded.serializeState(),r.unshielded.serializeState(),r.dust.serializeState()]),c={version:$o,network:t,address:e,timestamp:new Date().toISOString(),wallets:{shielded:o,unshielded:i,dust:a},...s?{chainId:s}:{}},d=gi(e,t,n),u=uh(d);if(!Sn(u))ch(u,{recursive:!0,mode:be});let l=d+`.tmp.${ph(4).toString("hex")}`;try{dh(l,JSON.stringify(c),{mode:Te}),lh(l,d)}catch(p){try{yn(l)}catch{}throw p}}function ud(e,t,r){if(!t)return[];let n=r??it(mi(),te,Oe),s=it(n,e);if(!Sn(s))return[];let o=[],i;try{i=Cs(s)}catch{return[]}for(let a of i){if(!a.endsWith(".json"))continue;let c=it(s,a);try{let d=JSON.parse(ld(c,"utf-8"));if(!d.chainId)continue;if(d.chainId!==t)yn(c),o.push(c)}catch{}}return o}function rt(e,t,r){let n=r??it(mi(),te,Oe);if(e&&t){let s=gi(e,t,r);try{yn(s)}catch{}return}if(t){let s=it(n,t);if(!Sn(s))return;try{for(let o of Cs(s))if(o.endsWith(".json"))yn(it(s,o))}catch{}return}if(!Sn(n))return;try{for(let s of Cs(n)){let o=it(n,s);try{for(let i of Cs(o))if(i.endsWith(".json"))yn(it(o,i))}catch{}}}catch{}}var rr=()=>{};import fh from"ws";async function xr(e,t,r=[]){let n=e.timeoutMs??mh;return new Promise((s,o)=>{ke(e.url);let i=new fh(e.url),a=!1,c=(u)=>{if(!a)a=!0,u()},d=setTimeout(()=>{c(()=>{try{i.close()}catch{}o(Error(`RPC ${t} timed out after ${n}ms`))})},n);i.on("open",()=>{try{i.send(JSON.stringify({jsonrpc:"2.0",id:1,method:t,params:r}))}catch(u){clearTimeout(d),c(()=>o(u instanceof Error?u:Error(String(u))))}}),i.on("message",(u)=>{clearTimeout(d),c(()=>{try{let l=JSON.parse(u.toString());try{i.close()}catch{}if(l.error)o(Error(`RPC ${t}: ${l.error.message}`));else s(l.result)}catch(l){o(l instanceof Error?l:Error(String(l)))}})}),i.on("error",(u)=>{clearTimeout(d),c(()=>o(gr(e.url,u)??(u instanceof Error?u:Error(String(u)))))})})}var mh=5000;var xs=E(()=>{Me()});async function Er(e){let t=pd.get(e);if(t&&Date.now()-t.fetchedAt<gh)return t.hash;try{let r=await xr({url:e,timeoutMs:5000},"chain_getBlockHash",[0]);if(typeof r!=="string"||!r.startsWith("0x"))return null;return pd.set(e,{hash:r,fetchedAt:Date.now()}),r}catch{return null}}var pd,gh=60000;var Es=E(()=>{xs();pd=new Map});async function It(e,t,r,n){ke(e);let s;try{s=await fetch(e,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(r?{query:t,variables:r}:{query:t}),signal:AbortSignal.timeout(n)})}catch(i){throw new nr(i.message)}if(!s.ok)throw Ht(e,s.status)??new nr(`HTTP ${s.status} ${s.statusText}`.trim());let o;try{o=await s.json()}catch(i){throw new nr(`the answer is not JSON: ${i.message}`)}if(o.errors?.length)throw new nr(o.errors.map((i)=>i.message).join("; "));if(o.data==null)throw new nr("the answer has no data");return o.data}var nr;var bn=E(()=>{Me();nr=class nr extends Error{constructor(e){super(e);this.name="IndexerQueryError",Object.setPrototypeOf(this,nr.prototype)}}});function md(e,t){if(t!==null&&t<ft.v9)throw new fd(e,t)}async function As(e){try{let r=(await It(e,"{ block { protocolVersion } }",void 0,hh)).block?.protocolVersion;return typeof r==="number"?BigInt(r):null}catch(t){if(uc(t))throw t;return null}}async function Je(e,t,r=As){md(e,await r(t.indexer))}async function gd(e,t,r={}){let n=await(r.fetchVersion??As)(t.indexer);if(n===null)throw new hi("indexer",t.indexer);if(md(e,n),await(r.fetchGenesis??Er)(t.node)===null)throw new hi("node",t.node)}function hd(e){return["shielded","unshielded","dust"].filter((t)=>e[t]<ft.v9)}var fd,hh=5000,hi;var sr=E(()=>{Ce();Es();Me();bn();fd=class fd extends Error{code="UNSUPPORTED_LEDGER";constructor(e,t){super(`${e} is on ledger 8 (protocol version ${t}), and this build of mn supports ledger 9 only.
|
|
46
46
|
Use midnight-wallet-cli 0.5.x for ledger-8 networks.`);this.name="UnsupportedLedgerError"}};hi=class hi extends Error{code="LOCAL_STACK_UNREACHABLE";constructor(e,t){super(`No ledger-9 stack is reachable: the ${e} at ${t} did not answer.
|
|
47
47
|
This build of mn can't start a localnet (no published indexer image runs ledger 9 yet).
|
|
48
48
|
Start a ledger-9 stack (node 2.1.0-rc.2, proof-server 9.0.0-rc.8, a 4.4 indexer) and point mn at it:
|
|
49
|
-
midnight config set network undeployed, then midnight config set node / indexer-ws / proof-server <url>`);this.name="LocalStackUnreachableError"}}});import
|
|
49
|
+
midnight config set network undeployed, then midnight config set node / indexer-ws / proof-server <url>`);this.name="LocalStackUnreachableError"}}});import wh from"ws";function Ar(e,t,r){return new Promise((n,s)=>{ke(t);let o=new wh(t,["graphql-transport-ws"]),i=new Map,a=0,c=0,d=0,u=!1,l=!1,p,f=()=>{let y=new Map,w=0,S=0,k=0;for(let T of i.values())if(!T.spent){w++;let N=y.get(T.tokenType)??0n;if(y.set(T.tokenType,N+T.value),T.tokenType===Lt)if(T.registeredForDustGeneration)S++;else k++}return{balances:y,utxoCount:w,txCount:a,highestTxId:c,registeredUtxos:S,unregisteredUtxos:k}},h=()=>{clearTimeout(p)},m=()=>{if(!l&&u&&(c===0||d>=c))l=!0,h(),o.send(JSON.stringify({id:"1",type:"complete"})),o.close(),n(f())};o.on("open",()=>{o.send(JSON.stringify({type:"connection_init"}))}),o.on("message",(y)=>{let w=JSON.parse(y.toString());switch(w.type){case"connection_ack":o.send(JSON.stringify({id:"1",type:"subscribe",payload:{query:yh,variables:{address:e}}}));break;case"next":{if(w.payload?.errors){let k=w.payload.errors[0]?.message||"Unknown GraphQL error";if(!l)l=!0,h(),o.close(),s(Error(`GraphQL error: ${k}`));return}let S=w.payload?.data?.unshieldedTransactions;if(!S)return;if(S.__typename==="UnshieldedTransaction"){a++;let k=S;d=Math.max(d,k.transaction.id);for(let T of k.createdUtxos){let N=`${T.intentHash}:${T.outputIndex}`;i.set(N,{value:BigInt(T.value),tokenType:T.tokenType,spent:!1,registeredForDustGeneration:T.registeredForDustGeneration===!0})}for(let T of k.spentUtxos){let N=`${T.intentHash}:${T.outputIndex}`,L=i.get(N);if(L)L.spent=!0}if(r)r(d,c);m()}else if(S.__typename==="UnshieldedTransactionsProgress")c=S.highestTransactionId,u=!0,m();break}case"error":if(!l)l=!0,h(),o.close(),s(Error(`GraphQL subscription error: ${JSON.stringify(w.payload)}`));break;case"complete":break}}),o.on("error",(y)=>{if(!l){l=!0,h();let w=y.message?.trim()?y.message:`unable to reach ${t} (connection refused, DNS, or TLS error). Is the indexer running?`;s(gr(t,y)??Error(`WebSocket connection failed: ${w}`))}}),o.on("close",()=>{if(!l)l=!0,h(),s(Error(`Indexer closed the connection before balance sync completed. Indexer: ${t}`))}),p=setTimeout(()=>{if(!l)l=!0,o.close(),s(Error(`Balance check timed out after ${Io/1000}s. Indexer: ${t}`))},Io)})}function vn(e){return e===Lt}var yh=`
|
|
50
50
|
subscription UnshieldedTransactions($address: UnshieldedAddress!) {
|
|
51
51
|
unshieldedTransactions(address: $address) {
|
|
52
52
|
__typename
|
|
@@ -60,7 +60,7 @@ Start a ledger-9 stack (node 2.1.0-rc.2, proof-server 9.0.0-rc.8, a 4.4 indexer)
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
|
-
`;var kn=E(()=>{Me()});function
|
|
63
|
+
`;var kn=E(()=>{Me()});function Sh(e,t){if(t<=0n)return[];let r=[...new Set(e)].filter((o)=>o>=0n&&o<t).sort((o,i)=>o<i?-1:o>i?1:0),n=[],s=-1n;for(let o of r){if(o>s+1n)n.push([s+1n,o-1n]);s=o}if(t-1n>s)n.push([s+1n,t-1n]);return n}function Ts(e,t,r){let n=Sh(t,r);if(n.length===0)return{state:e,collapsed:!1,rangesCollapsed:0,reason:"nothing-foreign"};let s=e.syncTime instanceof Date?e.syncTime:new Date(String(e.syncTime)),o,i;try{o=e.walletBalance(s),i=e.generatingTreeRoot()}catch(c){return{state:e,collapsed:!1,rangesCollapsed:0,reason:`no-reference: ${c.message}`}}let a=e;try{for(let[c,d]of n)a=a.collapseGenerationTree(c,d)}catch(c){return{state:e,collapsed:!1,rangesCollapsed:0,reason:`collapse-threw: ${c.message}`}}try{if(a.walletBalance(s)!==o||a.generatingTreeRoot()!==i)return{state:e,collapsed:!1,rangesCollapsed:0,reason:"guard-mismatch"};for(let c of a.utxos)if(a.generationInfo(c)===void 0)return{state:e,collapsed:!1,rangesCollapsed:0,reason:"guard-utxo-generation-missing"}}catch(c){return{state:e,collapsed:!1,rangesCollapsed:0,reason:`guard-threw: ${c.message}`}}return{state:a,collapsed:!0,rangesCollapsed:n.length}}import*as Tr from"@midnightntwrk/ledger-v9";function vh(){let e=new Tr.DustParameters(Ja,Va,qa);return new Tr.DustLocalState(e)}function wd(e,t,r={}){let{onProgress:n,onCheckpoint:s,timeoutMs:o=600000,idleMs:i=5000,initialSilenceMs:a=3000,signal:c,initialState:d,startFromId:u=0,initialRetention:l,collapse:p}=r,f=p!==!1&&process.env[wi]!=="1",h=500,m=d??vh(),y=[],w=e.publicKey,S=new Set((l?.ownedGenerationIndices??[]).map(BigInt)),k=BigInt(l?.generationFrontier??0),T=(M)=>{let O=M.content;if(O?.tag!=="dustInitialUtxo"||O.generationIndex===void 0)return;let le=O.generationIndex;if(le+1n>k)k=le+1n;if(O.generation?.owner===w)S.add(le)},N=()=>({ownedGenerationIndices:[...S].map(Number),generationFrontier:Number(k)}),L=0,J=u-1,Y=-1,V=()=>{if(y.length===0)return;if(m=m.replayEvents(e,y),L+=y.length,y.length=0,f)m=Ts(m,S,k).state;if(s&&J>=0)try{s(m,J,N())}catch{}};return Cr(t,{query:bh,variables:{id:u},idleMs:i,timeoutMs:o,initialSilenceMs:d?a:0,signal:c,onNext:(M)=>{let O=M?.dustLedgerEvents;if(!O)return!1;let le;try{le=Tr.Event.deserialize(Buffer.from(O.raw,"hex"))}catch(ge){throw Error(`Failed to deserialize dust event ${O.id}: ${ge.message}`)}if(T(le),y.push(le),J=O.id,O.maxId>Y)Y=O.maxId;if(y.length>=500)try{V()}catch(ge){throw Error(`Failed applying dust events: ${ge.message}`)}return n?.(L+y.length,Y),J>=Y},buildResult:(M)=>{try{V();let O=new Date;return m=m.processTtls(O),{balance:m.walletBalance(O),availableCoins:m.utxos.length,eventCount:L,ownedUtxoCount:m.utxos.length,syncTime:m.syncTime,state:m,retention:N(),lastAppliedEventId:J,partial:M}}catch(O){throw Error(`Failed to build dust state: ${O.message}`)}}})}var wi="MN_DISABLE_DUST_COLLAPSE",bh=`
|
|
64
64
|
subscription DustLedgerEvents($id: Int) {
|
|
65
65
|
dustLedgerEvents(id: $id) {
|
|
66
66
|
type: __typename
|
|
@@ -69,33 +69,33 @@ Start a ledger-9 stack (node 2.1.0-rc.2, proof-server 9.0.0-rc.8, a 4.4 indexer)
|
|
|
69
69
|
maxId
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
|
-
`;var yi=E(()=>{ws()});import{existsSync as
|
|
73
|
-
`,{mode:
|
|
72
|
+
`;var yi=E(()=>{ws()});import{existsSync as yd,mkdirSync as kh,readFileSync as Ch,readdirSync as xh,unlinkSync as Eh,writeFileSync as Ah}from"node:fs";import{homedir as Th}from"node:os";import{join as Ns}from"node:path";function Dh(e){return new URL(e).host}function yt(e,t,r){let n=Dh(t),s=Ns(r??Ns(Th(),te,Oe),e),o=Ns(s,Nh),i=yd(o)?Ch(o,"utf-8").trim():void 0;if(i===n)return;let a=yd(s)?xh(s).filter((u)=>u.endsWith(".json")):[],c=i??Rh[e]??n,d=0;if(c!==n)for(let u of a)Eh(Ns(s,u)),d++;return kh(s,{recursive:!0,mode:be}),Ah(o,n+`
|
|
73
|
+
`,{mode:Te}),d>0?{previous:c,current:n,removed:d}:void 0}function Rs(e,t){return`${e} is now read from ${t.current}; sync state saved from ${t.previous} can't be resumed there, so this sync starts from the beginning.`}var Nh="indexer.host",Rh;var Cn=E(()=>{Rh={preprod:"indexer.preprod.midnight.network",preview:"indexer.preview.midnight.network"}});import{spawn as Ih}from"node:child_process";import{existsSync as or,mkdirSync as _h,readFileSync as kd,readdirSync as Sd,unlinkSync as bd,writeFileSync as Ph}from"node:fs";import{homedir as Cd}from"node:os";import{dirname as vd,join as St}from"node:path";import{fileURLToPath as $h}from"node:url";import*as xd from"@midnightntwrk/ledger-v9";function Ed(){let e=process.env.MN_DUST_SYNC_BIN;if(e&&or(e))return e;let t=process.platform==="win32"?"dust-sync.exe":"dust-sync",r=vd($h(import.meta.url));for(let n of[["..",".."],[".."]]){let s=St(r,...n,"sidecar","dust-sync","target","release",t);if(or(s))return s}try{let n=`@nel349/dust-sync-${process.platform}-${process.arch}`,s=Oh(import.meta.url),o=St(vd(s.resolve(`${n}/package.json`)),t);if(or(o))return o}catch{}return null}function Oh(e){return globalThis.require??La("node:module").createRequire(e)}function Ad(){if(Mh!==Fh)return!1;if(process.env.MN_DISABLE_NATIVE_DUST==="1")return!1;return Ed()!==null}function Uh(e,t,r){if(e+1>=t)return"existing";if(r)return"seed";return"fresh"}function Lh(e){if(!or(e))return-2;try{let t=JSON.parse(kd(e,"utf-8"));return typeof t.last_applied_event_id==="number"?t.last_applied_event_id:-2}catch{return-2}}function Bh(e,t){let r=St(Cd(),te,Oe,e);if(!or(r))_h(r,{recursive:!0,mode:be});return St(r,`dust-native-${t.slice(0,20)}.json`)}function Ds(e,t){let r=St(Cd(),te,Oe);if(e&&t){try{bd(St(r,e,`dust-native-${t.slice(0,20)}.json`))}catch{}return}let n=(s)=>{if(!or(s))return;try{for(let o of Sd(s))if(o.startsWith("dust-native-")&&o.endsWith(".json"))try{bd(St(s,o))}catch{}}catch{}};if(e){n(St(r,e));return}if(!or(r))return;try{for(let s of Sd(r))n(St(r,s))}catch{}}function Td(e,t,r){return new Promise((n,s)=>{let o=Ed();if(!o){s(Error("dust-sync sidecar not found"));return}ke(t.indexerWS);let i=t.networkId.toLowerCase(),a=Ze(e),c=Bh(i,a),d=["--indexer-ws",t.indexerWS,"--out",c],u=Uh(Lh(c),r.startFromId,!!r.initialState);if(u==="seed"){let y={dust_state:Buffer.from(r.initialState.serialize()).toString("hex"),last_applied_event_id:r.startFromId-1,owned_generation_indices:r.initialRetention?.ownedGenerationIndices??[],generation_frontier:r.initialRetention?.generationFrontier??0,balance:"0",available_coins:0,events_applied:0,partial:!0};Ph(c,JSON.stringify(y),{mode:Te})}if(u!=="fresh")d.push("--resume",c);let l=Ih(o,d,{stdio:["pipe","pipe","pipe"]}),p=()=>{try{l.kill("SIGINT")}catch{}};r.signal?.addEventListener("abort",p,{once:!0}),l.stdin.on("error",()=>{});let f=Buffer.from(xt(e)).toString("hex");l.stdin.write(f+`
|
|
74
74
|
`),l.stdin.end();let h="",m="";l.stdout.on("data",(y)=>{h+=y.toString()}),l.stderr.on("data",(y)=>{let w=y.toString();m=(m+w).slice(-2000);for(let S of w.matchAll(/applied (\d+) \/ (\d+)/g))r.onProgress?.(Number(S[1]),Number(S[2]))}),l.on("error",(y)=>{r.signal?.removeEventListener("abort",p),s(y)}),l.on("close",(y)=>{if(r.signal?.removeEventListener("abort",p),y!==0){s(Error(`dust-sync exited ${y}: ${m.trim().slice(-300)}`));return}try{let w=h.trim().split(`
|
|
75
|
-
`).filter(Boolean).pop(),S=w?JSON.parse(w):JSON.parse(
|
|
76
|
-
Expected a bech32m address for network "${t.networkId}"`)}}function
|
|
75
|
+
`).filter(Boolean).pop(),S=w?JSON.parse(w):JSON.parse(kd(c,"utf-8"));n(Wh(S))}catch(w){s(Error(`dust-sync output parse failed: ${w.message}`))}})})}function Wh(e){let t=new Date,r=xd.DustLocalState.deserialize(new Uint8Array(Buffer.from(e.dust_state,"hex")));if(process.env[wi]!=="1"){let s=new Set(e.owned_generation_indices.map((o)=>BigInt(o)));r=Ts(r,s,BigInt(e.generation_frontier)).state}r=r.processTtls(t);let n=r.utxos.length;return{balance:r.walletBalance(t),availableCoins:n,eventCount:e.events_applied,ownedUtxoCount:n,syncTime:r.syncTime instanceof Date?r.syncTime:new Date(String(r.syncTime)),state:r,retention:{ownedGenerationIndices:e.owned_generation_indices,generationFrontier:e.generation_frontier},lastAppliedEventId:e.last_applied_event_id,partial:e.partial}}var Mh=8,Fh=9;var Si=E(()=>{Me();Vt();yi();er()});import*as Rd from"@midnightntwrk/ledger-v9";class Dd{now;fetchTip;fetchUnshielded;fetchDust;fetchChainId;fetchEventTip;fetchProtocolVersion;cacheDir;dustMemo=new Map;unshieldedMemo=new Map;tipMemo=new Map;constructor(e={}){this.now=e.now??Date.now,this.fetchTip=e.fetchTip??qh,this.fetchUnshielded=e.fetchUnshielded??zh,this.fetchDust=e.fetchDust??Xh,this.fetchChainId=e.fetchChainId??Er,this.fetchEventTip=e.fetchEventTip??ys,this.fetchProtocolVersion=e.fetchProtocolVersion??As,this.cacheDir=e.cacheDir}keepCachesOfThisIndexer(e,t,r){let n=yt(e,t.indexerWS,this.cacheDir);if(n)r?.(Rs(e,n))}async freshWalletOnDustCheckpoint(e,t,r){let n=kr(r,Ze(e),this.cacheDir);if(!n||n.lastAppliedEventId<0)return null;let s=await et(e,t,null);try{let{shielded:o,unshielded:i,dust:a}=s.facade,[c,d,u]=await Promise.all([o.serializeState(),i.serializeState(),a.serializeState()]);return{shielded:c,unshielded:d,dust:wn(u,n)}}finally{await We(s).catch(()=>{})}}async dust(e,t,r={}){let n=Is(t);await Je(n,t,this.fetchProtocolVersion);let s=Ze(e),o=`${n}:${s}`;if(!r.forceFresh){let y=await this.tryMemo(o,t,this.dustMemo,r.signal);if(y)return{...y,fromCache:!0,eventsApplied:0}}let i=await this.fetchChainId(t.node).catch(()=>null);Xc(n,i,this.cacheDir),this.keepCachesOfThisIndexer(n,t,r.onStatus);let a=i??void 0,c=r.forceFresh?null:kr(n,s,this.cacheDir);if(c&&Ss(c.lastAppliedEventId,await this.fetchEventTip(t.indexerWS,"dust")))ht(n,s,this.cacheDir),c=null;let d=c!==null,u=0,l=c?.lastAppliedEventId??-1,p=null,f=this.now(),h=0;for(let y=0;;y++){if(r.signal?.aborted)throw Error("Operation cancelled");let w=c?c.lastAppliedEventId+1:0;if(r.onStatus?.(y>0?`Resuming dust from event ${w} (continuation ${y+1})…`:c?`Resuming dust from event ${w}…`:"Reading dust events…"),p=await this.fetchDust(e,t,{startFromId:w,initialState:c?.state,initialRetention:c?.retention,signal:r.signal,onProgress:(S,k)=>{let T=Math.max(1,k+1-w);r.onStatus?.(`Reading dust events… ${S}/${T}`),r.onProgress?.(S,k)},onCheckpoint:(S,k,T)=>{try{ui(n,s,S,k,this.cacheDir,a,T)}catch{}}}),l=p.lastAppliedEventId>=0?p.lastAppliedEventId:c?.lastAppliedEventId??-1,p.lastAppliedEventId>=0||!c)try{ui(n,s,p.state,l,this.cacheDir,a,p.retention)}catch{}if(u+=p.eventCount,!p.partial)break;if(h=p.eventCount>0?0:h+1,h>=Gh||this.now()-f>=Hh)break;c=kr(n,s,this.cacheDir)}if(!p)throw Error("Dust sync exhausted retries without producing a result");let m={state:p.state,balance:p.balance,availableCoins:p.availableCoins,ownedUtxoCount:p.ownedUtxoCount,syncTime:p.syncTime,fromCache:d,eventsApplied:u,lastAppliedEventId:l,partial:p.partial,fetchedAt:this.now()};return await this.memoize(this.dustMemo,o,m,t,r.signal),m}async unshielded(e,t,r={}){let n=Is(t),s=typeof e==="string"?e:Ie(e,n),o=`${n}:${s}`;if(!r.forceFresh){let c=await this.tryMemo(o,t,this.unshieldedMemo,r.signal);if(c)return{...c,fromCache:!0}}let a={...await this.fetchUnshielded(s,t,r.onProgress),fromCache:!1,fetchedAt:this.now()};return await this.memoize(this.unshieldedMemo,o,a,t,r.signal),a}async withFacade(e,t,r,n={}){let s=n.syncMode??"full",o=n.requireStrictSync??!0,i=o&&!n.readOnly,a=Is(t),c=Ie(e,a),d=t.networkId!=="Undeployed",u=n.syncTimeoutMs??(d?Jh:Kh);await Je(a,t,this.fetchProtocolVersion);let l=await this.fetchChainId(t.node).catch(()=>null);ud(a,l,this.cacheDir),this.keepCachesOfThisIndexer(a,t,n.onStatus);let p=l??void 0;if(i&&!n.noPrime&&!n.forceFresh)try{await this.dust(e,t,{signal:n.signal,onStatus:n.onStatus})}catch(w){n.onSyncWarning?.("PrePrime",w.message)}let f,h,m=!1,y=async()=>{if(m||!f)return;m=!0;try{await We(f)}catch{}};try{for(let k=1;k<=xn;k++){if(n.signal?.aborted)throw Error("Operation cancelled");let T=n.forceFresh?null:Dt(c,a,this.cacheDir)??await this.freshWalletOnDustCheckpoint(e,t,a);f=await et(e,t,T);try{h=await Rt(f,{onProgress:n.onSyncProgress,onSyncDetail:n.onSyncDetail,timeoutMs:u,syncMode:s,requireStrictSync:o});break}catch(N){if(n.signal?.aborted)throw Error("Operation cancelled");if(N instanceof vs&&k<xn&&i){n.onStatus?.(`Cache is stale, clearing and rebuilding (attempt ${k+1}/${xn})...`),await We(f).catch(()=>{}),f=void 0,rt(c,a,this.cacheDir),ht(a,Ze(e),this.cacheDir);try{await this.dust(e,t,{signal:n.signal,onStatus:n.onStatus})}catch{}continue}if(k<xn&&String(N?.message??"").includes("timed out")){try{await wt(c,a,f.facade,this.cacheDir,p)}catch{}n.onStatus?.(`Sync timed out, retrying (attempt ${k+1}/${xn})...`),await We(f).catch(()=>{}),f=void 0;continue}throw N}}if(!f||!h)throw Error("Sync failed: no facade state after retries");let w,S=0;while(!0){if(S++,n.signal?.aborted)throw Error("Operation cancelled");try{w=await r({bundle:f,state:h});break}catch(k){if(!(i&&S<Nd&&ps(k)))throw k;if(n.onStatus?.(`Refreshing wallet state (attempt ${S+1}/${Nd})...`),await We(f).catch(()=>{}),f=void 0,await new Promise((L)=>setTimeout(L,Vh)),n.signal?.aborted)throw Error("Operation cancelled");let N=Dt(c,a,this.cacheDir);f=await et(e,t,N),h=await Rt(f,{onProgress:n.onSyncProgress,onSyncDetail:n.onSyncDetail,timeoutMs:u,syncMode:s,requireStrictSync:o})}}if(!n.skipAutoSave)try{await wt(c,a,f.facade,this.cacheDir,p)}catch{}if(!n.readOnly)this.invalidate({network:t,seed:e});return w}finally{await y()}}invalidate(e){let t=Is(e.network),r=e.kinds??["dust","unshielded","facade"];if(r.includes("dust"))if(e.seed){let n=Ze(e.seed);this.dustMemo.delete(`${t}:${n}`)}else this.deleteByPrefix(this.dustMemo,`${t}:`);if(r.includes("unshielded")){let n=e.address??(e.seed?Ie(e.seed,t):null);if(n)this.unshieldedMemo.delete(`${t}:${n}`);else this.deleteByPrefix(this.unshieldedMemo,`${t}:`)}if(r.includes("facade")&&e.seed){let n=Ie(e.seed,t);try{rt(n,t,this.cacheDir)}catch{}}}resetTipMemo(){this.tipMemo.clear()}async tryMemo(e,t,r,n){let s=r.get(e);if(!s)return null;let o;try{o=await this.getTip(t,n)}catch{return s.value}if(o===s.tipAtFetch)return s.value;return r.delete(e),null}async memoize(e,t,r,n,s){try{let o=await this.getTip(n,s);e.set(t,{value:r,fetchedAt:this.now(),tipAtFetch:o})}catch{U("repo",`tip unavailable; skipping memo for ${t}`)}}async getTip(e,t){let r=this.tipMemo.get(e.networkId);if(r&&this.now()-r.fetchedAt<jh)return r.tip;let n=await this.fetchTip(e,t);return this.tipMemo.set(e.networkId,{tip:n,fetchedAt:this.now()}),n}deleteByPrefix(e,t){for(let r of e.keys())if(r.startsWith(t))e.delete(r)}}function qh(e){return xr({url:e.node,timeoutMs:3000},"chain_getBlockHash",[])}function zh(e,t,r){return Ar(e,t.indexerWS,r)}function Yh(e,t,r){let n=xt(e),s=Rd.DustSecretKey.fromSeed(n);return wd(s,t.indexerWS,r)}async function Xh(e,t,r){if(Ad())try{return await Td(e,t,r)}catch(n){U("dust",`native sidecar failed, using WASM: ${n.message}`)}return Yh(e,t,r)}function Is(e){let t=e.networkId.toLowerCase();if(De(t))return t;throw Error(`Unsupported network: ${e.networkId}`)}function $e(){if(!bi)bi=new Dd;return bi}var jh=5000,Hh=3600000,Gh=3,Kh=30000,Jh=120000,xn=3,Nd=5,Vh=5000,bi=null;var _t=E(()=>{Ce();tt();Xt();er();rr();Es();sr();kn();yi();Cn();Si();Nt();xs();Vt();Xe();bs()});async function Id(e){try{let r=(await It(e,"{ block { timestamp } }",void 0,5000)).block?.timestamp;return typeof r==="number"?new Date(r):null}catch{return null}}function _d(e,t){if(t.getTime()-e.getTime()>Zh)throw new vi(e,t)}var Zh=120000,vi;var Pd=E(()=>{bn();fn();vi=class vi extends Error{code="CHAIN_CLOCK_BEHIND";constructor(e,t){super(`This chain's clock is ${Ge(t.getTime()-e.getTime())} behind this computer's (its latest block is stamped ${e.toISOString()}). Dust is generated in chain time, so a registration now would be refused for an unpaid fee. A local chain falls behind like this after the machine sleeps and catches up as it produces blocks: run midnight dust register again once it has, or restart the local chain.`);this.name="ChainClockBehindError",Object.setPrototypeOf(this,vi.prototype)}}});import*as xi from"@midnightntwrk/ledger-v9";import{MidnightBech32m as Qh,UnshieldedAddress as ew}from"@midnightntwrk/wallet-sdk/address-format";function Pt(e){if(e<=0)throw Error("Amount must be greater than 0");if(!Number.isFinite(e))throw Error("Amount must be a finite number");let t=e.toFixed(6),[r,n]=t.split("."),s=r+(n??"").padEnd(6,"0"),o=BigInt(s);if(o<=0n)throw Error("Amount too small — minimum is 0.000001 NIGHT");return o}function Nr(e){let t=e.trim(),r=/^(\d*)(?:\.(\d*))?$/.exec(t);if(!r||r[1]===""&&!r[2])throw new R(`Invalid amount: "${e}" — must be a positive number, e.g. 1.5`);let n=r[2]??"";if(n.length>ki)throw new R(`Invalid amount: "${e}" — NIGHT has ${ki} decimals, this has ${n.length}`);let s=Number(t);if(s<=0)throw new R(`Invalid amount: "${e}" — must be greater than 0`);let o=BigInt((r[1]||"0")+n.padEnd(ki,"0"));if(Pt(s)!==o)throw new R(`Invalid amount: "${e}" — too many digits to handle exactly`);return s}function tw(e,t){let r=He(t.networkId);try{return Qh.parse(e).decode(ew,r)}catch(n){throw Error(`Invalid recipient address: ${n.message}
|
|
76
|
+
Expected a bech32m address for network "${t.networkId}"`)}}function Ci(e){let t=Math.round(e/1000);if(t<60)return`${t}s`;let r=Math.floor(t/60),n=t%60;return`${r}m ${n}s`}function Ue(){let{warn:e,error:t}=console,r=(n)=>n.some((s)=>String(s).includes("RPC-CORE"));return console.warn=(...n)=>{if(!r(n))e(...n)},console.error=(...n)=>{if(!r(n))t(...n)},()=>{console.warn=e,console.error=t}}async function rw(e,t,r,n){await Promise.race([e.facade.dust.waitForSyncedState(),new Promise((a,c)=>setTimeout(()=>c(Error("Insufficient funds: dust wallet sync timed out")),Jn))]);let{fee:s}=await e.facade.estimateRegistration(t);await e.facade.waitForGeneratedDust(t,s,{timeoutMs:n});let o=await e.facade.registerNightUtxosForDustGeneration(t,e.keystore.getPublicKey(),e.keystore.signDataAsync,r),i;try{i=await e.facade.finalizeRecipe(o)}catch(a){try{await e.facade.revert(o)}catch{}throw a}return await e.facade.submitTransaction(i)}async function nw(e,t,r,n){let s=Date.now(),o=s+tc,i,a=!1,c=e.indexerHttpUrl?await Id(e.indexerHttpUrl):null;if(c)_d(c,new Date);let{fee:d,dustGenerationEstimations:u}=await e.facade.estimateRegistration(t),l=Ic(d,u);if(l.waitMs===null||l.waitMs>o-Date.now())throw new ls(l,new Date);let p=l.waitMs>0?`, fee covered in ${Ge(l.waitMs)}`:"";if(l.waitMs>0)n?.(`Waiting for the NIGHT to generate the ${pe(l.fee)} DUST registration fee (${Ge(l.waitMs)})...`);let f=setInterval(()=>{if(a&&n){let h=Ci(Date.now()-s);n(`Waiting for dust generation capacity (${h} elapsed${p})...`)}},1000);try{while(Date.now()<o)try{return await rw(e,t,r,o-Date.now())}catch(h){if(i=h,us(h)&&Date.now()+_o<o){a=!0;let m=Ci(Date.now()-s);n?.(`Waiting for dust generation capacity (${m} elapsed${p})...`),await new Promise((y)=>setTimeout(y,_o));continue}throw h}throw i??Error("Dust registration timed out")}finally{clearInterval(f)}}async function at(e,t,r){let n=r??await e.facade.waitForSyncedState();if(tr(n))return t?.("Dust available"),{alreadyAvailable:!0};if(n.unshielded.availableCoins.length===0&&(n.unshielded.pendingCoins?.length??0)===0)throw Error("This wallet has no NIGHT, so it generates no Dust to pay fees. Fund it first (on undeployed: midnight airdrop <amount>), then run: midnight dust register");let s=n.unshielded.availableCoins.filter((a)=>!a.meta.registeredForDustGeneration),o;if(s.length>0)t?.(`Registering ${s.length} UTXO(s) for dust generation...`),o=await nw(e,s,n.dust.address,t);else t?.("UTXOs already registered, waiting for dust generation...");t?.("Waiting for dust tokens...");let i=Date.now();while(Date.now()-i<Do){try{if((await Promise.race([e.facade.waitForSyncedState(),new Promise((c,d)=>setTimeout(()=>d(Error("Poll sync timed out")),Jn))])).dust.balance(new Date)>0n)return t?.("Dust available"),{alreadyAvailable:!1,txHash:o}}catch{}await new Promise((a)=>setTimeout(a,5000))}throw Error("Timed out waiting for dust tokens. Try running: midnight dust register")}async function sw(e,t,r,n,s,o,i,a){let c=Date.now(),d=c+Do,u,l=0;while(!0)try{if(u)await fi(e,"lite");let p=new Date(Date.now()+qn*60*1000);U("transfer","Building transfer transaction...");let f=await e.facade.transferTransaction([{type:"unshielded",outputs:[{amount:r,receiverAddress:t,type:xi.unshieldedToken().raw}]}],{ttl:p,payFees:!0});U("transfer","Signing recipe...");let h=await e.facade.signRecipe(f,e.keystore.signDataAsync);U("transfer","Generating ZK proof..."),n?.();let m=await Promise.race([e.facade.finalizeRecipe(h),new Promise((k,T)=>{setTimeout(()=>T(Error("ZK proof generation timed out")),Vn)})]);U("transfer","Submitting transaction to node..."),s?.();let y=Date.now(),w=i?setInterval(()=>i(Date.now()-y),1000):void 0,S;try{S=await e.facade.submitTransaction(m)}finally{if(w)clearInterval(w)}return U("transfer",`Transaction submitted: ${S}`),S}catch(p){if(u=p,(p?.code===rc||p?.message?.includes("115")||p?.message?.toLowerCase().includes("stale"))&&++l<ec)continue;if(ps(p))throw p;if(us(p)&&Date.now()<d){let h=Ci(Date.now()-c);o?.(`Dust insufficient, re-ensuring (${h} elapsed)...`);try{let m=await fi(e,"lite");if(await ms(m.dust,Xr,o,a),m.dust.balance(new Date)>=Xr)o?.(`Dust is short of this transaction's fee; waiting ${$d/1000} s for more...`),await Zt($d,a);await at(e,o,m)}catch(m){if(String(m?.message).startsWith("Insufficient dust"))throw m;await new Promise((y)=>setTimeout(y,5000))}continue}throw p}}async function Rr(e){let{seedBuffer:t,networkConfig:r,recipientAddress:n,amountNight:s,signal:o,onSync:i,onSyncDetail:a,onDust:c,onProving:d,onSubmitting:u,onSubmittingTick:l,onSyncWarning:p}=e,f=Pt(s),h=tw(n,r),m=Fe(p),y=Ue();try{return await $e().withFacade(t,r,async({bundle:w,state:S})=>{if(o?.aborted)throw Error("Operation cancelled");U("transfer","Sync complete, checking balance...");let k=S.unshielded.balances[xi.unshieldedToken().raw]??0n,T=S.unshielded.availableCoins?.length??0;if(U("transfer",`Balance: ${Number(k)/Bt} NIGHT, coins: ${T}`),k<f){let J=Number(k)/Bt;throw Error(`Insufficient balance: ${J.toFixed(6)} NIGHT available, ${s} NIGHT requested`)}if(await ms(S.dust,Xr,c,o),o?.aborted)throw Error("Operation cancelled");if(U("transfer","Ensuring dust availability..."),!(await at(w,c,S)).alreadyAvailable){let J,Y=await Promise.race([w.facade.waitForSyncedState(),new Promise((V)=>{J=setTimeout(()=>V(null),Jn)})]).finally(()=>clearTimeout(J));if(Y)await ms(Y.dust,Xr,c,o)}if(U("transfer","Dust available"),o?.aborted)throw Error("Operation cancelled");return U("transfer","Building and submitting transaction..."),{txHash:await sw(w,h,f,d,u,c,l,o),amountMicroNight:f}},{syncMode:"lite",requireStrictSync:!0,signal:o,onStatus:c,onSyncProgress:i,onSyncDetail:a,onSyncWarning:p})}finally{y(),m()}}var ki=6,$d=1e4;var bt=E(()=>{gt();tt();_t();Nt();ue();Xt();Xt();fn();Pd();vr();de()});import*as Od from"node:readline";function aw(e){return ow.has(e)}function cw(e){return iw.has(e)}function dw(e){let t=[],r=e.dappName?`Request from "${e.dappName}"`:"DApp Request";if(t.push(P(r)),t.push(""),t.push(` ${g("Action:")} ${X(e.method)}`),t.push(` ${g("Network:")} ${e.network}`),e.details.length>0){t.push("");for(let n of e.details)t.push(` ${g(n.label+":")} ${n.value}`)}return t.push(""),t.push(` ${z("[A]pprove")} ${he("[R]eject")}`),Dc(t,"heavy")}function lw(e,t){if(t.approveFees)return`--approve-fees approves only paying the Dust fee for an agent's own balanced transaction (and its submit); ${e.method} needs a terminal to approve`;return`${cw(e.method)?"Balancing prompts like any other write":`${e.method} needs a terminal to approve`}: use --approve-all for non-interactive environments, or --approve-fees for a fee wallet that only pays an agent's Dust fee`}async function Md(e,t={}){if(t.approveAll)return process.stderr.write(g(` Auto-approved: ${e.method}`)+`
|
|
77
77
|
`),"approve";if(t.approveFees&&e.feeOnly)return process.stderr.write(g(` Auto-approved (fee-only): ${e.method}`)+`
|
|
78
|
-
`),"approve";if(t.autoApproveReads&&
|
|
78
|
+
`),"approve";if(t.autoApproveReads&&aw(e.method))return process.stderr.write(g(` Auto-approved (read-only): ${e.method}`)+`
|
|
79
79
|
`),"approve";if(!process.stdin.isTTY)return process.stderr.write(he(" Cannot prompt for approval: stdin is not a TTY")+`
|
|
80
|
-
`),process.stderr.write(g(` ${
|
|
80
|
+
`),process.stderr.write(g(` ${lw(e,t)}`)+`
|
|
81
81
|
`),"reject";if(En)return process.stderr.write(he(" Rejected: another approval prompt is active")+`
|
|
82
82
|
`),"reject";process.stderr.write(`
|
|
83
|
-
`+
|
|
83
|
+
`+dw(e)+`
|
|
84
84
|
|
|
85
|
-
`),En=!0;let r;try{r=
|
|
86
|
-
`),"reject"}return new Promise((n)=>{let s=(o)=>{En=!1,r.close(),n(o)};r.on("close",()=>{if(En)s("reject")}),r.question(ee(" Approve? [A/r] "),(o)=>{let i=o.trim().toLowerCase();if(i==="r"||i==="reject")s("reject");else s("approve")})})}var
|
|
87
|
-
`)}),c.on("connection",(l)=>{let p=`conn_${++
|
|
85
|
+
`),En=!0;let r;try{r=Od.createInterface({input:process.stdin,output:process.stderr})}catch{return En=!1,process.stderr.write(he(" Cannot create readline interface")+`
|
|
86
|
+
`),"reject"}return new Promise((n)=>{let s=(o)=>{En=!1,r.close(),n(o)};r.on("close",()=>{if(En)s("reject")}),r.question(ee(" Approve? [A/r] "),(o)=>{let i=o.trim().toLowerCase();if(i==="r"||i==="reject")s("reject");else s("approve")})})}var ow,iw,En=!1;var Fd=E(()=>{de();ow=new Set(["getShieldedBalances","getUnshieldedBalances","getDustBalance","getShieldedAddresses","getUnshieldedAddress","getDustAddress","getTxHistory","getConfiguration","getConnectionStatus"]),iw=new Set(["balanceUnsealedTransaction","balanceSealedTransaction"])});import{WebSocketServer as uw}from"ws";function fw(e){if(Ei(e))return pw[e.code]??-32603;return-32603}function Ei(e){return typeof e==="object"&&e!==null&&"type"in e&&e.type==="DAppConnectorAPIError"}function mw(e){if(!(e instanceof Error)&&!(typeof e==="object"&&e!==null&&("_tag"in e)))return;let t=[],r=e.cause,n=new Set;while(r&&!n.has(r)){n.add(r);let s=r;if(r instanceof Error||typeof r==="object"&&s._tag){let o=s._tag,i=s.message??"";t.push(o?`[${o}] ${i}`:i),r=s.cause}else if(typeof r==="string"){t.push(r);break}else{try{t.push(JSON.stringify(r))}catch{t.push(String(r))}break}}if(t.length===0)return;return{causes:t}}function _s(e,t){if(typeof t==="bigint")return t.toString();return t}function gw(e,t){return t}function hw(e){let t;try{t=JSON.parse(e,gw)}catch{throw Object.assign(Error("Parse error"),{rpcCode:-32700})}if(typeof t!=="object"||t===null||t.jsonrpc!=="2.0"||typeof t.method!=="string")throw Object.assign(Error("Invalid Request"),{rpcCode:-32600});let r=t;if(r.id===void 0||r.id===null)throw Object.assign(Error("Missing request id"),{rpcCode:-32600});return r}function Ud(e){let{port:t,handlers:r,onConnect:n,onDisconnect:s,onRequest:o,onResponse:i}=e,a=new Map,c=new uw({port:t,host:"127.0.0.1"}),d=new Promise((l,p)=>{c.once("listening",()=>l()),c.once("error",p)});d.catch(()=>{}),c.on("error",(l)=>{process.stderr.write(`WebSocket server error: ${l.message}
|
|
87
|
+
`)}),c.on("connection",(l)=>{let p=`conn_${++ww}`,f={ws:l,id:p,connectedAt:new Date,authenticated:!1,requestCount:0,notify(y,w){if(l.readyState!==l.OPEN)return;let S={jsonrpc:"2.0",method:y,...w&&{params:w}};l.send(JSON.stringify(S,_s))}};a.set(p,f),n?.(f);let h=!1,m=()=>{if(h)return;h=!0,a.delete(p),s?.(f)};l.on("message",async(y)=>{let w=null,S,k,T=Date.now();try{S=hw(y.toString("utf-8")),w=S.id,f.requestCount++,o?.(f,S);let N=Object.hasOwn(r,S.method)?r[S.method]:void 0;if(!N){let V={jsonrpc:"2.0",id:S.id,error:{code:-32601,message:`Method not found: ${S.method}`}};l.send(JSON.stringify(V,_s));return}k={notify:f.notify.bind(f),connectionId:p,requestId:S.id,metadata:{}};let L=await N(S.params??{},k),J=Date.now()-T;if(S.method==="connect"&&L&&typeof L==="object")f.authenticated=!0,f.networkId=L.networkId;let Y={jsonrpc:"2.0",id:S.id,result:L};l.send(JSON.stringify(Y,_s)),i?.(f,S,J,L,void 0,k.metadata)}catch(N){let L=Date.now()-T,J=N?.rpcCode??fw(N),Y=N instanceof Error?N.message:"Internal error",V=Ei(N)?{type:N.type,code:N.code}:mw(N),M={jsonrpc:"2.0",id:w,error:{code:J,message:Y,data:V}};if(l.send(JSON.stringify(M,_s)),S){let O={message:Y,code:Ei(N)?N.code:void 0};i?.(f,S,L,void 0,O,k?.metadata)}}}),l.on("close",m),l.on("error",()=>{m();try{l.close()}catch{}})});async function u(){for(let l of a.values())l.ws.close(1001,"Server shutting down");return a.clear(),new Promise((l,p)=>{c.close((f)=>{if(f)p(f);else l()})})}return{wss:c,connections:a,ready:d,close:u}}function K(e,t){let r=Error(t);return r.type="DAppConnectorAPIError",r.code=e,r.reason=t,r}var pw,ww=0;var Ai=E(()=>{pw={Rejected:-32000,PermissionRejected:-32001,Disconnected:-32002,InvalidRequest:-32602,InternalError:-32603}});function Ld(e){let t=[],r,n;function s(){if(r!==void 0&&n!==void 0){let a=Date.now()-n;t.push({phase:r,durationMs:a}),e?.onComplete?.(r,a),r=void 0,n=void 0}}function o(a){s(),r=a,n=Date.now(),e?.onStart?.(a)}function i(){return[...t]}return{start:o,complete:s,getTimings:i}}function Bd(e){return Buffer.from(e).toString("hex")}function ir(e){if(!/^[0-9a-fA-F]*$/.test(e))throw Error("Invalid hex string: contains non-hex characters");if(e.length%2!==0)throw Error("Invalid hex string: odd length");return new Uint8Array(Buffer.from(e,"hex"))}function jd(e,t){if(e<=t.maxFeeSpecks)return;return`the estimated fee ${pe(e)} DUST is over --max-fee ${pe(t.maxFeeSpecks)} DUST`}function Hd(e,t){if(e<t.maxPending)return;return`${e} balanced transactions are still waiting to be submitted (--max-pending ${t.maxPending})`}var yw,Wd;var Gd=E(()=>{ue();de();yw=10n**15n,Wd={maxFeeSpecks:10n*yw,maxPending:2}});import{Transaction as Sw}from"@midnightntwrk/ledger-v9";function Ti(e,t){let r=[];r.push({label:"Tx size",value:Cw(e.length/2)});let n=bw(e,t);if(n){let s=vw(n);if(s.action)r.push({label:"Type",value:s.action});if(s.circuits.length>0)r.push({label:"Circuits",value:s.circuits.join(", ")});if(s.ttl)r.push({label:"TTL",value:s.ttl})}return r}function bw(e,t){let r=kw(e),n=t==="sealed"?[["signature","proof","binding"],["signature","proof","pre-binding"]]:[["signature","proof","pre-binding"],["signature","pre-proof","pre-binding"]];for(let[s,o,i]of n)try{return Sw.deserialize(s,o,i,r).toString(!0)}catch{}return null}function vw(e){let t={networkId:null,action:null,circuits:[],ttl:null},r=e.match(/network_id:\s*"([^"]+)"/);if(r)t.networkId=r[1];if(e.includes("Deploy ContractState"))t.action="Deploy contract";else if(e.match(/Call\s/))t.action="Call contract";let n=/(\w+):\s*<verifier key>/g,s;while((s=n.exec(e))!==null)t.circuits.push(s[1]);if(t.circuits.length===0){let i=e.match(/Call\s+\S+\s+(\w+)/);if(i)t.circuits.push(i[1])}let o=e.match(/ttl:\s*Timestamp\((\d+)\)/);if(o){let i=parseInt(o[1],10),a=new Date(i*1000);t.ttl=a.toISOString().replace("T"," ").slice(0,19)}return t}function kw(e){return new Uint8Array(Buffer.from(e,"hex"))}function Cw(e){if(e<1024)return`${e} B`;let t=e/1024;if(t<1024)return`${t.toFixed(1)} KB`;return`${(t/1024).toFixed(1)} MB`}var Kd=()=>{};import{Transaction as Jd,addressFromKey as Vd}from"@midnightntwrk/ledger-v9";function Dr(e,t){return t==="unsealed"?Jd.deserialize("signature","proof","pre-binding",e):Jd.deserialize("signature","proof","binding",e)}function Ni(e){return new Set([xw,...e.intents?.keys()??[],...e.fallibleOffer?.keys()??[]])}function qd(e,t){return[...e.intents??new Map].filter(([,r])=>r.ttl.getTime()<=t.getTime()).map(([r,n])=>({segment:r,ttl:n.ttl}))}function Ri(e){let t=[];for(let[r,n]of e.intents??new Map){let s=[["guaranteed",n.guaranteedUnshieldedOffer],["fallible",n.fallibleUnshieldedOffer]];for(let[o,i]of s)i?.inputs.forEach((a,c)=>t.push({where:`intent ${r} ${o} unshielded input ${c}`,owner:a.owner,signed:i.signatures[c]!==void 0}))}return t}function zd(e,t){if(e.rewards!==void 0)return["it is a rewards claim, not a standard transaction"];let r=[],n=Vd(t);for(let{where:s,owner:o,signed:i}of Ri(e)){if(Vd(o)===n)r.push(`${s} spends this wallet's own funds`);if(!i)r.push(`${s} is unsigned, so this wallet would sign it`)}for(let s of Ni(e)){let o;try{o=e.imbalances(s)}catch(i){r.push(`segment ${s}'s balance could not be computed: ${i.message??i}`);continue}for(let[i,a]of o){if(i.tag==="dust"||a>=0n)continue;r.push(`segment ${s} is short ${-a} of ${i.tag} token ${i.raw}, which a Dust-only balance can't fund`)}}return r}var xw=0;var Di=()=>{};function Yd(e){let t=Ri(e),r=t.filter((n)=>n.signed).length;if(r===0)return"none";return r===t.length?"all":"some"}function Ew(e){return[...Ni(e)].filter((t)=>[...e.imbalances(t)].some(([r,n])=>r.tag==="unshielded"&&n!==0n))}function Xd(e,t){let r=Yd(e);if(r==="some")throw new Ir;if(r==="all"&&t){let n=Ew(e);if(n.length>0)throw new Ii(n)}}async function Zd(e,t,r){if(t.type!=="UNBOUND_TRANSACTION")return e.signRecipe(t,r);let n=Dr(t.baseTransaction.serialize(),"unsealed"),s=Yd(n);if(s==="none")return e.signRecipe(t,r);if(s==="some")throw new Ir;if(!t.balancingTransaction)return t;let o=await e.signRecipe({type:"UNPROVEN_TRANSACTION",protocolVersion:t.protocolVersion,transaction:t.balancingTransaction},r);if(o.type!=="UNPROVEN_TRANSACTION")throw Error(`The wallet SDK signed an unproven transaction into a ${o.type} recipe`);return{...t,balancingTransaction:o.transaction}}var Ir,Ii;var Qd=E(()=>{Di();Ir=class Ir extends Error{constructor(){super("The transaction has both signed and unsigned unshielded inputs. This wallet can't add its signatures to it without duplicating the existing ones (a wallet SDK limitation): send it with every unshielded input signed, or with none signed.");this.name="PartlySignedTransactionError",Object.setPrototypeOf(this,Ir.prototype)}};Ii=class Ii extends Error{constructor(e){super(`The transaction's unshielded inputs are already signed, but segment ${e.join(", ")} is not balanced in unshielded value. This wallet balances it by adding inputs and outputs to the same intent, which invalidates those signatures. Leave the unshielded inputs unsigned so they are signed after balancing, or balance the sealed transaction with balanceSealedTransaction, which adds a separate intent.`);this.name="SignedTransactionNeedsUnshieldedError",Object.setPrototypeOf(this,Ii.prototype)}}});function el(e,t){switch(t){case"hex":try{return ir(e)}catch(r){throw Error(`data is not valid hex: ${r.message}`)}case"base64":if(!Aw.test(e))throw Error("data is not valid base64 (standard alphabet, padded)");return new Uint8Array(Buffer.from(e,"base64"));case"text":return new Uint8Array(Buffer.from(e,"utf-8"));default:throw Error(`Unknown encoding: ${t} (use hex, base64 or text)`)}}function tl(e){let t=Buffer.from(`midnight_signed_message:${e.length}:`,"utf-8");return new Uint8Array(Buffer.concat([t,e]))}var Aw;var rl=E(()=>{Aw=/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/});async function nl(e,t){let r;try{r=await It(e,Nw,{hash:t},Tw)}catch(o){throw new An(t,o.message)}let n=r.transactions?.find((o)=>o.__typename==="RegularTransaction");if(!n)throw new An(t,"the indexer has no such transaction");let s=n.transactionResult?.status;if(s!=="PARTIAL_SUCCESS")throw new An(t,`the indexer reports it as ${s??"having no result"}, not a partial success`);return n.transactionResult?.segments??[]}var Tw=1e4,Nw=`query ($hash: HexEncoded!) {
|
|
88
88
|
transactions(offset: { hash: $hash }) {
|
|
89
89
|
__typename
|
|
90
90
|
... on RegularTransaction { transactionResult { status segments { id success } } }
|
|
91
91
|
}
|
|
92
|
-
}`,
|
|
93
|
-
`)},
|
|
94
|
-
`)}function
|
|
95
|
-
`);let _=
|
|
96
|
-
`),await Zt(we),v+=we;continue}if(
|
|
97
|
-
`),await lt(Zr)!=="appeared")await Zt(Zr);
|
|
98
|
-
`)}};function
|
|
92
|
+
}`,An;var sl=E(()=>{bn();An=class An extends Error{constructor(e,t){super(`Could not read the segment results of transaction ${e} from the indexer: ${t}`);this.name="SegmentResultsUnavailableError",Object.setPrototypeOf(this,An.prototype)}}});import*as _r from"rxjs";import{MidnightBech32m as ol,UnshieldedAddress as Rw,ShieldedAddress as Dw}from"@midnightntwrk/wallet-sdk/address-format";function vt(e){let t=[],r=e,n=new Set;while(r&&!n.has(r)){n.add(r);let o=r;if(r instanceof Error||typeof r==="object"&&o._tag){let i=o._tag,a=o.message??"";if(i&&a)t.push(`[${i}] ${a}`);else if(a)t.push(a);else if(i)t.push(`[${i}]`);if(o.data&&typeof o.data==="object")try{t.push(`data=${JSON.stringify(o.data)}`)}catch{}r=o.cause}else if(typeof r==="string"){t.push(r);break}else{try{let i=JSON.stringify(r);if(i&&i!=="{}")t.push(i);else t.push(String(r))}catch{t.push(String(r))}break}}let s=[];for(let o of t)if(s.length===0||s[s.length-1]!==o)s.push(o);return s.join(" → ")||"Unknown error"}function al(e,t){switch(e.lifecycle.status){case"finalized":return{txHash:e.hash,txStatus:{status:"finalized",executionStatus:Iw(e,t)}};case"rejected":return{txHash:e.hash,txStatus:{status:"discarded"}};case"pending":return{txHash:e.hash,txStatus:{status:"pending"}}}}function Iw(e,t){switch(e.status){case"SUCCESS":return{0:"Success"};case"FAILURE":return{0:"Failure"};case"PARTIAL_SUCCESS":if(!t||t.length===0)throw Error(`Transaction ${e.hash} partly succeeded, but its segment results are missing`);return Object.fromEntries(t.map((r)=>[r.id,r.success?"Success":"Failure"]));case void 0:return{}}}function _w(e){if(e!=="schnorr")throw Error(`Unexpected signature scheme "${e}": mn signs with BIP-340 Schnorr only`);return"schnorr_bip340"}function cl(e){let{bundle:t,networkConfig:r,approvalOptions:n,callbacks:s}=e,o=e.feeLimits??Wd,{facade:i,keystore:a}=t,c=He(r.networkId),d=e.isCurrent??((b)=>b.isSynced),u=e.dustWaitMs??mn,l=e.initialState,p=e.initialState?.protocolVersion,f=i.state().subscribe((b)=>{if(p=b.protocolVersion,d(b))l=b});function h(){if(!l)throw K("Disconnected","Wallet not synced yet");return l}function m(){if(!p)throw K("Disconnected","Wallet not synced yet");let b=hd(p);if(b.length>0){let v=b.map((x)=>`${x} at ${p[x]}`).join(", ");throw K("Disconnected",`This wallet can't take transactions until all three of its wallets are on ledger 9 (fork at ${ft.v9}); still behind: ${v}. Wait for them to sync past the fork and retry.`)}}let y=new Map;function w(b,v,x,_=!1){let F=y.get(b);if(!F)F=new Map,y.set(b,F);let Q=setTimeout(async()=>{if(F.delete(v),F.size===0)y.delete(b);try{await i.revert(x)}catch{}process.stderr.write(g(` abandoned tx reverted (${b})`)+`
|
|
93
|
+
`)},sc);F.set(v,{finalized:x,timer:Q,feeOnly:_})}function S(b,v){let x=y.get(b);if(!x)return;let _=x.get(v);if(_)clearTimeout(_.timer),x.delete(v);if(x.size===0)y.delete(b)}async function k(b){let v=y.get(b);if(!v||v.size===0)return;y.delete(b);for(let[,x]of v){clearTimeout(x.timer);try{await i.revert(x.finalized)}catch{}}process.stderr.write(g(` reverted ${v.size} pending tx(s) on disconnect`)+`
|
|
94
|
+
`)}function T(){return new Date(Date.now()+qn*60*1000)}async function N(b,v){v?.start("signing");let x;try{x=await Zd(i,b,a.signDataAsync)}catch(j){try{await i.revert(b)}catch{}if(j instanceof Ir)throw K("InvalidRequest",j.message);throw j}v?.start("proving");let _,F,Q=i.finalizeRecipe(x);try{F=await Promise.race([Q,new Promise((j,ie)=>{_=setTimeout(()=>ie(Error("ZK proof generation timed out")),Vn)})])}catch(j){try{await i.revert(b)}catch{}throw Q.then((ie)=>i.revert(ie)).catch(()=>{}),j}finally{clearTimeout(_)}return v?.complete(),{hex:Bd(F.serialize()),finalized:F}}function L(b,v){try{return i.adoptTransaction(ir(b),v)}catch(x){throw K("InvalidRequest",`The transaction could not be read at stage ${v} as this wallet's ledger version: ${vt(x)}`)}}async function J(b,v=[],x,_=!1){x?.notify("approval:pending",{method:b});let F=await Md({method:b,network:r.networkId,details:v,dappName:x?.connectionId,feeOnly:_},n),Q=F==="reject"?"rejected":"approved";if(x?.notify("approval:resolved",{method:b,result:Q}),F==="reject")throw K("Rejected",n.approveFees?`${il}: this fee wallet (--approve-fees) approves without the operator only paying the Dust fee for an agent's own transaction and submitting a transaction it balanced that way on the same connection`:il)}function Y(b,v,x){if(x===!1)throw K("InvalidRequest","This wallet is a fee wallet (--approve-fees): it only pays the Dust fee, so payFees: false leaves it nothing to do");let _;try{_=Dr(ir(b),v)}catch(Q){throw K("InvalidRequest",`The transaction could not be read as a proven ledger-9 ${v} transaction: ${vt(Q)}`)}let F=zd(_,a.getPublicKey());if(F.length>0)throw K("Rejected",`This wallet is a fee wallet (--approve-fees) and pays only the Dust fee; it refuses this transaction because ${F.join("; ")}`)}function V(b,v){let x;try{x=qd(Dr(ir(b),v),new Date)}catch(_){throw K("InvalidRequest",vt(_))}if(x.length>0){let _=x.map(({segment:F,ttl:Q})=>`intent ${F}'s TTL (${Q.toISOString()})`).join(", ");throw K("InvalidRequest",`The transaction has expired: ${_} has passed. Build it again with a later TTL.`)}}function M(b,v){try{Xd(Dr(ir(b),"unsealed"),v)}catch(x){throw K("InvalidRequest",vt(x))}}function O(){let b=0;for(let[,v]of y)b+=v.size;return b}function le(b){return K("Rejected",`This wallet is a fee wallet (--approve-fees) and refuses this transaction: ${b}`)}let ge=0;function So(){let b=Hd(O()+ge,o);if(b)throw le(b);ge++;let v=!1;return()=>{if(!v)v=!0,ge--}}async function cr(b,v){let x=await Vr(()=>i.estimateTransactionFee(b,{ttl:v}));process.stderr.write(g(` fee-only: estimated fee ${pe(x)} DUST (limit ${pe(o.maxFeeSpecks)})`)+`
|
|
95
|
+
`);let _=jd(x,o);if(_)throw le(_)}async function Se(b,v,x,_){let F=String(x.tx??"");if(!F)throw K("InvalidRequest","tx is required");m();let Q=x.options?.payFees,j=n.approveFees===!0;if(j)Y(F,v,Q);let ie=j?["dust"]:Q===!1?["shielded","unshielded"]:"all",we=T(),st=v==="unsealed"?L(F,"Unbound"):L(F,"Finalized");if(V(F,v),v==="unsealed")M(F,ie==="all"||ie.includes("unshielded"));let ot=j?So():void 0;try{if(j)await cr(st,we);let lr=fe(b,_);lr.start("approve"),await J(b,Ti(F,v),_,j),lr.start("building");let Fa={ttl:we,tokenKindsToBalance:ie},vo;if(v==="unsealed"){let ko=st;vo=await Vr(()=>i.balanceUnboundTransaction(ko,Fa))}else{let ko=st;vo=await Vr(()=>i.balanceFinalizedTransaction(ko,Fa))}let{hex:Ua,finalized:Pm}=await N(vo,lr);return w(_.connectionId,Ua,Pm,j),_.metadata.phases=lr.getTimings(),{tx:Ua}}finally{ot?.()}}function dr(b){return ol.encode(c,b).asString()}function Mt(b,v){let x;try{if(typeof b!=="string"&&typeof b!=="number"&&typeof b!=="bigint")throw TypeError();x=BigInt(b)}catch{throw K("InvalidRequest",`Invalid ${v}: "${String(b)}" — must be a whole number of the token's smallest unit`)}if(x<=0n)throw K("InvalidRequest",`Invalid ${v}: ${x} — must be greater than 0`);return x}function Re(b,v){if(b!=="shielded"&&b!=="unshielded")throw K("InvalidRequest",`Invalid ${v} kind: "${b}" — must be "shielded" or "unshielded"`);return b}function Ft(b){if(typeof b!=="string"||!/^[0-9a-fA-F]{64}$/.test(b))throw K("InvalidRequest",`Invalid token type: "${b}" — must be 64 hex characters`);return b}function Ut(b){if(!Array.isArray(b))throw K("InvalidRequest","desiredInputs must be an array");let v={};for(let x of b){let _=Re(x?.kind,"input");v[_]??={},v[_][Ft(x.type)]=Mt(x.value,"value")}return v}function bo(b){if(!Array.isArray(b))throw K("InvalidRequest","desiredOutputs must be an array");let v={};for(let x of b){let _=Re(x?.kind,"output");v[_]??=[];let F=Ft(x.type),Q=Mt(x.value,"value"),j;try{j=ol.parse(String(x.recipient)).decode(_==="unshielded"?Rw:Dw,c)}catch(ie){throw K("InvalidRequest",`Invalid recipient: "${x.recipient}" is not ${_==="unshielded"?"an":"a"} ${_} address on ${r.networkId} (${vt(ie)})`)}v[_].push({type:F,receiverAddress:j,amount:Q})}return Object.entries(v).map(([x,_])=>({type:x,outputs:_}))}function fe(b,v){return Ld({onStart:(x)=>{let _=v?.connectionId??"unknown";s?.onPhaseStart?.(_,b,x),v?.notify("progress",{method:b,phase:x,status:"started"})},onComplete:(x,_)=>{let F=v?.connectionId??"unknown";s?.onPhaseComplete?.(F,b,x,_),v?.notify("progress",{method:b,phase:x,status:"completed",durationMs:_})}})}function Ae(){return l!==void 0&&tr(l)}async function lt(b){return new Promise((v)=>{if(Ae()){v("already");return}let x=i.state().pipe(_r.filter(()=>Ae()),_r.take(1),_r.timeout(b)).subscribe({next:()=>{x.unsubscribe(),v("appeared")},error:()=>{x.unsubscribe(),v("timeout")}})})}function kt(b){let v=O();if(v===0)return K("InternalError",`The wallet has no Dust available that covers this transaction's fee (${vt(b)}), and no balanced transaction is holding any back on this server. Dust builds up with time from the NIGHT registered for it: retry later, or register more NIGHT for Dust generation.`);return K("InternalError",`No Dust is free to pay the fee (${vt(b)}). Each balanced transaction reserves a whole Dust coin until it is submitted and on chain, or released when its connection closes or it expires; ${v} balanced transaction(s) are waiting to be submitted on this server. Retry once they settle. To pay for more transactions at once, the wallet needs more Dust coins: one per NIGHT UTXO registered for Dust generation.`)}function qe(b,v,x){let _=x===null?"Its registered NIGHT won't generate that within a day: register more NIGHT for Dust generation.":`Its registered NIGHT generates the rest in ${Ge(x)}: retry then, or register more NIGHT to get there sooner.`;return K("InternalError",`Not enough Dust available for this transaction's fee: the wallet has ${At(b)} DUST and the fee takes ${At(v,!0)}. ${_}`)}function Rm(b){if(l===void 0||O()>0)return;return si(b,l.dust,new Date)}async function Vr(b){let v=0,x=1;for(;;)try{return await b()}catch(_){let F=String(_?.message??_??"");if(!ri(_))throw _;let Q=Rm(_);if(Q){let{have:j,needed:ie,waitMs:we}=Q;if(we===null||v+we>u)throw qe(j,ie,we);process.stderr.write(g(` Dust: ${At(j)} of the ${At(ie,!0)} DUST this fee takes; waiting ${Ge(we)} for the rest...`)+`
|
|
96
|
+
`),await Zt(we),v+=we;continue}if(x>=Mo)throw kt(_);if(process.stderr.write(g(` dust unavailable, waiting for recovery (${x}/${Mo})... [${F.slice(0,60)}]`)+`
|
|
97
|
+
`),await lt(Zr)!=="appeared")await Zt(Zr);x++}}let Dm={connect:async(b)=>{let v=String(b.networkId??"");if(v.toLowerCase()!==r.networkId.toLowerCase())throw K("InvalidRequest",`Network mismatch: wallet is on ${r.networkId}, requested ${v}`);return{networkId:r.networkId}},getUnshieldedBalances:async()=>h().unshielded.balances,getShieldedBalances:async()=>h().shielded.balances,getDustBalance:async()=>{let v=h().dust.balance(new Date);return{cap:v,balance:v}},getUnshieldedAddress:async()=>{let b=h();return{unshieldedAddress:dr(b.unshielded.address)}},getShieldedAddresses:async()=>{let v=h().shielded.address;return{shieldedAddress:dr(v),shieldedCoinPublicKey:v.coinPublicKeyString(),shieldedEncryptionPublicKey:v.encryptionPublicKeyString()}},getDustAddress:async()=>{let b=h();return{dustAddress:dr(b.dust.address)}},getTxHistory:async(b)=>{h();let v=b.pageNumber??0,x=b.pageSize??20;if(!Number.isSafeInteger(v)||v<0)throw K("InvalidRequest",`Invalid pageNumber: ${JSON.stringify(v)} — must be a whole number, 0 or more`);if(!Number.isSafeInteger(x)||x<1)throw K("InvalidRequest",`Invalid pageSize: ${JSON.stringify(x)} — must be a whole number, 1 or more`);let _=v*x,F=await i.getAllFromTxHistory(),Q=[];for(let j of F.slice(_,_+x)){if(j.lifecycle.status!=="finalized"||j.status!=="PARTIAL_SUCCESS"){Q.push(al(j));continue}try{Q.push(al(j,await nl(r.indexer,j.hash)))}catch(ie){throw K("InternalError",vt(ie))}}return Q},getConfiguration:async()=>({indexerUri:r.indexer,indexerWsUri:r.indexerWS,proverServerUri:r.proofServer,substrateNodeUri:r.node,networkId:r.networkId}),getConnectionStatus:async()=>({status:"connected",networkId:c}),makeTransfer:async(b,v)=>{let x=b.desiredOutputs;if(!Array.isArray(x)||x.length===0)throw K("InvalidRequest","desiredOutputs must be a non-empty array");m();let _=bo(x),F=fe("makeTransfer",v),Q=x.map((ot,lr)=>({label:`Output ${lr+1}`,value:`${ot.value} → ${String(ot.recipient).slice(0,20)}... (${ot.kind})`}));F.start("approve"),await J("makeTransfer",Q,v),F.start("building");let j=b.options?.payFees??!0,ie=await Vr(()=>i.transferTransaction(_,{ttl:T(),payFees:j})),{hex:we,finalized:st}=await N(ie,F);return w(v.connectionId,we,st),v.metadata.phases=F.getTimings(),{tx:we}},submitTransaction:async(b,v)=>{let x=String(b.tx??"");if(!x)throw K("InvalidRequest","tx is required");m();let _=fe("submitTransaction",v),F=n.approveFees===!0&&y.get(v.connectionId)?.get(x)?.feeOnly===!0;_.start("approve");try{await J("submitTransaction",Ti(x,"sealed"),v,F)}catch(j){let we=y.get(v.connectionId)?.get(x);if(we)try{await i.revert(we.finalized)}catch{}throw S(v.connectionId,x),j}let Q=L(x,"Finalized");_.start("submitting");try{let j=await i.submitTransaction(Q);return _.complete(),S(v.connectionId,x),v.metadata.phases=_.getTimings(),{txHash:j}}catch(j){_.complete();let we=y.get(v.connectionId)?.get(x);if(we)try{await i.revert(we.finalized)}catch{}S(v.connectionId,x);let st=vt(j),ot=Error(`Transaction submission failed: ${st}`);throw ot.cause=j,ot}},balanceUnsealedTransaction:(b,v)=>Se("balanceUnsealedTransaction","unsealed",b,v),balanceSealedTransaction:(b,v)=>Se("balanceSealedTransaction","sealed",b,v),makeIntent:async(b,v)=>{let{desiredInputs:x,desiredOutputs:_,options:F}=b;if(!F)throw K("InvalidRequest","options is required for makeIntent");m();let Q=Ut(x??[]),j=bo(_??[]),ie=fe("makeIntent",v);ie.start("approve"),await J("makeIntent",[],v),ie.start("building");let we=await Vr(()=>i.initSwap(Q,j,{ttl:T(),payFees:F.payFees??!0})),{hex:st,finalized:ot}=await N(we,ie);return w(v.connectionId,st,ot),v.metadata.phases=ie.getTimings(),{tx:st}},signData:async(b,v)=>{let x=String(b.data??""),_=b.options;if(!x||!_?.encoding)throw K("InvalidRequest","data and options.encoding are required");if(_.keyType&&_.keyType!=="unshielded")throw K("InvalidRequest",`Unsupported keyType: "${_.keyType}" — only "unshielded" is supported`);let F;try{F=el(x,_.encoding)}catch(ie){throw K("InvalidRequest",ie.message)}await J("signData",[{label:"Encoding",value:_.encoding},{label:"Data",value:x.length>64?x.slice(0,64)+"...":x}],v);let Q=await a.signDataAsync(tl(F)),j=a.getPublicKey();return{data:x,signature:Q.value,verifyingKey:j.value,scheme:_w(Q.tag)}},getProvingProvider:async()=>({provingProvider:"ready",proverServerUri:r.proofServer}),hintUsage:async(b)=>{let v=b.methodNames??[];if(!Array.isArray(v)||!v.every((x)=>typeof x==="string"&&/^[A-Za-z]\w*$/.test(x)))throw K("InvalidRequest","methodNames must be an array of connector method names");process.stderr.write(g(` DApp hints usage: ${v.join(", ")}`)+`
|
|
98
|
+
`)}};function Im(){f.unsubscribe();for(let[,b]of y)for(let[,v]of b)clearTimeout(v.timer);y.clear()}function _m(){for(let[,b]of y)if(b.size>0)return!0;return!1}return{handlers:Dm,revertPendingTxs:k,hasPendingTxs:_m,dispose:Im}}var il="User rejected the request";var dl=E(()=>{tt();Ce();Fd();Ai();gt();Xt();Gd();Kd();Di();Qd();rl();vr();fn();sl();sr();de()});import{Socket as Pw}from"node:net";function ll(e){let{name:t,config:r}=me({args:{command:"serve",subcommand:void 0,positionals:[],flags:{...e.network?{network:e.network}:{},...is(e.endpoints??{})}}});return Le(r,e.endpoints??{},t),{networkName:t,networkConfig:r}}function $w(e,t){let r=(s,o)=>s!==void 0&&s.replace(/\/+$/,"")===o.replace(/\/+$/,""),n=[];if(!r(e.substrateNodeUri,t.node))n.push(`node ${e.substrateNodeUri} (need ${t.node})`);if(!r(e.indexerWsUri,t.indexerWS))n.push(`indexer ${e.indexerWsUri} (need ${t.indexerWS})`);return n.length>0?n.join(", "):void 0}function Ow(e,t){if(e===null||e===t.address)return;return`it serves the wallet at ${e}, and this command pays from ${t.name} (${t.address})`}function Mw(e){return new Promise((t)=>{let r=new Pw;r.setTimeout(1000),r.once("connect",()=>{r.destroy(),t(!0)}),r.once("timeout",()=>{r.destroy(),t(!1)}),r.once("error",()=>t(!1)),r.connect(e,"127.0.0.1")})}async function Fw(e){let r=(await _i(e,"getConnectionStatus"))?.networkId;return typeof r==="string"?r:null}async function Uw(e){let t=await _i(e,"getConfiguration");return t&&typeof t==="object"?t:null}async function Lw(e){let r=(await _i(e,"getUnshieldedAddress"))?.unshieldedAddress;return typeof r==="string"?r:null}async function _i(e,t){let r=(await import("ws")).default;return new Promise((n)=>{let s=new r(`ws://127.0.0.1:${e}`),o=setTimeout(()=>{try{s.close()}catch{}n(null)},2000);s.on("open",()=>{s.send(JSON.stringify({jsonrpc:"2.0",id:1,method:t,params:{}}))}),s.on("message",(i)=>{clearTimeout(o);try{let a=JSON.parse(i.toString());s.close(),n(a?.result??null)}catch{s.close(),n(null)}}),s.on("error",()=>{clearTimeout(o),n(null)})})}async function Ps(e){let t=e.port??Qr,r=(e.network??"undeployed").toLowerCase(),n=e.onMessage??(()=>{});if(await Mw(t)){let s=await Fw(t);if(!s)throw Error(`Port ${t} is in use by a process that does not look like mn serve. Free the port (e.g. \`lsof -nP -iTCP:${t} -sTCP:LISTEN\` then \`kill <pid>\`) and retry.`);let o=s.toLowerCase();if(o!==r)throw Error(`mn serve is already running on port ${t} for network ${o}, but this run needs ${r}. Stop the wrong-network serve first (\`pkill -f 'mn serve'\`) and retry.`);let i=await Uw(t),a=i?$w(i,ll(e).networkConfig):"its endpoints could not be read";if(a)throw Error(`mn serve on port ${t} is on a different ${o} chain: ${a}. Stop it first (\`pkill -f 'mn serve'\`) and retry.`);let c=await Lw(t);if(c!==null){let d=ce(oe(e.wallet)).addresses[o],u=Ow(c,{address:d,name:e.wallet??"the active wallet"});if(u)throw Error(`mn serve on port ${t} can't pay for this command: ${u}. Stop it first (\`pkill -f 'mn serve'\`) and retry, or run the command for the wallet it serves.`)}return n(`Reusing existing mn serve on port ${t}`),{port:t,async stop(){}}}return Bw(e)}async function Bw(e){let t=e.port??Qr,r=e.onMessage??(()=>{}),n=ce(oe(e.wallet)),s=Buffer.from(n.seed,"hex"),{networkName:o,networkConfig:i}=ll(e);await Je(o,i);let a=n.addresses[o],c=Fe((y,w)=>{r(`SDK: ${w}`)}),d=Ue();r("Building wallet facade...");let u=yt(o,i.indexerWS);if(u)r(Rs(o,u));let l=Dt(a,o),p=await et(s,i,l);r("Syncing wallet..."),await Rt(p,{onProgress:(y,w)=>{if(w>0){let S=Math.min(Math.round(y/w*100),100);r(`Syncing wallet... ${S}%`)}}}),r("Wallet synced"),r("Waiting for dust...");let f=await ks(p);r("Dust ready");try{await wt(a,o,p.facade)}catch{}let h=cl({bundle:p,networkConfig:i,approvalOptions:{approveAll:!0,autoApproveReads:!0},initialState:f,isCurrent:(y)=>hn(y,"full",p.emptyStreams),dustWaitMs:e.dustWaitMs,callbacks:{onPhaseStart:(y,w,S)=>{r(`${S}...`)},onPhaseComplete:(y,w,S,k)=>{r(`${S} ${Math.round(k)}ms`)}}}),m=Ud({port:t,handlers:h.handlers,onConnect:(y)=>{r(`connected ${y.id}`)},onDisconnect:(y)=>{r(`disconnected ${y.id}`),h.revertPendingTxs(y.id).catch(()=>{})},onRequest:(y,w)=>{r(`${y.id} → ${w.method}`)},onResponse:(y,w,S,k,T)=>{if(T)r(`${y.id} ← ${w.method} FAILED: ${T.message}`);else r(`${y.id} ← ${w.method} (${Math.round(S)}ms)`)}});try{await m.ready}catch(y){throw h.dispose(),await m.close(),await We(p),c(),d(),Error(`Could not start mn serve on port ${t}: ${y.message}`)}return r(`Server ready on ws://localhost:${t}`),{port:t,async stop(){m.close(),h.dispose(),d(),c();try{await We(p)}catch{}}}}var Pi=E(()=>{Pe();Ee();sr();Ce();tt();Cn();rr();bt();dl();Ai()});function Pr(e,t,r){let n=C(e,"network")??"undeployed",s={node:C(e,"node"),indexerWS:C(e,"indexer-ws"),proofServer:C(e,"proof-server")},{name:o,config:i}=me({args:{command:t,subcommand:r,positionals:[],flags:{network:n,...is(s)}}});return Le(i,s,o),{network:n,networkConfig:i,endpoints:s}}async function Tn({network:e,networkConfig:t},r,n){let s=ce(oe(r)),o=Buffer.from(s.seed,"hex"),i=s.addresses[e];await Promise.resolve().then(() => _t());let c=$e();try{let u=(await c.unshielded(i,t)).balances.get(Lt)??0n;if(u===0n)throw n.fail("No NIGHT balance"),Error(`Wallet has 0 NIGHT on ${e}.
|
|
99
99
|
|
|
100
100
|
Fund your wallet before deploying:
|
|
101
101
|
Address: ${i}
|
|
@@ -106,12 +106,12 @@ Expected a bech32m address for network "${t.networkId}"`)}}function xi(e){let t=
|
|
|
106
106
|
Register for dust generation:
|
|
107
107
|
Run: midnight dust register --network ${e}
|
|
108
108
|
Then wait: midnight dust status --network ${e}
|
|
109
|
-
`);return n.stop(`Wallet OK (${br(u)}, dust available)`),{nightBalance:u,dustBalance:l.balance}}catch(d){throw n.fail("Wallet check failed"),d}}async function Nn({network:e,endpoints:t},r,n){await Promise.resolve().then(() => Pi());let o=await Ps({network:e,endpoints:t,wallet:r,onMessage:(i)=>n.update(i),dustWaitMs:fs});return n.stop("mn serve ready (port "+o.port+")"),{port:o.port,stop:()=>o.stop()}}var $s=E(()=>{
|
|
110
|
-
`)}var Ms,
|
|
111
|
-
${r}`)}}async function Ls(e){let t=
|
|
112
|
-
${n}`)}}async function
|
|
113
|
-
${r}`)}}function
|
|
114
|
-
import WebSocket from
|
|
109
|
+
`);return n.stop(`Wallet OK (${br(u)}, dust available)`),{nightBalance:u,dustBalance:l.balance}}catch(d){throw n.fail("Wallet check failed"),d}}async function Nn({network:e,endpoints:t},r,n){await Promise.resolve().then(() => Pi());let o=await Ps({network:e,endpoints:t,wallet:r,onMessage:(i)=>n.update(i),dustWaitMs:fs});return n.stop("mn serve ready (port "+o.port+")"),{port:o.port,stop:()=>o.stop()}}var $s=E(()=>{re();Ce();Ee();Pe();de();vr()});import{existsSync as $i,statSync as Ww}from"node:fs";import{createRequire as ul}from"node:module";import{homedir as jw}from"node:os";import{join as Mi,resolve as Hw}from"node:path";import{pathToFileURL as Oi}from"node:url";function zw(e=import.meta.url){let t=ul(e),r=t.resolve(Kw);return{kind:"package",driverUrl:Oi(r).href,typesUrl:Oi(ul(r).resolve(Jw)).href,wsUrl:Oi(t.resolve(Vw)).href}}function fl(e,t,r=zw){let n=[e,t].find((s)=>s!==void 0&&s.trim()!=="");return n===void 0?r():{kind:"directory",dir:Hw(n)}}function ml(e=jw()){return Mi(e,te,qw)}function gl(e){if(e.kind==="package")return;let{dir:t}=e;if(!$i(t)||!Ww(t).isDirectory())throw new R(`The account build ${t} is not a directory.`);if(!$i(Mi(t,Os)))throw new R(`${t} is not an account build mn can drive: it has no ${Os}. Point --account-build at the directory that holds it (an older build has none: update it).`);if(!$i(Mi(t,"node_modules")))throw new R(`The account build ${t} has no node_modules: install its dependencies there first (npm install).`)}function hl(e=process.versions.node){let[t=0,r=0]=e.split(".").map(Number),[n=0,s=0]=pl.split(".").map(Number);if(t>n||t===n&&r>=s)return;throw new Ui(e)}var Os="driver.ts",Gw="@kuiralabs/midnight-account-chain",Kw,Jw="@midnight-ntwrk/midnight-js-types",Vw="ws",Fi=4,pl="22.18.0",qw="account-artifacts",Ui;var Li=E(()=>{ue();Kw=`${Gw}/driver`;Ui=class Ui extends Error{code="UNSUPPORTED_NODE";constructor(e){super(`mn grant runs the account build, which needs Node.js ${pl} or newer (a local build runs as TypeScript); this is Node.js ${e}. Install a current Node.js (https://nodejs.org) and run the command again.`);this.name="NodeTooOldForAccountBuildError",Object.setPrototypeOf(this,Ui.prototype)}}});import{mkdirSync as Yw}from"node:fs";import{homedir as Xw}from"node:os";import{basename as Zw,join as Qw}from"node:path";function wl(e,t=Et){if(e===void 0)return t();return Zw(e).replace(/\.json$/,"")}function yl(e,t,r=Xw()){return Qw(r,te,ey,e,t)}function Sl(e){Yw(e,{recursive:!0,mode:be})}var ey="accounts";var bl=E(()=>{Pe()});import{existsSync as vl}from"node:fs";import{join as kl}from"node:path";function Cl(e){for(let t of Ms){let r=kl(e,t);if(vl(r))return r}return null}function ry(e){for(let t of ty){let r=kl(e,t);if(vl(r))return r}return null}function xl(e){let{projectRoot:t,witnessNames:r}=e,n=ry(t),s=[`Contract declares ${r.length} witness(es): ${r.join(", ")}`,"but no compiled witnesses module was found.","",`Searched (relative to ${t}):`,...Ms.map((o)=>` - ${o}`),""];if(n)s.push(`Found ${n} — looks like it isn't compiled yet.`,'Build it (e.g. "npm run build") so a .js exists, then retry.');else s.push('Add a witnesses module exporting a "witnesses" object that maps each',"declared name to its implementation. Example: src/witnesses.ts → tsc → dist/witnesses.js.");return s.join(`
|
|
110
|
+
`)}var Ms,ty;var Bi=E(()=>{Ms=["dist/witnesses.js","src/witnesses.js","contract/dist/witnesses.js","contract/src/witnesses.js"],ty=["src/witnesses.ts","contract/src/witnesses.ts"]});function Fs(e){if(typeof e==="number")return Number.isInteger(e)?BigInt(e):e;if(typeof e==="string"){if(/^-?\d+n$/.test(e))return BigInt(e.slice(0,-1));return e}if(Array.isArray(e)){if(e.length>0&&e.every((t)=>typeof t==="number"&&Number.isInteger(t)&&t>=0&&t<=255))return Uint8Array.from(e);return e.map(Fs)}if(e&&typeof e==="object"&&Object.getPrototypeOf(e)===Object.prototype){let t={};for(let r in e)if(Object.prototype.hasOwnProperty.call(e,r))t[r]=Fs(e[r]);return t}return e}function El(e,t){let r=new Uint8Array(32);if(e&&e.length===64){for(let s=0;s<32;s++)r[s]=parseInt(e.substr(s*2,2),16);return r}let n=t??"";if(n.length>=64){for(let s=0;s<32;s++)r[s]=parseInt(n.substr(s*2,2),16);return r}return globalThis.crypto.getRandomValues(r),r}import{spawn as ny}from"node:child_process";import{randomBytes as sy}from"node:crypto";import{writeFileSync as oy,unlinkSync as Al,existsSync as Us,symlinkSync as Tl}from"node:fs";import{join as Rn,dirname as Nl}from"node:path";import{fileURLToPath as iy}from"node:url";function ay(){let e=Nl(iy(import.meta.url));for(let t=0;t<8;t++){let r=Rn(e,"node_modules");if(Us(r))return r;let n=Nl(e);if(n===e)break;e=n}return null}function Gi(e){return ke(e.indexer),{[ji]:e.indexer,[Hi]:e.indexerWS??e.indexer.replace("http","ws")}}async function $r(e){let t=py(e),r=await Dn({dir:e.dappDir,script:t,onMessage:e.onMessage,env:Gi(e.networkConfig)});try{return JSON.parse(r)}catch{throw Error(`State script returned unexpected output:
|
|
111
|
+
${r}`)}}async function Ls(e){let t=ly(e),r={...Gi(e.networkConfig),...e.privateStateSecretKey?{MN_PRIVATE_STATE_SECRET:e.privateStateSecretKey}:{}},n=await Dn({dir:e.dappDir,script:t,onMessage:e.onMessage,env:r});try{return JSON.parse(n)}catch{throw Error(`Deploy script returned unexpected output:
|
|
112
|
+
${n}`)}}async function Bs(e){let t=uy(e),r=await Dn({dir:e.dappDir,script:t,onMessage:e.onMessage,env:Gi(e.networkConfig)});try{return JSON.parse(r)}catch{throw Error(`Call script returned unexpected output:
|
|
113
|
+
${r}`)}}function Ws(e,t="ws"){return`
|
|
114
|
+
import WebSocket from ${JSON.stringify(t)};
|
|
115
115
|
|
|
116
116
|
const RPC_URL = 'ws://127.0.0.1:${e}';
|
|
117
117
|
let rpcId = 0;
|
|
@@ -168,7 +168,7 @@ const midnightProvider = createMidnightProvider(async (tx) => {
|
|
|
168
168
|
await rpcCall('submitTransaction', { tx: toHex(tx.serialize()) });
|
|
169
169
|
return tx.identifiers()[0];
|
|
170
170
|
});
|
|
171
|
-
`}function
|
|
171
|
+
`}function Dl(e,t){return`
|
|
172
172
|
import { pathToFileURL } from 'node:url';
|
|
173
173
|
import { resolve } from 'node:path';
|
|
174
174
|
import { CompiledContract } from '@midnight-ntwrk/compact-js';
|
|
@@ -213,7 +213,7 @@ if (!witnesses) {
|
|
|
213
213
|
// Uses a deterministic seed derived from the wallet so post/takeDown use the same key.
|
|
214
214
|
// The private state provider (leveldb) persists between calls, but initialPrivateState
|
|
215
215
|
// is the fallback when no stored state exists yet.
|
|
216
|
-
${
|
|
216
|
+
${cy}
|
|
217
217
|
function makeInitialPrivateState() {
|
|
218
218
|
if (createPrivateState) {
|
|
219
219
|
// Secret precedence (see resolvePrivateStateSecretKey, injected above via
|
|
@@ -239,7 +239,7 @@ const compiled = witnesses
|
|
|
239
239
|
CompiledContract.withVacantWitnesses,
|
|
240
240
|
(c) => CompiledContract.withCompiledFileAssets(c, MANAGED_DIR),
|
|
241
241
|
);
|
|
242
|
-
`}function
|
|
242
|
+
`}function Il(e,t){return`
|
|
243
243
|
const zkConfigProvider = new NodeZkConfigProvider(MANAGED_DIR);
|
|
244
244
|
|
|
245
245
|
const providers = {
|
|
@@ -249,32 +249,32 @@ const providers = {
|
|
|
249
249
|
accountId: 'mn-contract-runner',
|
|
250
250
|
}),
|
|
251
251
|
publicDataProvider: indexerPublicDataProvider({
|
|
252
|
-
queryURL: process.env.${
|
|
253
|
-
subscriptionURL: process.env.${
|
|
252
|
+
queryURL: process.env.${ji},
|
|
253
|
+
subscriptionURL: process.env.${Hi},
|
|
254
254
|
}),
|
|
255
255
|
zkConfigProvider,
|
|
256
256
|
proofProvider: httpClientProofProvider({ url: ${JSON.stringify(e.proofServer)}, zkConfigProvider }),
|
|
257
257
|
walletProvider,
|
|
258
258
|
midnightProvider,
|
|
259
259
|
};
|
|
260
|
-
`}function
|
|
260
|
+
`}function dy(e,t){let r=new RegExp(`^${Ki} (.*)$`,"m").exec(e);if(r)try{return JSON.parse(r[1])}catch{return r[1]}return e.trim()||`Script exited with code ${t}`}function ly(e){let t=e.privateStateKey??`${e.contractName}PrivateState`,r=JSON.stringify(e.args??[]);return`${Or}
|
|
261
261
|
import { setNetworkId } from '@midnight-ntwrk/midnight-js-network-id';
|
|
262
262
|
setNetworkId(${JSON.stringify(e.networkConfig.networkId.toLowerCase())});
|
|
263
263
|
|
|
264
|
-
${
|
|
265
|
-
${
|
|
264
|
+
${Ws(e.servePort)}
|
|
265
|
+
${Dl(e.contractName,e.managedDir)}
|
|
266
266
|
|
|
267
267
|
process.stderr.write('Connecting to mn serve...\\n');
|
|
268
268
|
await rpcConnect();
|
|
269
269
|
process.stderr.write('Connected\\n');
|
|
270
270
|
|
|
271
|
-
${
|
|
271
|
+
${Rl}
|
|
272
272
|
${js()}
|
|
273
|
-
${
|
|
273
|
+
${Il(e.networkConfig,t)}
|
|
274
274
|
|
|
275
275
|
import { deployContract } from '@midnight-ntwrk/midnight-js-contracts';
|
|
276
276
|
|
|
277
|
-
${
|
|
277
|
+
${_l}
|
|
278
278
|
const constructorArgs = (${r}).map(coerceArg);
|
|
279
279
|
process.stderr.write('Deploying contract' + (constructorArgs.length ? ' with ' + constructorArgs.length + ' constructor arg(s)...' : '...') + '\\n');
|
|
280
280
|
const deployed = await deployContract(providers, {
|
|
@@ -290,20 +290,20 @@ process.stderr.write('Deploy complete: ' + address + '\\n');
|
|
|
290
290
|
console.log(JSON.stringify({ contractAddress: address }));
|
|
291
291
|
rpcClose();
|
|
292
292
|
process.exit(0);
|
|
293
|
-
`}function
|
|
293
|
+
`}function uy(e){let t=e.privateStateKey??`${e.contractName}PrivateState`;return`${Or}
|
|
294
294
|
import { setNetworkId } from '@midnight-ntwrk/midnight-js-network-id';
|
|
295
295
|
setNetworkId(${JSON.stringify(e.networkConfig.networkId.toLowerCase())});
|
|
296
296
|
|
|
297
|
-
${
|
|
298
|
-
${
|
|
297
|
+
${Ws(e.servePort)}
|
|
298
|
+
${Dl(e.contractName,e.managedDir)}
|
|
299
299
|
|
|
300
300
|
process.stderr.write('Connecting to mn serve...\\n');
|
|
301
301
|
await rpcConnect();
|
|
302
302
|
process.stderr.write('Connected\\n');
|
|
303
303
|
|
|
304
|
-
${
|
|
304
|
+
${Rl}
|
|
305
305
|
${js()}
|
|
306
|
-
${
|
|
306
|
+
${Il(e.networkConfig,t)}
|
|
307
307
|
|
|
308
308
|
import { findDeployedContract } from '@midnight-ntwrk/midnight-js-contracts';
|
|
309
309
|
|
|
@@ -316,14 +316,14 @@ const deployed = await findDeployedContract(providers, {
|
|
|
316
316
|
});
|
|
317
317
|
|
|
318
318
|
process.stderr.write('Calling ${e.circuit}...\\n');
|
|
319
|
-
${
|
|
319
|
+
${_l}
|
|
320
320
|
const args = (${JSON.stringify(e.args??[])}).map(coerceArg);
|
|
321
321
|
await deployed.callTx.${e.circuit}(...args);
|
|
322
322
|
|
|
323
323
|
console.log(JSON.stringify({ status: 'success', circuit: ${JSON.stringify(e.circuit)} }));
|
|
324
324
|
rpcClose();
|
|
325
325
|
process.exit(0);
|
|
326
|
-
`}function
|
|
326
|
+
`}function py(e){return`${Or}
|
|
327
327
|
import { setNetworkId } from '@midnight-ntwrk/midnight-js-network-id';
|
|
328
328
|
setNetworkId(${JSON.stringify(e.networkConfig.networkId.toLowerCase())});
|
|
329
329
|
|
|
@@ -342,8 +342,8 @@ if (typeof contractMod.ledger !== 'function') {
|
|
|
342
342
|
|
|
343
343
|
process.stderr.write('Querying contract state...\\n');
|
|
344
344
|
const provider = indexerPublicDataProvider({
|
|
345
|
-
queryURL: process.env.${
|
|
346
|
-
subscriptionURL: process.env.${
|
|
345
|
+
queryURL: process.env.${ji},
|
|
346
|
+
subscriptionURL: process.env.${Hi},
|
|
347
347
|
});
|
|
348
348
|
|
|
349
349
|
const contractState = await provider.queryContractState(${JSON.stringify(e.contractAddress)});
|
|
@@ -384,50 +384,48 @@ for (const key of Object.keys(state)) {
|
|
|
384
384
|
|
|
385
385
|
console.log(JSON.stringify({ fields, maps }));
|
|
386
386
|
process.exit(0);
|
|
387
|
-
`}function
|
|
387
|
+
`}function my(e){if(!Wi)return[];let t=[];if(!Us(e)){try{Tl(Wi,e),t.push(e)}catch{}return t}for(let r of fy){let n=Rn(Wi,r),s=Rn(e,r);if(!Us(n)||Us(s))continue;try{Tl(n,s),t.push(s)}catch{}}return t}async function Dn({dir:e,script:t,onMessage:r,env:n,cwd:s,overlaySdk:o=!0,label:i="contract"}){let a=Rn(e,"node_modules"),c=o?my(a):[],d=Rn(e,`.mn-${i}-${Date.now()}-${sy(gy).toString("hex")}.mjs`);oy(d,t);let u=()=>{try{Al(d)}catch{}for(let l of c.slice().reverse())try{Al(l)}catch{}};return new Promise((l,p)=>{let f=ny(process.execPath,[d],{cwd:s??e,stdio:["ignore","pipe","pipe"],env:{...process.env,NODE_NO_WARNINGS:"1",...n}}),h="",m="";f.stdout?.on("data",(y)=>{h+=y.toString()}),f.stderr?.on("data",(y)=>{m+=y.toString();let w=y.toString().trim();if(w&&!w.includes(Ki))r?.(w)}),f.on("close",(y)=>{if(u(),y!==0){p(Error(dy(m,y)));return}l(h.trim())}),f.on("error",(y)=>{u(),p(y)})})}var Wi,ji="MN_INDEXER_URL",Hi="MN_INDEXER_WS_URL",Rl=`
|
|
388
388
|
import { createWalletProvider, createMidnightProvider, Transaction } from '@midnight-ntwrk/midnight-js-types';
|
|
389
389
|
import { toHex, fromHex } from '@midnight-ntwrk/midnight-js-utils';
|
|
390
390
|
import { NodeZkConfigProvider } from '@midnight-ntwrk/midnight-js-node-zk-config-provider';
|
|
391
391
|
import { httpClientProofProvider } from '@midnight-ntwrk/midnight-js-http-client-proof-provider';
|
|
392
392
|
import { indexerPublicDataProvider } from '@midnight-ntwrk/midnight-js-indexer-public-data-provider';
|
|
393
393
|
import { levelPrivateStateProvider } from '@midnight-ntwrk/midnight-js-level-private-state-provider';
|
|
394
|
-
`,
|
|
395
|
-
const resolvePrivateStateSecretKey = (${
|
|
396
|
-
`;
|
|
394
|
+
`,cy,_l,Ki="__MN_ERROR__",Or,fy,gy=4;var Mr=E(()=>{Me();Bi();Wi=ay();cy=`
|
|
395
|
+
const resolvePrivateStateSecretKey = (${El.toString()});
|
|
396
|
+
`;_l=`
|
|
397
397
|
const coerceArg = (${Fs.toString()});
|
|
398
398
|
`,Or=`
|
|
399
399
|
const fail = (e) => {
|
|
400
|
-
process.stderr.write('\\n${
|
|
400
|
+
process.stderr.write('\\n${Ki} ' + JSON.stringify(String(e?.message ?? e)) + '\\n');
|
|
401
401
|
process.exit(1);
|
|
402
402
|
};
|
|
403
403
|
process.on('uncaughtException', fail);
|
|
404
404
|
process.on('unhandledRejection', fail);
|
|
405
|
-
`;
|
|
405
|
+
`;fy=["@midnight-ntwrk","ws"]});import{randomBytes as hy}from"node:crypto";function Vi(e,t,r){if(e.networkId.toLowerCase()!=="undeployed")throw new Ji(e.networkId);return{MIDNIGHT_ACCOUNT_NODE_URL:wy(e.node),MIDNIGHT_ACCOUNT_INDEXER_URL:e.indexer,MIDNIGHT_ACCOUNT_PROOF_SERVER_URL:e.proofServer,MIDNIGHT_ACCOUNT_STATE_DIR:t,MIDNIGHT_ACCOUNT_ARTEFACTS_DIR:r.kind==="package"?ml():void 0,MIDNIGHT_ACCOUNT_ARTEFACTS_SOURCE:void 0,BENCH_PROFILE:void 0}}function ky(e){return`const value = BigInt(${JSON.stringify(e)});
|
|
406
406
|
const balances = await rpcCall('getShieldedBalances', {});
|
|
407
407
|
const held = BigInt(balances?.[${JSON.stringify(Lt)}] ?? 0);
|
|
408
|
-
const night = (specks) => (specks / ${
|
|
408
|
+
const night = (specks) => (specks / ${Bt}n) + '.' + String(specks % ${Bt}n).padStart(${String(Bt).length-1}, '0') + ' NIGHT';
|
|
409
409
|
if (held < value) {
|
|
410
410
|
fail(new Error('Not enough shielded NIGHT for this deposit: the wallet holds ' + night(held) + ' shielded and the deposit takes ' + night(value) + '. '
|
|
411
411
|
+ 'Get shielded NIGHT into it first: midnight airdrop <amount> --shielded on a local chain, or midnight transfer <this wallet> <amount> --shielded from another wallet.'));
|
|
412
412
|
}
|
|
413
|
-
const result = await driver.depositOver(wallet, value);`}function
|
|
413
|
+
const result = await driver.depositOver(wallet, value);`}function Cy(e,t,r){if(e.kind==="account")return`${Or}${Pl(t)}
|
|
414
414
|
const result = driver.accountOnRecord() ?? null;
|
|
415
|
-
${
|
|
415
|
+
${$l}
|
|
416
416
|
process.exit(0);
|
|
417
|
-
`;if(
|
|
417
|
+
`;if(r===void 0)throw Error(`The ${e.kind} action needs an mn serve to pay`);let n=e.kind==="deploy"?`const result = await driver.deployOver(wallet, process.env.${Ol});`:e.kind==="deposit"?ky(e.value):`const written = [];
|
|
418
418
|
const exitCode = await driver.runOwnerOver(wallet, ${JSON.stringify(e.argv)}, (text) => { written.push(text); });
|
|
419
419
|
const result = { exitCode, output: written.join('\\n'), errors: reported };`;return`${Or}
|
|
420
|
-
${
|
|
421
|
-
${
|
|
422
|
-
${
|
|
423
|
-
${
|
|
420
|
+
${Ws(r,t.kind==="package"?t.wsUrl:"ws")}
|
|
421
|
+
${vy(t)}${Pl(t)}
|
|
422
|
+
${n}
|
|
423
|
+
${$l}
|
|
424
424
|
rpcClose();
|
|
425
425
|
process.exit(0);
|
|
426
|
-
`}function
|
|
426
|
+
`}function xy(e,t){let r=e.trim().split(`
|
|
427
427
|
`).at(-1)??"";try{return JSON.parse(r)}catch{throw Error(`The account build's ${t} returned unexpected output:
|
|
428
|
-
${e}`)}}async function Hs(e,t,r,n={}){let
|
|
429
|
-
process.stdout.write('\\n' + JSON.stringify(result) + '\\n');
|
|
430
|
-
`;var Vi=E(()=>{Mr();ue();Fi();Gi=class Gi extends R{constructor(e){super(`The account build reaches only an undeployed (local) network; this is ${e}. Run mn grant with --network undeployed and the endpoints of a local ledger-9 stack.`);this.name="UnreachableByAccountBuildError",Object.setPrototypeOf(this,Gi.prototype)}};Dl=`
|
|
428
|
+
${e}`)}}async function Hs(e,t,r,n={}){let{build:s}=e,o=await Dn({dir:s.kind==="package"?e.recordsDir:s.dir,script:Cy(t,s,e.servePort),cwd:e.recordsDir,env:{...Vi(e.networkConfig,e.recordsDir,s),...n},onMessage:e.onMessage,overlaySdk:!1,label:"grant"});return xy(o,r)}function Ml(e){return Hs(e,{kind:"account"},"account lookup")}function Fl(e,t){return Hs(e,{kind:"deploy"},"deploy",{[Ol]:t})}async function Ul(e,t){if(!/^[1-9]\d*$/.test(t))throw Error(`A deposit's value is a positive whole number of the smallest unit; got "${t}"`);return Hs(e,{kind:"deposit",value:t},"deposit")}function Ll(e,t){return Hs(e,{kind:"owner",argv:t},"owner command")}function Bl(){return hy(32).toString("hex")}var Ji,wy=(e)=>e.replace(/^ws/,"http"),Ol="MN_GRANT_OWNER_KEY",yy="midnight config unset account-build, and no --account-build",Sy=(e)=>e.kind==="package"?JSON.stringify(e.driverUrl):`pathToFileURL(resolve(dirname(fileURLToPath(import.meta.url)), ${JSON.stringify(Os)})).href`,by=(e)=>e.kind==="package"?e.typesUrl:"@midnight-ntwrk/midnight-js-types",Pl=(e)=>`
|
|
431
429
|
import { dirname, resolve } from 'node:path';
|
|
432
430
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
433
431
|
|
|
@@ -437,12 +435,12 @@ const reported = [];
|
|
|
437
435
|
console.log = (...args) => process.stderr.write(args.join(' ') + '\\n');
|
|
438
436
|
console.error = (...args) => { reported.push(args.join(' ')); };
|
|
439
437
|
|
|
440
|
-
const driver = await import(
|
|
441
|
-
if (driver.DRIVER_VERSION !== ${
|
|
442
|
-
fail(new Error('This account build speaks version ' + driver.DRIVER_VERSION + ' of its interface; this mn speaks version ${
|
|
438
|
+
const driver = await import(${Sy(e)});
|
|
439
|
+
if (driver.DRIVER_VERSION !== ${Fi}) {
|
|
440
|
+
fail(new Error('This account build speaks version ' + driver.DRIVER_VERSION + ' of its interface; this mn speaks version ${Fi}. ${e.kind==="package"?"Reinstall mn.":`Update the build, or drive the account package mn installs instead: ${yy}.`}'));
|
|
443
441
|
}
|
|
444
|
-
`,
|
|
445
|
-
import { createWalletProvider, createMidnightProvider, Transaction } from
|
|
442
|
+
`,vy=(e)=>`
|
|
443
|
+
import { createWalletProvider, createMidnightProvider, Transaction } from ${JSON.stringify(by(e))};
|
|
446
444
|
const toHex = (bytes) => Buffer.from(bytes).toString('hex');
|
|
447
445
|
const fromHex = (hex) => new Uint8Array(Buffer.from(hex, 'hex'));
|
|
448
446
|
|
|
@@ -455,10 +453,12 @@ const wallet = {
|
|
|
455
453
|
balanceTx: (...args) => walletProvider.balanceTx(...args),
|
|
456
454
|
submitTx: (...args) => midnightProvider.submitTx(...args),
|
|
457
455
|
};
|
|
458
|
-
|
|
456
|
+
`,$l=`
|
|
457
|
+
process.stdout.write('\\n' + JSON.stringify(result) + '\\n');
|
|
458
|
+
`;var qi=E(()=>{Mr();ue();Li();Ji=class Ji extends R{constructor(e){super(`The account build reaches only an undeployed (local) network; this is ${e}. Run mn grant with --network undeployed and the endpoints of a local ledger-9 stack.`);this.name="UnreachableByAccountBuildError",Object.setPrototypeOf(this,Ji.prototype)}}});function Ay(e){return jl.includes(e??"")}function Wl(e,t,r,n){if(n.includes(t))return;let s=r.find((o)=>e.flags[o]!==void 0);if(s!==void 0)throw new R(`--${s} only applies to: midnight grant ${n.join(", ")}`)}function In(e,t,r,n){if(e.positionals.length>r){let s=e.positionals.slice(r).join(" ");throw new R(`midnight grant ${t} takes ${n}; unexpected: ${s}`)}return e.positionals}function Hl(e){let t=e.subcommand;if(!Ay(t))throw new R(Ey);switch(Wl(e,t,["dev-owner-key"],["deploy"]),Wl(e,t,[...zi.map(([r])=>r),"yes"],["issue"]),t){case"deploy":return In(e,t,0,"no argument"),{subcommand:t,devOwnerKey:D(e,"dev-owner-key")};case"deposit":{let[r]=In(e,t,1,"one amount of NIGHT");if(r===void 0)throw new R(`Missing the amount of NIGHT to deposit.
|
|
459
459
|
Usage: midnight grant deposit <amount>`);return{subcommand:t,amount:r,value:Pt(Nr(r)).toString()}}case"status":case"list":case"revoke-all":return In(e,t,0,"no argument"),{subcommand:t};case"issue":{let[r]=In(e,t,1,"one grant request link");if(r===void 0&&typeof e.flags.yes==="string")throw new R("Put --yes after the grant request link: midnight grant issue <link> --yes");if(r===void 0)throw new R(`Missing the grant request link.
|
|
460
|
-
Usage: midnight grant issue <link> [--cap N] [--per-call N] [--max-coin N] [--expires-in SECONDS] [--yes]`);let n={};for(let[s,o]of
|
|
461
|
-
Usage: midnight grant revoke <grant id | slot>`);if(!
|
|
460
|
+
Usage: midnight grant issue <link> [--cap N] [--per-call N] [--max-coin N] [--expires-in SECONDS] [--yes]`);let n={};for(let[s,o]of zi){let i=C(e,s);if(i===void 0)continue;if(!/^\d+$/.test(i))throw new R(`--${s} must be a whole number; got "${i}"`);if(s==="expires-in"&&BigInt(i)===0n)throw new R("--expires-in must be at least 1 second");n[o]=i}return{subcommand:t,link:r,limits:n,confirmed:D(e,"yes")}}case"revoke":{let[r]=In(e,t,1,"one grant id or slot");if(r===void 0)throw new R(`Missing the grant to revoke.
|
|
461
|
+
Usage: midnight grant revoke <grant id | slot>`);if(!Ty.test(r))throw new R(`A grant is named by its id (64 hex characters) or its slot (a number); got "${r}"`);return{subcommand:t,target:r}}}}function Gl(e){switch(e.subcommand){case"deploy":case"deposit":case"revoke":case"revoke-all":return!0;case"issue":return e.confirmed;case"status":case"list":return!1}}function Kl(e){if(e===null||typeof e!=="object"||Array.isArray(e)||Object.keys(e).length===0)throw Error("The account build reported no terms for this grant request.");return Object.entries(e).map(([t,r])=>`${t} ${typeof r==="string"?r:JSON.stringify(r)}`).join(", ")}function Jl(e,t){let r=t?["--json"]:[];switch(e.subcommand){case"status":return["status",...r];case"list":return["grants",...r];case"revoke-all":return["revoke-all",...r];case"revoke":return["revoke",e.target,...r];case"issue":{let n=zi.flatMap(([s,o])=>e.limits[o]===void 0?[]:[`--${s}`,e.limits[o]]);return["issue",e.link,...n,...e.confirmed?["--yes"]:[],...r]}}}var jl,zi,Ey,Ty;var Gs=E(()=>{re();ue();bt();jl=["deploy","deposit","status","list","issue","revoke","revoke-all"],zi=[["cap","cap"],["per-call","perCall"],["max-coin","maxCoin"],["expires-in","expiresIn"]],Ey=`Usage: midnight grant <${jl.join("|")}>
|
|
462
462
|
|
|
463
463
|
deploy Deploy this wallet's account, which holds what an agent may spend
|
|
464
464
|
deposit Move shielded NIGHT from this wallet into its account
|
|
@@ -468,18 +468,18 @@ Usage: midnight grant revoke <grant id | slot>`);if(!py.test(r))throw new R(`A g
|
|
|
468
468
|
revoke Revoke one grant, by its id or slot
|
|
469
469
|
revoke-all Revoke every grant
|
|
470
470
|
|
|
471
|
-
Run "midnight help grant" for more info.`;
|
|
472
|
-
Deploy one: midnight grant deploy --dev-owner-key`);this.name="NoAccountError",Object.setPrototypeOf(this,
|
|
471
|
+
Run "midnight help grant" for more info.`;Ty=/^(?:[0-9a-fA-F]{64}|\d+)$/});async function Fr(e){let t=Hl(e),r=fl(C(e,"account-build"),Ne()["account-build"]);gl(r),hl();let n=Pr(e,"grant",t.subcommand),s=wl(C(e,"wallet")),o=yl(n.network,s);Vi(n.networkConfig,o,r),Sl(o);let i={build:r,recordsDir:o,networkConfig:n.networkConfig},a=await Ml(i);if(t.subcommand==="deploy"){if(a===null&&!t.devOwnerKey)throw new R(Ny)}else if(a===null)throw new Yi(s,n.network);return{request:t,target:n,walletName:s,bridge:i,account:a}}var Ny="A new account needs --dev-owner-key for now: its owner key will be a random development key, kept in the account's records, which the wallet's mnemonic can't recover. (A key derived from the mnemonic comes once wallets agree on how to derive it.)",Yi;var Ks=E(()=>{re();Gt();ue();$s();Li();bl();qi();Gs();Yi=class Yi extends Error{code="NO_ACCOUNT";constructor(e,t){super(`Wallet "${e}" has no account on ${t} yet.
|
|
472
|
+
Deploy one: midnight grant deploy --dev-owner-key`);this.name="NoAccountError",Object.setPrototypeOf(this,Yi.prototype)}}});function _n(e,t){let r=e.trim().replace(/^0x/,"");if(r.length!==64&&r.length!==128||!/^[0-9a-fA-F]+$/.test(r))throw new R(`${t} must be 64 or 128 hex characters (a 32-byte seed, or a 64-byte BIP-39 seed)`);return Buffer.from(r,"hex")}function Xi(e,t={}){let r=C(e,"seed"),n=r??process.env.MN_SEED;if(n)return{seed:_n(n,r?"--seed":"MN_SEED"),walletPath:null,config:null};let s=C(e,"wallet");if(s===void 0&&t.requireExplicit)throw new R(`${t.label??"This command"} needs a seed source. Provide one of:
|
|
473
473
|
--seed <hex> seed as 64 hex chars (32-byte) or 128 (64-byte BIP-39)
|
|
474
474
|
MN_SEED=<hex> same seed via env (kept off the process list)
|
|
475
|
-
--wallet <name> derive from a saved wallet`);let o=oe(s),i=ce(o);return{seed:Buffer.from(i.seed,"hex"),walletPath:o,config:i}}function
|
|
476
|
-
Use --force to overwrite, or --output <file> to save to a different path.`);let c,d;if(o!==void 0)c=_n(o,n!==void 0?"--seed":"MN_SEED");else if(i!==void 0){if(!
|
|
475
|
+
--wallet <name> derive from a saved wallet`);let o=oe(s),i=ce(o);return{seed:Buffer.from(i.seed,"hex"),walletPath:o,config:i}}function Js(e,t){return Xi(e,t).seed}var Ur=E(()=>{re();ue();Pe()});var Xl={};ve(Xl,{default:()=>Yl});import*as zl from"fs";import*as Vs from"path";import{homedir as Ry}from"os";import{generateMnemonic as Dy,mnemonicToSeedSync as Vl,validateMnemonic as Iy}from"@scure/bip39";import{wordlist as ql}from"@scure/bip39/wordlists/english.js";async function Yl(e){let t=xe({args:e}),r=C(e,"output"),n=C(e,"seed"),s=process.env.MN_SEED?.trim(),o=n??(s?s:void 0),i=C(e,"mnemonic");if(o!==void 0&&i!==void 0)throw Error("Cannot specify both --seed and --mnemonic. Use one or the other.");let a=r?Vs.resolve(r):Vs.join(Ry(),te,zn);if(zl.existsSync(a)&&!D(e,"force"))throw Error(`Wallet file already exists: ${a}
|
|
476
|
+
Use --force to overwrite, or --output <file> to save to a different path.`);let c,d;if(o!==void 0)c=_n(o,n!==void 0?"--seed":"MN_SEED");else if(i!==void 0){if(!Iy(i,ql))throw Error("Invalid BIP-39 mnemonic. Expected 12 or 24 words from the English wordlist.");d=i,c=Buffer.from(Vl(d))}else d=Dy(ql,256),c=Buffer.from(Vl(d));let u=qt(c),l=u[t],p={seed:c.toString("hex"),addresses:u,createdAt:new Date().toISOString()};if(d)p.mnemonic=d;let f=ds(p,r);if(D(e,"json")){let h={addresses:u,activeAddress:l,activeNetwork:t,seed:c.toString("hex"),file:f,createdAt:p.createdAt};if(d)h.mnemonic=d;I(h);return}if(process.stdout.write(l+`
|
|
477
477
|
`),process.stderr.write(`
|
|
478
|
-
`+
|
|
478
|
+
`+B("Wallet Generated")+`
|
|
479
479
|
|
|
480
|
-
`),process.stderr.write(
|
|
481
|
-
`),process.stderr.write(
|
|
482
|
-
`),process.stderr.write(
|
|
480
|
+
`),process.stderr.write(A("Network",t)+`
|
|
481
|
+
`),process.stderr.write(A("Address",se(l))+`
|
|
482
|
+
`),process.stderr.write(A("File",f)+`
|
|
483
483
|
`),process.stderr.write(`
|
|
484
484
|
`),d)process.stderr.write(ee(P(" MNEMONIC (save securely!):"))+`
|
|
485
485
|
`),process.stderr.write(` ${d}
|
|
@@ -491,9 +491,9 @@ Use --force to overwrite, or --output <file> to save to a different path.`);let
|
|
|
491
491
|
`),process.stderr.write(g(" Next: midnight info | midnight balance")+`
|
|
492
492
|
|
|
493
493
|
`),process.stderr.write(z("✓")+` Wallet saved
|
|
494
|
-
`)}var
|
|
494
|
+
`)}var Zl=E(()=>{re();Xe();Ee();Pe();Ur();de()});var eu={};ve(eu,{default:()=>Ql});async function Ql(e){let t=oe(C(e,"wallet")),r=ce(t),n=xe({args:e}),s=r.addresses[n];if(D(e,"json")){let i={addresses:r.addresses,activeNetwork:n,activeAddress:s,createdAt:r.createdAt,file:t};if(r.shieldedAddresses)i.shieldedAddresses=r.shieldedAddresses;I(i);return}process.stdout.write(s+`
|
|
495
495
|
`),process.stderr.write(`
|
|
496
|
-
`+
|
|
496
|
+
`+B("Wallet Info")+`
|
|
497
497
|
|
|
498
498
|
`);let o=Object.keys(r.addresses);for(let i=0;i<o.length;i++){let a=o[i],c=a===n,d=r.addresses[a],u=r.shieldedAddresses?.[a],l=c?P(X(a))+g(" (active)"):a;if(process.stderr.write(` ${l}
|
|
499
499
|
`),process.stderr.write(` ${g("unshielded")} ${se(d)}
|
|
@@ -506,7 +506,7 @@ Use --force to overwrite, or --output <file> to save to a different path.`);let
|
|
|
506
506
|
`),process.stderr.write(` ${g("created")} ${r.createdAt}
|
|
507
507
|
`),process.stderr.write(` ${g("file ")} ${t}
|
|
508
508
|
|
|
509
|
-
`)}var
|
|
509
|
+
`)}var tu=E(()=>{re();Pe();Ee();de();de()});function Py(e){return!_y.includes(e)}function qs(e,t=!1){return Py(e)||t}function zs(e){return`Shielded is unavailable on ${e} (no faucet). Use --force-shielded to sync anyway, or --network undeployed.`}var _y;var Zi=E(()=>{_y=["preview","preprod"]});import*as Lr from"@midnightntwrk/ledger-v9";function Oy(e){let t=Lr.unshieldedToken().raw,r=0n,n=0;for(let s of e.coins)if(s.type===t)r+=s.value,n++;return{balance:r,count:n}}function ru(e,t,r={}){let{onProgress:n,onCheckpoint:s,timeoutMs:o=600000,idleMs:i=5000,initialSilenceMs:a=3000,signal:c,initialState:d,startFromId:u=0}=r,l=500,p=d??new Lr.ZswapLocalState,f=[],h=0,m=u-1,y=-1,w=()=>{if(f.length===0)return;if(p=p.replayEventsWithChanges(e,f).state,h+=f.length,f.length=0,s&&m>=0)try{s(p,m)}catch{}};return Cr(t,{query:$y,variables:{id:u},idleMs:i,timeoutMs:o,initialSilenceMs:d?a:0,signal:c,onNext:(S)=>{let k=S?.zswapLedgerEvents;if(!k)return!1;let T;try{T=Lr.Event.deserialize(new Uint8Array(Buffer.from(k.raw,"hex")))}catch(N){throw Error(`Failed to deserialize zswap event ${k.id}: ${N.message}`)}if(f.push(T),m=k.id,k.maxId>y)y=k.maxId;if(f.length>=500)try{w()}catch(N){throw Error(`Failed applying zswap events: ${N.message}`)}return n?.(h+f.length,y),m>=y},buildResult:(S)=>{try{w();let{balance:k,count:T}=Oy(p);return{balance:k,availableCoins:T,eventCount:h,state:p,lastAppliedEventId:m,partial:S}}catch(k){throw Error(`Failed to build shielded state: ${k.message}`)}}})}var $y=`
|
|
510
510
|
subscription ZswapLedgerEvents($id: Int) {
|
|
511
511
|
zswapLedgerEvents(id: $id) {
|
|
512
512
|
id
|
|
@@ -514,101 +514,101 @@ Use --force to overwrite, or --output <file> to save to a different path.`);let
|
|
|
514
514
|
maxId
|
|
515
515
|
}
|
|
516
516
|
}
|
|
517
|
-
`;var
|
|
517
|
+
`;var nu=E(()=>{ws()});import{existsSync as Ys,mkdirSync as My,writeFileSync as Fy,readFileSync as Uy,unlinkSync as ea,readdirSync as su,renameSync as Ly}from"node:fs";import{join as Br,dirname as By}from"node:path";import{homedir as ou}from"node:os";import{randomBytes as Wy}from"node:crypto";import*as Pn from"@midnightntwrk/ledger-v9";function au(e){return Pn.ZswapSecretKeys.fromSeed(Jt(e)).coinPublicKey}function cu(e,t){let r=t??Br(ou(),te,Oe);return Br(r,e)}function ta(e,t,r){let n=t.slice(0,20);return Br(cu(e,r),`shielded-${n}.json`)}function jy(e,t,r,n){let s=ta(e,t,r);if(!Ys(s))return null;try{let o=JSON.parse(Uy(s,"utf-8"));if(o.version!==iu)return null;if(o.network!==e)return null;if(o.coinPublicKeyHex!==t)return null;if(typeof o.lastAppliedEventId!=="number")return null;if(typeof o.zswapState!=="string")return null;if(n&&o.chainId&&o.chainId!==n)return null;return{state:Pn.ZswapLocalState.deserialize(new Uint8Array(Buffer.from(o.zswapState,"hex"))),lastAppliedEventId:o.lastAppliedEventId}}catch{return null}}function Qi(e,t,r,n,s,o){let i={version:iu,network:e,coinPublicKeyHex:t,lastAppliedEventId:n,timestamp:new Date().toISOString(),zswapState:Buffer.from(r.serialize()).toString("hex"),...o?{chainId:o}:{}},a=ta(e,t,s),c=By(a);if(!Ys(c))My(c,{recursive:!0,mode:be});let d=a+`.tmp.${Wy(4).toString("hex")}`;try{Fy(d,JSON.stringify(i),{mode:Te}),Ly(d,a)}catch(u){try{ea(d)}catch{}throw u}}function $n(e,t,r){let n=r??Br(ou(),te,Oe);if(e&&t){let o=ta(e,t,r);try{ea(o)}catch{}return}let s=(o)=>{if(!Ys(o))return;try{for(let i of su(o))if(i.startsWith("shielded-")&&i.endsWith(".json"))try{ea(Br(o,i))}catch{}}catch{}};if(e){s(cu(e,r));return}if(!Ys(n))return;try{for(let o of su(n))s(Br(n,o))}catch{}}async function du(e,t,r,n={}){let s=Pn.ZswapSecretKeys.fromSeed(Jt(e)),o=s.coinPublicKey;yt(t,r);let i=n.forceFresh?null:jy(t,o,void 0,n.chainId);if(i&&Ss(i.lastAppliedEventId,await ys(r,"zswap")))$n(t,o),i=null;let a=i?i.lastAppliedEventId+1:0,c=await ru(s,r,{initialState:i?.state,startFromId:a,onProgress:n.onProgress,signal:n.signal,timeoutMs:n.timeoutMs,onCheckpoint:(d,u)=>{try{Qi(t,o,d,u,void 0,n.chainId)}catch{}}});if(c.lastAppliedEventId>=0)Qi(t,o,c.state,c.lastAppliedEventId,void 0,n.chainId);else if(!i)Qi(t,o,c.state,-1,void 0,n.chainId);return{balance:c.balance,availableCoins:c.availableCoins,eventCount:c.eventCount,lastAppliedEventId:c.lastAppliedEventId>=0?c.lastAppliedEventId:i?.lastAppliedEventId??-1,fromCache:i!==null,partial:c.partial}}var iu=2;var ra=E(()=>{Cn();Vt();nu();bs()});function lu(e={}){let t=Math.min(Math.max(e.windowMs??15000,1000),60000),r=[],n=null,s=(i)=>{let a=i-t;while(r.length>0&&r[0].t<a)r.shift()},o=()=>{let i=r[r.length-1],a=r[0],c=i.highest>0?Math.min(100,Math.round(i.applied/i.highest*100)):null,d=null,u=null;if(r.length>=2){let l=i.applied-a.applied,p=i.t-a.t;if(p>=1000&&l>0){d=l/(p/1000);let f=Math.max(0,i.highest-i.applied);u=f>0?f/d:0}}return{applied:i.applied,highest:i.highest,percent:c,ratePerSec:d,etaSec:u}};return{sample(i){return r.push(i),s(i.t),n=o(),n},snapshot(){return n},reset(){r.length=0,n=null}}}function uu(e,t="Syncing"){let r=[t];if(e.percent!==null)r.push(`${e.percent}%`);else if(e.highest===0)r.push(`${e.applied} events`);if(e.etaSec!==null&&e.etaSec>0)r.push(`ETA ${Hy(e.etaSec)}`);if(e.ratePerSec!==null&&e.ratePerSec>0)r.push(`${Math.round(e.ratePerSec)} evt/s`);return r.join(" · ")}function Hy(e){if(!Number.isFinite(e)||e<0)return"?";if(e<60)return`${Math.ceil(e)}s`;let t=Math.floor(e/60),r=Math.round(e-t*60);if(t<60)return r>0?`${t}m ${r}s`:`${t}m`;let n=Math.floor(t/60),s=t-n*60;return s>0?`${n}h ${s}m`:`${n}h`}function Ve(){return{update(){},stop(){},fail(){},log(){},clear(){}}}function fu(e){return e.replace(/\x1b\[[0-9;]*m/g,"")}function H(e){let t=!1;if(!ln()){let a=e;process.stderr.write(`⠋ ${a}`);let c={update(d){a=d,process.stderr.write(`\r⠋ ${a}\x1B[K`)},stop(d){if(t)return;t=!0,$t=null,process.stderr.write(`\r✓ ${d??a}\x1B[K
|
|
518
518
|
`)},fail(d){if(t)return;t=!0,$t=null,process.stderr.write(`\r✗ ${d??a}\x1B[K
|
|
519
519
|
`)},log(d){process.stderr.write(`\r\x1B[K${d}
|
|
520
|
-
`),process.stderr.write(`⠋ ${a}`)},clear(){if(t)return;t=!0,$t=null,process.stderr.write("\r\x1B[K")}};return $t=c,c}let r=0,n=e,s=()=>{let a=X(
|
|
520
|
+
`),process.stderr.write(`⠋ ${a}`)},clear(){if(t)return;t=!0,$t=null,process.stderr.write("\r\x1B[K")}};return $t=c,c}let r=0,n=e,s=()=>{let a=X(pu[r]),d=(process.stderr.columns||80)-4,u=n;if(fu(u).length>d)u=fu(u).slice(0,d);process.stderr.write(`\r${a} ${u}\x1B[K`),r=(r+1)%pu.length};s();let o=setInterval(s,Gy),i={update(a){n=a},stop(a){if(t)return;t=!0,clearInterval(o),$t=null;let c=a??n;process.stderr.write(`\r\x1B[32m✓\x1B[0m ${c}\x1B[K
|
|
521
521
|
`)},fail(a){if(t)return;t=!0,clearInterval(o),$t=null;let c=a??n;process.stderr.write(`\r\x1B[31m✗\x1B[0m ${c}\x1B[K
|
|
522
522
|
`)},log(a){process.stderr.write(`\r\x1B[K${a}
|
|
523
|
-
`),s()},clear(){if(t)return;t=!0,clearInterval(o),$t=null,process.stderr.write("\r\x1B[K")}};return $t=i,i}async function Xs(e,t,r){let n=Date.now(),s=(a)=>{let c=Math.floor(a/1000),d=Math.floor(c/60).toString().padStart(2,"0"),u=(c%60).toString().padStart(2,"0");return`${d}:${u}`},o=()=>e.update(`${t} ${s(Date.now()-n)}`);o();let i=setInterval(o,1000);try{return await r}finally{clearInterval(i)}}var
|
|
524
|
-
Drop --network (we'll infer from the address) or pass an address for ${n}.`);if(!n&&r)e={...e,flags:{...e.flags,network:r}};let{name:s,config:o}=me({args:e});if(D(e,"shielded")){let a=
|
|
523
|
+
`),s()},clear(){if(t)return;t=!0,clearInterval(o),$t=null,process.stderr.write("\r\x1B[K")}};return $t=i,i}async function Xs(e,t,r){let n=Date.now(),s=(a)=>{let c=Math.floor(a/1000),d=Math.floor(c/60).toString().padStart(2,"0"),u=(c%60).toString().padStart(2,"0");return`${d}:${u}`},o=()=>e.update(`${t} ${s(Date.now()-n)}`);o();let i=setInterval(o,1000);try{return await r}finally{clearInterval(i)}}var pu,Gy=80,$t=null;var ct=E(()=>{pu=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"]});var wu={};ve(wu,{default:()=>gu});import*as mu from"@midnightntwrk/ledger-v9";import{MidnightBech32m as Ky}from"@midnightntwrk/wallet-sdk/address-format";async function gu(e){if(e.subcommand)return Vy(e);return hu(e)}function Jy(e){let t=e.match(/^mn_addr_([a-z]+)1/);if(!t)return null;let r=t[1];return De(r)?r:null}async function Vy(e){if(ze(e))Qe();let t=e.subcommand;U("balance",`address=${t}`);let r=Jy(t),n=C(e,"network");if(n&&r&&n!==r)throw Error(`Address belongs to ${r} but --network is ${n}.
|
|
524
|
+
Drop --network (we'll infer from the address) or pass an address for ${n}.`);if(!n&&r)e={...e,flags:{...e.flags,network:r}};let{name:s,config:o}=me({args:e});if(D(e,"shielded")){let a=Tc(t);if(a){U("balance",`shielded positional → wallet ${a.wallet.name} on ${a.network}`);let c={...e,flags:{...e.flags,wallet:a.wallet.file,network:a.network}};return hu(c)}throw Error("Shielded balances are private — they can only be read with the wallet's secret key, "+`not from an address alone.
|
|
525
525
|
This address isn't one of your wallets. Check its shielded balance from the wallet that owns it:
|
|
526
|
-
midnight balance --wallet <name> --shielded --network ${s}`)}Le(o,{proofServer:
|
|
526
|
+
midnight balance --wallet <name> --shielded --network ${s}`)}Le(o,{proofServer:C(e,"proof-server"),node:C(e,"node"),indexerWS:C(e,"indexer-ws")},s);let i=H(`Checking balance on ${s}...`);try{let a=await $e().unshielded(t,o,{forceFresh:D(e,"no-cache"),onProgress:(c,d)=>{if(d>0){let u=Math.round(c/d*100);i.update(`Syncing transactions... ${u}%`)}}});if(i.stop(`Synced ${a.txCount} transactions`),D(e,"json")){let c={};for(let[u,l]of a.balances){let p=vn(u)?"NIGHT":u;c[p]=vn(u)?zt(l):l.toString()}let d=c.NIGHT!==void 0?{NIGHT:c.NIGHT}:{};if(Ct(e)){I({network:s,balances:c,...d,utxoCount:a.utxoCount});return}I({address:t,network:s,balances:c,...d,utxoCount:a.utxoCount,txCount:a.txCount});return}if(a.balances.size===0)process.stdout.write(`0
|
|
527
527
|
`);else for(let[c,d]of a.balances)process.stdout.write(`${vn(c)?"NIGHT":c}=${d}
|
|
528
528
|
`);if(process.stderr.write(`
|
|
529
|
-
`+
|
|
529
|
+
`+B("Balance")+`
|
|
530
530
|
|
|
531
|
-
`),process.stderr.write(
|
|
532
|
-
`),process.stderr.write(
|
|
533
|
-
`),process.stderr.write(
|
|
534
|
-
`),process.stderr.write(
|
|
531
|
+
`),process.stderr.write(A("Address",se(t))+`
|
|
532
|
+
`),process.stderr.write(A("Network",s)+`
|
|
533
|
+
`),process.stderr.write(A("UTXOs",a.utxoCount.toString())+`
|
|
534
|
+
`),process.stderr.write(A("Transactions",a.txCount.toString())+`
|
|
535
535
|
`),process.stderr.write(`
|
|
536
536
|
`),a.balances.size===0)process.stderr.write(` ${g("No balance found")}
|
|
537
|
-
`);else for(let[c,d]of a.balances)if(vn(c))process.stderr.write(
|
|
538
|
-
`);else{let u=c.slice(0,8)+"…"+c.slice(-8);process.stderr.write(
|
|
537
|
+
`);else for(let[c,d]of a.balances)if(vn(c))process.stderr.write(A("NIGHT",P(br(d)))+`
|
|
538
|
+
`);else{let u=c.slice(0,8)+"…"+c.slice(-8);process.stderr.write(A(`Token ${u}`,P(d.toString()))+`
|
|
539
539
|
`)}process.stderr.write(`
|
|
540
540
|
`+Z()+`
|
|
541
541
|
|
|
542
|
-
`)}catch(a){throw i.fail("Failed"),a}}async function
|
|
543
|
-
`+
|
|
542
|
+
`)}catch(a){throw i.fail("Failed"),a}}async function hu(e){if(ze(e))Qe();let{name:t,config:r}=me({args:e});U("balance",`network=${t} indexerWS=${r.indexerWS}`);let{seed:n,walletPath:s,config:o}=Xi(e);U("balance",`wallet path=${s??"(from --seed/MN_SEED)"}`);let i=o?.addresses[t]??Ie(n,t),a=o?.shieldedAddresses?.[t]??"";Le(r,{proofServer:C(e,"proof-server"),node:C(e,"node"),indexerWS:C(e,"indexer-ws")},t);let c=Fe(),d=Ue(),u=D(e,"no-cache"),l=D(e,"json"),p=mu.unshieldedToken().raw,f=null;try{if(!l){if(process.stderr.write(`
|
|
543
|
+
`+B("Balance")+`
|
|
544
544
|
|
|
545
|
-
`),process.stderr.write(
|
|
546
|
-
`),a)process.stderr.write(
|
|
547
|
-
`);process.stderr.write(
|
|
545
|
+
`),process.stderr.write(A("Address",se(i))+`
|
|
546
|
+
`),a)process.stderr.write(A("Shielded",se(a))+`
|
|
547
|
+
`);process.stderr.write(A("Network",t)+`
|
|
548
548
|
`),process.stderr.write(`
|
|
549
549
|
`+P("Unshielded")+`
|
|
550
|
-
`)}if(!l)f=H("Checking unshielded...");U("balance",`phase=unshielded forceFresh=${u}`);let h=await $e().unshielded(i,r,{forceFresh:u}),m=h.balances.get(p)??0n,y=h.utxoCount;if(U("balance",`unshielded fromCache=${h.fromCache} utxos=${y} txs=${h.txCount}`),f)if(f.stop("Unshielded ready"),f=null,m>0n)process.stderr.write(
|
|
551
|
-
`),process.stderr.write(
|
|
550
|
+
`)}if(!l)f=H("Checking unshielded...");U("balance",`phase=unshielded forceFresh=${u}`);let h=await $e().unshielded(i,r,{forceFresh:u}),m=h.balances.get(p)??0n,y=h.utxoCount;if(U("balance",`unshielded fromCache=${h.fromCache} utxos=${y} txs=${h.txCount}`),f)if(f.stop("Unshielded ready"),f=null,m>0n)process.stderr.write(A(" NIGHT",P(br(m)))+`
|
|
551
|
+
`),process.stderr.write(A(" UTXOs",y.toString())+`
|
|
552
552
|
`);else process.stderr.write(` ${g("No unshielded balance")}
|
|
553
553
|
`);if(!l)process.stdout.write(`NIGHT=${m}
|
|
554
554
|
`),process.stderr.write(`
|
|
555
555
|
`+P("Shielded")+`
|
|
556
|
-
`);let w=qs(t,D(e,"force-shielded")),S=a,k=0n,
|
|
557
|
-
`),process.stderr.write(
|
|
556
|
+
`);let w=qs(t,D(e,"force-shielded")),S=a,k=0n,T=0,N=0;if(w){if(!l)f=H("Syncing shielded...");let L=lu(),J=He(r.networkId);if(S=Ky.encode(J,cn(n)).asString(),s)yr(s,t,S);await Je(t,r);let Y=await Er(r.node).catch(()=>null)??void 0,V=await du(n,t,r.indexerWS,{forceFresh:u,chainId:Y,onProgress:(M,O)=>{if(!f)return;let le=L.sample({applied:M,highest:O,t:Date.now()});f.update(uu(le,"Syncing shielded"))}});if(k=V.balance,T=V.availableCoins,N=0,f)if(f.stop("Shielded ready"),f=null,k>0n)process.stderr.write(A(" NIGHT",P(br(k)))+`
|
|
557
|
+
`),process.stderr.write(A(" Coins",`${T} available, ${N} pending`)+`
|
|
558
558
|
`);else process.stderr.write(` ${g("No shielded balance")}
|
|
559
559
|
`)}else if(!l)process.stderr.write(` ${g("Skipped — "+zs(t))}
|
|
560
|
-
`);if(l){if(
|
|
560
|
+
`);if(l){if(Ct(e)){I({network:t,unshielded:{NIGHT:zt(m),utxoCount:y},shielded:{NIGHT:zt(k),availableCoins:T,pendingCoins:N},shieldedSynced:w});return}I({address:i,shieldedAddress:S,network:t,unshielded:{NIGHT:zt(m),utxoCount:y},shielded:{NIGHT:zt(k),availableCoins:T,pendingCoins:N},shieldedSynced:w});return}process.stdout.write(`SHIELDED_NIGHT=${w?k:"skipped"}
|
|
561
561
|
`),process.stderr.write(`
|
|
562
562
|
`+Z()+`
|
|
563
563
|
|
|
564
|
-
`)}catch(h){throw f?.fail("Failed"),h}finally{d(),c()}}var
|
|
564
|
+
`)}catch(h){throw f?.fail("Failed"),h}finally{d(),c()}}var yu=E(()=>{re();Nt();Ce();Pe();Ur();Ee();Ce();Zi();gt();kn();_t();ra();sr();Xe();Es();tt();bt();de();ct()});var bu={};ve(bu,{default:()=>Su});async function Su(e){let t=Js(e,{requireExplicit:!0,label:"address"}),r=C(e,"index"),n=r!==void 0?parseInt(r,10):0;if(isNaN(n)||n<0||!Number.isInteger(Number(r??"0")))throw Error("Key index must be a non-negative integer");let s=xe({args:e}),o=Ie(t,s,n),i=`m/44'/2400'/0'/NightExternal/${n}`;if(D(e,"json")){I({address:o,network:s,index:n,path:i});return}process.stdout.write(o+`
|
|
565
565
|
`),process.stderr.write(`
|
|
566
|
-
`),process.stderr.write(
|
|
567
|
-
`),process.stderr.write(
|
|
568
|
-
`),process.stderr.write(
|
|
569
|
-
`),process.stderr.write(
|
|
566
|
+
`),process.stderr.write(A("Network",s)+`
|
|
567
|
+
`),process.stderr.write(A("Index",n.toString())+`
|
|
568
|
+
`),process.stderr.write(A("Address",se(o))+`
|
|
569
|
+
`),process.stderr.write(A("Path",g(i))+`
|
|
570
570
|
`),process.stderr.write(Z()+`
|
|
571
571
|
|
|
572
|
-
`)}var
|
|
572
|
+
`)}var vu=E(()=>{re();Ur();Xe();Ee();de()});var Cu={};ve(Cu,{default:()=>ku});async function ku(e){let t=xe({args:e}),r=Buffer.from(ut,"hex"),n=Ie(r,t);if(D(e,"json")){I({address:n,network:t});return}process.stdout.write(n+`
|
|
573
573
|
`),process.stderr.write(`
|
|
574
|
-
`),process.stderr.write(
|
|
575
|
-
`),process.stderr.write(
|
|
576
|
-
`),process.stderr.write(
|
|
574
|
+
`),process.stderr.write(A("Network",t)+`
|
|
575
|
+
`),process.stderr.write(A("Address",se(n))+`
|
|
576
|
+
`),process.stderr.write(A("Seed",g("0x01 (genesis)"))+`
|
|
577
577
|
`),process.stderr.write(Z()+`
|
|
578
578
|
|
|
579
|
-
`)}var
|
|
579
|
+
`)}var xu=E(()=>{re();Xe();Ee();de()});import*as Eu from"@midnightntwrk/ledger-v9";async function Au(e){let t=await It(e,"{ block { height ledgerParameters } }",void 0,1e4),r=t.block?.ledgerParameters;if(typeof r!=="string"||typeof t.block?.height!=="number")throw Error("The indexer returned no ledger parameters for its latest block");return{height:t.block.height,params:Eu.LedgerParameters.deserialize(Buffer.from(r,"hex"))}}var Tu=E(()=>{bn()});var Ru={};ve(Ru,{default:()=>Nu});function On(e,t,r){let n={readTime:0n,computeTime:0n,blockUsage:0n,bytesWritten:0n,bytesChurned:0n};n[t]=r;let o=e.normalizeFullness(n)[t];return Math.round(Number(r)/o)}function qy(e){return{readTime:On(e,"readTime",1000000000n),computeTime:On(e,"computeTime",1000000000n),blockUsage:On(e,"blockUsage",10000n),bytesWritten:On(e,"bytesWritten",10000n),bytesChurned:On(e,"bytesChurned",1000000n)}}async function Nu(e){let{name:t,config:r}=me({args:e});await Je(t,r);let{height:n,params:s}=await Au(r.indexer),o=qy(s);if(D(e,"json")){I({...o,network:t,height:n});return}for(let[i,a]of Object.entries(o))process.stdout.write(`${i}=${a}
|
|
580
580
|
`);process.stderr.write(`
|
|
581
|
-
`+
|
|
581
|
+
`+B("Block Limits")+`
|
|
582
582
|
|
|
583
583
|
`),process.stderr.write(g(` From the ledger parameters of block ${n} on ${t}`)+`
|
|
584
584
|
|
|
585
|
-
`);for(let[i,a]of Object.entries(o)){let c
|
|
585
|
+
`);for(let[i,a]of Object.entries(o)){let c=zy[i]??"";process.stderr.write(A(i,`${P(a.toLocaleString())} ${g(c)}`)+`
|
|
586
586
|
`)}process.stderr.write(`
|
|
587
587
|
`+Z()+`
|
|
588
588
|
`),process.stderr.write(g(" bytesWritten is typically the tightest constraint")+`
|
|
589
589
|
`),process.stderr.write(g(" for large contract deployments.")+`
|
|
590
590
|
|
|
591
|
-
`)}var
|
|
591
|
+
`)}var zy;var Du=E(()=>{re();de();Ee();Tu();sr();zy={readTime:"picoseconds",computeTime:"picoseconds",blockUsage:"bytes",bytesWritten:"bytes",bytesChurned:"bytes"}});var $u={};ve($u,{default:()=>Pu});import*as Iu from"@midnightntwrk/ledger-v9";import{MidnightBech32m as _u,ShieldedAddress as Yy}from"@midnightntwrk/wallet-sdk/address-format";async function Pu(e,t){ur(e);let r=e.subcommand;if(!r)throw Error(`Missing amount.
|
|
592
592
|
Usage: midnight airdrop <amount> [--wallet <name|file|address>]
|
|
593
593
|
Example: midnight airdrop 1000
|
|
594
594
|
Example: midnight airdrop 1000 --wallet alice
|
|
595
|
-
Example: midnight airdrop 1000 --wallet mn_addr_undeployed1...`);let n=Nr(r),{name:s,config:o}=me({args:e});if(Le(o,{proofServer:
|
|
595
|
+
Example: midnight airdrop 1000 --wallet mn_addr_undeployed1...`);let n=Nr(r),{name:s,config:o}=me({args:e});if(Le(o,{proofServer:C(e,"proof-server"),node:C(e,"node"),indexerWS:C(e,"indexer-ws")},s),s!=="undeployed")throw Error(`Airdrop is only available on the "undeployed" network (local devnet).
|
|
596
596
|
Current network: "${s}"
|
|
597
|
-
On preprod/preview, use a faucet or transfer from another wallet.`);let i=
|
|
597
|
+
On preprod/preview, use a faucet or transfer from another wallet.`);let i=C(e,"wallet"),a=D(e,"shielded")||i!==void 0&&i.startsWith("mn_shield-addr_"),c=Zy(e,s,o,a);if(a)return tS(e,c,n,s,o,t);return eS(e,c,n,s,o,t)}function Xy(e){return e.startsWith("mn_addr_")||e.startsWith("mn_shield-addr_")}function Zy(e,t,r,n){let s=C(e,"wallet");if(s!==void 0&&Xy(s))return Qy(s,t,r,n);let o=oe(s),i=ce(o);if(n){let a=He(r.networkId),c=Buffer.from(i.seed,"hex"),d=cn(c),u=_u.encode(a,d).asString();return{kind:"wallet",raw:d,bech32m:u,walletPath:o}}return{kind:"address",address:i.addresses[t]}}function Qy(e,t,r,n){let s=e.startsWith("mn_shield-addr_");if(n&&!s)throw Error(`--shielded was passed but --wallet is an unshielded address.
|
|
598
598
|
Pass a shielded address (mn_shield-addr_...) or drop --shielded.
|
|
599
599
|
Got: ${e}`);let o=n?`mn_shield-addr_${t}1`:`mn_addr_${t}1`;if(!e.startsWith(o))throw Error(`Address does not match network "${t}".
|
|
600
600
|
Expected prefix: ${o}
|
|
601
|
-
Got: ${e}`);if(n){let i=He(r.networkId),a;try{a=
|
|
602
|
-
`+
|
|
601
|
+
Got: ${e}`);if(n){let i=He(r.networkId),a;try{a=_u.parse(e).decode(Yy,i)}catch(c){throw Error(`Invalid shielded address: ${c.message}`)}return{kind:"address",raw:a,bech32m:e}}return{kind:"address",address:e}}async function eS(e,t,r,n,s,o){if(ze(e))Qe();let i=t.address,a=Buffer.from(ut,"hex");process.stderr.write(`
|
|
602
|
+
`+B("Airdrop")+`
|
|
603
603
|
|
|
604
|
-
`),process.stderr.write(
|
|
605
|
-
`),process.stderr.write(
|
|
606
|
-
`),process.stderr.write(
|
|
607
|
-
`),process.stderr.write(
|
|
604
|
+
`),process.stderr.write(A("Network",n)+`
|
|
605
|
+
`),process.stderr.write(A("From",g("genesis (seed 0x01)"))+`
|
|
606
|
+
`),process.stderr.write(A("To",se(i,!0))+`
|
|
607
|
+
`),process.stderr.write(A("Amount",P(r+" NIGHT"))+`
|
|
608
608
|
`),process.stderr.write(`
|
|
609
609
|
`);let c=H("Starting genesis wallet...");try{let d=await Rr({seedBuffer:a,networkConfig:s,recipientAddress:i,amountNight:r,signal:o,onSync(u,l){if(l>0){let p=Math.round(u/l*100);c.update(`Syncing genesis wallet... ${p}%`)}},onDust(u){c.update(`Dust: ${u}`)},onProving(){c.update("Generating ZK proof (this may take a few minutes)...")},onSubmitting(){c.update("Submitting and waiting for finalization (typically 12 to 30s)...")},onSubmittingTick(u){let l=Math.floor(u/1000),p=Math.floor(l/60).toString().padStart(2,"0"),f=(l%60).toString().padStart(2,"0");c.update(`Submitting and waiting for finalization... ${p}:${f} elapsed (typically 12 to 30s)`)},onSyncWarning(u,l){c.update(`Syncing genesis wallet... (${l}, retrying)`)}});if(c.stop("Transaction submitted"),D(e,"json")){I({txHash:d.txHash,amount:r,recipient:i,network:n});return}process.stdout.write(d.txHash+`
|
|
610
610
|
`),process.stderr.write(`
|
|
611
|
-
`+
|
|
611
|
+
`+Tt(`Airdropped ${r} NIGHT to your wallet`,d.txHash)+`
|
|
612
612
|
`),process.stderr.write(`
|
|
613
613
|
`+Z()+`
|
|
614
614
|
`),process.stderr.write(g(" Verify: midnight balance")+`
|
|
@@ -619,84 +619,84 @@ Got: ${e}`);if(n){let i=He(r.networkId),a;try{a=Ru.parse(e).decode(Oy,i)}catch(c
|
|
|
619
619
|
`)}catch(d){if(c.fail("Failed"),d instanceof Error&&d.message.toLowerCase().includes("dust"))throw Error(`${d.message}
|
|
620
620
|
|
|
621
621
|
On a fresh localnet, the minimum airdrop is ~1 NIGHT.
|
|
622
|
-
Try: midnight airdrop 1`);throw d}}async function
|
|
623
|
-
`+
|
|
622
|
+
Try: midnight airdrop 1`);throw d}}async function tS(e,t,r,n,s,o){let i=Pt(r);if(ze(e))Qe();let a=Buffer.from(ut,"hex"),c=Iu.unshieldedToken().raw,{raw:d,bech32m:u}=t;if(t.kind==="wallet")yr(t.walletPath,n,u);process.stderr.write(`
|
|
623
|
+
`+B("Shielded Airdrop")+`
|
|
624
624
|
|
|
625
|
-
`),process.stderr.write(
|
|
626
|
-
`),process.stderr.write(
|
|
627
|
-
`),process.stderr.write(
|
|
628
|
-
`),process.stderr.write(
|
|
625
|
+
`),process.stderr.write(A("Network",n)+`
|
|
626
|
+
`),process.stderr.write(A("From",g("genesis shielded (seed 0x01)"))+`
|
|
627
|
+
`),process.stderr.write(A("To",se(u,!0))+`
|
|
628
|
+
`),process.stderr.write(A("Amount",P(r+" NIGHT (shielded)"))+`
|
|
629
629
|
`),process.stderr.write(`
|
|
630
|
-
`);let l=Fe(),p=Ue(),f=H("Syncing genesis wallet...");try{let h=await $e().withFacade(a,s,async({bundle:m,state:y})=>{let w=y.shielded.balances[c]??0n;if(w<i){let L=Number(w)/1e6;throw Error(`Genesis wallet has insufficient shielded balance: ${L.toFixed(6)} NIGHT available, ${r} NIGHT requested`)}if(f.update("Checking dust..."),await at(m,(L)=>f.update(L)),o?.aborted)throw Error("Operation cancelled");f.update("Building shielded transaction...");let S=await m.facade.transferTransaction([{type:"shielded",outputs:[{type:c,amount:i,receiverAddress:d}]}],{ttl:new Date(Date.now()+3600000)});f.update("Signing...");let k=await m.facade.signRecipe(S,m.keystore.signDataAsync);f.update("Generating ZK proof (this may take a few minutes)...");let
|
|
630
|
+
`);let l=Fe(),p=Ue(),f=H("Syncing genesis wallet...");try{let h=await $e().withFacade(a,s,async({bundle:m,state:y})=>{let w=y.shielded.balances[c]??0n;if(w<i){let L=Number(w)/1e6;throw Error(`Genesis wallet has insufficient shielded balance: ${L.toFixed(6)} NIGHT available, ${r} NIGHT requested`)}if(f.update("Checking dust..."),await at(m,(L)=>f.update(L)),o?.aborted)throw Error("Operation cancelled");f.update("Building shielded transaction...");let S=await m.facade.transferTransaction([{type:"shielded",outputs:[{type:c,amount:i,receiverAddress:d}]}],{ttl:new Date(Date.now()+3600000)});f.update("Signing...");let k=await m.facade.signRecipe(S,m.keystore.signDataAsync);f.update("Generating ZK proof (this may take a few minutes)...");let T=await m.facade.finalizeRecipe(k),N=await Xs(f,"Submitting and waiting for finalization (typically 12 to 30s)...",m.facade.submitTransaction(T));return String(N)},{syncMode:"full",requireStrictSync:!0,signal:o,onStatus:(m)=>f.update(m),onSyncProgress:(m,y)=>{if(y>0){let w=Math.min(Math.round(m/y*100),100);f.update(w>=100?"Syncing genesis wallet...":`Syncing genesis wallet... ${w}%`)}},onSyncDetail:(m)=>f.update(`Syncing genesis wallet... (waiting on: ${m})`)});if(f.stop("Transaction submitted"),D(e,"json")){I({txHash:h,amount:r,shieldedAddress:u,network:n,type:"shielded"});return}process.stdout.write(h+`
|
|
631
631
|
`),process.stderr.write(`
|
|
632
|
-
`+
|
|
632
|
+
`+Tt(`Airdropped ${r} shielded NIGHT to your wallet`,h)+`
|
|
633
633
|
`),process.stderr.write(`
|
|
634
634
|
`+Z()+`
|
|
635
635
|
`),process.stderr.write(g(" Verify: midnight balance --shielded")+`
|
|
636
636
|
|
|
637
|
-
`)}catch(h){throw f.fail("Failed"),h}finally{p(),l()}}var
|
|
637
|
+
`)}catch(h){throw f.fail("Failed"),h}finally{p(),l()}}var Ou=E(()=>{re();Nt();Pe();Ee();Ce();gt();Xe();bt();tt();_t();de();ct()});import{MidnightBech32m as Mu,ShieldedAddress as rS,UnshieldedAddress as nS}from"@midnightntwrk/wallet-sdk/address-format";function Zs(e){let t=e.subcommand,r=e.positionals[0];if(!t)throw new R(`Missing recipient address.
|
|
638
638
|
Usage: midnight transfer <to> <amount>
|
|
639
639
|
Example: midnight transfer mn_addr_undeployed1... 100
|
|
640
640
|
Example: midnight transfer alice 100`);if(!r)throw new R(`Missing amount.
|
|
641
641
|
Usage: midnight transfer <to> <amount>
|
|
642
|
-
Example: midnight transfer mn_addr_undeployed1... 100`);let n=D(e,"shielded"),s=
|
|
643
|
-
Expected a shielded address (mn_shield-addr_...) for network "${t}"`)}}function
|
|
644
|
-
Expected a bech32m address (mn_addr_...) for network "${t}"`)}}function
|
|
645
|
-
Regenerate the wallet or run "midnight balance --shielded" first.`);return i}let o=n.addresses[s];if(!o)throw Error(`Wallet "${e}" has no address for network "${s}". Regenerate the wallet to derive one.`);return o}var
|
|
646
|
-
`+
|
|
647
|
-
|
|
648
|
-
`),process.stderr.write(
|
|
649
|
-
`),process.stderr.write(
|
|
650
|
-
`),process.stderr.write(
|
|
651
|
-
`),process.stderr.write(
|
|
642
|
+
Example: midnight transfer mn_addr_undeployed1... 100`);let n=D(e,"shielded"),s=oS(t,e,n),o=Nr(r),i=oe(C(e,"wallet")),a=ce(i),c=xe({args:e});if(n){if(!qs(c,D(e,"force-shielded")))throw Error(zs(c));na(s,c)}else sS(s,c);return{walletPath:i,walletConfig:a,networkName:c,recipientAddress:s,amountNight:o,shielded:n}}function na(e,t){try{return Mu.parse(e).decode(rS,wr(t))}catch(r){throw new R(`Invalid shielded address: ${r.message}
|
|
643
|
+
Expected a shielded address (mn_shield-addr_...) for network "${t}"`)}}function sS(e,t){try{return Mu.parse(e).decode(nS,wr(t))}catch(r){throw new R(`Invalid recipient address: ${r.message}
|
|
644
|
+
Expected a bech32m address (mn_addr_...) for network "${t}"`)}}function oS(e,t,r){if(e.startsWith("mn_addr_")||e.startsWith("mn_shield-addr_"))return e;let n=ce(oe(e)),s=xe({args:t});if(r){let i=n.shieldedAddresses?.[s];if(!i)throw Error(`Wallet "${e}" has no shielded address for network "${s}".
|
|
645
|
+
Regenerate the wallet or run "midnight balance --shielded" first.`);return i}let o=n.addresses[s];if(!o)throw Error(`Wallet "${e}" has no address for network "${s}". Regenerate the wallet to derive one.`);return o}var sa=E(()=>{re();ue();Pe();Ee();gt();Zi();bt()});var Lu={};ve(Lu,{default:()=>Uu});import*as Fu from"@midnightntwrk/ledger-v9";import{MidnightBech32m as iS}from"@midnightntwrk/wallet-sdk/address-format";async function Uu(e,t){ur(e);let r=Zs(e);return r.shielded?cS(e,r,t):aS(e,r,t)}async function aS(e,{walletConfig:t,recipientAddress:r,amountNight:n},s){let o=Buffer.from(t.seed,"hex"),{name:i,config:a}=me({args:e}),c=t.addresses[i];if(Le(a,{proofServer:C(e,"proof-server"),node:C(e,"node"),indexerWS:C(e,"indexer-ws")},i),process.stderr.write(`
|
|
646
|
+
`+B("Transfer")+`
|
|
647
|
+
|
|
648
|
+
`),process.stderr.write(A("Network",i)+`
|
|
649
|
+
`),process.stderr.write(A("From",se(c,!0))+`
|
|
650
|
+
`),process.stderr.write(A("To",se(r,!0))+`
|
|
651
|
+
`),process.stderr.write(A("Amount",P(n+" NIGHT"))+`
|
|
652
652
|
`),process.stderr.write(`
|
|
653
653
|
`),ze(e))Qe();let d=H("Starting wallet...");try{let u=await Rr({seedBuffer:o,networkConfig:a,recipientAddress:r,amountNight:n,signal:s,onSync(l,p){if(p>0){let f=Math.min(Math.round(l/p*100),100);d.update(f>=100?"Syncing wallet...":`Syncing wallet... ${f}%`)}},onSyncDetail(l){d.update(`Syncing wallet... (waiting on: ${l})`)},onDust(l){d.update(`Dust: ${l}`)},onProving(){d.update("Generating ZK proof (this may take a few minutes)...")},onSubmitting(){d.update("Submitting and waiting for finalization (typically 12 to 30s)...")},onSubmittingTick(l){let p=Math.floor(l/1000),f=Math.floor(p/60).toString().padStart(2,"0"),h=(p%60).toString().padStart(2,"0");d.update(`Submitting and waiting for finalization... ${f}:${h} elapsed (typically 12 to 30s)`)},onSyncWarning(l,p){d.update(`Syncing wallet... (${p}, retrying)`)}});if(d.stop("Transaction submitted"),D(e,"json")){I({txHash:u.txHash,amount:n,recipient:r,network:i});return}process.stdout.write(u.txHash+`
|
|
654
654
|
`),process.stderr.write(`
|
|
655
|
-
`+
|
|
655
|
+
`+Tt(`Transferred ${n} NIGHT`,u.txHash)+`
|
|
656
656
|
`),process.stderr.write(`
|
|
657
657
|
`+Z()+`
|
|
658
658
|
`),process.stderr.write(g(" Verify: midnight balance")+`
|
|
659
659
|
|
|
660
|
-
`)}catch(u){throw d.fail("Failed"),u}}async function
|
|
661
|
-
`+
|
|
660
|
+
`)}catch(u){throw d.fail("Failed"),u}}async function cS(e,{walletPath:t,walletConfig:r,recipientAddress:n,amountNight:s},o){let i=Pt(s),a=Buffer.from(r.seed,"hex"),{name:c,config:d}=me({args:e}),u=He(d.networkId),l=Fu.unshieldedToken().raw;Le(d,{proofServer:C(e,"proof-server"),node:C(e,"node"),indexerWS:C(e,"indexer-ws")},c);let p=na(n,c);if(process.stderr.write(`
|
|
661
|
+
`+B("Shielded Transfer")+`
|
|
662
662
|
|
|
663
|
-
`),process.stderr.write(
|
|
664
|
-
`),process.stderr.write(
|
|
665
|
-
`),process.stderr.write(
|
|
663
|
+
`),process.stderr.write(A("Network",c)+`
|
|
664
|
+
`),process.stderr.write(A("To",se(n,!0))+`
|
|
665
|
+
`),process.stderr.write(A("Amount",P(s+" NIGHT (shielded)"))+`
|
|
666
666
|
`),process.stderr.write(`
|
|
667
|
-
`),ze(e))Qe();let f=Fe(),h=Ue(),m=H("Syncing wallet...");try{let y=await $e().withFacade(a,d,async({bundle:w,state:S})=>{let k=
|
|
668
|
-
Fund shielded balance: midnight airdrop ${s} --shielded`)}if(m.update("Checking dust..."),await at(w,(
|
|
667
|
+
`),ze(e))Qe();let f=Fe(),h=Ue(),m=H("Syncing wallet...");try{let y=await $e().withFacade(a,d,async({bundle:w,state:S})=>{let k=iS.encode(u,S.shielded.address).asString();yr(t,c,k);let T=S.shielded.balances[l]??0n;if(T<i){let V=Number(T)/1e6;throw Error(`Insufficient shielded balance: ${V.toFixed(6)} NIGHT available, ${s} NIGHT requested.
|
|
668
|
+
Fund shielded balance: midnight airdrop ${s} --shielded`)}if(m.update("Checking dust..."),await at(w,(V)=>m.update(V)),o?.aborted)throw Error("Operation cancelled");m.update("Building shielded transaction...");let N=await Lc(()=>w.facade.transferTransaction([{type:"shielded",outputs:[{type:l,amount:i,receiverAddress:p}]}],{ttl:new Date(Date.now()+3600000)}),S.dust,{maxWaitMs:mn,onStatus:(V)=>m.update(V),signal:o});m.update("Signing...");let L=await w.facade.signRecipe(N,w.keystore.signDataAsync);m.update("Generating ZK proof (this may take a few minutes)...");let J=await w.facade.finalizeRecipe(L),Y=await Xs(m,"Submitting and waiting for finalization (typically 12 to 30s)...",w.facade.submitTransaction(J));return String(Y)},{syncMode:"full",requireStrictSync:!0,signal:o,onStatus:(w)=>m.update(w),onSyncProgress:(w,S)=>{if(S>0){let k=Math.min(Math.round(w/S*100),100);m.update(k>=100?"Syncing wallet...":`Syncing wallet... ${k}%`)}},onSyncDetail:(w)=>m.update(`Syncing wallet... (waiting on: ${w})`)});if(m.stop("Transaction submitted"),D(e,"json")){I({txHash:y,amount:s,recipient:n,network:c,type:"shielded"});return}process.stdout.write(y+`
|
|
669
669
|
`),process.stderr.write(`
|
|
670
|
-
`+
|
|
670
|
+
`+Tt(`Transferred ${s} shielded NIGHT`,y)+`
|
|
671
671
|
`),process.stderr.write(`
|
|
672
672
|
`+Z()+`
|
|
673
673
|
`),process.stderr.write(g(" Verify: midnight balance --shielded")+`
|
|
674
674
|
|
|
675
|
-
`)}catch(y){throw m.fail("Failed"),y}finally{h(),f()}}var
|
|
675
|
+
`)}catch(y){throw m.fail("Failed"),y}finally{h(),f()}}var Bu=E(()=>{re();Nt();Pe();Ee();Ce();gt();sa();bt();tt();_t();de();ct();vr()});async function dS(e,t){let r=await et(e,t,null);try{return await r.facade.dust.serializeState()}finally{await We(r)}}async function Wu(e,t,r,n={}){let s=Ze(e),i=await(n.repository??$e()).dust(e,r,{signal:n.signal,onProgress:n.onProgress}),a=await(n.buildBaseDust??dS)(e,r),c=i.lastAppliedEventId>=0?wn(a,{state:i.state,lastAppliedEventId:i.lastAppliedEventId}):a;return{network:t,dustPublicKey:s,offset:i.lastAppliedEventId,balance:i.balance,eventCount:i.eventsApplied,fromCache:i.fromCache,partial:i.partial,snapshot:c}}var ju=E(()=>{er();tt();_t()});var Gu={};ve(Gu,{default:()=>Hu});async function Hu(e,t){let r=e.subcommand;if(!r||r!=="register"&&r!=="status"&&r!=="export")throw new R(`Missing or invalid subcommand.
|
|
676
676
|
Usage:
|
|
677
677
|
midnight dust register Register NIGHT UTXOs for dust generation
|
|
678
678
|
midnight dust status Check dust registration status
|
|
679
|
-
midnight dust export Export a restorable dust snapshot (dustSerializedState)`);let{name:n,config:s}=me({args:e});if(Le(s,{proofServer:
|
|
679
|
+
midnight dust export Export a restorable dust snapshot (dustSerializedState)`);let{name:n,config:s}=me({args:e});if(Le(s,{proofServer:C(e,"proof-server"),node:C(e,"node"),indexerWS:C(e,"indexer-ws")},n),ze(e))Qe();let o=D(e,"json"),i=Ct(e);if(r==="export"){let f=Ue();try{await lS(Js(e),n,s,o,i,t)}finally{f()}return}let a=ce(oe(C(e,"wallet"))),c=Buffer.from(a.seed,"hex"),d=a.addresses[n];if(r==="status"){let f=await uS(d,n,s.indexerWS,t);if(!f.isRegistered){pS(n,f,o,i);return}let h=!D(e,"no-cache");await mS(c,s,f,o,i,h,t);return}ur(e);let u={},l=Fe((f,h)=>u.current?.(f,h)),p=Ue();try{await fS(c,s,o,t,u)}finally{p(),l()}}async function lS(e,t,r,n,s,o){let i=H(`Reading dust events from ${t}...`);try{let a=await Wu(e,t,r,{signal:o,onProgress:(c,d)=>i.update(d>0?`Reading dust events... ${c}/${d+1}`:`Reading dust events... ${c}`)});if(i.stop(a.partial?"Dust snapshot ready (incomplete)":a.fromCache&&a.eventCount===0?"Cache up to date":"Dust snapshot ready"),n){I({subcommand:"export",network:a.network,dustPublicKey:a.dustPublicKey,offset:a.offset,dustBalance:pe(a.balance),eventCount:a.eventCount,fromCache:a.fromCache,partial:a.partial,snapshot:a.snapshot});return}if(process.stdout.write(a.snapshot+`
|
|
680
680
|
`),s)return;if(process.stderr.write(`
|
|
681
|
-
`+
|
|
682
|
-
`),process.stderr.write(
|
|
683
|
-
`),process.stderr.write(
|
|
681
|
+
`+A("Network",a.network)+`
|
|
682
|
+
`),process.stderr.write(A("Dust balance",Yt(a.balance))+`
|
|
683
|
+
`),process.stderr.write(A("Snapshot offset",String(a.offset))+`
|
|
684
684
|
`),a.partial)process.stderr.write(`
|
|
685
685
|
`+ee(P("⚠ Snapshot is INCOMPLETE — the sync did not reach the chain tip."))+`
|
|
686
686
|
`+g(" Restoring it still beats a cold start, but the wallet has events left to catch up on.")+`
|
|
687
687
|
`+g(" Re-run `mn dust export` to resume from this checkpoint and finish.")+`
|
|
688
688
|
`);process.stderr.write(`
|
|
689
689
|
`+g("Restore with the wallet SDK dustSerializedState to skip the cold dust sync.")+`
|
|
690
|
-
`)}catch(a){throw i.fail("Failed"),a}}async function
|
|
691
|
-
`+
|
|
690
|
+
`)}catch(a){throw i.fail("Failed"),a}}async function uS(e,t,r,n){process.stderr.write(`
|
|
691
|
+
`+B("Dust Status")+`
|
|
692
692
|
|
|
693
|
-
`),process.stderr.write(
|
|
693
|
+
`),process.stderr.write(A("Network",t)+`
|
|
694
694
|
|
|
695
|
-
`);let s=H(`Checking registration on ${t}...`);try{let o=await
|
|
695
|
+
`);let s=H(`Checking registration on ${t}...`);try{let o=await Ar(e,r,(c,d)=>{if(d>0){let u=Math.min(Math.round(c/d*100),100);s.update(u>=100?"Checking registration...":`Checking registration... ${u}%`)}});if(n?.aborted)throw Error("Operation cancelled");let{registeredUtxos:i,unregisteredUtxos:a}=o;return s.stop("Registration checked"),{isRegistered:i>0,registeredUtxos:i,unregisteredUtxos:a}}catch(o){throw s.fail("Failed"),o}}function pS(e,t,r,n){let{registeredUtxos:s,unregisteredUtxos:o}=t,i=s+o;if(r){if(n){I({network:e,registered:!1,registeredUtxos:s,unregisteredUtxos:o});return}I({subcommand:"status",registered:!1,registeredUtxos:s,unregisteredUtxos:o,network:e});return}if(process.stdout.write(`registered=no
|
|
696
696
|
`),process.stdout.write(`registered_utxos=${s}
|
|
697
697
|
`),process.stdout.write(`unregistered_utxos=${o}
|
|
698
|
-
`),process.stderr.write(
|
|
699
|
-
`),process.stderr.write(
|
|
698
|
+
`),process.stderr.write(A("Registered",P("no"))+`
|
|
699
|
+
`),process.stderr.write(A("UTXOs",`${s} registered, ${o} unregistered`)+`
|
|
700
700
|
`),i===0)process.stderr.write(`
|
|
701
701
|
`+g("No NIGHT UTXOs at this address. Fund the wallet first.")+`
|
|
702
702
|
`);else process.stderr.write(`
|
|
@@ -704,46 +704,46 @@ Usage:
|
|
|
704
704
|
`);process.stderr.write(`
|
|
705
705
|
`+Z()+`
|
|
706
706
|
|
|
707
|
-
`)}async function
|
|
708
|
-
`+
|
|
707
|
+
`)}async function fS(e,t,r,n,s){let o=t.networkId.toLowerCase();process.stderr.write(`
|
|
708
|
+
`+B("Dust Register")+`
|
|
709
709
|
|
|
710
|
-
`),process.stderr.write(
|
|
710
|
+
`),process.stderr.write(A("Network",o)+`
|
|
711
711
|
|
|
712
|
-
`);let i=H("Syncing wallet...");if(s)s.current=(a,c)=>i.update(`Syncing wallet... (${c}, retrying)`);try{let{result:a,dustBal:c}=await $e().withFacade(e,t,async({bundle:d,state:u})=>{if(n?.aborted)throw Error("Operation cancelled");i.update("Checking dust status...");let l=await at(d,(f)=>i.update(f),u);if(n?.aborted)throw Error("Operation cancelled");let p=await
|
|
712
|
+
`);let i=H("Syncing wallet...");if(s)s.current=(a,c)=>i.update(`Syncing wallet... (${c}, retrying)`);try{let{result:a,dustBal:c}=await $e().withFacade(e,t,async({bundle:d,state:u})=>{if(n?.aborted)throw Error("Operation cancelled");i.update("Checking dust status...");let l=await at(d,(f)=>i.update(f),u);if(n?.aborted)throw Error("Operation cancelled");let p=await dd(d);return{result:l,dustBal:p.dust.balance(new Date)}},{syncMode:"lite",requireStrictSync:!0,signal:n,onStatus:(d)=>i.update(d),onSyncProgress:(d,u)=>{if(u>0){let l=Math.min(Math.round(d/u*100),100);i.update(l>=100?"Syncing wallet...":`Syncing wallet... ${l}%`)}},onSyncDetail:(d)=>i.update(`Syncing wallet... (waiting on: ${d})`)});if(i.stop(a.alreadyAvailable?"Dust already available":"Dust registration complete"),r){let d={subcommand:"register",dustBalance:pe(c)};if(a.txHash)d.txHash=a.txHash;I(d);return}process.stdout.write(c.toString()+`
|
|
713
713
|
`),process.stderr.write(`
|
|
714
|
-
`+
|
|
714
|
+
`+Tt(a.alreadyAvailable?`Dust tokens already available: ${Yt(c)}`:`Dust tokens available: ${Yt(c)}`)+`
|
|
715
715
|
|
|
716
|
-
`)}catch(a){throw i.fail("Failed"),a}}async function
|
|
716
|
+
`)}catch(a){throw i.fail("Failed"),a}}async function mS(e,t,r,n,s,o,i){let a=t.networkId.toLowerCase(),c=H(`Reading dust events from ${a}...`);try{let d=await $e().dust(e,t,{forceFresh:!o,signal:i,onStatus:(p)=>c.update(p)});c.stop(d.fromCache&&d.eventsApplied===0?"Cache up to date":"Dust events applied");let{registeredUtxos:u,unregisteredUtxos:l}=r;if(n){if(s){I({network:a,registered:!0,registeredUtxos:u,unregisteredUtxos:l,dustBalance:pe(d.balance),dustAvailable:d.availableCoins>0});return}I({subcommand:"status",registered:!0,registeredUtxos:u,unregisteredUtxos:l,dustBalance:pe(d.balance),dustAvailable:d.availableCoins>0,eventsApplied:d.eventsApplied,ownedUtxos:d.ownedUtxoCount,cached:d.fromCache,network:a});return}if(process.stdout.write(`registered=yes
|
|
717
717
|
`),process.stdout.write(`dust=${d.balance}
|
|
718
718
|
`),process.stdout.write(`registered_utxos=${u}
|
|
719
719
|
`),process.stdout.write(`unregistered_utxos=${l}
|
|
720
|
-
`),process.stderr.write(
|
|
721
|
-
`),process.stderr.write(
|
|
722
|
-
`),process.stderr.write(
|
|
723
|
-
`),process.stderr.write(
|
|
724
|
-
`),process.stderr.write(
|
|
720
|
+
`),process.stderr.write(A("Registered",P("yes"))+`
|
|
721
|
+
`),process.stderr.write(A("UTXOs",`${u} registered, ${l} unregistered`)+`
|
|
722
|
+
`),process.stderr.write(A("Dust Balance",P(Yt(d.balance)))+`
|
|
723
|
+
`),process.stderr.write(A("Dust Available",d.availableCoins>0?"yes":"no")+`
|
|
724
|
+
`),process.stderr.write(A("Events applied",d.eventsApplied.toString()+(d.fromCache?" (delta)":""))+`
|
|
725
725
|
`),l>0)process.stderr.write(`
|
|
726
726
|
`+g(`${l} UTXO(s) not yet registered. Run: midnight dust register`)+`
|
|
727
727
|
`);process.stderr.write(`
|
|
728
728
|
`+Z()+`
|
|
729
729
|
|
|
730
|
-
`)}catch(d){throw c.fail("Failed"),d}}var
|
|
730
|
+
`)}catch(d){throw c.fail("Failed"),d}}var Ku=E(()=>{re();ue();Nt();Pe();Ur();Ee();Ce();tt();bt();kn();ju();_t();de();ct()});var Vu={};ve(Vu,{default:()=>Ju});async function Ju(e){if(e.subcommand!=="clear")throw new R("Usage: midnight cache clear [--network <name>] [--wallet <name|file>]");let r=C(e,"wallet"),n=C(e,"network"),s=D(e,"json");if(r){let o=oe(r),i=ce(o),a=xe({args:e}),c=i.addresses[a];rt(c,a);let d=Ze(Buffer.from(i.seed,"hex"));ht(a,d),Ds(a,d);let u=au(Buffer.from(i.seed,"hex"));if($n(a,u),s){I({action:"clear",scope:"wallet",wallet:r,network:a});return}process.stderr.write(z("✓")+` Cache cleared for wallet "${r}" on ${a}
|
|
731
731
|
`)}else if(n){if(rt(void 0,n),ht(n),Ds(n),$n(n),s){I({action:"clear",scope:"network",network:n});return}process.stderr.write(z("✓")+` Cache cleared for network "${n}"
|
|
732
732
|
`)}else{if(rt(),ht(),Ds(),$n(),s){I({action:"clear",scope:"all"});return}process.stderr.write(z("✓")+` Cache cleared
|
|
733
|
-
`)}}var
|
|
733
|
+
`)}}var qu=E(()=>{re();ue();rr();er();ra();Si();Pe();Ee()});var Yu={};ve(Yu,{default:()=>zu});async function zu(e){let t=e.subcommand;if(!t||!["get","set","unset"].includes(t))throw new R(`Usage: midnight config <get|set|unset> <key> [value]
|
|
734
734
|
Valid keys: ${qo().join(", ")}`);let r=e.positionals[0];if(!r)throw new R(`Missing config key.
|
|
735
|
-
Valid keys: ${qo().join(", ")}`);let n=
|
|
736
|
-
Valid networks: preprod, preview, undeployed`);let s=n;if(t==="get"){let o=
|
|
737
|
-
`)}else if(t==="unset"){
|
|
735
|
+
Valid keys: ${qo().join(", ")}`);let n=C(e,"network");if(n!==void 0&&!De(n))throw new R(`Invalid network: "${n}"
|
|
736
|
+
Valid networks: preprod, preview, undeployed`);let s=n;if(t==="get"){let o=Jo(r,void 0,s);if(D(e,"json")){I({action:"get",key:r,value:o});return}process.stdout.write(o+`
|
|
737
|
+
`)}else if(t==="unset"){kc(r,void 0,s);let o=r==="network"?"(default)":"(removed)";if(D(e,"json")){I({action:"unset",key:r,value:o});return}process.stderr.write(z("✓")+` ${r} ${o}
|
|
738
738
|
`)}else{let o=e.positionals[1];if(o===void 0)throw new R(`Missing value for config set.
|
|
739
|
-
Usage: midnight config set ${r} <value>`);
|
|
740
|
-
`)}}var
|
|
739
|
+
Usage: midnight config set ${r} <value>`);vc(r,o,void 0,s);let i=r==="blockfrost-project-id"?Jo(r,void 0,s):o;if(D(e,"json")){I({action:"set",key:r,value:i});return}process.stderr.write(z("✓")+` ${r} = ${i}
|
|
740
|
+
`)}}var Xu=E(()=>{re();Ce();ue();Gt()});import{execSync as Mn}from"child_process";import{existsSync as Zu,mkdirSync as gS,readFileSync as hS,writeFileSync as Qu}from"fs";import{homedir as wS}from"os";import{join as ia}from"path";function rp(){let e={...eo,stdio:["ignore","pipe","pipe"]};try{return Mn("docker compose version",{...e,timeout:1e4}).trim()}catch{try{throw Mn("docker --version",{...e,timeout:5000}),Error(`Docker Compose v2 is required.
|
|
741
741
|
Install it from https://docs.docker.com/compose/install/`)}catch(t){if(t instanceof Error&&t.message.includes("Docker Compose v2"))throw t;throw Error(`Docker is required but was not found.
|
|
742
|
-
Install Docker from https://docs.docker.com/get-docker/`)}}}function
|
|
743
|
-
`)){if(!r.trim())continue;try{let n=JSON.parse(r),s=n.Service??"unknown";t.push({name:s,state:n.State??"unknown",health:n.Health??"",port:
|
|
744
|
-
`).find((a)=>a.startsWith(`${s}|`));if(i)e.push({name:s,project:i.slice(s.length+1).trim()})}let{remove:t,keep:r}=
|
|
742
|
+
Install Docker from https://docs.docker.com/get-docker/`)}}}function ca(){if(!kS)throw new np}function sp(){if(ca(),Zu(oa)&&Zu(Qs)&&hS(oa,"utf-8").trim()===ep)return!1;return gS(aa,{recursive:!0,mode:be}),Qu(Qs,vS,"utf-8"),Qu(oa,ep,"utf-8"),!0}function Wr(e){return Mn(`docker compose -f "${Qs}" ${e}`,eo)}function xS(e){let t=[];for(let r of e.split(`
|
|
743
|
+
`)){if(!r.trim())continue;try{let n=JSON.parse(r),s=n.Service??"unknown";t.push({name:s,state:n.State??"unknown",health:n.Health??"",port:CS[s]??"",image:n.Image??""})}catch{}}return t}function to(){try{return xS(Wr("ps -a --format json"))}catch{return[]}}function ES(e){Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,e)}function op(e=120000,t=3000){let r=Date.now()+e;while(Date.now()<r){let n=to();if(n.length===3&&n.every((o)=>o.state==="running")){if(n.every((i)=>i.health==="healthy"||i.health===""))return!0}ES(t)}return!1}function da(){return Qs}function TS(e){return{remove:e.filter((t)=>t.project===tp).map((t)=>t.name),keep:e.filter((t)=>t.project!==tp)}}function ip(){let e=[];for(let s of AS){let o;try{o=Mn(`docker ps -a --filter "name=^/${s}$" --format '{{.Names}}|{{.Label "com.docker.compose.project"}}'`,{...eo,timeout:1e4}).toString()}catch{e.push({name:s,project:"(unknown: docker ps failed)"});continue}let i=o.split(`
|
|
744
|
+
`).find((a)=>a.startsWith(`${s}|`));if(i)e.push({name:s,project:i.slice(s.length+1).trim()})}let{remove:t,keep:r}=TS(e),n=[];for(let s of t)try{Mn(`docker rm -f "${s}"`,{...eo,timeout:1e4}),n.push(s)}catch{}return{removed:n,kept:r}}var ep="3.0.6",yS="midnightntwrk/midnight-node:1.0.0",SS="midnightntwrk/indexer-standalone:4.3.3",bS="midnightntwrk/proof-server:8.1.0",aa,Qs,oa,vS,eo,kS=!1,np,CS,AS,tp;var ap=E(()=>{aa=ia(wS(),te,Po),Qs=ia(aa,"compose.yml"),oa=ia(aa,".version"),vS=`services:
|
|
745
745
|
proof-server:
|
|
746
|
-
image: '${
|
|
746
|
+
image: '${bS}'
|
|
747
747
|
container_name: "proof-server"
|
|
748
748
|
# Self-heal across Docker Desktop restarts and transient stops. Without this,
|
|
749
749
|
# a stopped node/proof-server never comes back while the indexer (below) does,
|
|
@@ -754,7 +754,7 @@ Install Docker from https://docs.docker.com/get-docker/`)}}}function ia(){if(!aS
|
|
|
754
754
|
- "6300:6300"
|
|
755
755
|
|
|
756
756
|
indexer:
|
|
757
|
-
image: '${
|
|
757
|
+
image: '${SS}'
|
|
758
758
|
container_name: "indexer"
|
|
759
759
|
# unless-stopped covers two cases: (1) indexer >=4.3.x runs an SPO sub-indexer
|
|
760
760
|
# that queries block #1 at startup and exits the whole process if it isn't there
|
|
@@ -790,7 +790,7 @@ Install Docker from https://docs.docker.com/get-docker/`)}}}function ia(){if(!aS
|
|
|
790
790
|
condition: service_started
|
|
791
791
|
|
|
792
792
|
node:
|
|
793
|
-
image: '${
|
|
793
|
+
image: '${yS}'
|
|
794
794
|
container_name: "node"
|
|
795
795
|
# Self-heal across Docker Desktop restarts / transient stops (see proof-server).
|
|
796
796
|
restart: unless-stopped
|
|
@@ -804,42 +804,42 @@ Install Docker from https://docs.docker.com/get-docker/`)}}}function ia(){if(!aS
|
|
|
804
804
|
start_period: 5s
|
|
805
805
|
environment:
|
|
806
806
|
CFG_PRESET: "dev"
|
|
807
|
-
`,eo={encoding:"utf-8",timeout:30000};
|
|
807
|
+
`,eo={encoding:"utf-8",timeout:30000};np=class np extends Error{code="LOCALNET_UNAVAILABLE";constructor(){super(`mn localnet can't start a ledger-9 network yet: no published indexer image runs ledger 9.
|
|
808
808
|
Run a ledger-9 stack yourself (node 2.1.0-rc.2, proof-server 9.0.0-rc.8, a 4.4 indexer) and point mn at it:
|
|
809
809
|
per command: --node ws://localhost:9944 --indexer-ws ws://localhost:8088/api/v4/graphql/ws --proof-server http://localhost:6300
|
|
810
|
-
or once: midnight config set node <url>; midnight config set indexer-ws <url>; midnight config set proof-server <url>`);this.name="LocalnetUnavailableError"}};
|
|
811
|
-
`)}async function
|
|
812
|
-
`);let r=H("Starting local network...");try{if(
|
|
810
|
+
or once: midnight config set node <url>; midnight config set indexer-ws <url>; midnight config set proof-server <url>`);this.name="LocalnetUnavailableError"}};CS={node:"9944",indexer:"8088","proof-server":"6300"};AS=["node","indexer","proof-server"],tp=Po});async function cp(e,t={}){let r=t.timeoutMs??30000,n=t.pollIntervalMs??1000,s=Date.now()+r;while(Date.now()<s){try{let o=await xr({url:e,timeoutMs:3000},"chain_getHeader"),i=typeof o?.number==="string"?o.number:"0x0",a=Number.parseInt(i,16);if(Number.isFinite(a)&&a>=1)return}catch{}await new Promise((o)=>setTimeout(o,n))}throw Error(`Node did not produce a block within ${r/1000}s`)}var dp=E(()=>{xs()});async function lp(e,t,r={}){let n=r.timeoutMs??30000,s=r.pollIntervalMs??1000,o=Date.now()+n;while(Date.now()<o){try{if((await Ar(t,e)).utxoCount>0)return}catch{}await new Promise((i)=>setTimeout(i,s))}throw Error(`Indexer did not report funds for ${t.slice(0,20)}… within ${n/1000}s`)}var up=E(()=>{kn()});async function pp(e,t={}){let r=t.timeoutMs??30000,n=t.pollIntervalMs??1000,s=t.requestTimeoutMs??2000,o=Date.now()+r,i=e.endsWith("/")?e:e+"/";while(Date.now()<o){try{let a=new AbortController,c=setTimeout(()=>a.abort(),s);try{if((await fetch(i,{method:"GET",signal:a.signal})).ok)return}finally{clearTimeout(c)}}catch{}await new Promise((a)=>setTimeout(a,n))}throw Error(`Proof server at ${i} did not respond within ${r/1000}s`)}var wp={};ve(wp,{default:()=>hp});import{spawn as fp}from"child_process";import{existsSync as NS,rmSync as RS}from"node:fs";import{resolve as DS}from"node:path";function IS(e){return mp.includes(e)}function gp(e){let t=[];for(let r of e){let n=r.state==="running"?z:he,s=r.health?` (${r.health})`:"",o=r.port?`:${r.port}`:"",i=r.image?` ${g(r.image)}`:"";if(t.push(` ${r.name.padEnd(16)}${n(r.state)}${g(s)}${g(o)}`),i)t.push(i)}return t.join(`
|
|
811
|
+
`)}async function _S(e){if(sp())process.stderr.write(g(` Wrote compose.yml to ${da()}`)+`
|
|
812
|
+
`);let r=H("Starting local network...");try{if(Wr("up -d"),r.update("Waiting for services to be healthy..."),!op(120000))r.stop(ee("Services started but not all healthy yet")),process.stderr.write(`
|
|
813
813
|
`+g(" Tip: run ")+P("midnight localnet logs")+g(" to check for errors")+`
|
|
814
|
-
`);else{r.update("Waiting for chain to produce first block...");try{await Promise.resolve().then(() =>
|
|
814
|
+
`);else{r.update("Waiting for chain to produce first block...");try{await Promise.resolve().then(() => dp());await Promise.resolve().then(() => up());await Promise.resolve();await Promise.resolve().then(() => Ce());await Promise.resolve().then(() => Xe());await Promise.resolve();let l=Ho("undeployed");await cp(l.node,{timeoutMs:30000}),r.update("Waiting for indexer to ingest genesis state...");let p=Ie(Buffer.from(ut,"hex"),"undeployed");await lp(l.indexerWS,p,{timeoutMs:30000}),r.update("Waiting for proof server..."),await pp(l.proofServer,{timeoutMs:30000}),r.stop("Local network is running")}catch(o){r.stop(ee("Services running but chain/indexer/proof-server not fully ready yet")),process.stderr.write(`
|
|
815
815
|
`+g(" Tip: give it a few more seconds then retry. Run ")+P("midnight localnet logs")+g(" if this persists.")+`
|
|
816
816
|
`)}}}catch(s){if(r.fail("Failed to start local network"),s instanceof Error){if(s.message.includes("is already in use by container"))throw Error(`Container name conflict — containers with the same names already exist.
|
|
817
817
|
|
|
818
818
|
`+`If an earlier mn localnet created them, "midnight localnet clean" removes them;
|
|
819
819
|
it leaves containers from anything else alone and lists them.`);if(s.message.includes("address already in use"))throw Error(`Port conflict detected — another process is using a required port.
|
|
820
820
|
`+"Check ports 9944, 8088, and 6300, then try again.")}throw s}let n=to();if(e){I({subcommand:"up",services:n.map((s)=>({name:s.name,state:s.state,port:s.port,health:s.health,image:s.image}))});return}if(n.length>0)process.stderr.write(`
|
|
821
|
-
`+
|
|
821
|
+
`+gp(n)+`
|
|
822
822
|
`);for(let s of n)process.stdout.write(`${s.name}=${s.state}:${s.port}
|
|
823
823
|
`);process.stderr.write(`
|
|
824
824
|
`+g(" Next: ")+P("midnight wallet generate dev --network undeployed")+`
|
|
825
|
-
`)}async function
|
|
826
|
-
`)}catch(r){throw t.fail("Failed to tear down local network"),r}}function
|
|
827
|
-
`+
|
|
825
|
+
`)}async function PS(e){let t=H("Stopping local network...");try{if(Wr("stop"),t.stop("Local network stopped (containers preserved)"),e){I({subcommand:"stop",status:"stopped"});return}}catch(r){throw t.fail("Failed to stop local network"),r}}async function $S(e){let t=H("Tearing down local network...");try{Wr("down --volumes");await Promise.resolve().then(() => rr());await Promise.resolve().then(() => er());rt(void 0,"undeployed"),ht("undeployed");let s=OS();if(t.stop("Local network removed (containers, networks, volumes, caches)"),e){I({subcommand:"down",status:"removed",cachesCleared:!0,dappLevelDbWiped:s});return}if(s)process.stderr.write(g(" Also cleared dapp leveldb at ./midnight-level-db (private state from old chain)")+`
|
|
826
|
+
`)}catch(r){throw t.fail("Failed to tear down local network"),r}}function OS(){let e=DS(process.cwd(),"midnight-level-db");if(!NS(e))return!1;try{return RS(e,{recursive:!0,force:!0}),!0}catch{return!1}}async function MS(e){let t=to();if(e){I({subcommand:"status",services:t.map((r)=>({name:r.name,state:r.state,port:r.port,health:r.health,image:r.image}))});return}if(t.length===0){process.stderr.write(`
|
|
827
|
+
`+B("Localnet Status")+`
|
|
828
828
|
|
|
829
829
|
`),process.stderr.write(g(" No services running.")+`
|
|
830
830
|
`),process.stderr.write(g(" ")+P("midnight localnet up")+g(" is refused on this ledger-9 build; see ")+P("midnight help localnet")+g(".")+`
|
|
831
831
|
|
|
832
832
|
`);return}process.stderr.write(`
|
|
833
|
-
`+
|
|
833
|
+
`+B("Localnet Status")+`
|
|
834
834
|
|
|
835
|
-
`),process.stderr.write(
|
|
835
|
+
`),process.stderr.write(gp(t)+`
|
|
836
836
|
`),process.stderr.write(`
|
|
837
837
|
`+Z()+`
|
|
838
838
|
|
|
839
839
|
`);for(let r of t)process.stdout.write(`${r.name}=${r.state}:${r.port}
|
|
840
|
-
`)}async function
|
|
841
|
-
`)}catch(r){throw t.fail("Failed to clean up"),r}}async function
|
|
842
|
-
`).filter(Boolean)});else process.stdout.write(a);d()}),i.on("error",u)})}let s=
|
|
840
|
+
`)}async function FS(e){let t=H("Removing conflicting containers...");try{try{Wr("down")}catch{}let{removed:r,kept:n}=ip();if(r.length>0)t.stop(`Removed ${r.length} container${r.length>1?"s":""}: ${r.join(", ")}`);else t.stop("No conflicting containers found");if(e){I({subcommand:"clean",status:"cleaned",removed:r,kept:n});return}for(let s of n)process.stderr.write(g(` Left "${s.name}" alone: it belongs to ${s.project?`compose project "${s.project}"`:"no compose project"}, not mn's localnet. Remove it yourself if it is in the way.`)+`
|
|
841
|
+
`)}catch(r){throw t.fail("Failed to clean up"),r}}async function US(e){let t=da(),r=C(e,"tail"),n=D(e,"json");if(r!==void 0||n){let o=r??"200",i=fp("docker",["compose","-f",t,"logs","--tail",o,"--no-color"],{stdio:["ignore","pipe","pipe"]}),a="",c="";return i.stdout.on("data",(d)=>{a+=d.toString()}),i.stderr.on("data",(d)=>{c+=d.toString()}),new Promise((d,u)=>{i.on("close",(l)=>{if(l!==0&&l!==null){u(Error(`docker compose logs exited with code ${l}: ${c.trim()}`));return}if(n)I({tail:Number(o),lines:a.split(`
|
|
842
|
+
`).filter(Boolean)});else process.stdout.write(a);d()}),i.on("error",u)})}let s=fp("docker",["compose","-f",t,"logs","-f"],{stdio:"inherit"});return new Promise((o,i)=>{s.on("close",(a)=>{if(a===0||a===130||a===null)o();else i(Error(`docker compose logs exited with code ${a}`))}),s.on("error",i)})}async function hp(e){let t=e.subcommand;if(!t||!IS(t))throw new R(`Usage: midnight localnet <${mp.join("|")}>
|
|
843
843
|
|
|
844
844
|
Subcommands:
|
|
845
845
|
up Start the local network (refused on this ledger-9 build)
|
|
@@ -849,24 +849,24 @@ Subcommands:
|
|
|
849
849
|
logs Stream service logs
|
|
850
850
|
clean Remove conflicting containers
|
|
851
851
|
|
|
852
|
-
Example: midnight localnet status`);if(t==="up")
|
|
853
|
-
`+
|
|
852
|
+
Example: midnight localnet status`);if(t==="up")ca();rp();let r=D(e,"json");switch(process.stderr.write(`
|
|
853
|
+
`+B("Localnet")+`
|
|
854
854
|
|
|
855
|
-
`),t){case"up":return
|
|
855
|
+
`),t){case"up":return _S(r);case"stop":return PS(r);case"down":return $S(r);case"status":return MS(r);case"logs":return US(e);case"clean":return FS(r)}}var mp;var yp=E(()=>{re();ue();ap();de();ct();mp=["up","stop","down","status","logs","clean"]});var kp={};ve(kp,{default:()=>vp});import*as bp from"fs";import*as la from"path";import{homedir as LS}from"os";import{generateMnemonic as BS,mnemonicToSeedSync as Sp,mnemonicToEntropy as WS,validateMnemonic as jS}from"@scure/bip39";import{wordlist as ua}from"@scure/bip39/wordlists/english.js";async function vp(e){let t=e.subcommand;switch(t){case"generate":return HS(e);case"list":case"ls":return GS(e);case"use":return KS(e);case"info":return JS(e);case"remove":case"rm":return VS(e);case"seed":return qS(e);default:throw new R(`Unknown wallet subcommand: "${t??"(none)"}"
|
|
856
856
|
Available: generate, list, use, info, remove, seed
|
|
857
|
-
Run "midnight help wallet" for usage.`)}}async function
|
|
858
|
-
Usage: midnight wallet generate <name> [--network <name>]`);if(!
|
|
859
|
-
Wallet name must be a simple name (no path separators, .json suffix, or special characters).`);let r=
|
|
860
|
-
Use --force to overwrite.`);let a,c;if(n!==void 0)a=_n(n,"--seed");else if(s!==void 0){if(!
|
|
857
|
+
Run "midnight help wallet" for usage.`)}}async function HS(e){let t=e.positionals[0];if(!t)throw Error(`Missing wallet name.
|
|
858
|
+
Usage: midnight wallet generate <name> [--network <name>]`);if(!Wt(t))throw Error(`Invalid wallet name: "${t}"
|
|
859
|
+
Wallet name must be a simple name (no path separators, .json suffix, or special characters).`);let r=xe({args:e}),n=C(e,"seed"),s=C(e,"mnemonic");if(n!==void 0&&s!==void 0)throw Error("Cannot specify both --seed and --mnemonic. Use one or the other.");let o=la.join(LS(),te,Yn),i=la.join(o,`${t}.json`);if(bp.existsSync(i)&&!D(e,"force"))throw Error(`Wallet "${t}" already exists: ${i}
|
|
860
|
+
Use --force to overwrite.`);let a,c;if(n!==void 0)a=_n(n,"--seed");else if(s!==void 0){if(!jS(s,ua))throw Error("Invalid BIP-39 mnemonic. Expected 12 or 24 words from the English wordlist.");c=s,a=Buffer.from(Sp(c))}else c=BS(ua,256),a=Buffer.from(Sp(c));let d=qt(a),u=an(a),l=d[r],p={seed:a.toString("hex"),addresses:d,shieldedAddresses:u,createdAt:new Date().toISOString()};if(c)p.mnemonic=c;let f=ds(p,i);if(Qo(t),D(e,"json")){let m={name:t,addresses:d,shieldedAddresses:u,activeAddress:l,activeNetwork:r,seed:a.toString("hex"),file:f,createdAt:p.createdAt,active:!0};if(c)m.mnemonic=c;I(m);return}process.stdout.write(l+`
|
|
861
861
|
`),process.stderr.write(`
|
|
862
|
-
`+
|
|
863
|
-
|
|
864
|
-
`),process.stderr.write(
|
|
865
|
-
`),process.stderr.write(
|
|
866
|
-
`),process.stderr.write(
|
|
867
|
-
`);let h=u[r];if(h)process.stderr.write(
|
|
868
|
-
`);if(process.stderr.write(
|
|
869
|
-
`),process.stderr.write(
|
|
862
|
+
`+B("Wallet Generated")+`
|
|
863
|
+
|
|
864
|
+
`),process.stderr.write(A("Name",t)+`
|
|
865
|
+
`),process.stderr.write(A("Network",r)+`
|
|
866
|
+
`),process.stderr.write(A("Address",se(l))+`
|
|
867
|
+
`);let h=u[r];if(h)process.stderr.write(A("Shielded",se(h))+`
|
|
868
|
+
`);if(process.stderr.write(A("File",f)+`
|
|
869
|
+
`),process.stderr.write(A("Active","yes")+`
|
|
870
870
|
`),process.stderr.write(`
|
|
871
871
|
`),c)process.stderr.write(ee(P(" MNEMONIC (save securely!):"))+`
|
|
872
872
|
`),process.stderr.write(` ${c}
|
|
@@ -878,12 +878,12 @@ Use --force to overwrite.`);let a,c;if(n!==void 0)a=_n(n,"--seed");else if(s!==v
|
|
|
878
878
|
`),process.stderr.write(g(" Next: midnight wallet list | midnight balance")+`
|
|
879
879
|
|
|
880
880
|
`),process.stderr.write(z("✓")+` Wallet saved
|
|
881
|
-
`)}async function
|
|
881
|
+
`)}async function GS(e){let t=ei(),r=xe({args:e});if(D(e,"json")){if(Ct(e)){I({activeNetwork:r,wallets:t.map((a)=>({name:a.name,active:a.isActive,network:r,address:a.addresses[r]??null,shieldedAddress:a.shieldedAddresses?.[r]??null}))});return}I({activeNetwork:r,wallets:t.map((a)=>({name:a.name,active:a.isActive,addresses:a.addresses,shieldedAddresses:a.shieldedAddresses,createdAt:a.createdAt,file:a.file}))});return}if(t.length===0){process.stderr.write(`
|
|
882
882
|
No wallets found.
|
|
883
883
|
`),process.stderr.write(g(" Create one: midnight wallet generate <name> --network <name>")+`
|
|
884
884
|
|
|
885
885
|
`);return}process.stderr.write(`
|
|
886
|
-
`+
|
|
886
|
+
`+B("Wallets")+`
|
|
887
887
|
|
|
888
888
|
`);let n=Math.max(...t.map((a)=>a.name.length)),s=19,o=19,i=" ".repeat(n-4);process.stderr.write(` ${g("name")}${i} ${g("unshielded".padEnd(s))} ${g("shielded")}
|
|
889
889
|
`);for(let a of t){let c=a.isActive?z("●"):" ",d=a.isActive?P(X(a.name)):X(a.name),u=" ".repeat(n-a.name.length),l=a.addresses[r]??"(unknown)",p=a.shieldedAddresses?.[r],f=p?se(p,!0):g("—".padEnd(o));process.stderr.write(` ${c} ${d}${u} ${se(l,!0)} ${f}
|
|
@@ -891,11 +891,11 @@ Use --force to overwrite.`);let a,c;if(n!==void 0)a=_n(n,"--seed");else if(s!==v
|
|
|
891
891
|
`+Z()+`
|
|
892
892
|
`),process.stderr.write(g(` ● = active wallet · network: ${r} · details: midnight wallet info <name>`)+`
|
|
893
893
|
|
|
894
|
-
`)}async function
|
|
894
|
+
`)}async function KS(e){let t=e.positionals[0];if(!t)throw Error(`Missing wallet name.
|
|
895
895
|
Usage: midnight wallet use <name>`);if(Qo(t),D(e,"json")){I({wallet:t,active:!0});return}process.stderr.write(z("✓")+` Active wallet set to "${t}"
|
|
896
|
-
`)}async function
|
|
896
|
+
`)}async function JS(e){let t=C(e,"wallet")??e.positionals[0]??Et(),r=oe(t),n=ce(r),s=t===Et(),o=xe({args:e}),i=n.addresses[o];if(D(e,"json")){if(Ct(e)){I({name:t,active:s,network:o,address:i,shieldedAddress:n.shieldedAddresses?.[o]??null});return}let c={name:t,addresses:n.addresses,activeAddress:i,activeNetwork:o,createdAt:n.createdAt,file:r,active:s};if(n.shieldedAddresses)c.shieldedAddresses=n.shieldedAddresses;I(c);return}process.stdout.write(i+`
|
|
897
897
|
`),process.stderr.write(`
|
|
898
|
-
`+
|
|
898
|
+
`+B(`Wallet: ${t}`)+`
|
|
899
899
|
|
|
900
900
|
`);let a=Object.keys(n.addresses);for(let c=0;c<a.length;c++){let d=a[c],u=d===o,l=n.addresses[d],p=n.shieldedAddresses?.[d],f=u?P(X(d))+g(" (active)"):d;if(process.stderr.write(` ${f}
|
|
901
901
|
`),process.stderr.write(` ${g("unshielded")} ${se(l)}
|
|
@@ -909,172 +909,172 @@ Usage: midnight wallet use <name>`);if(Qo(t),D(e,"json")){I({wallet:t,active:!0}
|
|
|
909
909
|
`),process.stderr.write(` ${g("file ")} ${r}
|
|
910
910
|
`),process.stderr.write(` ${g("active ")} ${s?z("yes"):"no"}
|
|
911
911
|
|
|
912
|
-
`)}async function
|
|
913
|
-
Usage: midnight wallet remove <name>`);if(
|
|
914
|
-
`)}async function
|
|
915
|
-
`+"The 32-byte entropy can only be computed from the original 24-word mnemonic.");i=Buffer.from(
|
|
912
|
+
`)}async function VS(e){let t=e.positionals[0];if(!t)throw Error(`Missing wallet name.
|
|
913
|
+
Usage: midnight wallet remove <name>`);if(Nc(t),D(e,"json")){I({wallet:t,removed:!0});return}process.stderr.write(z("✓")+` Wallet "${t}" removed
|
|
914
|
+
`)}async function qS(e){let t=C(e,"wallet")??e.positionals[0]??Et(),r=oe(t),n=await import("fs"),s=JSON.parse(n.readFileSync(r,"utf-8"));if(!s.seed)throw Error(`Wallet "${t}" has no seed in ${r}`);let o=D(e,"entropy"),i;if(o){if(!s.mnemonic)throw Error(`Wallet "${t}" has no mnemonic on file — cannot derive BIP-39 entropy.
|
|
915
|
+
`+"The 32-byte entropy can only be computed from the original 24-word mnemonic.");i=Buffer.from(WS(s.mnemonic,ua)).toString("hex")}if(D(e,"json")){let c={name:t,seed:s.seed};if(s.mnemonic)c.mnemonic=s.mnemonic;if(i)c.entropy=i;I(c);return}if(process.stderr.write(`
|
|
916
916
|
`),process.stderr.write(ee(P(" ⚠ WARNING: This will display your wallet seed and mnemonic."))+`
|
|
917
917
|
`),process.stderr.write(ee(" Anyone with this seed can access your funds.")+`
|
|
918
918
|
`),process.stderr.write(ee(" Never share it. Never paste it into a website.")+`
|
|
919
919
|
`),process.stderr.write(`
|
|
920
|
-
`),!await
|
|
920
|
+
`),!await zS(" Show seed? (y/N) ")){process.stderr.write(g(" Cancelled.")+`
|
|
921
921
|
|
|
922
922
|
`);return}if(process.stdout.write(s.seed+`
|
|
923
923
|
`),process.stderr.write(`
|
|
924
|
-
`),process.stderr.write(
|
|
925
|
-
`),process.stderr.write(
|
|
926
|
-
`),i)process.stderr.write(
|
|
927
|
-
`);if(s.mnemonic)process.stderr.write(
|
|
928
|
-
`);if(process.stderr.write(
|
|
924
|
+
`),process.stderr.write(A("Name",t)+`
|
|
925
|
+
`),process.stderr.write(A("Seed (64-byte PBKDF2)",s.seed)+`
|
|
926
|
+
`),i)process.stderr.write(A("Entropy (32-byte BIP-39)",i)+`
|
|
927
|
+
`);if(s.mnemonic)process.stderr.write(A("Mnemonic",s.mnemonic)+`
|
|
928
|
+
`);if(process.stderr.write(A("File",r)+`
|
|
929
929
|
`),i)process.stderr.write(`
|
|
930
930
|
`),process.stderr.write(g(" Note: seed and entropy derive DIFFERENT Midnight wallets from the")+`
|
|
931
931
|
`),process.stderr.write(g(" same mnemonic. Use the value your target project accepts.")+`
|
|
932
932
|
`);process.stderr.write(`
|
|
933
|
-
`)}function
|
|
934
|
-
`)[0];return{status:"unknown",latencyMs:0,lastChecked:t,notes:n}}}function
|
|
935
|
-
`)[0]}async function
|
|
933
|
+
`)}function zS(e){return new Promise((t)=>{let r=La("readline"),n=r.createInterface({input:process.stdin,output:process.stderr});n.question(e,(s)=>{n.close(),t(s.trim().toLowerCase()==="y")})})}var Cp=E(()=>{re();ue();Xe();Ee();Ur();Pe();de()});var Dp={};ve(Dp,{default:()=>Rp});function fa(e){let t=Date.now()-new Date(e).getTime();if(t<60000)return"just now";if(t<3600000)return`${Math.floor(t/60000)}m ago`;if(t<86400000)return`${Math.floor(t/3600000)}h ago`;return`${Math.floor(t/86400000)}d ago`}function pa(e){let t=!1,r=!1;for(let n of Object.values(e)){if(n.status==="down")t=!0;if(n.status==="degraded")r=!0}if(t)return"down";if(r)return"degraded";return"up"}async function ro(e){let t=`${Xn}${e}`,r=await fetch(t,{signal:AbortSignal.timeout(1e4)});if(!r.ok)throw Error(`Dashboard returned HTTP ${r.status} for ${e}`);return r.json()}async function QS(e){let t=C(e,"network");if(t)return t;try{await Promise.resolve().then(() => Gt());let n=Ne();if(n.network&&De(n.network))return n.network}catch{}return}async function so(e,t={}){let r=new AbortController,n=setTimeout(()=>r.abort(),ZS),s=Date.now();try{return{response:await fetch(e,{...t,signal:r.signal}),latencyMs:Date.now()-s}}finally{clearTimeout(n)}}function Tp(e,t){try{ke(e);return}catch(r){let n=r instanceof jt?"Needs a Blockfrost project id: midnight config set blockfrost-project-id <project id>":r.message.split(`
|
|
934
|
+
`)[0];return{status:"unknown",latencyMs:0,lastChecked:t,notes:n}}}function Np(e,t){return Ht(e,t)?.message.split(`
|
|
935
|
+
`)[0]}async function eb(e){let t=new Date().toISOString(),r=Tp(e,t);if(r)return r;try{let{response:n,latencyMs:s}=await so(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({query:"{ block { height } }"})});if(!n.ok){let a=Np(e,n.status);if(a)return{status:"down",latencyMs:s,lastChecked:t,notes:a};if(n.status===403)return{status:"degraded",latencyMs:s,lastChecked:t,notes:"HTTP 403 — likely WAF blocking"};return{status:"down",latencyMs:s,lastChecked:t,notes:`HTTP ${n.status}`}}let o=await n.json();if(!o?.data)return{status:"down",latencyMs:s,lastChecked:t,notes:"No data field"};let i=o.data?.block?.height;return{status:s>no?"degraded":"up",latencyMs:s,lastChecked:t,...i!==void 0?{blockHeight:i}:{},...s>no?{notes:`Slow (${s}ms)`}:{}}}catch(n){return{status:"down",latencyMs:0,lastChecked:t,notes:n.message}}}async function tb(e){let t=new Date().toISOString(),r=Tp(e,t);if(r)return r;let n=e.replace(/^wss:/,"https:").replace(/^ws:/,"http:");try{let{response:s,latencyMs:o}=await so(n,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"system_health",params:[]})});if(!s.ok){let p=Np(e,s.status);if(p)return{status:"down",latencyMs:o,lastChecked:t,notes:p};if(s.status===403)return{status:"degraded",latencyMs:o,lastChecked:t,notes:"HTTP 403 — likely WAF blocking"};return{status:"down",latencyMs:o,lastChecked:t,notes:`HTTP ${s.status}`}}let a=(await s.json())?.result;if(!a)return{status:"down",latencyMs:o,lastChecked:t,notes:"No result in response"};let c=a.peers??0,d=a.isSyncing??!1,u="up",l;if(d)u="degraded",l="Node is syncing";else if(c===0)u="degraded",l="No peers";return{status:u,latencyMs:o,lastChecked:t,peers:c,isSyncing:d,...l?{notes:l}:{}}}catch(s){return{status:"down",latencyMs:0,lastChecked:t,notes:s.message}}}async function rb(e){let t=new Date().toISOString();if(!e)return{status:"unknown",latencyMs:0,lastChecked:t,notes:"No faucet URL"};try{let{response:r,latencyMs:n}=await so(e);if(!r.ok)return{status:"down",latencyMs:n,lastChecked:t,notes:`HTTP ${r.status}`};return{status:n>Ep?"degraded":"up",latencyMs:n,lastChecked:t,...n>Ep?{notes:`Slow (${n}ms)`}:{}}}catch(r){return{status:"down",latencyMs:0,lastChecked:t,notes:r.message}}}async function nb(e){let t=new Date().toISOString();if(!e)return{status:"unknown",latencyMs:0,lastChecked:t,notes:"URL not configured"};try{let{response:r,latencyMs:n}=await so(e);if(!r.ok)return{status:"down",latencyMs:n,lastChecked:t,notes:`HTTP ${r.status}`};let s=await r.text();if(!s||s.length===0)return{status:"down",latencyMs:n,lastChecked:t,notes:"Empty response"};return{status:n>no?"degraded":"up",latencyMs:n,lastChecked:t,...n>no?{notes:`Slow (${n}ms)`}:{}}}catch(r){return{status:"down",latencyMs:0,lastChecked:t,notes:r.message}}}async function Ap(e){if(!De(e))return{};let t=os(e,{blockfrostProjectId:zo(e)}),r=YS[e];if(!r)return{};let[n,s,o,i]=await Promise.all([eb(t.indexer),tb(t.node),rb(r.faucet),nb(r.explorer)]);return{indexer:n,rpc:s,faucet:o,explorer:i}}function sb(e,t,r){process.stderr.write(`
|
|
936
936
|
`+P(e)+`
|
|
937
937
|
`),process.stderr.write(g(" "+"─".repeat(62))+`
|
|
938
|
-
`);let n=new Set([...Object.keys(r),...t?Object.keys(t):[]]);for(let s of n){let o=r[s],i=t?.[s],a=(
|
|
939
|
-
`)}else if(i){let c=
|
|
940
|
-
`)}}}function
|
|
941
|
-
`+
|
|
938
|
+
`);let n=new Set([...Object.keys(r),...t?Object.keys(t):[]]);for(let s of n){let o=r[s],i=t?.[s],a=(XS[s]??s).padEnd(18);if(o){let c=xp[o.status]??g("—"),d=o.latencyMs>0?g(` ${o.latencyMs}ms`):"",u=o.notes?g(` — ${o.notes}`):"",l="";if(i&&i.status!==o.status&&i.status!=="unknown")l=g(` (canary: ${i.status}${i.lastChecked?" "+fa(i.lastChecked):""})`);process.stderr.write(` ${pn(a)}${c}${d}${u}${l}
|
|
939
|
+
`)}else if(i){let c=xp[i.status]??g("—"),d=i.latencyMs>0?g(` ${i.latencyMs}ms`):"",u=i.lastChecked?g(` (${fa(i.lastChecked)})`):"",l=i.notes?g(` — ${i.notes}`):"";process.stderr.write(` ${pn(a)}${c}${d}${u}${l}
|
|
940
|
+
`)}}}function ob(e,t){let r=t?e.filter((n)=>n.affects.toLowerCase().includes(t.toLowerCase())):e;if(r.length===0)return;process.stderr.write(`
|
|
941
|
+
`+B("Known Issues")+`
|
|
942
942
|
|
|
943
943
|
`);for(let n of r)process.stderr.write(` ${he(n.id.padEnd(28))}${n.summary}
|
|
944
944
|
`),process.stderr.write(` ${" ".repeat(28)}${g(n.status)}
|
|
945
|
-
`)}async function
|
|
946
|
-
`+
|
|
947
|
-
`),i?.lastUpdated)process.stderr.write(g(` Canary: ${
|
|
945
|
+
`)}async function Rp(e){let t=D(e,"json"),r=D(e,"all"),n=D(e,"watch"),s=await QS(e)??"preprod",o=H("Checking network status..."),i=null,a=null,c,d;if(r)d=["preprod","preview"];else d=[s];let[u,...l]=await Promise.all([Promise.all([ro("/api/status"),ro("/api/issues")]).catch((m)=>(c=m.message,null)),...d.map((m)=>Ap(m))]);if(u)[i,a]=u;o.stop("Done");let p={};for(let m=0;m<d.length;m++)p[d[m]]=l[m];if(t){let m={lastUpdated:i?.lastUpdated??null,dashboard:Xn,canaryAvailable:i!==null,networks:{}};for(let w of d){let S=p[w]??{},k=i?.networks[w],T={...k,...S};m.networks[w]={overall:pa(T),live:S,canary:k??null}}if(a){let w=r?void 0:d[0];m.issues=w?a.issues.filter((S)=>S.affects.toLowerCase().includes(w.toLowerCase())):a.issues}if(c)m.canaryError=c;I(m);let y=d.reduce((w,S)=>{let k={...i?.networks[S]??{},...p[S]??{}},T=pa(k);if(T==="down")return"down";if(T==="degraded"&&w!=="down")return"degraded";return w},"up");if(y==="down")process.exitCode=2;else if(y==="degraded")process.exitCode=1;return}let f=()=>{if(process.stderr.write(`
|
|
946
|
+
`+B("Midnight Network Status")+`
|
|
947
|
+
`),i?.lastUpdated)process.stderr.write(g(` Canary: ${fa(i.lastUpdated)}`)+" ");if(process.stderr.write(g("Live: just now")+`
|
|
948
948
|
`),c)process.stderr.write(g(` (Dashboard unreachable: ${c})`)+`
|
|
949
949
|
`);if(d.length===0){process.stderr.write(`
|
|
950
950
|
`+g("No network data available.")+`
|
|
951
951
|
|
|
952
|
-
`);return}for(let m of d)
|
|
952
|
+
`);return}for(let m of d)sb(m,i?.networks[m],p[m]??{});if(a){let m=r?void 0:d[0];ob(a.issues,m)}process.stderr.write(`
|
|
953
953
|
`+Z()+`
|
|
954
954
|
`),process.stderr.write(g(" Dashboard: ")+X(Xn)+`
|
|
955
955
|
|
|
956
|
-
`)};if(f(),n){let m=setInterval(async()=>{try{let[y,...w]=await Promise.all([Promise.all([ro("/api/status"),ro("/api/issues")]).catch(()=>null),...d.map((S)=>
|
|
957
|
-
`)}},30000);await new Promise(()=>{process.on("SIGINT",()=>{clearInterval(m),process.exit(0)})})}let h=d.reduce((m,y)=>{let w={...i?.networks[y]??{},...p[y]??{}},S=
|
|
958
|
-
Available: ${i.join(", ")}`);a=t}else a=i[0];let c=i.filter((u)=>u!==a),d=jr(s,a,"compiler",io);return
|
|
956
|
+
`)};if(f(),n){let m=setInterval(async()=>{try{let[y,...w]=await Promise.all([Promise.all([ro("/api/status"),ro("/api/issues")]).catch(()=>null),...d.map((S)=>Ap(S))]);if(y)[i,a]=y;for(let S=0;S<d.length;S++)p[d[S]]=w[S];process.stderr.write("\x1B[2J\x1B[H"),f()}catch{process.stderr.write(g(" Refresh failed — retrying in 30s")+`
|
|
957
|
+
`)}},30000);await new Promise(()=>{process.on("SIGINT",()=>{clearInterval(m),process.exit(0)})})}let h=d.reduce((m,y)=>{let w={...i?.networks[y]??{},...p[y]??{}},S=pa(w);if(S==="down")return"down";if(S==="degraded"&&m!=="down")return"degraded";return m},"up");if(h==="down")process.exitCode=2;else if(h==="degraded")process.exitCode=1}var YS,XS,xp,ZS=15000,no=5000,Ep=1e4;var Ip=E(()=>{re();Me();Ce();Ee();de();ct();YS={preprod:{faucet:"https://faucet.preprod.midnight.network/",explorer:"https://preprod.midnightexplorer.com/"},preview:{faucet:"https://faucet.preview.midnight.network/",explorer:null},undeployed:{faucet:"",explorer:""}},XS={indexer:"Indexer",rpc:"RPC Node",faucet:"Faucet",explorer:"Explorer",chain:"Chain",dust:"Dust Generation",wallet:"Wallet Ops",dapp:"DApp Flow"},xp={up:z("UP"),down:he("DOWN"),degraded:P("\x1B[33mDEGRADED\x1B[0m"),unknown:g("—")}});function oo(e){if(!/^[0-9a-fA-F]{64}$/.test(e))throw new R(`A contract address is 64 hex characters (32 bytes); got "${e}" (${e.length} characters).`)}function _p(e,t,r){let n=e.circuits.filter((i)=>i.proof),s=n.find((i)=>i.name===t);if(!s){if(e.circuits.some((a)=>a.name===t))throw new R(`${t} is a pure circuit of ${e.name}: it runs locally and makes no transaction, so it can't be called.`);let i=n.map((a)=>a.name);throw new R(`${e.name} has no circuit "${t}". `+(i.length>0?`Its callable circuits: ${i.join(", ")}.`:"It has no circuits to call."))}let o=s.arguments.length;if(r.length!==o){let i=s.arguments.map((a)=>a.name).join(", ");throw new R(`${t} takes ${o} argument${o===1?"":"s"}${o>0?` (${i})`:""}; --args gave ${r.length}.`)}}var ma=E(()=>{ue()});import{existsSync as ga,readFileSync as ib,readdirSync as ab}from"node:fs";import{join as jr,basename as cb}from"node:path";function dt(e,t){let r=jr(e,"compiler",io);if(ga(r))return $p(r,e,[]);for(let n of Pp){let s=n?jr(e,n,"managed"):jr(e,"managed");if(!ga(s))continue;let o;try{o=ab(s).sort()}catch{continue}let i=o.filter((u)=>ga(jr(s,u,"compiler",io)));if(i.length===0)continue;let a;if(t){if(!i.includes(t))throw Error(`Contract "${t}" not found in ${s}
|
|
958
|
+
Available: ${i.join(", ")}`);a=t}else a=i[0];let c=i.filter((u)=>u!==a),d=jr(s,a,"compiler",io);return $p(d,jr(s,a),c)}throw Error(`No compiled contract found in ${e}
|
|
959
959
|
Expected: managed/<name>/compiler/${io}
|
|
960
|
-
Searched: ${
|
|
961
|
-
Run "compact compile" first, or use --managed <path> to specify the managed directory.`)}function
|
|
960
|
+
Searched: ${Pp.map((n)=>n?`${n}/managed/`:"managed/").join(", ")}
|
|
961
|
+
Run "compact compile" first, or use --managed <path> to specify the managed directory.`)}function $p(e,t,r){let n;try{n=JSON.parse(ib(e,"utf-8"))}catch(o){throw Error(`Failed to parse ${e}: ${o.message}`)}return{info:db(n,e,t,r),infoPath:e}}function db(e,t,r,n){if(typeof e!=="object"||e===null||Array.isArray(e))throw Error(`${t}: must be a JSON object`);let s=e,o=typeof s["compiler-version"]==="string"?s["compiler-version"]:"unknown",i=typeof s["language-version"]==="string"?s["language-version"]:"unknown",a=typeof s["runtime-version"]==="string"?s["runtime-version"]:"unknown",c=Array.isArray(s.circuits)?s.circuits:[],d=Array.isArray(s.witnesses)?s.witnesses:[];return{name:cb(r),managedDir:r,compilerVersion:o,languageVersion:i,runtimeVersion:a,circuits:c,witnesses:d,siblings:n}}function Ke(e){switch(e["type-name"]){case"Uint":return"bigint";case"Bytes":return"Uint8Array";case"Opaque":return e.tsType??"unknown";case"Tuple":if(!e.types||e.types.length===0)return"void";return`[${e.types.map(Ke).join(", ")}]`;case"Boolean":return"boolean";case"String":return"string";case"Vector":return e.types?.[0]?`${Ke(e.types[0])}[]`:"unknown[]";case"Map":if(e.types&&e.types.length>=2)return`Map<${Ke(e.types[0])}, ${Ke(e.types[1])}>`;return"Map<unknown, unknown>";case"Set":return e.types?.[0]?`Set<${Ke(e.types[0])}>`:"Set<unknown>";case"Option":return e.types?.[0]?`${Ke(e.types[0])} | null`:"unknown | null";default:return e["type-name"]??"unknown"}}function Op(e){let t=e.arguments.map((r)=>`${r.name}: ${Ke(r.type)}`).join(", ");return`${e.name}(${t})`}function Mp(e){if(e.pure)return"pure";let t=["impure"];if(e.proof)t.push("proof");return t.join(", ")}function Fp(e){let t=e.arguments.map((s)=>`${s.name}: ${Ke(s.type)}`).join(", "),r=Ke(e["result type"]),n=r!=="void"?` → ${r}`:"";return`${e.name}(${t})${n}`}function Up(e){return{name:e.name,compilerVersion:e.compilerVersion,languageVersion:e.languageVersion,runtimeVersion:e.runtimeVersion,managedDir:e.managedDir,siblings:e.siblings,circuits:e.circuits.map((t)=>({name:t.name,pure:t.pure,proof:t.proof,arguments:t.arguments.map((r)=>({name:r.name,type:Ke(r.type)})),returnType:Ke(t["result-type"])})),witnesses:e.witnesses.map((t)=>({name:t.name,arguments:t.arguments.map((r)=>({name:r.name,type:Ke(r.type)})),returnType:Ke(t["result type"])}))}}var io="contract-info.json",Pp;var Fn=E(()=>{Pp=["","contract/src","contract","contracts/src","contracts","src"]});import{resolve as ha}from"node:path";function Un(e){return ha(C(e,"managed")??C(e,"path")??process.cwd())}function ao(e){let t=ha(C(e,"path")??process.cwd()),{info:r}=dt(Un(e),C(e,"name")),n=r.witnesses.map((i)=>i.name);if(n.length>0&&!Cl(t))throw Error(xl({projectRoot:t,witnessNames:n}));let s=Lp(C(e,"args")),o=C(e,"secret-key");if(o!==void 0&&!/^[0-9a-fA-F]{64}$/.test(o))throw new R("--secret-key must be 32 bytes of hex (64 chars)");return{dappDir:t,info:r,constructorArgs:s,privateStateSecretKey:o}}function co(e){let t=ha(C(e,"path")??process.cwd()),r=zr(e,"address","contract address"),n=zr(e,"circuit","circuit name"),{info:s}=dt(Un(e),C(e,"name")),o=Lp(C(e,"args"));return oo(r),_p(s,n,o),{dappDir:t,info:s,address:r,circuit:n,callArgs:o}}function Lp(e){if(!e)return[];let t;try{t=JSON.parse(e)}catch(r){throw new R(`Invalid --args JSON: ${r.message}`)}if(Array.isArray(t))return t;if(t!==null&&typeof t==="object")return Object.values(t);throw new R(`Invalid --args JSON: expected an array or an object, got ${JSON.stringify(t)}`)}var lo=E(()=>{re();ue();Fn();Bi();ma()});import{indexerPublicDataProvider as lb}from"@midnight-ntwrk/midnight-js-indexer-public-data-provider";function Bp(e){return ke(e.indexer),lb({queryURL:e.indexer,subscriptionURL:e.indexerWS??e.indexer.replace("http","ws")})}var Wp=E(()=>{Me()});var Gp={};ve(Gp,{default:()=>Hp});import{resolve as ub}from"node:path";function pb(e){return jp.includes(e)}async function Hp(e,t){let r=e.subcommand;if(!r||!pb(r))throw new R(`Usage: midnight contract <${jp.join("|")}>
|
|
962
962
|
|
|
963
963
|
inspect Show circuits, witnesses, and types for a compiled contract
|
|
964
964
|
deploy Deploy a contract to the network
|
|
965
965
|
call Call a circuit on a deployed contract
|
|
966
966
|
state Read the ledger state of a deployed contract
|
|
967
967
|
|
|
968
|
-
Run "midnight help contract" for more info.`);switch(r){case"inspect":return
|
|
969
|
-
`+
|
|
968
|
+
Run "midnight help contract" for more info.`);switch(r){case"inspect":return fb(e);case"deploy":return mb(e);case"call":return hb(e);case"state":return wb(e)}}async function fb(e){let t=D(e,"json"),r=Un(e),n=C(e,"name"),{info:s}=dt(r,n);if(t){I(Up(s));return}if(process.stderr.write(`
|
|
969
|
+
`+B(`Contract: ${s.name}`)+`
|
|
970
970
|
|
|
971
|
-
`),process.stderr.write(
|
|
972
|
-
`),process.stderr.write(
|
|
973
|
-
`),process.stderr.write(
|
|
971
|
+
`),process.stderr.write(A("Compiler",s.compilerVersion)+`
|
|
972
|
+
`),process.stderr.write(A("Language",s.languageVersion)+`
|
|
973
|
+
`),process.stderr.write(A("Runtime",s.runtimeVersion)+`
|
|
974
974
|
`),process.stderr.write(`
|
|
975
975
|
`+P(" Circuits")+`
|
|
976
976
|
`),s.circuits.length===0)process.stderr.write(g(" (none)")+`
|
|
977
|
-
`);else for(let o of s.circuits){let i=
|
|
977
|
+
`);else for(let o of s.circuits){let i=Op(o),a=Mp(o),c=o.pure?X(a):ee(a);process.stderr.write(` ${i} ${g("—")} ${c}
|
|
978
978
|
`)}if(process.stderr.write(`
|
|
979
979
|
`+P(" Witnesses")+`
|
|
980
980
|
`),s.witnesses.length===0)process.stderr.write(g(" (none)")+`
|
|
981
|
-
`);else for(let o of s.witnesses)process.stderr.write(` ${
|
|
981
|
+
`);else for(let o of s.witnesses)process.stderr.write(` ${Fp(o)}
|
|
982
982
|
`);if(s.siblings.length>0){process.stderr.write(`
|
|
983
983
|
`+P(" Other contracts in this project")+`
|
|
984
984
|
`);for(let o of s.siblings)process.stderr.write(` ${X(o)}
|
|
985
985
|
`);process.stderr.write(`
|
|
986
986
|
`+g(" Inspect a sibling: mn contract inspect --name <name>")+`
|
|
987
987
|
`)}process.stderr.write(`
|
|
988
|
-
`)}async function
|
|
989
|
-
`+
|
|
988
|
+
`)}async function mb(e){let t=D(e,"json"),{dappDir:r,info:n,constructorArgs:s,privateStateSecretKey:o}=ao(e);await Promise.resolve().then(() => Mr());if(!t)process.stderr.write(`
|
|
989
|
+
`+B("Contract Deploy")+`
|
|
990
990
|
|
|
991
|
-
`);let a=Pr(e,"contract","deploy"),{network:c,networkConfig:d}=a;if(!t){if(process.stderr.write(
|
|
992
|
-
`),process.stderr.write(
|
|
993
|
-
`),s.length>0)process.stderr.write(
|
|
991
|
+
`);let a=Pr(e,"contract","deploy"),{network:c,networkConfig:d}=a;if(!t){if(process.stderr.write(A("Contract",n.name)+`
|
|
992
|
+
`),process.stderr.write(A("Network",c)+`
|
|
993
|
+
`),s.length>0)process.stderr.write(A("Constructor args",String(s.length))+`
|
|
994
994
|
`);process.stderr.write(`
|
|
995
|
-
`)}await
|
|
996
|
-
`),process.stderr.write(
|
|
995
|
+
`)}await Tn(a,C(e,"wallet"),t?Ve():H("Checking wallet..."));let u=await Nn(a,C(e,"wallet"),t?Ve():H("Starting mn serve...")),l=t?Ve():H("Deploying contract...");try{let p=await Ls({dappDir:r,networkConfig:d,managedDir:n.managedDir,contractName:n.name,servePort:u.port,args:s,privateStateSecretKey:o,onMessage:(f)=>l.update(f)});if(l.stop("Contract deployed"),t)I({subcommand:"deploy",contractName:n.name,address:p.contractAddress,network:c});else process.stderr.write(`
|
|
996
|
+
`),process.stderr.write(A("Address",p.contractAddress)+`
|
|
997
997
|
`),process.stderr.write(`
|
|
998
998
|
`+z(" ✓ Deploy successful")+`
|
|
999
|
-
`),
|
|
1000
|
-
`)}catch(p){throw l.fail("Deploy failed"),p}finally{await u.stop()}}function
|
|
999
|
+
`),gb(p.contractAddress,n.circuits,c),process.stdout.write(p.contractAddress+`
|
|
1000
|
+
`)}catch(p){throw l.fail("Deploy failed"),p}finally{await u.stop()}}function gb(e,t,r){let n=r==="undeployed"?"":` --network ${r}`;process.stderr.write(`
|
|
1001
1001
|
`+g(" Next:")+`
|
|
1002
1002
|
`),process.stderr.write(g(" mn contract state --address ")+X(e)+g(n)+`
|
|
1003
1003
|
`);let s=t.find((o)=>o.arguments.length===0);if(s)process.stderr.write(g(" mn contract call --address ")+X(e)+g(" --circuit ")+X(s.name)+g(n)+`
|
|
1004
1004
|
`);process.stderr.write(`
|
|
1005
|
-
`)}async function
|
|
1006
|
-
`+
|
|
1005
|
+
`)}async function hb(e){let t=D(e,"json"),{dappDir:r,info:n,address:s,circuit:o,callArgs:i}=co(e);await Promise.resolve().then(() => Mr());if(!t)process.stderr.write(`
|
|
1006
|
+
`+B("Contract Call")+`
|
|
1007
1007
|
|
|
1008
|
-
`);let c=Pr(e,"contract","call"),{network:d,networkConfig:u}=c;if(!t)process.stderr.write(
|
|
1009
|
-
`),process.stderr.write(
|
|
1010
|
-
`),process.stderr.write(
|
|
1008
|
+
`);let c=Pr(e,"contract","call"),{network:d,networkConfig:u}=c;if(!t)process.stderr.write(A("Contract",n.name)+`
|
|
1009
|
+
`),process.stderr.write(A("Circuit",o)+`
|
|
1010
|
+
`),process.stderr.write(A("Address",s.slice(0,20)+"...")+`
|
|
1011
1011
|
|
|
1012
|
-
`);await
|
|
1012
|
+
`);await Tn(c,C(e,"wallet"),t?Ve():H("Checking wallet..."));let l=await Nn(c,C(e,"wallet"),t?Ve():H("Starting mn serve...")),p=t?Ve():H(`Calling ${o}...`);try{let f=await Bs({dappDir:r,networkConfig:u,managedDir:n.managedDir,contractName:n.name,contractAddress:s,circuit:o,args:i,servePort:l.port,onMessage:(h)=>p.update(h)});if(p.stop(`${o} called`),t)I({subcommand:"call",contractName:n.name,circuit:o,address:s,network:d,status:f.status});else process.stderr.write(`
|
|
1013
1013
|
`+z(" ✓ Circuit call successful")+`
|
|
1014
1014
|
|
|
1015
|
-
`)}catch(f){throw p.fail("Call failed"),f}finally{await l.stop()}}async function
|
|
1016
|
-
`+
|
|
1015
|
+
`)}catch(f){throw p.fail("Call failed"),f}finally{await l.stop()}}async function wb(e){let t=D(e,"json"),r=ub(C(e,"path")??process.cwd()),n=Un(e),s=C(e,"name"),o=zr(e,"address","contract address");oo(o);await Promise.resolve().then(() => Mr());let{network:a,networkConfig:c}=Pr(e,"contract","state");if(!t)process.stderr.write(`
|
|
1016
|
+
`+B("Contract State")+`
|
|
1017
1017
|
|
|
1018
|
-
`),process.stderr.write(
|
|
1019
|
-
`),process.stderr.write(
|
|
1018
|
+
`),process.stderr.write(A("Address",o.slice(0,20)+"...")+`
|
|
1019
|
+
`),process.stderr.write(A("Network",a)+`
|
|
1020
1020
|
|
|
1021
|
-
`);let d=t?
|
|
1021
|
+
`);let d=t?Ve():H("Querying contract state...");try{let{info:u}=dt(n,s),l=await $r({dappDir:r,networkConfig:c,managedDir:u.managedDir,contractName:u.name,contractAddress:o,onMessage:(p)=>d.update(p)});if(d.stop("State retrieved"),t)I({subcommand:"state",address:o,network:a,...l});else{let p=Object.keys(l.fields).length>0,f=Object.keys(l.maps).length>0;if(p||f){process.stderr.write(P(" Ledger State")+`
|
|
1022
1022
|
`);for(let[h,m]of Object.entries(l.fields))process.stderr.write(` ${h}: ${X(m)}
|
|
1023
1023
|
`);for(let[h,m]of Object.entries(l.maps))process.stderr.write(` ${h}: ${g(`Map (${m.size} entries)`)}
|
|
1024
1024
|
`)}else process.stderr.write(g(" (no ledger fields found)")+`
|
|
1025
1025
|
`);process.stderr.write(`
|
|
1026
|
-
`)}}catch(u){d.stop(ee("⚠")+" Parsed state unavailable, showing raw");await Promise.resolve().then(() =>
|
|
1026
|
+
`)}}catch(u){d.stop(ee("⚠")+" Parsed state unavailable, showing raw");await Promise.resolve().then(() => Wp());let f=await Bp(c).queryContractState(o);if(!f)throw Error(`No contract found at address ${o} on ${a}`);let h=f.data??f;if(t)I({subcommand:"state",address:o,network:a,raw:h});else process.stderr.write(P(" Raw State")+`
|
|
1027
1027
|
`),process.stderr.write(g(" (run from dApp root for parsed ledger fields)")+`
|
|
1028
1028
|
`),process.stderr.write(` ${JSON.stringify(h).slice(0,200)}
|
|
1029
1029
|
|
|
1030
|
-
`)}}var
|
|
1031
|
-
Dust builds up with time from the NIGHT registered for it: see how much there is with "midnight dust status", and run the same command again when there is enough. A deploy that stopped part way carries on from where it stopped, so it then needs only what is left.`}var
|
|
1032
|
-
`+
|
|
1030
|
+
`)}}var jp;var Kp=E(()=>{re();ue();de();ct();$s();ma();lo();Fn();jp=["inspect","deploy","call","state"]});function Jp(e){let{transactions:t,totalDust:r,largestDust:n}=yb;return`Deploying an account takes about ${r} DUST from the wallet over ${t} transactions, the largest about ${n} DUST at once (measured on a local ledger-9 chain; fee prices move with the chain's load). This wallet had ${Yt(e)} when the deploy began.
|
|
1031
|
+
Dust builds up with time from the NIGHT registered for it: see how much there is with "midnight dust status", and run the same command again when there is enough. A deploy that stopped part way carries on from where it stopped, so it then needs only what is left.`}var yb;var Vp=E(()=>{de();yb={transactions:5,totalDust:48,largestDust:17.1}});var Yp={};ve(Yp,{default:()=>zp});function bb(e){let{errorCode:t}=Hn(e);return t===q.DUST_REQUIRED||t===q.INSUFFICIENT_BALANCE}async function zp(e,t){let{request:r,target:n,walletName:s,bridge:o,account:i}=await Fr(e),a=D(e,"json"),c=C(e,"wallet");if(!a){if(process.stderr.write(`
|
|
1032
|
+
`+B(`Grant: ${r.subcommand}`)+`
|
|
1033
1033
|
|
|
1034
|
-
`),process.stderr.write(
|
|
1035
|
-
`),process.stderr.write(
|
|
1036
|
-
`),i!==null)process.stderr.write(
|
|
1034
|
+
`),process.stderr.write(A("Network",n.network)+`
|
|
1035
|
+
`),process.stderr.write(A("Wallet",s)+`
|
|
1036
|
+
`),i!==null)process.stderr.write(A("Account",i.address)+`
|
|
1037
1037
|
`);process.stderr.write(`
|
|
1038
|
-
`)}let d=
|
|
1039
|
-
`+
|
|
1038
|
+
`)}let d=Gl(r)?await Tn(n,c,a?Ve():H("Checking wallet...")):void 0,u=await Nn(n,c,a?Ve():H("Starting mn serve...")),l=a?Ve():H(Sb[r.subcommand]),p={...o,servePort:u.port,onMessage:(h)=>l.update(h)},f={subcommand:r.subcommand,network:n.network,wallet:s,ownerKey:"development"};try{if(r.subcommand==="deploy"){let m=await Fl(p,Bl());if(l.stop(m.resumed?"Account ready":"Account deployed"),a)I({...f,...m});else{if(process.stderr.write(`
|
|
1039
|
+
`+A("Account",m.address)+`
|
|
1040
1040
|
`),m.resumed)process.stderr.write(g(" An account already on record was completed; no new one was deployed.")+`
|
|
1041
1041
|
`);if(m.setAside)process.stderr.write(g(` The record of an earlier deploy that never reached the chain was kept at ${m.setAside}`)+`
|
|
1042
1042
|
`);process.stderr.write(`
|
|
1043
|
-
`+ee(" "+
|
|
1043
|
+
`+ee(" "+qp)+`
|
|
1044
1044
|
`),process.stderr.write(g(" Next: midnight grant status")+`
|
|
1045
1045
|
|
|
1046
1046
|
`),process.stdout.write(m.address+`
|
|
1047
|
-
`)}return}if(r.subcommand==="deposit"){let m=await
|
|
1048
|
-
`+
|
|
1049
|
-
`),process.stderr.write(
|
|
1050
|
-
`),process.stderr.write(
|
|
1047
|
+
`)}return}if(r.subcommand==="deposit"){let m=await Ul(p,r.value);if(l.stop("Deposited"),a)I({...f,amount:r.amount,...m});else process.stderr.write(`
|
|
1048
|
+
`+A("Deposited",`${r.amount} NIGHT (${m.value} in the smallest unit, as status and --cap count)`)+`
|
|
1049
|
+
`),process.stderr.write(A("Block",String(m.blockHeight))+`
|
|
1050
|
+
`),process.stderr.write(A("Transaction",m.txHash)+`
|
|
1051
1051
|
`),process.stderr.write(`
|
|
1052
1052
|
`+g(" Next: midnight grant status")+`
|
|
1053
1053
|
|
|
1054
1054
|
`),process.stdout.write(m.txHash+`
|
|
1055
|
-
`);return}let h=await
|
|
1055
|
+
`);return}let h=await Ll(p,Jl(r,a));if(h.exitCode!==0){let m=h.errors.join(`
|
|
1056
1056
|
`)||`The account build's ${r.subcommand} command failed`;throw h.exitCode===2?new R(m):Error(m)}if(l.stop("Done"),a)I({...f,...JSON.parse(h.output)});else process.stderr.write(`
|
|
1057
1057
|
`),process.stdout.write(h.output+`
|
|
1058
1058
|
`),process.stderr.write(`
|
|
1059
|
-
`+g(" "+
|
|
1059
|
+
`+g(" "+qp)+`
|
|
1060
1060
|
|
|
1061
|
-
`)}catch(h){if(l.fail(`${r.subcommand} failed`),r.subcommand==="deploy"&&d!==void 0&&h instanceof Error&&
|
|
1061
|
+
`)}catch(h){if(l.fail(`${r.subcommand} failed`),r.subcommand==="deploy"&&d!==void 0&&h instanceof Error&&bb(h))throw Error(`${h.message}
|
|
1062
1062
|
|
|
1063
|
-
${
|
|
1064
|
-
Run this command from the root of a dApp project, or create a ${
|
|
1065
|
-
Check the build log: ${i}`);if(await
|
|
1066
|
-
Check the build log: ${i}`)}function
|
|
1063
|
+
${Jp(d.dustBalance)}`);throw h}finally{await u.stop()}}var qp="This account is on a development owner key, kept in its records: the wallet's mnemonic can't recover it.",Sb;var Xp=E(()=>{re();ue();To();qi();Vp();Ks();Gs();$s();de();ct();Sb={deploy:"Deploying the account...",deposit:"Depositing into the account...",status:"Reading the account...",list:"Reading the grants...",issue:"Reading the grant request...",revoke:"Revoking the grant...","revoke-all":"Revoking every grant..."}});import{existsSync as Hr,readFileSync as Ln,readdirSync as vb}from"node:fs";import{join as ar,resolve as kb}from"node:path";function uo(e){let t=kb(e??process.cwd()),r=ar(t,wa);if(!Hr(r))throw Error(`No ${wa} found in ${t}
|
|
1064
|
+
Run this command from the root of a dApp project, or create a ${wa} file.`);let n;try{n=JSON.parse(Ln(r,"utf-8"))}catch(o){throw Error(`Failed to parse ${r}: ${o.message}`)}return{config:Eb(n,r),configPath:r,dappDir:t}}function ya(e){let t=ar(e,Cb);if(!Hr(t))return[];let r=vb(t,{withFileTypes:!0}),n=[];for(let s of r){if(!s.isDirectory())continue;let o=ar(t,s.name),i=ar(o,"suite.json");if(!Hr(i))continue;let a;try{a=JSON.parse(Ln(i,"utf-8"))}catch(c){throw Error(`Failed to parse ${i}: ${c.message}`)}n.push({suite:Ab(a,i),suiteDir:o})}return n}function rf(e){let t=ar(e,"assertions.json");if(!Hr(t))return null;let r;try{r=JSON.parse(Ln(t,"utf-8"))}catch(n){throw Error(`Failed to parse ${t}: ${n.message}`)}return Tb(r,t)}function nf(e){let t=ar(e,"actions.json");if(!Hr(t))return null;let r;try{r=JSON.parse(Ln(t,"utf-8"))}catch(n){throw Error(`Failed to parse ${t}: ${n.message}`)}return Nb(r,t)}function sf(e){let t=ar(e,"prompt.md");if(!Hr(t))return null;return Ln(t,"utf-8")}function Eb(e,t){if(typeof e!=="object"||e===null||Array.isArray(e))throw Error(`${t}: must be a JSON object`);let r=e;if(typeof r.name!=="string"||r.name.length===0)throw Error(`${t}: "name" is required and must be a non-empty string`);if(r.network!==void 0&&!Zp.includes(r.network))throw Error(`${t}: "network" must be one of: ${Zp.join(", ")}`);if(r.port!==void 0&&(typeof r.port!=="number"||r.port<1||r.port>65535))throw Error(`${t}: "port" must be a number between 1 and 65535`);if(r.buildCmd!==void 0&&typeof r.buildCmd!=="string")throw Error(`${t}: "buildCmd" must be a string`);if(r.buildDir!==void 0&&typeof r.buildDir!=="string")throw Error(`${t}: "buildDir" must be a string`);if(r.url!==void 0&&typeof r.url!=="string")throw Error(`${t}: "url" must be a string`);if(!Array.isArray(r.prep))throw Error(`${t}: "prep" is required and must be an array of prep step IDs`);for(let n of r.prep)if(typeof n!=="string"||!xb.test(n))throw Error(`${t}: invalid prep step "${n}". Valid steps: cache-clear, localnet-up, balance:<amount>, dust-register, dust-wait, mn-serve, build-and-serve`);return{name:r.name,network:r.network??"undeployed",port:r.port,buildCmd:r.buildCmd,buildDir:r.buildDir,url:r.url,contractEntry:r.contractEntry,prep:r.prep}}function Ab(e,t){if(typeof e!=="object"||e===null||Array.isArray(e))throw Error(`${t}: must be a JSON object`);let r=e;if(typeof r.name!=="string"||r.name.length===0)throw Error(`${t}: "name" is required and must be a non-empty string`);if(typeof r.description!=="string")throw Error(`${t}: "description" is required and must be a string`);if(!Qp.includes(r.strategy))throw Error(`${t}: "strategy" must be one of: ${Qp.join(", ")}`);if(r.timeout!==void 0&&(typeof r.timeout!=="number"||r.timeout<=0))throw Error(`${t}: "timeout" must be a positive number (seconds)`);if(r.browserMode!==void 0&&!ef.includes(r.browserMode))throw Error(`${t}: "browserMode" must be one of: ${ef.join(", ")}`);return{name:r.name,description:r.description,strategy:r.strategy,browserMode:r.browserMode,model:r.model,effort:r.effort,timeout:r.timeout,depends:Array.isArray(r.depends)?r.depends:void 0}}function Tb(e,t){if(typeof e!=="object"||e===null||Array.isArray(e))throw Error(`${t}: must be a JSON object`);let r=e;if(!Array.isArray(r.post))throw Error(`${t}: "post" is required and must be an array of assertion checks`);for(let n of r.post){if(typeof n!=="object"||n===null)throw Error(`${t}: each assertion check must be an object`);let s=n;if(typeof s.id!=="string")throw Error(`${t}: each assertion check must have a string "id"`);if(typeof s.type!=="string")throw Error(`${t}: assertion "${s.id}" must have a string "type"`);if(typeof s.expect!=="string"||s.expect!=="pass"&&s.expect!=="fail")throw Error(`${t}: assertion "${s.id}" must have "expect" set to "pass" or "fail"`)}return{pre:Array.isArray(r.pre)?r.pre:void 0,post:r.post}}function Nb(e,t){if(typeof e!=="object"||e===null||Array.isArray(e))throw Error(`${t}: must be a JSON object`);let r=e;if(!Array.isArray(r.actions))throw Error(`${t}: "actions" is required and must be an array`);for(let n of r.actions){if(typeof n!=="object"||n===null)throw Error(`${t}: each action must be an object`);let s=n;if(typeof s.id!=="string")throw Error(`${t}: each action must have a string "id"`);if(typeof s.type!=="string"||!tf.includes(s.type))throw Error(`${t}: action "${s.id}" has invalid type "${s.type}". Valid: ${tf.join(", ")}`);if(s.type==="contract-call"&&typeof s.circuit!=="string")throw Error(`${t}: action "${s.id}" (contract-call) requires a "circuit" field`)}return{actions:r.actions}}var wa="dapp.test.json",Cb="tests/suites",Zp,Qp,ef,xb,tf;var of=E(()=>{Zp=["undeployed","preprod","preview"],Qp=["browser","cli","hybrid"],ef=["dom","script","vision","auto"],xb=/^(cache-clear|localnet-up|balance:\d+|dust|dust-register|dust-wait|mn-serve|build-and-serve)$/;tf=["contract-deploy","contract-call","contract-state","wallet-cmd"]});function af(){let e=[];return{cleanups:e,addCleanup(t){e.push(t)}}}import{spawn as Rb}from"node:child_process";import{createWriteStream as Db}from"node:fs";import{join as Ib}from"node:path";import _b from"node:http";import Pb from"node:net";async function df(e){let{dappDir:t,buildCmd:r,buildDir:n=".",port:s,url:o,logFile:i,timeoutMs:a=240000,onMessage:c=()=>{}}=e;if(await $b(s)){if(await cf(o))return c(`Reusing existing dev server on port ${s} (URL responds 200)`),{port:s,child:{kill:()=>!0},stop(){}};c(`Port ${s} in use by an unresponsive process — killing it`),await Ob(s),await new Promise((m)=>setTimeout(m,2000))}let d=Ib(t,n),u=Db(i,{flags:"a"}),l=Rb("bash",["-lc",r],{cwd:d,stdio:["ignore","pipe","pipe"],detached:!1});l.stdout?.pipe(u),l.stderr?.pipe(u);let p=!1,f=null;l.on("exit",(m)=>{p=!0,f=m}),c(`Building (${r})...`);let h=Date.now()+a;while(Date.now()<h){if(p)throw Error(`Build process exited with code ${f} before the UI was ready.
|
|
1065
|
+
Check the build log: ${i}`);if(await cf(o))return c("UI ready"),{port:s,child:l,stop(){if(!p)l.kill("SIGTERM"),setTimeout(()=>{if(!p)l.kill("SIGKILL")},5000).unref();u.end()}};await new Promise((m)=>setTimeout(m,2000))}throw l.kill("SIGTERM"),u.end(),Error(`UI did not start within ${Math.round(a/1000)}s at ${o}
|
|
1066
|
+
Check the build log: ${i}`)}function $b(e){return new Promise((t)=>{let r=new Pb.Socket;r.setTimeout(1000),r.on("connect",()=>{r.destroy(),t(!0)}),r.on("timeout",()=>{r.destroy(),t(!1)}),r.on("error",()=>{t(!1)}),r.connect(e,"127.0.0.1")})}async function Ob(e){let{execSync:t}=await import("node:child_process");try{let r=t(`lsof -ti:${e}`,{encoding:"utf-8"}).trim();if(r)t(`kill ${r}`,{stdio:"pipe"})}catch{}}function cf(e){return new Promise((t)=>{let r=_b.get(e,{timeout:3000},(n)=>{t(n.statusCode===200),n.resume()});r.on("error",()=>t(!1)),r.on("timeout",()=>{r.destroy(),t(!1)})})}var lf=()=>{};import*as pf from"@midnightntwrk/ledger-v9";import{join as Mb}from"node:path";async function ff(e,t,r,n){let s=[];for(let o of e.prep){let i=Date.now();n.onStepStart(o);try{await Fb(o,e,t,r,n);let a=Date.now()-i;s.push({step:o,status:"pass",duration:a}),n.onStepComplete(o,"pass",a)}catch(a){let c=Date.now()-i,d=a.message;throw s.push({step:o,status:"fail",duration:c,error:d}),n.onStepComplete(o,"fail",c,d),Error(`Prep step "${o}" failed: ${d}`)}}return s}async function Fb(e,t,r,n,s){if(e==="cache-clear")return Ub(t);if(e==="localnet-up")return Lb(t,s);if(e.startsWith("balance:")){let o=parseInt(e.split(":")[1],10);return Bb(o,t,s)}if(e==="dust"||e==="dust-register"||e==="dust-wait")return Wb(t,s);if(e==="mn-serve")return jb(t,n,s);if(e==="build-and-serve")return Hb(t,r,n,s);throw Error(`Unknown prep step: ${e}`)}async function Ub(e){let t=e.network??"undeployed";rt(void 0,t)}async function Lb(e,t){let r=e.network??"undeployed",{config:n}=me({args:{command:"test",subcommand:void 0,positionals:[],flags:{network:r}}});await gd(r,n),t.onMessage(`Using the ledger-9 stack at ${n.node} (indexer ${n.indexer})`)}async function Bb(e,t,r){let n=t.network??"undeployed",{config:s}=me({args:{command:"test",subcommand:void 0,positionals:[],flags:{network:n}}});await Je(n,s);let o=ce(oe()),i=Buffer.from(o.seed,"hex"),a=o.addresses[n];r.onMessage("Checking balance...");let c=Fe((h,m)=>{r.onMessage(`SDK: ${m}`)}),d=Ue();yt(n,s.indexerWS);let u=Dt(a,n),l=await et(i,s,u);try{let h=await Rt(l,{syncMode:"lite",onProgress:(w,S)=>{if(S>0){let k=Math.min(Math.round(w/S*100),100);r.onMessage(`Syncing wallet... ${k}%`)}},onSyncDetail:(w)=>{r.onMessage(`Syncing wallet... (${w})`)}}),m=pf.unshieldedToken().raw,y=h.unshielded.balances[m]??0n;if(y>0n){r.onMessage(`Balance OK: ${y}`);try{await wt(a,n,l.facade)}catch{}return}}finally{d(),c();try{await We(l)}catch{}}if(n!=="undeployed")throw Error(`Wallet has 0 NIGHT on ${n}. Fund your wallet before running tests:
|
|
1067
1067
|
mn airdrop ${e} (if faucet available)
|
|
1068
|
-
Or transfer NIGHT from another wallet.`);r.onMessage(`Balance is 0. Airdropping ${e} NIGHT from genesis...`);let p=Buffer.from(ut,"hex"),f=Ie(p,n);await Rr({seedBuffer:p,networkConfig:s,recipientAddress:a,amountNight:e,onSync(h,m){},onDust(h){r.onMessage(`Dust: ${h}`)},onProving(){r.onMessage("Generating ZK proof...")},onSubmitting(){r.onMessage("Submitting airdrop transaction...")},onSyncWarning(h,m){r.onMessage(`Syncing genesis... (${m})`)}}),r.onMessage(`Airdropped ${e} NIGHT`)}async function
|
|
1068
|
+
Or transfer NIGHT from another wallet.`);r.onMessage(`Balance is 0. Airdropping ${e} NIGHT from genesis...`);let p=Buffer.from(ut,"hex"),f=Ie(p,n);await Rr({seedBuffer:p,networkConfig:s,recipientAddress:a,amountNight:e,onSync(h,m){},onDust(h){r.onMessage(`Dust: ${h}`)},onProving(){r.onMessage("Generating ZK proof...")},onSubmitting(){r.onMessage("Submitting airdrop transaction...")},onSyncWarning(h,m){r.onMessage(`Syncing genesis... (${m})`)}}),r.onMessage(`Airdropped ${e} NIGHT`)}async function Wb(e,t){let r=e.network??"undeployed",{config:n}=me({args:{command:"test",subcommand:void 0,positionals:[],flags:{network:r}}});await Je(r,n);let s=ce(oe()),o=Buffer.from(s.seed,"hex"),i=s.addresses[r],a=Fe(),c=Ue();yt(r,n.indexerWS);let d=Dt(i,r),u=await et(o,n,d);try{if(t.onMessage("Syncing wallet..."),await Rt(u,{syncMode:"lite"}),t.onMessage("Ensuring dust..."),(await at(u,(h)=>t.onMessage(`Dust: ${h}`))).alreadyAvailable){t.onMessage("Dust already available");try{await wt(i,r,u.facade)}catch{}return}t.onMessage("Dust registered. Waiting for coins to become available...");let p=await ks(u,uf);if(!tr(p)){if(r!=="undeployed")throw Error(`Dust not available on ${r}. Register dust and wait for it to generate:
|
|
1069
1069
|
mn dust register
|
|
1070
|
-
mn dust status (check until dustAvailable: true)`);throw Error(`Dust not available after ${
|
|
1071
|
-
`).filter(Boolean);e(`Found ${r.length} orphan chrome-devtools-mcp Chrome process(es), killing`);for(let n of r)try{
|
|
1070
|
+
mn dust status (check until dustAvailable: true)`);throw Error(`Dust not available after ${uf/1000}s. The chain may be slow — try again.`)}t.onMessage("Dust is available");try{await wt(i,r,u.facade)}catch{}}finally{c(),a();try{await We(u)}catch{}}}async function jb(e,t,r){r.onMessage("Starting mn serve...");let n=await Ps({port:void 0,network:e.network,onMessage:(s)=>r.onMessage(`[serve] ${s}`),dustWaitMs:fs});t.serveHandle=n,t.addCleanup(async()=>n.stop()),r.onMessage(`mn serve ready on port ${n.port}`)}async function Hb(e,t,r,n){if(!e.buildCmd){n.onMessage("No buildCmd in config, skipping build");return}let s=e.port??4173,o=e.url??`http://localhost:${s}/`,i=Mb(t,"tests","results",`build_${Date.now()}.log`),a=await df({dappDir:t,buildCmd:e.buildCmd,buildDir:e.buildDir,port:s,url:o,logFile:i,onMessage:(c)=>n.onMessage(`[build] ${c}`)});r.buildHandle=a,r.addCleanup(async()=>a.stop())}var uf=90000;var mf=E(()=>{Cn();rr();Pe();Ee();sr();tt();rr();bt();Xe();Pi();vr();lf()});import{execSync as gf,spawn as Gb}from"node:child_process";import{createWriteStream as Kb,existsSync as Jb,mkdirSync as Vb,readFileSync as qb}from"node:fs";import{dirname as zb,join as Yb}from"node:path";import{homedir as Xb}from"node:os";function Zb(){let e=Yb(Xb(),".claude.json");if(!Jb(e))return!1;try{let t=JSON.parse(qb(e,"utf-8"));return Boolean(t.mcpServers?.["chrome-devtools"])}catch{return!1}}function ev(e){let t;try{t=gf(`ps -ax -o pid,command | grep "${Qb}" | grep -v grep | awk '{print $1}'`,{encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()}catch{return}if(!t)return;let r=t.split(`
|
|
1071
|
+
`).filter(Boolean);e(`Found ${r.length} orphan chrome-devtools-mcp Chrome process(es), killing`);for(let n of r)try{gf(`kill ${n}`,{stdio:"pipe"})}catch{}}function Sa(e){let t=e.browserMode??"vision";if(t==="auto")return"vision";return t}async function hf(e){let{suite:t,prompt:r,dappDir:n,logFile:s,onMessage:o=()=>{}}=e,i=(t.timeout??600)*1000,a=Sa(t);if(a==="dom"||a==="script"){if(!Zb())throw Error(`Browser mode "${a}" requires the chrome-devtools MCP server, which is not registered in ~/.claude.json.
|
|
1072
1072
|
|
|
1073
1073
|
Install it:
|
|
1074
1074
|
claude mcp add chrome-devtools --scope user npx chrome-devtools-mcp@latest
|
|
1075
1075
|
|
|
1076
|
-
Then re-run the suite. Alternatively, switch the suite to "browserMode": "vision" `+"(no MCP needed, but slower — uses screenshots).");
|
|
1077
|
-
`),s}function
|
|
1076
|
+
Then re-run the suite. Alternatively, switch the suite to "browserMode": "vision" `+"(no MCP needed, but slower — uses screenshots).");ev(o)}Vb(zb(s),{recursive:!0});let c=Kb(s),d=[];if(a==="vision")d.push("--chrome");if(d.push("--dangerously-skip-permissions"),t.model)d.push("--model",t.model);if(t.effort)d.push("--effort",t.effort);let u=r;if(a==="dom")u=tv+r;else if(a==="script")u=rv+r;return d.push("-p",u),o(`Launching Claude (mode: ${a}, model: ${t.model??"default"}, timeout: ${t.timeout??600}s)`),new Promise((l)=>{let p=Gb("claude",d,{cwd:n,stdio:["inherit","pipe","inherit"]}),f=!1;p.stdout?.on("data",(m)=>{process.stdout.write(m),c.write(m)});let h=setTimeout(()=>{f=!0,o(`Timeout: test exceeded ${t.timeout??600}s`),p.kill("SIGTERM"),setTimeout(()=>{if(!p.killed)p.kill("SIGKILL")},1e4).unref()},i);p.on("close",(m)=>{clearTimeout(h),c.end(),l({exitCode:m??1,logFile:s,timedOut:f})}),p.on("error",(m)=>{clearTimeout(h),c.end(),o(nv(m)),l({exitCode:1,logFile:s,timedOut:!1})})})}function nv(e){if(e.code==="ENOENT")return'The browser strategy drives the dApp through the Claude Code CLI, and no "claude" command was found on PATH. Install Claude Code, or test from the command line instead: mn test create --strategy cli';return`Claude process error: ${e.message}`}var Qb="chrome-devtools-mcp/chrome-profile",tv="## Browser Automation Mode: DOM (Accessibility Tree)\n\nYou have chrome-devtools MCP tools available. You MUST follow these rules:\n\n1. Use `navigate_page` to open URLs in Chrome.\n2. Use `take_snapshot` to read the page — it returns a structured accessibility tree with element UIDs. This is your primary tool for understanding page state.\n3. Use `click`, `fill`, and `type_text` with element UIDs from the snapshot to interact with the page.\n4. Use `press_key` for keyboard input (Enter, Escape, Tab, etc.).\n5. Only use `take_screenshot` for final visual verification or when the accessibility tree is insufficient.\n6. Do NOT rely on screenshots for navigation — the accessibility tree is faster and more reliable.\n7. After each interaction, take a new `take_snapshot` to verify the result.\n\n---\n\n",rv="## Browser Automation Mode: Script (Canvas App)\n\nYou have chrome-devtools MCP tools available. This is a canvas-based app — the accessibility tree will be empty. You MUST follow these rules:\n\n1. Use `navigate_page` to open the URL in Chrome.\n2. Use `evaluate_script` to dispatch keyboard input via `window.dispatchEvent(new KeyboardEvent(...))`.\n3. Use `evaluate_script` to read DOM state (e.g., toast notifications via `document.querySelector`).\n4. Use `list_console_messages` to monitor app output (contract addresses, errors, status changes).\n5. Use `take_screenshot` at key checkpoints to verify visual state — but minimize usage (a few, not every step).\n6. Do NOT use `take_snapshot` — the accessibility tree is empty for canvas content.\n7. Between actions, use `take_screenshot` or `list_console_messages` to verify transitions — not rapid polling.\n\n---\n\n";var wf=()=>{};import{existsSync as sv,readFileSync as ov}from"node:fs";import iv from"node:net";async function yf(e,t){let r=[];for(let n of e)try{let s=await av(n,t),o=n.expect==="pass"?s:!s;r.push({id:n.id,status:o?"pass":"fail",message:o?void 0:`Expected ${n.expect}, got ${s?"pass":"fail"}`})}catch(s){r.push({id:n.id,status:"fail",message:s.message})}return r}async function av(e,t){switch(e.type){case"balance-changed":return cv(e,t);case"process-exit-code":return dv(e,t);case"port-listening":return lv(e);case"agent-report-no-failure":return pv(e,t);default:throw Error(`Unsupported assertion type: "${e.type}" (available in v2)`)}}function cv(e,t){if(t.preBalance===void 0||t.postBalance===void 0)throw Error("Balance data not available — balance:N prep step may not have run");let r=BigInt(t.preBalance),n=BigInt(t.postBalance),s=e.params.direction;if(s==="decreased")return n<r;if(s==="increased")return n>r;if(s==="unchanged")return n===r;return n!==r}function dv(e,t){if(t.processExitCode===void 0)throw Error("Process exit code not available");let r=e.params.code;return t.processExitCode===r}function lv(e){let t=e.params.port;return new Promise((r)=>{let n=new iv.Socket;n.setTimeout(2000),n.on("connect",()=>{n.destroy(),r(!0)}),n.on("timeout",()=>{n.destroy(),r(!1)}),n.on("error",()=>{r(!1)}),n.connect(t,"127.0.0.1")})}function pv(e,t){let r=e.params??{},n=r.logPath??t.agentLogPath;if(!n||!sv(n))return!0;let s;try{s=ov(n,"utf-8")}catch{return!0}let o=mv(s),i=r.markers??uv;for(let a of i)if(fv(o,a))return!1;return!0}function fv(e,t){if(/\s/.test(t)||/[^ -~]/.test(t))return e.toLowerCase().includes(t.toLowerCase());let r=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`\\b${r}\\b`,"i").test(e)}function mv(e){return e.replace(/```[\s\S]*?```/g,"").replace(/`[^`]*`/g,"")}var uv;var Sf=E(()=>{uv=["FAILED","❌","did not pass","test failed","overall: fail","result: fail"]});import{existsSync as gv,mkdirSync as hv,writeFileSync as wv,readFileSync as yv,readdirSync as Sv}from"node:fs";import{join as po}from"node:path";function vf(e,t){let r=po(t,bf);hv(r,{recursive:!0});let n=`${e.suite}_${e.timestamp.replace(/[:.]/g,"-")}.json`,s=po(r,n);return wv(s,JSON.stringify(e,null,2)+`
|
|
1077
|
+
`),s}function kf(e,t){let r=ba(e,t);return r.length>0?r[0]:null}function ba(e,t){let r=po(e,bf);if(!gv(r))return[];let n=Sv(r).filter((o)=>o.endsWith(".json")&&!o.startsWith(".")).filter((o)=>!t||o.startsWith(t+"_")),s=[];for(let o of n)try{let i=JSON.parse(yv(po(r,o),"utf-8"));if(bv(i))s.push(i)}catch{}return s.sort((o,i)=>i.timestamp.localeCompare(o.timestamp)),s}function bv(e){let t=e;return typeof t==="object"&&t!==null&&typeof t.suite==="string"&&typeof t.timestamp==="string"&&(t.status==="pass"||t.status==="fail")&&Array.isArray(t.prep)&&Array.isArray(t.assertions)}var bf="tests/results";var Cf=()=>{};import{execSync as vv}from"node:child_process";async function va(e,t){if(e.buildHandle)try{e.buildHandle.stop(),t?.("Stopped build process")}catch{t?.("Failed to stop build process (may have already exited)")}if(e.serveHandle)try{await e.serveHandle.stop(),t?.("Stopped mn serve")}catch{t?.("Failed to stop mn serve")}for(let r of e.cleanups.reverse())try{await r()}catch{}if(e.buildHandle?.port)kv(e.buildHandle.port,t)}function kv(e,t){try{vv(`osascript -e 'tell application "Google Chrome"
|
|
1078
1078
|
repeat with theWindow in every window
|
|
1079
1079
|
repeat with theTab in every tab of theWindow
|
|
1080
1080
|
if URL of theTab contains "localhost:${e}" then
|
|
@@ -1082,7 +1082,7 @@ Then re-run the suite. Alternatively, switch the suite to "browserMode": "vision
|
|
|
1082
1082
|
end if
|
|
1083
1083
|
end repeat
|
|
1084
1084
|
end repeat
|
|
1085
|
-
end tell'`,{timeout:5000,stdio:"pipe"}),t?.(`Closed Chrome tabs for localhost:${e}`)}catch{}}var
|
|
1085
|
+
end tell'`,{timeout:5000,stdio:"pipe"}),t?.(`Closed Chrome tabs for localhost:${e}`)}catch{}}var xf=()=>{};function Ef(e){switch(e["type-name"]){case"Uint":return 0;case"Bytes":{let t=e.length??32;return Array.from({length:t},()=>0)}case"Boolean":return!1;case"String":return"test";case"Opaque":return e.tsType==="string"?"test":null;case"Vector":return[];case"Map":return{};case"Set":return[];case"Option":return null;case"Tuple":return(e.types??[]).map(Ef);default:return null}}function ka(e){let t={};for(let r of e.arguments)t[r.name]=Ef(r.type);return t}function Ca(e,t){if((t.strategy??"cli")==="browser"){if(!t.browser)throw Error("Browser strategy requires browser options (port, buildCmd, buildDir?, url?)");return Rv(t,t.browser)}return Nv(e,t)}function Nv(e,t){let r=t.suiteName??Cv,n=t.network??Af,s=t.servePort??Tf;return{dappConfig:{name:t.contractName,network:n,prep:Nf},suite:{name:r,description:`Auto-generated CLI test suite for ${t.contractName}. Edit args and add ledger-field assertions to taste.`,strategy:"cli",timeout:t.timeoutSeconds??Ev},actions:{actions:Iv(e)},assertions:{post:[Rf(s)]},prompt:null,suiteName:r}}function Rv(e,t){let r=e.suiteName??xv,n=e.network??Af,s=e.servePort??Tf,o=t.url??`http://localhost:${t.port}/`,i={name:e.contractName,network:n,port:t.port,buildCmd:t.buildCmd,url:o,prep:Tv};if(t.buildDir)i.buildDir=t.buildDir;return{dappConfig:i,suite:{name:r,description:`Auto-generated browser test suite for ${e.contractName}. Edit prompt.md to describe the dApp-specific user flow.`,strategy:"browser",timeout:e.timeoutSeconds??Av,...t.browserMode?{browserMode:t.browserMode}:{}},actions:null,assertions:{post:[{id:"claude-exit-ok",type:"process-exit-code",params:{code:0},expect:"pass"},Rf(s),{id:"agent-no-failure",type:"agent-report-no-failure",params:{},expect:"pass"}]},prompt:Dv(e.contractName,o),suiteName:r}}function Rf(e){return{id:"serve-port-listening",type:"port-listening",params:{port:e},expect:"pass"}}function Dv(e,t){return`You are running an automated E2E test of ${e}.
|
|
1086
1086
|
|
|
1087
1087
|
The UI is at ${t} — open it in Chrome.
|
|
1088
1088
|
mn serve is running with --approve-all so contract calls will auto-approve.
|
|
@@ -1112,44 +1112,44 @@ Follow these steps:
|
|
|
1112
1112
|
|
|
1113
1113
|
If any step fails, report exactly what you see on screen and stop.
|
|
1114
1114
|
Take screenshots at each major step to document the test.
|
|
1115
|
-
`}function
|
|
1115
|
+
`}function Iv(e){let t=[{id:"deploy",type:"contract-deploy"},{id:"check-initial",type:"contract-state"}],r=e.filter((n)=>!n.pure);for(let n of r){let s={id:`call-${n.name}`,type:"contract-call",circuit:n.name};if(n.arguments.length>0)s.args=ka(n);t.push(s)}return t.push({id:"check-final",type:"contract-state"}),t}var Af="undeployed",Cv="cli-default",xv="ui-default",Ev=300,Av=600,Tf=9932,Nf,Tv;var xa=E(()=>{Nf=["cache-clear","localnet-up","balance:1000","dust","mn-serve"],Tv=[...Nf,"build-and-serve"]});import{existsSync as If,mkdirSync as _v,readFileSync as Pv,writeFileSync as Df}from"node:fs";import{join as Gr}from"node:path";function _f(e,t){let{dappDir:r,force:n=!1}=t,s=Gr(r,"tests","suites",e.suiteName),o=Gr(r,"dapp.test.json"),i=[{path:Gr(s,"suite.json"),kind:"json",body:e.suite},{path:Gr(s,"assertions.json"),kind:"json",body:e.assertions}];if(e.actions)i.push({path:Gr(s,"actions.json"),kind:"json",body:e.actions});if(e.prompt)i.push({path:Gr(s,"prompt.md"),kind:"text",body:e.prompt});if(!n){let u=i.filter((l)=>If(l.path)).map((l)=>l.path);if(u.length>0)throw Error(`Suite "${e.suiteName}" already exists at ${s}.
|
|
1116
1116
|
Pick a different suite name (--suite <name>) or pass --force to overwrite.
|
|
1117
1117
|
Existing files:
|
|
1118
1118
|
`+u.map((l)=>` - ${l}`).join(`
|
|
1119
|
-
`))}let a=
|
|
1119
|
+
`))}let a=Mv(o,e,n);_v(s,{recursive:!0});let c=[],d=[];if(a.action==="write")Df(o,JSON.stringify(a.config,null,2)+`
|
|
1120
1120
|
`),c.push(o);else d.push(o);for(let u of i){let l=u.kind==="json"?JSON.stringify(u.body,null,2)+`
|
|
1121
|
-
`:u.body;
|
|
1122
|
-
Fix or remove it (or pass --force to overwrite).`)}if(n.name!==t.dappConfig.name)throw Error(`${e} exists with name "${String(n.name)}" but this scaffold targets "${t.dappConfig.name}". Use --force to overwrite, or run from the right project directory.`);let s=
|
|
1121
|
+
`:u.body;Df(u.path,l),c.push(u.path)}return{written:c,preserved:d}}function Ov(e,t){if(!t.prep.includes(Ea))return null;let r={};for(let s of $v)if(t[s]!==void 0&&e[s]===void 0)Object.assign(r,{[s]:t[s]});let n=Array.isArray(e.prep)?e.prep:[];if(!n.includes(Ea))r.prep=[...n,Ea];return Object.keys(r).length>0?r:null}function Mv(e,t,r){if(r||!If(e))return{action:"write",config:t.dappConfig};let n;try{n=JSON.parse(Pv(e,"utf-8"))}catch(o){let i=o instanceof Error?o.message:String(o);throw Error(`${e} exists but is not valid JSON: ${i}
|
|
1122
|
+
Fix or remove it (or pass --force to overwrite).`)}if(n.name!==t.dappConfig.name)throw Error(`${e} exists with name "${String(n.name)}" but this scaffold targets "${t.dappConfig.name}". Use --force to overwrite, or run from the right project directory.`);let s=Ov(n,t.dappConfig);return s===null?{action:"preserve"}:{action:"write",config:{...n,...s}}}var $v,Ea="build-and-serve";var Pf=E(()=>{$v=["port","buildCmd","buildDir","url"]});import{existsSync as Of,readdirSync as Fv,readFileSync as Uv,statSync as Lv}from"node:fs";import{basename as Bv,extname as Wv,join as Mf,relative as jv}from"node:path";function Ff(e){let t=new Map;for(let r of Hv){let n=Mf(e,r);if(!Of(n))continue;Aa(n,e,t)}return[...t.values()].sort((r,n)=>r.name.localeCompare(n.name))}function Uf(e,t=e){if(!Of(e))return[];let r=new Map;return Aa(e,t,r),[...r.values()].sort((n,s)=>n.name.localeCompare(s.name))}function Aa(e,t,r){let n;try{n=Fv(e)}catch{return}for(let s of n){let o=Mf(e,s),i;try{i=Lv(o)}catch{continue}if(i.isDirectory()){if(Gv.has(s.toLowerCase()))continue;Aa(o,t,r);continue}if(Wv(s)!==$f)continue;if(s.endsWith(".test.tsx")||s.endsWith(".spec.tsx"))continue;let a=Bv(s,$f);if(!Kv(a,o))continue;let c=Vv(a);if(r.has(c))continue;r.set(c,{name:c,component:a,path:o,relativePath:jv(t,o)})}}function Kv(e,t){if(!/^[A-Z][A-Za-z0-9]*$/.test(e))return!1;let r;try{r=Uv(t,"utf-8")}catch{return!1}return Jv.test(r)}function Vv(e){return e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").replace(/([A-Z]+)([A-Z][a-z])/g,"$1-$2").toLowerCase()}var Hv,$f=".tsx",Gv,Jv;var Ta=E(()=>{Hv=["src/components","src/pages","src/screens","src/views"];Gv=new Set(["layout","layouts","shared","common","ui","icons","styles"]);Jv=/\bexport\s+(default\b|const\s+[A-Z]|function\s+[A-Z])/});import{existsSync as qv,statSync as zv}from"node:fs";import*as Lf from"node:readline";function Bf(){return process.stdin.isTTY===!0}function nt(e,t){let r=Lf.createInterface({input:process.stdin,output:process.stderr}),n=t!==void 0?g(` [${t}]`):"";return new Promise((s)=>{r.question(` ${e}${n}: `,(o)=>{r.close();let i=o.trim();s(i===""&&t!==void 0?t:i)})})}async function Wf(){process.stderr.write(`
|
|
1123
1123
|
`+X("Test scaffold setup")+`
|
|
1124
1124
|
`);for(;;){let e=(await nt("Strategy? cli or ui","cli")).toLowerCase();if(e==="cli")return"cli";if(e==="ui"||e==="browser")return"browser";process.stderr.write(g(` Unknown strategy "${e}". Pick "cli" or "ui".
|
|
1125
|
-
`))}}async function
|
|
1125
|
+
`))}}async function jf(e={}){process.stderr.write(`
|
|
1126
1126
|
`+g("Browser test scaffold needs your dApp UI details:")+`
|
|
1127
|
-
`);let t=e.port!==void 0?String(e.port):await nt("Dev server port","4173"),r=parseInt(t,10);if(!Number.isFinite(r)||r<=0||r>65535)throw Error(`Invalid port "${t}" — must be a number between 1 and 65535.`);let n=e.buildCmd??await nt("Build command","npm run dev");if(!n)throw Error("Build command is required for browser strategy.");let s=e.buildDir!==void 0?e.buildDir:await nt("Build dir (blank for project root)",""),o=s===""?void 0:s,i=e.url??await nt("URL",`http://localhost:${r}/`),a=e.browserMode??await
|
|
1127
|
+
`);let t=e.port!==void 0?String(e.port):await nt("Dev server port","4173"),r=parseInt(t,10);if(!Number.isFinite(r)||r<=0||r>65535)throw Error(`Invalid port "${t}" — must be a number between 1 and 65535.`);let n=e.buildCmd??await nt("Build command","npm run dev");if(!n)throw Error("Build command is required for browser strategy.");let s=e.buildDir!==void 0?e.buildDir:await nt("Build dir (blank for project root)",""),o=s===""?void 0:s,i=e.url??await nt("URL",`http://localhost:${r}/`),a=e.browserMode??await Yv();return{port:r,buildCmd:n,buildDir:o,url:i,browserMode:a}}async function Yv(){process.stderr.write(`
|
|
1128
1128
|
`+X("Browser mode — how should Claude perceive the page?")+`
|
|
1129
1129
|
`),process.stderr.write(` ${g("1.")} dom ${g("— accessibility tree (text). Fast. HTML / React / Vue UIs.")}
|
|
1130
1130
|
`),process.stderr.write(` ${g("2.")} vision ${g("— screenshots. Slow. Canvas games (no DOM).")}
|
|
1131
1131
|
`),process.stderr.write(` ${g("3.")} script ${g("— direct JS. Fastest. Needs dApp-side hooks (advanced).")}
|
|
1132
1132
|
`),process.stderr.write(g(` dom and script need chrome-devtools-mcp installed.
|
|
1133
1133
|
`));for(;;){let e=(await nt("Mode","dom")).toLowerCase().trim();if(e==="1"||e==="dom")return"dom";if(e==="2"||e==="vision")return"vision";if(e==="3"||e==="script")return"script";process.stderr.write(ee(` Pick 1 (dom), 2 (vision), or 3 (script).
|
|
1134
|
-
`))}}async function
|
|
1134
|
+
`))}}async function Hf(e){let t=e.filter((r)=>!r.pure);if(t.length===0){process.stderr.write(g(` No impure circuits in this contract — nothing to test as a write path.
|
|
1135
1135
|
`));return}process.stderr.write(`
|
|
1136
1136
|
`+X("Pick the circuit this suite will exercise:")+`
|
|
1137
1137
|
`);for(let r=0;r<t.length;r++)process.stderr.write(` ${g(`${r+1}.`)} ${t[r].name}
|
|
1138
1138
|
`);process.stderr.write(g(` (or type "skip" to scaffold all circuits without AI)
|
|
1139
1139
|
`));for(;;){let r=(await nt("Circuit","1")).trim();if(r.toLowerCase()==="skip")return;let n=parseInt(r,10);if(Number.isFinite(n)&&n>=1&&n<=t.length)return t[n-1];let s=t.find((o)=>o.name===r);if(s)return s;process.stderr.write(g(` Pick a number 1–${t.length}, the circuit name, or "skip".
|
|
1140
|
-
`))}}async function
|
|
1140
|
+
`))}}async function Na(e){if(e.length===0)return Xv();process.stderr.write(`
|
|
1141
1141
|
`+X("Pick the screen this suite will test:")+`
|
|
1142
1142
|
`);for(let t=0;t<e.length;t++)process.stderr.write(` ${g(`${t+1}.`)} ${e[t].name} ${g(`(${e[t].relativePath})`)}
|
|
1143
1143
|
`);process.stderr.write(g(` (or type "skip" to scaffold a generic prompt.md without AI)
|
|
1144
1144
|
`));for(;;){let t=(await nt("Screen","1")).trim();if(t.toLowerCase()==="skip")return;let r=parseInt(t,10);if(Number.isFinite(r)&&r>=1&&r<=e.length)return e[r-1];let n=e.find((s)=>s.name===t||s.component===t);if(n)return n;process.stderr.write(g(` Pick a number 1–${e.length}, the screen name, or "skip".
|
|
1145
|
-
`))}}async function
|
|
1145
|
+
`))}}async function Xv(){process.stderr.write(g(`
|
|
1146
1146
|
Could not auto-discover screens (no src/components, src/pages, or src/screens under the build dir).
|
|
1147
|
-
`));for(;;){let e=(await nt('Path to a .tsx file or a UI directory (or "skip")')).trim();if(e.toLowerCase()==="skip"||e==="")return;if(!
|
|
1148
|
-
`));continue}let t;try{t
|
|
1149
|
-
`));continue}if(t.isDirectory()){let r=
|
|
1150
|
-
`));continue}return
|
|
1151
|
-
`));continue}return
|
|
1152
|
-
`))}}function
|
|
1147
|
+
`));for(;;){let e=(await nt('Path to a .tsx file or a UI directory (or "skip")')).trim();if(e.toLowerCase()==="skip"||e==="")return;if(!qv(e)){process.stderr.write(g(` No such path: ${e}
|
|
1148
|
+
`));continue}let t;try{t=zv(e)}catch{process.stderr.write(g(` Cannot stat: ${e}
|
|
1149
|
+
`));continue}if(t.isDirectory()){let r=Uf(e);if(r.length===0){process.stderr.write(g(` No PascalCase .tsx components in ${e}
|
|
1150
|
+
`));continue}return Na(r)}if(!e.endsWith(".tsx")){process.stderr.write(g(` Not a .tsx file: ${e}
|
|
1151
|
+
`));continue}return Qv(e)}}async function Gf(){let e=(await nt("What does success look like? (one line, optional)")).trim();return e===""?void 0:e}async function Ra(e){for(;;){let t=(await nt("Suite name",e)).trim();if(Zv(t))return t;process.stderr.write(ee(` Suite names must be kebab-case (a–z, 0–9, dashes, underscores). Try again.
|
|
1152
|
+
`))}}function Zv(e){return/^[a-z0-9][a-z0-9_-]{0,63}$/.test(e)}function Qv(e){let r=(e.split("/").pop()??e).replace(/\.tsx$/,"");return{name:r.replace(/([a-z0-9])([A-Z])/g,"$1-$2").replace(/([A-Z]+)([A-Z][a-z])/g,"$1-$2").toLowerCase(),component:r,path:e,relativePath:e}}var Kf=E(()=>{Ta()});function qf(e){let{contractName:t,contractSummary:r,contractSource:n,targetCircuit:s,goal:o,witnessDependentCircuits:i}=e,a=i&&i.size>0?`
|
|
1153
1153
|
## Circuits NOT testable from a CLI suite
|
|
1154
1154
|
|
|
1155
1155
|
These circuits call witnesses that read from private state. In a
|
|
@@ -1254,9 +1254,9 @@ Args coercion the runner applies (so JSON arg values can be):
|
|
|
1254
1254
|
- [0..255] int array → Uint8Array for Bytes<N>
|
|
1255
1255
|
- object → recurses into Struct fields
|
|
1256
1256
|
|
|
1257
|
-
${
|
|
1257
|
+
${Vf}
|
|
1258
1258
|
|
|
1259
|
-
Now produce the JSON.`}function
|
|
1259
|
+
Now produce the JSON.`}function zf(e){let{contractName:t,contractSummary:r,screenComponent:n,screenSource:s,relatedSources:o,url:i,goal:a}=e,c=(o??[]).map((l)=>`
|
|
1260
1260
|
--- ${l.path} ---
|
|
1261
1261
|
${l.source}
|
|
1262
1262
|
--- end ${l.path} ---`).join(`
|
|
@@ -1333,26 +1333,26 @@ A JSON object with three keys:
|
|
|
1333
1333
|
chain (e.g. ledger-field on a contract-state read).
|
|
1334
1334
|
- description: one short sentence summarising what this suite verifies.
|
|
1335
1335
|
|
|
1336
|
-
${
|
|
1336
|
+
${Vf}
|
|
1337
1337
|
|
|
1338
|
-
Now produce the JSON.`}function
|
|
1339
|
-
`)}var
|
|
1338
|
+
Now produce the JSON.`}function Da(e){let{name:t,circuits:r,witnesses:n}=e,s=[`Contract: ${t}`];if(r.length>0){s.push("","Circuits:");for(let o of r){let i=o.arguments.length===0?"()":"("+o.arguments.map((a)=>`${a.name}: ${a.type["type-name"]}`).join(", ")+")";s.push(` ${o.pure?"pure ":"impure"} ${o.name}${i}`)}}if(n.length>0){s.push("","Witnesses:");for(let o of n){let i=o.arguments.length===0?"()":"("+o.arguments.map((a)=>`${a.name}: ${a.type["type-name"]}`).join(", ")+")";s.push(` ${o.name}${i}`)}}return s.join(`
|
|
1339
|
+
`)}var Jf="```json",Vf;var Yf=E(()=>{Vf=`Output rules:
|
|
1340
1340
|
- Reply with EXACTLY one ${"```json"} ... \`\`\` fenced code block.
|
|
1341
1341
|
- Inside the fence: valid JSON, nothing else (no comments, no trailing text).
|
|
1342
1342
|
- Fields you don't know about: omit them. Don't invent fields.
|
|
1343
1343
|
- Use only the circuit / ledger field names that appear in the inputs below.
|
|
1344
|
-
- Be concise — fewer, well-named actions beat many vague ones.`});function Kr(e,t){if(t.length===0)return{byCircuit:new Map};let r=
|
|
1345
|
-
`)}var
|
|
1344
|
+
- Be concise — fewer, well-named actions beat many vague ones.`});function Kr(e,t){if(t.length===0)return{byCircuit:new Map};let r=rk(e),n=nk(r);if(n.size===0)return{byCircuit:new Map};let s=new Set(t),o=new Map,i=new Map;for(let[d,u]of n){o.set(d,new Set),i.set(d,new Set);for(let l of ok(u.body,u.argNames))if(s.has(l))o.get(d).add(l);else if(n.has(l))i.get(d).add(l)}let a=!0;while(a){a=!1;for(let[d,u]of i){let l=o.get(d);for(let p of u)for(let f of o.get(p)??[])if(!l.has(f))l.add(f),a=!0}}let c=new Map;for(let[d,u]of n){if(!u.isCircuit)continue;let l=o.get(d);if(l&&l.size>0)c.set(d,[...l].sort())}return{byCircuit:c}}function rk(e){return e.replace(tk,"").replace(ek,"")}function nk(e){let t=new Map,r=/\b(circuit|function)\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(([^)]*)\)/gms,n;while((n=r.exec(e))!==null){let s=n[1],o=n[2],i=n[3],a=n.index+n[0].length,c=e.indexOf("{",a);if(c<0)continue;let d=1,u=c+1;for(;u<e.length&&d>0;u++){let f=e[u];if(f==="{")d++;else if(f==="}")d--}if(d!==0)continue;let l=e.slice(c+1,u-1),p=sk(i);t.set(o,{body:l,argNames:p,isCircuit:s==="circuit"})}return t}function sk(e){let t=new Set;for(let r of e.split(",")){let n=r.trim();if(!n)continue;let s=n.indexOf(":"),o=s>-1?n.slice(0,s).trim():n;if(/^[A-Za-z_][A-Za-z0-9_]*$/.test(o))t.add(o)}return t}function ok(e,t){let r=new Set,n=/\b([A-Za-z_][A-Za-z0-9_]*)\s*\(/g,s;while((s=n.exec(e))!==null){let o=s[1];if(ik.has(o)||t.has(o))continue;r.add(o)}return r}var ek,tk,ik;var fo=E(()=>{ek=/\/\/[^\n]*/g,tk=/\/\*[\s\S]*?\*\//g;ik=new Set(["if","for","while","switch","return","new","assert","disclose","transientHash","persistentHash","ownPublicKey","publicKey","Map","Set","Vector","Tuple","Option","Bytes","Field","Uint","Boolean"])});var im={};ve(im,{claudeSubprocessRunner:()=>_a,findContractSourcePath:()=>Pa,generateCliScaffoldWithAI:()=>yk,generateUiScaffoldWithAI:()=>Sk,isClaudeAvailable:()=>fk});import{execFileSync as ak,spawn as ck}from"node:child_process";import{existsSync as Ia,readdirSync as dk,readFileSync as Qf}from"node:fs";import{dirname as Jr,join as mo}from"node:path";function fk(){try{return ak("claude",["--version"],{stdio:"ignore",timeout:5000}),!0}catch{return!1}}function nm(e){let r=new RegExp("```json\\s*\\n([\\s\\S]*?)\\n```").exec(e);if(!r)throw Error(`Claude response did not contain a ${Jf} ... \`\`\` fenced block. First 200 chars: ${e.slice(0,200)}`);try{return JSON.parse(r[1])}catch(n){let s=n instanceof Error?n.message:String(n);throw Error(`JSON inside the fence failed to parse: ${s}`)}}function mk(e,t){if(!e||typeof e!=="object")throw Error("AI response must be an object");if(typeof e.description!=="string"||!e.description)throw Error("AI response missing string `description`");if(!e.assertions||!Array.isArray(e.assertions.post))throw Error("AI response missing `assertions.post` array");let r=hk(e);if(!r)throw Error("AI response missing actions — expected either `actions: [...]` (top-level array) "+"or `actions: { actions: [...] }` (wrapped). Got: "+JSON.stringify(e.actions??null).slice(0,200));let n=new Map(t.circuits.map((s)=>[s.name,s]));for(let s of r){if(s.type!=="contract-call"||!s.circuit)continue;let o=n.get(s.circuit);if(!o)throw Error(`AI response references unknown circuit "${s.circuit}". Valid circuits: ${[...n.keys()].join(", ")||"(none)"}`);gk(s,o)}return{actions:r}}function gk(e,t){if(t.arguments.length===0)return;let r=e.args??{};for(let n of t.arguments){let s=r[n.name];if(s===void 0)throw Error(`Action "${e.id}" (circuit ${t.name}) is missing required arg "${n.name}" of type ${n.type["type-name"]}. Declared args: ${t.arguments.map((i)=>`${i.name}: ${i.type["type-name"]}`).join(", ")}`);let o=n.type["type-name"];if((o==="Struct"||o==="Alias")&&(s===null||typeof s!=="object"||Array.isArray(s)))throw Error(`Action "${e.id}" (circuit ${t.name}) arg "${n.name}" must be an object for ${o} type; got ${s===null?"null":typeof s}. Read the contract source to find the inner field names.`)}}function hk(e){if(Array.isArray(e.actions))return e.actions;let t=e.actions;if(t&&Array.isArray(t.actions))return t.actions;return null}function wk(e){if(!e||typeof e!=="object")throw Error("AI response must be an object");if(typeof e.description!=="string"||!e.description)throw Error("AI response missing string `description`");if(typeof e.prompt!=="string"||!e.prompt.trim())throw Error("AI response missing non-empty `prompt`");if(!e.assertions||!Array.isArray(e.assertions.post))throw Error("AI response missing `assertions.post` array")}async function yk(e,t=_a){let r=e.contractSourcePath&&Ia(e.contractSourcePath)?Qf(e.contractSourcePath,"utf-8"):void 0,n=e.contract.witnesses.map((w)=>w.name),s=r?Kr(r,n).byCircuit:new Map,o=e.targetCircuit?ka(e.targetCircuit):void 0,i=qf({contractName:e.contract.name,contractSummary:Da({name:e.contract.name,circuits:e.contract.circuits,witnesses:e.contract.witnesses}),contractSource:r,targetCircuit:e.targetCircuit,startingArgs:o,witnessDependentCircuits:s,goal:e.goal}),a=await t(i),c=nm(a),d=mk(c,e.contract),u=e.suiteName??(e.targetCircuit?`cli-${e.targetCircuit.name.toLowerCase().replace(/_/g,"-")}`:`cli-${om(e.goal)??"ai"}`),l=e.network??em,p=e.servePort??tm,f={name:e.contract.name,network:l,prep:rm},h={name:u,description:c.description,strategy:"cli",timeout:lk},m=bk(c.assertions,p),y=[...s.entries()].filter(([w])=>w!==e.targetCircuit?.name).map(([w,S])=>({name:w,reason:`uses witness ${S.join(", ")} (private state — UI-only)`}));return{dappConfig:f,suite:h,actions:d,assertions:m,prompt:null,suiteName:u,excludedCircuits:y.length>0?y:void 0}}async function Sk(e,t=_a){let r=e.screen?Qf(e.screen.path,"utf-8"):void 0,n=zf({contractName:e.contract.name,contractSummary:Da({name:e.contract.name,circuits:e.contract.circuits,witnesses:e.contract.witnesses}),screenComponent:e.screen?.component,screenSource:r,relatedSources:e.relatedSources,url:e.url,goal:e.goal}),s=await t(n),o=nm(s);wk(o);let i=e.suiteName??(e.screen?`ui-${e.screen.name}`:`ui-${om(e.goal)??"ai"}`),a=e.network??em,c=e.servePort??tm,d=e.url,u={name:e.contract.name,network:a,port:e.port,buildCmd:e.buildCmd,url:d,prep:pk};if(e.buildDir)u.buildDir=e.buildDir;let l={name:i,description:o.description,strategy:"browser",timeout:uk,...e.browserMode?{browserMode:e.browserMode}:{}},p=vk(o.assertions,c);return{dappConfig:u,suite:l,actions:null,assertions:p,prompt:o.prompt,suiteName:i}}function sm(e){let t=e.params;return typeof t?.port==="number"?t.port:void 0}function bk(e,t){if(e.post.some((n)=>n.type==="port-listening"&&sm(n)===t))return e;return{...e,post:[...e.post,{id:"serve-port-listening",type:"port-listening",params:{port:t},expect:"pass"}]}}function vk(e,t){let r=e.post;if(!r.some((i)=>i.type==="process-exit-code"))r=[...r,{id:"claude-exit-ok",type:"process-exit-code",params:{code:0},expect:"pass"}];if(!r.some((i)=>i.type==="port-listening"&&sm(i)===t))r=[...r,{id:"serve-port-listening",type:"port-listening",params:{port:t},expect:"pass"}];if(!r.some((i)=>i.type==="agent-report-no-failure"))r=[...r,{id:"agent-no-failure",type:"agent-report-no-failure",params:{},expect:"pass"}];return{...e,post:r}}function om(e){if(!e)return;let t=e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,32);return t.length>=2?t:void 0}function Pa(e){let t=e.split("/").pop(),r=[Jr(e),mo(Jr(e),"src"),Jr(Jr(e)),mo(Jr(Jr(e)),"src")];for(let n of r){if(!Ia(n))continue;if(t){let i=mo(n,`${t}.compact`);if(Ia(i))return i}let s;try{s=dk(n)}catch{continue}let o=s.find((i)=>i.endsWith(".compact"));if(o)return mo(n,o)}return}var em="undeployed",tm=9932,lk=300,uk=600,rm,pk,Xf=300000,Zf=4194304,_a=(e)=>new Promise((t,r)=>{let n=ck("claude",["--print"],{stdio:["pipe","pipe","pipe"]}),s="",o="",i=0,a=!1,c=setTimeout(()=>{n.kill("SIGTERM"),r(Error(`claude --print timed out after ${Xf/1000}s`))},Xf);n.stdout?.on("data",(d)=>{if(i+=d.length,i>Zf){a=!0,n.kill("SIGTERM");return}s+=d.toString()}),n.stderr?.on("data",(d)=>{o+=d.toString()}),n.on("error",(d)=>{if(clearTimeout(c),d.code==="ENOENT"){r(Error("claude CLI not found on PATH. Install Claude Code (npm install -g @anthropic-ai/claude-code) or run mn test create without --goal / --screen for the deterministic scaffolder."));return}r(d)}),n.on("exit",(d,u)=>{if(clearTimeout(c),a){r(Error(`claude --print response exceeded ${Zf/1024/1024}MB; aborted.`));return}if(u==="SIGTERM")return;if(d!==0){let l=o.trim().slice(0,300)||`(no stderr; exit ${d})`;r(Error(`claude --print exited with code ${d}: ${l}`));return}t(s)}),n.stdin?.write(e),n.stdin?.end()});var $a=E(()=>{Yf();xa();fo();rm=["cache-clear","localnet-up","balance:1000","dust","mn-serve"],pk=[...rm,"build-and-serve"]});async function am(e,t,r=1e4){try{let n=await fetch(e,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({query:"query($address: HexEncoded!) { contractAction(address: $address) { address } }",variables:{address:t}}),signal:AbortSignal.timeout(r)});if(!n.ok)return;let s=await n.json();if(s.errors!==void 0||s.data===void 0||s.data===null)return;return s.data.contractAction!==null&&s.data.contractAction!==void 0}catch{return}}import{existsSync as kk,mkdirSync as Ck,readFileSync as xk,writeFileSync as Ek}from"node:fs";import{join as cm}from"node:path";function dm(e,t){return cm(e,"tests","results",`.contract-cache-${t}.json`)}function lm(e,t,r){let n=dm(e,t);if(!kk(n))return;try{let s=JSON.parse(xk(n,"utf-8"));if(s.network!==r)return;return s.address}catch{return}}function um(e,t,r,n){Ck(cm(e,"tests","results"),{recursive:!0});let s={address:n,network:r,timestamp:new Date().toISOString()};Ek(dm(e,t),JSON.stringify(s,null,2)+`
|
|
1345
|
+
`)}var pm=()=>{};import{existsSync as Ak,readFileSync as Tk}from"node:fs";async function fm(e){let{actions:t,config:r,dappDir:n,suiteName:s,networkConfig:o,servePort:i,redeploy:a,onActionStart:c,onActionComplete:d,onMessage:u}=e,l=[],p=r.network??"undeployed",f;if(!a){if(f=lm(n,s,p),f&&await am(o.indexer,f)===!1)u?.(`The contract cached at ${f.slice(0,16)}... is not on this chain; deploying again`),f=void 0}let{info:h}=dt(n),m=Pk(h),y;for(let w of t){c?.(w);let S=Date.now();if(y&&(w.type==="contract-call"||w.type==="contract-state")){let k={id:w.id,type:w.type,status:"skip",duration:0,message:`cascaded skip — depends on ${y}`};l.push(k),d?.(w,k);continue}try{let k=await Nk(w,{dappDir:n,networkConfig:o,managedDir:h.managedDir,contractName:h.name,servePort:i,contractAddress:f,witnessDeps:m,onMessage:u});if(k.contractAddress){if(f=k.contractAddress,um(n,s,p,f),w.type==="contract-deploy")y=void 0}let T=Date.now()-S,N={...k,duration:T};if(l.push(N),d?.(w,N),k.status==="skip"&&w.type==="contract-call")y=`skipped action "${w.id}"`}catch(k){let T=Date.now()-S,N={id:w.id,type:w.type,status:"fail",duration:T,message:k.message};l.push(N),d?.(w,N);break}}return l}async function Nk(e,t){switch(e.type){case"contract-deploy":return Rk(e,t);case"contract-call":return Dk(e,t);case"contract-state":return Ik(e,t);case"wallet-cmd":return _k(e,t);default:throw Error(`Unknown action type: ${e.type}`)}}async function Rk(e,t){if(t.contractAddress)return{id:e.id,type:e.type,status:"pass",duration:0,contractAddress:t.contractAddress,message:`Reusing cached contract ${t.contractAddress.slice(0,16)}...`};let r=await Ls({dappDir:t.dappDir,networkConfig:t.networkConfig,managedDir:t.managedDir,contractName:t.contractName,servePort:t.servePort,onMessage:t.onMessage});return{id:e.id,type:e.type,status:"pass",duration:0,contractAddress:r.contractAddress,message:`Deployed at ${r.contractAddress.slice(0,16)}...`}}async function Dk(e,t){if(!t.contractAddress)throw Error(`Action "${e.id}": no contract address. Add a contract-deploy action first.`);if(!e.circuit)throw Error(`Action "${e.id}": missing circuit name.`);let r=t.witnessDeps.get(e.circuit);if(r&&r.length>0)return{id:e.id,type:e.type,status:"skip",duration:0,message:"not CLI-testable — circuit reads private state via witness "+`${r.join(", ")}. Cover with mn test create --strategy ui.`};let n;try{n=await $r({dappDir:t.dappDir,networkConfig:t.networkConfig,managedDir:t.managedDir,contractName:t.contractName,contractAddress:t.contractAddress,onMessage:()=>{}})}catch{}let s=e.args?Object.values(e.args):[];await Bs({dappDir:t.dappDir,networkConfig:t.networkConfig,managedDir:t.managedDir,contractName:t.contractName,contractAddress:t.contractAddress,circuit:e.circuit,args:s,servePort:t.servePort,onMessage:t.onMessage});let o;try{o=await $r({dappDir:t.dappDir,networkConfig:t.networkConfig,managedDir:t.managedDir,contractName:t.contractName,contractAddress:t.contractAddress,onMessage:()=>{}})}catch{}return{id:e.id,type:e.type,status:"pass",duration:0,message:`${e.circuit} called`,stateBefore:n,stateAfter:o}}async function Ik(e,t){if(!t.contractAddress)throw Error(`Action "${e.id}": no contract address. Add a contract-deploy action first.`);let r=await $r({dappDir:t.dappDir,networkConfig:t.networkConfig,managedDir:t.managedDir,contractName:t.contractName,contractAddress:t.contractAddress,onMessage:t.onMessage});if(e.assert){let n=[];for(let[s,o]of Object.entries(e.assert)){let i=r.fields[s];if(i===void 0){let a=r.maps[s];if(a)Oa(s,BigInt(a.size),o,n);else n.push(`Field "${s}" not found in ledger state`);continue}try{let a=BigInt(i);Oa(s,a,o,n)}catch{Oa(s,i,o,n)}}if(n.length>0)throw Error(`State assertion failed:
|
|
1346
1346
|
${n.join(`
|
|
1347
|
-
`)}`)}return{id:e.id,type:e.type,status:"pass",duration:0,message:`State checked (${Object.keys(r.fields).length} fields, ${Object.keys(r.maps).length} maps)`,stateAfter:r}}function
|
|
1347
|
+
`)}`)}return{id:e.id,type:e.type,status:"pass",duration:0,message:`State checked (${Object.keys(r.fields).length} fields, ${Object.keys(r.maps).length} maps)`,stateAfter:r}}function Oa(e,t,r,n){for(let[s,o]of Object.entries(r)){let i=typeof o==="number"?BigInt(o):o;if(typeof t==="bigint"&&(typeof i==="bigint"||typeof i==="number")){let a=BigInt(i);switch(s){case">":if(!(t>a))n.push(`${e}: expected > ${a}, got ${t}`);break;case">=":if(!(t>=a))n.push(`${e}: expected >= ${a}, got ${t}`);break;case"<":if(!(t<a))n.push(`${e}: expected < ${a}, got ${t}`);break;case"<=":if(!(t<=a))n.push(`${e}: expected <= ${a}, got ${t}`);break;case"==":if(t!==a)n.push(`${e}: expected == ${a}, got ${t}`);break;case"!=":if(t===a)n.push(`${e}: expected != ${a}, got ${t}`);break;default:n.push(`${e}: unknown operator "${s}"`)}}else{let a=String(i);switch(s){case"==":if(t!==a)n.push(`${e}: expected == "${a}", got "${t}"`);break;case"!=":if(t===a)n.push(`${e}: expected != "${a}", got "${t}"`);break;default:n.push(`${e}: operator "${s}" not supported for string values`)}}}}async function _k(e,t){return{id:e.id,type:e.type,status:"pass",duration:0,message:`wallet-cmd: ${e.cmd??"no command"} (not yet implemented)`}}function Pk(e){if(e.witnesses.length===0)return new Map;let t=Pa(e.managedDir);if(!t||!Ak(t))return new Map;let r=Tk(t,"utf-8"),n=e.witnesses.map((s)=>s.name);return Kr(r,n).byCircuit}function mm(e,t){if(!e||!t)return[];let r=[],n=new Set([...Object.keys(e.fields),...Object.keys(t.fields)]);for(let o of n){let i=e.fields[o]??"(absent)",a=t.fields[o]??"(absent)";if(i!==a)r.push({field:o,before:i,after:a})}let s=new Set([...Object.keys(e.maps),...Object.keys(t.maps)]);for(let o of s){let i=e.maps[o]?.size??"0",a=t.maps[o]?.size??"0";if(i!==a)r.push({field:`${o} (entries)`,before:i,after:a})}return r}var gm=E(()=>{Mr();Fn();fo();$a();pm()});var bm={};ve(bm,{default:()=>ym});import{join as hm}from"node:path";import{mkdirSync as $k}from"node:fs";function Ok(e){return wm.includes(e)}async function ym(e,t){let r=e.subcommand;if(!r||!Ok(r))throw new R(`Usage: midnight test <${wm.join("|")}>
|
|
1348
1348
|
|
|
1349
1349
|
create Generate dapp.test.json + a CLI test suite from the contract
|
|
1350
1350
|
run Run test suites for the current dApp
|
|
1351
1351
|
list List available test suites
|
|
1352
1352
|
results Show latest test results
|
|
1353
1353
|
|
|
1354
|
-
Run from the root of a dApp project containing dapp.test.json.`);let n=D(e,"json");switch(r){case"create":return
|
|
1355
|
-
`+
|
|
1354
|
+
Run from the root of a dApp project containing dapp.test.json.`);let n=D(e,"json");switch(r){case"create":return Bk(e,n);case"run":return Gk(e,n,t);case"list":return Kk(n);case"results":return Jk(e,n)}}function Mk(e){let t=(e??"").toLowerCase();if(t==="")return;if(t==="cli"||t==="browser")return t;if(t==="ui")return"browser";throw new R(`Unknown strategy "${e}". Use "cli" or "ui".`)}function Fk(e){return e==="preprod"||e==="preview"||e==="undeployed"?e:void 0}function Uk(e){let t={},r=C(e,"port");if(r!==void 0){let a=parseInt(r,10);if(!Number.isFinite(a)||a<=0||a>65535)throw new R(`Invalid --port "${r}" — must be 1–65535.`);t.port=a}let n=C(e,"build-cmd");if(n!==void 0)t.buildCmd=n;let s=C(e,"build-dir");if(s!==void 0)t.buildDir=s;let o=C(e,"url");if(o!==void 0)t.url=o;let i=C(e,"browser-mode");if(i!==void 0){if(i!=="dom"&&i!=="vision"&&i!=="script"&&i!=="auto")throw new R(`Invalid --browser-mode "${i}" — must be dom, vision, or script.`);t.browserMode=i}return t}function Lk(e){if(e.port===void 0||e.buildCmd===void 0)throw new R("Browser strategy needs --port and --build-cmd (and optionally --build-dir, --url) when running non-interactively.");return{port:e.port,buildCmd:e.buildCmd,buildDir:e.buildDir,url:e.url}}async function Bk(e,t){let{resolve:r}=await import("node:path");await Promise.resolve().then(() => Fn());await Promise.resolve().then(() => xa());await Promise.resolve().then(() => Pf());let i=await Promise.resolve().then(() => (Kf(),{}));await Promise.resolve();let m=await Promise.resolve().then(() => ($a(),im));await Promise.resolve().then(() => Ta());let w=r(C(e,"path")??process.cwd()),S=C(e,"name"),k=C(e,"suite"),T=Fk(C(e,"network")),N=D(e,"force"),L=!t&&Bf(),J=C(e,"goal"),Y=C(e,"screen"),V=D(e,"no-ai"),O=Mk(C(e,"strategy"))??(L?await Wf():"cli"),le;if(O==="browser"){let Re=Uk(e);le=L?await jf(Re):Lk(Re)}let{info:ge}=dt(w,S),So=!V&&m.isClaudeAvailable(),cr=!V&&(J!==void 0||Y!==void 0||L&&So),Se=cr?await Wk({strategy:O,info:ge,dappDir:w,browser:le,network:T,suiteName:k,goalFlag:J,screenFlag:Y,interactive:L,jsonMode:t,ai:m,promptCircuit:Hf,promptScreen:Na,promptGoal:Gf,promptSuiteName:Ra,discoverScreens:Ff})??Ca(ge.circuits,{contractName:ge.name,suiteName:k,strategy:O,browser:le,network:T}):Ca(ge.circuits,{contractName:ge.name,suiteName:k,strategy:O,browser:le,network:T});if(L&&!k){let Re=await Ra(Se.suiteName);if(Re!==Se.suiteName)Se.suiteName=Re,Se.suite.name=Re}let dr=_f(Se,{dappDir:w,force:N});if(t){I({subcommand:"create",contractName:ge.name,suiteName:Se.suiteName,strategy:O,aiAssisted:cr&&Se.suiteName!=="cli-default"&&Se.suiteName!=="ui-default",written:dr.written,excludedCircuits:Se.excludedCircuits});return}process.stderr.write(`
|
|
1355
|
+
`+B(`Test scaffold: ${ge.name}`)+`
|
|
1356
1356
|
|
|
1357
1357
|
`);for(let Re of dr.written)process.stderr.write(` ${z("✓")} ${Re}
|
|
1358
1358
|
`);let Mt=O==="browser"?{file:"prompt.md",hint:"verify the UI steps match your dApp — exact button labels, expected screens, success criteria. Claude follows these literally."}:{file:"actions.json",hint:'review args — placeholder values like 0 may violate contract assertions (e.g. "amount > 0").'};if(Se.excludedCircuits&&Se.excludedCircuits.length>0){process.stderr.write(`
|
|
@@ -1367,50 +1367,50 @@ Run from the root of a dApp project containing dapp.test.json.`);let n=D(e,"json
|
|
|
1367
1367
|
`),process.stderr.write(g(" Run ")+X(`mn test run --suite ${Se.suiteName}`)+`
|
|
1368
1368
|
`),process.stderr.write(g(" List ")+X("mn test list")+g(" (see every suite in this project)")+`
|
|
1369
1369
|
|
|
1370
|
-
`)}async function
|
|
1370
|
+
`)}async function Wk(e){try{if(!e.ai.isClaudeAvailable())return null;let t=e.goalFlag??(e.interactive?await e.promptGoal():void 0);if(e.strategy==="cli")return await jk(e,t);return await Hk(e,t)}catch(t){return process.stderr.write(`
|
|
1371
1371
|
${g("AI scaffold failed, falling back to deterministic:")} ${t.message}
|
|
1372
|
-
`),null}}async function
|
|
1372
|
+
`),null}}async function Sm(e,t,r){if(!r)return t();let n=H(e);try{let s=await t();return n.stop(),s}catch(s){throw n.fail("AI scaffold failed"),s}}async function jk(e,t){let r=e.interactive?await e.promptCircuit(e.info.circuits):e.info.circuits.find((s)=>!s.pure);if(!r&&!t)return null;let n=e.ai.findContractSourcePath(e.info.managedDir);if(r&&n&&e.interactive){let{readFileSync:s}=await import("node:fs");await Promise.resolve().then(() => fo());let i=s(n,"utf-8"),a=e.info.witnesses.map((u)=>u.name),d=Kr(i,a).byCircuit.get(r.name);if(d&&d.length>0)process.stderr.write(`
|
|
1373
1373
|
`+ee("!")+` ${r.name} calls ${d.join(", ")} — a witness that reads private state.
|
|
1374
1374
|
`),process.stderr.write(g(` The CLI suite will deploy + run, but expect a "Cannot read properties of undefined" failure
|
|
1375
1375
|
`)+g(` unless the dApp UI populates that state first. Consider --strategy ui instead.
|
|
1376
|
-
`))}return
|
|
1377
|
-
`+
|
|
1378
|
-
|
|
1379
|
-
`),process.stderr.write(
|
|
1380
|
-
`),n.port)process.stderr.write(
|
|
1381
|
-
`);if(a){if(process.stderr.write(
|
|
1382
|
-
`),process.stderr.write(
|
|
1383
|
-
`),a.suite.strategy==="browser"){let f=
|
|
1376
|
+
`))}return Sm("Asking Claude to scaffold the test suite (30–60s)...",()=>e.ai.generateCliScaffoldWithAI({contract:e.info,contractSourcePath:n,targetCircuit:r,goal:t,network:e.network,suiteName:e.suiteName}),e.interactive&&!e.jsonMode)}async function Hk(e,t){if(!e.browser)return null;let{join:r}=await import("node:path"),n=e.browser.buildDir?r(e.dappDir,e.browser.buildDir):e.dappDir,s=e.discoverScreens(n),o=e.screenFlag?s.find((i)=>i.name===e.screenFlag||i.component===e.screenFlag):e.interactive?await e.promptScreen(s):s[0];if(!o&&!t)return null;return Sm("Asking Claude to scaffold the test suite (30–60s)...",()=>e.ai.generateUiScaffoldWithAI({contract:e.info,screen:o,url:e.browser.url??`http://localhost:${e.browser.port}/`,port:e.browser.port,buildCmd:e.browser.buildCmd,buildDir:e.browser.buildDir,browserMode:e.browser.browserMode,goal:t,network:e.network,suiteName:e.suiteName}),e.interactive&&!e.jsonMode)}async function Gk(e,t,r){let{config:n,dappDir:s}=uo(),o=ya(s),i=C(e,"suite"),a;if(i){if(a=o.find((f)=>f.suite.name===i),!a){let f=o.map((h)=>h.suite.name).join(", ")||"none found";throw new R(`Suite "${i}" not found. Available: ${f}`)}}else if(o.length>0)a=o[0];$k(hm(s,"tests","results"),{recursive:!0});let c=Date.now(),d=new Date().toISOString();if(!t){if(process.stderr.write(`
|
|
1377
|
+
`+B(`E2E Test: ${n.name}`)+`
|
|
1378
|
+
|
|
1379
|
+
`),process.stderr.write(A("Network",n.network??"undeployed")+`
|
|
1380
|
+
`),n.port)process.stderr.write(A("Port",String(n.port))+`
|
|
1381
|
+
`);if(a){if(process.stderr.write(A("Suite",a.suite.name)+`
|
|
1382
|
+
`),process.stderr.write(A("Strategy",a.suite.strategy)+`
|
|
1383
|
+
`),a.suite.strategy==="browser"){let f=Sa(a.suite);process.stderr.write(A("Browser Mode",f)+`
|
|
1384
1384
|
`)}}process.stderr.write(`
|
|
1385
|
-
`)}let u=
|
|
1386
|
-
`)};r?.addEventListener("abort",()=>
|
|
1387
|
-
`));let f=null,h=await
|
|
1388
|
-
`);let m=0,y="";if(a){let M=a.suite;if(M.strategy==="browser"){let O=
|
|
1385
|
+
`)}let u=af(),l=[],p=(f)=>{if(!t)process.stderr.write(g(` [teardown] ${f}`)+`
|
|
1386
|
+
`)};r?.addEventListener("abort",()=>va(u,p),{once:!0});try{if(!t)process.stderr.write(P(` Prep
|
|
1387
|
+
`));let f=null,h=await ff(n,s,u,{onStepStart(M){f=H(`[prep] ${M}...`)},onStepComplete(M,O,le,ge){if(O==="pass")f?.stop(`${M} (${Vk(le)})`);else f?.fail(`${M}: ${ge??"failed"}`);f=null},onMessage(M){f?.update(M)}});if(l.push(...h),!t)process.stderr.write(`
|
|
1388
|
+
`);let m=0,y="";if(a){let M=a.suite;if(M.strategy==="browser"){let O=sf(a.suiteDir);if(!O)throw Error(`No prompt.md found in ${a.suiteDir} — required for browser strategy`);if(y=hm(s,"tests","results",`${M.name}_${d.replace(/[:.]/g,"-")}_claude.log`),!t)process.stderr.write(P(` Browser Test
|
|
1389
1389
|
`)),process.stderr.write(g(` Claude will take over the terminal. Output is also logged.
|
|
1390
1390
|
|
|
1391
|
-
`));let le=await
|
|
1391
|
+
`));let le=await hf({suite:M,prompt:O,dappDir:s,logFile:y,onMessage:(ge)=>{if(!t)process.stderr.write(g(` ${ge}`)+`
|
|
1392
1392
|
`)}});if(m=le.exitCode,!t)if(process.stderr.write(`
|
|
1393
1393
|
`),le.timedOut)process.stderr.write(` ${he("✗")} Browser test timed out
|
|
1394
1394
|
`);else process.stderr.write(` ${m===0?z("✓"):he("✗")} Claude exited with code ${m}
|
|
1395
|
-
`)}else if(M.strategy==="cli"){let O=
|
|
1395
|
+
`)}else if(M.strategy==="cli"){let O=nf(a.suiteDir);if(!O)throw Error(`No actions.json found in ${a.suiteDir} — required for CLI strategy`);if(!t)process.stderr.write(P(` CLI Test
|
|
1396
1396
|
`)),process.stderr.write(g(` Executing ${O.actions.length} action(s)
|
|
1397
1397
|
|
|
1398
|
-
`));await Promise.resolve().then(() =>
|
|
1399
|
-
`);else lt.fail(`${fe.id}: ${
|
|
1398
|
+
`));await Promise.resolve().then(() => gm());await Promise.resolve().then(() => Ee());let cr=n.network??"undeployed",{config:Se}=me({args:{command:"test",subcommand:"run",positionals:[],flags:{network:cr}}});await Promise.resolve();let Mt=u.serveHandle?.port??Qr,Re=D(e,"redeploy"),Ft,Ut=await fm({actions:O.actions,config:n,dappDir:s,suiteName:M.name,networkConfig:Se,servePort:Mt,redeploy:Re,onActionStart:(fe)=>{if(Ft=fe,!t){let Ae=H(`[${fe.id}] ${fe.type}${fe.circuit?` ${fe.circuit}`:""}...`);fe._spinner=Ae}},onActionComplete:(fe,Ae)=>{if(!t){let lt=fe._spinner;if(lt)if(Ae.status==="pass")lt.stop(`${fe.id}: ${Ae.message??"pass"}`);else if(Ae.status==="skip")lt.clear(),process.stderr.write(`${ee("⊘")} ${fe.id}: ${Ae.message??"skipped"}
|
|
1399
|
+
`);else lt.fail(`${fe.id}: ${Ae.message??"fail"}`);if(Ae.stateBefore&&Ae.stateAfter){let kt=mm(Ae.stateBefore,Ae.stateAfter);if(kt.length>0)for(let qe of kt)process.stderr.write(g(` ${qe.field}: ${qe.before} → `)+X(qe.after)+`
|
|
1400
1400
|
`)}}},onMessage:(fe)=>{if(!t&&Ft)Ft._spinner?.update(`[${Ft.id}] ${fe.split(`
|
|
1401
1401
|
`)[0]}`)}});if(m=Ut.some((fe)=>fe.status==="fail")?1:0,!t){process.stderr.write(`
|
|
1402
|
-
`);let fe=Ut.filter((qe)=>qe.status==="pass").length,
|
|
1402
|
+
`);let fe=Ut.filter((qe)=>qe.status==="pass").length,Ae=Ut.filter((qe)=>qe.status==="skip").length,lt=Ut.filter((qe)=>qe.status==="fail").length,kt=z(String(fe)+" passed");if(Ae>0)kt+=`, ${ee(String(Ae)+" skipped")}`;if(lt>0)kt+=`, ${he(String(lt)+" failed")}`;process.stderr.write(` Actions: ${kt}
|
|
1403
1403
|
`)}u._actionResults=Ut}}else if(!t)process.stderr.write(g(` No test suites found — only prep was run
|
|
1404
|
-
`));let w={processExitCode:m,agentLogPath:y},S=[];if(a){let M=
|
|
1404
|
+
`));let w={processExitCode:m,agentLogPath:y},S=[];if(a){let M=rf(a.suiteDir);if(M&&M.post.length>0){if(!t)process.stderr.write(`
|
|
1405
1405
|
`+P(` Assertions
|
|
1406
|
-
`));if(S=await
|
|
1407
|
-
`)}}}let k=Math.round((Date.now()-c)/1000),
|
|
1406
|
+
`));if(S=await yf(M.post,w),!t)for(let O of S){let le=O.status==="pass"?z("✓"):he("✗"),ge=O.message?g(` — ${O.message}`):"";process.stderr.write(` ${le} ${O.id}${ge}
|
|
1407
|
+
`)}}}let k=Math.round((Date.now()-c)/1000),T=l.every((M)=>M.status==="pass"),N=S.every((M)=>M.status==="pass"),L=T&&N&&m===0?"pass":"fail",J=u._actionResults,Y={id:`${n.name}_${d}`,dapp:n.name,suite:a?.suite.name??"prep-only",timestamp:d,duration:k,network:n.network??"undeployed",strategy:a?.suite.strategy??"none",model:a?.suite.model,status:L,prep:l,actions:J?.map((M)=>({id:M.id,type:M.type,status:M.status,duration:M.duration,message:M.message,contractAddress:M.contractAddress})),assertions:S,testOutput:y?{exitCode:m,logFile:y}:void 0},V=vf(Y,s);if(t)I(Y);else process.stderr.write(`
|
|
1408
1408
|
`+Z()+`
|
|
1409
1409
|
`),process.stderr.write(` ${L==="pass"?z(P("PASS")):he(P("FAIL"))} — ${n.name} (${k}s)
|
|
1410
|
-
`),process.stderr.write(g(` Results: ${
|
|
1410
|
+
`),process.stderr.write(g(` Results: ${V}`)+`
|
|
1411
1411
|
|
|
1412
|
-
`);if(L==="fail")process.exitCode=1}finally{await
|
|
1413
|
-
`+
|
|
1412
|
+
`);if(L==="fail")process.exitCode=1}finally{await va(u,p)}}function Kk(e){let{config:t,dappDir:r}=uo(),n=ya(r);if(e){I({dapp:t.name,suites:n.map((s)=>({name:s.suite.name,description:s.suite.description,strategy:s.suite.strategy,timeout:s.suite.timeout}))});return}if(process.stderr.write(`
|
|
1413
|
+
`+B(`Tests: ${t.name}`)+`
|
|
1414
1414
|
|
|
1415
1415
|
`),n.length===0)process.stderr.write(g(` No test suites found.
|
|
1416
1416
|
`)),process.stderr.write(g(` Create tests/suites/<name>/suite.json to add one.
|
|
@@ -1419,8 +1419,8 @@ Run from the root of a dApp project containing dapp.test.json.`);let n=D(e,"json
|
|
|
1419
1419
|
`),process.stderr.write(g(` strategy: ${s.strategy}`)+(s.timeout?g(`, timeout: ${s.timeout}s`):"")+`
|
|
1420
1420
|
|
|
1421
1421
|
`);process.stderr.write(`
|
|
1422
|
-
`)}function
|
|
1423
|
-
`+
|
|
1422
|
+
`)}function Jk(e,t){let{config:r,dappDir:n}=uo(),s=D(e,"all"),o=C(e,"suite"),i=s?ba(n,o):(()=>{let a=kf(n,o);return a?[a]:[]})();if(t){I(s?{dapp:r.name,results:i}:i[0]??{});return}if(process.stderr.write(`
|
|
1423
|
+
`+B(`Results: ${r.name}`)+`
|
|
1424
1424
|
|
|
1425
1425
|
`),i.length===0)process.stderr.write(g(` No test results found.
|
|
1426
1426
|
`)),process.stderr.write(g(` Run "midnight test run" to generate results.
|
|
@@ -1430,9 +1430,9 @@ Run from the root of a dApp project containing dapp.test.json.`);let n=D(e,"json
|
|
|
1430
1430
|
`);let l=a.assertions.filter((p)=>p.status==="fail");if(l.length>0)process.stderr.write(he(` assertions: ${l.length} failed`)+`
|
|
1431
1431
|
`);process.stderr.write(`
|
|
1432
1432
|
`)}process.stderr.write(`
|
|
1433
|
-
`)}function
|
|
1433
|
+
`)}function Vk(e){if(e<1000)return`${e}ms`;return`${(e/1000).toFixed(1)}s`}var wm;var vm=E(()=>{re();ue();de();ct();of();mf();wf();Sf();Cf();xf();wm=["run","list","results","create"]});import{readFileSync as km}from"node:fs";import{fileURLToPath as Am}from"node:url";import{Server as qk}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as zk}from"@modelcontextprotocol/sdk/server/stdio.js";import{ListToolsRequestSchema as Yk,CallToolRequestSchema as Xk,ListResourcesRequestSchema as Zk,ReadResourceRequestSchema as Qk}from"@modelcontextprotocol/sdk/types.js";re();async function W(e,t,r){let n=[];xo((s)=>n.push(s));try{if(t.flags.json=!0,!(Wn in t.flags))t.flags[Wn]=!0;await e(t,r);let s=n.join("").trim();if(!s)return{};return JSON.parse(s)}finally{xo(null)}}To();function ja(e){let t=e.split(`
|
|
1434
1434
|
|
|
1435
1435
|
`)[0].trim(),r=t.split(`
|
|
1436
1436
|
`),n=[];for(let s of r){if(/(?:^|\s)(midnight|mn)\s+[a-z]/i.test(s))break;if(/^(Try|Run|See|Open):\s/i.test(s.trim()))break;n.push(s)}return n.join(`
|
|
1437
|
-
`).trim()||t}te();var Gn={name:"midnight-wallet-cli",version:"0.6.0-rc.8",type:"module",description:"Git-style CLI wallet for the Midnight blockchain",license:"Apache-2.0",author:"Norman Lopez (https://github.com/nel349)",homepage:"https://github.com/nel349/midnight-wallet-cli#readme",repository:{type:"git",url:"git+https://github.com/nel349/midnight-wallet-cli.git"},bugs:{url:"https://github.com/nel349/midnight-wallet-cli/issues"},keywords:["midnight","blockchain","wallet","cli","zk","zero-knowledge","compact","mcp","ai-agent"],workspaces:["packages/connector"],bin:{midnight:"dist/wallet.js",mn:"dist/wallet.js","midnight-wallet-cli":"dist/wallet.js","midnight-wallet-mcp":"dist/mcp-server.js"},files:["dist","docs/SKILL.md","docs/SKILL-CORE.md","NOTICE"],engines:{node:">=22",bun:">=1.3.0"},scripts:{wallet:"tsx src/wallet.ts",build:'bun build src/wallet.ts --outfile dist/wallet.js --target node --format esm --packages external --minify --banner "#!/usr/bin/env node" && bun build src/mcp-server.ts --outfile dist/mcp-server.js --target node --format esm --packages external --minify --banner "#!/usr/bin/env node"',mcp:"tsx src/mcp-server.ts",link:"bun link",prepublishOnly:"npm run build && npm run test",test:"vitest run","test:watch":"vitest",typecheck:"tsc --noEmit"},dependencies:{"@midnight-ntwrk/compact-runtime":"0.20.0","@midnight-ntwrk/ledger-v8":"8.1.0","@midnight-ntwrk/midnight-js-contracts":"5.0.0-rc.1","@midnight-ntwrk/midnight-js-http-client-proof-provider":"5.0.0-rc.1","@midnight-ntwrk/midnight-js-indexer-public-data-provider":"5.0.0-rc.1","@midnight-ntwrk/midnight-js-level-private-state-provider":"5.0.0-rc.1","@midnight-ntwrk/midnight-js-network-id":"5.0.0-rc.1","@midnight-ntwrk/midnight-js-node-zk-config-provider":"5.0.0-rc.1","@midnight-ntwrk/midnight-js-protocol":"5.0.0-rc.1","@midnight-ntwrk/midnight-js-types":"5.0.0-rc.1","@midnight-ntwrk/midnight-js-utils":"5.0.0-rc.1","@midnightntwrk/dapp-connector-api":"4.1.0-beta.1","@midnightntwrk/ledger-v9":"1.0.0-rc.5","@midnightntwrk/onchain-runtime-v4":"4.0.0-rc.3","@midnightntwrk/wallet-sdk":"2.0.0-rc.0","@modelcontextprotocol/sdk":"^1.27.1","@scure/base":"2.0.0","@scure/bip39":"^2.0.1",rxjs:"7.8.2",ws:"^8.19.0"},devDependencies:{"@types/node":"^22.19.13","@types/ws":"^8.18.1",tsx:"^4.21.0",typescript:"^5.9.3",vitest:"^3.2.4"}};var ix=Gn.name,No=Gn.version,ax=Gn.description;import{randomUUID as Lm}from"node:crypto";var Wm=300000;function Ba(e={}){let t=e.ttlMs??Wm,r=e.now??(()=>Date.now()),n=new Map,s=(o)=>{let i=0;for(let[a,c]of n)if(c.expiresAt<=o)n.delete(a),i+=1;return i};return{create(o){let i=r();s(i);let a=Lm(),c={token:a,tool:o.tool,args:o.args,description:o.description,createdAt:i,expiresAt:i+t};return n.set(a,c),c},redeem(o){let i=n.get(o);if(!i)return null;if(i.expiresAt<=r())return n.delete(o),null;return n.delete(o),i},sweep(o=r()){return s(o)},size(){return n.size}}}import Bm from"node:v8";import jm from"node:os";import{spawn as Hm}from"node:child_process";var Fo="MN_HEAP_BUMPED",Gm="MN_MAX_OLD_SPACE_MB",nc=1048576;function Km(e){let t=e.desiredMb??za,r=e.ramFraction??Ya,n=e.minGainMb??Xa;if(!Number.isFinite(t)||t<=0)return null;if(!Number.isFinite(e.totalMb)||e.totalMb<=0)return null;let s=Math.floor(e.totalMb*r),o=Math.min(Math.floor(t),s);if(o<=e.currentLimitMb+n)return null;return o}async function sc(){if(process.env[Fo]){Jm();return}let e=process.env[Gm],t=e!==void 0?Number(e):void 0,r=Km({totalMb:Math.floor(jm.totalmem()/nc),currentLimitMb:Math.floor(Bm.getHeapStatistics().heap_size_limit/nc),desiredMb:t});if(r===null)return;return new Promise((n)=>{let s=Hm(process.execPath,[`--max-old-space-size=${r}`,...process.execArgv,process.argv[1],...process.argv.slice(2)],{stdio:"inherit",env:{...process.env,[Fo]:"1"}});Vm(s),s.on("error",()=>{process.env[Fo]="1",n()}),s.on("exit",(o,i)=>process.exit(i?1:o??0))})}function Vm(e,t=(r,n)=>{process.on(r,n)}){let r=["SIGINT","SIGTERM","SIGHUP"];for(let n of r)t(n,()=>{try{e.kill(n)}catch{}});t("exit",()=>{try{e.kill("SIGKILL")}catch{}})}function Jm(){let e=process.ppid;if(!e||e<=1)return;setInterval(()=>{if(process.ppid!==e)try{process.kill(process.pid,"SIGTERM")}catch{process.exit(0)}},2000).unref()}class Uo extends Error{code="UNSUPPORTED_NODE";constructor(e){super(`midnight-wallet-cli needs Node.js 22 or newer; this is Node.js ${e}. The Midnight wallet SDK uses features older versions lack. Install a current Node.js (https://nodejs.org) and run the command again.`);this.name="UnsupportedNodeError",Object.setPrototypeOf(this,Uo.prototype)}}function oc(e=process.versions){if(e.bun!==void 0)return;let t=Number(e.node.split(".")[0]);if(!Number.isInteger(t)||t<22)throw new Uo(e.node)}Me();function Ym(e){if(typeof e==="string")return jo(e)?ss(e):e;let t=Buffer.from(e.buffer,e.byteOffset,e.byteLength).toString("utf8");if(!jo(t))return e;let r=ss(t);return r===t?e:Buffer.from(r,"utf8")}function uc(e){return function(t,...r){return e.call(this,Ym(t),...r)}}var pc=!1;function fc(){if(pc)return;pc=!0,process.stdout.write=uc(process.stdout.write),process.stderr.write=uc(process.stderr.write)}var Cm="midnight-wallet://skill/core",Em="midnight-wallet://skill/full",Lk="midnight-wallet://skill",Wk=xm(new URL("../docs/SKILL-CORE.md",import.meta.url)),Bk=xm(new URL("../docs/SKILL.md",import.meta.url));function ye(e,t,r){let n={json:!0},s=[];for(let[o,i]of Object.entries(t)){if(i===void 0||i===null)continue;let a=o==="full"?qr:o;if(typeof i==="boolean"){if(i)n[a]=!0}else n[a]=String(i)}return{command:e,subcommand:r,positionals:s,flags:n}}function bm(e){let t=ye("transfer",e,e.to);return t.positionals=e.amount===void 0?[]:[String(e.amount)],delete t.flags.to,delete t.flags.amount,t}var Ot={wallet:{type:"string",description:"The wallet that owns the account and pays the fees"},network:{type:"string",enum:["undeployed"],description:"Only undeployed (a local ledger-9 stack)"},"account-build":{type:"string",description:"The account build's directory (default: the account-build config key)"}};function je(e,t,r,n={}){let s=ye("grant",t,e);if(r!==void 0){if(t[r]!==void 0)s.positionals=[String(t[r])];delete s.flags[r]}return Object.assign(s.flags,n),s}async function go(e,t){await Promise.resolve().then(() => Ks());await Fr(e),await ho(t)}async function ho(e){await Promise.resolve().then(() => Pe());ce(oe(e.wallet))}var jk={generate:()=>Promise.resolve().then(() => (zl(),ql)),info:()=>Promise.resolve().then(() => (Zl(),Xl)),balance:()=>Promise.resolve().then(() => (gu(),mu)),address:()=>Promise.resolve().then(() => (yu(),wu)),"genesis-address":()=>Promise.resolve().then(() => (vu(),bu)),"inspect-cost":()=>Promise.resolve().then(() => (Au(),Tu)),airdrop:()=>Promise.resolve().then(() => (_u(),Iu)),transfer:()=>Promise.resolve().then(() => (Fu(),Mu)),dust:()=>Promise.resolve().then(() => (ju(),Bu)),cache:()=>Promise.resolve().then(() => (Ku(),Gu)),config:()=>Promise.resolve().then(() => (qu(),Ju)),localnet:()=>Promise.resolve().then(() => (gp(),mp)),wallet:()=>Promise.resolve().then(() => (bp(),Sp)),status:()=>Promise.resolve().then(() => (Np(),Ap)),contract:()=>Promise.resolve().then(() => (jp(),Bp)),grant:()=>Promise.resolve().then(() => (qp(),Jp)),test:()=>Promise.resolve().then(() => (ym(),wm))};async function G(e){let t=jk[e];if(!t)throw Error(`Unknown command handler: ${e}`);return(await t()).default}var yo=[{name:"midnight_wallet_generate",description:"Create wallet.",annotations:{destructiveHint:!0},inputSchema:{type:"object",properties:{name:{type:"string"},network:{type:"string",enum:["preprod","preview","undeployed"]},seed:{type:"string",description:"64 or 128 hex chars (32-byte raw or 64-byte BIP-39)"},mnemonic:{type:"string",description:"BIP-39 24 words"},force:{type:"string"}},required:["name"]},async handler(e){let t=e.name,r=ye("wallet",e,"generate");if(r.positionals=[t],delete r.flags.name,e.force==="true"||e.force===!0)r.flags.force=!0;let n=await G("wallet");return B(n,r)}},{name:"midnight_wallet_list",description:"List wallets. Default: per-wallet { name, active, network, address, shieldedAddress } scoped to the active network. Pass { full: true } for the 3-network addresses + shieldedAddresses maps.",annotations:{readOnlyHint:!0,idempotentHint:!0},inputSchema:{type:"object",properties:{full:{type:"boolean",description:"Return full per-network addresses + shieldedAddresses maps (the same shape `mn wallet list --json` emits). Default false (slim)."}}},async handler({full:e}={}){let t={json:!0};if(e)t[qr]=!0;let r={command:"wallet",subcommand:"list",positionals:[],flags:t},n=await G("wallet");return B(n,r)}},{name:"midnight_wallet_use",description:"Set active wallet.",annotations:{idempotentHint:!0},inputSchema:{type:"object",properties:{name:{type:"string"}},required:["name"]},async handler(e){let r={command:"wallet",subcommand:"use",positionals:[e.name],flags:{json:!0}},n=await G("wallet");return B(n,r)}},{name:"midnight_wallet_info",description:"Show wallet details. Default: { name, active, network, address, shieldedAddress } scoped to the active network. Pass { full: true } for the per-network maps + createdAt + file path.",annotations:{readOnlyHint:!0,idempotentHint:!0},inputSchema:{type:"object",properties:{name:{type:"string"},full:{type:"boolean",description:"Return the full per-network addresses + shieldedAddresses maps and bookkeeping fields (matches `mn wallet info <name> --json`). Default false (slim)."}}},async handler(e){let{name:t,full:r}=e,n={json:!0};if(r)n[qr]=!0;let s={command:"wallet",subcommand:"info",positionals:t?[t]:[],flags:n},o=await G("wallet");return B(o,s)}},{name:"midnight_wallet_remove",description:"Remove wallet.",annotations:{destructiveHint:!0},inputSchema:{type:"object",properties:{name:{type:"string"}},required:["name"]},async handler(e){let r={command:"wallet",subcommand:"remove",positionals:[e.name],flags:{json:!0}},n=await G("wallet");return B(n,r)}},{name:"midnight_info",description:"Wallet metadata.",annotations:{readOnlyHint:!0,idempotentHint:!0},inputSchema:{type:"object",properties:{wallet:{type:"string"}}},async handler(e){let t=ye("info",e),r=await G("info");return B(r,t)}},{name:"midnight_balance",description:"NIGHT balance. Default: { network, unshielded, shielded } — no echoed addresses. Pass { full: true } for the human shape including address + shieldedAddress.",annotations:{readOnlyHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{address:{type:"string"},wallet:{type:"string"},network:{type:"string",enum:["preprod","preview","undeployed"]},"indexer-ws":{type:"string"},full:{type:"boolean",description:"Include the queried address + shieldedAddress in the response (matches `mn balance --json`). Default false (slim)."}}},async handler(e){let t=e.address,r=ye("balance",e,t);delete r.flags.address;let n=await G("balance");return B(n,r)}},{name:"midnight_address",description:"Derive address from seed.",annotations:{readOnlyHint:!0,idempotentHint:!0},inputSchema:{type:"object",properties:{seed:{type:"string",description:"64 or 128 hex chars (32-byte raw or 64-byte BIP-39)"},network:{type:"string",enum:["preprod","preview","undeployed"]},index:{type:"string"}},required:["seed"]},async handler(e){let t=ye("address",e),r=await G("address");return B(r,t)}},{name:"midnight_genesis_address",description:"Genesis address.",annotations:{readOnlyHint:!0,idempotentHint:!0},inputSchema:{type:"object",properties:{network:{type:"string",enum:["preprod","preview","undeployed"]}}},async handler(e){let t=ye("genesis-address",e),r=await G("genesis-address");return B(r,t)}},{name:"midnight_inspect_cost",description:"The chain's current block limits, from its latest block's ledger parameters.",annotations:{readOnlyHint:!0,idempotentHint:!0},inputSchema:{type:"object",properties:{network:{type:"string",description:"Network to read (default: the selected one)"}}},async handler(e){let t=ye("inspect-cost",e.network?{network:e.network}:{}),r=await G("inspect-cost");return B(r,t)}},{name:"midnight_airdrop",description:'Fund from genesis (undeployed). `wallet` accepts a wallet name, a wallet JSON path, or a raw bech32m address (mn_addr_… or mn_shield-addr_…). Add `shielded: "true"` to fund a shielded balance.',annotations:{destructiveHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{amount:{type:"string",description:"NIGHT"},wallet:{type:"string",description:"Destination: wallet name, JSON path, or bech32m address"},shielded:{type:"string",description:'Set to "true" for shielded airdrop'}},required:["amount"]},async handler(e){let t=e.amount,r=ye("airdrop",e,t);delete r.flags.amount;let n=await G("airdrop");return B(n,r)}},{name:"midnight_transfer",description:"Send NIGHT (returns pending token; see skill).",annotations:{destructiveHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{to:{type:"string",description:"bech32m"},amount:{type:"string",description:"NIGHT"},wallet:{type:"string"}},required:["to","amount"]},async handler(e){let t=await G("transfer");return B(t,bm(e))},async check(e){await Promise.resolve().then(() => ra());Zs(bm(e))}},{name:"midnight_dust_register",description:"Register for dust.",annotations:{destructiveHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{wallet:{type:"string"}}},async handler(e){let t=ye("dust",e,"register"),r=await G("dust");return B(r,t)}},{name:"midnight_dust_status",description:"Dust status. Default: { network, registered, registeredUtxos, unregisteredUtxos, dustBalance, dustAvailable }. Pass { full: true } for sync internals (eventsApplied, ownedUtxos, cached).",annotations:{readOnlyHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{wallet:{type:"string"},"proof-server":{type:"string"},node:{type:"string"},"indexer-ws":{type:"string"},"no-cache":{type:"string"},full:{type:"boolean",description:"Include sync internals (eventsApplied, ownedUtxos, cached) in the response (matches `mn dust status --json`). Default false (slim)."}}},async handler(e){let t=ye("dust",e,"status"),r=await G("dust");return B(r,t)}},{name:"midnight_config_get",description:"Read config.",annotations:{readOnlyHint:!0,idempotentHint:!0},inputSchema:{type:"object",properties:{key:{type:"string"},network:{type:"string",description:"For node / indexer-ws / proof-server: the network to read or write them for (default: the selected network)"}},required:["key"]},async handler(e){let r={command:"config",subcommand:"get",positionals:[e.key],flags:{json:!0,...e.network?{network:e.network}:{}}},n=await G("config");return B(n,r)}},{name:"midnight_config_set",description:"Write config.",annotations:{idempotentHint:!0},inputSchema:{type:"object",properties:{key:{type:"string"},network:{type:"string",description:"For node / indexer-ws / proof-server: the network to read or write them for (default: the selected network)"},value:{type:"string"}},required:["key","value"]},async handler(e){let{key:t,value:r}=e,n={command:"config",subcommand:"set",positionals:[t,r],flags:{json:!0,...e.network?{network:e.network}:{}}},s=await G("config");return B(s,n)}},{name:"midnight_cache_clear",description:"Clear sync cache.",annotations:{destructiveHint:!0,idempotentHint:!0},inputSchema:{type:"object",properties:{network:{type:"string",enum:["preprod","preview","undeployed"]},wallet:{type:"string"}}},async handler(e){let t=ye("cache",e,"clear"),r=await G("cache");return B(r,t)}},{name:"midnight_config_unset",description:"Reset config.",annotations:{idempotentHint:!0},inputSchema:{type:"object",properties:{key:{type:"string"},network:{type:"string",description:"For node / indexer-ws / proof-server: the network to read or write them for (default: the selected network)"}},required:["key"]},async handler(e){let r={command:"config",subcommand:"unset",positionals:[e.key],flags:{json:!0,...e.network?{network:e.network}:{}}},n=await G("config");return B(n,r)}},{name:"midnight_localnet_up",description:"Refused on this ledger-9 build: mn's localnet is ledger 8 and no ledger-9 indexer image is published. Run a ledger-9 stack yourself and point mn at it (config_set node / indexer-ws / proof-server).",annotations:{openWorldHint:!0},inputSchema:{type:"object",properties:{}},async handler(){let e={command:"localnet",subcommand:"up",positionals:[],flags:{json:!0}},t=await G("localnet");return B(t,e)}},{name:"midnight_localnet_stop",description:"Stop localnet (preserves state).",annotations:{idempotentHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{}},async handler(){let e={command:"localnet",subcommand:"stop",positionals:[],flags:{json:!0}},t=await G("localnet");return B(t,e)}},{name:"midnight_localnet_down",description:"Localnet teardown (volumes + undeployed cache).",annotations:{destructiveHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{}},async handler(){let e={command:"localnet",subcommand:"down",positionals:[],flags:{json:!0}},t=await G("localnet");return B(t,e)}},{name:"midnight_localnet_status",description:"Localnet status.",annotations:{readOnlyHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{}},async handler(){let e={command:"localnet",subcommand:"status",positionals:[],flags:{json:!0}},t=await G("localnet");return B(t,e)}},{name:"midnight_localnet_clean",description:"Remove stray containers.",annotations:{destructiveHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{}},async handler(){let e={command:"localnet",subcommand:"clean",positionals:[],flags:{json:!0}},t=await G("localnet");return B(t,e)}},{name:"midnight_contract_inspect",description:"Inspect a compiled Compact contract: name, circuits (with arg/return types), witnesses, compiler/language/runtime versions. Reads managed/<name>/compiler/contract-info.json under the dapp dir. Returns a `siblings` array listing other contracts in the same project — call again with `name` to inspect a sibling.",annotations:{readOnlyHint:!0,idempotentHint:!0},inputSchema:{type:"object",properties:{path:{type:"string",description:"Path to dApp directory (defaults to cwd)"},managed:{type:"string",description:"Direct path to a managed/<name>/ directory (overrides path)"},name:{type:"string",description:"Specific contract name to inspect when the project has multiple (see siblings field)"}}},async handler(e){let t=ye("contract",e,"inspect"),r=await G("contract");return B(r,t)}},{name:"midnight_contract_state",description:"Read the current ledger state of a deployed contract. Returns the ledger fields as a JSON object.",annotations:{readOnlyHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{address:{type:"string",description:"Contract address (hex)"},wallet:{type:"string"},network:{type:"string",enum:["preprod","preview","undeployed"]},path:{type:"string",description:"dApp directory (defaults to cwd; needed to find the compiled artifact for state decoding)"},managed:{type:"string",description:"Direct path to a managed/<name>/ directory (overrides path-based contract scan)"},name:{type:"string",description:"Specific contract name when the project has multiple"}},required:["address"]},async handler(e){let t=ye("contract",e,"state"),r=await G("contract");return B(r,t)}},{name:"midnight_contract_deploy",description:"Deploy a compiled Compact contract (returns pending token; agent must show the description and redeem via midnight_confirm_operation).",annotations:{destructiveHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{wallet:{type:"string"},network:{type:"string",enum:["preprod","preview","undeployed"]},args:{type:"string",description:"JSON-encoded array or object of constructor arguments"},path:{type:"string",description:"dApp directory (defaults to cwd)"},managed:{type:"string",description:"Direct path to a managed/<name>/ directory (overrides path-based contract scan)"},name:{type:"string",description:"Specific contract name when the project has multiple"}}},async handler(e){let t=ye("contract",e,"deploy"),r=await G("contract");return B(r,t)},async check(e){await Promise.resolve().then(() => lo());ao(ye("contract",e,"deploy")),await ho(e)}},{name:"midnight_contract_call",description:"Call a circuit on a deployed contract (returns pending token; agent must show the description and redeem via midnight_confirm_operation).",annotations:{destructiveHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{address:{type:"string",description:"Contract address (hex)"},circuit:{type:"string",description:"Circuit name to invoke"},wallet:{type:"string"},network:{type:"string",enum:["preprod","preview","undeployed"]},args:{type:"string",description:"JSON-encoded array or object of circuit arguments"},path:{type:"string",description:"dApp directory (defaults to cwd)"},managed:{type:"string",description:"Direct path to a managed/<name>/ directory (overrides path-based contract scan)"},name:{type:"string",description:"Specific contract name when the project has multiple"}},required:["address","circuit"]},async handler(e){let t=ye("contract",e,"call"),r=await G("contract");return B(r,t)},async check(e){await Promise.resolve().then(() => lo());co(ye("contract",e,"call")),await ho(e)}},{name:"midnight_grant_status",description:"The wallet's account: address, owner key, what it holds, number of grants. Needs an account build (see skill).",annotations:{readOnlyHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{...Ot}},async handler(e){return B(await G("grant"),je("status",e))}},{name:"midnight_grant_list",description:"Every grant on the wallet's account, with its limits and whether it is live.",annotations:{readOnlyHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{...Ot}},async handler(e){return B(await G("grant"),je("list",e))}},{name:"midnight_grant_request",description:"What issuing from an agent's grant request link would grant: who spends, who they can pay, and the limits (the account build's defaults for any not given). Issues nothing. Show the user this before midnight_grant_issue.",annotations:{readOnlyHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{link:{type:"string",description:"The grant request link"},cap:{type:"string",description:"Most the grant may ever pay (smallest unit)"},"per-call":{type:"string",description:"Most one payment may be"},"max-coin":{type:"string",description:"Largest coin the agent may take to pay from"},"expires-in":{type:"string",description:"Seconds the grant lasts"},...Ot},required:["link"]},async handler(e){return B(await G("grant"),je("issue",e,"link"))}},{name:"midnight_grant_deploy",description:"Deploy the wallet's account and activate its owner key (returns pending token). Takes about 48 DUST from the wallet (17 at once for the largest of five transactions) and a few minutes. The owner key is a random development key the mnemonic can't recover: dev-owner-key must be true.",annotations:{destructiveHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{"dev-owner-key":{type:"boolean",description:"Accept a development owner key"},...Ot}},async handler(e){return B(await G("grant"),je("deploy",e))},async check(e){await go(je("deploy",e),e)}},{name:"midnight_grant_deposit",description:"Move shielded NIGHT from the wallet into its account, where a grant lets an agent spend it (returns pending token). The wallet needs that much shielded NIGHT, plus Dust for the fee. mn has no command to take it back out.",annotations:{destructiveHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{amount:{type:"string",description:'NIGHT to deposit, e.g. "2" (up to 6 decimals)'},...Ot},required:["amount"]},async handler(e){return B(await G("grant"),je("deposit",e,"amount"))},async check(e){let t=je("deposit",e,"amount");await Promise.resolve().then(() => Ks());let{request:n,walletName:s,target:o,account:i}=await Fr(t);if(await ho(e),n.subcommand!=="deposit"||i===null)throw Error("A deposit was prepared as something else");return`Deposit ${n.amount} shielded NIGHT (${n.value} in the smallest unit) from wallet ${s} into its account ${i.address} on ${o.network}`}},{name:"midnight_grant_issue",description:"Issue a grant from an agent's request link (returns pending token, whose description gives the grant's terms as the account build read them). Lets that agent spend from the account within the limits.",annotations:{destructiveHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{link:{type:"string",description:"The grant request link"},cap:{type:"string",description:"Most the grant may ever pay (smallest unit)"},"per-call":{type:"string",description:"Most one payment may be"},"max-coin":{type:"string",description:"Largest coin the agent may take to pay from"},"expires-in":{type:"string",description:"Seconds the grant lasts"},...Ot},required:["link"]},async handler(e){return B(await G("grant"),je("issue",e,"link",{yes:!0}))},async check(e){await go(je("issue",e,"link",{yes:!0}),e);let t=await B(await G("grant"),je("issue",e,"link"));await Promise.resolve().then(() => Gs());return`Issue a grant on ${t.wallet}'s account on ${t.network}, letting an agent spend from it within these terms (amounts in the token's smallest unit; limits not given took the account build's defaults): ${jl(t.request)}`}},{name:"midnight_grant_revoke",description:"Revoke one grant, by its id or slot (returns pending token).",annotations:{destructiveHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{grant:{type:"string",description:"Grant id (64 hex) or slot number"},...Ot},required:["grant"]},async handler(e){return B(await G("grant"),je("revoke",e,"grant"))},async check(e){await go(je("revoke",e,"grant"),e)}},{name:"midnight_grant_revoke_all",description:"Revoke every grant on the wallet's account (returns pending token).",annotations:{destructiveHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{...Ot}},async handler(e){return B(await G("grant"),je("revoke-all",e))},async check(e){await go(je("revoke-all",e),e)}},{name:"midnight_test_create",description:"Generate a test scaffold for the contract. Two paths: (1) AI-assisted — pass `goal` (and optionally `screen` for UI strategy) and the scaffold is generated by Claude reading the contract + screen source, producing a focused suite with realistic args / on-screen labels. (2) Deterministic — pass `no-ai: true` (or omit goal/screen in non-interactive mode) for boilerplate scaffolds that the user reviews. CLI strategy emits dapp.test.json + tests/suites/<name>/{suite,actions,assertions}.json. Browser strategy emits prompt.md instead of actions.json plus the browser fields in dapp.test.json — required: port, build-cmd. Use force:true to overwrite.",annotations:{destructiveHint:!0},inputSchema:{type:"object",properties:{path:{type:"string",description:"dApp directory (defaults to cwd)"},name:{type:"string",description:"Specific contract name when the project has multiple"},suite:{type:"string",description:"Suite directory name under tests/suites/ (auto-derived from circuit/screen when AI scaffolds)"},strategy:{type:"string",enum:["cli","browser"],description:"cli (default): drive contracts via actions.json. browser: drive a real UI via Claude + Chrome via prompt.md."},network:{type:"string",enum:["preprod","preview","undeployed"]},goal:{type:"string",description:'AI mode: one-line success criterion this suite should verify (e.g. "round goes from 0 to 1 after increment"). Triggers AI scaffolding.'},screen:{type:"string",description:'AI mode + browser strategy: name of the screen component to focus on (e.g. "loan-request-form" or "LoanRequestForm"). Auto-discovered from src/components, src/pages, src/screens.'},"no-ai":{type:"boolean",description:"Force deterministic scaffolder even when claude CLI is available."},port:{type:"string",description:'Browser strategy only — dev server port (e.g. "4173").'},"build-cmd":{type:"string",description:'Browser strategy only — shell command that builds + serves the UI (e.g. "npm run dev").'},"build-dir":{type:"string",description:"Browser strategy only — subdir the build runs in (monorepo case)."},url:{type:"string",description:"Browser strategy only — full URL Claude opens (default http://localhost:<port>/)."},"browser-mode":{type:"string",enum:["dom","vision","script"],description:"Browser strategy only — how Claude perceives the page. dom (HTML/React UIs, fast, needs chrome-devtools-mcp), vision (canvas games, slow), script (advanced, needs hooks). Default: dom for AI scaffolds."},force:{type:"boolean",description:"Overwrite existing files instead of aborting on collision"}}},async handler(e){let t=ye("test",e,"create"),r=await G("test");return B(r,t)}},{name:"midnight_localnet_logs",description:"Snapshot of recent localnet logs (last N lines per service, no streaming). Returns { tail, lines: string[] }.",annotations:{readOnlyHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{tail:{type:"string",description:"Number of lines to retrieve (default 200)"}}},async handler(e){let t=ye("localnet",e,"logs");if(!t.flags.tail)t.flags.tail="200";let r=await G("localnet");return B(r,t)}},{name:"midnight_confirm_operation",description:"Redeem a pending token (confirm step).",annotations:{destructiveHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{token:{type:"string"}},required:["token"]},async handler(){throw Error("midnight_confirm_operation reached the inner handler — this is an MCP wiring bug")}}],Hk=new Set(yo.filter((e)=>e.check!==void 0).map((e)=>e.name)),vm=Ba();function Gk(e,t){let r=t.network??"active network",n=t.wallet??"active wallet";switch(e){case"midnight_transfer":return`Send ${t.amount} NIGHT from ${n} to ${t.to} on ${r}`;case"midnight_contract_deploy":{let s=t.args?` with args ${t.args}`:"";return`Deploy contract from ${t.path??"current directory"} as ${n} on ${r}${s}`}case"midnight_contract_call":{let s=t.args?` with args ${t.args}`:"";return`Call circuit ${t.circuit} on contract ${t.address} as ${n} on ${r}${s}`}case"midnight_grant_deploy":return`Deploy an account for ${n} on ${r}, on a development owner key the wallet's mnemonic can't recover`;case"midnight_grant_revoke":return`Revoke grant ${t.grant} on ${n}'s account on ${r}`;case"midnight_grant_revoke_all":return`Revoke every grant on ${n}'s account on ${r}`;default:return`Execute ${e} with ${JSON.stringify(t)}`}}var Wn=new Pk({name:"midnight-wallet-cli",version:No},{capabilities:{tools:{},resources:{}}});Wn.setRequestHandler(Fk,async()=>({resources:[{uri:Cm,name:"midnight-wallet skill (core)",description:"Read this first. Intent routing table + non-negotiable safety rules. ~830 tokens. Fetch /full on demand for canonical flows, error recovery, and concept primers.",mimeType:"text/markdown"},{uri:Em,name:"midnight-wallet skill (full)",description:"Canonical multi-step flows, error-recovery recipes, concept primers (NIGHT/DUST/shielded), network selection. Fetch on demand when you hit an error, start a multi-step flow, or need to explain a concept.",mimeType:"text/markdown"}]}));Wn.setRequestHandler(Uk,async(e)=>{let t=e.params.uri;if(t===Cm){let r=Sm(Wk,"utf-8");return{contents:[{uri:t,mimeType:"text/markdown",text:r}]}}if(t===Em||t===Lk){let r=Sm(Bk,"utf-8");return{contents:[{uri:t,mimeType:"text/markdown",text:r}]}}throw Error(`Unknown resource: ${t}`)});Wn.setRequestHandler(Ok,async()=>({tools:yo.map((e)=>({name:e.name,description:e.description,inputSchema:e.inputSchema,...e.annotations?{annotations:e.annotations}:{}}))}));Wn.setRequestHandler(Mk,async(e)=>{let{name:t,arguments:r}=e.params,n=r??{};if(t==="midnight_confirm_operation"){let s=typeof n.token==="string"?n.token:"",o=vm.redeem(s);if(!o)return wo(Error("Unknown or expired confirmation token. The first-step tool call may need to be re-issued."));return km(o.tool,o.args)}if(Hk.has(t)){let s;try{s=await yo.find((i)=>i.name===t)?.check?.(n)}catch(i){return wo(i instanceof Error?i:Error(String(i)))}let o=vm.create({tool:t,args:n,description:s??Gk(t,n)});return{content:[{type:"text",text:JSON.stringify($a({pending:!0,token:o.token,description:o.description,tool:o.tool,expiresAt:new Date(o.expiresAt).toISOString(),nextStep:"Show the description to the user, get explicit consent, then call midnight_confirm_operation with this token."}),null,2)}]}}return km(t,n)});function $a(e){return{...e,_serverVersion:No}}async function km(e,t){let r=yo.find((n)=>n.name===e);if(!r)return wo(Error(`Unknown tool: ${e}`));try{let n=await r.handler(t);return{content:[{type:"text",text:JSON.stringify($a(n),null,2)}]}}catch(n){return wo(n instanceof Error?n:Error(String(n)))}}function wo(e){let{errorCode:t}=Hn(e);return{content:[{type:"text",text:JSON.stringify($a({error:!0,code:t,message:Wa(e.message)}))}],isError:!0}}async function Kk(){oc(),fc(),await sc();let e=new $k;await Wn.connect(e)}Kk().catch((e)=>{process.stderr.write(`MCP server error: ${e.message}
|
|
1437
|
+
`).trim()||t}re();var Gn={name:"midnight-wallet-cli",version:"0.6.0-rc.9",type:"module",description:"Git-style CLI wallet for the Midnight blockchain",license:"Apache-2.0",author:"Norman Lopez (https://github.com/nel349)",homepage:"https://github.com/nel349/midnight-wallet-cli#readme",repository:{type:"git",url:"git+https://github.com/nel349/midnight-wallet-cli.git"},bugs:{url:"https://github.com/nel349/midnight-wallet-cli/issues"},keywords:["midnight","blockchain","wallet","cli","zk","zero-knowledge","compact","mcp","ai-agent"],workspaces:["packages/connector"],bin:{midnight:"dist/wallet.js",mn:"dist/wallet.js","midnight-wallet-cli":"dist/wallet.js","midnight-wallet-mcp":"dist/mcp-server.js"},files:["dist","docs/SKILL.md","docs/SKILL-CORE.md","NOTICE"],engines:{node:">=22",bun:">=1.3.0"},scripts:{wallet:"tsx src/wallet.ts",build:'bun build src/wallet.ts --outfile dist/wallet.js --target node --format esm --packages external --minify --banner "#!/usr/bin/env node" && bun build src/mcp-server.ts --outfile dist/mcp-server.js --target node --format esm --packages external --minify --banner "#!/usr/bin/env node"',mcp:"tsx src/mcp-server.ts",link:"bun link",prepublishOnly:"npm run build && npm run test",test:"vitest run","test:watch":"vitest",typecheck:"tsc --noEmit"},dependencies:{"@kuiralabs/midnight-account-chain":"0.2.2","@midnight-ntwrk/compact-runtime":"0.20.0","@midnight-ntwrk/ledger-v8":"8.1.0","@midnight-ntwrk/midnight-js-contracts":"5.0.0-rc.1","@midnight-ntwrk/midnight-js-http-client-proof-provider":"5.0.0-rc.1","@midnight-ntwrk/midnight-js-indexer-public-data-provider":"5.0.0-rc.1","@midnight-ntwrk/midnight-js-level-private-state-provider":"5.0.0-rc.1","@midnight-ntwrk/midnight-js-network-id":"5.0.0-rc.1","@midnight-ntwrk/midnight-js-node-zk-config-provider":"5.0.0-rc.1","@midnight-ntwrk/midnight-js-protocol":"5.0.0-rc.1","@midnight-ntwrk/midnight-js-types":"5.0.0-rc.1","@midnight-ntwrk/midnight-js-utils":"5.0.0-rc.1","@midnightntwrk/dapp-connector-api":"4.1.0-beta.1","@midnightntwrk/ledger-v9":"1.0.0-rc.5","@midnightntwrk/onchain-runtime-v4":"4.0.0-rc.3","@midnightntwrk/wallet-sdk":"2.0.0-rc.0","@modelcontextprotocol/sdk":"^1.27.1","@scure/base":"2.0.0","@scure/bip39":"^2.0.1",rxjs:"7.8.2",ws:"^8.19.0"},devDependencies:{"@types/node":"^22.19.13","@types/ws":"^8.18.1",tsx:"^4.21.0",typescript:"^5.9.3",vitest:"^3.2.4"}};var vC=Gn.name,No=Gn.version,kC=Gn.description;import{randomUUID as jm}from"node:crypto";var Hm=300000;function Ha(e={}){let t=e.ttlMs??Hm,r=e.now??(()=>Date.now()),n=new Map,s=(o)=>{let i=0;for(let[a,c]of n)if(c.expiresAt<=o)n.delete(a),i+=1;return i};return{create(o){let i=r();s(i);let a=jm(),c={token:a,tool:o.tool,args:o.args,description:o.description,createdAt:i,expiresAt:i+t};return n.set(a,c),c},redeem(o){let i=n.get(o);if(!i)return null;if(i.expiresAt<=r())return n.delete(o),null;return n.delete(o),i},sweep(o=r()){return s(o)},size(){return n.size}}}import Gm from"node:v8";import Km from"node:os";import{spawn as Jm}from"node:child_process";var Fo="MN_HEAP_BUMPED",Vm="MN_MAX_OLD_SPACE_MB",oc=1048576;function qm(e){let t=e.desiredMb??Xa,r=e.ramFraction??Za,n=e.minGainMb??Qa;if(!Number.isFinite(t)||t<=0)return null;if(!Number.isFinite(e.totalMb)||e.totalMb<=0)return null;let s=Math.floor(e.totalMb*r),o=Math.min(Math.floor(t),s);if(o<=e.currentLimitMb+n)return null;return o}async function ic(){if(process.env[Fo]){Ym();return}let e=process.env[Vm],t=e!==void 0?Number(e):void 0,r=qm({totalMb:Math.floor(Km.totalmem()/oc),currentLimitMb:Math.floor(Gm.getHeapStatistics().heap_size_limit/oc),desiredMb:t});if(r===null)return;return new Promise((n)=>{let s=Jm(process.execPath,[`--max-old-space-size=${r}`,...process.execArgv,process.argv[1],...process.argv.slice(2)],{stdio:"inherit",env:{...process.env,[Fo]:"1"}});zm(s),s.on("error",()=>{process.env[Fo]="1",n()}),s.on("exit",(o,i)=>process.exit(i?1:o??0))})}function zm(e,t=(r,n)=>{process.on(r,n)}){let r=["SIGINT","SIGTERM","SIGHUP"];for(let n of r)t(n,()=>{try{e.kill(n)}catch{}});t("exit",()=>{try{e.kill("SIGKILL")}catch{}})}function Ym(){let e=process.ppid;if(!e||e<=1)return;setInterval(()=>{if(process.ppid!==e)try{process.kill(process.pid,"SIGTERM")}catch{process.exit(0)}},2000).unref()}class Uo extends Error{code="UNSUPPORTED_NODE";constructor(e){super(`midnight-wallet-cli needs Node.js 22 or newer; this is Node.js ${e}. The Midnight wallet SDK uses features older versions lack. Install a current Node.js (https://nodejs.org) and run the command again.`);this.name="UnsupportedNodeError",Object.setPrototypeOf(this,Uo.prototype)}}function ac(e=process.versions){if(e.bun!==void 0)return;let t=Number(e.node.split(".")[0]);if(!Number.isInteger(t)||t<22)throw new Uo(e.node)}Me();function Qm(e){if(typeof e==="string")return jo(e)?ss(e):e;let t=Buffer.from(e.buffer,e.byteOffset,e.byteLength).toString("utf8");if(!jo(t))return e;let r=ss(t);return r===t?e:Buffer.from(r,"utf8")}function fc(e){return function(t,...r){return e.call(this,Qm(t),...r)}}var mc=!1;function gc(){if(mc)return;mc=!0,process.stdout.write=fc(process.stdout.write),process.stderr.write=fc(process.stderr.write)}var Tm="midnight-wallet://skill/core",Nm="midnight-wallet://skill/full",eC="midnight-wallet://skill",tC=Am(new URL("../docs/SKILL-CORE.md",import.meta.url)),rC=Am(new URL("../docs/SKILL.md",import.meta.url));function ye(e,t,r){let n={json:!0},s=[];for(let[o,i]of Object.entries(t)){if(i===void 0||i===null)continue;let a=o==="full"?qr:o;if(typeof i==="boolean"){if(i)n[a]=!0}else n[a]=String(i)}return{command:e,subcommand:r,positionals:s,flags:n}}function Cm(e){let t=ye("transfer",e,e.to);return t.positionals=e.amount===void 0?[]:[String(e.amount)],delete t.flags.to,delete t.flags.amount,t}var Ot={wallet:{type:"string",description:"The wallet that owns the account and pays the fees"},network:{type:"string",enum:["undeployed"],description:"Only undeployed (a local ledger-9 stack)"},"account-build":{type:"string",description:"A local account build's directory, to drive instead of the installed account package (default: the account-build config key)"}};function je(e,t,r,n={}){let s=ye("grant",t,e);if(r!==void 0){if(t[r]!==void 0)s.positionals=[String(t[r])];delete s.flags[r]}return Object.assign(s.flags,n),s}async function go(e,t){await Promise.resolve().then(() => Ks());await Fr(e),await ho(t)}async function ho(e){await Promise.resolve().then(() => Pe());ce(oe(e.wallet))}var nC={generate:()=>Promise.resolve().then(() => (Zl(),Xl)),info:()=>Promise.resolve().then(() => (tu(),eu)),balance:()=>Promise.resolve().then(() => (yu(),wu)),address:()=>Promise.resolve().then(() => (vu(),bu)),"genesis-address":()=>Promise.resolve().then(() => (xu(),Cu)),"inspect-cost":()=>Promise.resolve().then(() => (Du(),Ru)),airdrop:()=>Promise.resolve().then(() => (Ou(),$u)),transfer:()=>Promise.resolve().then(() => (Bu(),Lu)),dust:()=>Promise.resolve().then(() => (Ku(),Gu)),cache:()=>Promise.resolve().then(() => (qu(),Vu)),config:()=>Promise.resolve().then(() => (Xu(),Yu)),localnet:()=>Promise.resolve().then(() => (yp(),wp)),wallet:()=>Promise.resolve().then(() => (Cp(),kp)),status:()=>Promise.resolve().then(() => (Ip(),Dp)),contract:()=>Promise.resolve().then(() => (Kp(),Gp)),grant:()=>Promise.resolve().then(() => (Xp(),Yp)),test:()=>Promise.resolve().then(() => (vm(),bm))};async function G(e){let t=nC[e];if(!t)throw Error(`Unknown command handler: ${e}`);return(await t()).default}var yo=[{name:"midnight_wallet_generate",description:"Create wallet.",annotations:{destructiveHint:!0},inputSchema:{type:"object",properties:{name:{type:"string"},network:{type:"string",enum:["preprod","preview","undeployed"]},seed:{type:"string",description:"64 or 128 hex chars (32-byte raw or 64-byte BIP-39)"},mnemonic:{type:"string",description:"BIP-39 24 words"},force:{type:"string"}},required:["name"]},async handler(e){let t=e.name,r=ye("wallet",e,"generate");if(r.positionals=[t],delete r.flags.name,e.force==="true"||e.force===!0)r.flags.force=!0;let n=await G("wallet");return W(n,r)}},{name:"midnight_wallet_list",description:"List wallets. Default: per-wallet { name, active, network, address, shieldedAddress } scoped to the active network. Pass { full: true } for the 3-network addresses + shieldedAddresses maps.",annotations:{readOnlyHint:!0,idempotentHint:!0},inputSchema:{type:"object",properties:{full:{type:"boolean",description:"Return full per-network addresses + shieldedAddresses maps (the same shape `mn wallet list --json` emits). Default false (slim)."}}},async handler({full:e}={}){let t={json:!0};if(e)t[qr]=!0;let r={command:"wallet",subcommand:"list",positionals:[],flags:t},n=await G("wallet");return W(n,r)}},{name:"midnight_wallet_use",description:"Set active wallet.",annotations:{idempotentHint:!0},inputSchema:{type:"object",properties:{name:{type:"string"}},required:["name"]},async handler(e){let r={command:"wallet",subcommand:"use",positionals:[e.name],flags:{json:!0}},n=await G("wallet");return W(n,r)}},{name:"midnight_wallet_info",description:"Show wallet details. Default: { name, active, network, address, shieldedAddress } scoped to the active network. Pass { full: true } for the per-network maps + createdAt + file path.",annotations:{readOnlyHint:!0,idempotentHint:!0},inputSchema:{type:"object",properties:{name:{type:"string"},full:{type:"boolean",description:"Return the full per-network addresses + shieldedAddresses maps and bookkeeping fields (matches `mn wallet info <name> --json`). Default false (slim)."}}},async handler(e){let{name:t,full:r}=e,n={json:!0};if(r)n[qr]=!0;let s={command:"wallet",subcommand:"info",positionals:t?[t]:[],flags:n},o=await G("wallet");return W(o,s)}},{name:"midnight_wallet_remove",description:"Remove wallet.",annotations:{destructiveHint:!0},inputSchema:{type:"object",properties:{name:{type:"string"}},required:["name"]},async handler(e){let r={command:"wallet",subcommand:"remove",positionals:[e.name],flags:{json:!0}},n=await G("wallet");return W(n,r)}},{name:"midnight_info",description:"Wallet metadata.",annotations:{readOnlyHint:!0,idempotentHint:!0},inputSchema:{type:"object",properties:{wallet:{type:"string"}}},async handler(e){let t=ye("info",e),r=await G("info");return W(r,t)}},{name:"midnight_balance",description:"NIGHT balance. Default: { network, unshielded, shielded } — no echoed addresses. Pass { full: true } for the human shape including address + shieldedAddress.",annotations:{readOnlyHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{address:{type:"string"},wallet:{type:"string"},network:{type:"string",enum:["preprod","preview","undeployed"]},"indexer-ws":{type:"string"},full:{type:"boolean",description:"Include the queried address + shieldedAddress in the response (matches `mn balance --json`). Default false (slim)."}}},async handler(e){let t=e.address,r=ye("balance",e,t);delete r.flags.address;let n=await G("balance");return W(n,r)}},{name:"midnight_address",description:"Derive address from seed.",annotations:{readOnlyHint:!0,idempotentHint:!0},inputSchema:{type:"object",properties:{seed:{type:"string",description:"64 or 128 hex chars (32-byte raw or 64-byte BIP-39)"},network:{type:"string",enum:["preprod","preview","undeployed"]},index:{type:"string"}},required:["seed"]},async handler(e){let t=ye("address",e),r=await G("address");return W(r,t)}},{name:"midnight_genesis_address",description:"Genesis address.",annotations:{readOnlyHint:!0,idempotentHint:!0},inputSchema:{type:"object",properties:{network:{type:"string",enum:["preprod","preview","undeployed"]}}},async handler(e){let t=ye("genesis-address",e),r=await G("genesis-address");return W(r,t)}},{name:"midnight_inspect_cost",description:"The chain's current block limits, from its latest block's ledger parameters.",annotations:{readOnlyHint:!0,idempotentHint:!0},inputSchema:{type:"object",properties:{network:{type:"string",description:"Network to read (default: the selected one)"}}},async handler(e){let t=ye("inspect-cost",e.network?{network:e.network}:{}),r=await G("inspect-cost");return W(r,t)}},{name:"midnight_airdrop",description:'Fund from genesis (undeployed). `wallet` accepts a wallet name, a wallet JSON path, or a raw bech32m address (mn_addr_… or mn_shield-addr_…). Add `shielded: "true"` to fund a shielded balance.',annotations:{destructiveHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{amount:{type:"string",description:"NIGHT"},wallet:{type:"string",description:"Destination: wallet name, JSON path, or bech32m address"},shielded:{type:"string",description:'Set to "true" for shielded airdrop'}},required:["amount"]},async handler(e){let t=e.amount,r=ye("airdrop",e,t);delete r.flags.amount;let n=await G("airdrop");return W(n,r)}},{name:"midnight_transfer",description:"Send NIGHT (returns pending token; see skill).",annotations:{destructiveHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{to:{type:"string",description:"bech32m"},amount:{type:"string",description:"NIGHT"},wallet:{type:"string"}},required:["to","amount"]},async handler(e){let t=await G("transfer");return W(t,Cm(e))},async check(e){await Promise.resolve().then(() => sa());Zs(Cm(e))}},{name:"midnight_dust_register",description:"Register for dust.",annotations:{destructiveHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{wallet:{type:"string"}}},async handler(e){let t=ye("dust",e,"register"),r=await G("dust");return W(r,t)}},{name:"midnight_dust_status",description:"Dust status. Default: { network, registered, registeredUtxos, unregisteredUtxos, dustBalance, dustAvailable }. Pass { full: true } for sync internals (eventsApplied, ownedUtxos, cached).",annotations:{readOnlyHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{wallet:{type:"string"},"proof-server":{type:"string"},node:{type:"string"},"indexer-ws":{type:"string"},"no-cache":{type:"string"},full:{type:"boolean",description:"Include sync internals (eventsApplied, ownedUtxos, cached) in the response (matches `mn dust status --json`). Default false (slim)."}}},async handler(e){let t=ye("dust",e,"status"),r=await G("dust");return W(r,t)}},{name:"midnight_config_get",description:"Read config.",annotations:{readOnlyHint:!0,idempotentHint:!0},inputSchema:{type:"object",properties:{key:{type:"string"},network:{type:"string",description:"For node / indexer-ws / proof-server: the network to read or write them for (default: the selected network)"}},required:["key"]},async handler(e){let r={command:"config",subcommand:"get",positionals:[e.key],flags:{json:!0,...e.network?{network:e.network}:{}}},n=await G("config");return W(n,r)}},{name:"midnight_config_set",description:"Write config.",annotations:{idempotentHint:!0},inputSchema:{type:"object",properties:{key:{type:"string"},network:{type:"string",description:"For node / indexer-ws / proof-server: the network to read or write them for (default: the selected network)"},value:{type:"string"}},required:["key","value"]},async handler(e){let{key:t,value:r}=e,n={command:"config",subcommand:"set",positionals:[t,r],flags:{json:!0,...e.network?{network:e.network}:{}}},s=await G("config");return W(s,n)}},{name:"midnight_cache_clear",description:"Clear sync cache.",annotations:{destructiveHint:!0,idempotentHint:!0},inputSchema:{type:"object",properties:{network:{type:"string",enum:["preprod","preview","undeployed"]},wallet:{type:"string"}}},async handler(e){let t=ye("cache",e,"clear"),r=await G("cache");return W(r,t)}},{name:"midnight_config_unset",description:"Reset config.",annotations:{idempotentHint:!0},inputSchema:{type:"object",properties:{key:{type:"string"},network:{type:"string",description:"For node / indexer-ws / proof-server: the network to read or write them for (default: the selected network)"}},required:["key"]},async handler(e){let r={command:"config",subcommand:"unset",positionals:[e.key],flags:{json:!0,...e.network?{network:e.network}:{}}},n=await G("config");return W(n,r)}},{name:"midnight_localnet_up",description:"Refused on this ledger-9 build: mn's localnet is ledger 8 and no ledger-9 indexer image is published. Run a ledger-9 stack yourself and point mn at it (config_set node / indexer-ws / proof-server).",annotations:{openWorldHint:!0},inputSchema:{type:"object",properties:{}},async handler(){let e={command:"localnet",subcommand:"up",positionals:[],flags:{json:!0}},t=await G("localnet");return W(t,e)}},{name:"midnight_localnet_stop",description:"Stop localnet (preserves state).",annotations:{idempotentHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{}},async handler(){let e={command:"localnet",subcommand:"stop",positionals:[],flags:{json:!0}},t=await G("localnet");return W(t,e)}},{name:"midnight_localnet_down",description:"Localnet teardown (volumes + undeployed cache).",annotations:{destructiveHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{}},async handler(){let e={command:"localnet",subcommand:"down",positionals:[],flags:{json:!0}},t=await G("localnet");return W(t,e)}},{name:"midnight_localnet_status",description:"Localnet status.",annotations:{readOnlyHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{}},async handler(){let e={command:"localnet",subcommand:"status",positionals:[],flags:{json:!0}},t=await G("localnet");return W(t,e)}},{name:"midnight_localnet_clean",description:"Remove stray containers.",annotations:{destructiveHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{}},async handler(){let e={command:"localnet",subcommand:"clean",positionals:[],flags:{json:!0}},t=await G("localnet");return W(t,e)}},{name:"midnight_contract_inspect",description:"Inspect a compiled Compact contract: name, circuits (with arg/return types), witnesses, compiler/language/runtime versions. Reads managed/<name>/compiler/contract-info.json under the dapp dir. Returns a `siblings` array listing other contracts in the same project — call again with `name` to inspect a sibling.",annotations:{readOnlyHint:!0,idempotentHint:!0},inputSchema:{type:"object",properties:{path:{type:"string",description:"Path to dApp directory (defaults to cwd)"},managed:{type:"string",description:"Direct path to a managed/<name>/ directory (overrides path)"},name:{type:"string",description:"Specific contract name to inspect when the project has multiple (see siblings field)"}}},async handler(e){let t=ye("contract",e,"inspect"),r=await G("contract");return W(r,t)}},{name:"midnight_contract_state",description:"Read the current ledger state of a deployed contract. Returns the ledger fields as a JSON object.",annotations:{readOnlyHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{address:{type:"string",description:"Contract address (hex)"},wallet:{type:"string"},network:{type:"string",enum:["preprod","preview","undeployed"]},path:{type:"string",description:"dApp directory (defaults to cwd; needed to find the compiled artifact for state decoding)"},managed:{type:"string",description:"Direct path to a managed/<name>/ directory (overrides path-based contract scan)"},name:{type:"string",description:"Specific contract name when the project has multiple"}},required:["address"]},async handler(e){let t=ye("contract",e,"state"),r=await G("contract");return W(r,t)}},{name:"midnight_contract_deploy",description:"Deploy a compiled Compact contract (returns pending token; agent must show the description and redeem via midnight_confirm_operation).",annotations:{destructiveHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{wallet:{type:"string"},network:{type:"string",enum:["preprod","preview","undeployed"]},args:{type:"string",description:"JSON-encoded array or object of constructor arguments"},path:{type:"string",description:"dApp directory (defaults to cwd)"},managed:{type:"string",description:"Direct path to a managed/<name>/ directory (overrides path-based contract scan)"},name:{type:"string",description:"Specific contract name when the project has multiple"}}},async handler(e){let t=ye("contract",e,"deploy"),r=await G("contract");return W(r,t)},async check(e){await Promise.resolve().then(() => lo());ao(ye("contract",e,"deploy")),await ho(e)}},{name:"midnight_contract_call",description:"Call a circuit on a deployed contract (returns pending token; agent must show the description and redeem via midnight_confirm_operation).",annotations:{destructiveHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{address:{type:"string",description:"Contract address (hex)"},circuit:{type:"string",description:"Circuit name to invoke"},wallet:{type:"string"},network:{type:"string",enum:["preprod","preview","undeployed"]},args:{type:"string",description:"JSON-encoded array or object of circuit arguments"},path:{type:"string",description:"dApp directory (defaults to cwd)"},managed:{type:"string",description:"Direct path to a managed/<name>/ directory (overrides path-based contract scan)"},name:{type:"string",description:"Specific contract name when the project has multiple"}},required:["address","circuit"]},async handler(e){let t=ye("contract",e,"call"),r=await G("contract");return W(r,t)},async check(e){await Promise.resolve().then(() => lo());co(ye("contract",e,"call")),await ho(e)}},{name:"midnight_grant_status",description:"The wallet's account: address, owner key, what it holds, number of grants (see skill).",annotations:{readOnlyHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{...Ot}},async handler(e){return W(await G("grant"),je("status",e))}},{name:"midnight_grant_list",description:"Every grant on the wallet's account, with its limits and whether it is live.",annotations:{readOnlyHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{...Ot}},async handler(e){return W(await G("grant"),je("list",e))}},{name:"midnight_grant_request",description:"What issuing from an agent's grant request link would grant: who spends, who they can pay, and the limits (the account build's defaults for any not given). Issues nothing. Show the user this before midnight_grant_issue.",annotations:{readOnlyHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{link:{type:"string",description:"The grant request link"},cap:{type:"string",description:"Most the grant may ever pay (smallest unit)"},"per-call":{type:"string",description:"Most one payment may be"},"max-coin":{type:"string",description:"Largest coin the agent may take to pay from"},"expires-in":{type:"string",description:"Seconds the grant lasts"},...Ot},required:["link"]},async handler(e){return W(await G("grant"),je("issue",e,"link"))}},{name:"midnight_grant_deploy",description:"Deploy the wallet's account and activate its owner key (returns pending token). Takes about 48 DUST from the wallet (17 at once for the largest of five transactions) and a few minutes. The owner key is a random development key the mnemonic can't recover: dev-owner-key must be true.",annotations:{destructiveHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{"dev-owner-key":{type:"boolean",description:"Accept a development owner key"},...Ot}},async handler(e){return W(await G("grant"),je("deploy",e))},async check(e){await go(je("deploy",e),e)}},{name:"midnight_grant_deposit",description:"Move shielded NIGHT from the wallet into its account, where a grant lets an agent spend it (returns pending token). The wallet needs that much shielded NIGHT, plus Dust for the fee. mn has no command to take it back out.",annotations:{destructiveHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{amount:{type:"string",description:'NIGHT to deposit, e.g. "2" (up to 6 decimals)'},...Ot},required:["amount"]},async handler(e){return W(await G("grant"),je("deposit",e,"amount"))},async check(e){let t=je("deposit",e,"amount");await Promise.resolve().then(() => Ks());let{request:n,walletName:s,target:o,account:i}=await Fr(t);if(await ho(e),n.subcommand!=="deposit"||i===null)throw Error("A deposit was prepared as something else");return`Deposit ${n.amount} shielded NIGHT (${n.value} in the smallest unit) from wallet ${s} into its account ${i.address} on ${o.network}`}},{name:"midnight_grant_issue",description:"Issue a grant from an agent's request link (returns pending token, whose description gives the grant's terms as the account build read them). Lets that agent spend from the account within the limits.",annotations:{destructiveHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{link:{type:"string",description:"The grant request link"},cap:{type:"string",description:"Most the grant may ever pay (smallest unit)"},"per-call":{type:"string",description:"Most one payment may be"},"max-coin":{type:"string",description:"Largest coin the agent may take to pay from"},"expires-in":{type:"string",description:"Seconds the grant lasts"},...Ot},required:["link"]},async handler(e){return W(await G("grant"),je("issue",e,"link",{yes:!0}))},async check(e){await go(je("issue",e,"link",{yes:!0}),e);let t=await W(await G("grant"),je("issue",e,"link"));await Promise.resolve().then(() => Gs());return`Issue a grant on ${t.wallet}'s account on ${t.network}, letting an agent spend from it within these terms (amounts in the token's smallest unit; limits not given took the account build's defaults): ${Kl(t.request)}`}},{name:"midnight_grant_revoke",description:"Revoke one grant, by its id or slot (returns pending token).",annotations:{destructiveHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{grant:{type:"string",description:"Grant id (64 hex) or slot number"},...Ot},required:["grant"]},async handler(e){return W(await G("grant"),je("revoke",e,"grant"))},async check(e){await go(je("revoke",e,"grant"),e)}},{name:"midnight_grant_revoke_all",description:"Revoke every grant on the wallet's account (returns pending token).",annotations:{destructiveHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{...Ot}},async handler(e){return W(await G("grant"),je("revoke-all",e))},async check(e){await go(je("revoke-all",e),e)}},{name:"midnight_test_create",description:"Generate a test scaffold for the contract. Two paths: (1) AI-assisted — pass `goal` (and optionally `screen` for UI strategy) and the scaffold is generated by Claude reading the contract + screen source, producing a focused suite with realistic args / on-screen labels. (2) Deterministic — pass `no-ai: true` (or omit goal/screen in non-interactive mode) for boilerplate scaffolds that the user reviews. CLI strategy emits dapp.test.json + tests/suites/<name>/{suite,actions,assertions}.json. Browser strategy emits prompt.md instead of actions.json plus the browser fields in dapp.test.json — required: port, build-cmd. Use force:true to overwrite.",annotations:{destructiveHint:!0},inputSchema:{type:"object",properties:{path:{type:"string",description:"dApp directory (defaults to cwd)"},name:{type:"string",description:"Specific contract name when the project has multiple"},suite:{type:"string",description:"Suite directory name under tests/suites/ (auto-derived from circuit/screen when AI scaffolds)"},strategy:{type:"string",enum:["cli","browser"],description:"cli (default): drive contracts via actions.json. browser: drive a real UI via Claude + Chrome via prompt.md."},network:{type:"string",enum:["preprod","preview","undeployed"]},goal:{type:"string",description:'AI mode: one-line success criterion this suite should verify (e.g. "round goes from 0 to 1 after increment"). Triggers AI scaffolding.'},screen:{type:"string",description:'AI mode + browser strategy: name of the screen component to focus on (e.g. "loan-request-form" or "LoanRequestForm"). Auto-discovered from src/components, src/pages, src/screens.'},"no-ai":{type:"boolean",description:"Force deterministic scaffolder even when claude CLI is available."},port:{type:"string",description:'Browser strategy only — dev server port (e.g. "4173").'},"build-cmd":{type:"string",description:'Browser strategy only — shell command that builds + serves the UI (e.g. "npm run dev").'},"build-dir":{type:"string",description:"Browser strategy only — subdir the build runs in (monorepo case)."},url:{type:"string",description:"Browser strategy only — full URL Claude opens (default http://localhost:<port>/)."},"browser-mode":{type:"string",enum:["dom","vision","script"],description:"Browser strategy only — how Claude perceives the page. dom (HTML/React UIs, fast, needs chrome-devtools-mcp), vision (canvas games, slow), script (advanced, needs hooks). Default: dom for AI scaffolds."},force:{type:"boolean",description:"Overwrite existing files instead of aborting on collision"}}},async handler(e){let t=ye("test",e,"create"),r=await G("test");return W(r,t)}},{name:"midnight_localnet_logs",description:"Snapshot of recent localnet logs (last N lines per service, no streaming). Returns { tail, lines: string[] }.",annotations:{readOnlyHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{tail:{type:"string",description:"Number of lines to retrieve (default 200)"}}},async handler(e){let t=ye("localnet",e,"logs");if(!t.flags.tail)t.flags.tail="200";let r=await G("localnet");return W(r,t)}},{name:"midnight_confirm_operation",description:"Redeem a pending token (confirm step).",annotations:{destructiveHint:!0,openWorldHint:!0},inputSchema:{type:"object",properties:{token:{type:"string"}},required:["token"]},async handler(){throw Error("midnight_confirm_operation reached the inner handler — this is an MCP wiring bug")}}],sC=new Set(yo.filter((e)=>e.check!==void 0).map((e)=>e.name)),xm=Ha();function oC(e,t){let r=t.network??"active network",n=t.wallet??"active wallet";switch(e){case"midnight_transfer":return`Send ${t.amount} NIGHT from ${n} to ${t.to} on ${r}`;case"midnight_contract_deploy":{let s=t.args?` with args ${t.args}`:"";return`Deploy contract from ${t.path??"current directory"} as ${n} on ${r}${s}`}case"midnight_contract_call":{let s=t.args?` with args ${t.args}`:"";return`Call circuit ${t.circuit} on contract ${t.address} as ${n} on ${r}${s}`}case"midnight_grant_deploy":return`Deploy an account for ${n} on ${r}, on a development owner key the wallet's mnemonic can't recover`;case"midnight_grant_revoke":return`Revoke grant ${t.grant} on ${n}'s account on ${r}`;case"midnight_grant_revoke_all":return`Revoke every grant on ${n}'s account on ${r}`;default:return`Execute ${e} with ${JSON.stringify(t)}`}}var Bn=new qk({name:"midnight-wallet-cli",version:No},{capabilities:{tools:{},resources:{}}});Bn.setRequestHandler(Zk,async()=>({resources:[{uri:Tm,name:"midnight-wallet skill (core)",description:"Read this first. Intent routing table + non-negotiable safety rules. ~830 tokens. Fetch /full on demand for canonical flows, error recovery, and concept primers.",mimeType:"text/markdown"},{uri:Nm,name:"midnight-wallet skill (full)",description:"Canonical multi-step flows, error-recovery recipes, concept primers (NIGHT/DUST/shielded), network selection. Fetch on demand when you hit an error, start a multi-step flow, or need to explain a concept.",mimeType:"text/markdown"}]}));Bn.setRequestHandler(Qk,async(e)=>{let t=e.params.uri;if(t===Tm){let r=km(tC,"utf-8");return{contents:[{uri:t,mimeType:"text/markdown",text:r}]}}if(t===Nm||t===eC){let r=km(rC,"utf-8");return{contents:[{uri:t,mimeType:"text/markdown",text:r}]}}throw Error(`Unknown resource: ${t}`)});Bn.setRequestHandler(Yk,async()=>({tools:yo.map((e)=>({name:e.name,description:e.description,inputSchema:e.inputSchema,...e.annotations?{annotations:e.annotations}:{}}))}));Bn.setRequestHandler(Xk,async(e)=>{let{name:t,arguments:r}=e.params,n=r??{};if(t==="midnight_confirm_operation"){let s=typeof n.token==="string"?n.token:"",o=xm.redeem(s);if(!o)return wo(Error("Unknown or expired confirmation token. The first-step tool call may need to be re-issued."));return Em(o.tool,o.args)}if(sC.has(t)){let s;try{s=await yo.find((i)=>i.name===t)?.check?.(n)}catch(i){return wo(i instanceof Error?i:Error(String(i)))}let o=xm.create({tool:t,args:n,description:s??oC(t,n)});return{content:[{type:"text",text:JSON.stringify(Ma({pending:!0,token:o.token,description:o.description,tool:o.tool,expiresAt:new Date(o.expiresAt).toISOString(),nextStep:"Show the description to the user, get explicit consent, then call midnight_confirm_operation with this token."}),null,2)}]}}return Em(t,n)});function Ma(e){return{...e,_serverVersion:No}}async function Em(e,t){let r=yo.find((n)=>n.name===e);if(!r)return wo(Error(`Unknown tool: ${e}`));try{let n=await r.handler(t);return{content:[{type:"text",text:JSON.stringify(Ma(n),null,2)}]}}catch(n){return wo(n instanceof Error?n:Error(String(n)))}}function wo(e){let{errorCode:t}=Hn(e);return{content:[{type:"text",text:JSON.stringify(Ma({error:!0,code:t,message:ja(e.message)}))}],isError:!0}}async function iC(){ac(),gc(),await ic();let e=new zk;await Bn.connect(e)}iC().catch((e)=>{process.stderr.write(`MCP server error: ${e.message}
|
|
1438
1438
|
`),process.exit(1)});
|