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