@metamask-previews/ramps-controller 9.0.0-preview-d1f62d044 → 9.0.0-preview-56789ec91
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 +0 -3
- package/dist/RampsController.cjs +152 -5
- package/dist/RampsController.cjs.map +1 -1
- package/dist/RampsController.d.cts +43 -3
- package/dist/RampsController.d.cts.map +1 -1
- package/dist/RampsController.d.mts +43 -3
- package/dist/RampsController.d.mts.map +1 -1
- package/dist/RampsController.mjs +152 -5
- package/dist/RampsController.mjs.map +1 -1
- package/dist/RequestCache.cjs.map +1 -1
- package/dist/RequestCache.d.cts +1 -1
- package/dist/RequestCache.d.cts.map +1 -1
- package/dist/RequestCache.d.mts +1 -1
- package/dist/RequestCache.d.mts.map +1 -1
- package/dist/RequestCache.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,9 +9,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
9
9
|
|
|
10
10
|
### Changed
|
|
11
11
|
|
|
12
|
-
- **BREAKING:** Remove `state.quotes` and `state.widgetUrl` from RampsController state. Quote and widget URL data are now managed by consuming components ([#8013](https://github.com/MetaMask/core/pull/8013))
|
|
13
|
-
- **BREAKING:** Remove `fetchQuotesForSelection()` and `setSelectedQuote()`. Components call `getQuotes()` directly and manage selection locally ([#8013](https://github.com/MetaMask/core/pull/8013))
|
|
14
|
-
- Simplify `getWidgetUrl()` to a pure fetch-and-return API; it no longer reads or writes controller state ([#8013](https://github.com/MetaMask/core/pull/8013))
|
|
15
12
|
- Improve `TransakService` error handling ([#8010](https://github.com/MetaMask/core/pull/8010))
|
|
16
13
|
- **BREAKING:** Replace `startQuotePolling()`/`stopQuotePolling()` with `fetchQuotesForSelection()` — quotes are now fetched once per call instead of polling on a 15-second interval ([#7999](https://github.com/MetaMask/core/pull/7999))
|
|
17
14
|
|
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_clearPendingResourceCountForDependentResources, _RampsController_abortDependentRequests, _RampsController_mutateRequests, _RampsController_removeRequestState, _RampsController_cleanupState, _RampsController_fireAndForget, _RampsController_requireRegion, _RampsController_isRegionCurrent, _RampsController_isTokenCurrent, _RampsController_isProviderCurrent, _RampsController_updateResourceField, _RampsController_setResourceLoading, _RampsController_setResourceError, _RampsController_updateRequestState, _RampsController_syncTransakAuthOnError;
|
|
13
|
+
var _RampsController_instances, _RampsController_requestCacheTTL, _RampsController_requestCacheMaxSize, _RampsController_pendingRequests, _RampsController_pendingResourceCount, _RampsController_clearPendingResourceCountForDependentResources, _RampsController_abortDependentRequests, _RampsController_mutateRequests, _RampsController_removeRequestState, _RampsController_cleanupState, _RampsController_fireAndForget, _RampsController_requireRegion, _RampsController_isRegionCurrent, _RampsController_isTokenCurrent, _RampsController_isProviderCurrent, _RampsController_updateResourceField, _RampsController_setResourceLoading, _RampsController_setResourceError, _RampsController_updateRequestState, _RampsController_syncWidgetUrl, _RampsController_syncTransakAuthOnError;
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.RampsController = exports.getDefaultRampsControllerState = exports.RAMPS_CONTROLLER_REQUIRED_SERVICE_ACTIONS = exports.controllerName = void 0;
|
|
16
16
|
const base_controller_1 = require("@metamask/base-controller");
|
|
@@ -101,6 +101,18 @@ const rampsControllerMetadata = {
|
|
|
101
101
|
includeInStateLogs: true,
|
|
102
102
|
usedInUi: true,
|
|
103
103
|
},
|
|
104
|
+
quotes: {
|
|
105
|
+
persist: false,
|
|
106
|
+
includeInDebugSnapshot: true,
|
|
107
|
+
includeInStateLogs: false,
|
|
108
|
+
usedInUi: true,
|
|
109
|
+
},
|
|
110
|
+
widgetUrl: {
|
|
111
|
+
persist: false,
|
|
112
|
+
includeInDebugSnapshot: true,
|
|
113
|
+
includeInStateLogs: false,
|
|
114
|
+
usedInUi: true,
|
|
115
|
+
},
|
|
104
116
|
requests: {
|
|
105
117
|
persist: false,
|
|
106
118
|
includeInDebugSnapshot: true,
|
|
@@ -146,6 +158,8 @@ function getDefaultRampsControllerState() {
|
|
|
146
158
|
providers: createDefaultResourceState([], null),
|
|
147
159
|
tokens: createDefaultResourceState(null, null),
|
|
148
160
|
paymentMethods: createDefaultResourceState([], null),
|
|
161
|
+
quotes: createDefaultResourceState(null, null),
|
|
162
|
+
widgetUrl: createDefaultResourceState(null),
|
|
149
163
|
requests: {},
|
|
150
164
|
nativeProviders: {
|
|
151
165
|
transak: {
|
|
@@ -162,6 +176,7 @@ const DEPENDENT_RESOURCE_KEYS = [
|
|
|
162
176
|
'providers',
|
|
163
177
|
'tokens',
|
|
164
178
|
'paymentMethods',
|
|
179
|
+
'quotes',
|
|
165
180
|
];
|
|
166
181
|
const DEPENDENT_RESOURCE_KEYS_SET = new Set(DEPENDENT_RESOURCE_KEYS);
|
|
167
182
|
function resetResource(state, resourceType, defaultResource) {
|
|
@@ -173,7 +188,20 @@ function resetResource(state, resourceType, defaultResource) {
|
|
|
173
188
|
resource.error = def.error;
|
|
174
189
|
}
|
|
175
190
|
/**
|
|
176
|
-
* Resets
|
|
191
|
+
* Resets the widgetUrl resource to its default state.
|
|
192
|
+
* Mutates state in place; use from within controller update() for atomic updates.
|
|
193
|
+
*
|
|
194
|
+
* @param state - The state object to mutate.
|
|
195
|
+
*/
|
|
196
|
+
function resetWidgetUrl(state) {
|
|
197
|
+
const def = getDefaultRampsControllerState().widgetUrl;
|
|
198
|
+
state.widgetUrl.data = def.data;
|
|
199
|
+
state.widgetUrl.selected = def.selected;
|
|
200
|
+
state.widgetUrl.isLoading = def.isLoading;
|
|
201
|
+
state.widgetUrl.error = def.error;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Resets region-dependent resources (userRegion, providers, tokens, paymentMethods, quotes).
|
|
177
205
|
* Mutates state in place; use from within controller update() for atomic updates.
|
|
178
206
|
*
|
|
179
207
|
* @param state - The state object to mutate.
|
|
@@ -188,6 +216,7 @@ function resetDependentResources(state, options) {
|
|
|
188
216
|
for (const key of DEPENDENT_RESOURCE_KEYS) {
|
|
189
217
|
resetResource(state, key, defaultState[key]);
|
|
190
218
|
}
|
|
219
|
+
resetWidgetUrl(state);
|
|
191
220
|
}
|
|
192
221
|
// === HELPER FUNCTIONS ===
|
|
193
222
|
/**
|
|
@@ -521,6 +550,8 @@ class RampsController extends base_controller_1.BaseController {
|
|
|
521
550
|
this.update((state) => {
|
|
522
551
|
state.providers.selected = provider;
|
|
523
552
|
resetResource(state, 'paymentMethods');
|
|
553
|
+
state.quotes.selected = null;
|
|
554
|
+
resetWidgetUrl(state);
|
|
524
555
|
});
|
|
525
556
|
__classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_fireAndForget).call(this, this.getPaymentMethods(regionCode, { provider: provider.id }));
|
|
526
557
|
}
|
|
@@ -630,6 +661,8 @@ class RampsController extends base_controller_1.BaseController {
|
|
|
630
661
|
this.update((state) => {
|
|
631
662
|
state.tokens.selected = token;
|
|
632
663
|
resetResource(state, 'paymentMethods');
|
|
664
|
+
state.quotes.selected = null;
|
|
665
|
+
resetWidgetUrl(state);
|
|
633
666
|
});
|
|
634
667
|
__classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_fireAndForget).call(this, this.getPaymentMethods(regionCode, { assetId: token.assetId }));
|
|
635
668
|
}
|
|
@@ -766,7 +799,7 @@ class RampsController extends base_controller_1.BaseController {
|
|
|
766
799
|
}
|
|
767
800
|
/**
|
|
768
801
|
* Fetches quotes from all providers for a given set of parameters.
|
|
769
|
-
*
|
|
802
|
+
* The quotes are saved in the controller state once fetched.
|
|
770
803
|
*
|
|
771
804
|
* @param options - The parameters for fetching quotes.
|
|
772
805
|
* @param options.region - User's region code. If not provided, uses userRegion from state.
|
|
@@ -835,12 +868,91 @@ class RampsController extends base_controller_1.BaseController {
|
|
|
835
868
|
redirectUrl: options.redirectUrl,
|
|
836
869
|
action,
|
|
837
870
|
};
|
|
838
|
-
|
|
871
|
+
const response = await this.executeRequest(cacheKey, async () => {
|
|
839
872
|
return this.messenger.call('RampsService:getQuotes', params);
|
|
840
873
|
}, {
|
|
841
874
|
forceRefresh: options.forceRefresh,
|
|
842
875
|
ttl: options.ttl ?? DEFAULT_QUOTES_TTL,
|
|
876
|
+
resourceType: 'quotes',
|
|
877
|
+
isResultCurrent: () => __classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_isRegionCurrent).call(this, normalizedRegion),
|
|
878
|
+
});
|
|
879
|
+
this.update((state) => {
|
|
880
|
+
const userRegionCode = state.userRegion?.regionCode;
|
|
881
|
+
if (userRegionCode === undefined || userRegionCode === normalizedRegion) {
|
|
882
|
+
state.quotes.data = response;
|
|
883
|
+
}
|
|
884
|
+
});
|
|
885
|
+
return response;
|
|
886
|
+
}
|
|
887
|
+
/**
|
|
888
|
+
* Fetches quotes for the currently selected token, provider, and payment method.
|
|
889
|
+
* If the response contains exactly one quote, it is auto-selected.
|
|
890
|
+
* If multiple quotes are returned, the existing selection is preserved if still valid.
|
|
891
|
+
*
|
|
892
|
+
* Returns early (no-op) if the selected payment method is not yet set,
|
|
893
|
+
* allowing callers to invoke this before payment-method selection is finalized.
|
|
894
|
+
*
|
|
895
|
+
* @param options - Parameters for fetching quotes.
|
|
896
|
+
* @param options.walletAddress - The destination wallet address.
|
|
897
|
+
* @param options.amount - The amount (in fiat for buy, crypto for sell).
|
|
898
|
+
* @param options.redirectUrl - Optional redirect URL after order completion.
|
|
899
|
+
* @throws If required dependencies (region, token, provider) are not set.
|
|
900
|
+
*/
|
|
901
|
+
fetchQuotesForSelection(options) {
|
|
902
|
+
__classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_requireRegion).call(this);
|
|
903
|
+
const token = this.state.tokens.selected;
|
|
904
|
+
const provider = this.state.providers.selected;
|
|
905
|
+
const paymentMethod = this.state.paymentMethods.selected;
|
|
906
|
+
if (!token) {
|
|
907
|
+
throw new Error('Token is required. Cannot fetch quotes without a selected token.');
|
|
908
|
+
}
|
|
909
|
+
if (!provider) {
|
|
910
|
+
throw new Error('Provider is required. Cannot fetch quotes without a selected provider.');
|
|
911
|
+
}
|
|
912
|
+
if (!paymentMethod) {
|
|
913
|
+
return;
|
|
914
|
+
}
|
|
915
|
+
__classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_fireAndForget).call(this, this.getQuotes({
|
|
916
|
+
assetId: token.assetId,
|
|
917
|
+
amount: options.amount,
|
|
918
|
+
walletAddress: options.walletAddress,
|
|
919
|
+
redirectUrl: options.redirectUrl,
|
|
920
|
+
paymentMethods: [paymentMethod.id],
|
|
921
|
+
providers: [provider.id],
|
|
922
|
+
forceRefresh: true,
|
|
923
|
+
}).then((response) => {
|
|
924
|
+
let newSelectedQuote = null;
|
|
925
|
+
this.update((state) => {
|
|
926
|
+
if (response.success.length === 1) {
|
|
927
|
+
newSelectedQuote = response.success[0];
|
|
928
|
+
state.quotes.selected = newSelectedQuote;
|
|
929
|
+
}
|
|
930
|
+
else {
|
|
931
|
+
const currentSelection = state.quotes.selected;
|
|
932
|
+
if (currentSelection) {
|
|
933
|
+
const freshQuote = response.success.find((quote) => quote.provider === currentSelection.provider &&
|
|
934
|
+
quote.quote.paymentMethod ===
|
|
935
|
+
currentSelection.quote.paymentMethod);
|
|
936
|
+
newSelectedQuote = freshQuote ?? null;
|
|
937
|
+
state.quotes.selected = newSelectedQuote;
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
});
|
|
941
|
+
__classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_syncWidgetUrl).call(this, newSelectedQuote);
|
|
942
|
+
return undefined;
|
|
943
|
+
}));
|
|
944
|
+
}
|
|
945
|
+
/**
|
|
946
|
+
* Manually sets the selected quote.
|
|
947
|
+
* Automatically triggers a widget URL fetch for the new quote.
|
|
948
|
+
*
|
|
949
|
+
* @param quote - The quote to select, or null to clear the selection.
|
|
950
|
+
*/
|
|
951
|
+
setSelectedQuote(quote) {
|
|
952
|
+
this.update((state) => {
|
|
953
|
+
state.quotes.selected = quote;
|
|
843
954
|
});
|
|
955
|
+
__classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_syncWidgetUrl).call(this, quote);
|
|
844
956
|
}
|
|
845
957
|
/**
|
|
846
958
|
* Cleans up controller resources.
|
|
@@ -852,10 +964,12 @@ class RampsController extends base_controller_1.BaseController {
|
|
|
852
964
|
/**
|
|
853
965
|
* Fetches the widget URL from a quote for redirect providers.
|
|
854
966
|
* Makes a request to the buyURL endpoint via the RampsService to get the
|
|
855
|
-
* actual provider widget URL.
|
|
967
|
+
* actual provider widget URL, using the injected fetch and retry policy.
|
|
856
968
|
*
|
|
857
969
|
* @param quote - The quote to fetch the widget URL from.
|
|
858
970
|
* @returns Promise resolving to the widget URL string, or null if not available.
|
|
971
|
+
* @deprecated Read `state.widgetUrl` instead. The widget URL is now automatically
|
|
972
|
+
* fetched and stored in state whenever the selected quote changes.
|
|
859
973
|
*/
|
|
860
974
|
async getWidgetUrl(quote) {
|
|
861
975
|
const buyUrl = quote.quote?.buyURL;
|
|
@@ -1375,6 +1489,39 @@ _RampsController_requestCacheTTL = new WeakMap(), _RampsController_requestCacheM
|
|
|
1375
1489
|
}
|
|
1376
1490
|
}
|
|
1377
1491
|
});
|
|
1492
|
+
}, _RampsController_syncWidgetUrl = function _RampsController_syncWidgetUrl(quote) {
|
|
1493
|
+
const buyUrl = quote?.quote?.buyURL;
|
|
1494
|
+
if (!buyUrl) {
|
|
1495
|
+
this.update((state) => {
|
|
1496
|
+
resetWidgetUrl(state);
|
|
1497
|
+
});
|
|
1498
|
+
return;
|
|
1499
|
+
}
|
|
1500
|
+
if (this.state.widgetUrl.data === null) {
|
|
1501
|
+
this.update((state) => {
|
|
1502
|
+
state.widgetUrl.isLoading = true;
|
|
1503
|
+
state.widgetUrl.error = null;
|
|
1504
|
+
});
|
|
1505
|
+
}
|
|
1506
|
+
__classPrivateFieldGet(this, _RampsController_instances, "m", _RampsController_fireAndForget).call(this, this.messenger
|
|
1507
|
+
.call('RampsService:getBuyWidgetUrl', buyUrl)
|
|
1508
|
+
.then((buyWidget) => {
|
|
1509
|
+
this.update((state) => {
|
|
1510
|
+
state.widgetUrl.data = buyWidget;
|
|
1511
|
+
state.widgetUrl.isLoading = false;
|
|
1512
|
+
state.widgetUrl.error = null;
|
|
1513
|
+
});
|
|
1514
|
+
return undefined;
|
|
1515
|
+
})
|
|
1516
|
+
.catch((error) => {
|
|
1517
|
+
this.update((state) => {
|
|
1518
|
+
state.widgetUrl.isLoading = false;
|
|
1519
|
+
state.widgetUrl.error =
|
|
1520
|
+
error instanceof Error
|
|
1521
|
+
? error.message
|
|
1522
|
+
: 'Failed to fetch widget URL';
|
|
1523
|
+
});
|
|
1524
|
+
}));
|
|
1378
1525
|
}, _RampsController_syncTransakAuthOnError = function _RampsController_syncTransakAuthOnError(error) {
|
|
1379
1526
|
if (error instanceof Error &&
|
|
1380
1527
|
'httpStatus' in error &&
|