You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: recover stalled wallet syncs via idle watchdog and progress reorder
Two targeted changes to _refresh() in the base Wallet<T> class, plus a
supporting heartbeat hook on ElectrumXClient. Affects all wallet types
routing through the shared refresh flow (BTC, LTC, Firo, Monero, ETH,
Cardano, Solana, etc. — but NOT MimbleWimbleCoin, ETH tokens, or SOL
tokens, which override refresh()).
1. Idle watchdog on the refresh body. A Timer.periodic checks every
30s whether any refresh activity has been observed within the last
5 minutes. If not, the refresh is assumed wedged, the watchdog
throws TimeoutException, and the existing catch/finally releases
refreshMutex. Previously the mutex stayed locked forever when any
sub-operation hung, making every subsequent periodic sync bail out
at the isLocked check until the app was force-closed.
"Activity" is fed from two sources:
- _fireRefreshPercentChange (coarse checkpoints + Spark per-sector
progress during the anon-set download)
- successful electrum RPCs, via a new onRequestComplete hook on
ElectrumXClient
The electrum hook is important because updateTransactions() on a
wallet with large history does hundreds of sequential getTransaction
RPCs with no _fireRefreshPercentChange calls between 0.65 and 0.70.
Without the hook, a slow server could legitimately trigger a false
timeout on an initial restore. With the hook, the watchdog stays
fed as long as electrum is answering.
Note: the watchdog does not cancel in-flight work; it only unblocks
the outer future so the mutex can be released. The orphaned work
eventually resolves or errors on its own.
2. Fire progress updates *after* the awaited work completes rather
than before. The 0.65 and 0.70 calls previously fired immediately
after kicking off updateUTXOs/updateTransactions, making the bar
appear stuck at those values while the real work was still running.
The ~65% stall in Firo syncs was the most visible manifestation of
this; other wallets had the same cosmetic issue.
The refresh body is also extracted to a private _doRefreshWork(viewOnly)
helper to keep _refresh() focused on mutex/event/watchdog/error handling.
No behavioural change from the extraction.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0 commit comments