fix(quick-buy): enable Buy CTA in lockstep with quote loader#31218
Conversation
The Buy button could stay disabled for a beat after the quote loader disappeared. isPendingQuoteRefresh was derived from a ref updated inside a post-commit useEffect, so on the render where the quote arrived the loader hid (gated by isQuoteLoading) but the ref had not caught up yet, and ref writes do not schedule a re-render. The CTA only re-enabled on the next unrelated render. Derive isActiveQuoteForCurrentAmount synchronously by comparing the quote's own srcTokenAmount to the requested amount, and base isPendingQuoteRefresh on it. The loader and CTA now settle on the same render the matching quote lands. Co-authored-by: Cursor <cursoragent@cursor.com>
|
CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 1ca32d8. Configure here.
This update improves the handling of gas-included quotes in the QuickBuy flow. It introduces a new `sentAmount` property to accurately reflect the total wallet deduction, including fees, allowing for better comparison against the requested amount. Additionally, the `isActiveQuoteForCurrentAmount` logic has been updated to ensure the Buy CTA is enabled correctly when the active quote matches the expected amount after accounting for fees. Unit tests have been added to verify the new behavior, ensuring that the CTA is enabled for valid gas-included quotes and remains disabled when conditions are not met.
🔍 Smart E2E Test Selection
click to see 🤖 AI reasoning detailsE2E Test Selection:
Why no E2E tags are needed:
Performance Test Selection: |

Description
In the QuickBuy bottom sheet, the Buy button sometimes took longer to become enabled than the amount-section quote loader took to disappear. The user expects the CTA to become tappable as soon as the quote completes.
Reason for the change: the loader and the Buy button were gated by two conditions that drifted out of sync for one render. The loader is driven by
isBlockingQuoteLoad(gated byisQuoteLoading), which clears the instant the fetch resolves. The button is gated byisConfirmDisabled, which includesisPendingQuoteRefresh— and that value was derived fromsettledSourceTokenAmountRef, a ref updated only inside a post-commituseEffect. On the render where the quote arrived, the loader hid but the ref had not caught up, and ref writes do not schedule a re-render, so the CTA only re-enabled on the next unrelated render (a redux tick, gas-estimate update, quote countdown, etc.) — producing the variable lag.Solution: replace the timing/effect-based "settled amount" tracking with a synchronous derivation. A displayed quote is for the current amount when the quote's own
srcTokenAmountequals the requested amount (the request is built withcalcTokenValue(sourceTokenAmount, decimals).toFixed(0)and the bridge echoes that exact value back).isPendingQuoteRefreshnow derives from this synchronous check, soisBlockingQuoteLoadandisConfirmDisabledsettle on the same render the matching quote lands. Background refreshes of the same amount keepsrcTokenAmountunchanged, so the CTA stays enabled as before.Changelog
CHANGELOG entry: Fixed the QuickBuy Buy button sometimes staying disabled briefly after the quote finished loading.
Related issues
Fixes: An issue where he QuickBuy Buy button sometimes staying disabled briefly after the quote finished loading.
Manual testing steps
Screenshots/Recordings
Before
N/A
After
N/A
Pre-merge author checklist
Performance checks (if applicable)
trace()for usage andaddTokenfor an exampleFor performance guidelines and tooling, see the Performance Guide.
Pre-merge reviewer checklist
Made with Cursor
Note
Low Risk
Localized QuickBuy confirm/disable logic with added unit tests; no auth, submission, or bridge API changes beyond when the button enables.
Overview
Fixes QuickBuy Buy staying disabled briefly after the quote loader finishes by replacing post-commit ref tracking of the “settled” amount with a synchronous
isActiveQuoteForCurrentAmountcheck.isPendingQuoteRefreshnow derives from whether the on-screen quote matches the committed amount: atomic units fromcalcTokenValueon the requestedsourceTokenAmountare compared toactiveQuote.sentAmount(full wallet deduction), notquote.srcTokenAmount, so gas-included/sponsored quotes still enable the CTA when the displayed quote is valid.Tests add default
sentAmounton quote fixtures plus cases for same-render loader/CTA sync and post-feesrcTokenAmountwith matchingsentAmount.Reviewed by Cursor Bugbot for commit 4124eb2. Bugbot is set up for automated code reviews on this repo. Configure here.