Skip to content

feat(ramps-controller): scope-aware in-app provider widening in getQuotes#9353

Merged
saustrie-consensys merged 9 commits into
mainfrom
feat/ramps-controller-in-app-provider-scope
Jul 6, 2026
Merged

feat(ramps-controller): scope-aware in-app provider widening in getQuotes#9353
saustrie-consensys merged 9 commits into
mainfrom
feat/ramps-controller-in-app-provider-scope

Conversation

@saustrie-consensys

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

Copy link
Copy Markdown
Contributor

Explanation

Part of Headless Buy "all providers" support (Phase 1). This adds an opt-in way for a host to widen RampsController.getQuotes from native-only auto-selection to in-app WebView aggregator providers, with no change to callers that pass explicit providers.

  • New optional getProviderScope callback on RampsControllerOptions, plus an exported ProviderScope type ('off' | 'in-app' | 'all'). The callback is read on every getQuotes call, so a host toggle takes effect at runtime. It defaults to 'off' (today's behaviour) when omitted.
  • When the scope is not 'off', the native-only auto-selection path (autoSelectProvider / restrictToKnownOrNativeProviders) widens to every supporting provider and returns the single best in-app quote at success[0]. A private #pickInAppQuote drops external-browser (buyWidget.browser === 'IN_APP_OS_BROWSER') and custom-action quotes, enforces per-provider fiat limits up front, and orders by reliability then price using the server-provided sorted order. It reuses the existing getProviders hydration fallback so an empty catalog cannot silently quote nothing.
  • New optional getDefaultRedirectUrl callback on RampsControllerOptions. On the widened in-app path, when the caller does not pass a redirectUrl, getQuotes uses this default so aggregator quotes carry the buyURL / buyWidget the client needs to open the WebView. An explicit caller redirectUrl always wins, and scope 'off' never injects one. (This closes a gap where MetaMask Pay's quote fetch omits redirectUrl, leaving aggregator quotes without a buy URL.)
  • The default stays native-only, callers that pass explicit providers are unaffected, and providers.selected is never mutated.

This lets a client move the caller that reads getQuotes(...).success[0] onto in-app providers behind its own gate, with no other core changes.

VIDEO IN MOBILE PR that uses this new core version: MetaMask/metamask-mobile#32682

Here's a Google Drive link since Github is uploading this video very slowly: https://drive.google.com/file/d/14Ialq7Tg9Ep0tpCljAle5ttAX92zTPIh/view?usp=sharing

Uploading ScreenRecording_07-06-2026 00-12-51_1.MP4…

References

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Note

Medium Risk
Changes which ramp provider and quote getQuotes returns for gated auto-select callers (fiat purchase flow), though defaults preserve prior native-only behavior and coverage is extensive.

Overview
Adds opt-in Headless Buy Phase 1 behavior so hosts can widen fiat quote auto-selection from native-only to in-app aggregator providers without changing explicit-providers callers.

getProviderScope ('off' | 'in-app' | 'all', default 'off') is read on each getQuotes call. When scope is not 'off' and the caller uses autoSelectProvider or restrictToKnownOrNativeProviders without an explicit providers list, the controller quotes every region/asset-supporting provider, then #pickInAppQuote reduces the response to a single winner at success[0] (for success?.[0] consumers). Under 'in-app', selection skips external-browser (IN_APP_OS_BROWSER), custom-action providers, and quotes outside per-provider fiat limits; ordering follows server sorted (reliability, then price). Scope 'all' keeps external/custom quotes eligible. Empty supporting sets return an empty success list instead of unfiltered service quotes.

getDefaultRedirectUrl fills redirectUrl on that widened path when the caller omits it so aggregator quotes get a usable buyWidget URL; explicit redirectUrl wins and scope 'off' never injects. ProviderScope is exported from the package index.

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

…otes

Add an optional `getProviderScope` callback to `RampsControllerOptions`
(exported `ProviderScope` = 'off' | 'in-app' | 'all', read per getQuotes
call). When the scope is non-'off', the native-only auto-selection path
(autoSelectProvider / restrictToKnownOrNativeProviders) widens to every
supporting provider and returns the best in-app quote at success[0].

`#pickInAppQuote` drops external-browser (buyWidget.browser
'IN_APP_OS_BROWSER') and custom-action quotes, enforces per-provider fiat
limits up front, and orders by reliability then price off `sorted`. It also
reuses the existing getProviders hydration fallback so an empty catalog does
not silently quote nothing.

The default stays native-only, explicit-`providers` callers are untouched,
and providers.selected is never mutated. A host can now bump MM Pay's
getRampsQuote (which reads success[0]) onto in-app providers with no
transaction-pay-controller change.
@saustrie-consensys

Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-preview

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Preview builds have been published. Learn how to use preview builds in other projects.

Expand for full list of packages and versions.
@metamask-previews/account-tree-controller@7.5.3-preview-29a675b
@metamask-previews/accounts-controller@39.0.4-preview-29a675b
@metamask-previews/address-book-controller@7.1.2-preview-29a675b
@metamask-previews/ai-controllers@0.7.0-preview-29a675b
@metamask-previews/analytics-controller@1.2.1-preview-29a675b
@metamask-previews/analytics-data-regulation-controller@0.0.0-preview-29a675b
@metamask-previews/announcement-controller@8.1.0-preview-29a675b
@metamask-previews/app-metadata-controller@2.0.1-preview-29a675b
@metamask-previews/approval-controller@9.0.2-preview-29a675b
@metamask-previews/assets-controller@10.0.1-preview-29a675b
@metamask-previews/assets-controllers@109.3.0-preview-29a675b
@metamask-previews/authenticated-user-storage@3.0.0-preview-29a675b
@metamask-previews/base-controller@9.1.0-preview-29a675b
@metamask-previews/base-data-service@0.1.3-preview-29a675b
@metamask-previews/bitcoin-regtest-up@1.0.0-preview-29a675b
@metamask-previews/bridge-controller@77.3.1-preview-29a675b
@metamask-previews/bridge-status-controller@74.0.1-preview-29a675b
@metamask-previews/build-utils@3.0.4-preview-29a675b
@metamask-previews/chain-agnostic-permission@1.6.2-preview-29a675b
@metamask-previews/chomp-api-service@3.1.0-preview-29a675b
@metamask-previews/claims-controller@0.5.3-preview-29a675b
@metamask-previews/client-controller@1.0.1-preview-29a675b
@metamask-previews/compliance-controller@2.1.0-preview-29a675b
@metamask-previews/composable-controller@12.0.1-preview-29a675b
@metamask-previews/config-registry-controller@0.4.1-preview-29a675b
@metamask-previews/connectivity-controller@0.2.0-preview-29a675b
@metamask-previews/controller-utils@12.3.0-preview-29a675b
@metamask-previews/core-backend@6.5.0-preview-29a675b
@metamask-previews/delegation-controller@3.0.2-preview-29a675b
@metamask-previews/earn-controller@12.2.2-preview-29a675b
@metamask-previews/eip-5792-middleware@3.0.4-preview-29a675b
@metamask-previews/eip-7702-internal-rpc-middleware@0.1.1-preview-29a675b
@metamask-previews/eip1193-permission-middleware@2.0.1-preview-29a675b
@metamask-previews/ens-controller@19.1.5-preview-29a675b
@metamask-previews/eth-block-tracker@15.0.1-preview-29a675b
@metamask-previews/eth-json-rpc-middleware@23.1.3-preview-29a675b
@metamask-previews/eth-json-rpc-provider@6.0.1-preview-29a675b
@metamask-previews/foundryup@1.0.1-preview-29a675b
@metamask-previews/gas-fee-controller@26.2.4-preview-29a675b
@metamask-previews/gator-permissions-controller@4.2.2-preview-29a675b
@metamask-previews/geolocation-controller@0.1.3-preview-29a675b
@metamask-previews/java-tron-up@1.0.0-preview-29a675b
@metamask-previews/json-rpc-engine@10.5.0-preview-29a675b
@metamask-previews/json-rpc-middleware-stream@8.0.8-preview-29a675b
@metamask-previews/keyring-controller@27.1.0-preview-29a675b
@metamask-previews/local-node-utils@1.0.0-preview-29a675b
@metamask-previews/logging-controller@8.0.2-preview-29a675b
@metamask-previews/message-manager@14.1.2-preview-29a675b
@metamask-previews/messenger@1.2.0-preview-29a675b
@metamask-previews/messenger-cli@0.2.0-preview-29a675b
@metamask-previews/money-account-balance-service@2.1.2-preview-29a675b
@metamask-previews/money-account-controller@0.3.3-preview-29a675b
@metamask-previews/money-account-upgrade-controller@2.2.1-preview-29a675b
@metamask-previews/multichain-account-service@11.1.0-preview-29a675b
@metamask-previews/multichain-api-middleware@4.0.0-preview-29a675b
@metamask-previews/multichain-network-controller@3.2.1-preview-29a675b
@metamask-previews/multichain-transactions-controller@7.1.1-preview-29a675b
@metamask-previews/name-controller@9.1.2-preview-29a675b
@metamask-previews/network-controller@34.0.0-preview-29a675b
@metamask-previews/network-enablement-controller@5.4.1-preview-29a675b
@metamask-previews/notification-services-controller@24.3.0-preview-29a675b
@metamask-previews/passkey-controller@2.0.1-preview-29a675b
@metamask-previews/permission-controller@13.1.1-preview-29a675b
@metamask-previews/permission-log-controller@5.1.0-preview-29a675b
@metamask-previews/perps-controller@9.0.0-preview-29a675b
@metamask-previews/phishing-controller@17.2.0-preview-29a675b
@metamask-previews/platform-api-docs@0.0.0-preview-29a675b
@metamask-previews/polling-controller@16.0.8-preview-29a675b
@metamask-previews/preferences-controller@23.1.0-preview-29a675b
@metamask-previews/profile-metrics-controller@4.0.1-preview-29a675b
@metamask-previews/profile-sync-controller@28.2.0-preview-29a675b
@metamask-previews/ramps-controller@15.0.0-preview-29a675b
@metamask-previews/rate-limit-controller@7.0.1-preview-29a675b
@metamask-previews/react-data-query@0.2.1-preview-29a675b
@metamask-previews/remote-feature-flag-controller@4.2.2-preview-29a675b
@metamask-previews/sample-controllers@5.0.3-preview-29a675b
@metamask-previews/seedless-onboarding-controller@10.0.3-preview-29a675b
@metamask-previews/selected-network-controller@26.1.5-preview-29a675b
@metamask-previews/shield-controller@5.1.2-preview-29a675b
@metamask-previews/signature-controller@39.2.7-preview-29a675b
@metamask-previews/smart-transactions-controller@24.2.4-preview-29a675b
@metamask-previews/snap-account-service@1.0.0-preview-29a675b
@metamask-previews/social-controllers@2.3.1-preview-29a675b
@metamask-previews/solana-test-validator-up@1.0.0-preview-29a675b
@metamask-previews/stellar-quickstart-up@0.0.0-preview-29a675b
@metamask-previews/storage-service@1.0.2-preview-29a675b
@metamask-previews/subscription-controller@6.2.0-preview-29a675b
@metamask-previews/transaction-controller@68.2.2-preview-29a675b
@metamask-previews/transaction-pay-controller@23.17.3-preview-29a675b
@metamask-previews/user-operation-controller@41.2.6-preview-29a675b
@metamask-previews/wallet@6.0.0-preview-29a675b
@metamask-previews/wallet-cli@0.0.0-preview-29a675b

… link

- Add tests for the remaining getQuotes/#pickInAppQuote branches to restore
  the package's 100% coverage: inline isCustomAction exclusion, sort-order
  fall-through to the first candidate, scope `all` keeping external/custom
  quotes, restrict-only widening with a fitting limit, and amount-above-max
  limit skip.
- Flatten the CHANGELOG entry so the PR link sits on the top-level bullet
  (the check-changelog action requires each entry to link to the PR).
@saustrie-consensys

Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-preview

…testing

REVERT before release. Forces #pickInAppQuote to skip native providers so a
non-native in-app WebView provider is the one suggested during physical-device
testing of the Phase 1 in-app flow. istanbul-ignored to keep coverage at 100%.
@saustrie-consensys

Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-preview

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Preview builds have been published. Learn how to use preview builds in other projects.

Expand for full list of packages and versions.
@metamask-previews/account-tree-controller@7.5.3-preview-2855dbf4e
@metamask-previews/accounts-controller@39.0.4-preview-2855dbf4e
@metamask-previews/address-book-controller@7.1.2-preview-2855dbf4e
@metamask-previews/ai-controllers@0.7.0-preview-2855dbf4e
@metamask-previews/analytics-controller@1.2.1-preview-2855dbf4e
@metamask-previews/analytics-data-regulation-controller@0.0.0-preview-2855dbf4e
@metamask-previews/announcement-controller@8.1.0-preview-2855dbf4e
@metamask-previews/app-metadata-controller@2.0.1-preview-2855dbf4e
@metamask-previews/approval-controller@9.0.2-preview-2855dbf4e
@metamask-previews/assets-controller@10.0.1-preview-2855dbf4e
@metamask-previews/assets-controllers@109.3.0-preview-2855dbf4e
@metamask-previews/authenticated-user-storage@3.0.0-preview-2855dbf4e
@metamask-previews/base-controller@9.1.0-preview-2855dbf4e
@metamask-previews/base-data-service@0.1.3-preview-2855dbf4e
@metamask-previews/bitcoin-regtest-up@1.0.0-preview-2855dbf4e
@metamask-previews/bridge-controller@77.3.1-preview-2855dbf4e
@metamask-previews/bridge-status-controller@74.0.1-preview-2855dbf4e
@metamask-previews/build-utils@3.0.4-preview-2855dbf4e
@metamask-previews/chain-agnostic-permission@1.6.2-preview-2855dbf4e
@metamask-previews/chomp-api-service@3.1.0-preview-2855dbf4e
@metamask-previews/claims-controller@0.5.3-preview-2855dbf4e
@metamask-previews/client-controller@1.0.1-preview-2855dbf4e
@metamask-previews/compliance-controller@2.1.0-preview-2855dbf4e
@metamask-previews/composable-controller@12.0.1-preview-2855dbf4e
@metamask-previews/config-registry-controller@0.4.1-preview-2855dbf4e
@metamask-previews/connectivity-controller@0.2.0-preview-2855dbf4e
@metamask-previews/controller-utils@12.3.0-preview-2855dbf4e
@metamask-previews/core-backend@6.5.0-preview-2855dbf4e
@metamask-previews/delegation-controller@3.0.2-preview-2855dbf4e
@metamask-previews/earn-controller@12.2.2-preview-2855dbf4e
@metamask-previews/eip-5792-middleware@3.0.4-preview-2855dbf4e
@metamask-previews/eip-7702-internal-rpc-middleware@0.1.1-preview-2855dbf4e
@metamask-previews/eip1193-permission-middleware@2.0.1-preview-2855dbf4e
@metamask-previews/ens-controller@19.1.5-preview-2855dbf4e
@metamask-previews/eth-block-tracker@15.0.1-preview-2855dbf4e
@metamask-previews/eth-json-rpc-middleware@23.1.3-preview-2855dbf4e
@metamask-previews/eth-json-rpc-provider@6.0.1-preview-2855dbf4e
@metamask-previews/foundryup@1.0.1-preview-2855dbf4e
@metamask-previews/gas-fee-controller@26.2.4-preview-2855dbf4e
@metamask-previews/gator-permissions-controller@4.2.2-preview-2855dbf4e
@metamask-previews/geolocation-controller@0.1.3-preview-2855dbf4e
@metamask-previews/java-tron-up@1.0.0-preview-2855dbf4e
@metamask-previews/json-rpc-engine@10.5.0-preview-2855dbf4e
@metamask-previews/json-rpc-middleware-stream@8.0.8-preview-2855dbf4e
@metamask-previews/keyring-controller@27.1.0-preview-2855dbf4e
@metamask-previews/local-node-utils@1.0.0-preview-2855dbf4e
@metamask-previews/logging-controller@8.0.2-preview-2855dbf4e
@metamask-previews/message-manager@14.1.2-preview-2855dbf4e
@metamask-previews/messenger@1.2.0-preview-2855dbf4e
@metamask-previews/messenger-cli@0.2.0-preview-2855dbf4e
@metamask-previews/money-account-balance-service@2.1.2-preview-2855dbf4e
@metamask-previews/money-account-controller@0.3.3-preview-2855dbf4e
@metamask-previews/money-account-upgrade-controller@2.2.1-preview-2855dbf4e
@metamask-previews/multichain-account-service@11.1.0-preview-2855dbf4e
@metamask-previews/multichain-api-middleware@4.0.0-preview-2855dbf4e
@metamask-previews/multichain-network-controller@3.2.1-preview-2855dbf4e
@metamask-previews/multichain-transactions-controller@7.1.1-preview-2855dbf4e
@metamask-previews/name-controller@9.1.2-preview-2855dbf4e
@metamask-previews/network-controller@34.0.0-preview-2855dbf4e
@metamask-previews/network-enablement-controller@5.4.1-preview-2855dbf4e
@metamask-previews/notification-services-controller@24.3.0-preview-2855dbf4e
@metamask-previews/passkey-controller@2.0.1-preview-2855dbf4e
@metamask-previews/permission-controller@13.1.1-preview-2855dbf4e
@metamask-previews/permission-log-controller@5.1.0-preview-2855dbf4e
@metamask-previews/perps-controller@9.0.0-preview-2855dbf4e
@metamask-previews/phishing-controller@17.2.0-preview-2855dbf4e
@metamask-previews/platform-api-docs@0.0.0-preview-2855dbf4e
@metamask-previews/polling-controller@16.0.8-preview-2855dbf4e
@metamask-previews/preferences-controller@23.1.0-preview-2855dbf4e
@metamask-previews/profile-metrics-controller@4.0.1-preview-2855dbf4e
@metamask-previews/profile-sync-controller@28.2.0-preview-2855dbf4e
@metamask-previews/ramps-controller@15.0.0-preview-2855dbf4e
@metamask-previews/rate-limit-controller@7.0.1-preview-2855dbf4e
@metamask-previews/react-data-query@0.2.1-preview-2855dbf4e
@metamask-previews/remote-feature-flag-controller@4.2.2-preview-2855dbf4e
@metamask-previews/sample-controllers@5.0.3-preview-2855dbf4e
@metamask-previews/seedless-onboarding-controller@10.0.3-preview-2855dbf4e
@metamask-previews/selected-network-controller@26.1.5-preview-2855dbf4e
@metamask-previews/shield-controller@5.1.2-preview-2855dbf4e
@metamask-previews/signature-controller@39.2.7-preview-2855dbf4e
@metamask-previews/smart-transactions-controller@24.2.4-preview-2855dbf4e
@metamask-previews/snap-account-service@1.0.0-preview-2855dbf4e
@metamask-previews/social-controllers@2.3.1-preview-2855dbf4e
@metamask-previews/solana-test-validator-up@1.0.0-preview-2855dbf4e
@metamask-previews/stellar-quickstart-up@0.0.0-preview-2855dbf4e
@metamask-previews/storage-service@1.0.2-preview-2855dbf4e
@metamask-previews/subscription-controller@6.2.0-preview-2855dbf4e
@metamask-previews/transaction-controller@68.2.2-preview-2855dbf4e
@metamask-previews/transaction-pay-controller@23.17.3-preview-2855dbf4e
@metamask-previews/user-operation-controller@41.2.6-preview-2855dbf4e
@metamask-previews/wallet@6.0.0-preview-2855dbf4e
@metamask-previews/wallet-cli@0.0.0-preview-2855dbf4e

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Preview builds have been published. Learn how to use preview builds in other projects.

Expand for full list of packages and versions.
@metamask-previews/account-tree-controller@7.5.3-preview-9e722dac3
@metamask-previews/accounts-controller@39.0.4-preview-9e722dac3
@metamask-previews/address-book-controller@7.1.2-preview-9e722dac3
@metamask-previews/ai-controllers@0.7.0-preview-9e722dac3
@metamask-previews/analytics-controller@1.2.1-preview-9e722dac3
@metamask-previews/analytics-data-regulation-controller@0.0.0-preview-9e722dac3
@metamask-previews/announcement-controller@8.1.0-preview-9e722dac3
@metamask-previews/app-metadata-controller@2.0.1-preview-9e722dac3
@metamask-previews/approval-controller@9.0.2-preview-9e722dac3
@metamask-previews/assets-controller@10.0.1-preview-9e722dac3
@metamask-previews/assets-controllers@109.3.0-preview-9e722dac3
@metamask-previews/authenticated-user-storage@3.0.0-preview-9e722dac3
@metamask-previews/base-controller@9.1.0-preview-9e722dac3
@metamask-previews/base-data-service@0.1.3-preview-9e722dac3
@metamask-previews/bitcoin-regtest-up@1.0.0-preview-9e722dac3
@metamask-previews/bridge-controller@77.3.1-preview-9e722dac3
@metamask-previews/bridge-status-controller@74.0.1-preview-9e722dac3
@metamask-previews/build-utils@3.0.4-preview-9e722dac3
@metamask-previews/chain-agnostic-permission@1.6.2-preview-9e722dac3
@metamask-previews/chomp-api-service@3.1.0-preview-9e722dac3
@metamask-previews/claims-controller@0.5.3-preview-9e722dac3
@metamask-previews/client-controller@1.0.1-preview-9e722dac3
@metamask-previews/compliance-controller@2.1.0-preview-9e722dac3
@metamask-previews/composable-controller@12.0.1-preview-9e722dac3
@metamask-previews/config-registry-controller@0.4.1-preview-9e722dac3
@metamask-previews/connectivity-controller@0.2.0-preview-9e722dac3
@metamask-previews/controller-utils@12.3.0-preview-9e722dac3
@metamask-previews/core-backend@6.5.0-preview-9e722dac3
@metamask-previews/delegation-controller@3.0.2-preview-9e722dac3
@metamask-previews/earn-controller@12.2.2-preview-9e722dac3
@metamask-previews/eip-5792-middleware@3.0.4-preview-9e722dac3
@metamask-previews/eip-7702-internal-rpc-middleware@0.1.1-preview-9e722dac3
@metamask-previews/eip1193-permission-middleware@2.0.1-preview-9e722dac3
@metamask-previews/ens-controller@19.1.5-preview-9e722dac3
@metamask-previews/eth-block-tracker@15.0.1-preview-9e722dac3
@metamask-previews/eth-json-rpc-middleware@23.1.3-preview-9e722dac3
@metamask-previews/eth-json-rpc-provider@6.0.1-preview-9e722dac3
@metamask-previews/foundryup@1.0.1-preview-9e722dac3
@metamask-previews/gas-fee-controller@26.2.4-preview-9e722dac3
@metamask-previews/gator-permissions-controller@4.2.2-preview-9e722dac3
@metamask-previews/geolocation-controller@0.1.3-preview-9e722dac3
@metamask-previews/java-tron-up@1.0.0-preview-9e722dac3
@metamask-previews/json-rpc-engine@10.5.0-preview-9e722dac3
@metamask-previews/json-rpc-middleware-stream@8.0.8-preview-9e722dac3
@metamask-previews/keyring-controller@27.1.0-preview-9e722dac3
@metamask-previews/local-node-utils@1.0.0-preview-9e722dac3
@metamask-previews/logging-controller@8.0.2-preview-9e722dac3
@metamask-previews/message-manager@14.1.2-preview-9e722dac3
@metamask-previews/messenger@1.2.0-preview-9e722dac3
@metamask-previews/messenger-cli@0.2.0-preview-9e722dac3
@metamask-previews/money-account-balance-service@2.1.2-preview-9e722dac3
@metamask-previews/money-account-controller@0.3.3-preview-9e722dac3
@metamask-previews/money-account-upgrade-controller@2.2.1-preview-9e722dac3
@metamask-previews/multichain-account-service@11.1.0-preview-9e722dac3
@metamask-previews/multichain-api-middleware@4.0.0-preview-9e722dac3
@metamask-previews/multichain-network-controller@3.2.1-preview-9e722dac3
@metamask-previews/multichain-transactions-controller@7.1.1-preview-9e722dac3
@metamask-previews/name-controller@9.1.2-preview-9e722dac3
@metamask-previews/network-controller@34.0.0-preview-9e722dac3
@metamask-previews/network-enablement-controller@5.4.1-preview-9e722dac3
@metamask-previews/notification-services-controller@24.3.0-preview-9e722dac3
@metamask-previews/passkey-controller@2.0.1-preview-9e722dac3
@metamask-previews/permission-controller@13.1.1-preview-9e722dac3
@metamask-previews/permission-log-controller@5.1.0-preview-9e722dac3
@metamask-previews/perps-controller@9.0.0-preview-9e722dac3
@metamask-previews/phishing-controller@17.2.0-preview-9e722dac3
@metamask-previews/platform-api-docs@0.0.0-preview-9e722dac3
@metamask-previews/polling-controller@16.0.8-preview-9e722dac3
@metamask-previews/preferences-controller@23.1.0-preview-9e722dac3
@metamask-previews/profile-metrics-controller@4.0.1-preview-9e722dac3
@metamask-previews/profile-sync-controller@28.2.0-preview-9e722dac3
@metamask-previews/ramps-controller@15.0.0-preview-9e722dac3
@metamask-previews/rate-limit-controller@7.0.1-preview-9e722dac3
@metamask-previews/react-data-query@0.2.1-preview-9e722dac3
@metamask-previews/remote-feature-flag-controller@4.2.2-preview-9e722dac3
@metamask-previews/sample-controllers@5.0.3-preview-9e722dac3
@metamask-previews/seedless-onboarding-controller@10.0.3-preview-9e722dac3
@metamask-previews/selected-network-controller@26.1.5-preview-9e722dac3
@metamask-previews/shield-controller@5.1.2-preview-9e722dac3
@metamask-previews/signature-controller@39.2.7-preview-9e722dac3
@metamask-previews/smart-transactions-controller@24.2.4-preview-9e722dac3
@metamask-previews/snap-account-service@1.0.0-preview-9e722dac3
@metamask-previews/social-controllers@2.3.1-preview-9e722dac3
@metamask-previews/solana-test-validator-up@1.0.0-preview-9e722dac3
@metamask-previews/stellar-quickstart-up@0.0.0-preview-9e722dac3
@metamask-previews/storage-service@1.0.2-preview-9e722dac3
@metamask-previews/subscription-controller@6.2.0-preview-9e722dac3
@metamask-previews/transaction-controller@68.2.2-preview-9e722dac3
@metamask-previews/transaction-pay-controller@23.17.3-preview-9e722dac3
@metamask-previews/user-operation-controller@41.2.6-preview-9e722dac3
@metamask-previews/wallet@6.0.0-preview-9e722dac3
@metamask-previews/wallet-cli@0.0.0-preview-9e722dac3

Fixes the lint:misc:check failure. Formatting only, no behaviour change.
…-in-app-provider-scope

# Conflicts:
#	packages/ramps-controller/CHANGELOG.md
Remove the temporary device-testing exclusion of native providers from
#pickInAppQuote. It dead-ended native-only assets in prefer-native regions
(the on-ramp API dedups the aggregator away, leaving only Transak Native, which
the block then excluded -> zero quotes). Add a regression test asserting native
is selected when it ranks first among in-app candidates.
@saustrie-consensys

Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-preview

@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Preview builds have been published. Learn how to use preview builds in other projects.

Expand for full list of packages and versions.
@metamask-previews/account-tree-controller@7.5.3-preview-c52e72214
@metamask-previews/accounts-controller@39.0.4-preview-c52e72214
@metamask-previews/address-book-controller@7.1.2-preview-c52e72214
@metamask-previews/ai-controllers@0.7.0-preview-c52e72214
@metamask-previews/analytics-controller@1.2.1-preview-c52e72214
@metamask-previews/analytics-data-regulation-controller@0.0.0-preview-c52e72214
@metamask-previews/announcement-controller@8.1.0-preview-c52e72214
@metamask-previews/app-metadata-controller@2.0.1-preview-c52e72214
@metamask-previews/approval-controller@9.0.2-preview-c52e72214
@metamask-previews/assets-controller@10.0.1-preview-c52e72214
@metamask-previews/assets-controllers@109.3.0-preview-c52e72214
@metamask-previews/authenticated-user-storage@3.0.0-preview-c52e72214
@metamask-previews/base-controller@9.1.0-preview-c52e72214
@metamask-previews/base-data-service@0.1.3-preview-c52e72214
@metamask-previews/bitcoin-regtest-up@1.0.0-preview-c52e72214
@metamask-previews/bridge-controller@77.3.2-preview-c52e72214
@metamask-previews/bridge-status-controller@74.0.2-preview-c52e72214
@metamask-previews/build-utils@3.0.4-preview-c52e72214
@metamask-previews/chain-agnostic-permission@1.6.2-preview-c52e72214
@metamask-previews/chomp-api-service@3.1.0-preview-c52e72214
@metamask-previews/claims-controller@0.5.3-preview-c52e72214
@metamask-previews/client-controller@1.0.1-preview-c52e72214
@metamask-previews/client-utils@0.0.0-preview-c52e72214
@metamask-previews/compliance-controller@2.1.0-preview-c52e72214
@metamask-previews/composable-controller@12.0.1-preview-c52e72214
@metamask-previews/config-registry-controller@0.4.1-preview-c52e72214
@metamask-previews/connectivity-controller@0.2.0-preview-c52e72214
@metamask-previews/controller-utils@12.3.0-preview-c52e72214
@metamask-previews/core-backend@6.5.0-preview-c52e72214
@metamask-previews/delegation-controller@3.0.2-preview-c52e72214
@metamask-previews/earn-controller@12.2.2-preview-c52e72214
@metamask-previews/eip-5792-middleware@3.0.4-preview-c52e72214
@metamask-previews/eip-7702-internal-rpc-middleware@0.1.1-preview-c52e72214
@metamask-previews/eip1193-permission-middleware@2.0.1-preview-c52e72214
@metamask-previews/ens-controller@19.1.5-preview-c52e72214
@metamask-previews/eth-block-tracker@15.0.1-preview-c52e72214
@metamask-previews/eth-json-rpc-middleware@23.1.3-preview-c52e72214
@metamask-previews/eth-json-rpc-provider@6.0.1-preview-c52e72214
@metamask-previews/foundryup@1.0.1-preview-c52e72214
@metamask-previews/gas-fee-controller@26.2.4-preview-c52e72214
@metamask-previews/gator-permissions-controller@4.2.2-preview-c52e72214
@metamask-previews/geolocation-controller@0.1.3-preview-c52e72214
@metamask-previews/java-tron-up@1.0.0-preview-c52e72214
@metamask-previews/json-rpc-engine@10.5.0-preview-c52e72214
@metamask-previews/json-rpc-middleware-stream@8.0.8-preview-c52e72214
@metamask-previews/keyring-controller@27.1.0-preview-c52e72214
@metamask-previews/local-node-utils@1.0.0-preview-c52e72214
@metamask-previews/logging-controller@8.0.2-preview-c52e72214
@metamask-previews/message-manager@14.1.2-preview-c52e72214
@metamask-previews/messenger@1.2.0-preview-c52e72214
@metamask-previews/messenger-cli@0.2.0-preview-c52e72214
@metamask-previews/money-account-balance-service@2.1.2-preview-c52e72214
@metamask-previews/money-account-controller@0.3.3-preview-c52e72214
@metamask-previews/money-account-upgrade-controller@2.2.1-preview-c52e72214
@metamask-previews/multichain-account-service@11.1.0-preview-c52e72214
@metamask-previews/multichain-api-middleware@4.0.0-preview-c52e72214
@metamask-previews/multichain-network-controller@3.2.1-preview-c52e72214
@metamask-previews/multichain-transactions-controller@7.1.1-preview-c52e72214
@metamask-previews/name-controller@9.1.2-preview-c52e72214
@metamask-previews/network-controller@34.0.0-preview-c52e72214
@metamask-previews/network-enablement-controller@5.4.1-preview-c52e72214
@metamask-previews/notification-services-controller@24.3.0-preview-c52e72214
@metamask-previews/passkey-controller@2.0.1-preview-c52e72214
@metamask-previews/permission-controller@13.1.1-preview-c52e72214
@metamask-previews/permission-log-controller@5.1.0-preview-c52e72214
@metamask-previews/perps-controller@9.2.0-preview-c52e72214
@metamask-previews/phishing-controller@17.2.0-preview-c52e72214
@metamask-previews/platform-api-docs@0.0.0-preview-c52e72214
@metamask-previews/polling-controller@16.0.8-preview-c52e72214
@metamask-previews/preferences-controller@23.1.0-preview-c52e72214
@metamask-previews/profile-metrics-controller@4.0.1-preview-c52e72214
@metamask-previews/profile-sync-controller@28.2.0-preview-c52e72214
@metamask-previews/ramps-controller@15.0.0-preview-c52e72214
@metamask-previews/rate-limit-controller@7.0.1-preview-c52e72214
@metamask-previews/react-data-query@0.2.1-preview-c52e72214
@metamask-previews/remote-feature-flag-controller@4.2.2-preview-c52e72214
@metamask-previews/sample-controllers@5.0.3-preview-c52e72214
@metamask-previews/seedless-onboarding-controller@10.0.3-preview-c52e72214
@metamask-previews/selected-network-controller@26.1.5-preview-c52e72214
@metamask-previews/shield-controller@5.1.2-preview-c52e72214
@metamask-previews/signature-controller@39.2.7-preview-c52e72214
@metamask-previews/smart-transactions-controller@24.2.4-preview-c52e72214
@metamask-previews/snap-account-service@1.0.0-preview-c52e72214
@metamask-previews/social-controllers@2.3.1-preview-c52e72214
@metamask-previews/solana-test-validator-up@1.0.0-preview-c52e72214
@metamask-previews/stellar-quickstart-up@0.0.0-preview-c52e72214
@metamask-previews/storage-service@1.0.2-preview-c52e72214
@metamask-previews/subscription-controller@6.2.0-preview-c52e72214
@metamask-previews/transaction-controller@68.2.2-preview-c52e72214
@metamask-previews/transaction-pay-controller@23.17.4-preview-c52e72214
@metamask-previews/user-operation-controller@41.2.6-preview-c52e72214
@metamask-previews/wallet@6.0.0-preview-c52e72214
@metamask-previews/wallet-cli@0.0.0-preview-c52e72214

…in-app path

Add an optional getDefaultRedirectUrl callback. When getQuotes widens to in-app
providers and the caller omits redirectUrl, forward this default so aggregator
quotes carry the buyURL/buyWidget the client needs to open the in-app WebView.
An explicit caller redirectUrl always wins; scope 'off' never injects a default.
@saustrie-consensys

Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-preview

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Preview builds have been published. Learn how to use preview builds in other projects.

Expand for full list of packages and versions.
@metamask-previews/account-tree-controller@7.5.3-preview-9e8ad9c32
@metamask-previews/accounts-controller@39.0.4-preview-9e8ad9c32
@metamask-previews/address-book-controller@7.1.2-preview-9e8ad9c32
@metamask-previews/ai-controllers@0.7.0-preview-9e8ad9c32
@metamask-previews/analytics-controller@1.2.1-preview-9e8ad9c32
@metamask-previews/analytics-data-regulation-controller@0.0.0-preview-9e8ad9c32
@metamask-previews/announcement-controller@8.1.0-preview-9e8ad9c32
@metamask-previews/app-metadata-controller@2.0.1-preview-9e8ad9c32
@metamask-previews/approval-controller@9.0.2-preview-9e8ad9c32
@metamask-previews/assets-controller@10.0.1-preview-9e8ad9c32
@metamask-previews/assets-controllers@109.3.0-preview-9e8ad9c32
@metamask-previews/authenticated-user-storage@3.0.0-preview-9e8ad9c32
@metamask-previews/base-controller@9.1.0-preview-9e8ad9c32
@metamask-previews/base-data-service@0.1.3-preview-9e8ad9c32
@metamask-previews/bitcoin-regtest-up@1.0.0-preview-9e8ad9c32
@metamask-previews/bridge-controller@77.3.2-preview-9e8ad9c32
@metamask-previews/bridge-status-controller@74.0.2-preview-9e8ad9c32
@metamask-previews/build-utils@3.0.4-preview-9e8ad9c32
@metamask-previews/chain-agnostic-permission@1.6.2-preview-9e8ad9c32
@metamask-previews/chomp-api-service@3.1.0-preview-9e8ad9c32
@metamask-previews/claims-controller@0.5.3-preview-9e8ad9c32
@metamask-previews/client-controller@1.0.1-preview-9e8ad9c32
@metamask-previews/client-utils@0.0.0-preview-9e8ad9c32
@metamask-previews/compliance-controller@2.1.0-preview-9e8ad9c32
@metamask-previews/composable-controller@12.0.1-preview-9e8ad9c32
@metamask-previews/config-registry-controller@0.4.1-preview-9e8ad9c32
@metamask-previews/connectivity-controller@0.2.0-preview-9e8ad9c32
@metamask-previews/controller-utils@12.3.0-preview-9e8ad9c32
@metamask-previews/core-backend@6.5.0-preview-9e8ad9c32
@metamask-previews/delegation-controller@3.0.2-preview-9e8ad9c32
@metamask-previews/earn-controller@12.2.2-preview-9e8ad9c32
@metamask-previews/eip-5792-middleware@3.0.4-preview-9e8ad9c32
@metamask-previews/eip-7702-internal-rpc-middleware@0.1.1-preview-9e8ad9c32
@metamask-previews/eip1193-permission-middleware@2.0.1-preview-9e8ad9c32
@metamask-previews/ens-controller@19.1.5-preview-9e8ad9c32
@metamask-previews/eth-block-tracker@15.0.1-preview-9e8ad9c32
@metamask-previews/eth-json-rpc-middleware@23.1.3-preview-9e8ad9c32
@metamask-previews/eth-json-rpc-provider@6.0.1-preview-9e8ad9c32
@metamask-previews/foundryup@1.0.1-preview-9e8ad9c32
@metamask-previews/gas-fee-controller@26.2.4-preview-9e8ad9c32
@metamask-previews/gator-permissions-controller@4.2.2-preview-9e8ad9c32
@metamask-previews/geolocation-controller@0.1.3-preview-9e8ad9c32
@metamask-previews/java-tron-up@1.0.0-preview-9e8ad9c32
@metamask-previews/json-rpc-engine@10.5.0-preview-9e8ad9c32
@metamask-previews/json-rpc-middleware-stream@8.0.8-preview-9e8ad9c32
@metamask-previews/keyring-controller@27.1.0-preview-9e8ad9c32
@metamask-previews/local-node-utils@1.0.0-preview-9e8ad9c32
@metamask-previews/logging-controller@8.0.2-preview-9e8ad9c32
@metamask-previews/message-manager@14.1.2-preview-9e8ad9c32
@metamask-previews/messenger@1.2.0-preview-9e8ad9c32
@metamask-previews/messenger-cli@0.2.0-preview-9e8ad9c32
@metamask-previews/money-account-balance-service@2.1.2-preview-9e8ad9c32
@metamask-previews/money-account-controller@0.3.3-preview-9e8ad9c32
@metamask-previews/money-account-upgrade-controller@2.2.1-preview-9e8ad9c32
@metamask-previews/multichain-account-service@11.1.0-preview-9e8ad9c32
@metamask-previews/multichain-api-middleware@4.0.0-preview-9e8ad9c32
@metamask-previews/multichain-network-controller@3.2.1-preview-9e8ad9c32
@metamask-previews/multichain-transactions-controller@7.1.1-preview-9e8ad9c32
@metamask-previews/name-controller@9.1.2-preview-9e8ad9c32
@metamask-previews/network-controller@34.0.0-preview-9e8ad9c32
@metamask-previews/network-enablement-controller@5.4.1-preview-9e8ad9c32
@metamask-previews/notification-services-controller@24.3.0-preview-9e8ad9c32
@metamask-previews/passkey-controller@2.0.1-preview-9e8ad9c32
@metamask-previews/permission-controller@13.1.1-preview-9e8ad9c32
@metamask-previews/permission-log-controller@5.1.0-preview-9e8ad9c32
@metamask-previews/perps-controller@9.2.0-preview-9e8ad9c32
@metamask-previews/phishing-controller@17.2.0-preview-9e8ad9c32
@metamask-previews/platform-api-docs@0.0.0-preview-9e8ad9c32
@metamask-previews/polling-controller@16.0.8-preview-9e8ad9c32
@metamask-previews/preferences-controller@23.1.0-preview-9e8ad9c32
@metamask-previews/profile-metrics-controller@4.0.1-preview-9e8ad9c32
@metamask-previews/profile-sync-controller@28.2.0-preview-9e8ad9c32
@metamask-previews/ramps-controller@15.0.0-preview-9e8ad9c32
@metamask-previews/rate-limit-controller@7.0.1-preview-9e8ad9c32
@metamask-previews/react-data-query@0.2.1-preview-9e8ad9c32
@metamask-previews/remote-feature-flag-controller@4.2.2-preview-9e8ad9c32
@metamask-previews/sample-controllers@5.0.3-preview-9e8ad9c32
@metamask-previews/seedless-onboarding-controller@10.0.3-preview-9e8ad9c32
@metamask-previews/selected-network-controller@26.1.5-preview-9e8ad9c32
@metamask-previews/shield-controller@5.1.2-preview-9e8ad9c32
@metamask-previews/signature-controller@39.2.7-preview-9e8ad9c32
@metamask-previews/smart-transactions-controller@24.2.4-preview-9e8ad9c32
@metamask-previews/snap-account-service@1.0.0-preview-9e8ad9c32
@metamask-previews/social-controllers@2.3.1-preview-9e8ad9c32
@metamask-previews/solana-test-validator-up@1.0.0-preview-9e8ad9c32
@metamask-previews/stellar-quickstart-up@0.0.0-preview-9e8ad9c32
@metamask-previews/storage-service@1.0.2-preview-9e8ad9c32
@metamask-previews/subscription-controller@6.2.0-preview-9e8ad9c32
@metamask-previews/transaction-controller@68.2.2-preview-9e8ad9c32
@metamask-previews/transaction-pay-controller@23.17.4-preview-9e8ad9c32
@metamask-previews/user-operation-controller@41.2.6-preview-9e8ad9c32
@metamask-previews/wallet@6.0.0-preview-9e8ad9c32
@metamask-previews/wallet-cli@0.0.0-preview-9e8ad9c32

@saustrie-consensys saustrie-consensys self-assigned this Jul 6, 2026
@saustrie-consensys saustrie-consensys marked this pull request as ready for review July 6, 2026 09:11
@saustrie-consensys saustrie-consensys requested review from a team as code owners July 6, 2026 09:11

@cursor cursor Bot left a comment

Copy link
Copy Markdown

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 9e8ad9c. Configure here.

Comment thread packages/ramps-controller/src/RampsController.ts
…supports the asset

The empty-provider guard in getQuotes only short-circuited on
restrictToKnownOrNativeProviders. A caller that triggers in-app widening via
autoSelectProvider alone, in a region with no asset-supporting provider, got an
empty providersToUse that was then passed to the service, which omits the
provider filter and quotes every provider. Broaden the guard to also cover the
widened in-app path (widenToInAppProviders) so it returns an empty response
instead. Reported by Cursor Bugbot.
@saustrie-consensys saustrie-consensys added this pull request to the merge queue Jul 6, 2026
Merged via the queue into main with commit 359eb4a Jul 6, 2026
413 checks passed
@saustrie-consensys saustrie-consensys deleted the feat/ramps-controller-in-app-provider-scope branch July 6, 2026 11:55
This was referenced Jul 6, 2026
pull Bot pushed a commit to dmrazzy/core that referenced this pull request Jul 6, 2026
## Explanation

This release branch publishes `@metamask/ramps-controller` `15.1.0`.

The release includes the scope-aware in-app provider widening work from
MetaMask#9353, plus the existing unreleased `init()` / countries catalog refresh
entries from MetaMask#9261. The release tool also bumped the root monorepo
version to `1095.0.0` and updated
`@metamask/transaction-pay-controller`'s workspace dependency on
`@metamask/ramps-controller` to `^15.1.0`.

This branch was generated by `yarn create-release-branch`.

## References

- Related to MetaMask#9353
- Related to MetaMask#9261
- Related to MetaMask/metamask-mobile#32682

## Checklist

- [x] I've updated the test suite for new or updated code as appropriate
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [x] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

Validation: `yarn changelog:validate`

Made with [Cursor](https://cursor.com)

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
pull Bot pushed a commit to Reality2byte/core that referenced this pull request Jul 10, 2026
…ty (MetaMask#9448)

## Explanation

`@metamask/ramps-controller` normalized provider IDs by stripping a
`/providers/` prefix through a `normalizeProviderCode` helper. This
normalization was applied in two places: across the `getQuotes`
scope-aware selection logic (matching the providers list, each quote's
`provider`, custom-action provider IDs, and the sort-order IDs) and when
building a precreated stub order, where the provider code was re-wrapped
as `/providers/<code>`. The Ramps backend now returns canonical,
non-prefixed provider IDs, so this normalization is unnecessary and
inconsistent with the new contract.

This PR removes provider-ID normalization entirely so IDs are compared
and stored as-is (canonical). Concretely: the `normalizeProviderCode`
function and its public export are removed; the six
`normalizeProviderCode(...)` call sites in the `getQuotes` selection
logic are dropped so the map keys and lookups use the raw provider IDs;
and a precreated stub order's `provider.id` is now the canonical
provider code passed to the create-order call rather than a
`/providers/`-prefixed value. The dedicated `normalizeProviderCode` unit
test is removed and the stub-order test now expects the canonical
`paypal` ID.

One detail worth calling out for reviewers: the six removed call sites
were added recently in MetaMask#9353 (scope-aware in-app provider widening).
Because normalization is removed uniformly from both sides of every map
key and lookup, matching behavior is preserved for
consistently-formatted IDs, and the existing `getQuotes` tests continue
to pass unchanged (308 tests green).

This is a breaking change: `normalizeProviderCode` is no longer
exported, and the precreated stub order's `provider.id` changes shape
from `/providers/<code>` to `<code>`. Consumers must supply non-prefixed
(canonical) provider IDs. The mobile consumer PR removes all
`normalizeProviderCode` usages and the app-side normalization to adopt
this.

## References

* Fixes: https://consensyssoftware.atlassian.net/browse/TRAM-3560
* Consumer PR (mobile):
MetaMask/metamask-mobile#32819
* Related to MetaMask#9353 (introduced the `getQuotes` normalization removed
here)

## Checklist

- [x] I've updated the test suite for new or updated code as appropriate
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [x] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [x] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Breaking API and state shape changes for buy/quote flows; wrong IDs
from consumers that still pass `/providers/`-prefixed values could break
quote selection or order polling until clients migrate.
> 
> **Overview**
> **Breaking change:** `@metamask/ramps-controller` drops `/providers/`
prefix normalization so provider IDs are compared and stored as
canonical codes (e.g. `paypal`, `transak`).
> 
> The **`normalizeProviderCode` helper and its public export are
removed**. In **`getQuotes`** scope-aware selection, maps and lookups
now use raw `provider.id`, quote `provider`, custom-action `providerId`,
and sort-order IDs with no stripping. **`addPrecreatedOrder`** sets stub
`provider.id` to the passed `providerCode` instead of
`/providers/<code>`.
> 
> JSDoc and the changelog document the contract. Tests drop the
normalizer suite, expect canonical `paypal` on stubs, and add coverage
for plain-ID matching in scoped quote selection.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
e352e4f. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Darius Costolas <10818970+meltingice1337@users.noreply.github.com>
@amitabh94 amitabh94 mentioned this pull request Jul 11, 2026
3 tasks
pull Bot pushed a commit to dmrazzy/core that referenced this pull request Jul 13, 2026
…ller-side; share provider/quote/error helpers (MetaMask#9409)

## Explanation

Headless Buy provider expansion previously reached `RampsController`
through an injected `getProviderScope` callback returning a multivariate
scope (`off` | `in-app` | `all`), and `metamask-mobile` re-derived
gating logic the controller already owns privately. This PR replaces the
scope concept with a single boolean remote feature flag that the
controller reads itself, and lifts the shared logic into pure, tested,
exported helpers so consumers cannot drift from the controller's own
selection.

Flag semantics (`moneyHeadlessAllProviders`, boolean; this is the
client-side key, which the ClientConfig API camelizes from the
kebab-case LaunchDarkly dashboard key `money-headless-all-providers`):

- `true`: the auto-selection quote path (`autoSelectProvider` /
`restrictToKnownOrNativeProviders`) widens to every supporting provider
class: native, in-app WebView aggregator, and external-browser /
custom-action. The best quote is returned at `success[0]`, enforcing
per-provider fiat limits.
- `false`, missing, or any non-boolean value: today's native-only
behavior. The intermediate `in-app` scope is removed, along with the
exported `ProviderScope` type and the `getProviderScope` constructor
option (breaking).

Controller-side consumption:

- `RemoteFeatureFlagController:getState` is added to the controller's
allowed messenger actions (same pattern as `ConfigRegistryController` /
`bridge-controller`), and a private `#isAllProvidersEnabled()` resolves
the flag per `getQuotes` call, so a remote fetch or a local dev override
takes effect at runtime. The read fails closed: if the action is not
delegated, quoting stays native-only.
- New `featureFlags` module exports
`MONEY_HEADLESS_ALL_PROVIDERS_FLAG_KEY` and the pure
`isHeadlessAllProvidersEnabled(remoteFeatureFlagState)` helper (plus a
`HeadlessFeatureFlagsLookup` type). The helper owns the key lookup, the
`localOverrides`-over-`remoteFeatureFlags` merge (mobile's Settings >
Feature flag override screen writes `localOverrides`, and published
`RemoteFeatureFlagController` versions such as `4.2.2` do not fold
overrides into `remoteFeatureFlags` state), and defensive coercion: only
the literal boolean `true` enables. Mobile UI hooks call the same
helper, so the UI gate and the controller resolve the flag identically.

Shared pure helpers (consumed by the controller internally so they stay
behaviourally identical to its own selection):

- `providerAvailability`: `providerServesAsset`,
`getProvidersServingAsset`, `regionHasProviderForAsset`,
`isFiatDepositAvailable`. The latter two take an `allProvidersEnabled:
boolean` instead of a scope.
- `quoteClassification`: `isExternalBrowserQuote`,
`isCustomActionQuote`, `isInAppOnlyQuote`.
- `errorNormalization`: `getErrorMessage`, `extractExplicitTypedError`,
`normalizeToTypedError` (+ `TypedError<Code>`). The deliberately
host-specific bits (deeplink schemes, redirect URLs, session lifecycle,
error taxonomy values) stay in the consumer.

All 601 package tests pass with 100% coverage, including: widening
on/off via the flag, `localOverrides` honored in both directions,
garbage flag values coerced to `false`, an unwired
`RemoteFeatureFlagController:getState` failing closed, and per-call flag
reads picking up runtime changes.

## References

- Consumer PR: MetaMask/metamask-mobile#32890 (adopts these helpers,
removes the mobile-side scope plumbing, and consumes the flag via the
exported helper)
- Replaces the scope-aware widening surface introduced in MetaMask#9353 with the
boolean flag
- Part of the Headless Buy all-providers plan
(`app/components/UI/Ramp/headless/PLAN_-_ALL_PROVIDERS_SUPPORT.md` in
metamask-mobile)

## Checklist

- [x] I've updated the test suite for new or updated code as appropriate
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [x] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [x] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

Made with [Cursor](https://cursor.com)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants