Skip to content

Debounce useLockAssetsFeePreview to stop per-keystroke simulateTransaction calls - #182

Merged
prodbycorne merged 4 commits into
SmartDropLabs:mainfrom
oluwarantimini:fix/debounce-lock-assets-fee-preview-134
Aug 19, 2026
Merged

Debounce useLockAssetsFeePreview to stop per-keystroke simulateTransaction calls#182
prodbycorne merged 4 commits into
SmartDropLabs:mainfrom
oluwarantimini:fix/debounce-lock-assets-fee-preview-134

Conversation

@oluwarantimini

Copy link
Copy Markdown
Contributor

Summary

useLockAssetsFeePreview keyed its query directly on the raw, un-debounced amount string, so every keystroke that changed a still-valid amount in the Farm page's deposit modal fired a fresh simulateLockAssets call — two real RPC round trips (getAccount + simulateTransaction) per intermediate, never-submitted value typed on the way to a final amount.

  • Debounces amount inside useLockAssetsFeePreview itself (350ms, matching useLeaderboard's existing SEARCH_DEBOUNCE_MS pattern) rather than at the DepositModal call site, so any future caller of this hook gets the fix automatically.
  • isFetching is overridden to also be true while the raw amount hasn't settled into the debounced value yet, so farm/page.tsx's "Simulating..." text and its canSubmit gate (both already keyed off feePreview.isFetching) correctly reflect a pending state for the whole debounce window, not just the network request that follows it — no changes needed in DepositModal/farm/page.tsx.
  • debouncedAmount starts at "" rather than being seeded from the initial amount, matching useLeaderboard's searchQuery/searchInput split — otherwise a caller mounting the hook with a non-empty amount already would get an un-debounced fire on mount (caught by one of the new tests).
  • Superseded in-flight requests don't race: relies on React Query's per-query-key cache identity (a stale in-flight promise for an old key can't clobber a newer key's cache entry), verified explicitly with a dedicated test rather than just assumed.

PoolDetailClient.tsx's deposit modal doesn't use this hook at all, so this fix is correctly scoped to the Farm page only, per the issue's own note.

Closes #134

Test plan

  • npx tsc --noEmit
  • npx eslint src/hooks/useSorobanQuery.ts src/hooks/useSorobanQuery.test.ts
  • npx vitest run — all passing except one pre-existing, unrelated failure in src/lib/soroban-parsers.test.ts (decodeScString), confirmed to already fail identically on a clean clone of upstream main, and not something this repo's CI gates on (only e2e/build run in CI, not vitest)
  • New test: a rapid keystroke burst produces exactly one simulateLockAssets call, using the final typed value
  • New test: isFetching is true throughout the debounce window itself, before any RPC call fires
  • New test (regression): a settled single amount entry still produces a fee preview as before
  • New test: an invalid/empty amount never calls simulateLockAssets
  • New test: a slow, superseded request resolving late doesn't overwrite a fresher result already displayed
  • Manually reasoned through e2e/farm.spec.ts's deposit flow (amountInput.fill('10') fires a single change event, and the submit button click auto-waits on Playwright's actionability/enabled check with a 30s test timeout) — the added 350ms debounce is well within that margin and shouldn't affect the existing e2e test

…alls

Previously the query keyed directly on the raw, un-debounced amount
string, so every keystroke that changed a still-valid amount fired a
fresh simulateLockAssets call -- two real RPC round trips
(getAccount + simulateTransaction) per intermediate, never-submitted
value typed on the way to a final amount.

Debounces inside the hook itself (350ms, matching useLeaderboard's
SEARCH_DEBOUNCE_MS pattern) rather than at each call site, so future
callers get the fix automatically. isFetching is overridden to also be
true while amount hasn't settled into debouncedAmount yet, so UI keyed
off isFetching (the "Simulating..." text and the deposit modal's
canSubmit gate) reflects a pending state for the whole debounce window,
not just the network request that follows it -- no changes needed in
DepositModal itself.
debouncedAmount was seeded from the initial amount, so a caller that
mounts the hook with a non-empty amount already (rather than typing
into an initially-empty field) got its first query fired immediately,
un-debounced -- the same bug this fix targets, just via mount instead
of a keystroke. Starts at "" instead, matching useLeaderboard's
searchQuery/searchInput split, so every value -- including the first
one a caller passes -- goes through the debounce window once.

Caught by the accompanying test for a non-rapid single amount entry.
- A rapid keystroke burst produces exactly one simulateLockAssets call
  after the debounce window, using the final typed value.
- isFetching is true throughout the debounce window itself, before any
  RPC call has fired, so UI keyed off it doesn't look inert.
- A settled single amount entry still produces a fee preview
  (regression, unchanged behavior).
- An invalid/empty amount never calls simulateLockAssets, debounce
  window or not.
- A slow, superseded request from an earlier amount resolving after a
  newer request has already resolved does not clobber the fresher
  result -- explicit coverage for the "superseded in-flight calls
  don't race" acceptance criterion, relying on React Query's per-key
  cache identity rather than any new code in this hook.
@netlify

netlify Bot commented Aug 19, 2026

Copy link
Copy Markdown

Deploy Preview for spiffy-melomakarona-eb1e8a ready!

Name Link
🔨 Latest commit 47d96c6
🔍 Latest deploy log https://app.netlify.com/projects/spiffy-melomakarona-eb1e8a/deploys/6a856713ff88760008949436
😎 Deploy Preview https://deploy-preview-182--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 19, 2026

Copy link
Copy Markdown

Deploy Preview for smart-drop ready!

Name Link
🔨 Latest commit 47d96c6
🔍 Latest deploy log https://app.netlify.com/projects/smart-drop/deploys/6a856713ae47a2000801fd51
😎 Deploy Preview https://deploy-preview-182--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

Good Job done

@prodbycorne
prodbycorne merged commit f5ea19e into SmartDropLabs:main Aug 19, 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

Development

Successfully merging this pull request may close these issues.

useLockAssetsFeePreview fires a fresh Soroban simulateTransaction RPC call on every keystroke in the deposit amount field, with no debounce

2 participants