From e8edfd88b14ad07f5f97f5cb1d5d603d825a413d Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Sun, 28 Jun 2026 03:15:00 -0700 Subject: Scan silent payments from each wallet's birth, not the indexer's start MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A freshly-generated wallet can't have received SP before it existed, so set its scan watermark to the current tip on first connect (skipping the whole historical catch-up) instead of scanning from 0. Threaded a 'generated' flag through the create flow (openWallet → enterWallet → activateAccount → load spFresh); imported wallets still scan from the indexer start since they may have prior receipts. Verified on regtest: a fresh wallet skips the block-5780 receipt (watermark=tip, balance 0); the same seed imported finds it. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/wallet.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'src/wallet.js') diff --git a/src/wallet.js b/src/wallet.js index 2f9cca5..497b60b 100644 --- a/src/wallet.js +++ b/src/wallet.js @@ -158,8 +158,11 @@ export class Wallet { } // --- setup -------------------------------------------------------------- - load({ mnemonic = '', passphrase = '', xpub = '', xprv = '', netName = 'mainnet', offline = false }) { + load({ mnemonic = '', passphrase = '', xpub = '', xprv = '', netName = 'mainnet', offline = false, spFresh = false }) { this.stopRealtime(); + // A freshly-generated wallet can't have received silent payments before it + // existed, so we start its SP watermark at the current tip (no history scan). + this._spFresh = spFresh; this.mnemonic = (mnemonic || '').trim().replace(/\s+/g, ' '); this.passphrase = passphrase; this.xpub = xpub || ''; @@ -377,6 +380,14 @@ export class Wallet { const indexer = spIndexerUrl(this.netName); if (!keys || !indexer || this.offline) return { unavailable: true }; if (this._spScanBusy) return { busy: true }; + // Fresh wallet, never scanned: set the watermark to the current tip instead of + // scanning all history (nothing predates the wallet). New blocks + mempool + // arrive via the live push from here on. + if (this._spFresh && !this.lastSpScan && !rescan) { + this._spFresh = false; + try { this.lastSpScan = (await (await fetch(`${indexer}/height`)).json()).height || 0; this.saveCache(); } catch {} + return { fresh: true }; + } 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…"). -- cgit v1.2.3