@metamask/ramps-controller 17.1.0 → 17.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [17.2.0]
11
+
12
+ ### Added
13
+
14
+ - Add the pure `getHeadlessProviderAllowlist(remoteFeatureFlagState)` helper resolving the provider-id allowlist carried by the `moneyHeadlessAllProviders` flag's object payload; empty or malformed `providerIds` resolve to `undefined` (no restriction), unknown keys and non-string entries are ignored ([#9524](https://github.com/MetaMask/core/pull/9524))
15
+ - Add the `HEADLESS_ALL_PROVIDERS_FEATURE_VERSION` constant (currently `'1'`) and the `getHeadlessAllProvidersMinimumVersion(remoteFeatureFlagState)` helper; an enabled object payload must carry `featureVersion: '1'` or it resolves to disabled, and `minimumVersion` is exposed for clients to validate against the app version ([#9524](https://github.com/MetaMask/core/pull/9524))
16
+
17
+ ### Changed
18
+
19
+ - Widen the `moneyHeadlessAllProviders` flag value contract to accept an object payload `{ enabled: true, featureVersion: "1", providerIds?: string[] }` alongside the boolean form ([#9524](https://github.com/MetaMask/core/pull/9524))
20
+ - `isHeadlessAllProvidersEnabled` now returns `true` for an object payload whose `enabled` is the literal `true` and `featureVersion` is `"1"`; every other previously-false value still resolves to `false`, so boolean-only configurations see no behavior change
21
+ - When the payload lists provider ids, the widened quote pick drops candidates whose provider is not listed (ids match in prefixed `/providers/x` or bare form, case-insensitively); if nothing survives, `getQuotes` returns an empty `success[]` with `sorted` / `error` / `customActions` preserved
22
+ - Clients on earlier versions coerce the object payload to `false` (native-only), so serving it cannot enable widening for a client that cannot parse it
23
+
10
24
  ## [17.1.0]
11
25
 
12
26
  ### Added
@@ -454,7 +468,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
454
468
  - Add `OnRampService` for interacting with the OnRamp API
455
469
  - Add geolocation detection via IP address lookup
456
470
 
457
- [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/ramps-controller@17.1.0...HEAD
471
+ [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/ramps-controller@17.2.0...HEAD
472
+ [17.2.0]: https://github.com/MetaMask/core/compare/@metamask/ramps-controller@17.1.0...@metamask/ramps-controller@17.2.0
458
473
  [17.1.0]: https://github.com/MetaMask/core/compare/@metamask/ramps-controller@17.0.0...@metamask/ramps-controller@17.1.0
459
474
  [17.0.0]: https://github.com/MetaMask/core/compare/@metamask/ramps-controller@16.0.0...@metamask/ramps-controller@17.0.0
460
475
  [16.0.0]: https://github.com/MetaMask/core/compare/@metamask/ramps-controller@15.1.0...@metamask/ramps-controller@16.0.0
@@ -10,7 +10,7 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
10
10
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
11
11
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
12
12
  };
13
- var _RampsController_instances, _RampsController_requestCacheTTL, _RampsController_requestCacheMaxSize, _RampsController_getDefaultRedirectUrl, _RampsController_pendingRequests, _RampsController_pendingResourceCount, _RampsController_pendingResourceGeneration, _RampsController_orderPollingMeta, _RampsController_orderPollingTimer, _RampsController_isPolling, _RampsController_initPromise, _RampsController_clearPendingResourceCountForDependentResources, _RampsController_abortDependentRequests, _RampsController_isAllProvidersEnabled, _RampsController_mutateRequests, _RampsController_removeRequestState, _RampsController_cleanupState, _RampsController_requireRegion, _RampsController_isRegionCurrent, _RampsController_isTokenCurrent, _RampsController_isProviderCurrent, _RampsController_updateResourceField, _RampsController_setResourceLoading, _RampsController_setResourceError, _RampsController_updateRequestState, _RampsController_runInit, _RampsController_syncUserRegionFromCountriesCatalog, _RampsController_pickWidenedQuote, _RampsController_getSupportingProvidersForRegion, _RampsController_filterProviderIdsBySupport, _RampsController_resolveProviderIdsForQuote, _RampsController_getPreferredProviderIdsFromOrders, _RampsController_refreshOrder, _RampsController_pollPendingOrders, _RampsController_syncTransakAuthOnError, _RampsController_getNormalizedTransakError;
13
+ var _RampsController_instances, _RampsController_requestCacheTTL, _RampsController_requestCacheMaxSize, _RampsController_getDefaultRedirectUrl, _RampsController_pendingRequests, _RampsController_pendingResourceCount, _RampsController_pendingResourceGeneration, _RampsController_orderPollingMeta, _RampsController_orderPollingTimer, _RampsController_isPolling, _RampsController_initPromise, _RampsController_clearPendingResourceCountForDependentResources, _RampsController_abortDependentRequests, _RampsController_resolveAllProvidersFlag, _RampsController_mutateRequests, _RampsController_removeRequestState, _RampsController_cleanupState, _RampsController_requireRegion, _RampsController_isRegionCurrent, _RampsController_isTokenCurrent, _RampsController_isProviderCurrent, _RampsController_updateResourceField, _RampsController_setResourceLoading, _RampsController_setResourceError, _RampsController_updateRequestState, _RampsController_runInit, _RampsController_syncUserRegionFromCountriesCatalog, _RampsController_pickWidenedQuote, _RampsController_getSupportingProvidersForRegion, _RampsController_filterProviderIdsBySupport, _RampsController_resolveProviderIdsForQuote, _RampsController_getPreferredProviderIdsFromOrders, _RampsController_refreshOrder, _RampsController_pollPendingOrders, _RampsController_syncTransakAuthOnError, _RampsController_getNormalizedTransakError;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.RampsController = exports.getInternalOrderCode = exports.getDefaultRampsControllerState = exports.RAMPS_CONTROLLER_REQUIRED_SERVICE_ACTIONS = exports.controllerName = void 0;
16
16
  const base_controller_1 = require("@metamask/base-controller");
@@ -1016,7 +1016,13 @@ class RampsController extends base_controller_1.BaseController {
1016
1016
  const wantsAutoSelection = !options.providers &&
1017
1017
  (options.autoSelectProvider === true ||
1018
1018
  options.restrictToKnownOrNativeProviders === true);
1019
- const widenToAllProviders = wantsAutoSelection && __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_isAllProvidersEnabled).call(this);
1019
+ // Single flag read per call: the enabled bit and the allowlist come from
1020
+ // the same `RemoteFeatureFlagController` state snapshot, so a flag edit
1021
+ // during the awaited quote fetch cannot produce a mixed read.
1022
+ const { enabled: allProvidersEnabled, allowlist: providerAllowlist } = wantsAutoSelection
1023
+ ? __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_resolveAllProvidersFlag).call(this)
1024
+ : { enabled: false, allowlist: undefined };
1025
+ const widenToAllProviders = wantsAutoSelection && allProvidersEnabled;
1020
1026
  let providersToUse;
1021
1027
  let widenedProviderCatalog = this.state.providers.data;
1022
1028
  if (options.providers) {
@@ -1127,6 +1133,7 @@ class RampsController extends base_controller_1.BaseController {
1127
1133
  amount: options.amount,
1128
1134
  fiat: normalizedFiat,
1129
1135
  providers: widenedProviderCatalog,
1136
+ allowlist: providerAllowlist,
1130
1137
  });
1131
1138
  if (!selectedQuote) {
1132
1139
  // No quote fits the published provider limits: surface "no quote"
@@ -1794,13 +1801,16 @@ _RampsController_requestCacheTTL = new WeakMap(), _RampsController_requestCacheM
1794
1801
  __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_removeRequestState).call(this, cacheKey);
1795
1802
  }
1796
1803
  }
1797
- }, _RampsController_isAllProvidersEnabled = function _RampsController_isAllProvidersEnabled() {
1804
+ }, _RampsController_resolveAllProvidersFlag = function _RampsController_resolveAllProvidersFlag() {
1798
1805
  try {
1799
1806
  const remoteFeatureFlagState = this.messenger.call('RemoteFeatureFlagController:getState');
1800
- return (0, featureFlags_js_1.isHeadlessAllProvidersEnabled)(remoteFeatureFlagState);
1807
+ return {
1808
+ enabled: (0, featureFlags_js_1.isHeadlessAllProvidersEnabled)(remoteFeatureFlagState),
1809
+ allowlist: (0, featureFlags_js_1.getHeadlessProviderAllowlist)(remoteFeatureFlagState),
1810
+ };
1801
1811
  }
1802
1812
  catch {
1803
- return false;
1813
+ return { enabled: false };
1804
1814
  }
1805
1815
  }, _RampsController_mutateRequests = function _RampsController_mutateRequests(fn) {
1806
1816
  this.update((state) => {
@@ -1913,8 +1923,13 @@ _RampsController_requestCacheTTL = new WeakMap(), _RampsController_requestCacheM
1913
1923
  this.update((state) => {
1914
1924
  state.userRegion = userRegion;
1915
1925
  });
1916
- }, _RampsController_pickWidenedQuote = function _RampsController_pickWidenedQuote(response, { amount, fiat, providers, }) {
1926
+ }, _RampsController_pickWidenedQuote = function _RampsController_pickWidenedQuote(response, { amount, fiat, providers, allowlist, }) {
1917
1927
  const providerByCode = new Map(providers.map((provider) => [provider.id, provider]));
1928
+ const allowedProviderIds = allowlist && allowlist.length > 0
1929
+ ? new Set(allowlist.map(featureFlags_js_1.normalizeHeadlessProviderId))
1930
+ : undefined;
1931
+ const isAllowedProvider = (quote) => !allowedProviderIds ||
1932
+ allowedProviderIds.has((0, featureFlags_js_1.normalizeHeadlessProviderId)(quote.provider));
1918
1933
  const fitsProviderLimits = (quote) => {
1919
1934
  const provider = providerByCode.get(quote.provider);
1920
1935
  const limit = provider?.limits?.fiat?.[fiat]?.[quote.quote.paymentMethod];
@@ -1925,7 +1940,7 @@ _RampsController_requestCacheTTL = new WeakMap(), _RampsController_requestCacheM
1925
1940
  }
1926
1941
  return amount >= limit.minAmount && amount <= limit.maxAmount;
1927
1942
  };
1928
- const candidates = response.success.filter(fitsProviderLimits);
1943
+ const candidates = response.success.filter((quote) => isAllowedProvider(quote) && fitsProviderLimits(quote));
1929
1944
  if (candidates.length === 0) {
1930
1945
  return undefined;
1931
1946
  }