From 31268770ce5d824eb598b51f0fa159d21239ce2b Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Wed, 24 Jun 2026 15:13:19 -0700 Subject: Fix confirmed txs stuck showing "pending" Two paths left a tx's confirmed flag stale once the balance had already reconciled: - The frontier poll re-fetched an address's txs but only appended new ones (`if (!txs.some(...))`), so a tx that moved from mempool to a block kept its old pending status. Now it refreshes the record in place. - On reload, scan() skipped the history re-pull when the cached balance already matched on-chain, so a stale-pending cached tx never updated. scan() now also re-pulls history whenever any tx is still pending. Verified: a cached pending tx that is confirmed on-chain flips to confirmed (and pending balance clears) after a scan. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/wallet.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/wallet.js b/src/wallet.js index 4098087..9e7bb32 100644 --- a/src/wallet.js +++ b/src/wallet.js @@ -341,7 +341,12 @@ export class Wallet { } const list = await this.api.addressTxs(a.address); for (const tx of list) { - if (!this.txs.some((t) => t.txid === tx.txid)) this.txs.push(this._txSummary(tx)); + const summary = this._txSummary(tx); + const at = this.txs.findIndex((t) => t.txid === tx.txid); + // Refresh in place so a tx that has since confirmed loses its pending + // status — not just append new ones (which left confirmations stale). + if (at >= 0) this.txs[at] = summary; + else this.txs.push(summary); } } @@ -445,7 +450,11 @@ export class Wallet { // balance/addresses actually changed. Idle polls stay /address-only. const balanceChanged = `${this.confirmed}|${this.pending}|${this.nextReceiveIndex}|${this.nextChangeIndex}` !== prevBal; - if (!silent || balanceChanged || !this.loaded) { + // Always re-pull history while any tx is still pending, so confirmations + // get reconciled even when the balance itself hasn't changed (e.g. a + // received coin that simply moved from mempool to a block). + const hasPending = this.txs.some((t) => !t.confirmed); + if (!silent || balanceChanged || !this.loaded || hasPending) { // Balance + receive address are already known from the chain_stats above. // Show them right away so the wallet looks ready, then keep loading the // heavier UTXO set and full history in the background. -- cgit v1.2.3