Package-level declarations
Types
Builds + posts the HEADS-UP alert (#264 inbound): a high-importance, dismissible notification that pulls the user BACK to the app when something needs them — a tracked operation awaiting their input ("your turn"), or funds arriving ("received N NIGHT").
Single last-uploaded digest, so AppStateCloudBackupCoordinator can skip a redundant upload (and the network round-trip) when the app state is unchanged. One blob per sigil → one digest (no per-address keying, unlike dust). Production backs this with SharedPreferences; tests use an in-memory holder.
AppStateCloudBackup over an injected BackupStorage + a pre-derived AES key (SeedDerivedKeyDeriver.deriveAppStateBackupKey).
Per-address last-uploaded digest, so DustCloudBackupCoordinator can skip a redundant upload (and the network round-trip) when a checkpoint is unchanged. Production backs this with SharedPreferences; tests use an in-memory map.
DustCloudBackup over an injected BackupStorage (Drive in production) + a pre-derived AES key (com.midnight.kuira.core.identity.backup.SeedDerivedKeyDeriver).
Host hook for dust-backup restore continuity (roadmap #61): awaited once before the first NO-CHECKPOINT dust sync of each SDK build — the host's chance to obtain Drive consent so the cloud-checkpoint restore succeeds instead of the sync silently replaying from genesis.
Builds + posts the DISMISSIBLE finalization notification (#264): when a tracked operation finishes (success / pending / failed), the user — who may have left the app — gets a notification they clear THEMSELVES, so they know the transaction landed. Distinct from SyncNotifier's ONGOING progress notification: its own channel, NOT ongoing, auto-cancels on tap, alerts once.
Seam for constructing a raw MidnightSdk from a WalletConfig + seed.
Process-wide owner of the single live MidnightSdk instance.
The single, DURABLE source of truth for the user's selected network.
SharedPreferences-backed AppStateBackupDigestStore. Holds the SHA-256 of the last app-state blob successfully uploaded, so AppStateCloudBackupCoordinator skips the network round-trip when nothing changed. The digest is not secret (it's a hash of already-encrypted-at-rest state), so plain prefs is fine.
SharedPreferences-backed DustBackupDigestStore. Holds the SHA-256 of the last checkpoint successfully uploaded per address, so DustCloudBackupCoordinator skips the network round-trip when nothing changed. The digest is not secret (it's a hash of an already-encrypted-at-rest checkpoint), so plain prefs is fine.
Idempotency cursor for inbound-receipt notifications (#284): the highest receipt transaction id already announced per (network, address). Two paths can see the same receipt — the live in-app observer (WalletForegroundService) and the background poll (ReceivePollWorker) — and both run across process deaths; this persisted id makes a receipt announce at most once. Whichever path announces first records the id; the other then sees it as already handled.
Doze-aware background poll for incoming UNSHIELDED NIGHT (#271). Scheduled by WalletForegroundService.attach — periodically (~15 min) and as an expedited one-shot when the app backgrounds — so a receipt is noticed even while the app is backgrounded / the device is locked, when the live observer isn't running.
The active (network, unshielded address) the background receive poll should check.
Session auto-lock (#14). The decrypted seed lives in the process-singleton MidnightSdk owned by MidnightSdkProvider; after one biometric every value-bearing call runs with zero re-auth (the SDK cache bypasses Keystore's short auth window). This locks the session by dropping that cache — MidnightSdkProvider.close — so the next value-bearing action has to re-authenticate. Because the wallet panel never auto-triggers biometric (actions are user-initiated), a lock holds until the user acts; it is never silently undone.
Builds the wallet-sync "Live Update" notification (#235) — the background counterpart to the in-app WalletSyncIndicator. An ongoing, silent, themed progress notification visible in the shade, on the lock screen, and — on Android 16 — as a promoted status-bar chip ("Kuira Syncing" / "Kuira NN%"). The phase label (dust / shielded refresh / genesis) is resolved from SyncStatus.Syncing.phase.
Snapshot of every wallet-level toggle that affects SDK construction.
Foreground service that keeps a backgrounded wallet operation (send, dust registration, contract call — or any com.midnight.kuira.sdk.MidnightSdk.runForegroundOperation) OR a wallet sync alive, and shows its progress as an Android Live-Update notification (#261-264, generalizing the #235 dust-sync service).
POST_NOTIFICATIONS helper for ALL of the wallet's foreground notifications (#261-264, generalizing the original #235 dust-sync use): the ongoing operation/sync progress, the dismissible finalization push, and the received-funds / "your turn" alerts.
Hilt bindings for sdk:wallet-runtime.
Functions
Short, phase-specific text for the status-bar chip (#235) — the capsule is tiny, so one word per phase ("Dust" / "Balances" / "Genesis" / "Finalizing"), combined with the percent at the call site.
Presentation-edge mapping from an OperationKind (domain state) to its localized DEFAULT label resource (#259) — used for the ongoing foreground-service notification when the caller didn't supply its own label (i.e. the SDK's own built-in send / dust / contract operations). A caller-provided label always wins; this is only the fallback. The exhaustive when fails to compile if a kind is added without a label, so the centralization stays honest.
Terminal-status → localized result word for the finalization notification.
Presentation-edge mapping from a SyncPhase (domain state) to its localized label resource (#259). The when is exhaustive over the enum, so adding a new phase without a label fails to compile — the centralization stays honest.
Notification large-icon — the right-side thumbnail. The Rarámuri runner is the brand mark for every wallet sync/operation (the UI revamp's "feel the branding" on the notification), so all phases share it; the differentiation between phases is the text + percent, not the icon. The left-side small icon stays the brand K (app identity).