772a2de236
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).