add_contact
Add a contact to your address book by mapping a label to a blockchain address. The entry is signed with your Ledger in production mode or stored unsigned.
Instructions
Save a label → address binding to the address book. Production mode + Ledger paired: blob is signed with the user's paired Ledger key on that chain (BIP-137 for BTC, EIP-191 for EVM in v1.0; Solana / TRON support deferred to v1.5). Persisted to ~/.vaultpilot-mcp/contacts.json and verified on every read. Production mode + no Ledger paired (issue #428): writes to a process-local in-memory store and returns unsigned: true + anchorAddress: "UNSIGNED_NO_LEDGER" so first-run / accountant-share users can label addresses without entering demo mode (which intercepts broadcasts). The label is process-local — lost on restart — and resolves with a (unsigned) warning in send-flow verification blocks. Pair a Ledger and re-add to upgrade to a signed entry. Demo mode (VAULTPILOT_DEMO=true): same in-memory store, returns unsigned: true + anchorAddress: "DEMO_ANCHOR". All four chains usable from day one (btc/evm/solana/tron). v1.0 production chains: btc + evm. solana / tron return CONTACTS_CHAIN_NOT_YET_SUPPORTED. The notes and tags fields update the unsigned metadata sidecar (joined across chains by label) so editing them doesn't require a fresh device signature. Sends like prepare_native_send({ to: "Mom" }) resolve Mom against the signed blob first, then fall through to the unsigned overlay with a warning. Adding the same label twice on the same chain replaces the address (with a fresh signature in production-signed mode). Adding a different label that maps to an already-saved address rejects with CONTACTS_DUPLICATE_ADDRESS.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| chain | Yes | Which chain's blob to add to. v1.0 ships `btc` + `evm` only. `solana` / `tron` return CONTACTS_CHAIN_NOT_YET_SUPPORTED. | |
| label | Yes | Human-readable label, used to look up the contact by name in every prepare flow. Must be unique within a chain — adding the same label twice on the same chain replaces the address. | |
| address | Yes | On-chain address. Validated against the chain's address regex at call time; format mismatches reject before any device interaction. | |
| notes | No | Free-form note attached to the LABEL (joins across chains via the metadata sidecar — same notes show up on `Mom`'s BTC and EVM rows). Unsigned: tampering with notes does not redirect funds, but the agent surfaces 'notes integrity unverified' alongside the (verified) address. | |
| tags | No | Free-form tags ('family', 'cex-deposit', etc.). Like notes — stored in the unsigned metadata sidecar. | |
| intendedChains | No | EVM-only (issue #482). Tag the contact for specific EVM chains so `preview_send` emits a `CONTACT-CHAIN MISMATCH` warning when a prepare's chain isn't in this list (defense-in-depth for the Carol-on-Arbitrum-sent-on-Ethereum class of mistake). Omit for legacy 'any EVM chain' behavior. Rejected with a clear error for btc/solana/tron contacts. |