Skip to content

Scope backup nudge to wallets created on-device#544

Merged
n13 merged 3 commits into
mainfrom
fix/backup-nudge-too-aggressive
Jun 30, 2026
Merged

Scope backup nudge to wallets created on-device#544
n13 merged 3 commits into
mainfrom
fix/backup-nudge-too-aggressive

Conversation

@n13

@n13 n13 commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Only show the recovery-phrase backup nudge for mnemonic-backed wallets created on this device (or legacy wallets of unknown origin, for backwards compatibility).
  • Never nudge keystone/hardware wallets, multisig/entrusted accounts, or imported wallets (you already have the phrase when importing).
  • Track wallet origin (created vs imported) via a new WalletOrigin, persisted per walletIndex in SettingsService.
  • Add an "I already backed up my wallet" action on the recovery-phrase caution screen (shown from the home nudge) so users who already backed up can dismiss without viewing/copying the phrase again.

Test plan

  • Create a new wallet on-device, fund it above the threshold → nudge appears on home.
  • Tap nudge → "I already backed up my wallet" → nudge disappears (no phrase reveal needed).
  • View/copy the phrase → nudge also disappears (existing behavior).
  • Import a wallet → no nudge.
  • Keystone (hardware) wallet active → no nudge.
  • Multisig/entrusted account active → no nudge.
  • Legacy wallet (no stored origin) still nudges.

n13 added 2 commits June 30, 2026 16:03
Only show the recovery-phrase backup nudge for mnemonic-backed wallets
created on this device (or legacy wallets of unknown origin). Track wallet
origin (created vs imported) and never nudge keystone/hardware wallets,
multisig/entrusted accounts, or imported wallets.

Add an "I already backed up my wallet" action on the caution screen so users
who already have their phrase can dismiss the nudge without viewing/copying.

@n13 n13 left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: Scope backup nudge to wallets created on-device (#544)

Summary of changes

The PR scopes the home backup/recovery-phrase nudge to only on-device created (or legacy unknown-origin) mnemonic wallets. It introduces WalletOrigin tracking, sets it on create/import paths, updates the backupReminderWalletIndexProvider with the necessary guards, and adds an "I already backed up my wallet" secondary action (only surfaced from the home nudge) to dismiss without forcing phrase reveal.

What looks good

  • Correct scoping logic: RegularAccount + accountType == local + origin != imported + !viewed + balance threshold. Hardware, multisig, entrusted, and imported wallets are correctly excluded.
  • Legacy compatibility: getWalletOrigin returning null (unknown) still allows the nudge, matching the stated intent.
  • UX improvement: The new "I already backed up" path from the banner is a nice touch and only wired when showAlreadyBackedUp: true.
  • Settings storage: Origin is stored per walletIndex (same granularity as viewed/mnemonic), using the existing prefs pattern.
  • No linter/analyze issues on changed files; the "Analyze" CI check is green.
  • Translations added for both en and id (plus generated localizations).

Minor issues / suggestions (non-blocking)

  1. Test coverage gap
    wallet_creation_service_test.dart verifies mnemonic + account + referral, but does not assert the new setWalletOrigin(WalletOrigin.created) call (in the !hasRoot branch) or verifyNever in the has-root branch.
    The import path that now calls setWalletOrigin(imported) also lacks a corresponding assertion/test. Recommend adding:

    verify(settings.setWalletOrigin(0, WalletOrigin.created)).called(1);

    (and the negative case).

  2. Slight duplication in wallet bootstrap paths (DRY)
    Root account creation + mnemonic persist lives in WalletCreationService (used by welcome) and is duplicated inline in import_wallet_screen.dart (setMnemonic + addAccount + discover). Origin is now set in both.
    Not introduced by this PR, but a good future refactor would be to add an importWallet(...) helper in the service so both creation and import go through a single place for side effects like origin.

  3. Cleanup on wallet removal (hygiene)
    settings_service.removeWallet deletes the mnemonic but does not remove the wallet_origin_$n or recovery_phrase_viewed_$n keys. Since nextWalletIndex can reuse freed indices, a subsequent create/import on a reused index will overwrite, so no correctness bug today. Still, for cleanliness consider:

    _prefs.remove(_walletOriginKey(walletIndex));
    _prefs.remove(_recoveryPhraseViewedKey(walletIndex));

    (out of scope for this change).

  4. Minor inconsistency
    Import explicitly invalidates walletOriginProvider after setting; the welcome/create path does not. Because the provider is a plain derived Provider that reads prefs on access, it is not required for correctness, but adding the invalidate in welcome_screen.dart would be consistent.

  5. Debug flag interaction
    debugAlwaysShowBackupNudge is evaluated after the Regular+local type checks (good), so it won't force the nudge on hardware/imported in debug either.

Nitpicks

  • The provider now has a multi-line doc comment explaining the rules. If the project prefers very minimal comments, the doc could be trimmed, but the explanation is helpful for maintainers.
  • No behavior changes to multisig/entrusted/hardware flows or serialization.

Verdict

Approve

The change is focused, safe, and solves the stated problem without side effects on other account types. Ready to merge (test coverage improvement would be nice to have).


/// When true (the home backup nudge), offers an "I already backed up" action
/// that dismisses the nudge without revealing the phrase.
final bool showAlreadyBackedUp;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this necessary? we can just not displaying it at all if user already back up, can't we?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's an option on the screen because the screen is also used from settings. So when users open it from settings the button doesn't make sense.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh okayy

@dewabisma dewabisma left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looking good, just one thing to clarify.

@dewabisma dewabisma left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually will approve, but need clarification on the intent.

The recovery-phrase nudge stayed hidden for a freshly created wallet after a
logout/reset because recoveryPhraseViewedProvider/walletOriginProvider are
cached Provider.family instances that survived logout (clearAll wipes prefs
from disk but not the Riverpod cache).

- Invalidate both providers on logout so a reused wallet index reads fresh state
- Invalidate them in the welcome create flow for consistency with the import flow
- Clear wallet_origin_/recovery_phrase_viewed_ keys in removeWallet (hygiene)
@n13 n13 merged commit 11cc888 into main Jun 30, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants