@metamask-previews/ramps-controller 3.0.0-preview-fa81dffb → 4.0.0-preview-903db2da
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 +34 -1
- package/dist/RampsController.cjs +297 -76
- package/dist/RampsController.cjs.map +1 -1
- package/dist/RampsController.d.cts +104 -29
- package/dist/RampsController.d.cts.map +1 -1
- package/dist/RampsController.d.mts +104 -29
- package/dist/RampsController.d.mts.map +1 -1
- package/dist/RampsController.mjs +298 -77
- package/dist/RampsController.mjs.map +1 -1
- package/dist/RampsService-method-action-types.cjs.map +1 -1
- package/dist/RampsService-method-action-types.d.cts +20 -11
- package/dist/RampsService-method-action-types.d.cts.map +1 -1
- package/dist/RampsService-method-action-types.d.mts +20 -11
- package/dist/RampsService-method-action-types.d.mts.map +1 -1
- package/dist/RampsService-method-action-types.mjs.map +1 -1
- package/dist/RampsService.cjs +86 -14
- package/dist/RampsService.cjs.map +1 -1
- package/dist/RampsService.d.cts +39 -27
- package/dist/RampsService.d.cts.map +1 -1
- package/dist/RampsService.d.mts +39 -27
- package/dist/RampsService.d.mts.map +1 -1
- package/dist/RampsService.mjs +86 -14
- package/dist/RampsService.mjs.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +3 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,8 +9,40 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
9
9
|
|
|
10
10
|
### Added
|
|
11
11
|
|
|
12
|
+
- Add sync trigger methods to RampsController ([#7662](https://github.com/MetaMask/core/pull/7662))
|
|
13
|
+
|
|
14
|
+
- Export `RampAction` type for `'buy' | 'sell'` ramp actions ([#7663](https://github.com/MetaMask/core/pull/7663))
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- Evict expired cache entries based on TTL in addition to size-based eviction ([#7674](https://github.com/MetaMask/core/pull/7674))
|
|
19
|
+
|
|
20
|
+
- Update `getTokens()` to use v2 API endpoint and support optional provider parameter ([#7664](https://github.com/MetaMask/core/pull/7664))
|
|
21
|
+
|
|
22
|
+
## [4.0.0]
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
12
26
|
- Add `preferredProvider` state and `setPreferredProvider()` method to RampsController ([#7617](https://github.com/MetaMask/core/pull/7617))
|
|
13
27
|
|
|
28
|
+
- Export `UserRegion` type ([#7646](https://github.com/MetaMask/core/pull/7646))
|
|
29
|
+
|
|
30
|
+
- Add `defaultAmount` and `quickAmounts` fields to the `Country` type ([#7645](https://github.com/MetaMask/core/pull/7645))
|
|
31
|
+
|
|
32
|
+
- Add `providers` state and `getProviders()` method to RampsController. Providers are automatically fetched on init and when the region changes ([#7652](https://github.com/MetaMask/core/pull/7652))
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
|
|
36
|
+
- **BREAKING:** Change `userRegion` from `string | null` to `UserRegion | null`. Access region code via `userRegion.regionCode`. ([#7646](https://github.com/MetaMask/core/pull/7646))
|
|
37
|
+
|
|
38
|
+
- Update `getCountries()` endpoint to use v2 API (`v2/regions/countries`) ([#7645](https://github.com/MetaMask/core/pull/7645))
|
|
39
|
+
|
|
40
|
+
- Add `getApiPath()` helper function for versioned API paths with v2 default ([#7645](https://github.com/MetaMask/core/pull/7645))
|
|
41
|
+
|
|
42
|
+
### Removed
|
|
43
|
+
|
|
44
|
+
- **BREAKING:** Remove eligibility concept from RampsController. The `eligibility` state, `updateEligibility()` method, and `getEligibility()` service method have been removed. The `Eligibility` type and `RampsServiceGetEligibilityAction` are no longer exported. ([#7651](https://github.com/MetaMask/core/pull/7645))
|
|
45
|
+
|
|
14
46
|
## [3.0.0]
|
|
15
47
|
|
|
16
48
|
### Added
|
|
@@ -59,7 +91,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
59
91
|
- Add `OnRampService` for interacting with the OnRamp API
|
|
60
92
|
- Add geolocation detection via IP address lookup
|
|
61
93
|
|
|
62
|
-
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/ramps-controller@
|
|
94
|
+
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/ramps-controller@4.0.0...HEAD
|
|
95
|
+
[4.0.0]: https://github.com/MetaMask/core/compare/@metamask/ramps-controller@3.0.0...@metamask/ramps-controller@4.0.0
|
|
63
96
|
[3.0.0]: https://github.com/MetaMask/core/compare/@metamask/ramps-controller@2.1.0...@metamask/ramps-controller@3.0.0
|
|
64
97
|
[2.1.0]: https://github.com/MetaMask/core/compare/@metamask/ramps-controller@2.0.0...@metamask/ramps-controller@2.1.0
|
|
65
98
|
[2.0.0]: https://github.com/MetaMask/core/compare/@metamask/ramps-controller@1.0.0...@metamask/ramps-controller@2.0.0
|
package/dist/RampsController.cjs
CHANGED
|
@@ -38,7 +38,7 @@ const rampsControllerMetadata = {
|
|
|
38
38
|
includeInStateLogs: true,
|
|
39
39
|
usedInUi: true,
|
|
40
40
|
},
|
|
41
|
-
|
|
41
|
+
providers: {
|
|
42
42
|
persist: true,
|
|
43
43
|
includeInDebugSnapshot: true,
|
|
44
44
|
includeInStateLogs: true,
|
|
@@ -69,12 +69,65 @@ function getDefaultRampsControllerState() {
|
|
|
69
69
|
return {
|
|
70
70
|
userRegion: null,
|
|
71
71
|
preferredProvider: null,
|
|
72
|
-
|
|
72
|
+
providers: [],
|
|
73
73
|
tokens: null,
|
|
74
74
|
requests: {},
|
|
75
75
|
};
|
|
76
76
|
}
|
|
77
77
|
exports.getDefaultRampsControllerState = getDefaultRampsControllerState;
|
|
78
|
+
// === HELPER FUNCTIONS ===
|
|
79
|
+
/**
|
|
80
|
+
* Finds a country and state from a region code string.
|
|
81
|
+
*
|
|
82
|
+
* @param regionCode - The region code (e.g., "us-ca" or "us").
|
|
83
|
+
* @param countries - Array of countries to search.
|
|
84
|
+
* @returns UserRegion object with country and state, or null if not found.
|
|
85
|
+
*/
|
|
86
|
+
function findRegionFromCode(regionCode, countries) {
|
|
87
|
+
const normalizedCode = regionCode.toLowerCase().trim();
|
|
88
|
+
const parts = normalizedCode.split('-');
|
|
89
|
+
const countryCode = parts[0];
|
|
90
|
+
const stateCode = parts[1];
|
|
91
|
+
const country = countries.find((countryItem) => {
|
|
92
|
+
if (countryItem.isoCode?.toLowerCase() === countryCode) {
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
if (countryItem.id) {
|
|
96
|
+
const id = countryItem.id.toLowerCase();
|
|
97
|
+
if (id.startsWith('/regions/')) {
|
|
98
|
+
const extractedCode = id.replace('/regions/', '').split('/')[0];
|
|
99
|
+
return extractedCode === countryCode;
|
|
100
|
+
}
|
|
101
|
+
return id === countryCode || id.endsWith(`/${countryCode}`);
|
|
102
|
+
}
|
|
103
|
+
return false;
|
|
104
|
+
});
|
|
105
|
+
if (!country) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
let state = null;
|
|
109
|
+
if (stateCode && country.states) {
|
|
110
|
+
state =
|
|
111
|
+
country.states.find((stateItem) => {
|
|
112
|
+
if (stateItem.stateId?.toLowerCase() === stateCode) {
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
if (stateItem.id) {
|
|
116
|
+
const stateId = stateItem.id.toLowerCase();
|
|
117
|
+
if (stateId.includes(`-${stateCode}`) ||
|
|
118
|
+
stateId.endsWith(`/${stateCode}`)) {
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return false;
|
|
123
|
+
}) ?? null;
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
country,
|
|
127
|
+
state,
|
|
128
|
+
regionCode: normalizedCode,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
78
131
|
// === CONTROLLER DEFINITION ===
|
|
79
132
|
/**
|
|
80
133
|
* Manages cryptocurrency on/off ramps functionality.
|
|
@@ -208,73 +261,134 @@ class RampsController extends base_controller_1.BaseController {
|
|
|
208
261
|
return this.state.requests[cacheKey];
|
|
209
262
|
}
|
|
210
263
|
/**
|
|
211
|
-
* Updates the user's region by fetching geolocation
|
|
212
|
-
* This method calls the RampsService to get the geolocation
|
|
213
|
-
* then automatically fetches eligibility for that region.
|
|
264
|
+
* Updates the user's region by fetching geolocation.
|
|
265
|
+
* This method calls the RampsService to get the geolocation.
|
|
214
266
|
*
|
|
215
267
|
* @param options - Options for cache behavior.
|
|
216
|
-
* @returns The user region
|
|
268
|
+
* @returns The user region object.
|
|
217
269
|
*/
|
|
218
270
|
async updateUserRegion(options) {
|
|
271
|
+
// If a userRegion already exists and forceRefresh is not requested,
|
|
272
|
+
// return it immediately without fetching geolocation.
|
|
273
|
+
// This ensures that once a region is set (either via geolocation or manual selection),
|
|
274
|
+
// it will not be overwritten by subsequent geolocation fetches.
|
|
275
|
+
if (this.state.userRegion && !options?.forceRefresh) {
|
|
276
|
+
return this.state.userRegion;
|
|
277
|
+
}
|
|
278
|
+
// When forceRefresh is true, clear the existing region, tokens, and providers before fetching
|
|
279
|
+
if (options?.forceRefresh) {
|
|
280
|
+
this.update((state) => {
|
|
281
|
+
state.userRegion = null;
|
|
282
|
+
state.tokens = null;
|
|
283
|
+
state.providers = [];
|
|
284
|
+
});
|
|
285
|
+
}
|
|
219
286
|
const cacheKey = (0, RequestCache_1.createCacheKey)('updateUserRegion', []);
|
|
220
|
-
const
|
|
287
|
+
const regionCode = await this.executeRequest(cacheKey, async () => {
|
|
221
288
|
const result = await this.messenger.call('RampsService:getGeolocation');
|
|
222
289
|
return result;
|
|
223
290
|
}, options);
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
291
|
+
if (!regionCode) {
|
|
292
|
+
this.update((state) => {
|
|
293
|
+
state.userRegion = null;
|
|
294
|
+
state.tokens = null;
|
|
295
|
+
state.providers = [];
|
|
296
|
+
});
|
|
297
|
+
return null;
|
|
298
|
+
}
|
|
299
|
+
const normalizedRegion = regionCode.toLowerCase().trim();
|
|
300
|
+
try {
|
|
301
|
+
const countries = await this.getCountries('buy', options);
|
|
302
|
+
const userRegion = findRegionFromCode(normalizedRegion, countries);
|
|
303
|
+
if (userRegion) {
|
|
236
304
|
this.update((state) => {
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
|
|
305
|
+
const regionChanged = state.userRegion?.regionCode !== userRegion.regionCode;
|
|
306
|
+
state.userRegion = userRegion;
|
|
307
|
+
// Clear tokens and providers when region changes
|
|
308
|
+
if (regionChanged) {
|
|
240
309
|
state.tokens = null;
|
|
310
|
+
state.providers = [];
|
|
241
311
|
}
|
|
242
312
|
});
|
|
313
|
+
// Fetch providers for the new region
|
|
314
|
+
if (userRegion.regionCode) {
|
|
315
|
+
try {
|
|
316
|
+
await this.getProviders(userRegion.regionCode, options);
|
|
317
|
+
}
|
|
318
|
+
catch {
|
|
319
|
+
// Provider fetch failed - error state will be available via selectors
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
return userRegion;
|
|
243
323
|
}
|
|
324
|
+
// Region not found in countries data
|
|
325
|
+
this.update((state) => {
|
|
326
|
+
state.userRegion = null;
|
|
327
|
+
state.tokens = null;
|
|
328
|
+
state.providers = [];
|
|
329
|
+
});
|
|
330
|
+
return null;
|
|
331
|
+
}
|
|
332
|
+
catch {
|
|
333
|
+
// If countries fetch fails, we can't create a valid UserRegion
|
|
334
|
+
// Return null to indicate we don't have valid country data
|
|
335
|
+
this.update((state) => {
|
|
336
|
+
state.userRegion = null;
|
|
337
|
+
state.tokens = null;
|
|
338
|
+
state.providers = [];
|
|
339
|
+
});
|
|
340
|
+
return null;
|
|
244
341
|
}
|
|
245
|
-
return normalizedRegion;
|
|
246
342
|
}
|
|
247
343
|
/**
|
|
248
344
|
* Sets the user's region manually (without fetching geolocation).
|
|
249
345
|
* This allows users to override the detected region.
|
|
250
346
|
*
|
|
251
347
|
* @param region - The region code to set (e.g., "US-CA").
|
|
252
|
-
* @param options - Options for cache behavior
|
|
253
|
-
* @returns The
|
|
348
|
+
* @param options - Options for cache behavior.
|
|
349
|
+
* @returns The user region object.
|
|
254
350
|
*/
|
|
255
351
|
async setUserRegion(region, options) {
|
|
256
352
|
const normalizedRegion = region.toLowerCase().trim();
|
|
257
|
-
this.update((state) => {
|
|
258
|
-
state.userRegion = normalizedRegion;
|
|
259
|
-
state.tokens = null;
|
|
260
|
-
});
|
|
261
353
|
try {
|
|
262
|
-
|
|
354
|
+
const countries = await this.getCountries('buy', options);
|
|
355
|
+
const userRegion = findRegionFromCode(normalizedRegion, countries);
|
|
356
|
+
if (userRegion) {
|
|
357
|
+
this.update((state) => {
|
|
358
|
+
state.userRegion = userRegion;
|
|
359
|
+
state.tokens = null;
|
|
360
|
+
state.providers = [];
|
|
361
|
+
});
|
|
362
|
+
// Fetch providers for the new region
|
|
363
|
+
try {
|
|
364
|
+
await this.getProviders(userRegion.regionCode, options);
|
|
365
|
+
}
|
|
366
|
+
catch {
|
|
367
|
+
// Provider fetch failed - error state will be available via selectors
|
|
368
|
+
}
|
|
369
|
+
return userRegion;
|
|
370
|
+
}
|
|
371
|
+
// Region not found in countries data
|
|
372
|
+
this.update((state) => {
|
|
373
|
+
state.userRegion = null;
|
|
374
|
+
state.tokens = null;
|
|
375
|
+
state.providers = [];
|
|
376
|
+
});
|
|
377
|
+
throw new Error(`Region "${normalizedRegion}" not found in countries data. Cannot set user region without valid country information.`);
|
|
263
378
|
}
|
|
264
379
|
catch (error) {
|
|
265
|
-
//
|
|
266
|
-
//
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
380
|
+
// If the error is "not found", re-throw it
|
|
381
|
+
// Otherwise, it's from countries fetch failure
|
|
382
|
+
if (error instanceof Error && error.message.includes('not found')) {
|
|
383
|
+
throw error;
|
|
384
|
+
}
|
|
385
|
+
// Countries fetch failed
|
|
270
386
|
this.update((state) => {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
state.tokens = null;
|
|
275
|
-
}
|
|
387
|
+
state.userRegion = null;
|
|
388
|
+
state.tokens = null;
|
|
389
|
+
state.providers = [];
|
|
276
390
|
});
|
|
277
|
-
throw
|
|
391
|
+
throw new Error('Failed to fetch countries data. Cannot set user region without valid country information.');
|
|
278
392
|
}
|
|
279
393
|
}
|
|
280
394
|
/**
|
|
@@ -291,8 +405,10 @@ class RampsController extends base_controller_1.BaseController {
|
|
|
291
405
|
/**
|
|
292
406
|
* Initializes the controller by fetching the user's region from geolocation.
|
|
293
407
|
* This should be called once at app startup to set up the initial region.
|
|
294
|
-
* After the region is set
|
|
295
|
-
*
|
|
408
|
+
* After the region is set, tokens are fetched and saved to state.
|
|
409
|
+
*
|
|
410
|
+
* If a userRegion already exists (from persistence or manual selection),
|
|
411
|
+
* this method will skip geolocation fetch and only fetch tokens if needed.
|
|
296
412
|
*
|
|
297
413
|
* @param options - Options for cache behavior.
|
|
298
414
|
* @returns Promise that resolves when initialization is complete.
|
|
@@ -304,40 +420,25 @@ class RampsController extends base_controller_1.BaseController {
|
|
|
304
420
|
});
|
|
305
421
|
if (userRegion) {
|
|
306
422
|
try {
|
|
307
|
-
await this.getTokens(userRegion, 'buy', options);
|
|
423
|
+
await this.getTokens(userRegion.regionCode, 'buy', options);
|
|
308
424
|
}
|
|
309
425
|
catch {
|
|
310
426
|
// Token fetch failed - error state will be available via selectors
|
|
311
427
|
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
/**
|
|
315
|
-
* Updates the eligibility information for a given region.
|
|
316
|
-
*
|
|
317
|
-
* @param isoCode - The ISO code for the region (e.g., "us", "fr", "us-ny").
|
|
318
|
-
* @param options - Options for cache behavior.
|
|
319
|
-
* @returns The eligibility information.
|
|
320
|
-
*/
|
|
321
|
-
async updateEligibility(isoCode, options) {
|
|
322
|
-
const normalizedIsoCode = isoCode.toLowerCase().trim();
|
|
323
|
-
const cacheKey = (0, RequestCache_1.createCacheKey)('updateEligibility', [normalizedIsoCode]);
|
|
324
|
-
const eligibility = await this.executeRequest(cacheKey, async () => {
|
|
325
|
-
return this.messenger.call('RampsService:getEligibility', normalizedIsoCode);
|
|
326
|
-
}, options);
|
|
327
|
-
this.update((state) => {
|
|
328
|
-
const userRegion = state.userRegion?.toLowerCase().trim();
|
|
329
|
-
if (userRegion === undefined || userRegion === normalizedIsoCode) {
|
|
330
|
-
state.eligibility = eligibility;
|
|
428
|
+
try {
|
|
429
|
+
await this.getProviders(userRegion.regionCode, options);
|
|
331
430
|
}
|
|
332
|
-
|
|
333
|
-
|
|
431
|
+
catch {
|
|
432
|
+
// Provider fetch failed - error state will be available via selectors
|
|
433
|
+
}
|
|
434
|
+
}
|
|
334
435
|
}
|
|
335
436
|
/**
|
|
336
437
|
* Fetches the list of supported countries for a given ramp action.
|
|
337
438
|
*
|
|
338
439
|
* @param action - The ramp action type ('buy' or 'sell').
|
|
339
440
|
* @param options - Options for cache behavior.
|
|
340
|
-
* @returns An array of countries
|
|
441
|
+
* @returns An array of countries.
|
|
341
442
|
*/
|
|
342
443
|
async getCountries(action = 'buy', options) {
|
|
343
444
|
const cacheKey = (0, RequestCache_1.createCacheKey)('getCountries', [action]);
|
|
@@ -351,27 +452,135 @@ class RampsController extends base_controller_1.BaseController {
|
|
|
351
452
|
*
|
|
352
453
|
* @param region - The region code (e.g., "us", "fr", "us-ny"). If not provided, uses the user's region from controller state.
|
|
353
454
|
* @param action - The ramp action type ('buy' or 'sell').
|
|
354
|
-
* @param options - Options for cache behavior.
|
|
455
|
+
* @param options - Options for cache behavior and query filters.
|
|
456
|
+
* @param options.provider - Provider ID(s) to filter by.
|
|
355
457
|
* @returns The tokens response containing topTokens and allTokens.
|
|
356
458
|
*/
|
|
357
459
|
async getTokens(region, action = 'buy', options) {
|
|
358
|
-
const regionToUse = region ?? this.state.userRegion;
|
|
460
|
+
const regionToUse = region ?? this.state.userRegion?.regionCode;
|
|
359
461
|
if (!regionToUse) {
|
|
360
462
|
throw new Error('Region is required. Either provide a region parameter or ensure userRegion is set in controller state.');
|
|
361
463
|
}
|
|
362
464
|
const normalizedRegion = regionToUse.toLowerCase().trim();
|
|
363
|
-
const cacheKey = (0, RequestCache_1.createCacheKey)('getTokens', [
|
|
465
|
+
const cacheKey = (0, RequestCache_1.createCacheKey)('getTokens', [
|
|
466
|
+
normalizedRegion,
|
|
467
|
+
action,
|
|
468
|
+
options?.provider,
|
|
469
|
+
]);
|
|
364
470
|
const tokens = await this.executeRequest(cacheKey, async () => {
|
|
365
|
-
return this.messenger.call('RampsService:getTokens', normalizedRegion, action
|
|
471
|
+
return this.messenger.call('RampsService:getTokens', normalizedRegion, action, {
|
|
472
|
+
provider: options?.provider,
|
|
473
|
+
});
|
|
366
474
|
}, options);
|
|
367
475
|
this.update((state) => {
|
|
368
|
-
const
|
|
369
|
-
if (
|
|
476
|
+
const userRegionCode = state.userRegion?.regionCode;
|
|
477
|
+
if (userRegionCode === undefined || userRegionCode === normalizedRegion) {
|
|
370
478
|
state.tokens = tokens;
|
|
371
479
|
}
|
|
372
480
|
});
|
|
373
481
|
return tokens;
|
|
374
482
|
}
|
|
483
|
+
/**
|
|
484
|
+
* Fetches the list of providers for a given region.
|
|
485
|
+
* The providers are saved in the controller state once fetched.
|
|
486
|
+
*
|
|
487
|
+
* @param region - The region code (e.g., "us", "fr", "us-ny"). If not provided, uses the user's region from controller state.
|
|
488
|
+
* @param options - Options for cache behavior and query filters.
|
|
489
|
+
* @param options.provider - Provider ID(s) to filter by.
|
|
490
|
+
* @param options.crypto - Crypto currency ID(s) to filter by.
|
|
491
|
+
* @param options.fiat - Fiat currency ID(s) to filter by.
|
|
492
|
+
* @param options.payments - Payment method ID(s) to filter by.
|
|
493
|
+
* @returns The providers response containing providers array.
|
|
494
|
+
*/
|
|
495
|
+
async getProviders(region, options) {
|
|
496
|
+
const regionToUse = region ?? this.state.userRegion?.regionCode;
|
|
497
|
+
if (!regionToUse) {
|
|
498
|
+
throw new Error('Region is required. Either provide a region parameter or ensure userRegion is set in controller state.');
|
|
499
|
+
}
|
|
500
|
+
const normalizedRegion = regionToUse.toLowerCase().trim();
|
|
501
|
+
const cacheKey = (0, RequestCache_1.createCacheKey)('getProviders', [
|
|
502
|
+
normalizedRegion,
|
|
503
|
+
options?.provider,
|
|
504
|
+
options?.crypto,
|
|
505
|
+
options?.fiat,
|
|
506
|
+
options?.payments,
|
|
507
|
+
]);
|
|
508
|
+
const { providers } = await this.executeRequest(cacheKey, async () => {
|
|
509
|
+
return this.messenger.call('RampsService:getProviders', normalizedRegion, {
|
|
510
|
+
provider: options?.provider,
|
|
511
|
+
crypto: options?.crypto,
|
|
512
|
+
fiat: options?.fiat,
|
|
513
|
+
payments: options?.payments,
|
|
514
|
+
});
|
|
515
|
+
}, options);
|
|
516
|
+
this.update((state) => {
|
|
517
|
+
const userRegionCode = state.userRegion?.regionCode;
|
|
518
|
+
if (userRegionCode === undefined || userRegionCode === normalizedRegion) {
|
|
519
|
+
state.providers = providers;
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
return { providers };
|
|
523
|
+
}
|
|
524
|
+
// ============================================================
|
|
525
|
+
// Sync Trigger Methods
|
|
526
|
+
// These fire-and-forget methods are for use in React effects.
|
|
527
|
+
// Errors are stored in state and available via selectors.
|
|
528
|
+
// ============================================================
|
|
529
|
+
/**
|
|
530
|
+
* Triggers a user region update without throwing.
|
|
531
|
+
*
|
|
532
|
+
* @param options - Options for cache behavior.
|
|
533
|
+
*/
|
|
534
|
+
triggerUpdateUserRegion(options) {
|
|
535
|
+
this.updateUserRegion(options).catch(() => {
|
|
536
|
+
// Error stored in state
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* Triggers setting the user region without throwing.
|
|
541
|
+
*
|
|
542
|
+
* @param region - The region code to set (e.g., "US-CA").
|
|
543
|
+
* @param options - Options for cache behavior.
|
|
544
|
+
*/
|
|
545
|
+
triggerSetUserRegion(region, options) {
|
|
546
|
+
this.setUserRegion(region, options).catch(() => {
|
|
547
|
+
// Error stored in state
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Triggers fetching countries without throwing.
|
|
552
|
+
*
|
|
553
|
+
* @param action - The ramp action type ('buy' or 'sell').
|
|
554
|
+
* @param options - Options for cache behavior.
|
|
555
|
+
*/
|
|
556
|
+
triggerGetCountries(action = 'buy', options) {
|
|
557
|
+
this.getCountries(action, options).catch(() => {
|
|
558
|
+
// Error stored in state
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Triggers fetching tokens without throwing.
|
|
563
|
+
*
|
|
564
|
+
* @param region - The region code. If not provided, uses userRegion from state.
|
|
565
|
+
* @param action - The ramp action type ('buy' or 'sell').
|
|
566
|
+
* @param options - Options for cache behavior.
|
|
567
|
+
*/
|
|
568
|
+
triggerGetTokens(region, action = 'buy', options) {
|
|
569
|
+
this.getTokens(region, action, options).catch(() => {
|
|
570
|
+
// Error stored in state
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Triggers fetching providers without throwing.
|
|
575
|
+
*
|
|
576
|
+
* @param region - The region code. If not provided, uses userRegion from state.
|
|
577
|
+
* @param options - Options for cache behavior and query filters.
|
|
578
|
+
*/
|
|
579
|
+
triggerGetProviders(region, options) {
|
|
580
|
+
this.getProviders(region, options).catch(() => {
|
|
581
|
+
// Error stored in state
|
|
582
|
+
});
|
|
583
|
+
}
|
|
375
584
|
}
|
|
376
585
|
exports.RampsController = RampsController;
|
|
377
586
|
_RampsController_requestCacheTTL = new WeakMap(), _RampsController_requestCacheMaxSize = new WeakMap(), _RampsController_pendingRequests = new WeakMap(), _RampsController_instances = new WeakSet(), _RampsController_removeRequestState = function _RampsController_removeRequestState(cacheKey) {
|
|
@@ -381,20 +590,32 @@ _RampsController_requestCacheTTL = new WeakMap(), _RampsController_requestCacheM
|
|
|
381
590
|
});
|
|
382
591
|
}, _RampsController_updateRequestState = function _RampsController_updateRequestState(cacheKey, requestState) {
|
|
383
592
|
const maxSize = __classPrivateFieldGet(this, _RampsController_requestCacheMaxSize, "f");
|
|
593
|
+
const ttl = __classPrivateFieldGet(this, _RampsController_requestCacheTTL, "f");
|
|
384
594
|
this.update((state) => {
|
|
385
595
|
const requests = state.requests;
|
|
386
596
|
requests[cacheKey] = requestState;
|
|
387
|
-
// Evict
|
|
597
|
+
// Evict expired entries based on TTL
|
|
598
|
+
// Only evict SUCCESS states that have exceeded their TTL
|
|
388
599
|
const keys = Object.keys(requests);
|
|
389
|
-
|
|
600
|
+
for (const key of keys) {
|
|
601
|
+
const entry = requests[key];
|
|
602
|
+
if (entry &&
|
|
603
|
+
entry.status === RequestCache_1.RequestStatus.SUCCESS &&
|
|
604
|
+
(0, RequestCache_1.isCacheExpired)(entry, ttl)) {
|
|
605
|
+
delete requests[key];
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
// Evict oldest entries if cache still exceeds max size
|
|
609
|
+
const remainingKeys = Object.keys(requests);
|
|
610
|
+
if (remainingKeys.length > maxSize) {
|
|
390
611
|
// Sort by timestamp (oldest first)
|
|
391
|
-
const sortedKeys =
|
|
612
|
+
const sortedKeys = remainingKeys.sort((a, b) => {
|
|
392
613
|
const aTime = requests[a]?.timestamp ?? 0;
|
|
393
614
|
const bTime = requests[b]?.timestamp ?? 0;
|
|
394
615
|
return aTime - bTime;
|
|
395
616
|
});
|
|
396
617
|
// Remove oldest entries until we're under the limit
|
|
397
|
-
const entriesToRemove =
|
|
618
|
+
const entriesToRemove = remainingKeys.length - maxSize;
|
|
398
619
|
for (let i = 0; i < entriesToRemove; i++) {
|
|
399
620
|
const keyToRemove = sortedKeys[i];
|
|
400
621
|
if (keyToRemove) {
|