@metamask/ramps-controller 14.3.0 → 15.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -1
- package/dist/RampsController-method-action-types.cjs.map +1 -1
- package/dist/RampsController-method-action-types.d.cts +4 -4
- package/dist/RampsController-method-action-types.d.cts.map +1 -1
- package/dist/RampsController-method-action-types.d.mts +4 -4
- package/dist/RampsController-method-action-types.d.mts.map +1 -1
- package/dist/RampsController-method-action-types.mjs.map +1 -1
- package/dist/RampsController.cjs +185 -29
- package/dist/RampsController.cjs.map +1 -1
- package/dist/RampsController.d.cts +37 -7
- package/dist/RampsController.d.cts.map +1 -1
- package/dist/RampsController.d.mts +37 -7
- package/dist/RampsController.d.mts.map +1 -1
- package/dist/RampsController.mjs +185 -29
- 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 +4 -3
- package/dist/RampsService-method-action-types.d.cts.map +1 -1
- package/dist/RampsService-method-action-types.d.mts +4 -3
- 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 +4 -10
- package/dist/RampsService.cjs.map +1 -1
- package/dist/RampsService.d.cts +4 -5
- package/dist/RampsService.d.cts.map +1 -1
- package/dist/RampsService.d.mts +4 -5
- package/dist/RampsService.d.mts.map +1 -1
- package/dist/RampsService.mjs +4 -10
- package/dist/RampsService.mjs.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/RampsController.cjs
CHANGED
|
@@ -10,7 +10,7 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
|
|
|
10
10
|
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");
|
|
11
11
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
12
12
|
};
|
|
13
|
-
var _RampsController_instances, _RampsController_requestCacheTTL, _RampsController_requestCacheMaxSize, _RampsController_pendingRequests, _RampsController_pendingResourceCount, _RampsController_pendingResourceGeneration, _RampsController_orderPollingMeta, _RampsController_orderPollingTimer, _RampsController_isPolling, _RampsController_initPromise, _RampsController_clearPendingResourceCountForDependentResources, _RampsController_abortDependentRequests, _RampsController_mutateRequests, _RampsController_removeRequestState, _RampsController_cleanupState, _RampsController_requireRegion, _RampsController_isRegionCurrent, _RampsController_isTokenCurrent, _RampsController_isProviderCurrent, _RampsController_updateResourceField, _RampsController_setResourceLoading, _RampsController_setResourceError, _RampsController_updateRequestState, _RampsController_runInit, _RampsController_getSupportingProvidersForRegion, _RampsController_filterProviderIdsBySupport, _RampsController_resolveProviderIdsForQuote, _RampsController_getPreferredProviderIdsFromOrders, _RampsController_refreshOrder, _RampsController_pollPendingOrders, _RampsController_syncTransakAuthOnError, _RampsController_getNormalizedTransakError;
|
|
13
|
+
var _RampsController_instances, _RampsController_requestCacheTTL, _RampsController_requestCacheMaxSize, _RampsController_getProviderScope, _RampsController_getDefaultRedirectUrl, _RampsController_pendingRequests, _RampsController_pendingResourceCount, _RampsController_pendingResourceGeneration, _RampsController_orderPollingMeta, _RampsController_orderPollingTimer, _RampsController_isPolling, _RampsController_initPromise, _RampsController_clearPendingResourceCountForDependentResources, _RampsController_abortDependentRequests, _RampsController_mutateRequests, _RampsController_removeRequestState, _RampsController_cleanupState, _RampsController_requireRegion, _RampsController_isRegionCurrent, _RampsController_isTokenCurrent, _RampsController_isProviderCurrent, _RampsController_updateResourceField, _RampsController_setResourceLoading, _RampsController_setResourceError, _RampsController_updateRequestState, _RampsController_runInit, _RampsController_syncUserRegionFromCountriesCatalog, _RampsController_pickInAppQuote, _RampsController_getSupportingProvidersForRegion, _RampsController_filterProviderIdsBySupport, _RampsController_resolveProviderIdsForQuote, _RampsController_getPreferredProviderIdsFromOrders, _RampsController_refreshOrder, _RampsController_pollPendingOrders, _RampsController_syncTransakAuthOnError, _RampsController_getNormalizedTransakError;
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.RampsController = exports.getInternalOrderCode = exports.normalizeProviderCode = exports.getDefaultRampsControllerState = exports.RAMPS_CONTROLLER_REQUIRED_SERVICE_ACTIONS = exports.controllerName = void 0;
|
|
16
16
|
const base_controller_1 = require("@metamask/base-controller");
|
|
@@ -135,7 +135,7 @@ const rampsControllerMetadata = {
|
|
|
135
135
|
usedInUi: true,
|
|
136
136
|
},
|
|
137
137
|
countries: {
|
|
138
|
-
persist:
|
|
138
|
+
persist: false,
|
|
139
139
|
includeInDebugSnapshot: true,
|
|
140
140
|
includeInStateLogs: true,
|
|
141
141
|
usedInUi: true,
|
|
@@ -441,8 +441,13 @@ class RampsController extends base_controller_1.BaseController {
|
|
|
441
441
|
* controller. Missing properties will be filled in with defaults.
|
|
442
442
|
* @param args.requestCacheTTL - Time to live for cached requests in milliseconds.
|
|
443
443
|
* @param args.requestCacheMaxSize - Maximum number of entries in the request cache.
|
|
444
|
+
* @param args.getProviderScope - Optional callback returning the current
|
|
445
|
+
* provider-class scope for fiat quote widening. Defaults to `off`.
|
|
446
|
+
* @param args.getDefaultRedirectUrl - Optional callback returning the default
|
|
447
|
+
* redirect URL used for the widened in-app quote fetch when the caller omits
|
|
448
|
+
* `redirectUrl`. Defaults to a callback returning `undefined`.
|
|
444
449
|
*/
|
|
445
|
-
constructor({ messenger, state = {}, requestCacheTTL = RequestCache_1.DEFAULT_REQUEST_CACHE_TTL, requestCacheMaxSize = RequestCache_1.DEFAULT_REQUEST_CACHE_MAX_SIZE, }) {
|
|
450
|
+
constructor({ messenger, state = {}, requestCacheTTL = RequestCache_1.DEFAULT_REQUEST_CACHE_TTL, requestCacheMaxSize = RequestCache_1.DEFAULT_REQUEST_CACHE_MAX_SIZE, getProviderScope, getDefaultRedirectUrl, }) {
|
|
446
451
|
super({
|
|
447
452
|
messenger,
|
|
448
453
|
metadata: rampsControllerMetadata,
|
|
@@ -463,6 +468,17 @@ class RampsController extends base_controller_1.BaseController {
|
|
|
463
468
|
* Maximum number of entries in the request cache.
|
|
464
469
|
*/
|
|
465
470
|
_RampsController_requestCacheMaxSize.set(this, void 0);
|
|
471
|
+
/**
|
|
472
|
+
* Resolves the current provider-class scope for fiat quote widening. Defaults
|
|
473
|
+
* to `() => 'off'` (native-only) when no callback is injected.
|
|
474
|
+
*/
|
|
475
|
+
_RampsController_getProviderScope.set(this, void 0);
|
|
476
|
+
/**
|
|
477
|
+
* Resolves the default redirect URL for the widened in-app quote fetch when
|
|
478
|
+
* the caller omits `redirectUrl`. Defaults to `() => undefined` when no
|
|
479
|
+
* callback is injected.
|
|
480
|
+
*/
|
|
481
|
+
_RampsController_getDefaultRedirectUrl.set(this, void 0);
|
|
466
482
|
/**
|
|
467
483
|
* Map of pending requests for deduplication.
|
|
468
484
|
* Key is the cache key, value is the pending request with abort controller.
|
|
@@ -484,6 +500,8 @@ class RampsController extends base_controller_1.BaseController {
|
|
|
484
500
|
_RampsController_initPromise.set(this, null);
|
|
485
501
|
__classPrivateFieldSet(this, _RampsController_requestCacheTTL, requestCacheTTL, "f");
|
|
486
502
|
__classPrivateFieldSet(this, _RampsController_requestCacheMaxSize, requestCacheMaxSize, "f");
|
|
503
|
+
__classPrivateFieldSet(this, _RampsController_getProviderScope, getProviderScope ?? (() => 'off'), "f");
|
|
504
|
+
__classPrivateFieldSet(this, _RampsController_getDefaultRedirectUrl, getDefaultRedirectUrl ?? (() => undefined), "f");
|
|
487
505
|
this.messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
|
|
488
506
|
}
|
|
489
507
|
/**
|
|
@@ -721,8 +739,10 @@ class RampsController extends base_controller_1.BaseController {
|
|
|
721
739
|
* This should be called once at app startup to set up the initial region.
|
|
722
740
|
*
|
|
723
741
|
* Idempotent: subsequent calls return the same promise unless forceRefresh is set.
|
|
724
|
-
*
|
|
725
|
-
*
|
|
742
|
+
* Force-refetches the countries catalog on startup (bypassing the in-session
|
|
743
|
+
* request cache) so region preset amounts stay current. The catalog is not
|
|
744
|
+
* persisted, so a cold start always re-fetches it regardless. Skips
|
|
745
|
+
* geolocation when userRegion already exists.
|
|
726
746
|
*
|
|
727
747
|
* @param options - Options for cache behavior. forceRefresh bypasses idempotency and re-runs the full flow.
|
|
728
748
|
* @returns Promise that resolves when initialization is complete.
|
|
@@ -759,6 +779,7 @@ class RampsController extends base_controller_1.BaseController {
|
|
|
759
779
|
this.update((state) => {
|
|
760
780
|
state.countries.data = Array.isArray(countries) ? [...countries] : [];
|
|
761
781
|
});
|
|
782
|
+
__classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_syncUserRegionFromCountriesCatalog).call(this);
|
|
762
783
|
return countries;
|
|
763
784
|
}
|
|
764
785
|
/**
|
|
@@ -833,7 +854,6 @@ class RampsController extends base_controller_1.BaseController {
|
|
|
833
854
|
* @param options - Options for cache behavior and query filters.
|
|
834
855
|
* @param options.provider - Provider ID(s) to filter by.
|
|
835
856
|
* @param options.crypto - Crypto currency ID(s) to filter by.
|
|
836
|
-
* @param options.fiat - Fiat currency ID(s) to filter by.
|
|
837
857
|
* @param options.payments - Payment method ID(s) to filter by.
|
|
838
858
|
* @returns The providers response containing providers array.
|
|
839
859
|
*/
|
|
@@ -844,14 +864,12 @@ class RampsController extends base_controller_1.BaseController {
|
|
|
844
864
|
normalizedRegion,
|
|
845
865
|
options?.provider,
|
|
846
866
|
options?.crypto,
|
|
847
|
-
options?.fiat,
|
|
848
867
|
options?.payments,
|
|
849
868
|
]);
|
|
850
869
|
const { providers } = await this.executeRequest(cacheKey, async () => {
|
|
851
870
|
return this.messenger.call('RampsService:getProviders', normalizedRegion, {
|
|
852
871
|
provider: options?.provider,
|
|
853
872
|
crypto: options?.crypto,
|
|
854
|
-
fiat: options?.fiat,
|
|
855
873
|
payments: options?.payments,
|
|
856
874
|
});
|
|
857
875
|
}, {
|
|
@@ -873,31 +891,23 @@ class RampsController extends base_controller_1.BaseController {
|
|
|
873
891
|
*
|
|
874
892
|
* @param region - User's region code (e.g. "fr", "us-ny").
|
|
875
893
|
* @param options - Query parameters for filtering payment methods.
|
|
876
|
-
* @param options.fiat - Fiat currency code (e.g., "usd"). If not provided, uses the user's region currency.
|
|
877
894
|
* @param options.assetId - CAIP-19 cryptocurrency identifier.
|
|
878
895
|
* @param options.provider - Provider ID path.
|
|
879
896
|
* @returns The payment methods response containing payments array.
|
|
880
897
|
*/
|
|
881
898
|
async getPaymentMethods(region, options) {
|
|
882
899
|
const regionCode = region ?? __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_requireRegion).call(this);
|
|
883
|
-
const fiatToUse = options?.fiat ?? this.state.userRegion?.country?.currency ?? null;
|
|
884
900
|
const assetIdToUse = options?.assetId ?? this.state.tokens.selected?.assetId ?? '';
|
|
885
901
|
const providerToUse = options?.provider ?? this.state.providers.selected?.id ?? '';
|
|
886
|
-
if (!fiatToUse) {
|
|
887
|
-
throw new Error('Fiat currency is required. Either provide a fiat parameter or ensure userRegion is set in controller state.');
|
|
888
|
-
}
|
|
889
902
|
const normalizedRegion = regionCode.toLowerCase().trim();
|
|
890
|
-
const normalizedFiat = fiatToUse.toLowerCase().trim();
|
|
891
903
|
const cacheKey = (0, RequestCache_1.createCacheKey)('getPaymentMethods', [
|
|
892
904
|
normalizedRegion,
|
|
893
|
-
normalizedFiat,
|
|
894
905
|
assetIdToUse,
|
|
895
906
|
providerToUse,
|
|
896
907
|
]);
|
|
897
908
|
const response = await this.executeRequest(cacheKey, async () => {
|
|
898
909
|
return this.messenger.call('RampsService:getPaymentMethods', {
|
|
899
910
|
region: normalizedRegion,
|
|
900
|
-
fiat: normalizedFiat,
|
|
901
911
|
assetId: assetIdToUse,
|
|
902
912
|
provider: providerToUse,
|
|
903
913
|
});
|
|
@@ -1006,7 +1016,19 @@ class RampsController extends base_controller_1.BaseController {
|
|
|
1006
1016
|
if (normalizedAssetIdForValidation === '') {
|
|
1007
1017
|
throw new Error('assetId is required.');
|
|
1008
1018
|
}
|
|
1019
|
+
// When a non-`off` provider scope is active, widen the native-only
|
|
1020
|
+
// auto-selection path to every supporting provider and pick the best in-app
|
|
1021
|
+
// quote from the results (in-app vs external is only knowable per-quote via
|
|
1022
|
+
// `buyWidget.browser`). Only the auto-select/restrict path that MM Pay's
|
|
1023
|
+
// `getRampsQuote` uses is affected; explicit-`providers` callers and the
|
|
1024
|
+
// plain all-provider path are untouched.
|
|
1025
|
+
const providerScope = __classPrivateFieldGet(this, _RampsController_getProviderScope, "f").call(this);
|
|
1026
|
+
const widenToInAppProviders = providerScope !== 'off' &&
|
|
1027
|
+
!options.providers &&
|
|
1028
|
+
(options.autoSelectProvider === true ||
|
|
1029
|
+
options.restrictToKnownOrNativeProviders === true);
|
|
1009
1030
|
let providersToUse;
|
|
1031
|
+
let inAppProviderCatalog = this.state.providers.data;
|
|
1010
1032
|
if (options.providers) {
|
|
1011
1033
|
providersToUse = options.restrictToKnownOrNativeProviders
|
|
1012
1034
|
? await __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_filterProviderIdsBySupport).call(this, {
|
|
@@ -1016,6 +1038,17 @@ class RampsController extends base_controller_1.BaseController {
|
|
|
1016
1038
|
})
|
|
1017
1039
|
: options.providers;
|
|
1018
1040
|
}
|
|
1041
|
+
else if (widenToInAppProviders) {
|
|
1042
|
+
// `#getSupportingProvidersForRegion` also hydrates the provider catalog
|
|
1043
|
+
// when controller state is empty, so all-provider quoting cannot silently
|
|
1044
|
+
// return zero providers here.
|
|
1045
|
+
const { supporting } = await __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_getSupportingProvidersForRegion).call(this, {
|
|
1046
|
+
assetId: normalizedAssetIdForValidation,
|
|
1047
|
+
region: regionToUse,
|
|
1048
|
+
});
|
|
1049
|
+
inAppProviderCatalog = supporting;
|
|
1050
|
+
providersToUse = supporting.map((provider) => provider.id);
|
|
1051
|
+
}
|
|
1019
1052
|
else if (options.autoSelectProvider ||
|
|
1020
1053
|
options.restrictToKnownOrNativeProviders) {
|
|
1021
1054
|
// The restriction flag implies resolution: it must narrow the provider
|
|
@@ -1045,8 +1078,12 @@ class RampsController extends base_controller_1.BaseController {
|
|
|
1045
1078
|
// Under headless-buy gating, an empty resolved provider list means no
|
|
1046
1079
|
// eligible (native/supporting) provider exists. Return an empty response
|
|
1047
1080
|
// rather than passing `[]` to the service, which omits the provider filter
|
|
1048
|
-
// and would quote every provider.
|
|
1049
|
-
|
|
1081
|
+
// and would quote every provider. This also guards the widened in-app path:
|
|
1082
|
+
// a caller may trigger widening with `autoSelectProvider` alone (no
|
|
1083
|
+
// `restrictToKnownOrNativeProviders`), and an empty supporting set must not
|
|
1084
|
+
// fall through to unfiltered quotes from providers that do not support the
|
|
1085
|
+
// asset.
|
|
1086
|
+
if ((options.restrictToKnownOrNativeProviders || widenToInAppProviders) &&
|
|
1050
1087
|
providersToUse.length === 0) {
|
|
1051
1088
|
return { success: [], sorted: [], error: [], customActions: [] };
|
|
1052
1089
|
}
|
|
@@ -1054,6 +1091,12 @@ class RampsController extends base_controller_1.BaseController {
|
|
|
1054
1091
|
const normalizedFiat = fiatToUse.toLowerCase().trim();
|
|
1055
1092
|
const normalizedAssetId = normalizedAssetIdForValidation;
|
|
1056
1093
|
const normalizedWalletAddress = options.walletAddress.trim();
|
|
1094
|
+
// The quotes API only embeds a `buyURL`/`buyWidget` when a `redirectUrl` is
|
|
1095
|
+
// present, so on the widened in-app path (where MM Pay omits one) supply the
|
|
1096
|
+
// injected default so aggregator quotes carry a usable widget URL. An
|
|
1097
|
+
// explicit caller `redirectUrl` always wins, and scope `off` never injects.
|
|
1098
|
+
const effectiveRedirectUrl = options.redirectUrl ??
|
|
1099
|
+
(widenToInAppProviders ? __classPrivateFieldGet(this, _RampsController_getDefaultRedirectUrl, "f").call(this) : undefined);
|
|
1057
1100
|
const cacheKey = (0, RequestCache_1.createCacheKey)('getQuotes', [
|
|
1058
1101
|
normalizedRegion,
|
|
1059
1102
|
normalizedFiat,
|
|
@@ -1062,7 +1105,7 @@ class RampsController extends base_controller_1.BaseController {
|
|
|
1062
1105
|
normalizedWalletAddress,
|
|
1063
1106
|
[...paymentMethodsToUse].sort().join(','),
|
|
1064
1107
|
[...providersToUse].sort().join(','),
|
|
1065
|
-
|
|
1108
|
+
effectiveRedirectUrl,
|
|
1066
1109
|
action,
|
|
1067
1110
|
]);
|
|
1068
1111
|
const params = {
|
|
@@ -1073,15 +1116,45 @@ class RampsController extends base_controller_1.BaseController {
|
|
|
1073
1116
|
walletAddress: normalizedWalletAddress,
|
|
1074
1117
|
paymentMethods: paymentMethodsToUse,
|
|
1075
1118
|
providers: providersToUse,
|
|
1076
|
-
redirectUrl:
|
|
1119
|
+
redirectUrl: effectiveRedirectUrl,
|
|
1077
1120
|
action,
|
|
1078
1121
|
};
|
|
1079
|
-
|
|
1122
|
+
const response = await this.executeRequest(cacheKey, async () => {
|
|
1080
1123
|
return this.messenger.call('RampsService:getQuotes', params);
|
|
1081
1124
|
}, {
|
|
1082
1125
|
forceRefresh: options.forceRefresh,
|
|
1083
1126
|
ttl: options.ttl ?? DEFAULT_QUOTES_TTL,
|
|
1084
1127
|
});
|
|
1128
|
+
if (!widenToInAppProviders) {
|
|
1129
|
+
return response;
|
|
1130
|
+
}
|
|
1131
|
+
// Reduce the widened multi-provider result to the single best in-app quote
|
|
1132
|
+
// and place it at `success[0]`, since single-pick consumers
|
|
1133
|
+
// (`getRampsQuote` -> `success?.[0]`) rely on index 0 while `success[]`
|
|
1134
|
+
// order is server-defined rather than ranked.
|
|
1135
|
+
const selectedQuote = __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_pickInAppQuote).call(this, response, {
|
|
1136
|
+
scope: providerScope,
|
|
1137
|
+
amount: options.amount,
|
|
1138
|
+
fiat: normalizedFiat,
|
|
1139
|
+
providers: inAppProviderCatalog,
|
|
1140
|
+
});
|
|
1141
|
+
if (!selectedQuote) {
|
|
1142
|
+
// No usable in-app quote: surface "no quote" rather than leaking an
|
|
1143
|
+
// external/custom quote to the single-pick consumer.
|
|
1144
|
+
return {
|
|
1145
|
+
success: [],
|
|
1146
|
+
sorted: response.sorted,
|
|
1147
|
+
error: response.error,
|
|
1148
|
+
customActions: response.customActions,
|
|
1149
|
+
};
|
|
1150
|
+
}
|
|
1151
|
+
return {
|
|
1152
|
+
...response,
|
|
1153
|
+
success: [
|
|
1154
|
+
selectedQuote,
|
|
1155
|
+
...response.success.filter((quote) => quote !== selectedQuote),
|
|
1156
|
+
],
|
|
1157
|
+
};
|
|
1085
1158
|
}
|
|
1086
1159
|
// === ORDER MANAGEMENT ===
|
|
1087
1160
|
/**
|
|
@@ -1698,7 +1771,7 @@ class RampsController extends base_controller_1.BaseController {
|
|
|
1698
1771
|
}
|
|
1699
1772
|
}
|
|
1700
1773
|
exports.RampsController = RampsController;
|
|
1701
|
-
_RampsController_requestCacheTTL = new WeakMap(), _RampsController_requestCacheMaxSize = new WeakMap(), _RampsController_pendingRequests = new WeakMap(), _RampsController_pendingResourceCount = new WeakMap(), _RampsController_pendingResourceGeneration = new WeakMap(), _RampsController_orderPollingMeta = new WeakMap(), _RampsController_orderPollingTimer = new WeakMap(), _RampsController_isPolling = new WeakMap(), _RampsController_initPromise = new WeakMap(), _RampsController_instances = new WeakSet(), _RampsController_clearPendingResourceCountForDependentResources = function _RampsController_clearPendingResourceCountForDependentResources() {
|
|
1774
|
+
_RampsController_requestCacheTTL = new WeakMap(), _RampsController_requestCacheMaxSize = new WeakMap(), _RampsController_getProviderScope = new WeakMap(), _RampsController_getDefaultRedirectUrl = new WeakMap(), _RampsController_pendingRequests = new WeakMap(), _RampsController_pendingResourceCount = new WeakMap(), _RampsController_pendingResourceGeneration = new WeakMap(), _RampsController_orderPollingMeta = new WeakMap(), _RampsController_orderPollingTimer = new WeakMap(), _RampsController_isPolling = new WeakMap(), _RampsController_initPromise = new WeakMap(), _RampsController_instances = new WeakSet(), _RampsController_clearPendingResourceCountForDependentResources = function _RampsController_clearPendingResourceCountForDependentResources() {
|
|
1702
1775
|
for (const resourceType of DEPENDENT_RESOURCE_KEYS) {
|
|
1703
1776
|
__classPrivateFieldGet(this, _RampsController_pendingResourceCount, "f").delete(resourceType);
|
|
1704
1777
|
const generation = __classPrivateFieldGet(this, _RampsController_pendingResourceGeneration, "f").get(resourceType) ?? 0;
|
|
@@ -1784,20 +1857,103 @@ _RampsController_requestCacheTTL = new WeakMap(), _RampsController_requestCacheM
|
|
|
1784
1857
|
}
|
|
1785
1858
|
});
|
|
1786
1859
|
}, _RampsController_runInit = async function _RampsController_runInit(options) {
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
}
|
|
1860
|
+
// Force-refetch the catalog on startup so region preset amounts stay
|
|
1861
|
+
// current, bypassing the in-session request cache. The catalog is not
|
|
1862
|
+
// persisted, so a cold start always re-fetches it regardless.
|
|
1863
|
+
await this.getCountries({ ...options, forceRefresh: true });
|
|
1792
1864
|
// Always prefer the user's persisted region. Geolocation is only used to
|
|
1793
1865
|
// seed the initial value; once the user (or a prior init) has set a region
|
|
1794
1866
|
// we must respect that choice — even on forceRefresh.
|
|
1795
|
-
|
|
1796
|
-
|
|
1867
|
+
const persistedRegionCode = this.state.userRegion?.regionCode;
|
|
1868
|
+
const regionCode = persistedRegionCode ??
|
|
1869
|
+
(await this.messenger.call('RampsService:getGeolocation'));
|
|
1797
1870
|
if (!regionCode) {
|
|
1798
1871
|
throw new Error('Failed to fetch geolocation. Cannot initialize controller without valid region information.');
|
|
1799
1872
|
}
|
|
1873
|
+
// For an already-persisted region, getCountries() has already re-synced it
|
|
1874
|
+
// from the fresh catalog (see #syncUserRegionFromCountriesCatalog). Calling
|
|
1875
|
+
// setUserRegion here would re-validate against that catalog and, if it is
|
|
1876
|
+
// momentarily empty or no longer lists the region (e.g. a transient/partial
|
|
1877
|
+
// catalog response or a region with no current provider coverage), throw and
|
|
1878
|
+
// wipe the persisted region via #cleanupState. Preserve the existing region
|
|
1879
|
+
// instead; only resolve a brand-new region (from geolocation) strictly.
|
|
1880
|
+
if (persistedRegionCode) {
|
|
1881
|
+
return;
|
|
1882
|
+
}
|
|
1800
1883
|
await this.setUserRegion(regionCode, options);
|
|
1884
|
+
}, _RampsController_syncUserRegionFromCountriesCatalog = function _RampsController_syncUserRegionFromCountriesCatalog() {
|
|
1885
|
+
const regionCode = this.state.userRegion?.regionCode;
|
|
1886
|
+
if (!regionCode) {
|
|
1887
|
+
return;
|
|
1888
|
+
}
|
|
1889
|
+
const countriesData = this.state.countries.data;
|
|
1890
|
+
if (!countriesData.length) {
|
|
1891
|
+
return;
|
|
1892
|
+
}
|
|
1893
|
+
const userRegion = findRegionFromCode(regionCode, countriesData);
|
|
1894
|
+
if (!userRegion) {
|
|
1895
|
+
return;
|
|
1896
|
+
}
|
|
1897
|
+
this.update((state) => {
|
|
1898
|
+
state.userRegion = userRegion;
|
|
1899
|
+
});
|
|
1900
|
+
}, _RampsController_pickInAppQuote = function _RampsController_pickInAppQuote(response, { scope, amount, fiat, providers, }) {
|
|
1901
|
+
const providerByCode = new Map(providers.map((provider) => [
|
|
1902
|
+
normalizeProviderCode(provider.id),
|
|
1903
|
+
provider,
|
|
1904
|
+
]));
|
|
1905
|
+
const customActionProviderCodes = new Set(response.customActions.map((action) => normalizeProviderCode(action.buy.providerId)));
|
|
1906
|
+
const fitsProviderLimits = (quote) => {
|
|
1907
|
+
const provider = providerByCode.get(normalizeProviderCode(quote.provider));
|
|
1908
|
+
const limit = provider?.limits?.fiat?.[fiat]?.[quote.quote.paymentMethod];
|
|
1909
|
+
if (!limit) {
|
|
1910
|
+
// No published limits for this provider/payment method: treat as
|
|
1911
|
+
// eligible and let the provider enforce limits at checkout.
|
|
1912
|
+
return true;
|
|
1913
|
+
}
|
|
1914
|
+
return amount >= limit.minAmount && amount <= limit.maxAmount;
|
|
1915
|
+
};
|
|
1916
|
+
const isEligible = (quote) => {
|
|
1917
|
+
// `all` (Phase 2) skips the in-app-only exclusions; both scopes still
|
|
1918
|
+
// enforce provider limits up front.
|
|
1919
|
+
if (scope !== 'all') {
|
|
1920
|
+
const providerCode = normalizeProviderCode(quote.provider);
|
|
1921
|
+
if (customActionProviderCodes.has(providerCode)) {
|
|
1922
|
+
return false;
|
|
1923
|
+
}
|
|
1924
|
+
// Defensive: the wire may carry an inline `isCustomAction` flag that is
|
|
1925
|
+
// absent from the published `Quote` type.
|
|
1926
|
+
if (quote.quote.isCustomAction === true) {
|
|
1927
|
+
return false;
|
|
1928
|
+
}
|
|
1929
|
+
if (quote.quote.buyWidget?.browser === 'IN_APP_OS_BROWSER') {
|
|
1930
|
+
return false;
|
|
1931
|
+
}
|
|
1932
|
+
}
|
|
1933
|
+
return fitsProviderLimits(quote);
|
|
1934
|
+
};
|
|
1935
|
+
const candidates = response.success.filter(isEligible);
|
|
1936
|
+
if (candidates.length === 0) {
|
|
1937
|
+
return undefined;
|
|
1938
|
+
}
|
|
1939
|
+
const candidateByCode = new Map(candidates.map((quote) => [normalizeProviderCode(quote.provider), quote]));
|
|
1940
|
+
const pickBySortOrder = (sortBy) => {
|
|
1941
|
+
const order = response.sorted.find((entry) => entry.sortBy === sortBy)?.ids;
|
|
1942
|
+
if (!order) {
|
|
1943
|
+
return undefined;
|
|
1944
|
+
}
|
|
1945
|
+
for (const providerId of order) {
|
|
1946
|
+
const match = candidateByCode.get(normalizeProviderCode(providerId));
|
|
1947
|
+
if (match) {
|
|
1948
|
+
return match;
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1951
|
+
return undefined;
|
|
1952
|
+
};
|
|
1953
|
+
// Reliability first, then price, then the first surviving candidate.
|
|
1954
|
+
return (pickBySortOrder('reliability') ??
|
|
1955
|
+
pickBySortOrder('price') ??
|
|
1956
|
+
candidates[0]);
|
|
1801
1957
|
}, _RampsController_getSupportingProvidersForRegion =
|
|
1802
1958
|
/**
|
|
1803
1959
|
* Returns the region's providers that support the given asset, plus the full
|