a8b2fe5ddf
The campaigns grid renders up to 200 CampaignCards at once with no virtualization, and each card eagerly ran useCampaignDonations: an Esplora /address lookup per card (polling every 30s via refetchInterval) plus a /tx verification call per kind-8333 donation receipt. On first paint that's hundreds of /address calls and potentially thousands of /tx calls in one burst, then 200 more /address calls every 30s forever. Once mempool.space starts returning 429, the failover client retries each call across every configured endpoint, cascading the rate-limit to all of them. Gate the donation lookup behind an IntersectionObserver so only on-screen cards talk to Esplora, and drop the per-card 30s polling. The detail page (a single instance, not a grid) opts back into the 30s live refresh via a new refetchInterval option. - Add useInView hook (once-only, rootMargin pre-arm, IO-less fallback). - useCampaignDonations gains enabled + refetchInterval options; default no polling, longer staleTime; treat 'not enabled yet' as loading so off-screen cards show a skeleton instead of flashing '0 raised'. - Gate CampaignCard and CampaignInlinePreview on visibility. - CampaignDetailPage opts into refetchInterval: 30_000.