Skip to main content

Account Model

TL;DRDarknyx has no server-held balance ledger. Your assets are UTXO-style notes committed on-chain as hashes. Only you, with your spending key, can determine which notes are yours and what they are worth. You reconstruct your account state client-side from the public Merkle tree plus your keys; the engine never sees the spending key that would let it do it for you.

Why there is no balance in GET /account

GET /account returns the slice of account state the engine legitimately holds: your open orders (the orders you placed that are still in the book). It does not return balances or notes. On a custodial venue the operator keeps your balance in a database and serves it on request. That only works because the operator can see what you hold, which is exactly the position privacy Darknyx is built to remove. On Darknyx your balance is the set of notes you own. A note is committed on-chain as a Poseidon hash that seals its owner, value, and token. Determining that a given note is yours and reading its amount requires your spending key, and that key never enters the enclave. So the engine cannot compute your balance for you, by construction. A balance endpoint would either be empty or would require handing the enclave the one secret the whole design keeps out of it. Instead, you reconstruct account state yourself:
This is the self-custodial design: the data needed for recovery is public, and only your keys turn it into a balance. Before sending private order intent, you still verify the enclave measurement and signer set; see Privacy & Attestation.

What you read, and from where

The SDK wraps this: from your seed it derives your keys, scans the tree, and maintains a local note store of your spendable notes, so in practice you call an SDK method, not the raw tree endpoints. See SDK → TypeScript Client.

The note lifecycle

A note moves through a small set of states, each enforced on-chain by a distinct record so a note can never be used twice:
  • Spendable. The note has an inclusion path in a recent Merkle root and no applicable consume record exists. You can back an order with it or withdraw it.
  • Venue-reserved. A resting order references the note. The enclave prevents the same commitment from backing another live or settlement-pending order in this venue, but no on-chain lock exists merely because the order is resting.
  • On-chain locked. A private match has entered settlement. A live note-use-tag-keyed lock temporarily blocks withdrawal, merge, or another settlement. At its expiry it stops blocking use even before the expired account is swept.
  • Consumed. Settlement, merge, or withdrawal has created the shared tag-keyed consumed-note entry. Its value now lives in freshly created output notes (a change note for the unfilled remainder, the traded asset, and so on), each a new spendable note you own.
Because every value-moving path checks its on-chain replay guard, double-spends are impossible regardless of what the engine does.

Recovering your notes

Because your balance is derived, not stored by the venue, custody begins with a securely generated master seed and its encrypted backup.
  • CSPRNG seed + encrypted backup. Export the versioned authenticated backup and import it on a new device. Wallet-message signatures are not a seed or spend-authority mode.
  • Keys and notes. From the seed the SDK derives your trading, spending, and viewing keys. A deposit’s public recovery nonce reconstructs its hidden inner; merge and settlement outputs are derived from consumed openings and finalized chain data.
  • Settlement outputs. Exact trade and partial-fill change notes are recoverable from the encrypted ciphertext stored on-chain at settlement. The SDK decrypts the two-amount tuple with your viewing key, derives outputs from the consumed opening, and can rebuild deposit/fill/merge chains with recoverNotesFromChain. See Fills Channel.
The upshot: protect the encrypted seed backup. The engine never becomes your custodian; the seed backup + finalized chain are the durable recovery material for funds and note openings.

One seed, separate roles

The 64-byte CSPRNG master seed is the recovery root for the Darknyx keys and note openings held by your client:
The Solana wallet that signs deposits and withdrawals is separate and is not derived from this seed. Shielded ownership is derived directly from the spending key, so the encrypted seed backup covers that identity without any additional owner secret. If you run the reference market-maker daemon, also back up its adjacent *.order-sequence file. Orders that never settle do not appear on-chain, so their deterministic order-ID/trading-key indices cannot be reconstructed from chain history. The daemon advances and fsyncs this authenticated high-water file before signing; it refuses a persistent deployment without one rather than risk reusing an old key. During seed-backup recovery, pass the latest recorded next index to darknyx-keystore-init --sequence-start.

Trading keys vs. spending keys

Two different keys, two different jobs. Keep them distinct. The enclave can verify who placed an order (trading key) without ever being able to determine what you hold (spending key). That split is what lets matching be authenticated while balances stay private.

Account settings

GET / PUT /account/settings holds a small set of per-account preferences, persisted with your account. A PUT replaces them wholesale, so send the full object.