Files
eranos/src
Alex Gleason 772a2de236 Fix HD wallet cold-scan-on-every-refresh + pace bursts
Two bugs working together caused the HD wallet to make ~60 /txs requests
on every page refresh (well over public Esplora rate limits, visible as
clusters of HTTP 429s in devtools).

**Bug 1: cache hydration race.** useHdWallet used a useEffect-driven
ref to mirror the persisted PersistedScan into livePrevRef. On the first
render, useCurrentUser/useNostrLogin hadn't resolved yet, so pubkey was
"" and useSecureLocalStorage returned the default for the unknown
"hdwallet:scan:none" key. The hydration effect ran, populated
livePrevRef with an empty stub, and the "already populated" guard
prevented it from re-hydrating once pubkey became real. Result: every
single page refresh ran a cold gap-limit scan even though localStorage
held a perfectly good cached skeleton.

Fix: drop the effect entirely. Inside queryFn, read the cache directly
via secureStorage.getItem(scanCacheKey(pubkey)). The query is gated on
`pubkey !== ''` so by the time queryFn runs, the key is real. After the
scan completes, both livePrevRef (in-memory) and the persisted copy
are updated. No effect, no race, no flicker.

**Bug 2: burst concurrency.** Even with the cache fixed, a true cold
scan (fresh install) was still firing two chains × Promise.all(5) = 10
in-flight requests at once, plus the warm path's refresh-known-used
and walk-forward-from-index ran in parallel = double again on warm
scans. mempool.space rate-limits at the burst level, so even moderate
concurrency tripped 429s.

Fixes in scan.ts:
- SCAN_BATCH_SIZE 5 -> 3.
- INTER_BATCH_DELAY_MS = 250 between consecutive batches inside one
  chain walk, with a sleep() helper that honours the abort signal.
- scanChain warm path: refreshKnownUsed then walkForwardFromIndex,
  serially (was Promise.all).
- scanAccount: receive chain then change chain, serially (was Promise.all).

Net effect on a steady-state wallet with the cache populated:
~3-6 requests per refresh (only known-used addresses + tail probe),
paced ~250ms apart, spread over ~1-2s. First-ever cold scan is
~40 requests but paced into 14 batches over ~3.5s, well under any
sensible rate limit.

Also removed the unused EMPTY_PERSISTED_SCAN export from cache.ts
(no longer needed now that useHdWallet reads storage directly).
2026-05-21 14:07:48 -05:00
..
2026-04-30 13:19:22 +07:00
2026-04-17 16:22:33 +05:45
2026-05-13 18:35:03 -05:00