--- description: >- Local, non-custodial multi-chain crypto wallet the agent can read balances from and send transfers with — keys stay in-core and never cross the wire. icon: wallet --- # Wallet A deliberately **basic**, **non-custodial** multi-chain crypto wallet owned by the Rust core. It manages one account per supported chain derived from a single recovery phrase, reads balances, and runs a strict **prepare → confirm → execute** flow for native sends and a small set of token transfers. It is intentionally minimal: key/account management plus the primitive on-chain operations. Higher-level DeFi (swaps, bridges, generic contract/dapp calls) lives in a separate `web3` module and is **not** part of the wallet's agent or RPC surface. The most important property to understand: **signing and broadcast happen entirely in-core from the decrypted recovery phrase. No private keys ever leave the device or cross the network.** This is your money — the wallet is conservative by design. *** ## Supported chains and token standards Setup derives **exactly one account per chain**. EVM is a single account reused across six networks. Only the standards listed below are supported for transfers — anything else (swaps, arbitrary contract calls) is out of scope for the wallet. | Chain | Networks | Native | Token standard | Notes | | --- | --- | --- | --- | --- | | EVM | Ethereum, Base, Arbitrum, Optimism, Polygon, BNB Chain | ETH / BNB / etc. | ERC-20 (BEP-20 on BNB Chain) | One `Evm` account across all six; network selected per request, defaults to Ethereum mainnet. EIP-1559 / typed-tx signing. | | Bitcoin | Mainnet | BTC | — | P2WPKH (native SegWit). **Rejects token transfers.** Esplora REST for balance/broadcast. | | Solana | Mainnet / devnet (per RPC) | SOL | SPL | ed25519 signing; native + SPL token transfers. | | Tron | Mainnet | TRX | TRC-20 | TronGrid REST for native + TRC-20 transfers. | Built-in asset catalogs include the native asset plus common stablecoins per chain (e.g. USDC/USDT as ERC-20/BEP-20, USDC as SPL on Solana, USDT as TRC-20 on Tron). *** ## Onboarding and the recovery phrase Setup is a single, all-or-nothing operation: it persists a consent flag, the mnemonic word count, the setup source, exactly one derived account per supported chain, and the encrypted recovery phrase. Valid BIP-39 mnemonic word counts are **12, 15, 18, 21, or 24**. The recovery phrase is the only secret. The wallet stores the per-chain account **addresses** (safe to surface) separately from the secret material, and only the encrypted phrase can reconstruct private keys. *** ## Key custody and security The wallet is **non-custodial and local** — there is no server-side key escrow. - **The recovery phrase is always encrypted at rest.** It is encrypted via the core `encryption` domain before being persisted anywhere. - **Preferred home: the OS keychain.** The encrypted phrase lives in the operating system keychain under the key `wallet.mnemonic`, scoped by a workspace-derived user id. Access is gated by the keyring consent policy. - **Fallback: workspace JSON.** When the keychain is unavailable (e.g. headless), the encrypted phrase falls back to `{workspace_dir}/state/wallet-state.json`. On load, any JSON-resident secret is transparently **migrated into the keychain** when one becomes available, and stripped from the JSON. - **Atomic, guarded writes.** `wallet-state.json` is written atomically (temp file + fsync + persist) under a process-wide lock. Corrupt or invalid state files are quarantined rather than trusted. - **Decrypt only at signing time.** Chain signers decrypt the phrase in-core only when deriving a key to sign a confirmed transaction. Plaintext keys are never persisted and never serialized over the wire. See [OS keyring & secret storage](os-keyring-and-secret-storage.md) for how secrets are stored across platforms, and [Privacy & security](privacy-and-security.md) for the broader model. *** ## Reading balances and chain info Read-only surfaces require no confirmation: - **Status** — onboarding state plus the safe per-chain account addresses. - **Balances** — native-asset balances per account. Note: only **EVM balances read live** today (Ethereum mainnet); BTC, Solana, and Tron call their providers but fall back to a zero balance with a "provider missing" status on error. - **Network defaults / supported assets** — per-chain RPC and explorer URLs, capability flags, and the built-in asset catalog. - **Chain status** — per-chain readiness and the active RPC URL. RPC endpoints are overridable per chain/network via `OPENHUMAN_WALLET_RPC_*` environment variables. URLs are redacted to scheme + host in logs. *** ## Sending transfers: prepare → confirm → execute Every write is a two-step, intentional flow — the wallet never sends in one shot. 1. **Prepare** (`prepare_transfer`) — validates the amount, destination address, and (for tokens) calldata, estimates fees, and returns a **prepared quote** with a `quoteId`. Quotes are held in an in-memory store with a **5-minute TTL**, capped at 64, and are **not** persisted across restarts. 2. **Confirm + execute** (`execute_prepared`) — requires `confirmed: true` and a valid `quoteId`. The quote is consumed atomically before broadcast so concurrent confirmations can't double-submit; on failure it's restored with a refreshed TTL so it stays retryable. **Quote-owner binding.** Each quote is bound to the chat thread that prepared it. A quote can only be executed by the same owner that prepared it; a `quoteId` leaked into a shared channel returns an indistinguishable "not found" error rather than letting another session hijack it. Transfers are limited to **native sends and the token standards in the table above**. Bitcoin rejects token transfers. Swaps, bridges, and generic contract calls are not available here. *** ## Transaction status tracking After broadcast, three read-only inspectors let the agent follow a transaction by hash: - **`tx_status`** — lifecycle state: pending / confirmed / failed / not found. - **`tx_receipt`** — receipt details: success, fee, block. - **`lookup_tx`** — the raw transaction payload. *** ## Agent tools and approval safety The agent reaches the wallet through six tools: | Tool | Purpose | | --- | --- | | `wallet_status` | Onboarding status + account addresses. | | `wallet_chain_status` | Per-chain readiness + active RPC. | | `wallet_prepare_transfer` | Build a validated, fee-estimated quote. | | `wallet_tx_status` | Transaction lifecycle state by hash. | | `wallet_tx_receipt` | Transaction receipt by hash. | | `wallet_lookup_tx` | Raw transaction lookup by hash. | Notice there is **no agent tool that executes a transfer.** The agent can prepare a quote, but actually moving funds (`execute_prepared`) goes through the RPC surface, where it must be explicitly confirmed and pass the owner-binding check. Combined with the prepare-then-confirm flow and the per-thread quote binding, this keeps the agent from silently spending funds. Because these are financial actions, they should be surfaced through the [approval gate](approval-gate.md) so a human confirms before money moves. Treat every transfer as a high-stakes action. *** ## See also - [Approval gate](approval-gate.md) - [Privacy & security](privacy-and-security.md) - [OS keyring & secret storage](os-keyring-and-secret-storage.md)