DustRestoreGateImpl
The bundled wallet UI's DustRestoreGate (roadmap #61). Contract (canonical copy on MidnightSdk.Builder.dustRestoreGate): consent resolution ONLY, never a wallet sync call. A @Singleton (not ViewModel state) so it exists before any SDK build and survives every panel lifecycle — no registration race, nothing to clobber on ViewModel teardown.
Decision ladder:
Restored prefs say OPTED OUT → mirror into DustBackupStateStore, never prompt.
This identity already declined → nothing.
No backup signal (prefs don't say enabled AND the identity wasn't restored) → nothing — a brand-new wallet is never interrupted, and never even pays the Drive probe.
Silent Drive probe: grant already present (same-app reinstall / new device) → the SDK's checkpoint fetch right after this gate succeeds silently; just restore the toggle truth.
Consent missing → ONE prompt through consentRequests (the panel launches it). GRANTED commits the toggle; DECLINED is remembered per-identity; UNANSWERED (timeout, or no UI attached to show the dialog) burns nothing and takes the genesis path, same as today.
Constructors
Properties
Collected by the wallet panel into the same consent launcher as the enable flow.
True while the gate is offering a restore — the panel renders the blocking "Restore your wallet data?" step. The user answers via connectRestore (launches the ONE Google consent; a dismissed system dialog returns here for retry) or skipRestore (the explicit re-sync-from-scratch choice). The naked system dialog was too easy to dismiss by accident — this step makes skipping a restore deliberate.
Functions
Route a Drive consent activity result here first; true = a pending gate prompt consumed it (the enable flow must then NOT interpret the same result — it observes the shared verdict via awaitPendingVerdict instead).
The user chose Connect & Restore — launch the one Google consent via the panel's launcher.
The user explicitly chose to re-sync from scratch. Non-durable — a later install may re-offer.