midnight-wallet-cli 0.1.8 → 0.1.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 +97 -97
- package/dist/wallet.js +110 -110
- package/package.json +1 -1
package/dist/wallet.js
CHANGED
|
@@ -1,42 +1,42 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var
|
|
3
|
-
`);for(let B of
|
|
2
|
+
var L2=Object.defineProperty;var S=($,Z)=>{for(var Q in Z)L2($,Q,{get:Z[Q],enumerable:!0,configurable:!0,set:(X)=>Z[Q]=()=>X})};var O=($,Z)=>()=>($&&(Z=$($=0)),Z);function o1($){let Z=$??process.argv.slice(2),Q=[],X={},q=0;while(q<Z.length){let z=Z[q];if(z.startsWith("--")){let Y=z.slice(2),K=Z[q+1];if(K!==void 0&&!K.startsWith("-"))X[Y]=K,q+=2;else X[Y]=!0,q+=1}else if(z.startsWith("-")&&z.length===2){let Y=z.slice(1),K=Z[q+1];if(K!==void 0&&!K.startsWith("-"))X[Y]=K,q+=2;else X[Y]=!0,q+=1}else Q.push(z),q+=1}return{command:Q[0],subcommand:Q[1],positionals:Q.slice(2),flags:X}}function A($,Z){let Q=$.flags[Z];if(Q===void 0||Q===!0)return;return Q}function P($,Z){return Z in $.flags}function n1($,Z,Q){let X=A($,Z);if(X===void 0)throw new Error(`Missing required flag: --${Z} <${Q}>`);return X}var D0="0000000000000000000000000000000000000000000000000000000000000001",a1="0000000000000000000000000000000000000000000000000000000000000000",s0=6,t1=1e6,r1=1000000000000n,s1=5,e1=300000,$3=1e4,R0=120000,Z3=300000,e0=60000,$1=10,x0=3,Q3=600000,E0=15000,X3=115,m=".midnight",J0="wallet.json",q3="config.json",Q0=448,N0=384,z3="localnet";function i(){return!("NO_COLOR"in process.env)}function K0($,Z){if(!i())return $;return`\x1B[38;5;${Z}m${$}\x1B[0m`}function y($){if(!i())return $;return`\x1B[1m${$}\x1B[0m`}function j($){if(!i())return $;return`\x1B[2m${$}\x1B[0m`}function t($){return K0($,38)}function f($){return K0($,196)}function o($){return K0($,40)}function j0($){return K0($,226)}function F0($){return K0($,15)}function G0($){return K0($,245)}function I($,Z=J3){let Q=` ${$} `,X=Z-Q.length;if(X<=0)return y(Q);let q=Math.floor(X/2),z=X-q;return y("═".repeat(q)+Q+"═".repeat(z))}function D($=J3){return j("─".repeat($))}function H($,Z,Q=16){let X=($+":").padEnd(Q);return` ${G0(X)}${Z}`}function O0($){let Z=$<0n,Q=Z?-$:$,X=BigInt(10**s0),q=Q/X,Y=(Q%X).toString().padStart(s0,"0");return`${Z?"-":""}${q}.${Y}`}function v0($){return`${O0($)} NIGHT`}function L0($){let Z=$<0n,Q=Z?-$:$,X=10n**BigInt(Y3),q=Q/X,K=(Q%X).toString().padStart(Y3,"0").replace(/0+$/,"").padEnd(6,"0");return`${Z?"-":""}${q}.${K}`}function k0($){return`${L0($)} DUST`}function E($,Z=!1){let Q=Z&&$.length>20?$.slice(0,10)+"…"+$.slice(-8):$;return t(Q)}function y2($,Z){if(P0($).length<=Z)return[$];let X=$.split(/(\s+)/),q=[],z="",Y=0;for(let K of X){let G=P0(K).length;if(Y+G>Z&&Y>0)q.push(z),z=K.trimStart(),Y=P0(z).length;else z+=K,Y+=G}if(z.length>0)q.push(z);return q}function T2($,Z="light",Q=70){let X=Z==="heavy"?{tl:"╔",tr:"╗",bl:"╚",br:"╝",h:"═",v:"║"}:{tl:"┌",tr:"┐",bl:"└",br:"┘",h:"─",v:"│"},q=Q-4,z=[];for(let J of $){let W=J.split(`
|
|
3
|
+
`);for(let B of W)z.push(...y2(B,q))}let Y=Math.max(...z.map((J)=>P0(J).length)),K=Math.max(Y+2,20),G=X.tl+X.h.repeat(K)+X.tr,U=X.bl+X.h.repeat(K)+X.br,V=z.map((J)=>{let W=P0(J).length,B=K-W-2;return`${X.v} ${J}${" ".repeat(Math.max(0,B))} ${X.v}`});return[G,...V,U].join(`
|
|
4
4
|
`)}function K3($,Z){let X=$.split(`
|
|
5
|
-
`).map((z,Y)=>Y===0?
|
|
6
|
-
`)}var J3=60,Y3=15,
|
|
7
|
-
`;if(
|
|
8
|
-
`)}var
|
|
9
|
-
`)){if(!Q)continue;let[X,q]=Q.split("|"),z=(Y)=>{let K=new RegExp(`0\\.0\\.0\\.0:(\\d+)->${Y}/tcp`),G=q?.match(K);return G?parseInt(G[1],10):void 0};if(X.includes("indexer-standalone")||X.includes("indexer")){let Y=z(8088);if(Y)Z.indexerPort=Y}if(X.includes("midnight-node")){let Y=z(9944);if(Y)Z.nodePort=Y}if(X.includes("proof-server")){let Y=z(6300);if(Y)Z.proofServerPort=Y}}return Z}catch{return{}}}function O3($){let Z=
|
|
10
|
-
`,{mode:
|
|
11
|
-
Valid keys: ${
|
|
5
|
+
`).map((z,Y)=>Y===0?f(y("Error: "))+f(z):f(z));if(Z)X.push(""),X.push(j("Suggestion: ")+Z);let q=T2(X,"heavy");if(i())return q.replace(/[╔╗╚╝═║]/g,(z)=>f(z));return q}function X0($,Z){let X=[`${o("✓")} ${$}`];if(Z)X.push(H("Transaction",t(Z)));return X.join(`
|
|
6
|
+
`)}var J3=60,Y3=15,P0=($)=>$.replace(/\x1b\[[0-9;]*m/g,"");var N=()=>{};function y0($){let Z=($.message??"").toLowerCase();if(Z.includes("operation cancelled")||Z.includes("operation aborted")||Z==="cancelled"||Z==="aborted")return{exitCode:7,errorCode:g.CANCELLED};if(Z.includes("wallet file not found")||Z.includes("wallet")&&Z.includes("not found"))return{exitCode:3,errorCode:g.WALLET_NOT_FOUND};if(Z.includes("missing required flag")||Z.includes("missing amount")||Z.includes("missing recipient")||Z.includes("missing config key")||Z.includes("missing or invalid subcommand")||Z.includes("unknown command")||Z.includes("cannot specify both")||Z.includes("invalid bip-39")||Z.includes("seed must be")||Z.includes("key index must be")||Z.includes("usage:"))return{exitCode:2,errorCode:g.INVALID_ARGS};if(Z.includes("proof")&&Z.includes("timeout"))return{exitCode:6,errorCode:g.PROOF_TIMEOUT};if(Z.includes("stale utxo")||Z.includes("error code 115")||Z.includes("errorcode: 115"))return{exitCode:6,errorCode:g.STALE_UTXO};if(Z.includes("no dust")||Z.includes("dust")&&(Z.includes("required")||Z.includes("available")||Z.includes("insufficient")))return{exitCode:5,errorCode:g.DUST_REQUIRED};if(Z.includes("insufficient")||Z.includes("not enough"))return{exitCode:5,errorCode:g.INSUFFICIENT_BALANCE};if(Z.includes("rejected")||Z.includes("transaction failed"))return{exitCode:6,errorCode:g.TX_REJECTED};if(Z.includes("econnrefused")||Z.includes("enotfound")||Z.includes("etimedout")||Z.includes("websocket")||Z.includes("connection refused")||Z.includes("network")&&Z.includes("error"))return{exitCode:4,errorCode:g.NETWORK_ERROR};return{exitCode:1,errorCode:g.UNKNOWN}}var g;var Z1=O(()=>{g={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",PROOF_TIMEOUT:"PROOF_TIMEOUT",DUST_REQUIRED:"DUST_REQUIRED",CANCELLED:"CANCELLED",UNKNOWN:"UNKNOWN"}});function G3(){let $=process.stderr.write;return process.stderr.write=()=>!0,()=>{process.stderr.write=$}}function X1($){Q1=$}function L($){let Z=JSON.stringify($)+`
|
|
7
|
+
`;if(Q1)Q1(Z);else process.stdout.write(Z)}function U3($,Z,Q){process.stdout.write(JSON.stringify({error:!0,code:Z,message:$.message,exitCode:Q})+`
|
|
8
|
+
`)}var Q1=null;var b0;var B3=O(()=>{b0={name:"midnight-wallet-cli",version:"0.1.9",type:"module",description:"Git-style CLI wallet for the Midnight blockchain",license:"Apache-2.0",bin:{midnight:"dist/wallet.js",mn:"dist/wallet.js","midnight-wallet-cli":"dist/wallet.js","midnight-wallet-mcp":"dist/mcp-server.js"},files:["dist"],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",prepublishOnly:"npm run build && npm run test",test:"vitest run","test:watch":"vitest",typecheck:"tsc --noEmit"},dependencies:{"@midnight-ntwrk/ledger-v7":"7.0.0","@midnight-ntwrk/midnight-js-network-id":"3.0.0","@midnight-ntwrk/midnight-js-types":"3.0.0","@midnight-ntwrk/wallet-sdk-abstractions":"1.0.0","@midnight-ntwrk/wallet-sdk-address-format":"3.0.0","@midnight-ntwrk/wallet-sdk-dust-wallet":"1.0.0","@midnight-ntwrk/wallet-sdk-facade":"1.0.0","@midnight-ntwrk/wallet-sdk-hd":"3.0.0","@midnight-ntwrk/wallet-sdk-shielded":"1.0.0","@midnight-ntwrk/wallet-sdk-unshielded-wallet":"1.0.0","@modelcontextprotocol/sdk":"^1.27.1","@scure/bip39":"^2.0.1",rxjs:"^7.8.1",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 V3,q0,W3;var w0=O(()=>{B3();V3=b0.name,q0=b0.version,W3=b0.description});async function R($,Z,Q){let X=[];X1((z)=>X.push(z));let q=process.stderr.write;process.stderr.write=()=>!0;try{Z.flags.json=!0,await $(Z,Q);let z=X.join("").trim();if(!z)return{};return JSON.parse(z)}finally{X1(null),process.stderr.write=q}}var H3=()=>{};import{HDWallet as I2,Roles as _2}from"@midnight-ntwrk/wallet-sdk-hd";import{createKeystore as A2,PublicKey as D2}from"@midnight-ntwrk/wallet-sdk-unshielded-wallet";import{NetworkId as q1}from"@midnight-ntwrk/wallet-sdk-abstractions";function U0($,Z,Q=0){let X=R2[Z],q=I2.fromSeed($);if(q.type!=="seedOk")throw new Error("Invalid seed for HD wallet");let z=q.hdWallet.selectAccount(0).selectRole(_2.NightExternal).deriveKeyAt(Q);if(z.type==="keyOutOfBounds")throw new Error(`Key index ${Q} out of bounds`);let Y=A2(z.key,X);return D2.fromKeyStore(Y).address}var R2;var S0=O(()=>{R2={preprod:q1.NetworkId.PreProd,preview:q1.NetworkId.Preview,undeployed:q1.NetworkId.Undeployed}});import{execSync as x2}from"child_process";function n($){return j3.includes($)}function N2($){return{...E2[$]}}function F3(){return j3}function P3($){if($.startsWith("mn_addr_preprod1"))return"preprod";if($.startsWith("mn_addr_preview1"))return"preview";if($.startsWith("mn_addr_undeployed1"))return"undeployed";return null}function v2(){try{let $=x2('docker ps --format "{{.Image}}|{{.Ports}}"',{encoding:"utf-8",timeout:5000}),Z={};for(let Q of $.trim().split(`
|
|
9
|
+
`)){if(!Q)continue;let[X,q]=Q.split("|"),z=(Y)=>{let K=new RegExp(`0\\.0\\.0\\.0:(\\d+)->${Y}/tcp`),G=q?.match(K);return G?parseInt(G[1],10):void 0};if(X.includes("indexer-standalone")||X.includes("indexer")){let Y=z(8088);if(Y)Z.indexerPort=Y}if(X.includes("midnight-node")){let Y=z(9944);if(Y)Z.nodePort=Y}if(X.includes("proof-server")){let Y=z(6300);if(Y)Z.proofServerPort=Y}}return Z}catch{return{}}}function O3($){let Z=N2($);if($==="undeployed"){let Q=v2();if(Q.indexerPort)Z.indexer=`http://localhost:${Q.indexerPort}/api/v3/graphql`,Z.indexerWS=`ws://localhost:${Q.indexerPort}/api/v3/graphql/ws`;if(Q.nodePort)Z.node=`ws://localhost:${Q.nodePort}`;if(Q.proofServerPort)Z.proofServer=`http://localhost:${Q.proofServerPort}`}return Z}var E2,j3;var C0=O(()=>{E2={preprod:{indexer:"https://indexer.preprod.midnight.network/api/v3/graphql",indexerWS:"wss://indexer.preprod.midnight.network/api/v3/graphql/ws",node:"wss://rpc.preprod.midnight.network",proofServer:"http://localhost:6300",networkId:"PreProd"},preview:{indexer:"https://indexer.preview.midnight.network/api/v3/graphql",indexerWS:"wss://indexer.preview.midnight.network/api/v3/graphql/ws",node:"wss://rpc.preview.midnight.network",proofServer:"http://localhost:6300",networkId:"Preview"},undeployed:{indexer:"http://localhost:8088/api/v3/graphql",indexerWS:"ws://localhost:8088/api/v3/graphql/ws",node:"ws://localhost:9944",proofServer:"http://localhost:6300",networkId:"Undeployed"}},j3=["preprod","preview","undeployed"]});import*as a from"fs";import*as z1 from"path";import{homedir as k2}from"os";function L3($){return $??z1.join(k2(),m)}function y3($){return z1.join(L3($),q3)}function b2($){let Z=L3($);if(!a.existsSync(Z))a.mkdirSync(Z,{recursive:!0,mode:Q0})}function h0($){let Z=y3($);if(!a.existsSync(Z))return{...f0};let Q;try{Q=a.readFileSync(Z,"utf-8")}catch{return{...f0}}let X;try{X=JSON.parse(Q)}catch{return{...f0}}return{network:X.network&&n(X.network)?X.network:f0.network}}function w2($,Z){b2(Z);let Q=y3(Z);a.writeFileSync(Q,JSON.stringify($,null,2)+`
|
|
10
|
+
`,{mode:N0})}function T3($,Z){let Q=h0(Z);if($==="network")return Q.network;throw new Error(`Unknown config key: "${$}"
|
|
11
|
+
Valid keys: ${Y1.join(", ")}`)}function M3($,Z,Q){let X=h0(Q);if($==="network"){if(!n(Z))throw new Error(`Invalid network: "${Z}"
|
|
12
12
|
Valid networks: preprod, preview, undeployed`);X.network=Z}else throw new Error(`Unknown config key: "${$}"
|
|
13
|
-
Valid keys: ${
|
|
14
|
-
Valid networks: ${F3().join(", ")}`);return Z}if($.walletNetwork&&
|
|
15
|
-
Generate a wallet first: midnight generate --network <name>`);let Q;try{Q=
|
|
16
|
-
${q.message}`)}let X;try{X=JSON.parse(Q)}catch{throw new Error(`Invalid JSON in wallet file: ${Z}`)}if(!X.seed||!X.network||!X.address||!X.createdAt){let q=["seed","network","address","createdAt"].filter((z)=>!X[z]);throw new Error(`Wallet file is missing required fields (${q.join(", ")}): ${Z}`)}if(!/^[0-9a-fA-F]+$/.test(X.seed))throw new Error(`Invalid seed format in wallet file (expected hex string): ${Z}`);if(!
|
|
17
|
-
Valid networks: preprod, preview, undeployed`);return X}function A3($,Z){let Q=Z?
|
|
18
|
-
`,{mode:
|
|
19
|
-
Use --force to overwrite, or --output <file> to save to a different path.`);let Y,K;if(X!==void 0){let J=X.replace(/^0x/,"");if(J.length!==64||!/^[0-9a-fA-F]+$/.test(J))throw new Error("Seed must be a 64-character hex string (32 bytes)");Y=Buffer.from(J,"hex")}else if(q!==void 0){if(!
|
|
13
|
+
Valid keys: ${Y1.join(", ")}`);w2(X,Q)}function J1(){return Y1}var f0,Y1;var K1=O(()=>{C0();f0={network:"undeployed"},Y1=["network"]});function z0($){let Z=A($.args,"network");if(Z!==void 0){if(!n(Z))throw new Error(`Invalid network: "${Z}"
|
|
14
|
+
Valid networks: ${F3().join(", ")}`);return Z}if($.walletNetwork&&n($.walletNetwork))return $.walletNetwork;if($.address){let X=P3($.address);if(X)return X}let Q=h0($.configDir);if(Q.network&&n(Q.network))return Q.network;return"undeployed"}function r($){let Z=z0($),Q=O3(Z);return{name:Z,config:Q}}var s=O(()=>{C0();K1()});import*as h from"fs";import*as e from"path";import{homedir as S2}from"os";function I3(){return e.join(S2(),m)}function _3(){return e.join(I3(),J0)}function C2(){let $=I3();if(!h.existsSync($))h.mkdirSync($,{recursive:!0,mode:Q0})}function d($){let Z=$?e.resolve($):_3();if(!h.existsSync(Z))throw new Error(`Wallet file not found: ${Z}
|
|
15
|
+
Generate a wallet first: midnight generate --network <name>`);let Q;try{Q=h.readFileSync(Z,"utf-8")}catch(q){throw new Error(`Failed to read wallet file: ${Z}
|
|
16
|
+
${q.message}`)}let X;try{X=JSON.parse(Q)}catch{throw new Error(`Invalid JSON in wallet file: ${Z}`)}if(!X.seed||!X.network||!X.address||!X.createdAt){let q=["seed","network","address","createdAt"].filter((z)=>!X[z]);throw new Error(`Wallet file is missing required fields (${q.join(", ")}): ${Z}`)}if(!/^[0-9a-fA-F]+$/.test(X.seed))throw new Error(`Invalid seed format in wallet file (expected hex string): ${Z}`);if(!n(X.network))throw new Error(`Invalid network "${X.network}" in wallet file: ${Z}
|
|
17
|
+
Valid networks: preprod, preview, undeployed`);return X}function A3($,Z){let Q=Z?e.resolve(Z):_3();if(!Z)C2();else{let X=e.dirname(Q);if(!h.existsSync(X))h.mkdirSync(X,{recursive:!0,mode:Q0})}return h.writeFileSync(Q,JSON.stringify($,null,2)+`
|
|
18
|
+
`,{mode:N0}),Q}var Y0=O(()=>{C0()});var G1={};S(G1,{default:()=>E3});import*as x3 from"fs";import*as p0 from"path";import{homedir as f2}from"os";import{generateMnemonic as h2,mnemonicToSeedSync as D3,validateMnemonic as p2}from"@scure/bip39";import{wordlist as R3}from"@scure/bip39/wordlists/english.js";async function E3($){let Z=z0({args:$}),Q=A($,"output"),X=A($,"seed"),q=A($,"mnemonic");if(X!==void 0&&q!==void 0)throw new Error("Cannot specify both --seed and --mnemonic. Use one or the other.");let z=Q?p0.resolve(Q):p0.join(f2(),m,J0);if(x3.existsSync(z)&&!P($,"force"))throw new Error(`Wallet file already exists: ${z}
|
|
19
|
+
Use --force to overwrite, or --output <file> to save to a different path.`);let Y,K;if(X!==void 0){let J=X.replace(/^0x/,"");if(J.length!==64||!/^[0-9a-fA-F]+$/.test(J))throw new Error("Seed must be a 64-character hex string (32 bytes)");Y=Buffer.from(J,"hex")}else if(q!==void 0){if(!p2(q,R3))throw new Error("Invalid BIP-39 mnemonic. Expected 12 or 24 words from the English wordlist.");K=q,Y=Buffer.from(D3(K).slice(0,32))}else K=h2(R3,256),Y=Buffer.from(D3(K).slice(0,32));let G=U0(Y,Z),U={seed:Y.toString("hex"),network:Z,address:G,createdAt:new Date().toISOString()};if(K)U.mnemonic=K;let V=A3(U,Q);if(P($,"json")){let J={address:G,network:Z,seed:Y.toString("hex"),file:V,createdAt:U.createdAt};if(K)J.mnemonic=K;L(J);return}if(process.stdout.write(G+`
|
|
20
20
|
`),process.stderr.write(`
|
|
21
|
-
`+
|
|
21
|
+
`+I("Wallet Generated")+`
|
|
22
22
|
|
|
23
23
|
`),process.stderr.write(H("Network",Z)+`
|
|
24
24
|
`),process.stderr.write(H("Address",E(G))+`
|
|
25
|
-
`),process.stderr.write(H("File",
|
|
25
|
+
`),process.stderr.write(H("File",V)+`
|
|
26
26
|
`),process.stderr.write(`
|
|
27
|
-
`),K)process.stderr.write(
|
|
27
|
+
`),K)process.stderr.write(j0(y(" MNEMONIC (save securely!):"))+`
|
|
28
28
|
`),process.stderr.write(` ${K}
|
|
29
29
|
|
|
30
|
-
`);process.stderr.write(
|
|
30
|
+
`);process.stderr.write(j0(y(" SEED (hex):"))+`
|
|
31
31
|
`),process.stderr.write(` ${Y.toString("hex")}
|
|
32
32
|
|
|
33
33
|
`),process.stderr.write(D()+`
|
|
34
34
|
`),process.stderr.write(j(" Next: midnight info | midnight balance")+`
|
|
35
35
|
|
|
36
|
-
`),process.stderr.write(
|
|
37
|
-
`)}var
|
|
36
|
+
`),process.stderr.write(o("✓")+` Wallet saved
|
|
37
|
+
`)}var U1=O(()=>{S0();s();Y0();N()});var B1={};S(B1,{default:()=>N3});import*as u0 from"path";import{homedir as u2}from"os";async function N3($){let Z=A($,"wallet"),Q=d(Z),X=Z?u0.resolve(Z):u0.join(u2(),m,J0);if(P($,"json")){L({address:Q.address,network:Q.network,createdAt:Q.createdAt,file:X});return}process.stdout.write(Q.address+`
|
|
38
38
|
`),process.stderr.write(`
|
|
39
|
-
`+
|
|
39
|
+
`+I("Wallet Info")+`
|
|
40
40
|
|
|
41
41
|
`),process.stderr.write(H("Address",E(Q.address))+`
|
|
42
42
|
`),process.stderr.write(H("Network",Q.network)+`
|
|
@@ -45,7 +45,7 @@ Use --force to overwrite, or --output <file> to save to a different path.`);let
|
|
|
45
45
|
`),process.stderr.write(`
|
|
46
46
|
`+D()+`
|
|
47
47
|
|
|
48
|
-
`)}var
|
|
48
|
+
`)}var V1=O(()=>{Y0();N();N()});import c2 from"ws";function v3($,Z,Q){return new Promise((X,q)=>{let z=new c2(Z,["graphql-transport-ws"]),Y=new Map,K=0,G=0,U=0,V=!1,J=!1,W,B=()=>{let _=new Map,T=0;for(let k of Y.values())if(!k.spent){T++;let C=_.get(k.tokenType)??0n;_.set(k.tokenType,C+k.value)}return{balances:_,utxoCount:T,txCount:K,highestTxId:G}},F=()=>{clearTimeout(W)},M=()=>{if(!J&&V&&(G===0||U>=G))J=!0,F(),z.send(JSON.stringify({id:"1",type:"complete"})),z.close(),X(B())};z.on("open",()=>{z.send(JSON.stringify({type:"connection_init"}))}),z.on("message",(_)=>{let T=JSON.parse(_.toString());switch(T.type){case"connection_ack":z.send(JSON.stringify({id:"1",type:"subscribe",payload:{query:m2,variables:{address:$}}}));break;case"next":{if(T.payload?.errors){let C=T.payload.errors[0]?.message||"Unknown GraphQL error";if(!J)J=!0,F(),z.close(),q(new Error(`GraphQL error: ${C}`));return}let k=T.payload?.data?.unshieldedTransactions;if(!k)return;if(k.__typename==="UnshieldedTransaction"){K++;let C=k;U=Math.max(U,C.transaction.id);for(let c of C.createdUtxos){let b=`${c.intentHash}:${c.outputIndex}`;Y.set(b,{value:BigInt(c.value),tokenType:c.tokenType,spent:!1})}for(let c of C.spentUtxos){let b=`${c.intentHash}:${c.outputIndex}`,$0=Y.get(b);if($0)$0.spent=!0}if(Q)Q(U,G);M()}else if(k.__typename==="UnshieldedTransactionsProgress")G=k.highestTransactionId,V=!0,M();break}case"error":if(!J)J=!0,F(),z.close(),q(new Error(`GraphQL subscription error: ${JSON.stringify(T.payload)}`));break;case"complete":break}}),z.on("error",(_)=>{if(!J)J=!0,F(),q(new Error(`WebSocket connection failed: ${_.message}`))}),z.on("close",()=>{if(!J)J=!0,F(),q(new Error(`Indexer closed the connection before balance sync completed. Indexer: ${Z}`))}),W=setTimeout(()=>{if(!J)J=!0,z.close(),q(new Error(`Balance check timed out after ${e0/1000}s. Indexer: ${Z}`))},e0)})}function T0($){return $===a1}var m2=`
|
|
49
49
|
subscription UnshieldedTransactions($address: UnshieldedAddress!) {
|
|
50
50
|
unshieldedTransactions(address: $address) {
|
|
51
51
|
__typename
|
|
@@ -59,13 +59,13 @@ Use --force to overwrite, or --output <file> to save to a different path.`);let
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
|
-
`;var k3=()=>{};function v($){if(!
|
|
63
|
-
`)}};let Z=0,Q=$,X=()=>{let z=
|
|
64
|
-
`)}}}var b3,
|
|
65
|
-
`);else for(let[U,
|
|
66
|
-
`);else process.stdout.write(`${U}=${
|
|
62
|
+
`;var k3=()=>{};function v($){if(!i())return process.stderr.write(`⠋ ${$}`),{update(z){process.stderr.write(`\r⠋ ${z}`)},stop(z){let Y=z??$;process.stderr.write(`\r✓ ${Y}
|
|
63
|
+
`)}};let Z=0,Q=$,X=()=>{let z=t(b3[Z]);process.stderr.write(`\r${z} ${Q}\x1B[K`),Z=(Z+1)%b3.length};X();let q=setInterval(X,g2);return{update(z){Q=z},stop(z){clearInterval(q);let Y=z??Q;process.stderr.write(`\r\x1B[32m✓\x1B[0m ${Y}\x1B[K
|
|
64
|
+
`)}}}var b3,g2=80;var B0=O(()=>{b3=["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"]});var W1={};S(W1,{default:()=>w3});async function w3($){let Z,Q;if($.subcommand)Z=$.subcommand;else{let G=A($,"wallet"),U=d(G);Z=U.address,Q=U.network}if(!Z)throw new Error("No address provided and no wallet file found.");let{name:X,config:q}=r({args:$,walletNetwork:Q,address:Z}),Y=A($,"indexer-ws")??q.indexerWS,K=v(`Checking balance on ${X}...`);try{let G=await v3(Z,Y,(U,V)=>{if(V>0){let J=Math.round(U/V*100);K.update(`Syncing transactions... ${J}%`)}});if(K.stop(`Synced ${G.txCount} transactions`),P($,"json")){let U={};for(let[V,J]of G.balances){let W=T0(V)?"NIGHT":V;U[W]=T0(V)?O0(J):J.toString()}L({address:Z,network:X,balances:U,utxoCount:G.utxoCount,txCount:G.txCount});return}if(G.balances.size===0)process.stdout.write(`0
|
|
65
|
+
`);else for(let[U,V]of G.balances)if(T0(U))process.stdout.write(`NIGHT=${V}
|
|
66
|
+
`);else process.stdout.write(`${U}=${V}
|
|
67
67
|
`);if(process.stderr.write(`
|
|
68
|
-
`+
|
|
68
|
+
`+I("Balance")+`
|
|
69
69
|
|
|
70
70
|
`),process.stderr.write(H("Address",E(Z))+`
|
|
71
71
|
`),process.stderr.write(H("Network",X)+`
|
|
@@ -73,12 +73,12 @@ Use --force to overwrite, or --output <file> to save to a different path.`);let
|
|
|
73
73
|
`),process.stderr.write(H("Transactions",G.txCount.toString())+`
|
|
74
74
|
`),process.stderr.write(`
|
|
75
75
|
`),G.balances.size===0)process.stderr.write(` ${j("No balance found")}
|
|
76
|
-
`);else for(let[U,
|
|
77
|
-
`);else{let J=U.slice(0,8)+"…"+U.slice(-8);process.stderr.write(H(`Token ${J}`,y(
|
|
76
|
+
`);else for(let[U,V]of G.balances)if(T0(U))process.stderr.write(H("NIGHT",y(v0(V)))+`
|
|
77
|
+
`);else{let J=U.slice(0,8)+"…"+U.slice(-8);process.stderr.write(H(`Token ${J}`,y(V.toString()))+`
|
|
78
78
|
`)}process.stderr.write(`
|
|
79
79
|
`+D()+`
|
|
80
80
|
|
|
81
|
-
`)}catch(G){throw K.stop("Failed"),G}}var
|
|
81
|
+
`)}catch(G){throw K.stop("Failed"),G}}var H1=O(()=>{Y0();s();k3();N();B0()});var j1={};S(j1,{default:()=>S3});async function S3($){let Z=n1($,"seed","hex").replace(/^0x/,"");if(Z.length!==64||!/^[0-9a-fA-F]+$/.test(Z))throw new Error("Seed must be a 64-character hex string (32 bytes)");let Q=A($,"index"),X=Q!==void 0?parseInt(Q,10):0;if(isNaN(X)||X<0||!Number.isInteger(Number(Q??"0")))throw new Error("Key index must be a non-negative integer");let q=Buffer.from(Z,"hex"),z=z0({args:$}),Y=U0(q,z,X),K=`m/44'/2400'/0'/NightExternal/${X}`;if(P($,"json")){L({address:Y,network:z,index:X,path:K});return}process.stdout.write(Y+`
|
|
82
82
|
`),process.stderr.write(`
|
|
83
83
|
`),process.stderr.write(H("Network",z)+`
|
|
84
84
|
`),process.stderr.write(H("Index",X.toString())+`
|
|
@@ -86,41 +86,41 @@ Use --force to overwrite, or --output <file> to save to a different path.`);let
|
|
|
86
86
|
`),process.stderr.write(H("Path",j(K))+`
|
|
87
87
|
`),process.stderr.write(D()+`
|
|
88
88
|
|
|
89
|
-
`)}var
|
|
89
|
+
`)}var F1=O(()=>{S0();s();N()});var P1={};S(P1,{default:()=>C3});async function C3($){let Z=z0({args:$}),Q=Buffer.from(D0,"hex"),X=U0(Q,Z);if(P($,"json")){L({address:X,network:Z});return}process.stdout.write(X+`
|
|
90
90
|
`),process.stderr.write(`
|
|
91
91
|
`),process.stderr.write(H("Network",Z)+`
|
|
92
92
|
`),process.stderr.write(H("Address",E(X))+`
|
|
93
93
|
`),process.stderr.write(H("Seed",j("0x01 (genesis)"))+`
|
|
94
94
|
`),process.stderr.write(D()+`
|
|
95
95
|
|
|
96
|
-
`)}var
|
|
96
|
+
`)}var O1=O(()=>{S0();s();N()});var L1={};S(L1,{default:()=>h3});import*as f3 from"@midnight-ntwrk/ledger-v7";function M0($,Z,Q){let X={readTime:0n,computeTime:0n,blockUsage:0n,bytesWritten:0n,bytesChurned:0n};X[Z]=Q;let z=$.normalizeFullness(X)[Z];return Math.round(Number(Q)/z)}function d2($){return{readTime:M0($,"readTime",1000000000n),computeTime:M0($,"computeTime",1000000000n),blockUsage:M0($,"blockUsage",10000n),bytesWritten:M0($,"bytesWritten",10000n),bytesChurned:M0($,"bytesChurned",1000000n)}}async function h3($){let Z=f3.LedgerParameters.initialParameters(),Q=d2(Z);if(P($,"json")){L(Q);return}for(let[X,q]of Object.entries(Q))process.stdout.write(`${X}=${q}
|
|
97
97
|
`);process.stderr.write(`
|
|
98
|
-
`+
|
|
98
|
+
`+I("Block Limits")+`
|
|
99
99
|
|
|
100
100
|
`),process.stderr.write(j(" Derived from LedgerParameters.initialParameters()")+`
|
|
101
101
|
|
|
102
|
-
`);for(let[X,q]of Object.entries(Q)){let z=
|
|
102
|
+
`);for(let[X,q]of Object.entries(Q)){let z=l2[X]??"";process.stderr.write(H(X,`${y(q.toLocaleString())} ${j(z)}`)+`
|
|
103
103
|
`)}process.stderr.write(`
|
|
104
104
|
`+D()+`
|
|
105
105
|
`),process.stderr.write(j(" bytesWritten is typically the tightest constraint")+`
|
|
106
106
|
`),process.stderr.write(j(" for large contract deployments.")+`
|
|
107
107
|
|
|
108
|
-
`)}var
|
|
109
|
-
Expected a bech32m address for network "${Z.networkId}"`)}}function
|
|
108
|
+
`)}var l2;var y1=O(()=>{N();l2={readTime:"picoseconds",computeTime:"picoseconds",blockUsage:"bytes",bytesWritten:"bytes",bytesChurned:"bytes"}});import{HDWallet as i2,Roles as T1}from"@midnight-ntwrk/wallet-sdk-hd";function M1($,Z){let Q=i2.fromSeed($);if(Q.type!=="seedOk")throw new Error("Invalid seed for HD wallet");let X=Q.hdWallet.selectAccount(0).selectRole(Z).deriveKeyAt(0);if(X.type==="keyOutOfBounds")throw new Error("Key derivation out of bounds");return X.key}function p3($){return M1($,T1.Zswap)}function u3($){return M1($,T1.NightExternal)}function c3($){return M1($,T1.Dust)}var m3=()=>{};import{ShieldedWallet as o2}from"@midnight-ntwrk/wallet-sdk-shielded";import{UnshieldedWallet as n2,createKeystore as a2,PublicKey as t2,InMemoryTransactionHistoryStorage as r2}from"@midnight-ntwrk/wallet-sdk-unshielded-wallet";import{DustWallet as s2}from"@midnight-ntwrk/wallet-sdk-dust-wallet";import{WalletFacade as e2}from"@midnight-ntwrk/wallet-sdk-facade";import*as V0 from"@midnight-ntwrk/ledger-v7";import{NetworkId as I1}from"@midnight-ntwrk/wallet-sdk-abstractions";import*as p from"rxjs";function c0($,Z){let Q=$$[Z.networkId];if(Q===void 0)throw new Error(`Unknown networkId: ${Z.networkId}`);let X=p3($),q=u3($),z=c3($),Y=V0.ZswapSecretKeys.fromSeed(X),K=V0.DustSecretKey.fromSeed(z),G=a2(q,Q),U={networkId:Q,indexerClientConnection:{indexerHttpUrl:Z.indexer,indexerWsUrl:Z.indexerWS},provingServerUrl:new URL(Z.proofServer),relayURL:new URL(Z.node)},V={networkId:Q,indexerClientConnection:{indexerHttpUrl:Z.indexer,indexerWsUrl:Z.indexerWS},txHistoryStorage:new r2},J={networkId:Q,costParameters:{additionalFeeOverhead:r1,feeBlocksMargin:s1},indexerClientConnection:{indexerHttpUrl:Z.indexer,indexerWsUrl:Z.indexerWS},provingServerUrl:new URL(Z.proofServer),relayURL:new URL(Z.node)},W=o2(U).startWithSecretKeys(Y),B=n2(V).startWithPublicKey(t2.fromKeyStore(G)),F=s2(J).startWithSecretKey(K,V0.LedgerParameters.initialParameters().dust);return{facade:new e2(W,B,F),keystore:G,zswapSecretKeys:Y,dustSecretKey:K}}async function I0($,Z){let{facade:Q,zswapSecretKeys:X,dustSecretKey:q}=$;return await Q.start(X,q),p.firstValueFrom(Q.state().pipe(p.tap((z)=>{if(Z){let Y=z.unshielded.progress;if(Y)Z(Number(Y.appliedId),Number(Y.highestTransactionId))}}),p.filter((z)=>z.isSynced),p.timeout(e1)))}async function g3($){return p.firstValueFrom($.facade.state().pipe(p.filter((Z)=>Z.isSynced),p.timeout($3)))}async function m0($){await $.facade.stop()}function g0($){let Z=(X)=>{let q=X?._tag;if(typeof q==="string"&&q.startsWith("Wallet.")){let z=X?.message??"transient error";$?.(q,z);return}Q("Unhandled rejection:",X),process.exit(1)},Q=console.error;return console.error=(...X)=>{let q=X[0];if(typeof q==="object"&&q?._tag?.startsWith("Wallet.")){$?.(q._tag,q?.message??"transient error");return}if(typeof q==="string"&&q.startsWith("Wallet.")){$?.("Wallet.Sync","transient error");return}Q(...X)},process.on("unhandledRejection",Z),()=>{process.removeListener("unhandledRejection",Z),console.error=Q}}var $$;var _1=O(()=>{m3();$$={PreProd:I1.NetworkId.PreProd,Preview:I1.NetworkId.Preview,Undeployed:I1.NetworkId.Undeployed}});import*as D1 from"@midnight-ntwrk/ledger-v7";import{MidnightBech32m as Z$,UnshieldedAddress as Q$}from"@midnight-ntwrk/wallet-sdk-address-format";import{NetworkId as A1}from"@midnight-ntwrk/wallet-sdk-abstractions";import*as u from"rxjs";function q$($){if($<=0)throw new Error("Amount must be greater than 0");if(!Number.isFinite($))throw new Error("Amount must be a finite number");let Z=$.toFixed(6),[Q,X]=Z.split("."),q=Q+(X??"").padEnd(6,"0"),z=BigInt(q);if(z<=0n)throw new Error("Amount too small — minimum is 0.000001 NIGHT");return z}function d0($){let Z=Number($);if(Number.isNaN(Z)||!Number.isFinite(Z))throw new Error(`Invalid amount: "${$}" — must be a positive number`);if(Z<=0)throw new Error(`Invalid amount: "${$}" — must be greater than 0`);return Z}function z$($,Z){let Q=X$[Z.networkId];if(Q===void 0)throw new Error(`Unknown networkId: ${Z.networkId}`);try{Z$.parse($).decode(Q$,Q)}catch(X){throw new Error(`Invalid recipient address: ${X.message}
|
|
109
|
+
Expected a bech32m address for network "${Z.networkId}"`)}}function d3($){let Z=$;while(Z){let Q=String(Z?.message??"").toLowerCase();if(Q.includes("submission error"))return!0;if(Q.includes("transaction")&&Q.includes("invalid"))return!0;if(Q.includes("138"))return!0;let X=Z?._tag;if(X==="TransactionInvalidError"||X==="SubmissionError")return!0;Z=Z.cause}return!1}function Y$($){let Z=Math.round($/1000);if(Z<60)return`${Z}s`;let Q=Math.floor(Z/60),X=Z%60;return`${Q}m ${X}s`}async function J$($,Z,Q){let X=new Date(Date.now()+$1*60*1000);await $.facade.dust.waitForSyncedState();let q=await $.facade.dust.createDustGenerationTransaction(new Date,X,Z,$.keystore.getPublicKey(),Q),z=q.intents?.get(1);if(!z)throw new Error("Dust generation intent not found on transaction");let Y=$.keystore.signData(z.signatureData(1)),K=await $.facade.dust.addDustGenerationSignature(q,Y),G=await $.facade.finalizeTransaction(K);return await $.facade.submitTransaction(G)}async function R1($,Z,Q,X){let q=Date.now(),z=q+Q3,Y,K=console.warn,G=console.error,U=(W)=>W.some((B)=>String(B).includes("RPC-CORE")),V=()=>{console.warn=(...W)=>{if(U(W))return;K(...W)},console.error=(...W)=>{if(U(W))return;G(...W)}},J=()=>{console.warn=K,console.error=G};V();try{while(Date.now()<z)try{return await J$($,Z,Q)}catch(W){if(Y=W,d3(W)&&Date.now()+E0<z){let B=Y$(Date.now()-q);X?.(`Waiting for dust generation capacity (${B} elapsed, ~5 min on fresh wallets)...`),await new Promise((F)=>setTimeout(F,E0));continue}throw W}throw Y??new Error("Dust registration timed out")}finally{J()}}async function K$($,Z){let Q=await u.firstValueFrom($.facade.state().pipe(u.filter((q)=>q.isSynced))),X=Q.unshielded.availableCoins.filter((q)=>q.meta?.registeredForDustGeneration!==!0);if(X.length>0){Z?.(`Registering ${X.length} UTXO(s) for dust generation...`);let q=X.map((z)=>({...z.utxo,ctime:new Date(z.meta.ctime)}));await R1($,q,Q.dust.dustAddress,Z)}else if(Q.dust.availableCoins.length>0){Z?.("Dust available");return}else Z?.("UTXOs already registered, waiting for dust generation...");Z?.("Waiting for dust tokens..."),await u.firstValueFrom($.facade.state().pipe(u.throttleTime(5000),u.filter((q)=>q.isSynced),u.filter((q)=>q.dust.walletBalance(new Date)>0n),u.timeout(R0))),Z?.("Dust available")}async function G$($,Z,Q,X,q,z){let Y;for(let K=1;K<=x0;K++)try{if(K>1)await g3($);let G=new Date(Date.now()+$1*60*1000),U=await $.facade.transferTransaction([{type:"unshielded",outputs:[{amount:Q,receiverAddress:Z,type:D1.unshieldedToken().raw}]}],{shieldedSecretKeys:$.zswapSecretKeys,dustSecretKey:$.dustSecretKey},{ttl:G,payFees:!0}),V=await $.facade.signRecipe(U,(B)=>$.keystore.signData(B));X?.();let J=await Promise.race([$.facade.finalizeRecipe(V),new Promise((B,F)=>{setTimeout(()=>F(new Error("ZK proof generation timed out")),Z3)})]);return q?.(),await $.facade.submitTransaction(J)}catch(G){if(Y=G,(G?.code===X3||G?.message?.includes("115")||G?.message?.toLowerCase().includes("stale"))&&K<x0)continue;let V=G?.message?.toLowerCase().includes("not enough dust")||G?.message?.toLowerCase().includes("dust generated"),J=d3(G);if((V||J)&&K<x0){z?.("Waiting for more dust capacity to accumulate..."),await new Promise((W)=>setTimeout(W,E0));continue}throw G}throw Y??new Error("Transfer failed after retries")}async function l0($){let{seedBuffer:Z,networkConfig:Q,recipientAddress:X,amountNight:q,signal:z,onSync:Y,onDust:K,onProving:G,onSubmitting:U,onSyncWarning:V}=$,J=q$(q);z$(X,Q);let W=g0(V),B=console.warn,F=console.error,M=(b)=>b.some(($0)=>String($0).includes("RPC-CORE"));console.warn=(...b)=>{if(!M(b))B(...b)},console.error=(...b)=>{if(!M(b))F(...b)};let _=()=>{console.warn=B,console.error=F},T=c0(Z,Q),k=!1,C=async()=>{if(!k){k=!0;try{await m0(T)}catch{}}},c=()=>{C()};z?.addEventListener("abort",c,{once:!0});try{let b=await I0(T,Y);if(z?.aborted)throw new Error("Operation cancelled");let $0=b.unshielded.balances[D1.unshieldedToken().raw]??0n;if($0<J){let O2=Number($0)/t1;throw new Error(`Insufficient balance: ${O2.toFixed(6)} NIGHT available, ${q} NIGHT requested`)}if(z?.aborted)throw new Error("Operation cancelled");if(await K$(T,K),z?.aborted)throw new Error("Operation cancelled");return{txHash:await G$(T,X,J,G,U,K),amountMicroNight:J}}finally{z?.removeEventListener("abort",c),_(),W(),await C()}}var X$;var i0=O(()=>{_1();X$={PreProd:A1.NetworkId.PreProd,Preview:A1.NetworkId.Preview,Undeployed:A1.NetworkId.Undeployed}});var x1={};S(x1,{default:()=>l3});async function l3($,Z){let Q=$.subcommand;if(!Q)throw new Error(`Missing amount.
|
|
110
110
|
Usage: midnight airdrop <amount>
|
|
111
|
-
Example: midnight airdrop 1000`);let X=
|
|
111
|
+
Example: midnight airdrop 1000`);let X=d0(Q),q=A($,"wallet"),z=d(q),{name:Y,config:K}=r({args:$,walletNetwork:z.network,address:z.address});if(Y!=="undeployed")throw new Error(`Airdrop is only available on the "undeployed" network (local devnet).
|
|
112
112
|
Current network: "${Y}"
|
|
113
|
-
On preprod/preview, use a faucet or transfer from another wallet.`);let G=z.address,U=Buffer.from(
|
|
114
|
-
`+
|
|
113
|
+
On preprod/preview, use a faucet or transfer from another wallet.`);let G=z.address,U=Buffer.from(D0,"hex");process.stderr.write(`
|
|
114
|
+
`+I("Airdrop")+`
|
|
115
115
|
|
|
116
116
|
`),process.stderr.write(H("Network",Y)+`
|
|
117
117
|
`),process.stderr.write(H("From",j("genesis (seed 0x01)"))+`
|
|
118
118
|
`),process.stderr.write(H("To",E(G,!0))+`
|
|
119
119
|
`),process.stderr.write(H("Amount",y(X+" NIGHT"))+`
|
|
120
120
|
`),process.stderr.write(`
|
|
121
|
-
`);let
|
|
121
|
+
`);let V=v("Starting genesis wallet...");try{let J=await l0({seedBuffer:U,networkConfig:K,recipientAddress:G,amountNight:X,signal:Z,onSync(W,B){if(B>0){let F=Math.round(W/B*100);V.update(`Syncing genesis wallet... ${F}%`)}},onDust(W){V.update(`Dust: ${W}`)},onProving(){V.update("Generating ZK proof (this may take a few minutes)...")},onSubmitting(){V.update("Submitting transaction...")},onSyncWarning(W,B){V.update(`Syncing genesis wallet... (${B}, retrying)`)}});if(V.stop("Transaction submitted"),P($,"json")){L({txHash:J.txHash,amount:X,recipient:G,network:Y});return}process.stdout.write(J.txHash+`
|
|
122
122
|
`),process.stderr.write(`
|
|
123
|
-
`+
|
|
123
|
+
`+X0(`Airdropped ${X} NIGHT to your wallet`,J.txHash)+`
|
|
124
124
|
`),process.stderr.write(`
|
|
125
125
|
`+D()+`
|
|
126
126
|
`),process.stderr.write(j(" Verify: midnight balance")+`
|
|
@@ -128,69 +128,69 @@ On preprod/preview, use a faucet or transfer from another wallet.`);let G=z.addr
|
|
|
128
128
|
`),process.stderr.write(j(" Note: Dust generation takes a few minutes on a fresh wallet.")+`
|
|
129
129
|
`),process.stderr.write(j(" It will happen automatically on your first transfer.")+`
|
|
130
130
|
|
|
131
|
-
`)}catch(J){if(
|
|
131
|
+
`)}catch(J){if(V.stop("Failed"),J instanceof Error&&J.message.toLowerCase().includes("dust"))throw new Error(`${J.message}
|
|
132
132
|
|
|
133
133
|
On a fresh localnet, the minimum airdrop is ~1 NIGHT.
|
|
134
|
-
Try: midnight airdrop 1`);throw J}}var
|
|
134
|
+
Try: midnight airdrop 1`);throw J}}var E1=O(()=>{Y0();s();i0();N();B0()});var N1={};S(N1,{default:()=>i3});async function i3($,Z){let Q=$.subcommand,X=$.positionals[0];if(!Q)throw new Error(`Missing recipient address.
|
|
135
135
|
Usage: midnight transfer <to> <amount>
|
|
136
136
|
Example: midnight transfer mn_addr_undeployed1... 100`);if(!X)throw new Error(`Missing amount.
|
|
137
137
|
Usage: midnight transfer <to> <amount>
|
|
138
|
-
Example: midnight transfer mn_addr_undeployed1... 100`);let q=
|
|
139
|
-
`+
|
|
138
|
+
Example: midnight transfer mn_addr_undeployed1... 100`);let q=d0(X),z=A($,"wallet"),Y=d(z),K=Buffer.from(Y.seed,"hex"),{name:G,config:U}=r({args:$,walletNetwork:Y.network,address:Y.address});process.stderr.write(`
|
|
139
|
+
`+I("Transfer")+`
|
|
140
140
|
|
|
141
141
|
`),process.stderr.write(H("Network",G)+`
|
|
142
142
|
`),process.stderr.write(H("From",E(Y.address,!0))+`
|
|
143
143
|
`),process.stderr.write(H("To",E(Q,!0))+`
|
|
144
144
|
`),process.stderr.write(H("Amount",y(q+" NIGHT"))+`
|
|
145
145
|
`),process.stderr.write(`
|
|
146
|
-
`);let
|
|
146
|
+
`);let V=v("Starting wallet...");try{let J=await l0({seedBuffer:K,networkConfig:U,recipientAddress:Q,amountNight:q,signal:Z,onSync(W,B){if(B>0){let F=Math.round(W/B*100);V.update(`Syncing wallet... ${F}%`)}},onDust(W){V.update(`Dust: ${W}`)},onProving(){V.update("Generating ZK proof (this may take a few minutes)...")},onSubmitting(){V.update("Submitting transaction...")},onSyncWarning(W,B){V.update(`Syncing wallet... (${B}, retrying)`)}});if(V.stop("Transaction submitted"),P($,"json")){L({txHash:J.txHash,amount:q,recipient:Q,network:G});return}process.stdout.write(J.txHash+`
|
|
147
147
|
`),process.stderr.write(`
|
|
148
|
-
`+
|
|
148
|
+
`+X0(`Transferred ${q} NIGHT`,J.txHash)+`
|
|
149
149
|
`),process.stderr.write(`
|
|
150
150
|
`+D()+`
|
|
151
151
|
`),process.stderr.write(j(" Verify: midnight balance")+`
|
|
152
152
|
|
|
153
|
-
`)}catch(J){throw
|
|
153
|
+
`)}catch(J){throw V.stop("Failed"),J}}var v1=O(()=>{Y0();s();i0();N();B0()});var k1={};S(k1,{default:()=>n3});import*as o3 from"@midnight-ntwrk/ledger-v7";import*as w from"rxjs";async function n3($,Z){let Q=$.subcommand;if(!Q||Q!=="register"&&Q!=="status")throw new Error(`Missing or invalid subcommand.
|
|
154
154
|
Usage:
|
|
155
155
|
midnight dust register Register NIGHT UTXOs for dust generation
|
|
156
|
-
midnight dust status Check dust registration status`);let X=A($,"wallet"),q=
|
|
157
|
-
`+
|
|
156
|
+
midnight dust status Check dust registration status`);let X=A($,"wallet"),q=d(X),z=Buffer.from(q.seed,"hex"),{name:Y,config:K}=r({args:$,walletNetwork:q.network,address:q.address}),G=c0(z,K),U=async()=>{try{await m0(G)}catch{}},V=()=>{U()};Z?.addEventListener("abort",V,{once:!0});let J={},W=g0((F,M)=>{J.current?.(F,M)}),B=P($,"json");try{if(Q==="register")await U$(G,Y,B,Z,J);else await B$(G,Y,B,Z,J)}finally{Z?.removeEventListener("abort",V),W(),await U()}}async function U$($,Z,Q,X,q){process.stderr.write(`
|
|
157
|
+
`+I("Dust Register")+`
|
|
158
158
|
|
|
159
159
|
`),process.stderr.write(H("Network",Z)+`
|
|
160
160
|
|
|
161
|
-
`);let z=v("Syncing wallet...");if(q)q.current=(Y,K)=>z.update(`Syncing wallet... (${K}, retrying)`);try{if(await
|
|
161
|
+
`);let z=v("Syncing wallet...");if(q)q.current=(Y,K)=>z.update(`Syncing wallet... (${K}, retrying)`);try{if(await I0($,(J,W)=>{if(W>0){let B=Math.round(J/W*100);z.update(`Syncing wallet... ${B}%`)}}),X?.aborted)throw new Error("Operation cancelled");z.update("Checking dust status...");let Y=await w.firstValueFrom($.facade.state().pipe(w.filter((J)=>J.isSynced)));if(Y.dust.availableCoins.length>0){let J=Y.dust.walletBalance(new Date);if(z.stop("Dust already available"),Q){L({subcommand:"register",dustBalance:L0(J)});return}process.stdout.write(J.toString()+`
|
|
162
162
|
`),process.stderr.write(`
|
|
163
|
-
`+
|
|
163
|
+
`+X0(`Dust tokens already available: ${k0(J)}`)+`
|
|
164
164
|
|
|
165
|
-
`);return}let K=Y.unshielded.availableCoins.filter((J)=>J.meta?.registeredForDustGeneration!==!0),G;if(K.length===0)z.update("All UTXOs already registered, waiting for dust generation...");else{z.update(`Registering ${K.length} UTXO(s) for dust generation...`);let J=K.map((
|
|
165
|
+
`);return}let K=Y.unshielded.availableCoins.filter((J)=>J.meta?.registeredForDustGeneration!==!0),G;if(K.length===0)z.update("All UTXOs already registered, waiting for dust generation...");else{z.update(`Registering ${K.length} UTXO(s) for dust generation...`);let J=K.map((W)=>({...W.utxo,ctime:new Date(W.meta.ctime)}));G=await R1($,J,Y.dust.dustAddress,(W)=>{z.update(W)}),z.update(`Registration submitted (${G.slice(0,12)}...), waiting for dust...`)}if(X?.aborted)throw new Error("Operation cancelled");let V=(await w.firstValueFrom($.facade.state().pipe(w.throttleTime(5000),w.filter((J)=>J.isSynced),w.filter((J)=>J.dust.walletBalance(new Date)>0n),w.timeout(R0)))).dust.walletBalance(new Date);if(z.stop("Dust registration complete"),Q){let J={subcommand:"register",dustBalance:L0(V)};if(G)J.txHash=G;L(J);return}process.stdout.write(V.toString()+`
|
|
166
166
|
`),process.stderr.write(`
|
|
167
|
-
`+
|
|
167
|
+
`+X0(`Dust tokens available: ${k0(V)}`)+`
|
|
168
168
|
|
|
169
|
-
`)}catch(Y){throw z.stop("Failed"),Y}}async function
|
|
170
|
-
`+
|
|
169
|
+
`)}catch(Y){throw z.stop("Failed"),Y}}async function B$($,Z,Q,X,q){process.stderr.write(`
|
|
170
|
+
`+I("Dust Status")+`
|
|
171
171
|
|
|
172
172
|
`),process.stderr.write(H("Network",Z)+`
|
|
173
173
|
|
|
174
|
-
`);let z=v("Syncing wallet...");if(q)q.current=(Y,K)=>z.update(`Syncing wallet... (${K}, retrying)`);try{if(await
|
|
174
|
+
`);let z=v("Syncing wallet...");if(q)q.current=(Y,K)=>z.update(`Syncing wallet... (${K}, retrying)`);try{if(await I0($,(B,F)=>{if(F>0){let M=Math.round(B/F*100);z.update(`Syncing wallet... ${M}%`)}}),X?.aborted)throw new Error("Operation cancelled");z.update("Checking dust status...");let Y=await w.firstValueFrom($.facade.state().pipe(w.filter((B)=>B.isSynced))),K=Y.dust.walletBalance(new Date),G=Y.dust.availableCoins.length>0,U=Y.unshielded.availableCoins,V=U.filter((B)=>B.meta?.registeredForDustGeneration!==!0),J=U.length-V.length,W=Y.unshielded.balances[o3.unshieldedToken().raw]??0n;if(z.stop("Done"),Q){L({subcommand:"status",dustBalance:L0(K),registered:J,unregistered:V.length,nightBalance:O0(W),dustAvailable:G});return}process.stdout.write(`dust=${K}
|
|
175
175
|
`),process.stdout.write(`registered=${J}
|
|
176
|
-
`),process.stdout.write(`unregistered=${
|
|
177
|
-
`),process.stderr.write(H("NIGHT Balance",y(
|
|
178
|
-
`),process.stderr.write(H("Dust Balance",y(
|
|
176
|
+
`),process.stdout.write(`unregistered=${V.length}
|
|
177
|
+
`),process.stderr.write(H("NIGHT Balance",y(v0(W)))+`
|
|
178
|
+
`),process.stderr.write(H("Dust Balance",y(k0(K)))+`
|
|
179
179
|
`),process.stderr.write(H("Dust Available",G?"yes":"no")+`
|
|
180
180
|
`),process.stderr.write(H("Registered",J.toString()+" UTXO(s)")+`
|
|
181
|
-
`),process.stderr.write(H("Unregistered",
|
|
181
|
+
`),process.stderr.write(H("Unregistered",V.length.toString()+" UTXO(s)")+`
|
|
182
182
|
`),process.stderr.write(`
|
|
183
183
|
`+D()+`
|
|
184
184
|
|
|
185
|
-
`)}catch(Y){throw z.stop("Failed"),Y}}var
|
|
186
|
-
Valid keys: ${
|
|
187
|
-
Valid keys: ${
|
|
185
|
+
`)}catch(Y){throw z.stop("Failed"),Y}}var b1=O(()=>{Y0();s();_1();i0();N();B0()});var w1={};S(w1,{default:()=>a3});async function a3($){let Z=$.subcommand;if(!Z||Z!=="get"&&Z!=="set")throw new Error(`Usage: midnight config <get|set> <key> [value]
|
|
186
|
+
Valid keys: ${J1().join(", ")}`);let Q=$.positionals[0];if(!Q)throw new Error(`Missing config key.
|
|
187
|
+
Valid keys: ${J1().join(", ")}`);if(Z==="get"){let X=T3(Q);if(P($,"json")){L({action:"get",key:Q,value:X});return}process.stdout.write(X+`
|
|
188
188
|
`)}else{let X=$.positionals[1];if(X===void 0)throw new Error(`Missing value for config set.
|
|
189
|
-
Usage: midnight config set ${Q} <value>`);if(M3(Q,X),P($,"json")){L({action:"set",key:Q,value:X});return}process.stderr.write(
|
|
190
|
-
`)}}var
|
|
189
|
+
Usage: midnight config set ${Q} <value>`);if(M3(Q,X),P($,"json")){L({action:"set",key:Q,value:X});return}process.stderr.write(o("✓")+` ${Q} = ${X}
|
|
190
|
+
`)}}var S1=O(()=>{K1()});import{execSync as _0}from"child_process";import{existsSync as t3,mkdirSync as V$,readFileSync as W$,writeFileSync as r3}from"fs";import{homedir as H$}from"os";import{join as f1}from"path";function e3(){try{return _0("docker compose version",{...n0,timeout:1e4}).trim()}catch{try{throw _0("docker --version",{...n0,timeout:5000}),new Error(`Docker Compose v2 is required.
|
|
191
191
|
Install it from https://docs.docker.com/compose/install/`)}catch($){if($ instanceof Error&&$.message.includes("Docker Compose v2"))throw $;throw new Error(`Docker is required but was not found.
|
|
192
|
-
Install Docker from https://docs.docker.com/get-docker/`)}}}function
|
|
193
|
-
`),Q=[];for(let X of Z){if(!X.trim())continue;try{let q=JSON.parse(X),z=q.Service??"unknown";Q.push({name:z,state:q.State??"unknown",health:q.Health??"",port:
|
|
192
|
+
Install Docker from https://docs.docker.com/get-docker/`)}}}function $2(){if(t3(C1)&&t3(o0)&&W$(C1,"utf-8").trim()===s3)return!1;return V$(h1,{recursive:!0,mode:Q0}),r3(o0,j$,"utf-8"),r3(C1,s3,"utf-8"),!0}function W0($){return _0(`docker compose -f "${o0}" ${$}`,n0)}function a0(){try{let $=W0("ps --format json");if(!$.trim())return[];let Z=$.trim().split(`
|
|
193
|
+
`),Q=[];for(let X of Z){if(!X.trim())continue;try{let q=JSON.parse(X),z=q.Service??"unknown";Q.push({name:z,state:q.State??"unknown",health:q.Health??"",port:F$[z]??""})}catch{}}return Q}catch{return[]}}function Z2($=120000,Z=3000){let Q=Date.now()+$;while(Date.now()<Q){let X=a0();if(X.length===3&&X.every((z)=>z.state==="running")){if(X.every((Y)=>Y.health==="healthy"||Y.health===""))return!0}_0(`sleep ${Z/1000}`,{timeout:Z+1000})}return!1}function p1(){return o0}function Q2(){let $=[];for(let Z of P$)try{_0(`docker rm -f "${Z}"`,{...n0,timeout:1e4}),$.push(Z)}catch{}return $}var s3="1.4.0",h1,o0,C1,j$=`services:
|
|
194
194
|
proof-server:
|
|
195
195
|
image: 'nel349/proof-server:7.0.0'
|
|
196
196
|
container_name: "proof-server"
|
|
@@ -232,34 +232,34 @@ Install Docker from https://docs.docker.com/get-docker/`)}}}function e3(){if(a3(
|
|
|
232
232
|
start_period: 5s
|
|
233
233
|
environment:
|
|
234
234
|
CFG_PRESET: "dev"
|
|
235
|
-
`,
|
|
236
|
-
`)}async function
|
|
237
|
-
`);let Q=v("Starting local network...");try{if(
|
|
235
|
+
`,n0,F$,P$;var X2=O(()=>{h1=f1(H$(),m,z3),o0=f1(h1,"compose.yml"),C1=f1(h1,".version"),n0={encoding:"utf-8",timeout:30000};F$={node:"9944",indexer:"8088","proof-server":"6300"};P$=["node","indexer","proof-server"]});var u1={};S(u1,{default:()=>Y2});import{spawn as O$}from"child_process";function L$($){return q2.includes($)}function z2($){let Z=[];for(let Q of $){let X=Q.state==="running"?o:f,q=Q.health?` (${Q.health})`:"",z=Q.port?`:${Q.port}`:"";Z.push(` ${Q.name.padEnd(16)}${X(Q.state)}${j(q)}${j(z)}`)}return Z.join(`
|
|
236
|
+
`)}async function y$($){if($2())process.stderr.write(j(` Wrote compose.yml to ${p1()}`)+`
|
|
237
|
+
`);let Q=v("Starting local network...");try{if(W0("up -d"),Q.update("Waiting for services to be healthy..."),!Z2(120000))Q.stop(j0("Services started but not all healthy yet")),process.stderr.write(`
|
|
238
238
|
`+j(" Tip: run ")+y("midnight localnet logs")+j(" to check for errors")+`
|
|
239
|
-
`);else Q.stop("Local network is running")}catch(q){if(Q.stop(
|
|
239
|
+
`);else Q.stop("Local network is running")}catch(q){if(Q.stop(f("Failed to start local network")),q instanceof Error){if(q.message.includes("is already in use by container"))throw new Error(`Container name conflict — containers with the same names already exist
|
|
240
240
|
`+`(likely from a previous midnight-local-network setup).
|
|
241
241
|
|
|
242
242
|
Run "midnight localnet clean" to remove them, then try again.`);if(q.message.includes("address already in use"))throw new Error(`Port conflict detected — another process is using a required port.
|
|
243
|
-
`+"Check ports 9944, 8088, and 6300, then try again.")}throw q}let X=
|
|
244
|
-
`+
|
|
243
|
+
`+"Check ports 9944, 8088, and 6300, then try again.")}throw q}let X=a0();if($){L({subcommand:"up",services:X.map((q)=>({name:q.name,state:q.state,port:q.port,health:q.health}))});return}if(X.length>0)process.stderr.write(`
|
|
244
|
+
`+z2(X)+`
|
|
245
245
|
`);for(let q of X)process.stdout.write(`${q.name}=${q.state}:${q.port}
|
|
246
246
|
`);process.stderr.write(`
|
|
247
247
|
`+j(" Next: ")+y("midnight generate --network undeployed")+`
|
|
248
|
-
`)}async function
|
|
249
|
-
`+
|
|
248
|
+
`)}async function T$($){let Z=v("Stopping local network...");try{if(W0("stop"),Z.stop("Local network stopped (containers preserved)"),$){L({subcommand:"stop",status:"stopped"});return}}catch(Q){throw Z.stop(f("Failed to stop local network")),Q}}async function M$($){let Z=v("Tearing down local network...");try{if(W0("down --volumes"),Z.stop("Local network removed (containers, networks, volumes)"),$){L({subcommand:"down",status:"removed"});return}}catch(Q){throw Z.stop(f("Failed to tear down local network")),Q}}async function I$($){let Z=a0();if($){L({subcommand:"status",services:Z.map((Q)=>({name:Q.name,state:Q.state,port:Q.port,health:Q.health}))});return}if(Z.length===0){process.stderr.write(`
|
|
249
|
+
`+I("Localnet Status")+`
|
|
250
250
|
|
|
251
251
|
`),process.stderr.write(j(" No services running.")+`
|
|
252
252
|
`),process.stderr.write(j(" Run ")+y("midnight localnet up")+j(" to start.")+`
|
|
253
253
|
|
|
254
254
|
`);return}process.stderr.write(`
|
|
255
|
-
`+
|
|
255
|
+
`+I("Localnet Status")+`
|
|
256
256
|
|
|
257
|
-
`),process.stderr.write(
|
|
257
|
+
`),process.stderr.write(z2(Z)+`
|
|
258
258
|
`),process.stderr.write(`
|
|
259
259
|
`+D()+`
|
|
260
260
|
|
|
261
261
|
`);for(let Q of Z)process.stdout.write(`${Q.name}=${Q.state}:${Q.port}
|
|
262
|
-
`)}async function
|
|
262
|
+
`)}async function _$($){let Z=v("Removing conflicting containers...");try{try{W0("down")}catch{}let Q=Q2();if(Q.length>0)Z.stop(`Removed ${Q.length} container${Q.length>1?"s":""}: ${Q.join(", ")}`);else Z.stop("No conflicting containers found");if($){L({subcommand:"clean",status:"cleaned",removed:Q});return}}catch(Q){throw Z.stop(f("Failed to clean up")),Q}}async function A$(){let $=p1(),Z=O$("docker",["compose","-f",$,"logs","-f"],{stdio:"inherit"});return new Promise((Q,X)=>{Z.on("close",(q)=>{if(q===0||q===130||q===null)Q();else X(new Error(`docker compose logs exited with code ${q}`))}),Z.on("error",X)})}async function Y2($){let Z=$.subcommand;if(!Z||!L$(Z))throw new Error(`Usage: midnight localnet <${q2.join("|")}>
|
|
263
263
|
|
|
264
264
|
Subcommands:
|
|
265
265
|
up Start the local network
|
|
@@ -269,47 +269,47 @@ Subcommands:
|
|
|
269
269
|
logs Stream service logs
|
|
270
270
|
clean Remove conflicting containers
|
|
271
271
|
|
|
272
|
-
Example: midnight localnet up`);
|
|
273
|
-
`+
|
|
274
|
-
|
|
275
|
-
`),Z){case"up":return
|
|
276
|
-
`),process.exit(1)})});function
|
|
277
|
-
`),X=Math.floor($*100);if(Z>=1)return
|
|
278
|
-
`);return Q.map((q,z)=>Array.from(q).map((Y,K)=>{if(Y===" ")return" ";let G=(z*131+K*997)%100/100;return Z>=G?Y:
|
|
279
|
-
`)}var
|
|
280
|
-
`),
|
|
281
|
-
`),q=X.length,z=36,Y=Math.max(q,Z?.length??0),K=3;if(!
|
|
282
|
-
`)}return}function G(B,F){for(let
|
|
283
|
-
`);else process.stderr.write(
|
|
284
|
-
`)}}function U(){process.stderr.write(`\x1B[${Y}A`)}for(let B=0;B<=20;B++){if($?.aborted)break;let F=B/20,
|
|
285
|
-
`);if(B>0)U();G(
|
|
272
|
+
Example: midnight localnet up`);e3();let Q=P($,"json");switch(process.stderr.write(`
|
|
273
|
+
`+I("Localnet")+`
|
|
274
|
+
|
|
275
|
+
`),Z){case"up":return y$(Q);case"stop":return T$(Q);case"down":return M$(Q);case"status":return I$(Q);case"logs":return A$();case"clean":return _$(Q)}}var q2;var c1=O(()=>{X2();N();B0();q2=["up","stop","down","status","logs","clean"]});var k$={};import{Server as D$}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as R$}from"@modelcontextprotocol/sdk/server/stdio.js";import{ListToolsRequestSchema as x$,CallToolRequestSchema as E$}from"@modelcontextprotocol/sdk/types.js";function l($,Z,Q){let X={json:!0},q=[];for(let[z,Y]of Object.entries(Z)){if(Y===void 0||Y===null)continue;if(typeof Y==="boolean"){if(Y)X[z]=!0}else X[z]=String(Y)}return{command:$,subcommand:Q,positionals:q,flags:X}}async function x($){let Z=N$[$];if(!Z)throw new Error(`Unknown command handler: ${$}`);return(await Z()).default}async function v$(){let $=new R$;await m1.connect($)}var N$,J2,m1;var K2=O(()=>{H3();Z1();w0();N$={generate:()=>Promise.resolve().then(() => (U1(),G1)),info:()=>Promise.resolve().then(() => (V1(),B1)),balance:()=>Promise.resolve().then(() => (H1(),W1)),address:()=>Promise.resolve().then(() => (F1(),j1)),"genesis-address":()=>Promise.resolve().then(() => (O1(),P1)),"inspect-cost":()=>Promise.resolve().then(() => (y1(),L1)),airdrop:()=>Promise.resolve().then(() => (E1(),x1)),transfer:()=>Promise.resolve().then(() => (v1(),N1)),dust:()=>Promise.resolve().then(() => (b1(),k1)),config:()=>Promise.resolve().then(() => (S1(),w1)),localnet:()=>Promise.resolve().then(() => (c1(),u1))};J2=[{name:"midnight_generate",description:"Generate a new wallet (random mnemonic, or restore from seed/mnemonic)",inputSchema:{type:"object",properties:{network:{type:"string",description:"Network: preprod, preview, undeployed",enum:["preprod","preview","undeployed"]},seed:{type:"string",description:"Restore from existing seed (64-char hex)"},mnemonic:{type:"string",description:"Restore from BIP-39 mnemonic (24 words)"},output:{type:"string",description:"Custom output path (default: ~/.midnight/wallet.json)"},force:{type:"string",description:'Set to "true" to overwrite existing wallet file'}}},async handler($){let Z=l("generate",$);if($.force==="true"||$.force===!0)Z.flags.force=!0;let Q=await x("generate");return R(Q,Z)}},{name:"midnight_info",description:"Display wallet address, network, creation date (no secrets shown)",inputSchema:{type:"object",properties:{wallet:{type:"string",description:"Custom wallet file path"}}},async handler($){let Z=l("info",$),Q=await x("info");return R(Q,Z)}},{name:"midnight_balance",description:"Check unshielded balance via indexer subscription",inputSchema:{type:"object",properties:{address:{type:"string",description:"Address to check (or reads from wallet file)"},wallet:{type:"string",description:"Custom wallet file path"},network:{type:"string",description:"Override network detection",enum:["preprod","preview","undeployed"]},"indexer-ws":{type:"string",description:"Custom indexer WebSocket URL"}}},async handler($){let Z=$.address,Q=l("balance",$,Z);delete Q.flags.address;let X=await x("balance");return R(X,Q)}},{name:"midnight_address",description:"Derive and display an unshielded address from a seed",inputSchema:{type:"object",properties:{seed:{type:"string",description:"Seed to derive from (required, 64-char hex)"},network:{type:"string",description:"Network for address prefix",enum:["preprod","preview","undeployed"]},index:{type:"string",description:"Key derivation index (default: 0)"}},required:["seed"]},async handler($){let Z=l("address",$),Q=await x("address");return R(Q,Z)}},{name:"midnight_genesis_address",description:"Display the genesis wallet address (seed 0x01) for a network",inputSchema:{type:"object",properties:{network:{type:"string",description:"Network for address prefix",enum:["preprod","preview","undeployed"]}}},async handler($){let Z=l("genesis-address",$),Q=await x("genesis-address");return R(Q,Z)}},{name:"midnight_inspect_cost",description:"Display current block limits derived from LedgerParameters",inputSchema:{type:"object",properties:{}},async handler(){let $=l("inspect-cost",{}),Z=await x("inspect-cost");return R(Z,$)}},{name:"midnight_airdrop",description:"Fund your wallet from the genesis wallet (undeployed network only)",inputSchema:{type:"object",properties:{amount:{type:"string",description:"Amount in NIGHT to airdrop"},wallet:{type:"string",description:"Custom wallet file path"}},required:["amount"]},async handler($){let Z=$.amount,Q=l("airdrop",$,Z);delete Q.flags.amount;let X=await x("airdrop");return R(X,Q)}},{name:"midnight_transfer",description:"Send NIGHT tokens to another address",inputSchema:{type:"object",properties:{to:{type:"string",description:"Recipient bech32m address"},amount:{type:"string",description:"Amount in NIGHT to send"},wallet:{type:"string",description:"Custom wallet file path"}},required:["to","amount"]},async handler($){let{to:Z,amount:Q}=$,X=l("transfer",$,Z);X.positionals=[Q],delete X.flags.to,delete X.flags.amount;let q=await x("transfer");return R(q,X)}},{name:"midnight_dust_register",description:"Register NIGHT UTXOs for dust (fee token) generation",inputSchema:{type:"object",properties:{wallet:{type:"string",description:"Custom wallet file path"}}},async handler($){let Z=l("dust",$,"register"),Q=await x("dust");return R(Q,Z)}},{name:"midnight_dust_status",description:"Check dust registration status and balance",inputSchema:{type:"object",properties:{wallet:{type:"string",description:"Custom wallet file path"}}},async handler($){let Z=l("dust",$,"status"),Q=await x("dust");return R(Q,Z)}},{name:"midnight_config_get",description:"Read a persistent config value",inputSchema:{type:"object",properties:{key:{type:"string",description:'Config key to read (e.g. "network")'}},required:["key"]},async handler($){let Q={command:"config",subcommand:"get",positionals:[$.key],flags:{json:!0}},X=await x("config");return R(X,Q)}},{name:"midnight_config_set",description:"Write a persistent config value",inputSchema:{type:"object",properties:{key:{type:"string",description:'Config key to set (e.g. "network")'},value:{type:"string",description:"Config value to set"}},required:["key","value"]},async handler($){let{key:Z,value:Q}=$,X={command:"config",subcommand:"set",positionals:[Z,Q],flags:{json:!0}},q=await x("config");return R(q,X)}},{name:"midnight_localnet_up",description:"Start a local Midnight network via Docker Compose",inputSchema:{type:"object",properties:{}},async handler(){let $={command:"localnet",subcommand:"up",positionals:[],flags:{json:!0}},Z=await x("localnet");return R(Z,$)}},{name:"midnight_localnet_stop",description:"Stop local network containers (preserves state for fast restart)",inputSchema:{type:"object",properties:{}},async handler(){let $={command:"localnet",subcommand:"stop",positionals:[],flags:{json:!0}},Z=await x("localnet");return R(Z,$)}},{name:"midnight_localnet_down",description:"Remove local network containers, networks, and volumes (full teardown)",inputSchema:{type:"object",properties:{}},async handler(){let $={command:"localnet",subcommand:"down",positionals:[],flags:{json:!0}},Z=await x("localnet");return R(Z,$)}},{name:"midnight_localnet_status",description:"Show local network service status and ports",inputSchema:{type:"object",properties:{}},async handler(){let $={command:"localnet",subcommand:"status",positionals:[],flags:{json:!0}},Z=await x("localnet");return R(Z,$)}},{name:"midnight_localnet_clean",description:"Remove conflicting containers from other setups",inputSchema:{type:"object",properties:{}},async handler(){let $={command:"localnet",subcommand:"clean",positionals:[],flags:{json:!0}},Z=await x("localnet");return R(Z,$)}}],m1=new D$({name:"midnight-wallet-cli",version:q0},{capabilities:{tools:{}}});m1.setRequestHandler(x$,async()=>{return{tools:J2.map(($)=>({name:$.name,description:$.description,inputSchema:$.inputSchema}))}});m1.setRequestHandler(E$,async($)=>{let{name:Z,arguments:Q}=$.params,X=J2.find((q)=>q.name===Z);if(!X)return{content:[{type:"text",text:`Unknown tool: ${Z}`}],isError:!0};try{let q=await X.handler(Q??{});return{content:[{type:"text",text:JSON.stringify(q,null,2)}]}}catch(q){let z=q instanceof Error?q:new Error(String(q)),{errorCode:Y}=y0(z);return{content:[{type:"text",text:JSON.stringify({error:!0,code:Y,message:z.message})}],isError:!0}}});v$().catch(($)=>{process.stderr.write(`MCP server error: ${$.message}
|
|
276
|
+
`),process.exit(1)})});function U2($){let Z=Math.max(0,Math.min(1,$)),Q=H0[0].length,X=Math.floor(Z*Q);return H0.map((q)=>q.slice(0,X).padEnd(Q))}function B2($){let Z=Math.max(0,Math.min(1,$)),Q=Math.floor($*100);if(Z>=1)return H0;return H0.map((X,q)=>Array.from(X).map((z,Y)=>{if(z===" ")return" ";if(Z<=0)return r0(q+20,Y,0);let K=((q+20)*131+Y*997)%100/100;return Z>=K?z:r0(q+20,Y,Q)}).join(""))}function r0($,Z,Q){let X=($*131+Z*997+Q*7919)%65537/65537;return G2[Math.floor(X*G2.length)]}function V2($){let Z=Math.max(0,Math.min(1,$)),Q=t0.split(`
|
|
277
|
+
`),X=Math.floor($*100);if(Z>=1)return t0;if(Z<=0)return Q.map((q,z)=>Array.from(q).map((Y,K)=>r0(z,K,0)).join("")).join(`
|
|
278
|
+
`);return Q.map((q,z)=>Array.from(q).map((Y,K)=>{if(Y===" ")return" ";let G=(z*131+K*997)%100/100;return Z>=G?Y:r0(z,K,X)}).join("")).join(`
|
|
279
|
+
`)}var t0,H0,g1,G2;var d1=O(()=>{t0=[" ████████████ "," ███ ███ "," ███ ██ ███ "," ██ ██ "," ██ ██ ██ "," ██ ██ "," ██ ██ ██ "," ██ ██ "," ██ ██ "," ██ ██ "," ██ ██ "," ███ ███ "," ███ ███ "," ████████████ "].join(`
|
|
280
|
+
`),H0=["█▄ ▄█ █ █▀▄ █▄ █ █ █▀▀ █ █ ▀█▀","█ █ █ █ █ █ █ ██ █ █ █ █▀█ █ ","▀ ▀ ▀ ▀▀ ▀ ▀ ▀ ▀▀▀ ▀ ▀ ▀ "];g1=[["generate","Generate or restore a wallet"],["info","Display wallet metadata"],["balance","Check unshielded balance"],["address","Derive address from seed"],["genesis-address","Show genesis address"],["inspect-cost","Display block limits"],["airdrop","Fund from genesis wallet"],["transfer","Send NIGHT tokens"],["dust","Manage dust (fee tokens)"],["config","Manage CLI config"],["localnet","Manage local network"],["help","Show command usage"]],G2=["░","▒","▓","█","·"," "]});function i1($,Z){return new Promise((Q,X)=>{if(Z?.aborted){Q();return}let q=setTimeout(Q,$);Z?.addEventListener("abort",()=>{clearTimeout(q),Q()},{once:!0})})}async function W2($,Z){let X=t0.split(`
|
|
281
|
+
`),q=X.length,z=36,Y=Math.max(q,Z?.length??0),K=3;if(!i()){for(let B=0;B<Y;B++){let F=(B<q?X[B]:"").padEnd(35),M=Z?.[B]??"";process.stderr.write(F+M+`
|
|
282
|
+
`)}return}function G(B,F){for(let M=0;M<Y;M++){let _=M<B.length?F0(B[M]):"",T=F[M]??"";if(T)process.stderr.write(_+"\x1B[36G"+T+`\x1B[K
|
|
283
|
+
`);else process.stderr.write(_+`\x1B[K
|
|
284
|
+
`)}}function U(){process.stderr.write(`\x1B[${Y}A`)}for(let B=0;B<=20;B++){if($?.aborted)break;let F=B/20,_=V2(F).split(`
|
|
285
|
+
`);if(B>0)U();G(_,[]),await i1(l1,$)}let V=20;for(let B=0;B<=V;B++){if($?.aborted)break;let F=B/V,M=U2(F);U();let _=new Array(Y).fill(null);for(let T=0;T<M.length;T++)_[T]=y(F0(M[T]));G(X,_),await i1(l1,$)}let J=12;for(let B=0;B<=J;B++){if($?.aborted)break;let F=B/J,M=B2(F);U();let _=new Array(Y).fill(null);for(let T=0;T<M.length;T++)_[T]=y(F0(M[T]));G(X,_),await i1(l1,$)}U();let W=new Array(Y).fill(null);if(Z)for(let B=0;B<Z.length;B++)if(B<3)W[B]=y(F0(Z[B]));else W[B]=Z[B];G(X,W)}var l1=80;var H2=O(()=>{d1()});var F2={};S(F2,{default:()=>j2,COMMAND_SPECS:()=>A0});function b$(){let $=[];for(let Z of H0)$.push(Z);$.push(""),$.push(y("Commands"));for(let[Z,Q]of g1)$.push(`${t(Z.padEnd(18))}${Q}`);return $.push(""),$.push(j("midnight (or mn) help <command>")),$.push(j("--json flag available on all commands")),$.push(j("midnight help --agent")+j(" AI & MCP reference")),$}function w$(){process.stderr.write(`
|
|
286
286
|
Commands:
|
|
287
287
|
|
|
288
|
-
`);for(let[$,Z]of
|
|
288
|
+
`);for(let[$,Z]of g1)process.stderr.write(` ${$.padEnd(18)}${Z}
|
|
289
289
|
`);process.stderr.write(`
|
|
290
290
|
Usage: midnight <command> (or: mn <command>)
|
|
291
291
|
`),process.stderr.write(` --json flag available on all commands
|
|
292
292
|
`),process.stderr.write(` midnight help --agent AI & MCP reference
|
|
293
293
|
|
|
294
|
-
`)}function
|
|
295
|
-
`+
|
|
294
|
+
`)}function S$($){if(process.stdout.write(`
|
|
295
|
+
`+I($.name)+`
|
|
296
296
|
|
|
297
297
|
`),process.stdout.write(` ${$.description}
|
|
298
298
|
|
|
299
|
-
`),process.stdout.write(
|
|
299
|
+
`),process.stdout.write(G0("Usage:")+`
|
|
300
300
|
`),process.stdout.write(` ${$.usage}
|
|
301
301
|
|
|
302
|
-
`),$.flags&&$.flags.length>0){process.stdout.write(
|
|
302
|
+
`),$.flags&&$.flags.length>0){process.stdout.write(G0("Flags:")+`
|
|
303
303
|
`);for(let Z of $.flags)process.stdout.write(` ${Z}
|
|
304
304
|
`);process.stdout.write(`
|
|
305
|
-
`)}if($.examples&&$.examples.length>0){process.stdout.write(
|
|
305
|
+
`)}if($.examples&&$.examples.length>0){process.stdout.write(G0("Examples:")+`
|
|
306
306
|
`);for(let Z of $.examples)process.stdout.write(` ${j("$")} ${Z}
|
|
307
307
|
`);process.stdout.write(`
|
|
308
|
-
`)}}function
|
|
308
|
+
`)}}function C$(){let $={cli:{name:V3,version:q0,description:W3,bin:["midnight","mn"]},globalFlags:[{name:"--json",description:"Output structured JSON to stdout (suppresses all stderr)"},{name:"--wallet <file>",description:"Custom wallet file path"},{name:"--network <name>",description:"Override network (preprod, preview, undeployed)"},{name:"--version, -v",description:"Print CLI version"},{name:"--help, -h",description:"Show help"}],commands:A0.map((Z)=>({name:Z.name,description:Z.description,usage:Z.usage,flags:Z.flags,examples:Z.examples,jsonFields:Z.jsonFields}))};L($)}function f$(){let $=`
|
|
309
309
|
MIDNIGHT CLI — AI Agent & MCP Reference
|
|
310
310
|
========================================
|
|
311
311
|
|
|
312
|
-
Version: ${
|
|
312
|
+
Version: ${q0}
|
|
313
313
|
|
|
314
314
|
STRUCTURED JSON OUTPUT
|
|
315
315
|
──────────────────────
|
|
@@ -332,7 +332,7 @@ for programmatic discovery of CLI capabilities.
|
|
|
332
332
|
|
|
333
333
|
COMMANDS & JSON SCHEMAS
|
|
334
334
|
───────────────────────
|
|
335
|
-
${
|
|
335
|
+
${A0.filter((Z)=>Z.jsonFields).map((Z)=>{let Q=Object.entries(Z.jsonFields).map(([X,q])=>` ${X.padEnd(20)}${q}`).join(`
|
|
336
336
|
`);return`
|
|
337
337
|
${Z.name}
|
|
338
338
|
${Z.usage}
|
|
@@ -411,10 +411,10 @@ EXAMPLE WORKFLOW
|
|
|
411
411
|
# 4. Transfer tokens
|
|
412
412
|
midnight transfer mn_addr_... 100 --json
|
|
413
413
|
# → {"txHash":"...","amount":"100","recipient":"mn_addr_...","network":"undeployed"}
|
|
414
|
-
`;process.stdout.write($)}async function
|
|
415
|
-
Available commands: ${
|
|
416
|
-
`),process.exit(0);if(P($,"help")||P($,"h"))$.command="help";let Q=$.command??"help",X;if(Z)X=G3();let q=new AbortController,{signal:z}=q;process.on("SIGINT",Y),process.on("SIGTERM",Y);async function K(){switch(Q){case"help":{let{default:U}=await Promise.resolve().then(() => (
|
|
417
|
-
Run "midnight help" to see available commands.`)}}let G=new Set(["airdrop","transfer","dust"]);K().then(()=>{if(G.has(Q))process.exit(0)}).catch((U)=>{if(Z){X?.();let{exitCode:
|
|
414
|
+
`;process.stdout.write($)}async function j2($){if(P($,"agent")){f$();return}if(P($,"json")){C$();return}let Z=$.subcommand;if(Z){let X=A0.find((q)=>q.name===Z);if(!X)throw new Error(`Unknown command: "${Z}"
|
|
415
|
+
Available commands: ${A0.map((q)=>q.name).join(", ")}`);S$(X);return}if(!process.stderr.isTTY){w$();return}let Q=b$();await W2(void 0,Q)}var A0;var P2=O(()=>{N();H2();d1();w0();A0=[{name:"generate",description:"Generate a new wallet (random mnemonic, or restore from seed/mnemonic)",usage:'midnight generate [--network <name>] [--seed <hex>] [--mnemonic "..."] [--output <file>] [--force]',flags:["--network <name> Network: preprod, preview, undeployed","--seed <hex> Restore from existing seed (64-char hex)",'--mnemonic "..." Restore from BIP-39 mnemonic (24 words)',"--output <file> Custom output path (default: ~/.midnight/wallet.json)","--force Overwrite existing wallet file"],examples:["midnight generate --network preprod","midnight generate --network preprod --output my-wallet.json","midnight generate --seed 0123456789abcdef..."],jsonFields:{address:"Generated wallet address (bech32m)",network:"Network name",seed:"Hex-encoded 32-byte seed",mnemonic:"BIP-39 mnemonic (24 words, only if generated or provided)",file:"Path where wallet file was saved",createdAt:"ISO 8601 creation timestamp"}},{name:"info",description:"Display wallet address, network, creation date (no secrets shown)",usage:"midnight info [--wallet <file>]",flags:["--wallet <file> Custom wallet file path"],examples:["midnight info","midnight info --wallet my-wallet.json"],jsonFields:{address:"Wallet address (bech32m)",network:"Network name",createdAt:"ISO 8601 creation timestamp",file:"Wallet file path"}},{name:"balance",description:"Check unshielded balance via GraphQL subscription",usage:"midnight balance [address] [--network <name>] [--indexer-ws <url>]",flags:["<address> Address to check (or reads from wallet file)","--network <name> Override network detection","--indexer-ws <url> Custom indexer WebSocket URL"],examples:["midnight balance","midnight balance mn_addr_preprod1...","midnight balance --network preprod"],jsonFields:{address:"Checked address (bech32m)",network:"Network name",balances:"Object mapping token type to balance string",utxoCount:"Number of UTXOs",txCount:"Number of transactions synced"}},{name:"address",description:"Derive and display an unshielded address from a seed",usage:"midnight address --seed <hex> [--network <name>] [--index <n>]",flags:["--seed <hex> Seed to derive from (required, 64-char hex)","--network <name> Network for address prefix (default: resolved)","--index <n> Key derivation index (default: 0)"],examples:["midnight address --seed 0123456789abcdef... --network preprod","midnight address --seed 0123456789abcdef... --index 1"],jsonFields:{address:"Derived address (bech32m)",network:"Network name",index:"Key derivation index",path:"BIP-44 derivation path"}},{name:"genesis-address",description:"Display the genesis wallet address (seed 0x01) for a network",usage:"midnight genesis-address [--network <name>]",flags:["--network <name> Network for address prefix (default: resolved)"],examples:["midnight genesis-address --network undeployed","midnight genesis-address --network preprod"],jsonFields:{address:"Genesis wallet address (bech32m)",network:"Network name"}},{name:"inspect-cost",description:"Display current block limits derived from LedgerParameters",usage:"midnight inspect-cost",examples:["midnight inspect-cost"],jsonFields:{readTime:"Read time limit (picoseconds)",computeTime:"Compute time limit (picoseconds)",blockUsage:"Block usage limit (bytes)",bytesWritten:"Bytes written limit (bytes)",bytesChurned:"Bytes churned limit (bytes)"}},{name:"airdrop",description:"Fund your wallet from the genesis wallet (undeployed network only)",usage:"midnight airdrop <amount> [--wallet <file>]",flags:["<amount> Amount in NIGHT to airdrop","--wallet <file> Custom wallet file path"],examples:["midnight airdrop 1000","midnight airdrop 0.5 --wallet my-wallet.json"],jsonFields:{txHash:"Transaction hash",amount:"Amount airdropped (NIGHT string)",recipient:"Recipient address (bech32m)",network:"Network name"}},{name:"transfer",description:"Send NIGHT tokens to another address",usage:"midnight transfer <to> <amount> [--wallet <file>]",flags:["<to> Recipient bech32m address","<amount> Amount in NIGHT to send","--wallet <file> Custom wallet file path"],examples:["midnight transfer mn_addr_undeployed1... 100","midnight transfer mn_addr_preprod1... 50 --wallet my-wallet.json"],jsonFields:{txHash:"Transaction hash",amount:"Amount transferred (NIGHT string)",recipient:"Recipient address (bech32m)",network:"Network name"}},{name:"dust",description:"Register UTXOs for dust (fee token) generation or check status",usage:"midnight dust <register|status> [--wallet <file>]",flags:["register Register NIGHT UTXOs for dust generation","status Check dust registration status and balance","--wallet <file> Custom wallet file path"],examples:["midnight dust register","midnight dust status"],jsonFields:{subcommand:"register or status",dustBalance:"Dust balance (raw bigint string)",registered:"Number of registered UTXOs (status only)",unregistered:"Number of unregistered UTXOs (status only)",nightBalance:"NIGHT balance (raw bigint string, status only)",dustAvailable:"Whether dust tokens are available (status only)",txHash:"Registration transaction hash (register only, if submitted)"}},{name:"config",description:"Manage persistent config (default network, etc.)",usage:"midnight config <get|set> <key> [value]",flags:["get <key> Read a config value","set <key> <value> Write a config value"],examples:["midnight config get network","midnight config set network preprod"],jsonFields:{action:"get or set",key:"Config key name",value:"Config value"}},{name:"localnet",description:"Manage a local Midnight network via Docker Compose",usage:"midnight localnet <up|stop|down|status|logs|clean>",flags:["up Start the local network (node, indexer, proof server)","stop Stop containers (preserves state for fast restart)","down Remove containers, networks, and volumes (full teardown)","status Show service status and ports","logs Stream service logs (Ctrl+C to stop)","clean Remove conflicting containers from other setups"],examples:["midnight localnet up","midnight localnet stop","midnight localnet status","midnight localnet down","midnight localnet clean"],jsonFields:{subcommand:"up, stop, down, status, or clean",services:"Array of { name, state, port, health? } (up/status only)",status:"Operation result message (stop/down/clean)",removed:"Array of removed container names (clean only)"}},{name:"help",description:"Show usage for all commands or a specific command",usage:"midnight help [command]",examples:["midnight help","midnight help balance"],jsonFields:{cli:"CLI metadata (name, version, description)",globalFlags:"Array of global flag descriptions",commands:"Array of command specs with jsonFields"}}]});N();Z1();w0();if(process.argv.includes("--mcp"))await Promise.resolve().then(() => (K2(),k$));else{let Y=function(){q.abort(),setTimeout(()=>process.exit(130),5000).unref()},$=o1(),Z=P($,"json");if(P($,"version")||P($,"v"))process.stdout.write(q0+`
|
|
416
|
+
`),process.exit(0);if(P($,"help")||P($,"h"))$.command="help";let Q=$.command??"help",X;if(Z)X=G3();let q=new AbortController,{signal:z}=q;process.on("SIGINT",Y),process.on("SIGTERM",Y);async function K(){switch(Q){case"help":{let{default:U}=await Promise.resolve().then(() => (P2(),F2));return U($)}case"generate":{let{default:U}=await Promise.resolve().then(() => (U1(),G1));return U($)}case"info":{let{default:U}=await Promise.resolve().then(() => (V1(),B1));return U($)}case"balance":{let{default:U}=await Promise.resolve().then(() => (H1(),W1));return U($)}case"address":{let{default:U}=await Promise.resolve().then(() => (F1(),j1));return U($)}case"genesis-address":{let{default:U}=await Promise.resolve().then(() => (O1(),P1));return U($)}case"inspect-cost":{let{default:U}=await Promise.resolve().then(() => (y1(),L1));return U($)}case"config":{let{default:U}=await Promise.resolve().then(() => (S1(),w1));return U($)}case"airdrop":{let{default:U}=await Promise.resolve().then(() => (E1(),x1));return U($,z)}case"transfer":{let{default:U}=await Promise.resolve().then(() => (v1(),N1));return U($,z)}case"dust":{let{default:U}=await Promise.resolve().then(() => (b1(),k1));return U($,z)}case"localnet":{let{default:U}=await Promise.resolve().then(() => (c1(),u1));return U($)}default:throw new Error(`Unknown command: "${Q}"
|
|
417
|
+
Run "midnight help" to see available commands.`)}}let G=new Set(["airdrop","transfer","dust"]);K().then(()=>{if(G.has(Q))process.exit(0)}).catch((U)=>{if(Z){X?.();let{exitCode:V,errorCode:J}=y0(U);U3(U,J,V),process.exit(V)}else{process.stderr.write(`
|
|
418
418
|
`+K3(U.message,'Run "midnight help" for usage information.')+`
|
|
419
419
|
|
|
420
|
-
`);let{exitCode:
|
|
420
|
+
`);let{exitCode:V}=y0(U);process.exit(V)}})}
|