Seedelf-Wallet

Chunk 5 plan: vault, onboarding and lock

Done on 2026-09-23. What was built, and where it differs from this plan, is in the roadmap handoff note.

Branch: web-wallet/vault-lock, created from seedelf-web-wallet at b3e9383 (after PR #248). It ends with a PR back into seedelf-web-wallet.

Start here (new session)

  1. Check out the branch: git checkout web-wallet/vault-lock && git pull. If seedelf-web-wallet has moved since, merge it in.
  2. Read this plan, then:
  3. The tooling is already installed on the dev machine:
    • Rust 1.98 with wasm32-unknown-unknown
    • clang and llvm-ar-18
    • wasm-bindgen-cli 0.2.128
    • Node 24
    • Playwright’s Chromium (build 1243)

    Build and test commands are in extension/README.md.

  4. Confirm the decisions with the user before building the parts they affect.

Goal

When the chunk is done, a user can:

The chunk-4 Wallet core check screen is removed. Balances come in chunk 6.

Decisions to confirm first

Decision Suggestion Notes
Auto-lock default 15 minutes Lace defaults to “never”. A settings screen can come later.
Password rule At least 12 characters, no composition rules, with a strength hint The CLI requires 14 characters with character classes.
QR code for the receive address Later (chunk 6 or 11) Copy is enough for now.

Work items

1. Rust / WASM additions

In seedelf-crypto::derivation, exposed through seedelf-wasm. The frozen v1 derivation is not touched.

2. Vault (SecretBox SBV1): extension/src/background/vault/

3. Wallet state and lock (service worker)

States: no-wallet → unlocked (after create or restore) ⇄ locked.

Unlock:

  1. Open the vault.
  2. Turn the entropy into a phrase (WASM).
  3. Derive SeedelfKey and CardanoAccount (account 0), and keep them in worker memory.
  4. Copy the entropy into chrome.storage.session, so a restarted worker can re-derive the keys without the password. See architecture.md, Staying unlocked across restarts.

Worker start-up:

Lock: free() the WASM objects, clear chrome.storage.session, and zero the buffers.

Auto-lock:

Unlock back-off:

Lace reference: packages/contract/app-lock/src/store/{state-machine,side-effects}.ts.

Manifest: add "permissions": ["storage", "alarms"], and update tests/manifest.test.ts.

Create flow: the worker generates the phrase and returns it for display. It writes the vault only after the user confirms the phrase.

4. RPC: extension/src/shared/rpc.ts

Replace preview with:

Request Payload Result
status none { state, network, networks, version }
generate-phrase none { phrase }
create-wallet { phrase, password } writes the vault and unlocks
restore-wallet { phrase, password } writes the vault and unlocks
unlock { password } OK, or { retryAfterMs }
lock, activity none none
account none { receiveAddress, stakeAddress, seedelfPublicValue }, only when unlocked
wordlist none the BIP39 list. The UI doesn’t load WASM, so it fetches the list once and caches it.
reset-wallet none deletes the vault. The UI requires a typed confirmation first.

5. UI screens: extension/src/ui/

6. Tests

Vitest:

Playwright:

CI already runs Vitest and Playwright.

7. Docs to update at the end

Out of scope