diff options
| -rw-r--r-- | src/app.js | 15 | ||||
| -rw-r--r-- | src/i18n.js | 2 | ||||
| -rw-r--r-- | tools/onboard-backup-test.js | 35 |
3 files changed, 51 insertions, 1 deletions
@@ -4160,6 +4160,19 @@ function onboardScreen() { }, t('onbStart')), h('div', { class: 'onb-or' }, h('span', {}, t('onbOrSignIn'))), signinDoors(), + // Bringing a wallet from another device: its twelve words, typed in. + // This used to hide as a line under the freshly minted words behind + // "Create a new wallet", where a person signing in on their second + // phone found it only by chance (user feedback, 2026-11-02). Its own + // door, straight to the import pane. + h('button', { id: 'onb-restore', class: 'btn-block', style: 'padding:14px', onClick: () => { + clearSeedDrafts(); + ui.unlockTab = 'import'; + ui.unlockError = ''; + ui.onbError = ''; + o.step = 'seed'; + render(); + } }, t('onbRestoreDoor')), // The move from the original coinos.io used to wait behind the // Spending offer, where nobody looking for it found it. Its own door // on the front page: it stashes the intent the /migrate link stashes @@ -4234,7 +4247,7 @@ function onboardScreen() { // means seeing (or bringing) your seed phrase, not a wallet minted // behind your back. Opening one ends the wizard into the wallet + tour. return page([ - title(t('onbSeedTitle')), + title(t(ui.unlockTab === 'import' ? 'onbRestoreTitle' : 'onbSeedTitle')), unlockCard(), // the entropy page brings its own Back — one is enough ui.entropyPage ? null : h('button', { class: 'linklike small', onClick: () => { ui.unlockError = ''; o.step = 'welcome'; render(); } }, t('back')), diff --git a/src/i18n.js b/src/i18n.js index b944f96..ac6066a 100644 --- a/src/i18n.js +++ b/src/i18n.js @@ -1396,6 +1396,8 @@ const STR = { backupReminder: 'Your recovery phrase is still unwritten.', backupReminderGo: 'Write it down', onbSeedTitle: 'Set up your wallet', + onbRestoreTitle: 'Restore your wallet', + onbRestoreDoor: 'Restore from twelve words', onbSigninTitle: 'Sign in', onbLegacyTitle: 'Move your coinos.io account', onbLegacyBody: 'The original coinos. We can move your balance over and point your username here. Your old account keeps working, it just stops receiving payments.', diff --git a/tools/onboard-backup-test.js b/tools/onboard-backup-test.js index ddef8d7..3cb607c 100644 --- a/tools/onboard-backup-test.js +++ b/tools/onboard-backup-test.js @@ -93,6 +93,41 @@ try { await page.close(); } + // Three: a wallet made elsewhere comes in by its twelve words, and that + // door has to be on the front page too — it used to be a line under the + // freshly minted words behind "Create a new wallet", found by chance. + console.log('\n[restoring from twelve words]'); + { + const ctx = await browser.createBrowserContext(); + const page = await ctx.newPage(); + await page.setViewport({ width: 390, height: 844 }); + await page.goto('http://localhost:5291/', { waitUntil: 'domcontentloaded' }); + await page.evaluate(() => localStorage.setItem('btc-wallet-network', 'regtest')); + await page.reload({ waitUntil: 'domcontentloaded' }); + await waitText(page, 'sign in with nostr'); + const door = await page.evaluate(() => { + const b = document.getElementById('onb-restore'); + const c = document.getElementById('onb-create'); + return b && c ? { label: b.textContent.trim(), below: b.getBoundingClientRect().top > c.getBoundingClientRect().top, visible: !!b.offsetParent } : null; + }); + check('the front page has a door for an existing wallet', !!door && door.visible && /twelve words|seed/i.test(door.label), door ? door.label : 'missing'); + check('...below the way in, with the other alternatives', !!door && door.below); + await page.evaluate(() => document.getElementById('onb-restore')?.click()); + await sleep(600); + const pane = await page.evaluate(() => ({ + title: /restore your wallet/i.test(document.body.innerText), + field: !!document.querySelector('textarea[placeholder*="seed words" i]'), + minted: document.querySelectorAll('.words .w .t').length, + })); + check('it opens straight onto the phrase field, no minted words', pane.title && pane.field && pane.minted === 0, + `${pane.title ? 'titled' : 'untitled'}, ${pane.field ? 'field' : 'no field'}, ${pane.minted} minted words`); + const phrase = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'; + await page.type('textarea[placeholder*="seed words" i]', phrase); + await click(page, 'open wallet'); + check('the typed phrase opens the wallet', await waitText(page, 'receive')); + await ctx.close(); + } + console.log('\n[signing in, then writing it down]'); { const { page, ctx, seed } = await signIn(); |
