Seedelf-Wallet

Chunk 27 · The restore scan

O5: after a restore, or with the same phrase in another browser, what a private session’s one-time account (24301') still holds didn’t show, and Remove wallet and Forgot password said so (independent review M5). That warning was the promise this keeps.

Status: ✅ built 2026-10-11 on web-wallet/restore-scan, from main after #298. One PR: the plan, the build and the docs together, so this file went straight to the archive. What still holds is in the design docs: keys-and-accounts.md (The restore scan: what it asks, what it can’t find), flows.md (the restore’s note, the dApps page, Remove wallet, Forgot password, a stalled session), privacy.md and architecture.md. The privacy policy has its dated entry.

Why now: the design was settled in chunk 22 and waited on what it would tell Koios: every one-time account asked about together, from one IP address. On mainnet that question goes to our own server since 1.4.0, which logs neither, and every route the scan needs was already one of its public routes (account_addresses for 20 stake keys, credential_utxos, account_txs, tx_info with its outputs’ indexes, utxo_info, datum_info, address_utxos). No server change.

What it does

SessionService.scan(network) (sessions.ts), the session-scan request:

  1. Walks the one-time stake keys (2/i) from 0, 20 at a time (account_addresses), until a batch has none used.
  2. For the used ones the book doesn’t know: what they hold (credential_utxos); each one’s transactions (account_txs with _after_block_height: 0, one request an account); what those spent and paid (tx_info, inputs alone, whose outputs come with them).
  3. Their orders, through the swap that placed them: each output the account’s key-signed transactions paid to an order script orders.json pins, read by readDexOrder as the account’s (utxo_info, datum_info for a datum kept by hash). Then liveOrders on the record decides which are open, a Splash fill’s remnants too (since 1.5.0’s release review, off the rows just read, asking utxo_info nothing more: C15).
  4. Adds a session found (recovered: { at, own }) for each that holds something or has an order open: its funding (the oldest transaction its key didn’t sign) as out, its swaps as swap with their orders, and what its key signed as own, which its return counts as the session’s own. One holding nothing, with no order open, isn’t added.
  5. Moves the book’s next past every used index. The merge is into the book as it is once everything’s read, so a session started meanwhile keeps its index; one scan a network at a time.

It runs after a restore (in handlers.ts, behind the look for public accounts, on the network restored on) and from Find leftovers.

1.5.0’s release review changed some of this: a server behind the one that showed an account used fails the scan rather than find nothing (C14); a scan is tied to the phrase it started on (C16); a restore marks every network until a scan finishes there, its own counting as under way from the restore on (C19); and a found session’s funding keeps what the scan read at the account, so that one this device has sent nothing for ends by itself once nothing of it would come back (C02). keys-and-accounts.md has each. (1.5.0’s cross-area review: one whose record holds a swap ends only at a refresh 15 minutes or more after the first that found it so, since its order’s fill pays the account in the very transaction that spends the order, X01; and a new session’s funding no longer clears the restore’s mark, X02.)

Choices made here (the owner can overturn any)

Cost

  Requests
A phrase that never used a one-time account 1 (account_addresses)
Each further batch of 20 indices 1
The used ones the book doesn’t know 1 credential_utxos per 75, 1 account_txs each, 1 tx_info per 20 of their transactions
Where those paid an order script 1 utxo_info per 60 of those outputs (every account’s together), 1 datum_info per 60 datums kept by hash, and 1 utxo_info per account holding nothing whose swaps placed orders (liveOrders), plus, for one whose spent order was Splash’s, its remnant look. Since 1.5.0’s release review liveOrders reads which are open off the first rows, so that second utxo_info is gone (C15, C35)

A restore of a phrase with no sessions spends one request on it (the restore’s e2e test counts it).

Tests

Left for later