walletSyncControllerProvider top-level property

NotifierProvider<WalletSyncController, WalletSyncDrive> walletSyncControllerProvider
final

Drives the background sync loop from (session-present ∧ app-foreground).

LIFETIME: a plain (non-autoDispose) NotifierProvider. It is built lazily the first time something watches it: the wallet surface when it first renders Active (_WalletActive watches it), or — FR-51 — a HOST that listens to walletSyncDriveProvider at its root so sync runs whenever a session is live and the app is foreground, wallet screen or not. Built before a session exists it is inactive and does nothing; the session arriving rebuilds it and starts the loop. From then on it persists for the life of the root ProviderContainer (the same mechanism that keeps onboardingControllerProvider/walletSessionProvider/syncStatusProvider alive across navigation), so sync keeps running while the user is on another screen — incoming funds are still detected with the wallet screen closed — and is suspended only by actual backgrounding. It is re-built (a FRESH instance, fields reset) only when its one watched dependency, walletSessionProvider, changes (e.g. null → session on Active). The SDK itself never warms it at boot: WHEN the wallet opens (and so when sync can start) is the host's decision, since opening takes the single-writer lock. A host that opens the wallet at launch and listens to the drive gets sync from launch; one that opens lazily gets it from the first wallet use.

ORTHOGONAL to SyncStatusNotifier: that one OBSERVES the status stream (and pauses/reconnects it); this one CONTROLS the loop. They share the same lifecycle triggers but never call each other — one source of truth each. On a resume both act independently: the observer re-subscribes (replaying the CURRENT status immediately) while this controller re-issues startSync. That ordering is unsynchronized and SAFE by construction — startSync is idempotent + near-instant (spawns the loop, no network wait), the stream's current-first replay means the banner is always the real status, and this drive state is not rendered except failed. So there is no window in which the UI claims a state the core isn't in.

Implementation

final walletSyncControllerProvider =
    NotifierProvider<WalletSyncController, WalletSyncDrive>(
      WalletSyncController.new,
    );