aboutsummaryrefslogtreecommitdiffstats
path: root/src/features
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-07-05 23:16:30 -0700
committerAdam Soltys <[email protected]>2026-07-05 23:16:30 -0700
commit81a55be4ea07d4dee4a83a3728c8ba0914744cd5 (patch)
treea0fe2ab8fd1b69aa92375459b0c6a9faf4684ef3 /src/features
parenteb89b9e3681d9eea331b6471ecc576f39a0fd5ec (diff)
downloadcoinosv3-81a55be4ea07d4dee4a83a3728c8ba0914744cd5.tar.gz
coinosv3-81a55be4ea07d4dee4a83a3728c8ba0914744cd5.zip
Stop pointless SP catch-up scans
A gift-claimed wallet is a brand-new seed but the claim flow never passed generated:true, so every gift wallet ground through the indexer's full history (~336k tweaks) hunting silent payments it could not have received — the CPU burn seen with a fresh gift wallet open. Fresh claim wallets now fast-forward their scan watermark to the tip like any other generated wallet. And two tabs on the same wallet no longer duplicate a catch-up: a localStorage lease, refreshed per chunk, lets the second tab yield. Co-Authored-By: Claude Fable 5 <[email protected]>
Diffstat (limited to 'src/features')
-rw-r--r--src/features/gifts.js4
-rw-r--r--src/features/sp-wallet.js10
2 files changed, 12 insertions, 2 deletions
diff --git a/src/features/gifts.js b/src/features/gifts.js
index 0038f75..ff2ab5a 100644
--- a/src/features/gifts.js
+++ b/src/features/gifts.js
@@ -81,7 +81,7 @@ export function giftsFeature(ctx) {
// first-timer (or a wrong-network device) never has to visit Settings.
// Per-wallet networks make this safe — other wallets keep their own.
hook('arkGiftAdoptNetwork', code);
- enterWallet(newMnemonic(), '', { gift: code });
+ enterWallet(newMnemonic(), '', { gift: code, generated: true });
}
// Claim a gift into an existing wallet (no new seed). activateAccount loads it and
@@ -117,7 +117,7 @@ export function giftsFeature(ctx) {
h('span', { class: 'muted', style: 'font-size:18px;line-height:1' }, '\u203a'))
),
h('div', { class: 'small faint', style: 'text-align:center' }, t('claimOr')),
- h('button', { class: 'btn-primary btn-block', onClick: () => { ui.claimChoose = null; hook('arkGiftAdoptNetwork', code); enterWallet(newMnemonic(), '', { gift: code }); } }, t('claimNewWallet'))
+ h('button', { class: 'btn-primary btn-block', onClick: () => { ui.claimChoose = null; hook('arkGiftAdoptNetwork', code); enterWallet(newMnemonic(), '', { gift: code, generated: true }); } }, t('claimNewWallet'))
)
);
}
diff --git a/src/features/sp-wallet.js b/src/features/sp-wallet.js
index e72532c..116f2e0 100644
--- a/src/features/sp-wallet.js
+++ b/src/features/sp-wallet.js
@@ -198,6 +198,15 @@ export function installSpWallet(wallet) {
try { this.lastSpScan = (await (await fetch(`${indexer}/height`)).json()).height || 0; this.saveCache(); } catch {}
return { fresh: true };
}
+ // Two tabs on the same wallet must not both grind the catch-up: a
+ // localStorage lease (refreshed per chunk) lets the second tab yield.
+ const leaseKey = this._cacheKey() + ':spscan-lease';
+ try {
+ if (!rescan && Date.now() - (parseInt(localStorage.getItem(leaseKey), 10) || 0) < 30000) {
+ return { busy: true };
+ }
+ localStorage.setItem(leaseKey, String(Date.now()));
+ } catch {}
this._spScanBusy = true;
// Only a manual scan shows the visible "Scanning…" state; auto-scans are
// invisible (setting spScanning for them left the card stuck on "Scanning…").
@@ -237,6 +246,7 @@ export function installSpWallet(wallet) {
}
const maxH = slice[slice.length - 1].height;
if (maxH > (this.lastSpScan || 0)) { this.lastSpScan = maxH; this.saveCache(); } // checkpoint
+ try { localStorage.setItem(leaseKey, String(Date.now())); } catch {} // keep the lease
await new Promise((r) => setTimeout(r, 0)); // let the UI breathe
}
if (tip > (this.lastSpScan || 0)) this.lastSpScan = tip;