Skip to content

fix: switch to compatible provider when MMPay loads with an incompatible UB2 selection - #34162

Closed
saustrie-consensys wants to merge 4 commits into
mainfrom
saustrie/fix-mmplay-provider-compatibility-switch
Closed

fix: switch to compatible provider when MMPay loads with an incompatible UB2 selection#34162
saustrie-consensys wants to merge 4 commits into
mainfrom
saustrie/fix-mmplay-provider-compatibility-switch

Conversation

@saustrie-consensys

@saustrie-consensyssaustrie-consensys commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Description

When a user selects an aggregator provider (e.g. Coinbase) in the UB2 Buy flow and then opens the MMPay "Add funds" confirmation screen, the shared RampsController.providers.selected value carries over. With the moneyHeadlessAllProviders flag off (production default), useIsFiatPaymentAvailable returns false for any non-native provider, which causes useAutomaticTransactionPayToken to exit its fiat path without setting isUpdated.current. The result is the "Pay with..." row skeleton loading forever.

Root cause

useHasNativeFiatProvider (pre-Phase 2) checks selectedProvider?.type === 'native'. An aggregator provider selected in UB2 fails that check. The downstream useAutomaticTransactionPayToken has an early return at the !isFiatEnabled branch that does not set the latch (isUpdated.current), so the effect stays retriable — but there is nothing to trigger a re-render and retry it, so the skeleton never resolves.

Fix

Adds useEnsureCompatibleProvider(assetId) — a hook called at the MMPay confirmation entry point. When the selected provider does not support the given asset, it dispatches setSelectedProvider to swap in the first compatible provider (using the same providerSupportsAsset utility as UB2's BuildQuote tier-1 silent switch). The dispatch triggers a re-render; on that render isFiatEnabled is now true, the auto-selection effect runs again (it did not latch on the previous run), and the payment method row resolves.

The !isFiatEnabled early return in useAutomaticTransactionPayToken intentionally does not set isUpdated.current — that is what allows the retry. A comment has been added there to document this contract and prevent a future regression.

This is also defense-in-depth: Phase 2 (moneyHeadlessAllProviders on) already unblocks the loading path for any provider type. This fix covers the flag-off (production) case.

Changelog

CHANGELOG entry: Fixed a bug where navigating to the MMPay "Add funds" screen after selecting an aggregator provider in UB2 would cause the payment method row to load indefinitely.

Related issues

Refs: N/A

Manual testing steps

Feature: MMPay payment method row resolves after UB2 provider switchScenario: user opens MMPay after selecting Coinbase in UB2Given the moneyHeadlessAllProviders flag is disabled (production default)
And the user has previously used UB2 and selected Coinbase as their provider
When the user opens the MMPay "Add funds" / money account deposit confirmation screen
Then the "Pay with..." payment method row resolves to a selectable row
And the row is NOT stuck in an infinite skeleton loading state
Scenario: user opens MMPay with a compatible provider already selected (regression)Given the user's selected provider supports the mUSD-on-Monad asset
When the user opens the MMPay confirmation screen
Then setSelectedProvider is never called (no unnecessary switch)
And the payment method row resolves normally

Screenshots/Recordings

N/A

Before

"Pay with..." row shows a perpetual skeleton.

After

"Pay with..." row resolves to a selectable payment method.

Pre-merge author checklist

Performance checks (if applicable)

  • I've tested on Android
    • Ideally on a mid-range device; emulator is acceptable
  • 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.

… selection
When a user selects an aggregator provider (e.g. Coinbase) in the UB2 buy
flow and then opens the MMPay "Add funds" confirmation screen, the shared
`RampsController.providers.selected` value carries over. With the
moneyHeadlessAllProviders flag off, `useIsFiatPaymentAvailable` returns
false for any non-native provider, causing `useAutomaticTransactionPayToken`
to dead-end before setting a payToken. The result is the "Pay with..."
skeleton loading forever.
UB2 solves this in BuildQuote via a silent tier-1 switch effect; MMPay had
no equivalent. This adds `useEnsureCompatibleProvider`, which fires at the
MMPay confirmation entry point and swaps in the first provider whose
`supportedCryptoCurrencies` map covers mUSD-on-Monad before the fiat
auto-selection hook reads the selected provider.
@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.

@metamask-cimetamask-ciBot added the team-money-movement issues related to Money Movement features label Aug 1, 2026
@metamask-ci

Copy link
Copy Markdown
Contributor

PR template — items to address before "Ready for review"

Warnings — informational, address before merging:

  • Pre-merge author checklist has unchecked items (e.g. "I've documented my code using JSDoc format if applicable"). Every box must be consciously checked — see docs/readme/ready-for-review.md.

See docs/readme/ready-for-review.md for the full Definition of Ready for Review.

…test name
Adds a comment near the early-return in the fiat auto-selection effect
explaining why isUpdated.current must not be set there. Without this
guard, useEnsureCompatibleProvider's provider switch (which triggers a
re-render) would not cause the effect to retry and the Pay-with row
would stay stuck as a skeleton.
Also renames "does not switch the provider to itself" in the hook's test
suite to "does not switch when the only provider does not support the
asset", which accurately describes what the test actually asserts.
…ller
Replaces the providers.find + setSelectedProvider block in BuildQuote's
Effect 2 with Engine.context.RampsController.setSelectedProviderForAsset,
which owns the same find-and-switch logic inside the controller.
A providers.length === 0 guard keeps providers in the dep array so the
effect still re-runs when providers load or refresh, preserving the
existing re-run semantics. setSelectedProvider is removed from the dep
array since it is no longer referenced in Effect 2 (Effect 1 still uses
it via the destructured hook return).
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

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

E2E Test Selection:
The PR changes affect three functional areas:

  1. BuildQuote.tsx (Ramp buy flow): Refactors provider auto-switching logic to delegate to Engine.context.RampsController.setSelectedProviderForAsset() instead of calling setSelectedProvider directly. Also adds an early return guard when providers.length === 0. This is a behavioral change in the fiat on-ramp quote building flow → SmokeMoney.

  2. useEnsureCompatibleProvider.ts (new hook): New hook that silently switches the selected Ramps provider to one compatible with a given asset ID. Used at the MMPay confirmation entry point to ensure the downstream fiat auto-selection hook sees a compatible provider → SmokeMoney + SmokeConfirmations.

  3. money-account-deposit-info.tsx (confirmation component): Now calls useEnsureCompatibleProvider(MUSD_TOKEN_ASSET_ID_BY_CHAIN[CHAIN_IDS.MONAD]) to ensure a compatible provider is selected before the money account deposit confirmation renders → SmokeConfirmations (confirmation UI) + SmokeMoney (Card Add Funds/deposit flow).

  4. useAutomaticTransactionPayToken.ts (pay token hook): Removes the isUpdated.current latch in the fiat-disabled branch to allow re-runs when useEnsureCompatibleProvider triggers a provider switch. This is a behavioral fix in the pay-with confirmation flow → SmokeConfirmations.

Per SmokeMoney tag description: "Card: home screen, navbar entry, Add Funds (Deposit/Swap paths)..." and "When selecting SmokeMoney for Card Add Funds or similar flows that execute swaps, also select SmokeSwap and SmokeConfirmations." The money account deposit is an Add Funds flow, so SmokeConfirmations is required. SmokeSwap is not directly triggered here as the changes are specifically about provider selection for fiat deposits, not swap execution.

No changes to wallet home/actions entry, so SmokeWalletPlatform is not needed. No changes to network, accounts, or browser flows.

Performance Test Selection:
The changes are focused on provider selection logic (auto-switching between Ramp providers) and a latch fix in the pay token hook. These are correctness/behavioral fixes, not performance-sensitive code paths. No rendering loops, asset loading, account list, onboarding, login, swap execution, or app launch code is modified. No performance test files were changed.

View GitHub Actions results

@saustrie-consensys

Copy link
Copy Markdown
ContributorAuthor

Closing in favour of a new PR that integrates with the core controller method (RampsController:setSelectedProviderForAsset, MetaMask/core#9759). This branch is kept as a reference for the V1 hook-only approach.

1 similar comment
@saustrie-consensys

Copy link
Copy Markdown
ContributorAuthor

Closing in favour of a new PR that integrates with the core controller method (RampsController:setSelectedProviderForAsset, MetaMask/core#9759). This branch is kept as a reference for the V1 hook-only approach.

@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 3, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

size-Mteam-money-movementissues related to Money Movement features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@saustrie-consensys