Uh oh!
There was an error while loading. Please reload this page.
fix: switch to compatible provider when MMPay loads with an incompatible UB2 selection - #34162
fix: switch to compatible provider when MMPay loads with an incompatible UB2 selection#34162saustrie-consensys wants to merge 4 commits into
Conversation
… 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.
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. |
PR template — items to address before "Ready for review"Warnings — informational, address before merging:
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).
🔍 Smart E2E Test Selection
click to see 🤖 AI reasoning detailsE2E Test Selection:
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: |
…o controller" This reverts commit 9db9d57.
saustrie-consensys
commented
Aug 3, 2026
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
commented
Aug 3, 2026
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. |
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.selectedvalue carries over. With themoneyHeadlessAllProvidersflag off (production default),useIsFiatPaymentAvailablereturnsfalsefor any non-native provider, which causesuseAutomaticTransactionPayTokento exit its fiat path without settingisUpdated.current. The result is the "Pay with..." row skeleton loading forever.Root cause
useHasNativeFiatProvider(pre-Phase 2) checksselectedProvider?.type === 'native'. An aggregator provider selected in UB2 fails that check. The downstreamuseAutomaticTransactionPayTokenhas an early return at the!isFiatEnabledbranch 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 dispatchessetSelectedProviderto swap in the first compatible provider (using the sameproviderSupportsAssetutility as UB2's BuildQuote tier-1 silent switch). The dispatch triggers a re-render; on that renderisFiatEnabledis nowtrue, the auto-selection effect runs again (it did not latch on the previous run), and the payment method row resolves.The
!isFiatEnabledearly return inuseAutomaticTransactionPayTokenintentionally does not setisUpdated.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 (
moneyHeadlessAllProviderson) 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
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)
trace()for usage andaddTokenfor an examplePre-merge reviewer checklist