Skip to content

fix: PoolDetailClient shares usePools() cache instead of bypassing it - #180

Merged
prodbycorne merged 7 commits into
SmartDropLabs:mainfrom
boluwacodes:fix/pool-detail-shared-cache-143
Aug 17, 2026
Merged

fix: PoolDetailClient shares usePools() cache instead of bypassing it#180
prodbycorne merged 7 commits into
SmartDropLabs:mainfrom
boluwacodes:fix/pool-detail-shared-cache-143

Conversation

@boluwacodes

Copy link
Copy Markdown
Contributor

Summary

PoolDetailClient fetched pool data and depositors with two hand-rolled useEffects calling sorobanService directly, entirely bypassing React Query — the same getFactoryPools() round trip usePools() performs, uncached and with no refetch policy. Visiting /farm then a pool's detail page triggered a second, fully independent RPC call even though the same data was sitting in the QueryClient's cache moments earlier, and once loaded, the detail page's stats never updated again for the lifetime of the page view.

  • PoolDetailClient now uses usePools() (the same hook the Farm page's list uses) and derives pool via useMemo(() => pools?.find((p) => p.id === poolId) ?? null) — sharing cache, staleTime, and refetchInterval with the Farm page.
  • New usePoolDepositors(poolId, limit) hook (staleTime: 30000 / refetchInterval: 60000, matching usePools()) replaces the one-shot getPoolDepositors useEffect.
  • Behavior change called out explicitly per the issue's own note: deriving pool via useMemo means it now recomputes if the pool later disappears from a factory poll (arguably more correct), whereas before a pool removed from the factory after initial load stayed displayed until the user navigated away and back.

Closes #143

Test plan

  • npx tsc --noEmit — clean
  • npm run lint — clean (only pre-existing unrelated warnings)
  • npm run build — succeeds
  • npx vitest run — 231/232 pass; the one failure (soroban-parsers.test.ts) is on a file untouched by this branch, confirmed byte-identical to upstream/main, unrelated to this change
  • New coverage (12 tests across 3 files) matching the issue's acceptance criteria:
    • usePoolDepositors fetches through sorobanService.getPoolDepositors with the given poolId/limit, stays disabled when poolId is empty, defaults limit to 20
    • PoolDetailClient mounted against a shared QueryClient after a bare usePools() consumer (simulating /farm) does not trigger a second getFactoryPools() call — call-count assertion, per the issue's own suggested test
    • PoolDetailClient's displayed dailyRate updates after usePools()'s 60s refetchInterval elapses, where before it would stay frozen at its initial value
    • Loading skeletons, "Pool not found.", and "Failed to load pool data." states are all preserved after the migration

getPoolDepositors previously had no query-hook wrapper — it was
called from a one-shot useEffect in PoolDetailClient with no refetch
policy, so depositor data froze at mount for the page's lifetime
(SmartDropLabs#143). staleTime/refetchInterval match usePools()'s policy.
…cache

Replaces the direct, uncached sorobanService.getFactoryPools()
useEffect with usePools() — the same hook the Farm page's list uses.
Visiting /farm then a pool's detail page no longer triggers a second,
independent RPC round trip while the cache is fresh, and pool stats
now update on usePools()'s 60s refetchInterval instead of being
frozen at mount for the page's lifetime (SmartDropLabs#143).

pool is now derived via useMemo(() => pools?.find(...)) rather than a
one-shot check — recomputes if the pool later disappears from a
factory poll (a behavior change from before: previously a pool
removed from the factory after initial load stayed displayed until
the user navigated away and back).
Replaces the one-shot sorobanService.getPoolDepositors() useEffect
with the new usePoolDepositors() query hook, so the Top Depositors
table also refreshes on an interval instead of being frozen at mount
for the page's lifetime (SmartDropLabs#143).
Fetches through sorobanService.getPoolDepositors with the given
poolId/limit, stays disabled (no fetch) when poolId is empty, and
defaults limit to 20 when not provided.
Simulates the issue's exact repro: a bare usePools() consumer (the
Farm page) populates a shared QueryClient's cache, then
PoolDetailClient mounts against the same client for the same pool.
getFactoryPools is asserted called exactly once total — the second
consumer must not trigger its own independent RPC round trip while
the cache is fresh.
Advances past usePools()'s 60s refetchInterval with a changed mocked
getFactoryPools response and asserts the displayed dailyRate updates
to reflect it — pre-fix, PoolDetailClient had no polling mechanism at
all and this figure would stay frozen at its initial value for the
lifetime of the page view (SmartDropLabs#143).
…tDropLabs#143)

Covers the acceptance criteria's "existing behavior is preserved"
requirement directly: loading skeletons show while usePools() is
pending, "Pool not found." shows when the resolved pool list doesn't
contain the requested poolId, and "Failed to load pool data." shows
when the fetch itself fails (advancing through usePools()'s 3-retry
exponential backoff via fake timers rather than waiting ~7s of real
time).
@netlify

netlify Bot commented Aug 17, 2026

Copy link
Copy Markdown

Deploy Preview for spiffy-melomakarona-eb1e8a ready!

Name Link
🔨 Latest commit 9c921ea
🔍 Latest deploy log https://app.netlify.com/projects/spiffy-melomakarona-eb1e8a/deploys/6a8362e2a702920008df8ce6
😎 Deploy Preview https://deploy-preview-180--spiffy-melomakarona-eb1e8a.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify

netlify Bot commented Aug 17, 2026

Copy link
Copy Markdown

Deploy Preview for smart-drop ready!

Name Link
🔨 Latest commit 9c921ea
🔍 Latest deploy log https://app.netlify.com/projects/smart-drop/deploys/6a8362e22619ff00088d5b47
😎 Deploy Preview https://deploy-preview-180--smart-drop.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@prodbycorne

Copy link
Copy Markdown
Contributor

All ci s passed. welldone

@prodbycorne
prodbycorne merged commit b305288 into SmartDropLabs:main Aug 17, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants