Skip to content
ENBANKDesk

Enbank docs

Sealed transfers

How a send is validated, rounded, queued, and kept on this device.

On this page

Send form

The transfer view collects four fields: destination address, asset (USDC, SOL, or eUSD), amount, and an optional note. The available balance for the selected asset is read from the vault. While the vault is sealed, that figure is not printed in the error path beyond the generic rejection.

A successful submit replaces the form with a sealed confirmation and two exits: back to the overview, or the activity list. "Send another" clears the confirmation and keeps the same destination.

Validation

The form rejects the submit before send runs when any of these fail:

  1. isAddress must accept the destination. The message asks for an EVM address starting with 0x, or a Solana-style address. Rules are on Accounts and keys.
  2. The destination must differ from desk.address.
  3. parseAmount allows digits with one optional decimal point, after stripping commas. Zero, negatives, and non-numeric text fail.
  4. Decimal places are capped at 2 for USDC and eUSD, and at 4 for SOL.
  5. The amount must be less than or equal to the current asset balance.

Ledger write

send rounds with roundAmount, which is Math.round(value * 1e8) / 1e8. It then writes three changes in one state update:

  • Subtract the rounded amount from that asset. The result is clamped at zero.
  • Prepend an activity row: kind: "send", title Send {ASSET}, status Queued, timestamp from stamp() in en-GB day-month hour:minute. The detail is the note, or To plus shortAddr.
  • Replace desk.transit with this send. A new send overwrites the previous transit object. It does not append.
activity: {
  id: crypto.randomUUID(),
  kind: "send",
  title: "Send USDC",
  detail: note || "To 0x1234…abcd",
  amount,          // rounded
  asset,
  status: "Queued",
  at: "03 Oct, 22:40"
}

The toast is "Instruction sealed on this desk." Settlement of that row is a later local action, settle(id), which flips the status to Settled and does not move balances again.

Transit

Transit is a single in-flight object, not a queue.

type Transit = {
  asset: Asset;
  destination: string; // short address, or a desk name for the seed
  eta: string;         // sends write "12 MIN"
  done: number;        // roundAmount(amount * 0.32)
  total: number;       // the send amount
};

The 0.32 progress and the 12 minute ETA are display constants. They do not advance with the clock. The seed transit is different: 2,365 of 7,800 USDC toward AUREUM DESK, also labeled 12 minutes. The first user send replaces it.

Production transfer

A production transfer would encrypt amount, asset, and recipient, then queue the transfer circuit. The callback may publish that the sender account settled a transfer. It should not publish the amount. The preview mirrors the private side of that contract by keeping the amount out of the screen until reveal, and it stops there.

Card withdrawal is a separate instruction with a card destination instead of an address. It is specified on Withdraw to a debit card. The send form does not collect card fields.