Tokens and scopes

Walletd uses bearer-token authentication on every request except GET /healthz. Comparison is constant-time (subtle::ConstantTimeEq).

Three scoped tokens

Walletd issues three tokens, one per scope. On first start it auto-generates them at <datadir>/token-{read,manage,spend} (mode 0600).

The authoritative scope of every method is Scope::for_method in src/auth.rs; anything not listed below as manage or spend is read. The RPC reference tags each method with its scope.

ScopeMethods
readping, validate_address, the get_* family, list_addresses, list_settlements, verify_message, get_status, get_wallet_balance, htlc_status/htlc_list/htlc_lookup_by_hashlock, simulate_*, wait_for_tx/wait_for_payment, payment_uri_*, swap_status/swap_list/swap_pool_info/swap_price_klines, lp_pool_info/lp_position/lp_deposit_status, bsc_get_address/bsc_get_balances/bsc_tx_history, contract_stats, get_attestation_edges
managegenerate_address, generate_independent_address, generate_standard_address, import_private_key, import_mnemonic, import_standard_mnemonic, bsc_create_address, bsc_import_mnemonic, bsc_import_key, abandon_transfer, htlc_forget
spendtransfer, send_raw_transaction, sign_message, htlc_lock/htlc_claim/htlc_reclaim, reveal_mnemonic/reveal_private_key/reveal_address_mnemonic/reveal_evm_private_key, export_vault/export_address/import_vault, delete_address, swap_get_quote/swap_execute/swap_refund, bsc_send_bnb/bsc_reveal_mnemonic/bsc_delete_key, lp_withdraw_self

Containment: spend ⊇ manage ⊇ read. A token at a higher scope satisfies every lower scope, so an exchange's withdrawal worker only needs the spend token — it gets manage and read for free.

Configuring

The default behaviour (auto-generate on first run) suits most setups. Override any subset from a secret manager:

exfer-walletd \
    --auth-token-read   "$(vault read -field=token secret/walletd-read)" \
    --auth-token-manage "$(vault read -field=token secret/walletd-manage)" \
    --auth-token-spend  "$(vault read -field=token secret/walletd-spend)"

Env equivalents: WALLETD_AUTH_TOKEN_READ, WALLETD_AUTH_TOKEN_MANAGE, WALLETD_AUTH_TOKEN_SPEND. Setting any of them suppresses auto-file creation for that scope.

Typical splits

ComponentToken to issue
Deposit watchertoken-read
Address provisioningtoken-manage
Withdrawal workertoken-spend
Operator dashboard / SREtoken-read

A leaked read token can survey balances and pubkeys but cannot mint addresses or spend. A leaked manage token can mint addresses but cannot spend or sign messages. A leaked spend token is "every wallet, all funds" — guard accordingly.

Bind safety

Walletd enforces at startup:

Bind addressPolicy
Loopback (127.0.0.1, ::1)Always allowed.
Private (RFC1918, ULA, link-local)Allowed; warns if no token is set.
Public (any global IP, 0.0.0.0, ::)Refused unless --tls OR --allow-public-bind.

The reason public binds need an opt-in: by default walletd doesn't terminate TLS, and a plaintext bearer token on the public wire is fatal. --tls (walletd terminates TLS itself, see Quick start → Production) solves it directly; --allow-public-bind is your assertion that an external TLS terminator sits in front. Without one, walletd fail-closes.

Next