@metamask-previews/ramps-controller 5.1.0-preview-dcbbb24 → 5.1.0-preview-57408350

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ### Changed
11
+
12
+ - **BREAKING:** Restructure `RampsControllerState` to use nested `ResourceState` objects for each resource with `data`, `selected`, `isLoading`, and `error` ([#7779](https://github.com/MetaMask/core/pull/7779))
13
+
10
14
  ## [5.1.0]
11
15
 
12
16
  ### Added
@@ -10,7 +10,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
10
10
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
11
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
12
  };
13
- var _RampsController_instances, _RampsController_requestCacheTTL, _RampsController_requestCacheMaxSize, _RampsController_pendingRequests, _RampsController_removeRequestState, _RampsController_cleanupState, _RampsController_updateRequestState;
13
+ var _RampsController_instances, _RampsController_requestCacheTTL, _RampsController_requestCacheMaxSize, _RampsController_pendingRequests, _RampsController_removeRequestState, _RampsController_cleanupState, _RampsController_fireAndForget, _RampsController_updateResourceField, _RampsController_setResourceLoading, _RampsController_setResourceError, _RampsController_updateRequestState;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.RampsController = exports.getDefaultRampsControllerState = exports.controllerName = void 0;
16
16
  const base_controller_1 = require("@metamask/base-controller");
@@ -37,12 +37,6 @@ const rampsControllerMetadata = {
37
37
  includeInStateLogs: true,
38
38
  usedInUi: true,
39
39
  },
40
- selectedProvider: {
41
- persist: false,
42
- includeInDebugSnapshot: true,
43
- includeInStateLogs: true,
44
- usedInUi: true,
45
- },
46
40
  countries: {
47
41
  persist: true,
48
42
  includeInDebugSnapshot: true,
@@ -61,24 +55,12 @@ const rampsControllerMetadata = {
61
55
  includeInStateLogs: true,
62
56
  usedInUi: true,
63
57
  },
64
- selectedToken: {
65
- persist: false,
66
- includeInDebugSnapshot: true,
67
- includeInStateLogs: true,
68
- usedInUi: true,
69
- },
70
58
  paymentMethods: {
71
59
  persist: false,
72
60
  includeInDebugSnapshot: true,
73
61
  includeInStateLogs: true,
74
62
  usedInUi: true,
75
63
  },
76
- selectedPaymentMethod: {
77
- persist: false,
78
- includeInDebugSnapshot: true,
79
- includeInStateLogs: true,
80
- usedInUi: true,
81
- },
82
64
  quotes: {
83
65
  persist: false,
84
66
  includeInDebugSnapshot: true,
@@ -92,6 +74,23 @@ const rampsControllerMetadata = {
92
74
  usedInUi: true,
93
75
  },
94
76
  };
77
+ /**
78
+ * Creates a default resource state object.
79
+ *
80
+ * @template TData - The type of the resource data.
81
+ * @template TSelected - The type of the selected item.
82
+ * @param data - The initial data value.
83
+ * @param selected - The initial selected value.
84
+ * @returns A ResourceState object with default loading and error values.
85
+ */
86
+ function createDefaultResourceState(data, selected = null) {
87
+ return {
88
+ data,
89
+ selected,
90
+ isLoading: false,
91
+ error: null,
92
+ };
93
+ }
95
94
  /**
96
95
  * Constructs the default {@link RampsController} state. This allows
97
96
  * consumers to provide a partial state object when initializing the controller
@@ -102,15 +101,12 @@ const rampsControllerMetadata = {
102
101
  */
103
102
  function getDefaultRampsControllerState() {
104
103
  return {
105
- userRegion: null,
106
- selectedProvider: null,
107
- countries: [],
108
- providers: [],
109
- tokens: null,
110
- selectedToken: null,
111
- paymentMethods: [],
112
- selectedPaymentMethod: null,
113
- quotes: null,
104
+ userRegion: createDefaultResourceState(null),
105
+ countries: createDefaultResourceState([]),
106
+ providers: createDefaultResourceState([], null),
107
+ tokens: createDefaultResourceState(null, null),
108
+ paymentMethods: createDefaultResourceState([], null),
109
+ quotes: createDefaultResourceState(null),
114
110
  requests: {},
115
111
  };
116
112
  }
@@ -240,8 +236,13 @@ class RampsController extends base_controller_1.BaseController {
240
236
  // Create abort controller for this request
241
237
  const abortController = new AbortController();
242
238
  const lastFetchedAt = Date.now();
239
+ const { resourceType } = options ?? {};
243
240
  // Update state to loading
244
241
  __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_updateRequestState).call(this, cacheKey, (0, RequestCache_1.createLoadingState)());
242
+ // Set resource-level loading state (only on cache miss)
243
+ if (resourceType) {
244
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_setResourceLoading).call(this, resourceType, true);
245
+ }
245
246
  // Create the fetch promise
246
247
  const promise = (async () => {
247
248
  try {
@@ -251,6 +252,10 @@ class RampsController extends base_controller_1.BaseController {
251
252
  throw new Error('Request was aborted');
252
253
  }
253
254
  __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_updateRequestState).call(this, cacheKey, (0, RequestCache_1.createSuccessState)(data, lastFetchedAt));
255
+ // Clear error on success
256
+ if (resourceType) {
257
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_setResourceError).call(this, resourceType, null);
258
+ }
254
259
  return data;
255
260
  }
256
261
  catch (error) {
@@ -258,8 +263,12 @@ class RampsController extends base_controller_1.BaseController {
258
263
  if (abortController.signal.aborted) {
259
264
  throw error;
260
265
  }
261
- const errorMessage = error?.message;
262
- __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_updateRequestState).call(this, cacheKey, (0, RequestCache_1.createErrorState)(errorMessage ?? 'Unknown error', lastFetchedAt));
266
+ const errorMessage = error?.message ?? 'Unknown error';
267
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_updateRequestState).call(this, cacheKey, (0, RequestCache_1.createErrorState)(errorMessage, lastFetchedAt));
268
+ // Set resource-level error
269
+ if (resourceType) {
270
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_setResourceError).call(this, resourceType, errorMessage);
271
+ }
263
272
  throw error;
264
273
  }
265
274
  finally {
@@ -268,6 +277,10 @@ class RampsController extends base_controller_1.BaseController {
268
277
  if (currentPending?.abortController === abortController) {
269
278
  __classPrivateFieldGet(this, _RampsController_pendingRequests, "f").delete(cacheKey);
270
279
  }
280
+ // Clear resource-level loading state
281
+ if (resourceType) {
282
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_setResourceLoading).call(this, resourceType, false);
283
+ }
271
284
  }
272
285
  })();
273
286
  // Store pending request for deduplication
@@ -310,37 +323,36 @@ class RampsController extends base_controller_1.BaseController {
310
323
  async setUserRegion(region, options) {
311
324
  const normalizedRegion = region.toLowerCase().trim();
312
325
  try {
313
- const { countries } = this.state;
314
- if (!countries || countries.length === 0) {
326
+ const countriesData = this.state.countries.data;
327
+ if (!countriesData || countriesData.length === 0) {
315
328
  __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_cleanupState).call(this);
316
329
  throw new Error('No countries found. Cannot set user region without valid country information.');
317
330
  }
318
- const userRegion = findRegionFromCode(normalizedRegion, countries);
331
+ const userRegion = findRegionFromCode(normalizedRegion, countriesData);
319
332
  if (!userRegion) {
320
333
  __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_cleanupState).call(this);
321
334
  throw new Error(`Region "${normalizedRegion}" not found in countries data. Cannot set user region without valid country information.`);
322
335
  }
323
336
  // Only cleanup state if region is actually changing
324
- const regionChanged = normalizedRegion !== this.state.userRegion?.regionCode;
337
+ const regionChanged = normalizedRegion !== this.state.userRegion.data?.regionCode;
325
338
  // Set the new region atomically with cleanup to avoid intermediate null state
326
339
  this.update((state) => {
327
340
  if (regionChanged) {
328
- state.selectedProvider = null;
329
- state.selectedToken = null;
330
- state.tokens = null;
331
- state.providers = [];
332
- state.paymentMethods = [];
333
- state.selectedPaymentMethod = null;
334
- state.quotes = null;
341
+ state.providers.selected = null;
342
+ state.tokens.selected = null;
343
+ state.tokens.data = null;
344
+ state.providers.data = [];
345
+ state.paymentMethods.data = [];
346
+ state.paymentMethods.selected = null;
347
+ state.quotes.data = null;
335
348
  }
336
- state.userRegion = userRegion;
349
+ state.userRegion.data = userRegion;
337
350
  });
338
- // Only trigger fetches if region changed or if data is missing
339
- if (regionChanged || !this.state.tokens) {
340
- this.triggerGetTokens(userRegion.regionCode, 'buy', options);
351
+ if (regionChanged || !this.state.tokens.data) {
352
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_fireAndForget).call(this, this.getTokens(userRegion.regionCode, 'buy', options));
341
353
  }
342
- if (regionChanged || this.state.providers.length === 0) {
343
- this.triggerGetProviders(userRegion.regionCode, options);
354
+ if (regionChanged || this.state.providers.data.length === 0) {
355
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_fireAndForget).call(this, this.getProviders(userRegion.regionCode, options));
344
356
  }
345
357
  return userRegion;
346
358
  }
@@ -360,17 +372,17 @@ class RampsController extends base_controller_1.BaseController {
360
372
  setSelectedProvider(providerId) {
361
373
  if (providerId === null) {
362
374
  this.update((state) => {
363
- state.selectedProvider = null;
364
- state.paymentMethods = [];
365
- state.selectedPaymentMethod = null;
375
+ state.providers.selected = null;
376
+ state.paymentMethods.data = [];
377
+ state.paymentMethods.selected = null;
366
378
  });
367
379
  return;
368
380
  }
369
- const regionCode = this.state.userRegion?.regionCode;
381
+ const regionCode = this.state.userRegion.data?.regionCode;
370
382
  if (!regionCode) {
371
383
  throw new Error('Region is required. Cannot set selected provider without valid region information.');
372
384
  }
373
- const { providers } = this.state;
385
+ const providers = this.state.providers.data;
374
386
  if (!providers || providers.length === 0) {
375
387
  throw new Error('Providers not loaded. Cannot set selected provider before providers are fetched.');
376
388
  }
@@ -379,16 +391,11 @@ class RampsController extends base_controller_1.BaseController {
379
391
  throw new Error(`Provider with ID "${providerId}" not found in available providers.`);
380
392
  }
381
393
  this.update((state) => {
382
- state.selectedProvider = provider;
383
- state.paymentMethods = [];
384
- state.selectedPaymentMethod = null;
385
- });
386
- // fetch payment methods for the new provider
387
- // this is needed because you can change providers without changing the token
388
- // (getPaymentMethods will use state as its default)
389
- this.triggerGetPaymentMethods(regionCode, {
390
- provider: provider.id,
394
+ state.providers.selected = provider;
395
+ state.paymentMethods.data = [];
396
+ state.paymentMethods.selected = null;
391
397
  });
398
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_fireAndForget).call(this, this.getPaymentMethods(regionCode, { provider: provider.id }));
392
399
  }
393
400
  /**
394
401
  * Initializes the controller by fetching the user's region from geolocation.
@@ -401,21 +408,32 @@ class RampsController extends base_controller_1.BaseController {
401
408
  * @returns Promise that resolves when initialization is complete.
402
409
  */
403
410
  async init(options) {
404
- await this.getCountries(options);
405
- let regionCode = this.state.userRegion?.regionCode;
406
- regionCode ?? (regionCode = await this.messenger.call('RampsService:getGeolocation'));
407
- if (!regionCode) {
408
- throw new Error('Failed to fetch geolocation. Cannot initialize controller without valid region information.');
411
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_setResourceLoading).call(this, 'userRegion', true);
412
+ try {
413
+ await this.getCountries(options);
414
+ let regionCode = this.state.userRegion.data?.regionCode;
415
+ regionCode ?? (regionCode = await this.messenger.call('RampsService:getGeolocation'));
416
+ if (!regionCode) {
417
+ throw new Error('Failed to fetch geolocation. Cannot initialize controller without valid region information.');
418
+ }
419
+ await this.setUserRegion(regionCode, options);
420
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_setResourceError).call(this, 'userRegion', null);
421
+ }
422
+ catch (error) {
423
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_setResourceError).call(this, 'userRegion', error?.message ?? 'Unknown error');
424
+ throw error;
425
+ }
426
+ finally {
427
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_setResourceLoading).call(this, 'userRegion', false);
409
428
  }
410
- await this.setUserRegion(regionCode, options);
411
429
  }
412
430
  hydrateState(options) {
413
- const regionCode = this.state.userRegion?.regionCode;
431
+ const regionCode = this.state.userRegion.data?.regionCode;
414
432
  if (!regionCode) {
415
433
  throw new Error('Region code is required. Cannot hydrate state without valid region information.');
416
434
  }
417
- this.triggerGetTokens(regionCode, 'buy', options);
418
- this.triggerGetProviders(regionCode, options);
435
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_fireAndForget).call(this, this.getTokens(regionCode, 'buy', options));
436
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_fireAndForget).call(this, this.getProviders(regionCode, options));
419
437
  }
420
438
  /**
421
439
  * Fetches the list of supported countries.
@@ -429,9 +447,9 @@ class RampsController extends base_controller_1.BaseController {
429
447
  const cacheKey = (0, RequestCache_1.createCacheKey)('getCountries', []);
430
448
  const countries = await this.executeRequest(cacheKey, async () => {
431
449
  return this.messenger.call('RampsService:getCountries');
432
- }, options);
450
+ }, { ...options, resourceType: 'countries' });
433
451
  this.update((state) => {
434
- state.countries = countries;
452
+ state.countries.data = countries;
435
453
  });
436
454
  return countries;
437
455
  }
@@ -446,7 +464,7 @@ class RampsController extends base_controller_1.BaseController {
446
464
  * @returns The tokens response containing topTokens and allTokens.
447
465
  */
448
466
  async getTokens(region, action = 'buy', options) {
449
- const regionToUse = region ?? this.state.userRegion?.regionCode;
467
+ const regionToUse = region ?? this.state.userRegion.data?.regionCode;
450
468
  if (!regionToUse) {
451
469
  throw new Error('Region is required. Either provide a region parameter or ensure userRegion is set in controller state.');
452
470
  }
@@ -460,11 +478,11 @@ class RampsController extends base_controller_1.BaseController {
460
478
  return this.messenger.call('RampsService:getTokens', normalizedRegion, action, {
461
479
  provider: options?.provider,
462
480
  });
463
- }, options);
481
+ }, { ...options, resourceType: 'tokens' });
464
482
  this.update((state) => {
465
- const userRegionCode = state.userRegion?.regionCode;
483
+ const userRegionCode = state.userRegion.data?.regionCode;
466
484
  if (userRegionCode === undefined || userRegionCode === normalizedRegion) {
467
- state.tokens = tokens;
485
+ state.tokens.data = tokens;
468
486
  }
469
487
  });
470
488
  return tokens;
@@ -480,17 +498,17 @@ class RampsController extends base_controller_1.BaseController {
480
498
  setSelectedToken(assetId) {
481
499
  if (!assetId) {
482
500
  this.update((state) => {
483
- state.selectedToken = null;
484
- state.paymentMethods = [];
485
- state.selectedPaymentMethod = null;
501
+ state.tokens.selected = null;
502
+ state.paymentMethods.data = [];
503
+ state.paymentMethods.selected = null;
486
504
  });
487
505
  return;
488
506
  }
489
- const regionCode = this.state.userRegion?.regionCode;
507
+ const regionCode = this.state.userRegion.data?.regionCode;
490
508
  if (!regionCode) {
491
509
  throw new Error('Region is required. Cannot set selected token without valid region information.');
492
510
  }
493
- const { tokens } = this.state;
511
+ const tokens = this.state.tokens.data;
494
512
  if (!tokens) {
495
513
  throw new Error('Tokens not loaded. Cannot set selected token before tokens are fetched.');
496
514
  }
@@ -500,13 +518,11 @@ class RampsController extends base_controller_1.BaseController {
500
518
  throw new Error(`Token with asset ID "${assetId}" not found in available tokens.`);
501
519
  }
502
520
  this.update((state) => {
503
- state.selectedToken = token;
504
- state.paymentMethods = [];
505
- state.selectedPaymentMethod = null;
506
- });
507
- this.triggerGetPaymentMethods(regionCode, {
508
- assetId: token.assetId,
521
+ state.tokens.selected = token;
522
+ state.paymentMethods.data = [];
523
+ state.paymentMethods.selected = null;
509
524
  });
525
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_fireAndForget).call(this, this.getPaymentMethods(regionCode, { assetId: token.assetId }));
510
526
  }
511
527
  /**
512
528
  * Fetches the list of providers for a given region.
@@ -521,7 +537,7 @@ class RampsController extends base_controller_1.BaseController {
521
537
  * @returns The providers response containing providers array.
522
538
  */
523
539
  async getProviders(region, options) {
524
- const regionToUse = region ?? this.state.userRegion?.regionCode;
540
+ const regionToUse = region ?? this.state.userRegion.data?.regionCode;
525
541
  if (!regionToUse) {
526
542
  throw new Error('Region is required. Either provide a region parameter or ensure userRegion is set in controller state.');
527
543
  }
@@ -540,11 +556,11 @@ class RampsController extends base_controller_1.BaseController {
540
556
  fiat: options?.fiat,
541
557
  payments: options?.payments,
542
558
  });
543
- }, options);
559
+ }, { ...options, resourceType: 'providers' });
544
560
  this.update((state) => {
545
- const userRegionCode = state.userRegion?.regionCode;
561
+ const userRegionCode = state.userRegion.data?.regionCode;
546
562
  if (userRegionCode === undefined || userRegionCode === normalizedRegion) {
547
- state.providers = providers;
563
+ state.providers.data = providers;
548
564
  }
549
565
  });
550
566
  return { providers };
@@ -561,10 +577,10 @@ class RampsController extends base_controller_1.BaseController {
561
577
  * @returns The payment methods response containing payments array.
562
578
  */
563
579
  async getPaymentMethods(region, options) {
564
- const regionCode = region ?? this.state.userRegion?.regionCode ?? null;
565
- const fiatToUse = options?.fiat ?? this.state.userRegion?.country?.currency ?? null;
566
- const assetIdToUse = options?.assetId ?? this.state.selectedToken?.assetId ?? '';
567
- const providerToUse = options?.provider ?? this.state.selectedProvider?.id ?? '';
580
+ const regionCode = region ?? this.state.userRegion.data?.regionCode ?? null;
581
+ const fiatToUse = options?.fiat ?? this.state.userRegion.data?.country?.currency ?? null;
582
+ const assetIdToUse = options?.assetId ?? this.state.tokens.selected?.assetId ?? '';
583
+ const providerToUse = options?.provider ?? this.state.providers.selected?.id ?? '';
568
584
  if (!regionCode) {
569
585
  throw new Error('Region is required. Either provide a region parameter or ensure userRegion is set in controller state.');
570
586
  }
@@ -586,21 +602,21 @@ class RampsController extends base_controller_1.BaseController {
586
602
  assetId: assetIdToUse,
587
603
  provider: providerToUse,
588
604
  });
589
- }, options);
605
+ }, { ...options, resourceType: 'paymentMethods' });
590
606
  this.update((state) => {
591
- const currentAssetId = state.selectedToken?.assetId ?? '';
592
- const currentProviderId = state.selectedProvider?.id ?? '';
607
+ const currentAssetId = state.tokens.selected?.assetId ?? '';
608
+ const currentProviderId = state.providers.selected?.id ?? '';
593
609
  const tokenSelectionUnchanged = assetIdToUse === currentAssetId;
594
610
  const providerSelectionUnchanged = providerToUse === currentProviderId;
595
611
  // this is a race condition check to ensure that the selected token and provider in state are the same as the tokens we're requesting for
596
612
  // ex: if the user rapidly changes the token or provider, the in-flight payment methods might not be valid
597
613
  // so this check will ensure that the payment methods are still valid for the token and provider that were requested
598
614
  if (tokenSelectionUnchanged && providerSelectionUnchanged) {
599
- state.paymentMethods = response.payments;
615
+ state.paymentMethods.data = response.payments;
600
616
  // this will auto-select the first payment method if the selected payment method is not in the new payment methods
601
- const currentSelectionStillValid = response.payments.some((pm) => pm.id === state.selectedPaymentMethod?.id);
617
+ const currentSelectionStillValid = response.payments.some((pm) => pm.id === state.paymentMethods.selected?.id);
602
618
  if (!currentSelectionStillValid) {
603
- state.selectedPaymentMethod = response.payments[0] ?? null;
619
+ state.paymentMethods.selected = response.payments[0] ?? null;
604
620
  }
605
621
  }
606
622
  });
@@ -616,11 +632,11 @@ class RampsController extends base_controller_1.BaseController {
616
632
  setSelectedPaymentMethod(paymentMethodId) {
617
633
  if (!paymentMethodId) {
618
634
  this.update((state) => {
619
- state.selectedPaymentMethod = null;
635
+ state.paymentMethods.selected = null;
620
636
  });
621
637
  return;
622
638
  }
623
- const { paymentMethods } = this.state;
639
+ const paymentMethods = this.state.paymentMethods.data;
624
640
  if (!paymentMethods || paymentMethods.length === 0) {
625
641
  throw new Error('Payment methods not loaded. Cannot set selected payment method before payment methods are fetched.');
626
642
  }
@@ -629,7 +645,7 @@ class RampsController extends base_controller_1.BaseController {
629
645
  throw new Error(`Payment method with ID "${paymentMethodId}" not found in available payment methods.`);
630
646
  }
631
647
  this.update((state) => {
632
- state.selectedPaymentMethod = paymentMethod;
648
+ state.paymentMethods.selected = paymentMethod;
633
649
  });
634
650
  }
635
651
  /**
@@ -651,10 +667,10 @@ class RampsController extends base_controller_1.BaseController {
651
667
  * @returns The quotes response containing success, sorted, error, and customActions.
652
668
  */
653
669
  async getQuotes(options) {
654
- const regionToUse = options.region ?? this.state.userRegion?.regionCode;
655
- const fiatToUse = options.fiat ?? this.state.userRegion?.country?.currency;
670
+ const regionToUse = options.region ?? this.state.userRegion.data?.regionCode;
671
+ const fiatToUse = options.fiat ?? this.state.userRegion.data?.country?.currency;
656
672
  const paymentMethodsToUse = options.paymentMethods ??
657
- this.state.paymentMethods.map((pm) => pm.id);
673
+ this.state.paymentMethods.data.map((pm) => pm.id);
658
674
  const action = options.action ?? 'buy';
659
675
  if (!regionToUse) {
660
676
  throw new Error('Region is required. Either provide a region parameter or ensure userRegion is set in controller state.');
@@ -705,11 +721,12 @@ class RampsController extends base_controller_1.BaseController {
705
721
  }, {
706
722
  forceRefresh: options.forceRefresh,
707
723
  ttl: options.ttl ?? DEFAULT_QUOTES_TTL,
724
+ resourceType: 'quotes',
708
725
  });
709
726
  this.update((state) => {
710
- const userRegionCode = state.userRegion?.regionCode;
727
+ const userRegionCode = state.userRegion.data?.regionCode;
711
728
  if (userRegionCode === undefined || userRegionCode === normalizedRegion) {
712
- state.quotes = response;
729
+ state.quotes.data = response;
713
730
  }
714
731
  });
715
732
  return response;
@@ -724,90 +741,6 @@ class RampsController extends base_controller_1.BaseController {
724
741
  getWidgetUrl(quote) {
725
742
  return quote.quote?.widgetUrl ?? null;
726
743
  }
727
- // ============================================================
728
- // Sync Trigger Methods
729
- // These fire-and-forget methods are for use in React effects.
730
- // Errors are stored in state and available via selectors.
731
- // ============================================================
732
- /**
733
- * Triggers setting the user region without throwing.
734
- *
735
- * @param region - The region code to set (e.g., "US-CA").
736
- * @param options - Options for cache behavior.
737
- */
738
- triggerSetUserRegion(region, options) {
739
- this.setUserRegion(region, options).catch(() => {
740
- // Error stored in state
741
- });
742
- }
743
- /**
744
- * Triggers fetching countries without throwing.
745
- *
746
- * @param options - Options for cache behavior.
747
- */
748
- triggerGetCountries(options) {
749
- this.getCountries(options).catch(() => {
750
- // Error stored in state
751
- });
752
- }
753
- /**
754
- * Triggers fetching tokens without throwing.
755
- *
756
- * @param region - The region code. If not provided, uses userRegion from state.
757
- * @param action - The ramp action type ('buy' or 'sell').
758
- * @param options - Options for cache behavior.
759
- */
760
- triggerGetTokens(region, action = 'buy', options) {
761
- this.getTokens(region, action, options).catch(() => {
762
- // Error stored in state
763
- });
764
- }
765
- /**
766
- * Triggers fetching providers without throwing.
767
- *
768
- * @param region - The region code. If not provided, uses userRegion from state.
769
- * @param options - Options for cache behavior and query filters.
770
- */
771
- triggerGetProviders(region, options) {
772
- this.getProviders(region, options).catch(() => {
773
- // Error stored in state
774
- });
775
- }
776
- /**
777
- * Triggers fetching payment methods without throwing.
778
- *
779
- * @param region - User's region code (e.g., "us", "fr", "us-ny").
780
- * @param options - Query parameters for filtering payment methods.
781
- * @param options.fiat - Fiat currency code. If not provided, uses userRegion currency.
782
- * @param options.assetId - CAIP-19 cryptocurrency identifier.
783
- * @param options.provider - Provider ID path.
784
- */
785
- triggerGetPaymentMethods(region, options) {
786
- this.getPaymentMethods(region, options).catch(() => {
787
- // Error stored in state
788
- });
789
- }
790
- /**
791
- * Triggers fetching quotes without throwing.
792
- *
793
- * @param options - The parameters for fetching quotes.
794
- * @param options.region - User's region code. If not provided, uses userRegion from state.
795
- * @param options.fiat - Fiat currency code. If not provided, uses userRegion currency.
796
- * @param options.assetId - CAIP-19 cryptocurrency identifier.
797
- * @param options.amount - The amount (in fiat for buy, crypto for sell).
798
- * @param options.walletAddress - The destination wallet address.
799
- * @param options.paymentMethods - Array of payment method IDs. If not provided, uses paymentMethods from state.
800
- * @param options.provider - Optional provider ID to filter quotes.
801
- * @param options.redirectUrl - Optional redirect URL after order completion.
802
- * @param options.action - The ramp action type. Defaults to 'buy'.
803
- * @param options.forceRefresh - Whether to bypass cache.
804
- * @param options.ttl - Custom TTL for this request.
805
- */
806
- triggerGetQuotes(options) {
807
- this.getQuotes(options).catch(() => {
808
- // Error stored in state
809
- });
810
- }
811
744
  }
812
745
  exports.RampsController = RampsController;
813
746
  _RampsController_requestCacheTTL = new WeakMap(), _RampsController_requestCacheMaxSize = new WeakMap(), _RampsController_pendingRequests = new WeakMap(), _RampsController_instances = new WeakSet(), _RampsController_removeRequestState = function _RampsController_removeRequestState(cacheKey) {
@@ -817,15 +750,28 @@ _RampsController_requestCacheTTL = new WeakMap(), _RampsController_requestCacheM
817
750
  });
818
751
  }, _RampsController_cleanupState = function _RampsController_cleanupState() {
819
752
  this.update((state) => {
820
- state.userRegion = null;
821
- state.selectedProvider = null;
822
- state.selectedToken = null;
823
- state.tokens = null;
824
- state.providers = [];
825
- state.paymentMethods = [];
826
- state.selectedPaymentMethod = null;
827
- state.quotes = null;
753
+ state.userRegion.data = null;
754
+ state.providers.selected = null;
755
+ state.tokens.selected = null;
756
+ state.tokens.data = null;
757
+ state.providers.data = [];
758
+ state.paymentMethods.data = [];
759
+ state.paymentMethods.selected = null;
760
+ state.quotes.data = null;
761
+ });
762
+ }, _RampsController_fireAndForget = function _RampsController_fireAndForget(promise) {
763
+ promise.catch((_error) => undefined);
764
+ }, _RampsController_updateResourceField = function _RampsController_updateResourceField(resourceType, field, value) {
765
+ this.update((state) => {
766
+ const resource = state[resourceType];
767
+ if (resource) {
768
+ resource[field] = value;
769
+ }
828
770
  });
771
+ }, _RampsController_setResourceLoading = function _RampsController_setResourceLoading(resourceType, loading) {
772
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_updateResourceField).call(this, resourceType, 'isLoading', loading);
773
+ }, _RampsController_setResourceError = function _RampsController_setResourceError(resourceType, error) {
774
+ __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_updateResourceField).call(this, resourceType, 'error', error);
829
775
  }, _RampsController_updateRequestState = function _RampsController_updateRequestState(cacheKey, requestState) {
830
776
  const maxSize = __classPrivateFieldGet(this, _RampsController_requestCacheMaxSize, "f");
831
777
  const ttl = __classPrivateFieldGet(this, _RampsController_requestCacheTTL, "f");