Skip to content

fix: tempo disable confirm button until gas autoselect#28722

Closed
maxime-oe wants to merge 1 commit into
mainfrom
fix/tempo-disable-tx-confirm-until-autoselect
Closed

fix: tempo disable confirm button until gas autoselect#28722
maxime-oe wants to merge 1 commit into
mainfrom
fix/tempo-disable-tx-confirm-until-autoselect

Conversation

@maxime-oe
Copy link
Copy Markdown
Contributor

@maxime-oe maxime-oe commented Apr 13, 2026

Description

The goal of the change is to prevent a premature "enablement" for the Confirm button when a transaction is loading. There are pre-existing race conditions that allowed users to confirm a transaction before everything is fully loaded. Those conditions could make the tx skip gasless flows, falling back to native token for gas payment.

The impact is bigger on Tempo because using a native token is not an option (there is no native token on Tempo), which means that such race condition will always result in a failed tx (the tx won't be sent to the RPC or relayer).

The changes solve the race conditions cases, as well as adds some extra conditions for the loading when on a chain that has no native token.

Changelog

CHANGELOG entry: add new isGaslessLoading guard to Confirmation button - consistently with Extension.
CHANGELOG entry: useIsGaslessSupported to use useQuery instead of useAsync to avoid race conditions.

Related issues

Fixes: https://consensyssoftware.atlassian.net/browse/NEB-944?atlOrigin=eyJpIjoiYWFiY2U0NjU1ZjEzNGNmODlmOTZkNTQwNzM4N2MxMTUiLCJwIjoiaiJ9

Manual testing steps

Repeating instructions shared for Extension since Mobile flow will be very similar (just "tap" instead of click ;))

  • On Tempo mainnet, find pathUSD and click on "Send".
  • Set amount to 0.01 and select the account to send to (any account).
  • As soon as you clicked on the recipient account, start "spam clicking" on "Confirm" or the location where you know "Confirm" will appear.
image image

What should be observed is that despite spam-clicking, it should not be possible to "Confirm" the transaction "too soon" and it should always succeed no matter how "early" you click on "Confirm".

Screenshots/Recordings

Before

After

Pre-merge author checklist

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.

Note

Medium Risk
Changes confirmation disablement logic around gasless support and switches gasless eligibility checks to React Query; could affect when users can confirm transactions and may introduce edge-case loading states on chains without native gas.

Overview
Prevents premature transaction confirmation by disabling the Confirm button while gasless support/fee-token auto-selection is still loading (Footer now gates on new useIsGaslessLoading in addition to transaction pay loading).

Adds useIsGaslessLoading to detect gasless-related loading (including Tempo-style no native token cases and mismatched selectedGasFeeToken), and refactors useIsGaslessSupported to use React Query (useQuery) for relay support checks to reduce race conditions.

Test infrastructure is updated to wrap renderWithProvider/renderHookWithProvider with a QueryClientProvider, and relevant tests are adjusted/mocked accordingly (including new unit tests for useIsGaslessLoading).

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

@github-actions
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.

@metamaskbot metamaskbot added the team-networks Networks team label Apr 13, 2026
@maxime-oe maxime-oe force-pushed the fix/tempo-disable-tx-confirm-until-autoselect branch 4 times, most recently from 281323b to 1b844da Compare April 13, 2026 15:38
@maxime-oe maxime-oe marked this pull request as ready for review April 13, 2026 15:46
@maxime-oe maxime-oe requested a review from a team as a code owner April 13, 2026 15:46
Comment thread app/components/Views/confirmations/hooks/gas/useIsGaslessLoading.test.ts Outdated
Comment thread app/components/Views/confirmations/hooks/gas/useIsGaslessLoading.test.ts Outdated
@maxime-oe maxime-oe force-pushed the fix/tempo-disable-tx-confirm-until-autoselect branch from 1b844da to a48f2e0 Compare April 13, 2026 16:07
@github-actions github-actions Bot added the risk-medium Moderate testing recommended · Possible bug introduction risk label Apr 13, 2026
@maxime-oe maxime-oe force-pushed the fix/tempo-disable-tx-confirm-until-autoselect branch from a48f2e0 to d5f98e2 Compare April 13, 2026 17:06
@github-actions github-actions Bot added risk-medium Moderate testing recommended · Possible bug introduction risk and removed risk-medium Moderate testing recommended · Possible bug introduction risk labels Apr 13, 2026
Comment thread app/components/Views/confirmations/components/confirm/confirm-component.test.tsx Outdated
Comment thread app/components/Views/confirmations/hooks/gas/useIsGaslessLoading.ts Outdated
Comment thread app/components/Views/confirmations/hooks/gas/useIsGaslessSupported.test.ts Outdated
@maxime-oe maxime-oe force-pushed the fix/tempo-disable-tx-confirm-until-autoselect branch from d5f98e2 to cc20675 Compare April 13, 2026 17:36
@github-actions github-actions Bot added risk-medium Moderate testing recommended · Possible bug introduction risk and removed risk-medium Moderate testing recommended · Possible bug introduction risk labels Apr 13, 2026
Comment thread app/components/Views/confirmations/components/info-root/info-root.test.tsx Outdated
@maxime-oe maxime-oe force-pushed the fix/tempo-disable-tx-confirm-until-autoselect branch from cc20675 to 972e979 Compare April 13, 2026 17:44
@github-actions github-actions Bot added risk-medium Moderate testing recommended · Possible bug introduction risk and removed risk-medium Moderate testing recommended · Possible bug introduction risk labels Apr 13, 2026
@maxime-oe maxime-oe force-pushed the fix/tempo-disable-tx-confirm-until-autoselect branch from 972e979 to 29c57f3 Compare April 13, 2026 18:08
@github-actions github-actions Bot added risk-medium Moderate testing recommended · Possible bug introduction risk and removed risk-medium Moderate testing recommended · Possible bug introduction risk labels Apr 13, 2026
Comment thread app/components/Views/confirmations/hooks/gas/useIsGaslessLoading.ts Outdated
@maxime-oe maxime-oe force-pushed the fix/tempo-disable-tx-confirm-until-autoselect branch from 29c57f3 to 40efe92 Compare April 13, 2026 18:23
@maxime-oe maxime-oe requested a review from a team as a code owner April 13, 2026 18:23
@github-actions github-actions Bot removed the risk-medium Moderate testing recommended · Possible bug introduction risk label Apr 13, 2026
@maxime-oe maxime-oe force-pushed the fix/tempo-disable-tx-confirm-until-autoselect branch from 1a72f8f to d21da8d Compare April 14, 2026 06:56
@github-actions github-actions Bot added risk-medium Moderate testing recommended · Possible bug introduction risk and removed risk-medium Moderate testing recommended · Possible bug introduction risk labels Apr 14, 2026
@codecov-commenter
Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.10345% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.15%. Comparing base (9f195d0) to head (d21da8d).
⚠️ Report is 73 commits behind head on main.

Files with missing lines Patch % Lines
...ews/confirmations/hooks/gas/useIsGaslessLoading.ts 90.90% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff            @@
##             main   #28722     +/-   ##
=========================================
  Coverage   82.14%   82.15%             
=========================================
  Files        4949     5000     +51     
  Lines      130070   131267   +1197     
  Branches    29004    29289    +285     
=========================================
+ Hits       106851   107840    +989     
- Misses      15923    16087    +164     
- Partials     7296     7340     +44     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@maxime-oe maxime-oe force-pushed the fix/tempo-disable-tx-confirm-until-autoselect branch from d21da8d to 5aad6bc Compare April 14, 2026 07:16
@github-actions github-actions Bot added risk-medium Moderate testing recommended · Possible bug introduction risk and removed risk-medium Moderate testing recommended · Possible bug introduction risk labels Apr 14, 2026
@maxime-oe maxime-oe force-pushed the fix/tempo-disable-tx-confirm-until-autoselect branch from 5aad6bc to 84f14f2 Compare April 14, 2026 08:12
@github-actions github-actions Bot added risk-medium Moderate testing recommended · Possible bug introduction risk and removed risk-medium Moderate testing recommended · Possible bug introduction risk labels Apr 14, 2026
@maxime-oe maxime-oe force-pushed the fix/tempo-disable-tx-confirm-until-autoselect branch from 84f14f2 to 519d6d7 Compare April 14, 2026 08:38
@github-actions github-actions Bot added risk-medium Moderate testing recommended · Possible bug introduction risk and removed risk-medium Moderate testing recommended · Possible bug introduction risk labels Apr 14, 2026
Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

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 519d6d7. Configure here.

Comment thread app/util/test/renderWithProvider.tsx
@maxime-oe maxime-oe force-pushed the fix/tempo-disable-tx-confirm-until-autoselect branch from 519d6d7 to 5f8bb07 Compare April 21, 2026 13:30
@github-actions github-actions Bot added risk-medium Moderate testing recommended · Possible bug introduction risk and removed risk-medium Moderate testing recommended · Possible bug introduction risk labels Apr 21, 2026
@maxime-oe maxime-oe force-pushed the fix/tempo-disable-tx-confirm-until-autoselect branch from 5f8bb07 to 164017b Compare April 21, 2026 16:59
@github-actions github-actions Bot added risk-medium Moderate testing recommended · Possible bug introduction risk and removed risk-medium Moderate testing recommended · Possible bug introduction risk labels Apr 21, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

  • Selected E2E tags: SmokeConfirmations, SmokeTrade, SmokePredictions, SmokePerps
  • Selected Performance tags: None (no tests recommended)
  • Risk Level: medium
  • AI Confidence: 85%
click to see 🤖 AI reasoning details

E2E Test Selection:

The changes in this PR are focused on the confirmations system with gasless transaction support:

  1. footer.tsx - The confirmation footer now disables the confirm button when isGaslessLoading is true. This affects ALL confirmation types (send, swap, signatures, contract interactions). The footer is a shared component across all confirmation flows.

  2. useIsGaslessLoading.ts (new hook) - Determines if gasless fee token loading is in progress. This is used to prevent premature confirmation submission when gasless fee tokens haven't loaded yet (relevant for EIP-7702 and Smart Transactions).

  3. useIsGaslessSupported.ts - Refactored from useAsyncResult to @tanstack/react-query's useQuery. This changes the async state management for relay support checks. The pending state behavior may differ slightly between the two implementations, which could affect when the confirm button is disabled.

  4. renderWithProvider.tsx - Added QueryClientProvider wrapper to the shared test utility. This is a test infrastructure change that enables @tanstack/react-query hooks to work in all tests using renderWithProvider. This is a positive change but could theoretically affect test behavior if any tests were previously mocking @tanstack/react-query globally (as seen in PredictBalance.test.tsx which removed its manual mock).

Tag Selection Rationale:

  • SmokeConfirmations: Primary target - the footer component and gasless loading hooks directly affect all confirmation flows including send, swap, signatures, EIP-7702 batch transactions, and gas fee token payments.
  • SmokeTrade: Swap and bridge flows go through confirmations. The footer change affects the confirm button in swap confirmation screens. Per tag description, when selecting SmokeTrade for swap/bridge, also select SmokeConfirmations.
  • SmokePredictions: The PredictBalance and PredictPositionsHeader test files were modified to remove manual @tanstack/react-query mocks (now handled by renderWithProvider). Predictions involve on-chain transactions that go through confirmations.
  • SmokePerps: The Perps Add Funds flow involves on-chain transactions through confirmations. Also, Perps is a section inside Trending (SmokeWalletPlatform), but the direct impact is through confirmations.

Not selected:

  • SmokeWalletPlatform: No direct changes to wallet platform features; the Predict test changes are minor mock cleanup
  • SmokeAccounts, SmokeIdentity, SmokeNetworkAbstractions, SmokeNetworkExpansion, SmokeMultiChainAPI, SmokeBrowser, SmokeRamps, SmokeCard, SmokeSeedlessOnboarding, FlaskBuildTests: No relevant changes to these areas

Performance Test Selection:
The changes are focused on gasless loading state management in the confirmation footer and a refactor of useIsGaslessSupported from useAsyncResult to react-query. These are logic/state changes rather than rendering performance changes. The renderWithProvider test utility change adds QueryClientProvider but this is test-only infrastructure. No performance-sensitive code paths (account lists, app startup, login, asset loading, swap execution timing) are affected.

View GitHub Actions results

@github-actions
Copy link
Copy Markdown
Contributor

E2E Fixture Validation — Schema is up to date
12 value mismatches detected (expected — fixture represents an existing user).
View details

@sonarqubecloud
Copy link
Copy Markdown

@nikolastoimenovski-consensys
Copy link
Copy Markdown

Tested locally, fixed, adding the "qa passed" label.

@nikolastoimenovski-consensys nikolastoimenovski-consensys added the QA Passed QA testing has been completed and passed label Apr 22, 2026
return isRelaySupported(chainId as Hex);
}, [chainId, shouldCheck7702Eligibility]);

const { data: relaySupportsChain, isFetching: relayPending } = useQuery({
Copy link
Copy Markdown
Member

@matthewwalsh0 matthewwalsh0 Apr 22, 2026

Choose a reason for hiding this comment

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

What's the benefit of switching to useQuery here? Is this required?

Any caching should be handled by the server and browser / os based on caching headers.

Copy link
Copy Markdown
Contributor Author

@maxime-oe maxime-oe Apr 22, 2026

Choose a reason for hiding this comment

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

The problem was that useAsync was not properly managing the { enabled } mode with the shouldCheck7702Eligibility && Boolean(chainId) condition. The hook go through cycles where chainId has some value, then hasn't, then has some value again.
I first tried to change useAsync so it would behave more that useQuery, then decided it was too risky cause useAsync is used in multiple places.
Then I tried to wrap the shouldCheck7702Eligibility && Boolean(chainId) condition manually in useIsGaslessSupported but I kept getting race conditions.

useQuery on the other hand worked immediately and exacted as one would expect when reading the code. So I went for it - after 1/2 hrs of die and retry.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Then the deeper issue is why the chainId is ever not set for an active transaction?

It should be available on the transaction meta for its entire lifetime, why doesn't the same behaviour happen in extension?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Then the deeper issue is why the chainId is ever not set for an active transaction?

I think this never happens, but that transactionMeta is not always set. Maybe I was wrong about that one re-becoming undefined but at least one variable was doing back-and-forth - I should have noted this one.

I'll start over and try to redo it but it might not be as bullet-proof as the useQuery solution. The current solutions works (as opposed as before). It is just not the original code.

const isPending =
smartTransactionPending || (shouldCheck7702Eligibility && relayPending);
const is7702SupportedPending = shouldCheck7702Eligibility && relayPending;
const pending = smartTransactionPending || is7702SupportedPending;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is this needed? If not, does this file need changing at all?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No I can roll back those two lines if reducing the LoCs / amount of changes is import. I still want to fight for my useQuery though, unless you see a clear alternative: Only one I'd see otherwise is making the hook more complex by not using either useQuery or useAsync.

isTransactionValueUpdating ||
isPayLoading;
isPayLoading ||
isGaslessLoading;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does this have larger implications if mobile wasn't previously disabled while gas station was loading?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes it might actually feel less flaky on slower devices - the "Confirm" button blinks much more on Mobile than on Extension, maybe due to isTransactionValueUpdating. If isGaslessLoading remains "true" longer than the time for isTransactionValueUpdating to go true then false for example.
But on Tempo this "blinking" is more than UX gimmick, it makes the tx fail if the user taps during one of those blinks.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We wouldn't need any changes in Predict code if we didn't change to useQuery?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No but I couldn't find any clean alternative.
I modified those 2 test files after making the changes in renderWithProvider.tsx

@maxime-oe
Copy link
Copy Markdown
Contributor Author

Dropped and replaced by #29188

@maxime-oe maxime-oe closed this Apr 23, 2026
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 23, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

QA Passed QA testing has been completed and passed risk-medium Moderate testing recommended · Possible bug introduction risk size-M team-networks Networks team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants