@metamask/ramps-controller 11.0.0 → 12.0.1

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.
@@ -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_pendingRequests, _RampsController_pendingResourceCount, _RampsController_orderPollingMeta, _RampsController_orderPollingTimer, _RampsController_isPolling, _RampsController_clearPendingResourceCountForDependentResources, _RampsController_abortDependentRequests, _RampsController_registerActionHandlers, _RampsController_mutateRequests, _RampsController_removeRequestState, _RampsController_cleanupState, _RampsController_fireAndForget, _RampsController_requireRegion, _RampsController_isRegionCurrent, _RampsController_isTokenCurrent, _RampsController_isProviderCurrent, _RampsController_updateResourceField, _RampsController_setResourceLoading, _RampsController_setResourceError, _RampsController_updateRequestState, _RampsController_refreshOrder, _RampsController_pollPendingOrders, _RampsController_syncTransakAuthOnError;
13
+ var _RampsController_instances, _RampsController_requestCacheTTL, _RampsController_requestCacheMaxSize, _RampsController_pendingRequests, _RampsController_pendingResourceCount, _RampsController_orderPollingMeta, _RampsController_orderPollingTimer, _RampsController_isPolling, _RampsController_initPromise, _RampsController_clearPendingResourceCountForDependentResources, _RampsController_abortDependentRequests, _RampsController_mutateRequests, _RampsController_removeRequestState, _RampsController_cleanupState, _RampsController_fireAndForget, _RampsController_requireRegion, _RampsController_isRegionCurrent, _RampsController_isTokenCurrent, _RampsController_isProviderCurrent, _RampsController_updateResourceField, _RampsController_setResourceLoading, _RampsController_setResourceError, _RampsController_updateRequestState, _RampsController_runInit, _RampsController_refreshOrder, _RampsController_pollPendingOrders, _RampsController_syncTransakAuthOnError;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.RampsController = exports.normalizeProviderCode = exports.getDefaultRampsControllerState = exports.RAMPS_CONTROLLER_REQUIRED_SERVICE_ACTIONS = exports.controllerName = void 0;
16
16
  const base_controller_1 = require("@metamask/base-controller");
@@ -270,6 +270,55 @@ const PENDING_ORDER_STATUSES = new Set([
270
270
  const DEFAULT_POLLING_INTERVAL_MS = 30000;
271
271
  const MAX_ERROR_COUNT = 5;
272
272
  // === CONTROLLER DEFINITION ===
273
+ const MESSENGER_EXPOSED_METHODS = [
274
+ 'executeRequest',
275
+ 'abortRequest',
276
+ 'getRequestState',
277
+ 'setUserRegion',
278
+ 'setSelectedProvider',
279
+ 'init',
280
+ 'getCountries',
281
+ 'getTokens',
282
+ 'setSelectedToken',
283
+ 'getProviders',
284
+ 'getPaymentMethods',
285
+ 'setSelectedPaymentMethod',
286
+ 'getQuotes',
287
+ 'addOrder',
288
+ 'removeOrder',
289
+ 'startOrderPolling',
290
+ 'stopOrderPolling',
291
+ 'getBuyWidgetData',
292
+ 'addPrecreatedOrder',
293
+ 'getOrder',
294
+ 'getOrderFromCallback',
295
+ 'transakSetApiKey',
296
+ 'transakSetAccessToken',
297
+ 'transakClearAccessToken',
298
+ 'transakSetAuthenticated',
299
+ 'transakResetState',
300
+ 'transakSendUserOtp',
301
+ 'transakVerifyUserOtp',
302
+ 'transakLogout',
303
+ 'transakGetUserDetails',
304
+ 'transakGetBuyQuote',
305
+ 'transakGetKycRequirement',
306
+ 'transakGetAdditionalRequirements',
307
+ 'transakCreateOrder',
308
+ 'transakGetOrder',
309
+ 'transakGetUserLimits',
310
+ 'transakRequestOtt',
311
+ 'transakGeneratePaymentWidgetUrl',
312
+ 'transakSubmitPurposeOfUsageForm',
313
+ 'transakPatchUser',
314
+ 'transakSubmitSsnDetails',
315
+ 'transakConfirmPayment',
316
+ 'transakGetTranslation',
317
+ 'transakGetIdProofStatus',
318
+ 'transakCancelOrder',
319
+ 'transakCancelAllActiveOrders',
320
+ 'transakGetActiveOrders',
321
+ ];
273
322
  /**
274
323
  * Manages cryptocurrency on/off ramps functionality.
275
324
  */
@@ -327,9 +376,10 @@ class RampsController extends base_controller_1.BaseController {
327
376
  _RampsController_orderPollingMeta.set(this, new Map());
328
377
  _RampsController_orderPollingTimer.set(this, null);
329
378
  _RampsController_isPolling.set(this, false);
379
+ _RampsController_initPromise.set(this, null);
330
380
  __classPrivateFieldSet(this, _RampsController_requestCacheTTL, requestCacheTTL, "f");
331
381
  __classPrivateFieldSet(this, _RampsController_requestCacheMaxSize, requestCacheMaxSize, "f");
332
- __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_registerActionHandlers).call(this);
382
+ this.messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
333
383
  }
334
384
  /**
335
385
  * Executes a request with caching, deduplication, and at most one in-flight
@@ -569,25 +619,28 @@ class RampsController extends base_controller_1.BaseController {
569
619
  * Initializes the controller by fetching the user's region from geolocation.
570
620
  * This should be called once at app startup to set up the initial region.
571
621
  *
572
- * If a userRegion already exists (from persistence or manual selection),
573
- * this method will skip geolocation fetch and use the existing region.
622
+ * Idempotent: subsequent calls return the same promise unless forceRefresh is set.
623
+ * Skips getCountries when countries are already loaded; skips geolocation when
624
+ * userRegion already exists.
574
625
  *
575
- * @param options - Options for cache behavior.
626
+ * @param options - Options for cache behavior. forceRefresh bypasses idempotency and re-runs the full flow.
576
627
  * @returns Promise that resolves when initialization is complete.
577
628
  */
578
629
  async init(options) {
579
- await this.getCountries(options);
580
- let regionCode = this.state.userRegion?.regionCode;
581
- regionCode ?? (regionCode = await this.messenger.call('RampsService:getGeolocation'));
582
- if (!regionCode) {
583
- throw new Error('Failed to fetch geolocation. Cannot initialize controller without valid region information.');
630
+ if (!options?.forceRefresh && __classPrivateFieldGet(this, _RampsController_initPromise, "f") !== null) {
631
+ return __classPrivateFieldGet(this, _RampsController_initPromise, "f");
584
632
  }
585
- await this.setUserRegion(regionCode, options);
586
- }
587
- hydrateState(options) {
588
- const regionCode = __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_requireRegion).call(this);
589
- __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_fireAndForget).call(this, this.getTokens(regionCode, 'buy', options));
590
- __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_fireAndForget).call(this, this.getProviders(regionCode, options));
633
+ if (options?.forceRefresh) {
634
+ __classPrivateFieldSet(this, _RampsController_initPromise, null, "f");
635
+ }
636
+ const initPromise = __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_runInit).call(this, options).then(() => undefined, (error) => {
637
+ if (__classPrivateFieldGet(this, _RampsController_initPromise, "f") === initPromise) {
638
+ __classPrivateFieldSet(this, _RampsController_initPromise, null, "f");
639
+ }
640
+ throw error;
641
+ });
642
+ __classPrivateFieldSet(this, _RampsController_initPromise, initPromise, "f");
643
+ return initPromise;
591
644
  }
592
645
  /**
593
646
  * Fetches the list of supported countries.
@@ -1029,23 +1082,25 @@ class RampsController extends base_controller_1.BaseController {
1029
1082
  */
1030
1083
  async getOrder(providerCode, orderCode, wallet) {
1031
1084
  const order = await this.messenger.call('RampsService:getOrder', providerCode, orderCode, wallet);
1085
+ const healedWalletAddress = order.walletAddress || wallet;
1086
+ const healedOrder = {
1087
+ ...order,
1088
+ walletAddress: healedWalletAddress,
1089
+ providerOrderId: orderCode,
1090
+ };
1032
1091
  this.update((state) => {
1033
1092
  const idx = state.orders.findIndex((existing) => existing.providerOrderId === orderCode);
1034
1093
  if (idx === -1) {
1035
- state.orders.push({
1036
- ...order,
1037
- providerOrderId: orderCode,
1038
- });
1094
+ state.orders.push(healedOrder);
1039
1095
  }
1040
1096
  else {
1041
1097
  state.orders[idx] = {
1042
1098
  ...state.orders[idx],
1043
- ...order,
1044
- providerOrderId: orderCode,
1099
+ ...healedOrder,
1045
1100
  };
1046
1101
  }
1047
1102
  });
1048
- return order;
1103
+ return healedOrder;
1049
1104
  }
1050
1105
  /**
1051
1106
  * Extracts an order from a provider callback URL.
@@ -1457,7 +1512,7 @@ class RampsController extends base_controller_1.BaseController {
1457
1512
  }
1458
1513
  }
1459
1514
  exports.RampsController = RampsController;
1460
- _RampsController_requestCacheTTL = new WeakMap(), _RampsController_requestCacheMaxSize = new WeakMap(), _RampsController_pendingRequests = new WeakMap(), _RampsController_pendingResourceCount = new WeakMap(), _RampsController_orderPollingMeta = new WeakMap(), _RampsController_orderPollingTimer = new WeakMap(), _RampsController_isPolling = new WeakMap(), _RampsController_instances = new WeakSet(), _RampsController_clearPendingResourceCountForDependentResources = function _RampsController_clearPendingResourceCountForDependentResources() {
1515
+ _RampsController_requestCacheTTL = new WeakMap(), _RampsController_requestCacheMaxSize = new WeakMap(), _RampsController_pendingRequests = new WeakMap(), _RampsController_pendingResourceCount = new WeakMap(), _RampsController_orderPollingMeta = new WeakMap(), _RampsController_orderPollingTimer = new WeakMap(), _RampsController_isPolling = new WeakMap(), _RampsController_initPromise = new WeakMap(), _RampsController_instances = new WeakSet(), _RampsController_clearPendingResourceCountForDependentResources = function _RampsController_clearPendingResourceCountForDependentResources() {
1461
1516
  for (const resourceType of DEPENDENT_RESOURCE_KEYS) {
1462
1517
  __classPrivateFieldGet(this, _RampsController_pendingResourceCount, "f").delete(resourceType);
1463
1518
  }
@@ -1470,10 +1525,6 @@ _RampsController_requestCacheTTL = new WeakMap(), _RampsController_requestCacheM
1470
1525
  __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_removeRequestState).call(this, cacheKey);
1471
1526
  }
1472
1527
  }
1473
- }, _RampsController_registerActionHandlers = function _RampsController_registerActionHandlers() {
1474
- this.messenger.registerActionHandler('RampsController:getOrder', this.getOrder.bind(this));
1475
- this.messenger.registerActionHandler('RampsController:getQuotes', this.getQuotes.bind(this));
1476
- this.messenger.registerActionHandler('RampsController:setSelectedToken', this.setSelectedToken.bind(this));
1477
1528
  }, _RampsController_mutateRequests = function _RampsController_mutateRequests(fn) {
1478
1529
  this.update((state) => {
1479
1530
  const requests = state.requests;
@@ -1544,6 +1595,24 @@ _RampsController_requestCacheTTL = new WeakMap(), _RampsController_requestCacheM
1544
1595
  }
1545
1596
  }
1546
1597
  });
1598
+ }, _RampsController_runInit = async function _RampsController_runInit(options) {
1599
+ const forceRefresh = options?.forceRefresh === true;
1600
+ const hasCountries = this.state.countries.data.length > 0;
1601
+ if (forceRefresh || !hasCountries) {
1602
+ await this.getCountries(options);
1603
+ }
1604
+ let regionCode;
1605
+ if (forceRefresh) {
1606
+ regionCode = await this.messenger.call('RampsService:getGeolocation');
1607
+ }
1608
+ else {
1609
+ regionCode = this.state.userRegion?.regionCode;
1610
+ regionCode ?? (regionCode = await this.messenger.call('RampsService:getGeolocation'));
1611
+ }
1612
+ if (!regionCode) {
1613
+ throw new Error('Failed to fetch geolocation. Cannot initialize controller without valid region information.');
1614
+ }
1615
+ await this.setUserRegion(regionCode, options);
1547
1616
  }, _RampsController_refreshOrder =
1548
1617
  /**
1549
1618
  * Refreshes a single order via the V2 API and updates it in state.