midnight-wallet-cli 0.1.10 → 0.1.11
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/README.md +6 -11
- package/dist/mcp-server.js +1 -1
- package/dist/wallet.js +54 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -91,8 +91,7 @@ Create `.mcp.json` in your project root:
|
|
|
91
91
|
{
|
|
92
92
|
"mcpServers": {
|
|
93
93
|
"midnight-wallet": {
|
|
94
|
-
"command": "
|
|
95
|
-
"args": ["-y", "midnight-wallet-cli@latest", "--mcp"]
|
|
94
|
+
"command": "midnight-wallet-mcp"
|
|
96
95
|
}
|
|
97
96
|
}
|
|
98
97
|
}
|
|
@@ -106,8 +105,7 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)
|
|
|
106
105
|
{
|
|
107
106
|
"mcpServers": {
|
|
108
107
|
"midnight-wallet": {
|
|
109
|
-
"command": "
|
|
110
|
-
"args": ["-y", "midnight-wallet-cli@latest", "--mcp"]
|
|
108
|
+
"command": "midnight-wallet-mcp"
|
|
111
109
|
}
|
|
112
110
|
}
|
|
113
111
|
}
|
|
@@ -121,8 +119,7 @@ Create `.cursor/mcp.json` in your project root:
|
|
|
121
119
|
{
|
|
122
120
|
"mcpServers": {
|
|
123
121
|
"midnight-wallet": {
|
|
124
|
-
"command": "
|
|
125
|
-
"args": ["-y", "midnight-wallet-cli@latest", "--mcp"]
|
|
122
|
+
"command": "midnight-wallet-mcp"
|
|
126
123
|
}
|
|
127
124
|
}
|
|
128
125
|
}
|
|
@@ -137,8 +134,7 @@ Create `.vscode/mcp.json` in your project root:
|
|
|
137
134
|
"servers": {
|
|
138
135
|
"midnight-wallet": {
|
|
139
136
|
"type": "stdio",
|
|
140
|
-
"command": "
|
|
141
|
-
"args": ["-y", "midnight-wallet-cli@latest", "--mcp"]
|
|
137
|
+
"command": "midnight-wallet-mcp"
|
|
142
138
|
}
|
|
143
139
|
}
|
|
144
140
|
}
|
|
@@ -152,14 +148,13 @@ Add to `~/.codeium/windsurf/mcp_config.json`:
|
|
|
152
148
|
{
|
|
153
149
|
"mcpServers": {
|
|
154
150
|
"midnight-wallet": {
|
|
155
|
-
"command": "
|
|
156
|
-
"args": ["-y", "midnight-wallet-cli@latest", "--mcp"]
|
|
151
|
+
"command": "midnight-wallet-mcp"
|
|
157
152
|
}
|
|
158
153
|
}
|
|
159
154
|
}
|
|
160
155
|
```
|
|
161
156
|
|
|
162
|
-
> **Tip:** If you installed globally
|
|
157
|
+
> **Tip:** If you haven't installed globally, use `"command": "npx"` with `"args": ["-y", "midnight-wallet-cli@latest", "--mcp"]` instead.
|
|
163
158
|
|
|
164
159
|
### Available MCP Tools
|
|
165
160
|
|
package/dist/mcp-server.js
CHANGED
|
@@ -273,5 +273,5 @@ Subcommands:
|
|
|
273
273
|
Example: midnight localnet up`);f3();let Q=P($,"json");switch(process.stderr.write(`
|
|
274
274
|
`+I("Localnet")+`
|
|
275
275
|
|
|
276
|
-
`),Z){case"up":return a2(Q);case"stop":return r2(Q);case"down":return t2(Q);case"status":return s2(Q);case"logs":return $$();case"clean":return e2(Q)}}var g3;var o3=M(()=>{u3();w();q0();g3=["up","stop","down","status","logs","clean"]});import{Server as Z$}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as Q$}from"@modelcontextprotocol/sdk/server/stdio.js";import{ListToolsRequestSchema as X$,CallToolRequestSchema as z$}from"@modelcontextprotocol/sdk/types.js";async function T($,Z,Q){let X=[];l0((q)=>X.push(q));let z=process.stderr.write;process.stderr.write=()=>!0;try{Z.flags.json=!0,await $(Z,Q);let q=X.join("").trim();if(!q)return{};return JSON.parse(q)}finally{l0(null),process.stderr.write=z}}var S={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 F1($){let Z=($.message??"").toLowerCase();if(Z.includes("operation cancelled")||Z.includes("operation aborted")||Z==="cancelled"||Z==="aborted")return{exitCode:7,errorCode:S.CANCELLED};if(Z.includes("wallet file not found")||Z.includes("wallet")&&Z.includes("not found"))return{exitCode:3,errorCode:S.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:S.INVALID_ARGS};if(Z.includes("proof")&&Z.includes("timeout"))return{exitCode:6,errorCode:S.PROOF_TIMEOUT};if(Z.includes("stale utxo")||Z.includes("error code 115")||Z.includes("errorcode: 115"))return{exitCode:6,errorCode:S.STALE_UTXO};if(Z.includes("no dust")||Z.includes("dust")&&(Z.includes("required")||Z.includes("available")||Z.includes("insufficient")))return{exitCode:5,errorCode:S.DUST_REQUIRED};if(Z.includes("insufficient")||Z.includes("not enough"))return{exitCode:5,errorCode:S.INSUFFICIENT_BALANCE};if(Z.includes("rejected")||Z.includes("transaction failed"))return{exitCode:6,errorCode:S.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:S.NETWORK_ERROR};return{exitCode:1,errorCode:S.UNKNOWN}}var _0={name:"midnight-wallet-cli",version:"0.1.10",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 V$=_0.name,L1=_0.version,F$=_0.description;function p($,Z,Q){let X={json:!0},z=[];for(let[q,Y]of Object.entries(Z)){if(Y===void 0||Y===null)continue;if(typeof Y==="boolean"){if(Y)X[q]=!0}else X[q]=String(Y)}return{command:$,subcommand:Q,positionals:z,flags:X}}var q$={generate:()=>Promise.resolve().then(() => (r1(),a1)),info:()=>Promise.resolve().then(() => (e1(),s1)),balance:()=>Promise.resolve().then(() => (q3(),z3)),address:()=>Promise.resolve().then(() => (J3(),G3)),"genesis-address":()=>Promise.resolve().then(() => (H3(),U3)),"inspect-cost":()=>Promise.resolve().then(() => (V3(),B3)),airdrop:()=>Promise.resolve().then(() => (R3(),I3)),transfer:()=>Promise.resolve().then(() => (y3(),D3)),dust:()=>Promise.resolve().then(() => (C3(),N3)),config:()=>Promise.resolve().then(() => (b3(),v3)),localnet:()=>Promise.resolve().then(() => (o3(),i3))};async function D($){let Z=q$[$];if(!Z)throw new Error(`Unknown command handler: ${$}`);return(await Z()).default}var n3=[{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=p("generate",$);if($.force==="true"||$.force===!0)Z.flags.force=!0;let Q=await D("generate");return T(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=p("info",$),Q=await D("info");return T(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=p("balance",$,Z);delete Q.flags.address;let X=await D("balance");return T(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=p("address",$),Q=await D("address");return T(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=p("genesis-address",$),Q=await D("genesis-address");return T(Q,Z)}},{name:"midnight_inspect_cost",description:"Display current block limits derived from LedgerParameters",inputSchema:{type:"object",properties:{}},async handler(){let $=p("inspect-cost",{}),Z=await D("inspect-cost");return T(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=p("airdrop",$,Z);delete Q.flags.amount;let X=await D("airdrop");return T(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=p("transfer",$,Z);X.positionals=[Q],delete X.flags.to,delete X.flags.amount;let z=await D("transfer");return T(z,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=p("dust",$,"register"),Q=await D("dust");return T(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=p("dust",$,"status"),Q=await D("dust");return T(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 D("config");return T(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}},z=await D("config");return T(z,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 D("localnet");return T(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 D("localnet");return T(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 D("localnet");return T(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 D("localnet");return T(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 D("localnet");return T(Z,$)}}],B1=new Z$({name:"midnight-wallet-cli",version:L1},{capabilities:{tools:{}}});B1.setRequestHandler(X$,async()=>{return{tools:n3.map(($)=>({name:$.name,description:$.description,inputSchema:$.inputSchema}))}});B1.setRequestHandler(z$,async($)=>{let{name:Z,arguments:Q}=$.params,X=n3.find((z)=>z.name===Z);if(!X)return{content:[{type:"text",text:`Unknown tool: ${Z}`}],isError:!0};try{let z=await X.handler(Q??{});return{content:[{type:"text",text:JSON.stringify(z,null,2)}]}}catch(z){let q=z instanceof Error?z:new Error(String(z)),{errorCode:Y}=F1(q);return{content:[{type:"text",text:JSON.stringify({error:!0,code:Y,message:q.message})}],isError:!0}}});async function Y$(){let $=new Q$;await B1.connect($)}Y$().catch(($)=>{process.stderr.write(`MCP server error: ${$.message}
|
|
276
|
+
`),Z){case"up":return a2(Q);case"stop":return r2(Q);case"down":return t2(Q);case"status":return s2(Q);case"logs":return $$();case"clean":return e2(Q)}}var g3;var o3=M(()=>{u3();w();q0();g3=["up","stop","down","status","logs","clean"]});import{Server as Z$}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as Q$}from"@modelcontextprotocol/sdk/server/stdio.js";import{ListToolsRequestSchema as X$,CallToolRequestSchema as z$}from"@modelcontextprotocol/sdk/types.js";async function T($,Z,Q){let X=[];l0((q)=>X.push(q));let z=process.stderr.write;process.stderr.write=()=>!0;try{Z.flags.json=!0,await $(Z,Q);let q=X.join("").trim();if(!q)return{};return JSON.parse(q)}finally{l0(null),process.stderr.write=z}}var S={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 F1($){let Z=($.message??"").toLowerCase();if(Z.includes("operation cancelled")||Z.includes("operation aborted")||Z==="cancelled"||Z==="aborted")return{exitCode:7,errorCode:S.CANCELLED};if(Z.includes("wallet file not found")||Z.includes("wallet")&&Z.includes("not found"))return{exitCode:3,errorCode:S.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:S.INVALID_ARGS};if(Z.includes("proof")&&Z.includes("timeout"))return{exitCode:6,errorCode:S.PROOF_TIMEOUT};if(Z.includes("stale utxo")||Z.includes("error code 115")||Z.includes("errorcode: 115"))return{exitCode:6,errorCode:S.STALE_UTXO};if(Z.includes("no dust")||Z.includes("dust")&&(Z.includes("required")||Z.includes("available")||Z.includes("insufficient")))return{exitCode:5,errorCode:S.DUST_REQUIRED};if(Z.includes("insufficient")||Z.includes("not enough"))return{exitCode:5,errorCode:S.INSUFFICIENT_BALANCE};if(Z.includes("rejected")||Z.includes("transaction failed"))return{exitCode:6,errorCode:S.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:S.NETWORK_ERROR};return{exitCode:1,errorCode:S.UNKNOWN}}var _0={name:"midnight-wallet-cli",version:"0.1.11",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 V$=_0.name,L1=_0.version,F$=_0.description;function p($,Z,Q){let X={json:!0},z=[];for(let[q,Y]of Object.entries(Z)){if(Y===void 0||Y===null)continue;if(typeof Y==="boolean"){if(Y)X[q]=!0}else X[q]=String(Y)}return{command:$,subcommand:Q,positionals:z,flags:X}}var q$={generate:()=>Promise.resolve().then(() => (r1(),a1)),info:()=>Promise.resolve().then(() => (e1(),s1)),balance:()=>Promise.resolve().then(() => (q3(),z3)),address:()=>Promise.resolve().then(() => (J3(),G3)),"genesis-address":()=>Promise.resolve().then(() => (H3(),U3)),"inspect-cost":()=>Promise.resolve().then(() => (V3(),B3)),airdrop:()=>Promise.resolve().then(() => (R3(),I3)),transfer:()=>Promise.resolve().then(() => (y3(),D3)),dust:()=>Promise.resolve().then(() => (C3(),N3)),config:()=>Promise.resolve().then(() => (b3(),v3)),localnet:()=>Promise.resolve().then(() => (o3(),i3))};async function D($){let Z=q$[$];if(!Z)throw new Error(`Unknown command handler: ${$}`);return(await Z()).default}var n3=[{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=p("generate",$);if($.force==="true"||$.force===!0)Z.flags.force=!0;let Q=await D("generate");return T(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=p("info",$),Q=await D("info");return T(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=p("balance",$,Z);delete Q.flags.address;let X=await D("balance");return T(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=p("address",$),Q=await D("address");return T(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=p("genesis-address",$),Q=await D("genesis-address");return T(Q,Z)}},{name:"midnight_inspect_cost",description:"Display current block limits derived from LedgerParameters",inputSchema:{type:"object",properties:{}},async handler(){let $=p("inspect-cost",{}),Z=await D("inspect-cost");return T(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=p("airdrop",$,Z);delete Q.flags.amount;let X=await D("airdrop");return T(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=p("transfer",$,Z);X.positionals=[Q],delete X.flags.to,delete X.flags.amount;let z=await D("transfer");return T(z,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=p("dust",$,"register"),Q=await D("dust");return T(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=p("dust",$,"status"),Q=await D("dust");return T(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 D("config");return T(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}},z=await D("config");return T(z,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 D("localnet");return T(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 D("localnet");return T(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 D("localnet");return T(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 D("localnet");return T(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 D("localnet");return T(Z,$)}}],B1=new Z$({name:"midnight-wallet-cli",version:L1},{capabilities:{tools:{}}});B1.setRequestHandler(X$,async()=>{return{tools:n3.map(($)=>({name:$.name,description:$.description,inputSchema:$.inputSchema}))}});B1.setRequestHandler(z$,async($)=>{let{name:Z,arguments:Q}=$.params,X=n3.find((z)=>z.name===Z);if(!X)return{content:[{type:"text",text:`Unknown tool: ${Z}`}],isError:!0};try{let z=await X.handler(Q??{});return{content:[{type:"text",text:JSON.stringify(z,null,2)}]}}catch(z){let q=z instanceof Error?z:new Error(String(z)),{errorCode:Y}=F1(q);return{content:[{type:"text",text:JSON.stringify({error:!0,code:Y,message:q.message})}],isError:!0}}});async function Y$(){let $=new Q$;await B1.connect($)}Y$().catch(($)=>{process.stderr.write(`MCP server error: ${$.message}
|
|
277
277
|
`),process.exit(1)});
|
package/dist/wallet.js
CHANGED
|
@@ -5,7 +5,7 @@ var D2=Object.defineProperty;var b=($,Z)=>{for(var Q in Z)D2($,Q,{get:Z[Q],enume
|
|
|
5
5
|
`).map((z,Y)=>Y===0?k(M("Error: "))+k(z):k(z));if(Z)X.push(""),X.push(j("Suggestion: ")+Z);let q=R2(X,"heavy");if(m())return q.replace(/[╔╗╚╝═║]/g,(z)=>k(z));return q}function s($,Z){let X=[`${g("✓")} ${$}`];if(Z)X.push(B("Transaction",i(Z)));return X.join(`
|
|
6
6
|
`)}var B3=60,H3=15,O0=($)=>$.replace(/\x1b\[[0-9;]*m/g,"");var N=()=>{};function T0($){let Z=($.message??"").toLowerCase();if(Z.includes("operation cancelled")||Z.includes("operation aborted")||Z==="cancelled"||Z==="aborted")return{exitCode:7,errorCode:h.CANCELLED};if(Z.includes("wallet file not found")||Z.includes("wallet")&&Z.includes("not found"))return{exitCode:3,errorCode:h.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:h.INVALID_ARGS};if(Z.includes("proof")&&Z.includes("timeout"))return{exitCode:6,errorCode:h.PROOF_TIMEOUT};if(Z.includes("stale utxo")||Z.includes("error code 115")||Z.includes("errorcode: 115"))return{exitCode:6,errorCode:h.STALE_UTXO};if(Z.includes("no dust")||Z.includes("dust")&&(Z.includes("required")||Z.includes("available")||Z.includes("insufficient")))return{exitCode:5,errorCode:h.DUST_REQUIRED};if(Z.includes("insufficient")||Z.includes("not enough"))return{exitCode:5,errorCode:h.INSUFFICIENT_BALANCE};if(Z.includes("rejected")||Z.includes("transaction failed"))return{exitCode:6,errorCode:h.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:h.NETWORK_ERROR};return{exitCode:1,errorCode:h.UNKNOWN}}var h;var q1=L(()=>{h={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 F3(){let $=process.stderr.write;return process.stderr.write=()=>!0,()=>{process.stderr.write=$}}function Y1($){z1=$}function T($){let Z=JSON.stringify($)+`
|
|
7
7
|
`;if(z1)z1(Z);else process.stdout.write(Z)}function P3($,Z,Q){process.stdout.write(JSON.stringify({error:!0,code:Z,message:$.message,exitCode:Q})+`
|
|
8
|
-
`)}var z1=null;var b0;var O3=L(()=>{b0={name:"midnight-wallet-cli",version:"0.1.
|
|
8
|
+
`)}var z1=null;var b0;var O3=L(()=>{b0={name:"midnight-wallet-cli",version:"0.1.11",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 L3,e,T3;var k0=L(()=>{O3();L3=b0.name,e=b0.version,T3=b0.description});async function R($,Z,Q){let X=[];Y1((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{Y1(null),process.stderr.write=q}}var M3=()=>{};import{HDWallet as E2,Roles as N2}from"@midnight-ntwrk/wallet-sdk-hd";import{createKeystore as v2,PublicKey as w2}from"@midnight-ntwrk/wallet-sdk-unshielded-wallet";import{NetworkId as J1}from"@midnight-ntwrk/wallet-sdk-abstractions";function K0($,Z,Q=0){let X=C2[Z],q=E2.fromSeed($);if(q.type!=="seedOk")throw new Error("Invalid seed for HD wallet");let z=q.hdWallet.selectAccount(0).selectRole(N2.NightExternal).deriveKeyAt(Q);if(z.type==="keyOutOfBounds")throw new Error(`Key index ${Q} out of bounds`);let Y=v2(z.key,X);return w2.fromKeyStore(Y).address}var C2;var S0=L(()=>{C2={preprod:J1.NetworkId.PreProd,preview:J1.NetworkId.Preview,undeployed:J1.NetworkId.Undeployed}});import{execSync as b2}from"child_process";function d($){return _3.includes($)}function S2($){return{...k2[$]}}function I3(){return _3}function y3($){if($.startsWith("mn_addr_preprod1"))return"preprod";if($.startsWith("mn_addr_preview1"))return"preview";if($.startsWith("mn_addr_undeployed1"))return"undeployed";return null}function f2(){try{let $=b2('docker ps --format "{{.Image}}|{{.Ports}}"',{encoding:"utf-8",timeout:5000}),Z={};for(let Q of $.trim().split(`
|
|
9
9
|
`)){if(!Q)continue;let[X,q]=Q.split("|"),z=(Y)=>{let K=new RegExp(`0\\.0\\.0\\.0:(\\d+)->${Y}/tcp`),W=q?.match(K);return W?parseInt(W[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 D3($){let Z=S2($);if($==="undeployed"){let Q=f2();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 k2,_3;var f0=L(()=>{k2={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"}},_3=["preprod","preview","undeployed"]});import*as l from"fs";import*as K1 from"path";import{homedir as h2}from"os";function A3($){return $??K1.join(h2(),f)}function R3($){return K1.join(A3($),W3)}function p2($){let Z=A3($);if(!l.existsSync(Z))l.mkdirSync(Z,{recursive:!0,mode:r})}function p0($){let Z=R3($);if(!l.existsSync(Z))return{...h0};let Q;try{Q=l.readFileSync(Z,"utf-8")}catch{return{...h0}}let X;try{X=JSON.parse(Q)}catch{return{...h0}}return{network:X.network&&d(X.network)?X.network:h0.network}}function u2($,Z){p2(Z);let Q=R3(Z);l.writeFileSync(Q,JSON.stringify($,null,2)+`
|
|
10
10
|
`,{mode:N0})}function x3($,Z){let Q=p0(Z);if($==="network")return Q.network;throw new Error(`Unknown config key: "${$}"
|
|
11
11
|
Valid keys: ${G1.join(", ")}`)}function E3($,Z,Q){let X=p0(Q);if($==="network"){if(!d(Z))throw new Error(`Invalid network: "${Z}"
|
|
@@ -382,21 +382,68 @@ The CLI includes an MCP (Model Context Protocol) server for native
|
|
|
382
382
|
AI agent integration. Instead of parsing CLI output, agents call
|
|
383
383
|
typed tools directly via JSON-RPC over stdio.
|
|
384
384
|
|
|
385
|
-
|
|
385
|
+
Setup — add to your MCP config:
|
|
386
386
|
|
|
387
|
+
Claude Code (.mcp.json in project root):
|
|
387
388
|
{
|
|
388
389
|
"mcpServers": {
|
|
389
390
|
"midnight-wallet": {
|
|
390
|
-
"
|
|
391
|
-
"
|
|
391
|
+
"type": "stdio",
|
|
392
|
+
"command": "midnight-wallet-mcp"
|
|
392
393
|
}
|
|
393
394
|
}
|
|
394
395
|
}
|
|
395
396
|
|
|
396
|
-
Or
|
|
397
|
+
Or via CLI: claude mcp add --transport stdio midnight-wallet -- midnight-wallet-mcp
|
|
397
398
|
|
|
398
|
-
|
|
399
|
-
|
|
399
|
+
Cursor (.cursor/mcp.json):
|
|
400
|
+
{
|
|
401
|
+
"mcpServers": {
|
|
402
|
+
"midnight-wallet": {
|
|
403
|
+
"command": "midnight-wallet-mcp"
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
If not installed globally, use "command": "npx" with
|
|
409
|
+
"args": ["-y", "midnight-wallet-cli@latest", "--mcp"] instead.
|
|
410
|
+
|
|
411
|
+
AVAILABLE MCP TOOLS (17)
|
|
412
|
+
────────────────────────
|
|
413
|
+
|
|
414
|
+
Tool Name Description Required Params
|
|
415
|
+
midnight_generate Generate or restore a wallet —
|
|
416
|
+
midnight_info Display wallet metadata —
|
|
417
|
+
midnight_balance Check unshielded balance —
|
|
418
|
+
midnight_address Derive address from seed seed
|
|
419
|
+
midnight_genesis_address Genesis wallet address —
|
|
420
|
+
midnight_airdrop Fund wallet from genesis (undeployed only) amount
|
|
421
|
+
midnight_transfer Send NIGHT tokens to, amount
|
|
422
|
+
midnight_dust_register Register UTXOs for dust generation —
|
|
423
|
+
midnight_dust_status Check dust balance and registration —
|
|
424
|
+
midnight_config_get Read a config value key
|
|
425
|
+
midnight_config_set Write a config value key, value
|
|
426
|
+
midnight_localnet_up Start local network (Docker) —
|
|
427
|
+
midnight_localnet_stop Stop local network (preserves state) —
|
|
428
|
+
midnight_localnet_down Full teardown (removes volumes) —
|
|
429
|
+
midnight_localnet_status Show service status and ports —
|
|
430
|
+
midnight_localnet_clean Remove conflicting containers —
|
|
431
|
+
|
|
432
|
+
Optional params shared by wallet tools: wallet (custom wallet path),
|
|
433
|
+
network (preprod, preview, undeployed).
|
|
434
|
+
|
|
435
|
+
All tools return JSON. Errors return: {error, code, message}.
|
|
436
|
+
|
|
437
|
+
TYPICAL AGENT WORKFLOW
|
|
438
|
+
──────────────────────
|
|
439
|
+
|
|
440
|
+
1. midnight_localnet_up → Start local network
|
|
441
|
+
2. midnight_generate → Create wallet (network: "undeployed")
|
|
442
|
+
3. midnight_airdrop → Fund wallet (amount: "1000")
|
|
443
|
+
4. midnight_dust_register → Register UTXOs for fee tokens
|
|
444
|
+
5. midnight_balance → Verify balance
|
|
445
|
+
6. midnight_transfer → Send tokens (to: "mn_addr_...", amount: "100")
|
|
446
|
+
7. midnight_dust_status → Check remaining dust for fees
|
|
400
447
|
|
|
401
448
|
EXAMPLE WORKFLOW
|
|
402
449
|
────────────────
|