walletIdentityProvider top-level property

Provider<Object?> walletIdentityProvider
final

The wallet IDENTITY the money surfaces key their last-known values on (#381 (c) — the converged HIGH). Riverpod retains an async provider's previous value through a rebuild (copyWithPrevious), which is exactly right for a transient re-read or the rescan's same-wallet session swap — and exactly WRONG across a wallet identity change, where it painted the DELETED wallet's balance, as-of stamp, Send gate, and parked/in-flight amounts onto the NEXT wallet's first frames (persistently under a busy first read), and on a duress/decoy multi-identity host flashed the OWNER's balance on the DECOY's surface — the same leak class the settings store got its identity fence for (A4/#348). The four money read providers below drop their retained value whenever THIS value changes.

Derivation:

  • no session ⇒ null — a change to/from null is an identity edge (the #380 (c) wallet-gone set closes the gate, so a delete → create/restore always crosses null even if intermediate states coalesce).
  • the package gate owns the session (an OnboardingActive whose session IS this session) ⇒ the state's OnboardingActive.identityEpoch — the controller keeps it stable across a rescan's session swap (same wallet, new handle ⇒ retention survives; NO blank frame mid-rescan) and bumps it for every genuinely new wallet life.
  • a SESSION-ONLY host (walletSessionProvider overridden; the package gate not Active) ⇒ the session OBJECT itself. Every session flip is then an identity change — exactly right for the duress/decoy host, and conservatively right for a host that swaps handles over the same wallet (it gets an honest cold reload instead of retention; a host wanting same-wallet retention integrates via the package gate).

Implementation

final walletIdentityProvider = Provider<Object?>((ref) {
  final session = ref.watch(walletSessionProvider);
  if (session == null) return null;
  final onboarding = ref.watch(onboardingControllerProvider);
  if (onboarding is OnboardingActive &&
      identical(onboarding.session, session)) {
    return onboarding.identityEpoch;
  }
  return session;
});