From 92626d18830c34d223b2174e0b81ced6a24ec91f Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Fri, 26 Jun 2026 11:29:24 -0700 Subject: Persist wallets as watch-only across sessions; re-enter seed to spend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closing the browser without 'Save to device' used to wipe the wallet entirely. Now every wallet's account xpub is mirrored to a durable localStorage directory (never the seed), so it survives a session wipe as a watch-only entry — you keep seeing balance and history, and re-enter the seed to spend again. - Durable account directory: saveDirectory() mirrors {id,label,xpub} for every account; restore falls back to it as watch-only when there's no session/vault. - Instant view: a full wallet also caches under its xpub key, so the downgraded watch-only shows balance/history immediately (no rescan). Verified round-trip. - Re-enter seed to spend: the Send tab (now shown for watch-only) and Settings prompt for the recovery phrase / xprv; it must derive to this wallet's xpub (verified via accountXpubFor — wrong seed/passphrase rejected), with an option to Save to device at the same time. Upgrade is in place (id/label/cache kept). - Vault merge now dedupes by xpub so saved + non-saved wallets coexist without duplicates. Privacy note: the xpub now persists by default (someone with device access can see balance/history without the seed); 'Remove' clears it. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/i18n.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src/i18n.js') diff --git a/src/i18n.js b/src/i18n.js index e3341a7..d36f301 100644 --- a/src/i18n.js +++ b/src/i18n.js @@ -47,6 +47,18 @@ const STR = { watchOnlyAdd: 'Add watch-only', watchOnlyDesc: 'Watch any wallet from its account public key. You can receive and view balance and history, but not send.', watchOnlyNote: 'This is a watch-only wallet. You can receive and view, but you cannot send.', + loadSeedTitle: 'Load recovery phrase', + loadSeedDesc: "Enter this wallet's recovery phrase (or private key) to spend from it — it must match this wallet.", + loadSeedBtn: 'Load recovery phrase', + seedPlaceholder: 'Recovery phrase or xprv', + bip39PassphraseOpt: 'BIP39 passphrase (optional)', + alsoSaveDevice: 'Also save to this device', + enterSeedToSpend: 'Enter your recovery phrase.', + seedMismatch: "That recovery phrase doesn't match this wallet.", + seedNeedsPrivate: "That's a public key — enter the recovery phrase or private key to spend.", + seedInvalid: 'Not a valid recovery phrase or key.', + watchOnlySendTitle: 'Load your seed to send', + watchOnlySendDesc: "You're viewing this wallet without its seed, so you can't spend yet. Load your recovery phrase to send.", watchXpubLabel: 'Account xpub or zpub', labelOptional: 'Label (optional)', walletLabelN: 'Wallet {n}', @@ -85,6 +97,7 @@ const STR = { wordN: 'Word #{n}', reenterPassphrase: 'Re-enter passphrase', back: '← Back', + cancel: 'Cancel', openWallet: 'Open wallet', wordsMismatch: 'Those words don’t match your phrase. Check your backup.', passphraseMismatch: 'That passphrase doesn’t match the one you entered.', -- cgit v1.2.3