Skip to content

feat(ramp): consume JSON moneyHeadlessAllProviders payload + thread rampSurface into headless getQuotes - #33362

Merged
saustrie-consensys merged 28 commits into
mainfrom
saustrie/headless-allowlist-surface
Jul 29, 2026
Merged

feat(ramp): consume JSON moneyHeadlessAllProviders payload + thread rampSurface into headless getQuotes#33362
saustrie-consensys merged 28 commits into
mainfrom
saustrie/headless-allowlist-surface

Conversation

@saustrie-consensys

@saustrie-consensys saustrie-consensys commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Description

Phase 2 of Headless Buy all-providers needs QA to force a specific provider mix (for example external-browser-only) with only a LaunchDarkly edit. MetaMask/core#9524 widens the moneyHeadlessAllProviders flag's value contract so the same key also accepts a JSON payload { "enabled": true, "providerIds": [...] }; when provider ids are listed, the controller's widened quote pick drops candidates whose provider is not listed. Old clients coerce the payload to false (native-only), and production serves false everywhere, so serving it cannot enable widening for a client that cannot parse it.

This PR is the mobile half:

  • Bump @metamask/ramps-controller to consume the new contract. No mobile flag-interpretation logic is added: useHeadlessAllProvidersEnabled still delegates to the core helper, so the object form flows through the existing UI availability gates automatically.

Plan doc: app/components/UI/Ramp/headless/PLAN_-_ALL_PROVIDERS_SUPPORT.md, milestone P2.M5 (revision in #32906 records the single-flag JSON design).

Changelog

CHANGELOG entry: null

Related issues

Refs: MetaMask/core#9524

Manual testing steps

  1. In the LaunchDarkly dev environment (or via Settings > Feature flag override once LD serves an object variation), set money-headless-all-providers to { "enabled": true, "providerIds": ["/providers/<external-browser-provider>"] } in a region where an in-app aggregator normally wins on reliability.
  2. Drive an MM Pay money deposit (Money account > Add funds) and confirm the selected quote comes from the forced provider.
  3. Set the flag back to true (or remove providerIds) and confirm selection reverts to the reliability winner.
  4. Set the flag to false (or { "enabled": false }) and confirm the flow is native-only again.

Screenshots/Recordings

Before

N/A (dev/QA-gated quoting behavior; no UI change)

After

Had to allow temporarily fiat transactions in Perps in my local RC, but here's an example of perps allowing Coinbase

ScreenRecording_07-23-2026.10-26-43_1.MP4

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
    • Use these power-user SRPs to import wallets with many accounts and tokens
  • I've instrumented key operations with Sentry traces for production performance metrics

For performance guidelines and tooling, see the Performance Guide.

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
Touches MM Pay fiat availability and region gating behind a feature flag, with a short “optimistic available” window during provider fetch that could briefly show deposit UI before resolving.

Overview
Bumps @metamask/ramps-controller to ^18.0.0 so mobile picks up the updated moneyHeadlessAllProviders contract (JSON payload with featureVersion: '1' and enabled: true, plus optional providerIds handled in core). useHeadlessAllProvidersEnabled still delegates to core’s isHeadlessAllProvidersEnabled; tests now cover enabling object payloads, rejecting stale/malformed values, and keeping local override behavior.

Renames useHasNativeFiatProvider to useHasFiatProvider and updates MM Pay gates (useIsFiatPaymentAvailable, mocks) so naming/docs match flag-aware availability (native-only when the flag is off, any provider class when on).

Fixes a cold provider fetch regression in useRegionHasFiatProvider: when all-providers widening is on and the catalog is still loading with an empty list after a region switch, the hook temporarily treats the region as available so add-funds entry does not disappear until providers load.

Docs/comments only elsewhere (useRampsBuyLimits, useFiatConfirm notes that rampSurface is analytics-only).

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

@saustrie-consensys saustrie-consensys added the team-money-movement issues related to Money Movement features label Jul 15, 2026
@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.

@github-actions github-actions Bot added the pr-not-ready-for-e2e Skip E2E and block merging. Remove this label once the PR is ready to run the E2E tests. label Jul 15, 2026
@metamask-ci

metamask-ci Bot commented Jul 15, 2026

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 tested on Android"). 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.

@socket-security

socket-security Bot commented Jul 15, 2026

Copy link
Copy Markdown

All alerts resolved. Learn more about Socket for GitHub.

This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored.

View full report

@saustrie-consensys saustrie-consensys removed the pr-not-ready-for-e2e Skip E2E and block merging. Remove this label once the PR is ready to run the E2E tests. label Jul 16, 2026
@saustrie-consensys
saustrie-consensys marked this pull request as ready for review July 23, 2026 16:52
@saustrie-consensys
saustrie-consensys requested review from a team as code owners July 23, 2026 16:52
Comment thread app/components/UI/Ramp/hooks/useHeadlessAllProvidersEnabled.ts Outdated
…r fetch

On a region switch RampsController clears providers to [] (persist:false) and
refetches, a window that can last ~24s on a cold switch (observed in NY). The
Money Add-funds gate keyed the Deposit row on regionHasProviderForAsset, which
returns false for an empty list, so the entry vanished for the whole fetch even
in regions that do offer fiat. useRegionHasFiatProvider now treats "widening on
+ still loading + nothing fetched yet" as available, resolving to the real
asset-aware answer once providers arrive. Gated on the flag so the production
native-only default is unchanged.
The hook stopped meaning "has a native provider" once it became flag-aware:
with moneyHeadlessAllProviders on it returns true for aggregator and
external-browser/custom-action providers (PayPal, Coinbase), not just native.
Rename the hook, its file, and its consumers, and correct the stale
"native-only for v0" docstring on useIsFiatPaymentAvailable. Pure rename plus
doc fix; no behavior change.
…lds resolve the lockfile

The type:non-breaking preview overlay rewrote the @metamask/ramps-controller@npm:^17.0.0
descriptor out of the lockfile, so it only resolved when the preview-builds plugin
re-applied the remap at runtime. The iOS RC build's CocoaPods/autolinking install does
not apply that remap, so it failed with 'not present in your lockfile' (run 29539668587).
type:breaking keeps the ^17.0.0 descriptor in the lockfile (the app still resolves to the
preview) so autolinking resolves cleanly; matches how the Phase 1 branch RC-built.
…lback

REVERT BEFORE MERGE - testing unblock only, real fix belongs in core.

With assetsUnifyState enabled, AssetsController:getStateForTransactionPay
only carries prices for assets the account holds, so getTokenFiatRate
returns undefined for the deposit's required token (e.g. Arbitrum USDC
for a Perps deposit) and buildRequiredToken drops it. Both the crypto
and fiat payment routes then die before quoting and the confirmation
shows the blocking no_payment_route_available alert.

Patch: in getTokenFiatRate, when a token is in the STABLECOINS list but
has no market data entry, peg usdRate to 1 and derive fiatRate from the
chain's native currency rates instead of returning undefined. Known
stablecoins with market data, other tokens, and natives are unchanged.
useHeadlessAllProvidersEnabled now validates the payload's
minimumVersion through the shared validatedVersionGatedFeatureFlag util
and inherits the core contract's featureVersion requirement; consumes
ramps-controller preview 17.0.0-preview-40d5fb1e2 carrying the new
helpers (TEMP pin, swap for the released 17.1.0 before merge).
@saustrie-consensys
saustrie-consensys force-pushed the saustrie/headless-allowlist-surface branch from adb6af7 to 03b4221 Compare July 23, 2026 18:53
@github-actions github-actions Bot added the risk:high AI analysis: high risk label Jul 23, 2026
Comment thread app/components/UI/Ramp/hooks/useRampsQuotes.ts Outdated
…ype gap

bridge-controller v77 (installed at top level, used by app selectors) has
`string | null` in TokenAmountValues, while bridge-status-controller v74 was
compiled against bridge-controller v78 which uses plain `string`. This makes
the spread quote object structurally incompatible with submitTx at the type
level even though the values are runtime-equivalent. Use a typed double-cast
(`as unknown as SubmitTxQuoteArg`) to bridge the declared type mismatch.
@saustrie-consensys
saustrie-consensys requested a review from a team as a code owner July 28, 2026 16:13

@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 97ac9b9. Configure here.

Comment thread package.json Outdated
@saustrie-consensys
saustrie-consensys removed the request for review from a team July 28, 2026 17:02
amitabh94
amitabh94 previously approved these changes Jul 28, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

  • Selected E2E tags: SmokeAccounts, SmokeConfirmations, SmokeNetworkAbstractions, SmokeNetworkExpansion, SmokeSwap, SmokeStake, SmokeWalletPlatform, SmokeMoney, SmokePerps, SmokeMultiChainAPI, SmokePredictions, SmokeSeedlessOnboarding, SmokeSeedlessOnboardingExtended, SmokeBrowser, SmokeSnaps, SmokeMMConnect
  • Selected Performance tags: None (no tests recommended)
  • Risk Level: high
  • AI Confidence: 100%
click to see 🤖 AI reasoning details

E2E Test Selection:
Hard rule (controller-version-update): @MetaMask controller package version updated in package.json: @metamask/ramps-controller. Running all tests.

Performance Test Selection:
No performance-sensitive code paths are changed. The changes are limited to: (1) a ramps-controller version bump, (2) a hook rename with expanded provider logic, (3) a loading state guard in useRegionHasFiatProvider, and (4) comment/doc updates. None of these changes affect app launch, login, onboarding, asset loading, account list rendering, swap execution timing, or other performance-measured flows. No performance spec files were changed.

View GitHub Actions results

@sonarqubecloud

Copy link
Copy Markdown

@weitingsun weitingsun 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.

platform CO files LGTM

@jpuri jpuri 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.

Changes to confirmation owned files looks ok.

@saustrie-consensys
saustrie-consensys added this pull request to the merge queue Jul 29, 2026
Merged via the queue into main with commit 9363d18 Jul 29, 2026
135 checks passed
@saustrie-consensys
saustrie-consensys deleted the saustrie/headless-allowlist-surface branch July 29, 2026 13:23
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 29, 2026
@metamask-ci metamask-ci Bot added the release-8.6.0 Issue or pull request that will be included in release 8.6.0 label Jul 29, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

release-8.6.0 Issue or pull request that will be included in release 8.6.0 risk:high AI analysis: high risk size-M team-money-movement issues related to Money Movement features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants