Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Data Models: Arktos Wallet

From cognokratos/arktos-wallet · docs/data-models.md · pinned revision 92650a034799

This document describes the data models used within the Arktos Wallet application, primarily focusing on how wallets and their associated accounts are structured and stored.

Storage Mechanism

Arktos stores data in a single local SQLite database encrypted with SQLCipher (rusqlite, bundled-sqlcipher-vendored-openssl). The schema is defined by versioned SQL migrations in migrations/ (V1 initial schema, V2 account network) and applied automatically at startup (see Architecture — Data Architecture). All tables are STRICT, foreign keys are enforced, and timestamps are UTC ISO-8601 strings generated by SQLite (e.g. 2026-10-03T21:14:02.628Z).

Tables

api_keys

Client credentials. Only the HMAC of each key is stored.

ColumnTypeConstraintsDescription
idINTEGERPRIMARY KEY
key_hashTEXTNOT NULL, UNIQUE, 64 charsHMAC-SHA256 (hex) of the API key
key_nameTEXTNOT NULL, 1–255 charsDisplay name
is_revokedINTEGER0 or 1, default 0Revoked keys cannot authenticate
created_atTEXTNOT NULL, default now

wallets

One BIP39 wallet owned by one API key.

ColumnTypeConstraintsDescription
idINTEGERPRIMARY KEY
key_idINTEGERNOT NULL, FK → api_keys.id (RESTRICT)Owner
nameTEXTNOT NULL, 1–255 charsWallet name
encrypted_passphraseTEXTNOT NULLRecovery phrase in an AES-256-GCM envelope (the only secret column)
created_atTEXTNOT NULL, default now

UNIQUE (key_id, name): wallet names are unique per owner; different owners may use the same name. Every wallet query is scoped by key_id.

accounts

Public data of a derived account. Private keys are not stored; they are re-derived from the wallet's recovery phrase when needed.

ColumnTypeConstraintsDescription
idINTEGERPRIMARY KEY
wallet_idINTEGERNOT NULL, FK → wallets.id (RESTRICT)
chain_typeTEXTBitcoin or Ethereum
networkTEXTBitcoin: mainnet/testnet/signet/regtest; Ethereum: evmAddress space the account was derived for
account_indexINTEGER0 … 2³¹−1 (non-hardened)BIP32 child index
derivation_pathTEXTNOT NULL, must equal the canonical pathBIP86 m/86'/0'/0'/0/{index} (Bitcoin mainnet), m/86'/1'/0'/0/{index} (Bitcoin test networks) or BIP44 m/44'/60'/0'/0/{index} (Ethereum)
public_keyTEXTNOT NULLCompressed SEC1 public key, 0x-hex
addressTEXTNOT NULL; Ethereum must be lowercaseBitcoin Taproot (bc1p…/tb1p…/bcrt1p…) or Ethereum (0x…, canonical lowercase; EIP-55 checksum applied in responses)
created_atTEXTNOT NULL, default now

UNIQUE (wallet_id, chain_type, network, account_index): each account is derived and stored once per network; concurrent first requests return the same row, and changing BITCOIN_NETWORK never returns an account of another network. The Ethereum chain ID is not stored (the address is chain-independent); it is taken from configuration when responding.

Relationships

api_keys 1 ── * wallets 1 ── * accounts

Deletes are restricted (no cascading); Arktos currently never deletes rows — API keys are revoked, not removed.

Encryption

Two independent layers protect sensitive data:

  • SQLCipher (DATABASE_KEY) encrypts the entire database file.
  • Field encryption (AES-256-GCM) additionally encrypts the Passphrase (wallets.encrypted_passphrase) with the wallet-seed key derived from MASTER_KEY via HKDF-SHA256, so someone who can read the opened database still sees only ciphertext. No private keys are stored.

Values are stored as a versioned envelope {"v":1,"alg":"A256GCM","nonce":…,"ct":…}. API keys are stored only as HMAC-SHA256 hashes (api_keys.key_hash). See Architecture — Key Hierarchy & Secret Storage.

This chapter is maintained in cognokratos/arktos-wallet beside the code it teaches. The book shows docs/data-models.md at revision 92650a0347993622cbb3e5eeac2c908069c67fd6 (branch main). View source at this revision · Report a correction.

Corrections are made upstream against the current main branch and appear here when the book's pin for this source is updated.