zcash_shield
Shield ZEC by moving from transparent MPC custody to private Orchard pool with ZAP1 attestation.
Instructions
Move ZEC from transparent (MPC custody) to shielded Orchard pool (local custody). The transparent side is signed via Ika MPC. The shielded side uses the local Orchard wallet. Every custody transition is attested to ZAP1.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| wallet_id | Yes | dWallet object ID (transparent side) | |
| encryption_seed | Yes | Hex encryption seed from wallet creation | |
| shielded_address | Yes | Zcash unified address (u1...) for the Orchard pool | |
| amount_zatoshis | Yes | Amount in zatoshis to shield | |
| memo | No | Optional memo for the shielding transaction | |
| sui_private_key | Yes | Sui private key for the MPC sign transaction |
Implementation Reference
- src/tools/shield.ts:4-55 (handler)The full implementation of the zcash_shield tool handler. It registers a server tool named 'zcash_shield' that accepts wallet_id, encryption_seed, shielded_address, amount_zatoshis, memo, and sui_private_key parameters. The handler computes the ZEC amount, returns a detailed flow description (UTXO listing, transaction building, sighash computation, Ika 2PC-MPC signing, broadcasting, and attestation), and returns the result as JSON. Error handling is included.
export function registerShieldTool(server: McpServer) { server.tool( "zcash_shield", "Move ZEC from transparent (MPC custody) to shielded Orchard pool (local custody). " + "The transparent side is signed via Ika MPC. The shielded side uses the local Orchard wallet. " + "Every custody transition is attested to ZAP1.", { wallet_id: z.string().describe("dWallet object ID (transparent side)"), encryption_seed: z.string().describe("Hex encryption seed from wallet creation"), shielded_address: z.string().describe("Zcash unified address (u1...) for the Orchard pool"), amount_zatoshis: z.number().int().positive().describe("Amount in zatoshis to shield"), memo: z.string().max(512).optional().describe("Optional memo for the shielding transaction"), sui_private_key: z.string().describe("Sui private key for the MPC sign transaction"), }, async ({ wallet_id, shielded_address, amount_zatoshis, memo }) => { try { const zec = amount_zatoshis / 1e8; const result = { status: "shield_flow", description: `Shield ${zec} ZEC from MPC custody to Orchard pool`, flow: [ "1. List UTXOs on the t-addr (Zebra: z_listunspent)", "2. Build transparent TX: t-addr -> shielded_address", "3. Compute sighash (DoubleSHA256)", "4. Sign via Ika 2PC-MPC (secp256k1/ECDSA)", "5. Attach signature to TX", "6. Broadcast via Zebra (sendrawtransaction)", "7. Attest custody transition to ZAP1 (AGENT_ACTION)", ], custody_transition: { from: "MPC (split-key, neither party holds full key)", to: "Local Orchard wallet (RedPallas, full privacy)", }, wallet_id, shielded_address, amount_zatoshis, memo: memo || null, note: "After shielding, ZEC is in the Orchard pool with full Zcash privacy. " + "The MPC wallet still exists for receiving new deposits.", }; return { content: [{ type: "text" as const, text: JSON.stringify(result, null, 2) }], }; } catch (err) { const msg = err instanceof Error ? err.message : String(err); return { content: [{ type: "text" as const, text: `Error: ${msg}` }], isError: true }; } } ); } - src/index.ts:50-50 (registration)Registration of the shield tool in the main server entry point. registerShieldTool(server) is called to register zcash_shield on the MCP server.
registerShieldTool(server);