Skip to content

fix: keep QuickBuy CTA live during background quote refresh#31059

Merged
xavier-brochard merged 2 commits into
mainfrom
fix/quickbuy-non-blocking-quote-refresh
Jun 4, 2026
Merged

fix: keep QuickBuy CTA live during background quote refresh#31059
xavier-brochard merged 2 commits into
mainfrom
fix/quickbuy-non-blocking-quote-refresh

Conversation

@xavier-brochard

@xavier-brochard xavier-brochard commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Description

Screen.Recording.2026-06-04.at.11.04.52.mov

In QuickBuy, quotes auto-refresh on a fixed interval. The data layer already keeps the displayed quote live during a refresh (useQuickBuyQuotes only flips isQuoteLoading = true and atomically swaps rawQuotes on success — it never clears the existing quote). However, the controller wired the raw isQuoteLoading flag into the CTA disable gate and the amount-section spinner.

As a result, on every refresh tick the Buy/Sell button greyed out and the receive estimate was replaced by a spinner, even though the on-screen quote stayed valid and submittable the entire time. This produced a visible, recurring flicker.

This PR introduces isBlockingQuoteLoad — loading that has no usable on-screen quote yet (first load, or an input change where the current quote no longer matches). A plain background refresh is excluded, so the CTA stays enabled and the receive estimate stays visible, then updates in place when the new quote arrives.

The genuine "no usable quote for what's displayed" cases remain blocked via the existing, more precise guards:

  • mid-drag -> isAmountUncommitted
  • amount changed, quote is for old amount -> isPendingQuoteRefresh
  • token pair changed -> hasQuoteMismatch
  • no quote / error -> !activeQuote, hasError

The all-quotes select screen keeps consuming raw isQuoteLoading, where reflecting refresh activity is desirable.

Key changes

  • useQuickBuyController.ts: derive hasUsableQuoteOnScreen + isBlockingQuoteLoad; use the latter in isConfirmDisabled and isTotalLoading; expose it on the result type.
  • QuickBuyAmount.tsx: feed isBlockingQuoteLoad to the amount section so the receive estimate persists during refresh.
  • Added controller tests for the background-refresh (enabled) and initial-load (blocked) cases; updated typed context mocks.

Changelog

CHANGELOG entry: null

Related issues

Fixes:

Manual testing steps

Feature: QuickBuy non-blocking quote refresh

  Scenario: user keeps the CTA usable while quotes auto-refresh
    Given the user has opened QuickBuy and selected a valid amount with a quote shown

    When the periodic quote refresh runs in the background
    Then the Buy/Sell button stays enabled
    And the receive estimate stays visible (no spinner) and updates in place when the new quote lands

  Scenario: user changes the amount
    Given the user has a quote on screen

    When the user changes the amount or token
    Then the CTA is disabled and the loading state is shown until a matching quote arrives

Screenshots/Recordings

Before

After

Pre-merge author checklist

Performance checks (if applicable)

  • I've tested on Android
  • I've tested with a power user scenario
  • I've instrumented key operations with Sentry traces for production performance metrics

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

Made with Cursor


Note

Medium Risk
Changes quote gating and submit-disable logic for trades; incorrect stale/usable detection could allow or block submission at the wrong time, though new flags and tests target those cases.

Overview
QuickBuy was treating every quote fetch as a full UI block: the Buy/Sell CTA and receive estimate reacted to raw isQuoteLoading, so periodic auto-refresh caused flicker even when the on-screen quote stayed valid.

The controller now derives isBlockingQuoteLoad (loading only when there is no usable quote for the current amount, token pair, and committed inputs) and wires that into confirm disable, total loading, and the amount section spinner. useQuickBuyQuotes adds isQuoteRequestStale when hidden request inputs (slippage, destination address, gas flags) change after the last settled fetch, so the CTA cannot stay enabled on a quote that no longer matches the active request.

Initial load and real input changes still block as before; benign background refreshes keep the CTA enabled and the estimate visible until the new quote lands.

Reviewed by Cursor Bugbot for commit bc095ab. Bugbot is set up for automated code reviews on this repo. Configure here.

The CTA disable gate and amount-section spinner were wired to the raw
isQuoteLoading flag, so the Buy/Sell button greyed out and the receive
estimate was replaced by a spinner on every periodic quote refresh, even
though the displayed quote stayed valid and submittable the whole time.

Introduce isBlockingQuoteLoad (loading without a usable on-screen quote)
and use it for the CTA, total, and amount spinner. The displayed quote
now stays interactive during refresh and updates in place when the new
quote lands. Genuine no-usable-quote cases (first load, amount/token
change, mid-drag, error) remain blocked via existing guards.

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

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.

@mm-token-exchange-service mm-token-exchange-service Bot added the team-social-ai Social & AI team label Jun 4, 2026
@github-actions github-actions Bot added the size-M label Jun 4, 2026
@xavier-brochard xavier-brochard marked this pull request as ready for review June 4, 2026 09:21
@github-actions github-actions Bot added the risk:high AI analysis: high risk label Jun 4, 2026
@xavier-brochard xavier-brochard removed the risk:high AI analysis: high risk label Jun 4, 2026

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ 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 06b5620. Configure here.

This update adds an `isQuoteRequestStale` flag to the Quick Buy functionality, which indicates when request-only inputs (like slippage and destination address) have changed since the last quote was fetched. This ensures that the displayed quotes are not treated as submittable when they no longer match the current request.

The flag is integrated into the `useQuickBuyController` and `useQuickBuyQuotes` hooks, affecting the UI behavior of the Quick Buy CTA and loading states. Additionally, tests have been added to verify the correct behavior when inputs change and quotes are refetched.

Co-authored-by: Tyler Chong <tyler.chong@consensys.net>
@github-actions github-actions Bot added the risk:high AI analysis: high risk label Jun 4, 2026
@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

  • Selected E2E tags: SmokePerps, SmokeSwap, SmokeConfirmations, SmokeWalletPlatform
  • Selected Performance tags: None (no tests recommended)
  • Risk Level: low
  • AI Confidence: 72%
click to see 🤖 AI reasoning details

E2E Test Selection:
The changes are confined to the SocialLeaderboard/TraderPositionView/QuickBuy feature area. Specifically:

  1. useQuickBuyQuotes.ts: Adds isQuoteRequestStale flag to detect when request-only inputs (slippage, destination address, gas settings) have changed since the last settled quote fetch.
  2. useQuickBuyController.ts: Introduces isBlockingQuoteLoad (distinguishes blocking first-loads from benign background refreshes), updates isConfirmDisabled and isTotalLoading to use the new flags. This is a UX improvement — the CTA stays enabled during background refreshes when a valid quote is already displayed.
  3. QuickBuyAmount.tsx: Uses isBlockingQuoteLoad instead of isQuoteLoading for UI blocking.
  4. Test files: Unit test updates to reflect new interface properties.

No E2E test files reference QuickBuy, SocialLeaderboard, or TraderPositionView directly. The changes are purely internal hook/component refinements with no shared infrastructure impact (no controllers, Engine, navigation, or shared components modified).

Tag selection rationale:

  • SmokePerps: QuickBuy is the "Add Funds" / buy-token flow within the Perps/trading ecosystem (TraderPositionView). Changes to the CTA enable/disable logic and loading states directly affect the Perps Add Funds flow.
  • SmokeSwap: QuickBuy is a swap-like flow (fetching quotes, selecting tokens, executing transactions). The isBlockingQuoteLoad change affects quote loading UX which is analogous to swap quote flows.
  • SmokeConfirmations: Per SmokePerps tag description, Add Funds deposits are on-chain transactions that go through confirmations. The isConfirmDisabled logic change could affect when users can proceed to confirmation.
  • SmokeWalletPlatform: Per SmokePerps tag description, SmokeWalletPlatform should be selected alongside SmokePerps (Perps is a section inside Trending tab).

Risk is low because: (1) changes are isolated to a single feature area, (2) no shared infrastructure is modified, (3) the logic change is a refinement (background refresh no longer blocks CTA), (4) comprehensive unit tests cover the new behavior.

Performance Test Selection:
The changes are internal hook logic refinements for the QuickBuy feature (isBlockingQuoteLoad, isQuoteRequestStale). While these affect quote loading state management, they are behavioral correctness fixes (not blocking CTA during background refreshes) rather than performance-impacting changes. No rendering loops, list components, or critical startup paths are modified. No performance tests are warranted.

View GitHub Actions results

@xavier-brochard xavier-brochard enabled auto-merge June 4, 2026 09:42
@xavier-brochard xavier-brochard added this pull request to the merge queue Jun 4, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 4, 2026
@xavier-brochard xavier-brochard added this pull request to the merge queue Jun 4, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 4, 2026
@xavier-brochard xavier-brochard added this pull request to the merge queue Jun 4, 2026
Merged via the queue into main with commit 8597157 Jun 4, 2026
213 checks passed
@xavier-brochard xavier-brochard deleted the fix/quickbuy-non-blocking-quote-refresh branch June 4, 2026 11:52
@github-actions github-actions Bot locked and limited conversation to collaborators Jun 4, 2026
@metamaskbotv2 metamaskbotv2 Bot added the release-7.81.0 Issue or pull request that will be included in release 7.81.0 label Jun 4, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

release-7.81.0 Issue or pull request that will be included in release 7.81.0 risk:high AI analysis: high risk size-M team-social-ai Social & AI team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants