FakeWalletProvisioner class
A host-VM fake WalletProvisioner — no native library, no device. Drives the OnboardingController state machine deterministically: configure what is on disk, make any step succeed or throw a TYPED failure, and count calls.
- Implemented types
Constructors
-
FakeWalletProvisioner({bool exists = false, WalletSession? session, List<
String> recoveryWords = _vectorWords})
Properties
- createCount ↔ int
-
getter/setter pair
- createWatchOnlyCount ↔ int
-
getter/setter pair
- custodyDisclosureCount ↔ int
-
getter/setter pair
- deleteCount ↔ int
-
getter/setter pair
- disclosure ↔ CustodyDisclosure
-
What custodyDisclosure returns — a hardware tier by default; override to
exercise the best-effort copy (e.g.
tier: 'none'/eraseAssurance: EraseAssurance.bestEffort).getter/setter pair - exists ↔ bool
-
What walletExists reports (the on-disk fork). Mutable so a test can flip
it (e.g. create makes a wallet exist for a later resume).
getter/setter pair
- exportedUfvk ↔ String
-
The UFVK string exportUfvk returns. Override per test.
getter/setter pair
- exportUfvkCount ↔ int
-
getter/setter pair
- failCreate ↔ Object?
-
getter/setter pair
- failCreateWatchOnly ↔ Object?
-
getter/setter pair
- failCustodyDisclosure ↔ Object?
-
When set, custodyDisclosure throws this.
getter/setter pair
- failDelete ↔ Object?
-
When set, deleteWallet throws this (the wipe-fault path the controller
recovers from by re-opening — set failOpen too to exercise the
failed-AND-closed → OnboardingFailed route). A delete that throws does NOT
flip exists (the keychain-first wipe deletes nothing on a fault).
getter/setter pair
- failExportUfvk ↔ Object?
-
getter/setter pair
- failForceDelete ↔ Object?
-
When set, forceDeleteWallet throws this (the rare post-force filesystem
fault — the controller re-probes to a still-escapable failure). A force
delete that throws does NOT flip exists.
getter/setter pair
- failOpen ↔ Object?
-
getter/setter pair
- failRescan ↔ Object?
-
When set, rescanFrom throws this (the handle-closed path the controller
recovers from by re-opening — set failOpen too to exercise the
failed-AND-closed → OnboardingFailed route).
getter/setter pair
- failRestore ↔ Object?
-
getter/setter pair
- failReveal ↔ Object?
-
getter/setter pair
- failSwitch ↔ Object?
-
Thrown by switchSyncServer instead of returning — a typed
WalletApiErrordrives the controller's refused / recovered arms.getter/setter pair - failWalletExists ↔ Object?
-
When set, the matching call throws this instead of succeeding. Use a real
WalletApiErrorto exercise the failure classifier.getter/setter pair - forceDeleteCount ↔ int
-
Counts forceDeleteWallet calls (the #251 escape-hatch assertion).
getter/setter pair
- hashCode → int
-
The hash code for this object.
no setterinherited
-
holdCreate
↔ Completer<
void> ? -
When set, createGenerated blocks on this until completed (AFTER the
call is counted and BEFORE it marks the wallet existing) — so a test can
observe the transient OnboardingGenerating window on a slow seed-seal, or
drive the controller deterministically to Generating. Mirrors holdOpen.
getter/setter pair
-
holdCreateWatchOnly
↔ Completer<
void> ? -
When set, createWatchOnly blocks on this until completed (AFTER the call
is counted + recorded) — the transient creating window. Mirrors holdCreate.
getter/setter pair
-
holdDelete
↔ Completer<
void> ? -
When set, deleteWallet blocks on this until completed (AFTER the call is
counted) — so a test can hold a delete in flight and prove a concurrent
rescan is refused (the delete↔rescan mutual-exclusion).
getter/setter pair
-
holdOpen
↔ Completer<
void> ? -
When set, open blocks on this until completed — so a test can dispose
the container WHILE an open is in flight (the disposal-safety guard).
getter/setter pair
-
holdRescan
↔ Completer<
void> ? -
When set, rescanFrom blocks on this until completed (AFTER the call is
counted + recorded) — so a test can observe the transient running window.
getter/setter pair
-
holdRestore
↔ Completer<
void> ? -
When set, restore blocks on this until completed (AFTER the call is
counted and recorded, BEFORE it marks the wallet existing) — so a test can
observe the transient OnboardingRestoring window. Mirrors holdCreate.
getter/setter pair
-
holdSwitch
↔ Completer<
void> ? -
Holds switchSyncServer open until completed (in-flight latch tests).
getter/setter pair
- lastEstimatedTime ↔ DateTime?
-
What estimateBirthdayHeight last received — the size-cue threading.
getter/setter pair
- lastRescanTarget ↔ RescanTarget?
-
What rescanFrom last received — so a test can assert the sheet's
selection reached the adapter as the intended sealed arm (a picked date
/ the wallet's floor height / all-history).
getter/setter pair
- lastRestoreCreationTime ↔ DateTime?
-
getter/setter pair
-
lastRestoreWords
↔ List<
String> ? -
What restore last received — so a test can assert the lowercase + trim
contract held (the words reached the SDK normalized) and the birthday date
was threaded.
getter/setter pair
- lastSwitchChoice ↔ SyncServerChoice?
-
getter/setter pair
- lastWatchOnlyBirthdayHeight ↔ int?
-
getter/setter pair
- lastWatchOnlyUfvk ↔ String?
-
What createWatchOnly last received — so a test can assert the pasted
artifact + the picker's estimated birthday reached the adapter verbatim.
getter/setter pair
- openCount ↔ int
-
getter/setter pair
-
recoveryWords
↔ List<
String> -
The words revealMnemonic returns.
getter/setter pair
- rescanCount ↔ int
-
getter/setter pair
- rescanSession ↔ WalletSession?
-
The session rescanFrom returns on success — a DISTINCT session from
session by default, so a test can assert the active gate swapped to a new
identity (the live-sync-graph rebuild trigger). Override to pin a specific
one.
getter/setter pair
- restoreCount ↔ int
-
getter/setter pair
- revealCount ↔ int
-
getter/setter pair
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
- session ↔ WalletSession
-
The session createGenerated/open return.
getter/setter pair
- switchCount ↔ int
-
getter/setter pair
- switchSession ↔ WalletSession?
-
The session switchSyncServer returns (a FRESH instance by default, the
graph-rebuild trigger the controller's swap relies on).
getter/setter pair
- walletExistsCount ↔ int
-
getter/setter pair
Methods
-
createGenerated(
) → Future< WalletSession> -
Create a BRAND-NEW wallet: the SDK generates a fresh 24-word seed in Rust
(
OsRng) and seals it under the device keychain — the seed NEVER crosses the bridge. Returns the live WalletSession. The caller MUST drive the recovery-phrase backup (revealMnemonic) and confirm it before the wallet is presented as deposit-ready (money-safety; the OnboardingController gate). Throws (typed) if a wallet already exists here — call walletExists first; the non-clobber is the contract, never a silent overwrite.override -
createWatchOnly(
String ufvk, {required int birthdayHeight}) → Future< WalletSession> -
Create a WATCH-ONLY wallet from an exported unified full viewing key
(#397 §3.7 D2 / ADR-0538 — the consumer half of exportUfvk).
ufvkis the standarduview1…/uviewtest1…string; garbage, a truncated artifact, or a WRONG-network key throw a typedWalletErrorKind.invalidViewingKey(a well-formed cross-network key isWalletErrorKind.networkMismatch) BEFORE any store side effect — the controller renders it as a fixable input fault, exactly like a bad mnemonic word. NOT a spend-key crossing: a UFVK is viewing capability (total history visibility, no spend, no seed), so a watch-only wallet has NOTHING to back up and goes straight to Active (no backup-confirmation step).override -
custodyDisclosure(
) → Future< CustodyDisclosure> -
The PRODUCTION per-tier custody disclosure (FR-14 H1) for THIS wallet — the
honest "are my keys hardware-backed / what does delete do" answer a host
renders BEFORE deleteWallet and as an ambient custody badge. Reads ONLY
the measured vault tier (no seed, no unseal, NO key material). Bounded like
the other local steps. A
tier == "none"(headless desktop) or anEraseAssurance.bestEfforttier is HONEST best-effort — the host MUST disclose the flash-recovery residual. No tier is permanent erasure (ADR-0571).override -
deleteWallet(
) → Future< void> -
Delete this wallet (FR-14): the "delete wallet" / "reset" primitive.
CLOSES the live handle first (a wipe refuses while an instance holds the
single-writer lock —
WalletOpen), THEN deletes the keychain wrap key (so this key store can no longer open the on-disk seals or the DB ciphertext; custodyDisclosure says how strongly, ADR-0571) and removes the data directory. The seed NEVER crosses the bridge.override -
estimateBirthdayHeight(
DateTime time) → int -
Fixed blocks-per-day slope so estimate-threading tests are deterministic
(the real adapter rides the SDK's checkpoint-backed estimator).
override
-
exportUfvk(
) → Future< String> -
Export this wallet's UNIFIED FULL VIEWING KEY — the ONE sanctioned UFVK
egress (#397 §3.7 D1 / ADR-0538; the outbound sibling of revealMnemonic,
gated by the reference UI at the SAME backup-phrase bar). Returns the
standard
uview1…/uviewtest1…string. Valid only after a create/open/restore/createWatchOnly on this instance (works at every custody tier including watch-only — re-export is an identity operation).override -
forceDeleteWallet(
) → Future< void> -
FORCE-complete a deleteWallet for a wallet that cannot be opened and whose
custody key is ALREADY GONE — the #251 escape out of a non-retryable
OnboardingFailed(needsRecovery). The plain deleteWallet fails CLOSED (keystoreInconsistent) when its verify-real-sever guard finds no key to sever; this SKIPS that guard and removes the unreadable remnant's files. It MUST be called DELIBERATELY — only AFTER a plain deleteWallet reportedkeystoreInconsistent, with the device UNLOCKED (the SDKwipe_forcecontract: forcing past the guard could otherwise delete the wrong files). The seed is NOT on the device — funds are recovered from the recovery phrase the user then enters — so removing the remnant loses no money. THROWS on a genuine filesystem fault (the caller re-probes to a still-escapable failure, never a dead-end). After success this instance owns no wallet — the caller routes to the restore form.override -
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
open(
) → Future< WalletSession> -
Open the EXISTING provisioned wallet at the host data dir. Throws (typed)
for not-found / another-instance-open / network-mismatch / device-locked /
an interrupted create — open does NOT repair a remnant (it throws
provisioningIncomplete); CREATE resumes the repair from the sealed seed, which is why the boot fork routes a remnant (walletExists() == false) to create, never here.override -
rescanFrom(
RescanTarget target) → Future< WalletSession> -
Rescan the wallet from an EARLIER birthday to recover funds an over-high
restore birthday skipped (ADR-0534 — the in-app fix for the ADR-0533
"balance reads zero, sync says done" gap).
targetchooses the floor: RescanFromTime is converted to a birthday HEIGHT via the SDK's CONSERVATIVEestimateBirthday(never past the time → never skips notes) and the configured network, exactly as restore threads its birthday; RescanFromWalletBirthday passes the wallet's own floor height verbatim (the sheet's default — see the type doc); RescanAllHistory scans the FULL history (floors to Sapling activation — slower, but money-SAFE; it never silently skips older funds, NEVER ~tip). NO key material crosses — the seed stays sealed in the keychain; the only thing passed is a bare height.override -
restore(
List< String> mnemonicWords, {DateTime? approximateCreationTime}) → Future<WalletSession> -
RESTORE an existing wallet from its BIP39 recovery phrase — the ONE
sanctioned INBOUND key crossing (spec §3.3; counterpart to the outbound
revealMnemonic).
mnemonicWordsare the recovery words in order.override -
revealMnemonic(
) → Future< List< String> > -
The current wallet's BIP39 recovery words, in index order — the ONE
sanctioned OUTBOUND key crossing (spec §3.3). Valid only after a
createGenerated/open on this instance. The words ARE the whole secret:
the caller shows them ONCE on a FLAG_SECURE screen, never logs / persists /
screenshots / transmits them. Dart memory cannot be zeroized — the
documented §10 residue; the Rust side wipes its own copies when this
returns. Throws
WalletErrorKind.noMnemonicfor a raw-seed wallet (the host-supplied-seed path; its recovery is the host's own master phrase, never a wallet-local phrase).override -
switchSyncServer(
SyncServerChoice choice) → Future< WalletSession> -
Switch the active wallet onto
choiceand REMEMBER it (the picker, P3-13 —sync-server-picker.mdD3): the SDK probes the server, stops and joins the sync loop, writes the choice, and rebuilds the session over the SAME database — no rescan, no re-download; funds, history, queued sends and the sync verdict are untouched. Returns a FRESH session over the same handle, the rescanFrom shape, so the live-sync graph (keyed on session identity) rebuilds and re-subscribes; sync auto-restarts on the new server.override -
toString(
) → String -
A string representation of this object.
inherited
-
walletExists(
) → Future< bool> -
Whether a wallet is already provisioned at the host data dir (a prior
createGenerated completed). Drives the boot fork: no wallet → offer
create; a wallet → open it and gate on backup confirmation.
override
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited
Static Methods
-
estimateHeightFor(
DateTime time) → int - The fake estimator: days since 2020-01-01 × 1152 blocks (the ~75s cadence), floored at 1. Public so a test can compute its expectation through the same slope.