diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/app.js | 11 | ||||
| -rw-r--r-- | src/wallet.js | 28 |
2 files changed, 25 insertions, 14 deletions
@@ -521,6 +521,17 @@ function settingsTab() { { class: 'card col' }, h('h3', {}, 'Offline transfer'), snapshotActions() + ), + h( + 'div', + { class: 'card col' }, + h('h3', {}, 'Rescan'), + h('p', { class: 'small muted', style: 'margin:0' }, + 'Your current address updates automatically. Rescan only if a payment was sent to an old (reused) address and isn’t showing.'), + wallet.offline + ? null + : h('button', { disabled: wallet.scanning, onClick: () => wallet.scan() }, + wallet.scanning ? 'Scanning…' : 'Rescan wallet') ) ); } diff --git a/src/wallet.js b/src/wallet.js index b3c6a25..440f8dc 100644 --- a/src/wallet.js +++ b/src/wallet.js @@ -229,21 +229,22 @@ export class Wallet { return arr.find((a) => a.index === index); } - // Light poll: only re-query the addresses that can actually change — ones - // holding coins (could be spent) and the next fresh receive/change address - // (could receive). Stable historical addresses stay cached and aren't - // re-fetched. If anything moved, fall back to a full scan to reconcile. + // Light poll: only check the fresh frontier — the next receive and change + // address — for new activity. Already-scanned addresses are never re-polled; + // changes to them (spends) arrive over the WebSocket while connected, and a + // manual rescan covers anything missed (e.g. address reuse). If the frontier + // moved, escalate to a full scan once to reconcile. async refreshLive() { if (this.offline || this._refreshing || this._polling) return; this._polling = true; try { - const targets = new Map(); - for (const u of this.utxos) targets.set(`${u.chain}/${u.index}`, { chain: u.chain, index: u.index }); - targets.set(`0/${this.nextReceiveIndex}`, { chain: 0, index: this.nextReceiveIndex }); - targets.set(`1/${this.nextChangeIndex}`, { chain: 1, index: this.nextChangeIndex }); + const targets = [ + { chain: 0, index: this.nextReceiveIndex }, + { chain: 1, index: this.nextChangeIndex }, + ]; let changed = false; - for (const { chain, index } of targets.values()) { + for (const { chain, index } of targets) { const { address } = this.derive(chain, index); const info = await this.api.addressInfo(address); const cs = info.chain_stats || {}; @@ -497,11 +498,10 @@ export class Wallet { startRealtime() { if (this.offline) return; this.stopRealtime(); - // Safety-net polling (the WebSocket gives instant updates, but its pushes - // can be missed): a light poll of just the live addresses every 15s, plus - // an occasional full scan to catch anything the frontier check can't. - this._pollTimer = setInterval(() => this.refreshLive(), 15000); - this._deepTimer = setInterval(() => this.scan({ silent: true }), 300000); + // Safety-net poll: only the fresh frontier (next receive/change address), + // in case the WebSocket misses a deposit. Already-scanned addresses are + // never re-polled. No periodic full scan — use the manual Rescan for that. + this._pollTimer = setInterval(() => this.refreshLive(), 20000); if (typeof WebSocket === 'undefined') return; this._wsWant = true; |
