walletSnapshotReadProvider top-level property
The on-resume cold snapshot (spec §3.3) — balance, Tor, tip, balance
age, seq. A one-shot read; SyncStatusNotifier invalidates it on a
real resume so a backgrounded UI re-reads cold state before trusting
live events again. Only watched when a session exists. The identity-
scoped READER behind walletSnapshotProvider — invalidate THIS to
force a re-read; watch the view.
DELIBERATE KEEP of the container default retry (the audit; contrast
walletNoSilentRetry): a transient FFI fault here self-heals in seconds
instead of waiting for the next sync edge, and the view's last-known
retention keeps the heal cycles invisible — the surface never regresses
below its retained truth while the retry runs. The guard StateErrors
below are Errors, which the default never retries.
Implementation
final walletSnapshotReadProvider = FutureProvider.autoDispose
.family<WalletState, Object?>((ref, identity) {
// DYING-ELEMENT guard (review, converged): at an identity flip
// the OLD key's still-listened element is flushed once against the
// NEW session before the view re-keys away and it disposes — without
// this, that flush costs up to four discarded FFI reads at exactly
// the busiest moment (and leaves a theoretical fast-flip-back
// corner). A superseded key never reads.
if (ref.watch(walletIdentityProvider) != identity) {
return Future<WalletState>.error(
StateError(
'walletSnapshotReadProvider read under a superseded '
'wallet identity',
),
);
}
final session = ref.watch(walletSessionProvider);
if (session == null) {
// Defensive: the screen renders the not-provisioned state and never
// reads this when the session is null. Surfaced as an error only if a
// future caller forgets that branch.
return Future<WalletState>.error(
StateError('walletSnapshotProvider read with no wallet session'),
);
}
return session.snapshot();
});