genesis wallet
Use genesis wallet to manage a local encrypted wallet and expose a stable
machine-readable interface for agents.
Supported chains:
btc: local BIP39/BIP84-derived Bitcoin address, Esplora balance/UTXO/broadcastevm: local BIP39-derived EVM addresses through EVM JSON-RPC URLs. Ethereum, Base, and Monad are enabled by default with public RPC endpoints.sol: local BIP39/SLIP-0010-derived Solana address through@solana/web3.jstrx: local BIP39-derived TRON address through TronWebxmr: read and transfer throughmonero-wallet-rpc; Genesis does not sign Monero locally
Security model:
- The encrypted keystore is stored under the Genesis credentials directory with owner-only file permissions.
- Public address metadata is readable while the keystore is locked.
- One BIP39 secret recovery phrase derives every local keystore chain account
(
btc,evm,sol, andtrx) through that chain's configured derivation path. EVM accounts share the same derived address across configured EVM networks. - Existing mnemonics, private keys, passphrases, and raw secret material are not returned by JSON output, Gateway RPC, or the Control UI.
- EVM message, digest, and raw transaction signing are CLI-only and return signatures or signed transaction bytes, never private keys.
- The Control UI can create a new recovery phrase or import/replace one through
the admin-scoped
wallet.recoveryPhrase.setmethod. A newly generated phrase is returned once so it can be backed up; imported or existing phrases are not echoed back. - Send and broadcast flows stay in the CLI.
Create or import
Create a new wallet:
printf '%s\n' "$GENESIS_WALLET_PASSPHRASE" | genesis wallet init --passphrase-stdin
Import a mnemonic:
export GENESIS_WALLET_PASSPHRASE='use-a-long-local-passphrase'
printf '%s\n' "$MNEMONIC" | genesis wallet import --mnemonic-stdin
Notes:
initgenerates a new mnemonic and encrypts it locally.--show-mnemonicprints a generated mnemonic once in human-readable output and cannot be combined with--json.import --mnemonic-stdinreads the mnemonic from stdin and reads the passphrase fromGENESIS_WALLET_PASSPHRASE.--overwritereplaces an existing keystore.
Addresses and balances
Public addresses:
genesis wallet
genesis wallet list
genesis wallet address --chain evm
genesis wallet address --json
Native balances:
genesis wallet balance --chain btc
genesis wallet balance --chain evm --account evm:base --json
Configured EVM tokens and NFT collections:
genesis wallet tokens --account evm:ethereum --json
genesis wallet nfts --account evm:base --json
Token and NFT commands read the contracts configured under
wallet.networks.evm.chains.<chain>.tokens and
wallet.networks.evm.chains.<chain>.nfts. ERC-20 token balances use
balanceOf; token metadata comes from config or from symbol, name, and
decimals contract calls. ERC-721 collections can show balanceOf and can
check configured tokenIds through ownerOf/tokenURI. ERC-1155 collections
use configured tokenIds and balanceOf(address, tokenId).
Agents should prefer --json and treat the response as the stable automation
surface.
Quote and send
Quote a native asset transfer:
genesis wallet quote --chain sol --to <address> --amount 0.1
genesis wallet quote --chain sol --to <address> --amount 0.1 --json
Broadcasting is intentionally harder. A send must pass all configured and per-invocation guards:
wallet.spending.enabled: true--yes- wallet passphrase from
GENESIS_WALLET_PASSPHRASEor--passphrase-stdin GENESIS_WALLET_ALLOW_SPEND=1unlesswallet.spending.requireAllowEnvis disabledwallet.spending.maxNativeAmount, when configured
Example:
GENESIS_WALLET_ALLOW_SPEND=1 \
GENESIS_WALLET_PASSPHRASE='use-a-long-local-passphrase' \
genesis wallet send --chain trx --to <address> --amount 1 --yes
Signing and raw transactions
The wallet can sign EVM payloads with a configured EVM account:
GENESIS_WALLET_PASSPHRASE='use-a-long-local-passphrase' \
genesis wallet sign-message --chain evm --account evm:base --message 'hello' --yes --json
GENESIS_WALLET_PASSPHRASE='use-a-long-local-passphrase' \
genesis wallet sign-digest --chain evm --digest 0x0000000000000000000000000000000000000000000000000000000000000001 --yes --json
sign-message uses the EVM personal-sign/EIP-191 message prefix. Use
--message-hex to sign exact message bytes. sign-digest signs the exact
32-byte digest and does not add a message prefix.
Raw transaction signing and broadcast use the same spending gates as send
because they can move funds or invoke contracts:
GENESIS_WALLET_ALLOW_SPEND=1 \
GENESIS_WALLET_PASSPHRASE='use-a-long-local-passphrase' \
genesis wallet sign-raw-transaction \
--chain evm \
--account evm:base \
--tx-json '{"to":"0x0000000000000000000000000000000000000001","nonce":0,"gasLimit":"21000","gasPrice":"1","value":"1"}' \
--yes \
--json
GENESIS_WALLET_ALLOW_SPEND=1 \
GENESIS_WALLET_PASSPHRASE='use-a-long-local-passphrase' \
genesis wallet broadcast-raw \
--chain evm \
--account evm:base \
--raw-transaction 0x... \
--yes \
--json
sign-raw-transaction accepts unsigned EVM transaction request fields such as
to, from, nonce, gasLimit or gas, gasPrice, maxFeePerGas,
maxPriorityFeePerGas, value, data, chainId, type, and accessList.
If chainId is omitted, Genesis fills the selected EVM network's chain id.
If chainId is present, it must match the selected account's network.
When transaction.value is present, wallet.spending.maxNativeAmount is
checked against that native asset value. Genesis does not decode arbitrary
contract calldata for token-level spend limits.
Configuration
Minimal example:
{
wallet: {
enabled: true,
networks: {
btc: { network: "mainnet" },
evm: {
// Optional. Omit `rpcUrl` to use the built-in public RPC defaults for
// ethereum, base, and monad. Override or disable individual EVM chains
// under `chains`.
chains: {
ethereum: {
rpcUrl: { source: "env", provider: "default", id: "ETH_RPC_URL" },
tokens: {
usdc: {
address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
symbol: "USDC",
name: "USD Coin",
decimals: 6,
},
},
nfts: {
badge: {
address: "0x0000000000000000000000000000000000000001",
standard: "erc721",
tokenIds: ["1"],
},
},
},
base: {
rpcUrl: { source: "env", provider: "default", id: "BASE_RPC_URL" },
},
monad: {
rpcUrl: { source: "env", provider: "default", id: "MONAD_RPC_URL" },
},
},
},
sol: { network: "mainnet-beta" },
trx: {
fullHost: "https://api.trongrid.io",
apiKey: { source: "env", provider: "default", id: "TRONGRID_API_KEY" },
},
xmr: {
walletRpcUrl: "http://127.0.0.1:18082/json_rpc",
username: { source: "env", provider: "default", id: "MONERO_RPC_USER" },
password: { source: "env", provider: "default", id: "MONERO_RPC_PASSWORD" },
},
},
spending: {
enabled: false,
requireAllowEnv: true,
maxNativeAmount: "0.1",
},
},
}
Secret-bearing wallet fields support SecretRef inputs where the config schema marks them sensitive. See Secrets Management.
When wallet.networks.evm.rpcUrl is omitted and no legacy single-chain EVM
config is set, Genesis creates EVM accounts for evm:ethereum, evm:base, and
evm:monad. A legacy single-chain config for Ethereum, Base, or Monad also uses
that chain's public RPC when rpcUrl is omitted. These defaults are
rate-limited and are best for setup, address display, and low-volume balance
checks. For production or agentic send flows, configure private or secret-backed
endpoints under wallet.networks.evm.chains.
Gateway and Control UI
The Gateway exposes read-only wallet.summary for operator clients with
operator.read. The Control UI Wallet tab calls that method and displays public
addresses, balance refresh results, warnings, and copy buttons.
The Control UI also supports admin-scoped recovery phrase management through
wallet.recoveryPhrase.set:
mode: "generate"creates a new BIP39 phrase, encrypts it locally, derives all local chain accounts, and returns the generated phrase once.mode: "import"imports a BIP39 phrase, encrypts it locally, derives all local chain accounts, and does not return the phrase.passphraseis optional for the web/admin method; omit it to create or import a wallet without a passphrase.overwrite: trueis required when replacing an existing keystore.
No Gateway or web method returns existing seed phrases, private keys, stored passphrases, signatures, raw transaction signing, or a send/broadcast control.