@metamask/ramps-controller 8.0.0 → 9.0.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.
Files changed (54) hide show
  1. package/CHANGELOG.md +26 -1
  2. package/dist/RampsController.cjs +646 -116
  3. package/dist/RampsController.cjs.map +1 -1
  4. package/dist/RampsController.d.cts +284 -13
  5. package/dist/RampsController.d.cts.map +1 -1
  6. package/dist/RampsController.d.mts +284 -13
  7. package/dist/RampsController.d.mts.map +1 -1
  8. package/dist/RampsController.mjs +646 -116
  9. package/dist/RampsController.mjs.map +1 -1
  10. package/dist/RampsService-method-action-types.cjs.map +1 -1
  11. package/dist/RampsService-method-action-types.d.cts +32 -1
  12. package/dist/RampsService-method-action-types.d.cts.map +1 -1
  13. package/dist/RampsService-method-action-types.d.mts +32 -1
  14. package/dist/RampsService-method-action-types.d.mts.map +1 -1
  15. package/dist/RampsService-method-action-types.mjs.map +1 -1
  16. package/dist/RampsService.cjs +83 -1
  17. package/dist/RampsService.cjs.map +1 -1
  18. package/dist/RampsService.d.cts +126 -0
  19. package/dist/RampsService.d.cts.map +1 -1
  20. package/dist/RampsService.d.mts +126 -0
  21. package/dist/RampsService.d.mts.map +1 -1
  22. package/dist/RampsService.mjs +82 -0
  23. package/dist/RampsService.mjs.map +1 -1
  24. package/dist/RequestCache.cjs.map +1 -1
  25. package/dist/RequestCache.d.cts +2 -0
  26. package/dist/RequestCache.d.cts.map +1 -1
  27. package/dist/RequestCache.d.mts +2 -0
  28. package/dist/RequestCache.d.mts.map +1 -1
  29. package/dist/RequestCache.mjs.map +1 -1
  30. package/dist/TransakService-method-action-types.cjs +7 -0
  31. package/dist/TransakService-method-action-types.cjs.map +1 -0
  32. package/dist/TransakService-method-action-types.d.cts +106 -0
  33. package/dist/TransakService-method-action-types.d.cts.map +1 -0
  34. package/dist/TransakService-method-action-types.d.mts +106 -0
  35. package/dist/TransakService-method-action-types.d.mts.map +1 -0
  36. package/dist/TransakService-method-action-types.mjs +6 -0
  37. package/dist/TransakService-method-action-types.mjs.map +1 -0
  38. package/dist/TransakService.cjs +588 -0
  39. package/dist/TransakService.cjs.map +1 -0
  40. package/dist/TransakService.d.cts +329 -0
  41. package/dist/TransakService.d.cts.map +1 -0
  42. package/dist/TransakService.d.mts +329 -0
  43. package/dist/TransakService.d.mts.map +1 -0
  44. package/dist/TransakService.mjs +582 -0
  45. package/dist/TransakService.mjs.map +1 -0
  46. package/dist/index.cjs +7 -1
  47. package/dist/index.cjs.map +1 -1
  48. package/dist/index.d.cts +7 -4
  49. package/dist/index.d.cts.map +1 -1
  50. package/dist/index.d.mts +7 -4
  51. package/dist/index.d.mts.map +1 -1
  52. package/dist/index.mjs +2 -1
  53. package/dist/index.mjs.map +1 -1
  54. package/package.json +4 -4
@@ -9,7 +9,7 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
9
9
  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");
10
10
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
11
11
  };
12
- var _RampsController_instances, _RampsController_requestCacheTTL, _RampsController_requestCacheMaxSize, _RampsController_pendingRequests, _RampsController_pendingResourceCount, _RampsController_quotePollingInterval, _RampsController_quotePollingOptions, _RampsController_clearPendingResourceCountForDependentResources, _RampsController_removeRequestState, _RampsController_cleanupState, _RampsController_fireAndForget, _RampsController_restartPollingIfActive, _RampsController_updateResourceField, _RampsController_setResourceLoading, _RampsController_setResourceError, _RampsController_updateRequestState;
12
+ var _RampsController_instances, _RampsController_requestCacheTTL, _RampsController_requestCacheMaxSize, _RampsController_pendingRequests, _RampsController_pendingResourceCount, _RampsController_quotePollingInterval, _RampsController_quotePollingOptions, _RampsController_clearPendingResourceCountForDependentResources, _RampsController_abortDependentRequests, _RampsController_mutateRequests, _RampsController_removeRequestState, _RampsController_cleanupState, _RampsController_fireAndForget, _RampsController_restartPollingIfActive, _RampsController_requireRegion, _RampsController_isRegionCurrent, _RampsController_isTokenCurrent, _RampsController_isProviderCurrent, _RampsController_updateResourceField, _RampsController_setResourceLoading, _RampsController_setResourceError, _RampsController_updateRequestState, _RampsController_syncWidgetUrl, _RampsController_syncTransakAuthOnError;
13
13
  import { BaseController } from "@metamask/base-controller";
14
14
  import { DEFAULT_REQUEST_CACHE_TTL, DEFAULT_REQUEST_CACHE_MAX_SIZE, createCacheKey, isCacheExpired, createLoadingState, createSuccessState, createErrorState, RequestStatus } from "./RequestCache.mjs";
15
15
  // === GENERAL ===
@@ -32,6 +32,32 @@ export const RAMPS_CONTROLLER_REQUIRED_SERVICE_ACTIONS = [
32
32
  'RampsService:getPaymentMethods',
33
33
  'RampsService:getQuotes',
34
34
  'RampsService:getBuyWidgetUrl',
35
+ 'RampsService:getOrder',
36
+ 'RampsService:getOrderFromCallback',
37
+ 'TransakService:setApiKey',
38
+ 'TransakService:setAccessToken',
39
+ 'TransakService:clearAccessToken',
40
+ 'TransakService:sendUserOtp',
41
+ 'TransakService:verifyUserOtp',
42
+ 'TransakService:logout',
43
+ 'TransakService:getUserDetails',
44
+ 'TransakService:getBuyQuote',
45
+ 'TransakService:getKycRequirement',
46
+ 'TransakService:getAdditionalRequirements',
47
+ 'TransakService:createOrder',
48
+ 'TransakService:getOrder',
49
+ 'TransakService:getUserLimits',
50
+ 'TransakService:requestOtt',
51
+ 'TransakService:generatePaymentWidgetUrl',
52
+ 'TransakService:submitPurposeOfUsageForm',
53
+ 'TransakService:patchUser',
54
+ 'TransakService:submitSsnDetails',
55
+ 'TransakService:confirmPayment',
56
+ 'TransakService:getTranslation',
57
+ 'TransakService:getIdProofStatus',
58
+ 'TransakService:cancelOrder',
59
+ 'TransakService:cancelAllActiveOrders',
60
+ 'TransakService:getActiveOrders',
35
61
  ];
36
62
  /**
37
63
  * Default TTL for quotes requests (15 seconds).
@@ -78,12 +104,24 @@ const rampsControllerMetadata = {
78
104
  includeInStateLogs: false,
79
105
  usedInUi: true,
80
106
  },
107
+ widgetUrl: {
108
+ persist: false,
109
+ includeInDebugSnapshot: true,
110
+ includeInStateLogs: false,
111
+ usedInUi: true,
112
+ },
81
113
  requests: {
82
114
  persist: false,
83
115
  includeInDebugSnapshot: true,
84
116
  includeInStateLogs: false,
85
117
  usedInUi: true,
86
118
  },
119
+ nativeProviders: {
120
+ persist: false,
121
+ includeInDebugSnapshot: true,
122
+ includeInStateLogs: false,
123
+ usedInUi: true,
124
+ },
87
125
  };
88
126
  /**
89
127
  * Creates a default resource state object.
@@ -118,9 +156,46 @@ export function getDefaultRampsControllerState() {
118
156
  tokens: createDefaultResourceState(null, null),
119
157
  paymentMethods: createDefaultResourceState([], null),
120
158
  quotes: createDefaultResourceState(null, null),
159
+ widgetUrl: createDefaultResourceState(null),
121
160
  requests: {},
161
+ nativeProviders: {
162
+ transak: {
163
+ isAuthenticated: false,
164
+ userDetails: createDefaultResourceState(null),
165
+ buyQuote: createDefaultResourceState(null),
166
+ kycRequirement: createDefaultResourceState(null),
167
+ },
168
+ },
122
169
  };
123
170
  }
171
+ const DEPENDENT_RESOURCE_KEYS = [
172
+ 'providers',
173
+ 'tokens',
174
+ 'paymentMethods',
175
+ 'quotes',
176
+ ];
177
+ const DEPENDENT_RESOURCE_KEYS_SET = new Set(DEPENDENT_RESOURCE_KEYS);
178
+ function resetResource(state, resourceType, defaultResource) {
179
+ const def = defaultResource ?? getDefaultRampsControllerState()[resourceType];
180
+ const resource = state[resourceType];
181
+ resource.data = def.data;
182
+ resource.selected = def.selected;
183
+ resource.isLoading = def.isLoading;
184
+ resource.error = def.error;
185
+ }
186
+ /**
187
+ * Resets the widgetUrl resource to its default state.
188
+ * Mutates state in place; use from within controller update() for atomic updates.
189
+ *
190
+ * @param state - The state object to mutate.
191
+ */
192
+ function resetWidgetUrl(state) {
193
+ const def = getDefaultRampsControllerState().widgetUrl;
194
+ state.widgetUrl.data = def.data;
195
+ state.widgetUrl.selected = def.selected;
196
+ state.widgetUrl.isLoading = def.isLoading;
197
+ state.widgetUrl.error = def.error;
198
+ }
124
199
  /**
125
200
  * Resets region-dependent resources (userRegion, providers, tokens, paymentMethods, quotes).
126
201
  * Mutates state in place; use from within controller update() for atomic updates.
@@ -133,22 +208,11 @@ function resetDependentResources(state, options) {
133
208
  if (options?.clearUserRegionData) {
134
209
  state.userRegion = null;
135
210
  }
136
- state.providers.selected = null;
137
- state.providers.data = [];
138
- state.providers.isLoading = false;
139
- state.providers.error = null;
140
- state.tokens.selected = null;
141
- state.tokens.data = null;
142
- state.tokens.isLoading = false;
143
- state.tokens.error = null;
144
- state.paymentMethods.data = [];
145
- state.paymentMethods.selected = null;
146
- state.paymentMethods.isLoading = false;
147
- state.paymentMethods.error = null;
148
- state.quotes.data = null;
149
- state.quotes.selected = null;
150
- state.quotes.isLoading = false;
151
- state.quotes.error = null;
211
+ const defaultState = getDefaultRampsControllerState();
212
+ for (const key of DEPENDENT_RESOURCE_KEYS) {
213
+ resetResource(state, key, defaultState[key]);
214
+ }
215
+ resetWidgetUrl(state);
152
216
  }
153
217
  // === HELPER FUNCTIONS ===
154
218
  /**
@@ -272,31 +336,49 @@ export class RampsController extends BaseController {
272
336
  __classPrivateFieldSet(this, _RampsController_requestCacheMaxSize, requestCacheMaxSize, "f");
273
337
  }
274
338
  /**
275
- * Executes a request with caching and deduplication.
339
+ * Executes a request with caching, deduplication, and at most one in-flight
340
+ * request per resource type.
276
341
  *
277
- * If a request with the same cache key is already in flight, returns the
278
- * existing promise. If valid cached data exists, returns it without making
279
- * a new request.
342
+ * 1. **Same cache key in flight** – If a request with this cache key is
343
+ * already pending, returns that promise (deduplication; no second request).
280
344
  *
281
- * @param cacheKey - Unique identifier for this request.
282
- * @param fetcher - Function that performs the actual fetch. Receives an AbortSignal.
283
- * @param options - Options for cache behavior.
284
- * @returns The result of the request.
345
+ * 2. **Cache hit** – If valid, non-expired data exists in state.requests for
346
+ * this key and forceRefresh is not set, returns that data without fetching.
347
+ *
348
+ * 3. **New request** Creates an AbortController and fires the fetcher.
349
+ * If options.resourceType is set, tags the pending request with that
350
+ * resource type (so #abortDependentRequests can cancel it on region
351
+ * change or cleanup) and ref-counts resource-level loading state.
352
+ * On success or error, updates request state and resource error;
353
+ * in finally, clears resource loading only if this request was not
354
+ * aborted.
355
+ *
356
+ * @param cacheKey - Unique identifier for this request (e.g. from createCacheKey).
357
+ * @param fetcher - Async function that performs the fetch. Receives an AbortSignal
358
+ * that is aborted when this request is superseded by another for the same resource.
359
+ * @param options - Optional forceRefresh, ttl, and resourceType for loading/error state.
360
+ * @returns The result of the request (from cache, joined promise, or fetcher).
285
361
  */
286
362
  async executeRequest(cacheKey, fetcher, options) {
363
+ // Get TTL for verifying cache expiration
287
364
  const ttl = options?.ttl ?? __classPrivateFieldGet(this, _RampsController_requestCacheTTL, "f");
288
- // Check for existing pending request - join it instead of making a duplicate
365
+ // DEDUPLICATION:
366
+ // Check if a request is already in flight for this cache key
367
+ // If so, return the original promise for that request
289
368
  const pending = __classPrivateFieldGet(this, _RampsController_pendingRequests, "f").get(cacheKey);
290
369
  if (pending) {
291
370
  return pending.promise;
292
371
  }
372
+ // CACHE HIT:
373
+ // If cache is not expired, return the cached data
293
374
  if (!options?.forceRefresh) {
294
375
  const cached = this.state.requests[cacheKey];
295
376
  if (cached && !isCacheExpired(cached, ttl)) {
296
377
  return cached.data;
297
378
  }
298
379
  }
299
- // Create abort controller for this request
380
+ // Create a new abort controller for this request
381
+ // Record the time the request was started
300
382
  const abortController = new AbortController();
301
383
  const lastFetchedAt = Date.now();
302
384
  const { resourceType } = options ?? {};
@@ -315,15 +397,11 @@ export class RampsController extends BaseController {
315
397
  const promise = (async () => {
316
398
  try {
317
399
  const data = await fetcher(abortController.signal);
318
- // Don't update state if aborted
319
400
  if (abortController.signal.aborted) {
320
401
  throw new Error('Request was aborted');
321
402
  }
322
403
  __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_updateRequestState).call(this, cacheKey, createSuccessState(data, lastFetchedAt));
323
404
  if (resourceType) {
324
- // We need the extra logic because there are two situations where we’re allowed to clear the error:
325
- // No callback → always clear
326
- // Callback present → clear only when isResultCurrent() returns true.
327
405
  const isCurrent = !options?.isResultCurrent || options.isResultCurrent();
328
406
  if (isCurrent) {
329
407
  __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_setResourceError).call(this, resourceType, null);
@@ -332,7 +410,6 @@ export class RampsController extends BaseController {
332
410
  return data;
333
411
  }
334
412
  catch (error) {
335
- // Don't update state if aborted
336
413
  if (abortController.signal.aborted) {
337
414
  throw error;
338
415
  }
@@ -347,13 +424,12 @@ export class RampsController extends BaseController {
347
424
  throw error;
348
425
  }
349
426
  finally {
350
- // Only delete if this is still our entry (not replaced by a new request)
351
- const currentPending = __classPrivateFieldGet(this, _RampsController_pendingRequests, "f").get(cacheKey);
352
- if (currentPending?.abortController === abortController) {
427
+ if (__classPrivateFieldGet(this, _RampsController_pendingRequests, "f").get(cacheKey)?.abortController ===
428
+ abortController) {
353
429
  __classPrivateFieldGet(this, _RampsController_pendingRequests, "f").delete(cacheKey);
354
430
  }
355
431
  // Clear resource-level loading state only when no requests for this resource remain
356
- if (resourceType) {
432
+ if (resourceType && !abortController.signal.aborted) {
357
433
  const count = __classPrivateFieldGet(this, _RampsController_pendingResourceCount, "f").get(resourceType) ?? 0;
358
434
  const next = Math.max(0, count - 1);
359
435
  if (next === 0) {
@@ -366,8 +442,11 @@ export class RampsController extends BaseController {
366
442
  }
367
443
  }
368
444
  })();
369
- // Store pending request for deduplication
370
- __classPrivateFieldGet(this, _RampsController_pendingRequests, "f").set(cacheKey, { promise, abortController });
445
+ __classPrivateFieldGet(this, _RampsController_pendingRequests, "f").set(cacheKey, {
446
+ promise,
447
+ abortController,
448
+ resourceType,
449
+ });
371
450
  return promise;
372
451
  }
373
452
  /**
@@ -421,9 +500,8 @@ export class RampsController extends BaseController {
421
500
  !this.state.tokens.data ||
422
501
  this.state.providers.data.length === 0;
423
502
  if (regionChanged) {
503
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_abortDependentRequests).call(this);
424
504
  __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_clearPendingResourceCountForDependentResources).call(this);
425
- }
426
- if (regionChanged) {
427
505
  this.stopQuotePolling();
428
506
  }
429
507
  this.update((state) => {
@@ -464,15 +542,11 @@ export class RampsController extends BaseController {
464
542
  this.stopQuotePolling();
465
543
  this.update((state) => {
466
544
  state.providers.selected = null;
467
- state.paymentMethods.data = [];
468
- state.paymentMethods.selected = null;
545
+ resetResource(state, 'paymentMethods');
469
546
  });
470
547
  return;
471
548
  }
472
- const regionCode = this.state.userRegion?.regionCode;
473
- if (!regionCode) {
474
- throw new Error('Region is required. Cannot set selected provider without valid region information.');
475
- }
549
+ const regionCode = __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_requireRegion).call(this);
476
550
  const providers = this.state.providers.data;
477
551
  if (!providers || providers.length === 0) {
478
552
  throw new Error('Providers not loaded. Cannot set selected provider before providers are fetched.');
@@ -483,9 +557,9 @@ export class RampsController extends BaseController {
483
557
  }
484
558
  this.update((state) => {
485
559
  state.providers.selected = provider;
486
- state.paymentMethods.data = [];
487
- state.paymentMethods.selected = null;
560
+ resetResource(state, 'paymentMethods');
488
561
  state.quotes.selected = null;
562
+ resetWidgetUrl(state);
489
563
  });
490
564
  __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_fireAndForget).call(this, this.getPaymentMethods(regionCode, { provider: provider.id }).then(() => {
491
565
  // Restart quote polling after payment methods are fetched
@@ -513,10 +587,7 @@ export class RampsController extends BaseController {
513
587
  await this.setUserRegion(regionCode, options);
514
588
  }
515
589
  hydrateState(options) {
516
- const regionCode = this.state.userRegion?.regionCode;
517
- if (!regionCode) {
518
- throw new Error('Region code is required. Cannot hydrate state without valid region information.');
519
- }
590
+ const regionCode = __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_requireRegion).call(this);
520
591
  __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_fireAndForget).call(this, this.getTokens(regionCode, 'buy', options));
521
592
  __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_fireAndForget).call(this, this.getProviders(regionCode, options));
522
593
  }
@@ -534,7 +605,7 @@ export class RampsController extends BaseController {
534
605
  return this.messenger.call('RampsService:getCountries');
535
606
  }, { ...options, resourceType: 'countries' });
536
607
  this.update((state) => {
537
- state.countries.data = countries;
608
+ state.countries.data = Array.isArray(countries) ? [...countries] : [];
538
609
  });
539
610
  return countries;
540
611
  }
@@ -549,10 +620,7 @@ export class RampsController extends BaseController {
549
620
  * @returns The tokens response containing topTokens and allTokens.
550
621
  */
551
622
  async getTokens(region, action = 'buy', options) {
552
- const regionToUse = region ?? this.state.userRegion?.regionCode;
553
- if (!regionToUse) {
554
- throw new Error('Region is required. Either provide a region parameter or ensure userRegion is set in controller state.');
555
- }
623
+ const regionToUse = region ?? __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_requireRegion).call(this);
556
624
  const normalizedRegion = regionToUse.toLowerCase().trim();
557
625
  const cacheKey = createCacheKey('getTokens', [
558
626
  normalizedRegion,
@@ -566,8 +634,7 @@ export class RampsController extends BaseController {
566
634
  }, {
567
635
  ...options,
568
636
  resourceType: 'tokens',
569
- isResultCurrent: () => this.state.userRegion?.regionCode === undefined ||
570
- this.state.userRegion?.regionCode === normalizedRegion,
637
+ isResultCurrent: () => __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_isRegionCurrent).call(this, normalizedRegion),
571
638
  });
572
639
  this.update((state) => {
573
640
  const userRegionCode = state.userRegion?.regionCode;
@@ -590,15 +657,11 @@ export class RampsController extends BaseController {
590
657
  this.stopQuotePolling();
591
658
  this.update((state) => {
592
659
  state.tokens.selected = null;
593
- state.paymentMethods.data = [];
594
- state.paymentMethods.selected = null;
660
+ resetResource(state, 'paymentMethods');
595
661
  });
596
662
  return;
597
663
  }
598
- const regionCode = this.state.userRegion?.regionCode;
599
- if (!regionCode) {
600
- throw new Error('Region is required. Cannot set selected token without valid region information.');
601
- }
664
+ const regionCode = __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_requireRegion).call(this);
602
665
  const tokens = this.state.tokens.data;
603
666
  if (!tokens) {
604
667
  throw new Error('Tokens not loaded. Cannot set selected token before tokens are fetched.');
@@ -610,9 +673,9 @@ export class RampsController extends BaseController {
610
673
  }
611
674
  this.update((state) => {
612
675
  state.tokens.selected = token;
613
- state.paymentMethods.data = [];
614
- state.paymentMethods.selected = null;
676
+ resetResource(state, 'paymentMethods');
615
677
  state.quotes.selected = null;
678
+ resetWidgetUrl(state);
616
679
  });
617
680
  __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_fireAndForget).call(this, this.getPaymentMethods(regionCode, { assetId: token.assetId }).then(() => {
618
681
  __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_restartPollingIfActive).call(this);
@@ -632,10 +695,7 @@ export class RampsController extends BaseController {
632
695
  * @returns The providers response containing providers array.
633
696
  */
634
697
  async getProviders(region, options) {
635
- const regionToUse = region ?? this.state.userRegion?.regionCode;
636
- if (!regionToUse) {
637
- throw new Error('Region is required. Either provide a region parameter or ensure userRegion is set in controller state.');
638
- }
698
+ const regionToUse = region ?? __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_requireRegion).call(this);
639
699
  const normalizedRegion = regionToUse.toLowerCase().trim();
640
700
  const cacheKey = createCacheKey('getProviders', [
641
701
  normalizedRegion,
@@ -654,8 +714,7 @@ export class RampsController extends BaseController {
654
714
  }, {
655
715
  ...options,
656
716
  resourceType: 'providers',
657
- isResultCurrent: () => this.state.userRegion?.regionCode === undefined ||
658
- this.state.userRegion?.regionCode === normalizedRegion,
717
+ isResultCurrent: () => __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_isRegionCurrent).call(this, normalizedRegion),
659
718
  });
660
719
  this.update((state) => {
661
720
  const userRegionCode = state.userRegion?.regionCode;
@@ -677,13 +736,10 @@ export class RampsController extends BaseController {
677
736
  * @returns The payment methods response containing payments array.
678
737
  */
679
738
  async getPaymentMethods(region, options) {
680
- const regionCode = region ?? this.state.userRegion?.regionCode ?? null;
739
+ const regionCode = region ?? __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_requireRegion).call(this);
681
740
  const fiatToUse = options?.fiat ?? this.state.userRegion?.country?.currency ?? null;
682
741
  const assetIdToUse = options?.assetId ?? this.state.tokens.selected?.assetId ?? '';
683
742
  const providerToUse = options?.provider ?? this.state.providers.selected?.id ?? '';
684
- if (!regionCode) {
685
- throw new Error('Region is required. Either provide a region parameter or ensure userRegion is set in controller state.');
686
- }
687
743
  if (!fiatToUse) {
688
744
  throw new Error('Fiat currency is required. Either provide a fiat parameter or ensure userRegion is set in controller state.');
689
745
  }
@@ -706,10 +762,9 @@ export class RampsController extends BaseController {
706
762
  ...options,
707
763
  resourceType: 'paymentMethods',
708
764
  isResultCurrent: () => {
709
- const regionMatch = this.state.userRegion?.regionCode === undefined ||
710
- this.state.userRegion?.regionCode === normalizedRegion;
711
- const tokenMatch = (this.state.tokens.selected?.assetId ?? '') === assetIdToUse;
712
- const providerMatch = (this.state.providers.selected?.id ?? '') === providerToUse;
765
+ const regionMatch = __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_isRegionCurrent).call(this, normalizedRegion);
766
+ const tokenMatch = __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_isTokenCurrent).call(this, assetIdToUse);
767
+ const providerMatch = __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_isProviderCurrent).call(this, providerToUse);
713
768
  return regionMatch && tokenMatch && providerMatch;
714
769
  },
715
770
  });
@@ -779,7 +834,7 @@ export class RampsController extends BaseController {
779
834
  * @returns The quotes response containing success, sorted, error, and customActions.
780
835
  */
781
836
  async getQuotes(options) {
782
- const regionToUse = options.region ?? this.state.userRegion?.regionCode;
837
+ const regionToUse = options.region ?? __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_requireRegion).call(this);
783
838
  const fiatToUse = options.fiat ?? this.state.userRegion?.country?.currency;
784
839
  const paymentMethodsToUse = options.paymentMethods ??
785
840
  this.state.paymentMethods.data.map((pm) => pm.id);
@@ -787,9 +842,6 @@ export class RampsController extends BaseController {
787
842
  this.state.providers.data.map((provider) => provider.id);
788
843
  const action = options.action ?? 'buy';
789
844
  const assetIdToUse = options.assetId ?? this.state.tokens.selected?.assetId;
790
- if (!regionToUse) {
791
- throw new Error('Region is required. Either provide a region parameter or ensure userRegion is set in controller state.');
792
- }
793
845
  if (!fiatToUse) {
794
846
  throw new Error('Fiat currency is required. Either provide a fiat parameter or ensure userRegion is set in controller state.');
795
847
  }
@@ -840,8 +892,7 @@ export class RampsController extends BaseController {
840
892
  forceRefresh: options.forceRefresh,
841
893
  ttl: options.ttl ?? DEFAULT_QUOTES_TTL,
842
894
  resourceType: 'quotes',
843
- isResultCurrent: () => this.state.userRegion?.regionCode === undefined ||
844
- this.state.userRegion?.regionCode === normalizedRegion,
895
+ isResultCurrent: () => __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_isRegionCurrent).call(this, normalizedRegion),
845
896
  });
846
897
  this.update((state) => {
847
898
  const userRegionCode = state.userRegion?.regionCode;
@@ -857,21 +908,20 @@ export class RampsController extends BaseController {
857
908
  * If the response contains exactly one quote, it is auto-selected.
858
909
  * If multiple quotes are returned, the existing selection is preserved if still valid.
859
910
  *
911
+ * Returns early (no-op) if the selected payment method is not yet set,
912
+ * allowing callers to invoke this before payment-method selection is finalized.
913
+ *
860
914
  * @param options - Parameters for fetching quotes.
861
915
  * @param options.walletAddress - The destination wallet address.
862
916
  * @param options.amount - The amount (in fiat for buy, crypto for sell).
863
917
  * @param options.redirectUrl - Optional redirect URL after order completion.
864
- * @throws If required dependencies (region, token, provider, payment method) are not set.
918
+ * @throws If required dependencies (region, token, provider) are not set.
865
919
  */
866
920
  startQuotePolling(options) {
867
- // Validate required dependencies
868
- const regionCode = this.state.userRegion?.regionCode;
921
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_requireRegion).call(this);
869
922
  const token = this.state.tokens.selected;
870
923
  const provider = this.state.providers.selected;
871
924
  const paymentMethod = this.state.paymentMethods.selected;
872
- if (!regionCode) {
873
- throw new Error('Region is required. Cannot start quote polling without valid region information.');
874
- }
875
925
  if (!token) {
876
926
  throw new Error('Token is required. Cannot start quote polling without a selected token.');
877
927
  }
@@ -896,10 +946,12 @@ export class RampsController extends BaseController {
896
946
  providers: [provider.id],
897
947
  forceRefresh: true,
898
948
  }).then((response) => {
949
+ let newSelectedQuote = null;
899
950
  // Auto-select logic: only when exactly one quote is returned
900
951
  this.update((state) => {
901
952
  if (response.success.length === 1) {
902
- state.quotes.selected = response.success[0];
953
+ newSelectedQuote = response.success[0];
954
+ state.quotes.selected = newSelectedQuote;
903
955
  }
904
956
  else {
905
957
  // Keep existing selection if still valid, but update with fresh data
@@ -908,11 +960,12 @@ export class RampsController extends BaseController {
908
960
  const freshQuote = response.success.find((quote) => quote.provider === currentSelection.provider &&
909
961
  quote.quote.paymentMethod ===
910
962
  currentSelection.quote.paymentMethod);
911
- // Update with fresh quote data, or clear if no longer valid
912
- state.quotes.selected = freshQuote ?? null;
963
+ newSelectedQuote = freshQuote ?? null;
964
+ state.quotes.selected = newSelectedQuote;
913
965
  }
914
966
  }
915
967
  });
968
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_syncWidgetUrl).call(this, newSelectedQuote);
916
969
  return undefined;
917
970
  }));
918
971
  };
@@ -934,6 +987,7 @@ export class RampsController extends BaseController {
934
987
  }
935
988
  /**
936
989
  * Manually sets the selected quote.
990
+ * Automatically triggers a widget URL fetch for the new quote.
937
991
  *
938
992
  * @param quote - The quote to select, or null to clear the selection.
939
993
  */
@@ -941,6 +995,7 @@ export class RampsController extends BaseController {
941
995
  this.update((state) => {
942
996
  state.quotes.selected = quote;
943
997
  });
998
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_syncWidgetUrl).call(this, quote);
944
999
  }
945
1000
  /**
946
1001
  * Cleans up controller resources.
@@ -958,6 +1013,8 @@ export class RampsController extends BaseController {
958
1013
  *
959
1014
  * @param quote - The quote to fetch the widget URL from.
960
1015
  * @returns Promise resolving to the widget URL string, or null if not available.
1016
+ * @deprecated Read `state.widgetUrl` instead. The widget URL is now automatically
1017
+ * fetched and stored in state whenever the selected quote changes.
961
1018
  */
962
1019
  async getWidgetUrl(quote) {
963
1020
  const buyUrl = quote.quote?.buyURL;
@@ -968,33 +1025,458 @@ export class RampsController extends BaseController {
968
1025
  const buyWidget = await this.messenger.call('RampsService:getBuyWidgetUrl', buyUrl);
969
1026
  return buyWidget.url ?? null;
970
1027
  }
971
- catch (error) {
972
- console.error('Error fetching widget URL:', error);
1028
+ catch {
973
1029
  return null;
974
1030
  }
975
1031
  }
1032
+ /**
1033
+ * Fetches an order from the unified V2 API endpoint.
1034
+ * Returns a normalized RampsOrder for all provider types (aggregator and native).
1035
+ *
1036
+ * @param providerCode - The provider code (e.g., "transak", "transak-native", "moonpay").
1037
+ * @param orderCode - The order identifier.
1038
+ * @param wallet - The wallet address associated with the order.
1039
+ * @returns The unified order data.
1040
+ */
1041
+ async getOrder(providerCode, orderCode, wallet) {
1042
+ return await this.messenger.call('RampsService:getOrder', providerCode, orderCode, wallet);
1043
+ }
1044
+ /**
1045
+ * Extracts an order from a provider callback URL.
1046
+ * Sends the callback URL to the V2 backend for provider-specific parsing,
1047
+ * then fetches the full order. This is the V2 equivalent of the aggregator
1048
+ * SDK's `getOrderFromCallback`.
1049
+ *
1050
+ * @param providerCode - The provider code (e.g., "transak", "moonpay").
1051
+ * @param callbackUrl - The full callback URL the provider redirected to.
1052
+ * @param wallet - The wallet address associated with the order.
1053
+ * @returns The unified order data.
1054
+ */
1055
+ async getOrderFromCallback(providerCode, callbackUrl, wallet) {
1056
+ return await this.messenger.call('RampsService:getOrderFromCallback', providerCode, callbackUrl, wallet);
1057
+ }
1058
+ /**
1059
+ * Sets the Transak API key used for all Transak API requests.
1060
+ *
1061
+ * @param apiKey - The Transak API key.
1062
+ */
1063
+ transakSetApiKey(apiKey) {
1064
+ this.messenger.call('TransakService:setApiKey', apiKey);
1065
+ }
1066
+ /**
1067
+ * Sets the Transak access token and marks the user as authenticated.
1068
+ *
1069
+ * @param token - The access token received from Transak auth.
1070
+ */
1071
+ transakSetAccessToken(token) {
1072
+ this.messenger.call('TransakService:setAccessToken', token);
1073
+ this.transakSetAuthenticated(true);
1074
+ }
1075
+ /**
1076
+ * Clears the Transak access token and marks the user as unauthenticated.
1077
+ */
1078
+ transakClearAccessToken() {
1079
+ this.messenger.call('TransakService:clearAccessToken');
1080
+ this.transakSetAuthenticated(false);
1081
+ }
1082
+ /**
1083
+ * Updates the Transak authentication flag in controller state.
1084
+ *
1085
+ * @param isAuthenticated - Whether the user is authenticated with Transak.
1086
+ */
1087
+ transakSetAuthenticated(isAuthenticated) {
1088
+ this.update((state) => {
1089
+ state.nativeProviders.transak.isAuthenticated = isAuthenticated;
1090
+ });
1091
+ }
1092
+ /**
1093
+ * Resets all Transak state back to defaults (unauthenticated, no data).
1094
+ */
1095
+ transakResetState() {
1096
+ this.messenger.call('TransakService:clearAccessToken');
1097
+ this.update((state) => {
1098
+ state.nativeProviders.transak =
1099
+ getDefaultRampsControllerState().nativeProviders.transak;
1100
+ });
1101
+ }
1102
+ /**
1103
+ * Sends a one-time password to the user's email for Transak authentication.
1104
+ *
1105
+ * @param email - The user's email address.
1106
+ * @returns The OTP response containing a state token for verification.
1107
+ */
1108
+ async transakSendUserOtp(email) {
1109
+ return this.messenger.call('TransakService:sendUserOtp', email);
1110
+ }
1111
+ /**
1112
+ * Verifies a one-time password and authenticates the user with Transak.
1113
+ * Updates the controller's authentication state on success.
1114
+ *
1115
+ * @param email - The user's email address.
1116
+ * @param verificationCode - The OTP code entered by the user.
1117
+ * @param stateToken - The state token from the sendUserOtp response.
1118
+ * @returns The access token for subsequent authenticated requests.
1119
+ */
1120
+ async transakVerifyUserOtp(email, verificationCode, stateToken) {
1121
+ const token = await this.messenger.call('TransakService:verifyUserOtp', email, verificationCode, stateToken);
1122
+ this.transakSetAuthenticated(true);
1123
+ return token;
1124
+ }
1125
+ /**
1126
+ * Logs the user out of Transak. Clears authentication state and user details
1127
+ * regardless of whether the API call succeeds or fails.
1128
+ *
1129
+ * @returns A message indicating the logout result.
1130
+ */
1131
+ async transakLogout() {
1132
+ try {
1133
+ const result = await this.messenger.call('TransakService:logout');
1134
+ return result;
1135
+ }
1136
+ finally {
1137
+ this.transakClearAccessToken();
1138
+ this.update((state) => {
1139
+ state.nativeProviders.transak.userDetails.data = null;
1140
+ });
1141
+ }
1142
+ }
1143
+ /**
1144
+ * Fetches the authenticated user's details from Transak.
1145
+ * Updates the userDetails resource state with loading/success/error states.
1146
+ *
1147
+ * @returns The user's profile and KYC details.
1148
+ */
1149
+ async transakGetUserDetails() {
1150
+ this.update((state) => {
1151
+ state.nativeProviders.transak.userDetails.isLoading = true;
1152
+ state.nativeProviders.transak.userDetails.error = null;
1153
+ });
1154
+ try {
1155
+ const details = await this.messenger.call('TransakService:getUserDetails');
1156
+ this.update((state) => {
1157
+ state.nativeProviders.transak.userDetails.data = details;
1158
+ state.nativeProviders.transak.userDetails.isLoading = false;
1159
+ });
1160
+ return details;
1161
+ }
1162
+ catch (error) {
1163
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_syncTransakAuthOnError).call(this, error);
1164
+ const errorMessage = error?.message ?? 'Unknown error';
1165
+ this.update((state) => {
1166
+ state.nativeProviders.transak.userDetails.isLoading = false;
1167
+ state.nativeProviders.transak.userDetails.error = errorMessage;
1168
+ });
1169
+ throw error;
1170
+ }
1171
+ }
1172
+ /**
1173
+ * Fetches a buy quote from Transak for the given parameters.
1174
+ * Updates the buyQuote resource state with loading/success/error states.
1175
+ *
1176
+ * @param fiatCurrency - The fiat currency code (e.g., "USD").
1177
+ * @param cryptoCurrency - The cryptocurrency identifier.
1178
+ * @param network - The blockchain network identifier.
1179
+ * @param paymentMethod - The payment method identifier.
1180
+ * @param fiatAmount - The fiat amount as a string.
1181
+ * @returns The buy quote with pricing and fee details.
1182
+ */
1183
+ async transakGetBuyQuote(fiatCurrency, cryptoCurrency, network, paymentMethod, fiatAmount) {
1184
+ this.update((state) => {
1185
+ state.nativeProviders.transak.buyQuote.isLoading = true;
1186
+ state.nativeProviders.transak.buyQuote.error = null;
1187
+ });
1188
+ try {
1189
+ const quote = await this.messenger.call('TransakService:getBuyQuote', fiatCurrency, cryptoCurrency, network, paymentMethod, fiatAmount);
1190
+ this.update((state) => {
1191
+ state.nativeProviders.transak.buyQuote.data = quote;
1192
+ state.nativeProviders.transak.buyQuote.isLoading = false;
1193
+ });
1194
+ return quote;
1195
+ }
1196
+ catch (error) {
1197
+ const errorMessage = error?.message ?? 'Unknown error';
1198
+ this.update((state) => {
1199
+ state.nativeProviders.transak.buyQuote.isLoading = false;
1200
+ state.nativeProviders.transak.buyQuote.error = errorMessage;
1201
+ });
1202
+ throw error;
1203
+ }
1204
+ }
1205
+ /**
1206
+ * Fetches the KYC requirement for a given quote.
1207
+ * Updates the kycRequirement resource state with loading/success/error states.
1208
+ *
1209
+ * @param quoteId - The quote ID to check KYC requirements for.
1210
+ * @returns The KYC requirement status and whether the user can place an order.
1211
+ */
1212
+ async transakGetKycRequirement(quoteId) {
1213
+ this.update((state) => {
1214
+ state.nativeProviders.transak.kycRequirement.isLoading = true;
1215
+ state.nativeProviders.transak.kycRequirement.error = null;
1216
+ });
1217
+ try {
1218
+ const requirement = await this.messenger.call('TransakService:getKycRequirement', quoteId);
1219
+ this.update((state) => {
1220
+ state.nativeProviders.transak.kycRequirement.data = requirement;
1221
+ state.nativeProviders.transak.kycRequirement.isLoading = false;
1222
+ });
1223
+ return requirement;
1224
+ }
1225
+ catch (error) {
1226
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_syncTransakAuthOnError).call(this, error);
1227
+ const errorMessage = error?.message ?? 'Unknown error';
1228
+ this.update((state) => {
1229
+ state.nativeProviders.transak.kycRequirement.isLoading = false;
1230
+ state.nativeProviders.transak.kycRequirement.error = errorMessage;
1231
+ });
1232
+ throw error;
1233
+ }
1234
+ }
1235
+ /**
1236
+ * Fetches additional KYC requirements (e.g., ID proof, address proof) for a quote.
1237
+ *
1238
+ * @param quoteId - The quote ID to check additional requirements for.
1239
+ * @returns The list of additional forms required.
1240
+ */
1241
+ async transakGetAdditionalRequirements(quoteId) {
1242
+ try {
1243
+ return await this.messenger.call('TransakService:getAdditionalRequirements', quoteId);
1244
+ }
1245
+ catch (error) {
1246
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_syncTransakAuthOnError).call(this, error);
1247
+ throw error;
1248
+ }
1249
+ }
1250
+ /**
1251
+ * Creates a new order on Transak. If an existing order conflicts (HTTP 409),
1252
+ * active orders are cancelled and the creation is retried.
1253
+ *
1254
+ * @param quoteId - The quote ID to create an order from.
1255
+ * @param walletAddress - The destination wallet address.
1256
+ * @param paymentMethodId - The payment method to use.
1257
+ * @returns The created deposit order.
1258
+ */
1259
+ async transakCreateOrder(quoteId, walletAddress, paymentMethodId) {
1260
+ try {
1261
+ return await this.messenger.call('TransakService:createOrder', quoteId, walletAddress, paymentMethodId);
1262
+ }
1263
+ catch (error) {
1264
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_syncTransakAuthOnError).call(this, error);
1265
+ throw error;
1266
+ }
1267
+ }
1268
+ /**
1269
+ * Fetches an existing order from Transak by order ID.
1270
+ *
1271
+ * @param orderId - The order ID (deposit format or raw Transak format).
1272
+ * @param wallet - The wallet address associated with the order.
1273
+ * @param paymentDetails - Optional payment details to attach to the order.
1274
+ * @returns The deposit order details.
1275
+ */
1276
+ async transakGetOrder(orderId, wallet, paymentDetails) {
1277
+ return this.messenger.call('TransakService:getOrder', orderId, wallet, paymentDetails);
1278
+ }
1279
+ /**
1280
+ * Fetches the user's spending limits for a given currency and payment method.
1281
+ *
1282
+ * @param fiatCurrency - The fiat currency code.
1283
+ * @param paymentMethod - The payment method identifier.
1284
+ * @param kycType - The KYC level type.
1285
+ * @returns The user's limits, spending, and remaining amounts.
1286
+ */
1287
+ async transakGetUserLimits(fiatCurrency, paymentMethod, kycType) {
1288
+ try {
1289
+ return await this.messenger.call('TransakService:getUserLimits', fiatCurrency, paymentMethod, kycType);
1290
+ }
1291
+ catch (error) {
1292
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_syncTransakAuthOnError).call(this, error);
1293
+ throw error;
1294
+ }
1295
+ }
1296
+ /**
1297
+ * Requests a one-time token (OTT) for the Transak payment widget.
1298
+ *
1299
+ * @returns The OTT response containing the token.
1300
+ */
1301
+ async transakRequestOtt() {
1302
+ try {
1303
+ return await this.messenger.call('TransakService:requestOtt');
1304
+ }
1305
+ catch (error) {
1306
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_syncTransakAuthOnError).call(this, error);
1307
+ throw error;
1308
+ }
1309
+ }
1310
+ /**
1311
+ * Generates a URL for the Transak payment widget with pre-filled parameters.
1312
+ *
1313
+ * @param ottToken - The one-time token for widget authentication.
1314
+ * @param quote - The buy quote to pre-fill in the widget.
1315
+ * @param walletAddress - The destination wallet address.
1316
+ * @param extraParams - Optional additional URL parameters.
1317
+ * @returns The fully constructed widget URL string.
1318
+ */
1319
+ transakGeneratePaymentWidgetUrl(ottToken, quote, walletAddress, extraParams) {
1320
+ return this.messenger.call('TransakService:generatePaymentWidgetUrl', ottToken, quote, walletAddress, extraParams);
1321
+ }
1322
+ /**
1323
+ * Submits the user's purpose of usage form for KYC compliance.
1324
+ *
1325
+ * @param purpose - Array of purpose strings selected by the user.
1326
+ * @returns A promise that resolves when the form is submitted.
1327
+ */
1328
+ async transakSubmitPurposeOfUsageForm(purpose) {
1329
+ try {
1330
+ return await this.messenger.call('TransakService:submitPurposeOfUsageForm', purpose);
1331
+ }
1332
+ catch (error) {
1333
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_syncTransakAuthOnError).call(this, error);
1334
+ throw error;
1335
+ }
1336
+ }
1337
+ /**
1338
+ * Updates the user's personal or address details on Transak.
1339
+ *
1340
+ * @param data - The user data fields to update.
1341
+ * @returns The API response data.
1342
+ */
1343
+ async transakPatchUser(data) {
1344
+ try {
1345
+ return await this.messenger.call('TransakService:patchUser', data);
1346
+ }
1347
+ catch (error) {
1348
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_syncTransakAuthOnError).call(this, error);
1349
+ throw error;
1350
+ }
1351
+ }
1352
+ /**
1353
+ * Submits the user's SSN for identity verification.
1354
+ *
1355
+ * @param ssn - The Social Security Number.
1356
+ * @param quoteId - The quote ID associated with the order requiring SSN.
1357
+ * @returns The API response data.
1358
+ */
1359
+ async transakSubmitSsnDetails(ssn, quoteId) {
1360
+ try {
1361
+ return await this.messenger.call('TransakService:submitSsnDetails', ssn, quoteId);
1362
+ }
1363
+ catch (error) {
1364
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_syncTransakAuthOnError).call(this, error);
1365
+ throw error;
1366
+ }
1367
+ }
1368
+ /**
1369
+ * Confirms payment for an order after the user has completed payment.
1370
+ *
1371
+ * @param orderId - The order ID to confirm payment for.
1372
+ * @param paymentMethodId - The payment method used.
1373
+ * @returns Whether the payment confirmation was successful.
1374
+ */
1375
+ async transakConfirmPayment(orderId, paymentMethodId) {
1376
+ try {
1377
+ return await this.messenger.call('TransakService:confirmPayment', orderId, paymentMethodId);
1378
+ }
1379
+ catch (error) {
1380
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_syncTransakAuthOnError).call(this, error);
1381
+ throw error;
1382
+ }
1383
+ }
1384
+ /**
1385
+ * Translates generic ramps identifiers to Transak-specific identifiers.
1386
+ *
1387
+ * @param request - The translation request with optional identifiers to translate.
1388
+ * @returns The translated Transak-specific identifiers.
1389
+ */
1390
+ async transakGetTranslation(request) {
1391
+ return this.messenger.call('TransakService:getTranslation', request);
1392
+ }
1393
+ /**
1394
+ * Checks the status of an ID proof submission for KYC.
1395
+ *
1396
+ * @param workFlowRunId - The workflow run ID to check status for.
1397
+ * @returns The current ID proof status.
1398
+ */
1399
+ async transakGetIdProofStatus(workFlowRunId) {
1400
+ try {
1401
+ return await this.messenger.call('TransakService:getIdProofStatus', workFlowRunId);
1402
+ }
1403
+ catch (error) {
1404
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_syncTransakAuthOnError).call(this, error);
1405
+ throw error;
1406
+ }
1407
+ }
1408
+ /**
1409
+ * Cancels a specific Transak order.
1410
+ *
1411
+ * @param depositOrderId - The deposit order ID to cancel.
1412
+ * @returns A promise that resolves when the order is cancelled.
1413
+ */
1414
+ async transakCancelOrder(depositOrderId) {
1415
+ try {
1416
+ return await this.messenger.call('TransakService:cancelOrder', depositOrderId);
1417
+ }
1418
+ catch (error) {
1419
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_syncTransakAuthOnError).call(this, error);
1420
+ throw error;
1421
+ }
1422
+ }
1423
+ /**
1424
+ * Cancels all active Transak orders. Individual cancellation failures
1425
+ * are collected and returned rather than thrown.
1426
+ *
1427
+ * @returns An array of errors from any failed cancellations (empty if all succeeded).
1428
+ */
1429
+ async transakCancelAllActiveOrders() {
1430
+ try {
1431
+ return await this.messenger.call('TransakService:cancelAllActiveOrders');
1432
+ }
1433
+ catch (error) {
1434
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_syncTransakAuthOnError).call(this, error);
1435
+ throw error;
1436
+ }
1437
+ }
1438
+ /**
1439
+ * Fetches all active Transak orders for the authenticated user.
1440
+ *
1441
+ * @returns The list of active orders.
1442
+ */
1443
+ async transakGetActiveOrders() {
1444
+ try {
1445
+ return await this.messenger.call('TransakService:getActiveOrders');
1446
+ }
1447
+ catch (error) {
1448
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_syncTransakAuthOnError).call(this, error);
1449
+ throw error;
1450
+ }
1451
+ }
976
1452
  }
977
1453
  _RampsController_requestCacheTTL = new WeakMap(), _RampsController_requestCacheMaxSize = new WeakMap(), _RampsController_pendingRequests = new WeakMap(), _RampsController_pendingResourceCount = new WeakMap(), _RampsController_quotePollingInterval = new WeakMap(), _RampsController_quotePollingOptions = new WeakMap(), _RampsController_instances = new WeakSet(), _RampsController_clearPendingResourceCountForDependentResources = function _RampsController_clearPendingResourceCountForDependentResources() {
978
- const types = [
979
- 'providers',
980
- 'tokens',
981
- 'paymentMethods',
982
- 'quotes',
983
- ];
984
- for (const resourceType of types) {
1454
+ for (const resourceType of DEPENDENT_RESOURCE_KEYS) {
985
1455
  __classPrivateFieldGet(this, _RampsController_pendingResourceCount, "f").delete(resourceType);
986
1456
  }
987
- }, _RampsController_removeRequestState = function _RampsController_removeRequestState(cacheKey) {
1457
+ }, _RampsController_abortDependentRequests = function _RampsController_abortDependentRequests() {
1458
+ for (const [cacheKey, pending] of __classPrivateFieldGet(this, _RampsController_pendingRequests, "f").entries()) {
1459
+ if (pending.resourceType &&
1460
+ DEPENDENT_RESOURCE_KEYS_SET.has(pending.resourceType)) {
1461
+ pending.abortController.abort();
1462
+ __classPrivateFieldGet(this, _RampsController_pendingRequests, "f").delete(cacheKey);
1463
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_removeRequestState).call(this, cacheKey);
1464
+ }
1465
+ }
1466
+ }, _RampsController_mutateRequests = function _RampsController_mutateRequests(fn) {
988
1467
  this.update((state) => {
989
1468
  const requests = state.requests;
1469
+ fn(requests);
1470
+ });
1471
+ }, _RampsController_removeRequestState = function _RampsController_removeRequestState(cacheKey) {
1472
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_mutateRequests).call(this, (requests) => {
990
1473
  delete requests[cacheKey];
991
1474
  });
992
1475
  }, _RampsController_cleanupState = function _RampsController_cleanupState() {
993
1476
  this.stopQuotePolling();
1477
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_abortDependentRequests).call(this);
994
1478
  __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_clearPendingResourceCountForDependentResources).call(this);
995
- this.update((state) => resetDependentResources(state, {
996
- clearUserRegionData: true,
997
- }));
1479
+ this.update((state) => resetDependentResources(state, { clearUserRegionData: true }));
998
1480
  }, _RampsController_fireAndForget = function _RampsController_fireAndForget(promise) {
999
1481
  promise.catch((_error) => undefined);
1000
1482
  }, _RampsController_restartPollingIfActive = function _RampsController_restartPollingIfActive() {
@@ -1009,6 +1491,21 @@ _RampsController_requestCacheTTL = new WeakMap(), _RampsController_requestCacheM
1009
1491
  // when dependencies are available
1010
1492
  }
1011
1493
  }
1494
+ }, _RampsController_requireRegion = function _RampsController_requireRegion() {
1495
+ const regionCode = this.state.userRegion?.regionCode;
1496
+ if (!regionCode) {
1497
+ throw new Error('Region is required. Cannot proceed without valid region information.');
1498
+ }
1499
+ return regionCode;
1500
+ }, _RampsController_isRegionCurrent = function _RampsController_isRegionCurrent(normalizedRegion) {
1501
+ const current = this.state.userRegion?.regionCode;
1502
+ return current === undefined || current === normalizedRegion;
1503
+ }, _RampsController_isTokenCurrent = function _RampsController_isTokenCurrent(normalizedAssetId) {
1504
+ const current = this.state.tokens.selected?.assetId ?? '';
1505
+ return current === normalizedAssetId;
1506
+ }, _RampsController_isProviderCurrent = function _RampsController_isProviderCurrent(normalizedProviderId) {
1507
+ const current = this.state.providers.selected?.id ?? '';
1508
+ return current === normalizedProviderId;
1012
1509
  }, _RampsController_updateResourceField = function _RampsController_updateResourceField(resourceType, field, value) {
1013
1510
  this.update((state) => {
1014
1511
  const resource = state[resourceType];
@@ -1023,11 +1520,8 @@ _RampsController_requestCacheTTL = new WeakMap(), _RampsController_requestCacheM
1023
1520
  }, _RampsController_updateRequestState = function _RampsController_updateRequestState(cacheKey, requestState) {
1024
1521
  const maxSize = __classPrivateFieldGet(this, _RampsController_requestCacheMaxSize, "f");
1025
1522
  const ttl = __classPrivateFieldGet(this, _RampsController_requestCacheTTL, "f");
1026
- this.update((state) => {
1027
- const requests = state.requests;
1523
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_mutateRequests).call(this, (requests) => {
1028
1524
  requests[cacheKey] = requestState;
1029
- // Evict expired entries based on TTL
1030
- // Only evict SUCCESS states that have exceeded their TTL
1031
1525
  const keys = Object.keys(requests);
1032
1526
  for (const key of keys) {
1033
1527
  const entry = requests[key];
@@ -1036,16 +1530,13 @@ _RampsController_requestCacheTTL = new WeakMap(), _RampsController_requestCacheM
1036
1530
  delete requests[key];
1037
1531
  }
1038
1532
  }
1039
- // Evict oldest entries if cache still exceeds max size
1040
1533
  const remainingKeys = Object.keys(requests);
1041
1534
  if (remainingKeys.length > maxSize) {
1042
- // Sort by timestamp (oldest first)
1043
1535
  const sortedKeys = remainingKeys.sort((a, b) => {
1044
1536
  const aTime = requests[a]?.timestamp ?? 0;
1045
1537
  const bTime = requests[b]?.timestamp ?? 0;
1046
1538
  return aTime - bTime;
1047
1539
  });
1048
- // Remove oldest entries until we're under the limit
1049
1540
  const entriesToRemove = remainingKeys.length - maxSize;
1050
1541
  for (let i = 0; i < entriesToRemove; i++) {
1051
1542
  const keyToRemove = sortedKeys[i];
@@ -1055,5 +1546,44 @@ _RampsController_requestCacheTTL = new WeakMap(), _RampsController_requestCacheM
1055
1546
  }
1056
1547
  }
1057
1548
  });
1549
+ }, _RampsController_syncWidgetUrl = function _RampsController_syncWidgetUrl(quote) {
1550
+ const buyUrl = quote?.quote?.buyURL;
1551
+ if (!buyUrl) {
1552
+ this.update((state) => {
1553
+ resetWidgetUrl(state);
1554
+ });
1555
+ return;
1556
+ }
1557
+ if (this.state.widgetUrl.data === null) {
1558
+ this.update((state) => {
1559
+ state.widgetUrl.isLoading = true;
1560
+ state.widgetUrl.error = null;
1561
+ });
1562
+ }
1563
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_fireAndForget).call(this, this.messenger
1564
+ .call('RampsService:getBuyWidgetUrl', buyUrl)
1565
+ .then((buyWidget) => {
1566
+ this.update((state) => {
1567
+ state.widgetUrl.data = buyWidget;
1568
+ state.widgetUrl.isLoading = false;
1569
+ state.widgetUrl.error = null;
1570
+ });
1571
+ return undefined;
1572
+ })
1573
+ .catch((error) => {
1574
+ this.update((state) => {
1575
+ state.widgetUrl.isLoading = false;
1576
+ state.widgetUrl.error =
1577
+ error instanceof Error
1578
+ ? error.message
1579
+ : 'Failed to fetch widget URL';
1580
+ });
1581
+ }));
1582
+ }, _RampsController_syncTransakAuthOnError = function _RampsController_syncTransakAuthOnError(error) {
1583
+ if (error instanceof Error &&
1584
+ 'httpStatus' in error &&
1585
+ error.httpStatus === 401) {
1586
+ this.transakSetAuthenticated(false);
1587
+ }
1058
1588
  };
1059
1589
  //# sourceMappingURL=RampsController.mjs.map