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