feat(lite): send-time unlock prompt for locked encrypted wallets

When the user confirms a send on a locked encrypted lite wallet, show an unlock
modal (passphrase -> unlockWallet) instead of letting the backend reject it with
"Wallet is locked". After unlocking, the user re-confirms the send (the form is
preserved). Balances remain viewable while locked; only spending needs unlock.

- send_tab: the Confirm-and-send button routes to App::requestLiteUnlock() when
  getWalletState().isLocked(), else sends as before.
- App::renderLiteUnlockPrompt(): centered modal, passphrase (Enter submits),
  Unlock/Cancel; the passphrase buffer is sodium-zeroed after every path.

Full-node unaffected (gated on liteWallet()/isLocked()). Builds clean, launches
clean, tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-05 18:22:15 -05:00
parent 9569b0ba43
commit d52d3d1b7f
4 changed files with 64 additions and 0 deletions

View File

@@ -588,6 +588,12 @@ void I18n::loadBuiltinEnglish()
strings_["lite_welcome_created"] = "Wallet created — back up your recovery phrase now in Settings → Backup & keys";
strings_["lite_welcome_restore_hint"] = "Restore your wallet under Settings → Lite wallet request";
strings_["lite_welcome_create_failed"] = "Could not create wallet";
// Lite send-time unlock prompt.
strings_["lite_unlock_title"] = "Unlock wallet";
strings_["lite_unlock_msg"] = "Enter your passphrase to unlock the wallet for spending.";
strings_["lite_unlock_btn"] = "Unlock";
strings_["lite_unlock_ok"] = "Wallet unlocked — you can send now";
strings_["lite_unlock_failed"] = "Unlock failed — wrong passphrase?";
// Send Tab
strings_["pay_from"] = "Pay From";