@metamask/ramps-controller 22.0.0 → 24.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 +35 -2
- package/dist/NeoBankService-method-action-types.d.ts +10 -1
- package/dist/NeoBankService-method-action-types.d.ts.map +1 -1
- package/dist/NeoBankService-method-action-types.js.map +1 -1
- package/dist/NeoBankService.d.ts +6 -0
- package/dist/NeoBankService.d.ts.map +1 -1
- package/dist/NeoBankService.js +13 -0
- package/dist/NeoBankService.js.map +1 -1
- package/dist/RampsController-method-action-types.d.ts +62 -1
- package/dist/RampsController-method-action-types.d.ts.map +1 -1
- package/dist/RampsController-method-action-types.js.map +1 -1
- package/dist/RampsController.d.ts +130 -5
- package/dist/RampsController.d.ts.map +1 -1
- package/dist/RampsController.js +295 -3
- package/dist/RampsController.js.map +1 -1
- package/dist/RampsService-method-action-types.d.ts +3 -1
- package/dist/RampsService-method-action-types.d.ts.map +1 -1
- package/dist/RampsService-method-action-types.js.map +1 -1
- package/dist/RampsService.d.ts +3 -1
- package/dist/RampsService.d.ts.map +1 -1
- package/dist/RampsService.js +3 -2
- package/dist/RampsService.js.map +1 -1
- package/dist/TransakService.d.ts +3 -1
- package/dist/TransakService.d.ts.map +1 -1
- package/dist/TransakService.js +10 -3
- package/dist/TransakService.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/RampsController.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BaseController } from '@metamask/base-controller';
|
|
2
2
|
import { BrokenCircuitError } from '@metamask/controller-utils';
|
|
3
|
-
import {
|
|
3
|
+
import { BigNumber } from 'bignumber.js';
|
|
4
|
+
import { applyAutorampRemoteStatus, AutorampStatus, createAutorampAccount, markAutorampNotified, } from './autorampAccount.js';
|
|
4
5
|
import { getHeadlessProviderAllowlist, isHeadlessAllProvidersEnabled, normalizeHeadlessProviderId, } from './featureFlags.js';
|
|
5
6
|
import { areOrdersEqual, deleteOrderInUserStorage, syncOrdersWithUserStorage as syncOrdersWithUserStorageInternal, updateOrderInUserStorage, } from './order-syncing/index.js';
|
|
6
7
|
import { PENDING_ORDER_STATUSES, TERMINAL_ORDER_STATUSES, } from './orderStatus.js';
|
|
@@ -61,6 +62,7 @@ export const RAMPS_CONTROLLER_REQUIRED_SERVICE_ACTIONS = [
|
|
|
61
62
|
'TransakService:cancelAllActiveOrders',
|
|
62
63
|
'TransakService:getActiveOrders',
|
|
63
64
|
'NeoBankService:getAutoramp',
|
|
65
|
+
'NeoBankService:getAutoramps',
|
|
64
66
|
'NeoBankService:createAutoramp',
|
|
65
67
|
'NeoBankService:getCustomerByExternalId',
|
|
66
68
|
'NeoBankService:getWalletRegistrationStatus',
|
|
@@ -79,11 +81,28 @@ export const RAMPS_CONTROLLER_REQUIRED_CONTROLLER_ACTIONS = [
|
|
|
79
81
|
'AuthenticationController:getSessionProfile',
|
|
80
82
|
'AuthenticationController:isSignedIn',
|
|
81
83
|
'KeyringController:signPersonalMessage',
|
|
84
|
+
'KycController:getSessionStatusForVendor',
|
|
85
|
+
'KycController:refreshSessionStatus',
|
|
86
|
+
'KycController:hasCompletedVendorDisclaimers',
|
|
87
|
+
'KycController:hasCompletedSessionDisclaimers',
|
|
82
88
|
'RemoteFeatureFlagController:getState',
|
|
83
89
|
'UserStorageController:getState',
|
|
84
90
|
'UserStorageController:performGetStorageAllFeatureEntries',
|
|
85
91
|
'UserStorageController:performBatchSetStorage',
|
|
86
92
|
];
|
|
93
|
+
/**
|
|
94
|
+
* The Mobile route for the current VBA onboarding step.
|
|
95
|
+
*/
|
|
96
|
+
export var VbaOnboardingStage;
|
|
97
|
+
(function (VbaOnboardingStage) {
|
|
98
|
+
VbaOnboardingStage["EmailOtpRequired"] = "EmailOtpRequired";
|
|
99
|
+
VbaOnboardingStage["VendorTermsRequired"] = "VendorTermsRequired";
|
|
100
|
+
VbaOnboardingStage["ProviderTermsRequired"] = "ProviderTermsRequired";
|
|
101
|
+
VbaOnboardingStage["KycRequired"] = "KycRequired";
|
|
102
|
+
VbaOnboardingStage["KycPending"] = "KycPending";
|
|
103
|
+
VbaOnboardingStage["KycRejected"] = "KycRejected";
|
|
104
|
+
VbaOnboardingStage["Completed"] = "Completed";
|
|
105
|
+
})(VbaOnboardingStage || (VbaOnboardingStage = {}));
|
|
87
106
|
/**
|
|
88
107
|
* Distinguishes an already-materialized {@link AutorampAccount} from the
|
|
89
108
|
* create-fields shape accepted by {@link RampsController.addAutoramp}.
|
|
@@ -218,6 +237,12 @@ const rampsControllerMetadata = {
|
|
|
218
237
|
includeInStateLogs: true,
|
|
219
238
|
usedInUi: true,
|
|
220
239
|
},
|
|
240
|
+
vbaOnboardingStage: {
|
|
241
|
+
persist: true,
|
|
242
|
+
includeInDebugSnapshot: true,
|
|
243
|
+
includeInStateLogs: true,
|
|
244
|
+
usedInUi: true,
|
|
245
|
+
},
|
|
221
246
|
};
|
|
222
247
|
/**
|
|
223
248
|
* Creates a default resource state object.
|
|
@@ -263,6 +288,7 @@ export function getDefaultRampsControllerState() {
|
|
|
263
288
|
orders: [],
|
|
264
289
|
autoramps: [],
|
|
265
290
|
providerAutoSelected: false,
|
|
291
|
+
vbaOnboardingStage: null,
|
|
266
292
|
};
|
|
267
293
|
}
|
|
268
294
|
const DEPENDENT_RESOURCE_KEYS = [
|
|
@@ -409,10 +435,12 @@ const MESSENGER_EXPOSED_METHODS = [
|
|
|
409
435
|
'getPaymentMethodsForContext',
|
|
410
436
|
'setSelectedPaymentMethod',
|
|
411
437
|
'getQuotes',
|
|
438
|
+
'getQuoteWithFees',
|
|
412
439
|
'addOrder',
|
|
413
440
|
'removeOrder',
|
|
414
441
|
'addAutoramp',
|
|
415
442
|
'createAutoramp',
|
|
443
|
+
'hydrateVbaOnboarding',
|
|
416
444
|
'removeAutoramp',
|
|
417
445
|
'registerMoneyAccountWallet',
|
|
418
446
|
'markAutorampAsNotified',
|
|
@@ -474,6 +502,27 @@ function contextStillMatches(state, context) {
|
|
|
474
502
|
context.assetId &&
|
|
475
503
|
(state.providers.selected?.id.trim() ?? '') === context.providerId);
|
|
476
504
|
}
|
|
505
|
+
/**
|
|
506
|
+
* Provider codes that identify Transak's native (non-aggregator) integration,
|
|
507
|
+
* in the bare form produced by {@link normalizeHeadlessProviderId}.
|
|
508
|
+
*/
|
|
509
|
+
const NATIVE_TRANSAK_PROVIDER_CODES = [
|
|
510
|
+
'transak-native',
|
|
511
|
+
'transak-native-staging',
|
|
512
|
+
];
|
|
513
|
+
/**
|
|
514
|
+
* Coerces a quote fee value to a non-negative BigNumber, treating a missing or
|
|
515
|
+
* invalid value as zero.
|
|
516
|
+
*
|
|
517
|
+
* @param value - Raw fee value from a quote.
|
|
518
|
+
* @returns The fee as a non-negative BigNumber.
|
|
519
|
+
*/
|
|
520
|
+
function getSafeRampsFee(value) {
|
|
521
|
+
const fee = new BigNumber(value ?? 0);
|
|
522
|
+
return fee.isFinite() && fee.isGreaterThanOrEqualTo(0)
|
|
523
|
+
? fee
|
|
524
|
+
: new BigNumber(0);
|
|
525
|
+
}
|
|
477
526
|
export class RampsController extends BaseController {
|
|
478
527
|
/**
|
|
479
528
|
* Default TTL for cached requests.
|
|
@@ -504,6 +553,7 @@ export class RampsController extends BaseController {
|
|
|
504
553
|
#orderPollingTimer = null;
|
|
505
554
|
#isPolling = false;
|
|
506
555
|
#initPromise = null;
|
|
556
|
+
#vbaOnboardingHydrationPromise = null;
|
|
507
557
|
/**
|
|
508
558
|
* Semaphore that prevents sync feedback loops while applying remote order changes.
|
|
509
559
|
*/
|
|
@@ -1666,6 +1716,120 @@ export class RampsController extends BaseController {
|
|
|
1666
1716
|
],
|
|
1667
1717
|
};
|
|
1668
1718
|
}
|
|
1719
|
+
/**
|
|
1720
|
+
* Fetches the best on-ramp quote for a request and, when the resolved
|
|
1721
|
+
* provider is Transak Native, reconciles its fees to match what Transak
|
|
1722
|
+
* Native actually charges.
|
|
1723
|
+
*
|
|
1724
|
+
* The aggregator `/quotes` estimate of Transak's fee does not match the
|
|
1725
|
+
* native integration. When the resolved provider is Transak Native this
|
|
1726
|
+
* fetches the native buy quote (an unauthenticated, API-key-only lookup, so
|
|
1727
|
+
* it is safe at estimate time) and rewrites the returned quote's fee fields
|
|
1728
|
+
* to its `totalFee`, keeping the aggregator's `networkFee` on the network
|
|
1729
|
+
* line and placing the remainder in the provider fee so the breakdown
|
|
1730
|
+
* survives and `providerFee + networkFee` still equals the native total. A
|
|
1731
|
+
* non-native provider, a failed lookup, or an unusable native fee returns the
|
|
1732
|
+
* aggregator quote unchanged.
|
|
1733
|
+
*
|
|
1734
|
+
* Consumers (e.g. `TransactionPayController`) call this instead of owning the
|
|
1735
|
+
* provider check, asset-id parsing, and second native quote themselves.
|
|
1736
|
+
*
|
|
1737
|
+
* @param options - Quote options; see {@link getQuotes}, plus the fee mode.
|
|
1738
|
+
* @param options.amount - Fiat amount for the quote.
|
|
1739
|
+
* @param options.assetId - CAIP-19 asset id being bought.
|
|
1740
|
+
* @param options.fiat - Optional fiat currency; defaults like {@link getQuotes}.
|
|
1741
|
+
* @param options.paymentMethods - Optional payment method ids.
|
|
1742
|
+
* @param options.walletAddress - Wallet address receiving the on-ramped asset.
|
|
1743
|
+
* @param options.isFeeExcludedFromFiat - Whether Transak adds its fee on top
|
|
1744
|
+
* of the fiat amount (`true`, fee-on-top) or carves it out (`false`). Must
|
|
1745
|
+
* mirror the eventual checkout mode so the estimate equals the charge.
|
|
1746
|
+
* Defaults to `true`.
|
|
1747
|
+
* @param options.providers - See {@link getQuotes}.
|
|
1748
|
+
* @param options.autoSelectProvider - See {@link getQuotes}.
|
|
1749
|
+
* @param options.restrictToKnownOrNativeProviders - See {@link getQuotes}.
|
|
1750
|
+
* @param options.preferredProviderIds - See {@link getQuotes}.
|
|
1751
|
+
* @param options.region - See {@link getQuotes}.
|
|
1752
|
+
* @param options.redirectUrl - See {@link getQuotes}.
|
|
1753
|
+
* @param options.action - See {@link getQuotes}.
|
|
1754
|
+
* @param options.forceRefresh - See {@link getQuotes}.
|
|
1755
|
+
* @param options.ttl - See {@link getQuotes}.
|
|
1756
|
+
* @returns The best quote with native-reconciled fees, or `undefined` when
|
|
1757
|
+
* no quote is available.
|
|
1758
|
+
*/
|
|
1759
|
+
async getQuoteWithFees(options) {
|
|
1760
|
+
const { isFeeExcludedFromFiat = true, ...quoteOptions } = options;
|
|
1761
|
+
const response = await this.getQuotes(quoteOptions);
|
|
1762
|
+
const quote = response.success?.[0];
|
|
1763
|
+
if (!quote) {
|
|
1764
|
+
return undefined;
|
|
1765
|
+
}
|
|
1766
|
+
return this.#reconcileNativeTransakFee(quote, {
|
|
1767
|
+
amount: options.amount,
|
|
1768
|
+
assetId: options.assetId,
|
|
1769
|
+
fiat: options.fiat,
|
|
1770
|
+
// Use the resolved quote's own payment method, not the request list: the
|
|
1771
|
+
// aggregator may price a method other than `paymentMethods[0]` (or the
|
|
1772
|
+
// caller may omit the list), and the native lookup must match the quote
|
|
1773
|
+
// being reconciled.
|
|
1774
|
+
paymentMethod: quote.quote.paymentMethod,
|
|
1775
|
+
isFeeExcludedFromFiat,
|
|
1776
|
+
});
|
|
1777
|
+
}
|
|
1778
|
+
/**
|
|
1779
|
+
* Rewrites a quote's fees to Transak Native's own total when the resolved
|
|
1780
|
+
* provider is Transak Native, so an estimate matches the native charge.
|
|
1781
|
+
* Returns the quote unchanged for a non-native provider, a failed native
|
|
1782
|
+
* lookup, or an unusable native fee.
|
|
1783
|
+
*
|
|
1784
|
+
* @param quote - The resolved aggregator quote.
|
|
1785
|
+
* @param context - Native lookup inputs.
|
|
1786
|
+
* @param context.amount - Fiat amount for the native quote.
|
|
1787
|
+
* @param context.assetId - CAIP-19 asset id being bought.
|
|
1788
|
+
* @param context.fiat - Fiat currency for the native quote.
|
|
1789
|
+
* @param context.paymentMethod - Payment method id for the native quote.
|
|
1790
|
+
* @param context.isFeeExcludedFromFiat - Fee mode for the native quote.
|
|
1791
|
+
* @returns The quote with reconciled fees, or the original quote.
|
|
1792
|
+
*/
|
|
1793
|
+
async #reconcileNativeTransakFee(quote, { amount, assetId, fiat, paymentMethod, isFeeExcludedFromFiat, }) {
|
|
1794
|
+
// `normalizeHeadlessProviderId` strips the `/providers/` prefix and
|
|
1795
|
+
// lowercases, so `/providers/transak-native` and `transak-native` both match
|
|
1796
|
+
// the native codes below (and the aggregator `transak` does not).
|
|
1797
|
+
const providerCode = normalizeHeadlessProviderId(quote.provider);
|
|
1798
|
+
if (!NATIVE_TRANSAK_PROVIDER_CODES.includes(providerCode)) {
|
|
1799
|
+
return quote;
|
|
1800
|
+
}
|
|
1801
|
+
const fiatCurrency = fiat ?? this.state.userRegion?.country?.currency;
|
|
1802
|
+
if (!fiatCurrency || !paymentMethod) {
|
|
1803
|
+
return quote;
|
|
1804
|
+
}
|
|
1805
|
+
try {
|
|
1806
|
+
const network = assetId.split('/')[0];
|
|
1807
|
+
const nativeQuote = await this.messenger.call('TransakService:getBuyQuote', fiatCurrency, assetId, network, paymentMethod, String(amount), isFeeExcludedFromFiat);
|
|
1808
|
+
const nativeTotalFee = new BigNumber(nativeQuote.totalFee ?? NaN);
|
|
1809
|
+
if (!nativeTotalFee.isFinite() || nativeTotalFee.isLessThan(0)) {
|
|
1810
|
+
return quote;
|
|
1811
|
+
}
|
|
1812
|
+
// Transak Native returns a single total fee, so keep the aggregator's
|
|
1813
|
+
// network fee on the network line (clamped to the native total) and put
|
|
1814
|
+
// the remainder in the provider fee. The breakdown survives and
|
|
1815
|
+
// `providerFee + networkFee` still equals the native total.
|
|
1816
|
+
const aggregatorNetworkFee = getSafeRampsFee(quote.quote.networkFee);
|
|
1817
|
+
const networkFee = BigNumber.min(aggregatorNetworkFee, nativeTotalFee);
|
|
1818
|
+
const providerFee = nativeTotalFee.minus(networkFee);
|
|
1819
|
+
return {
|
|
1820
|
+
...quote,
|
|
1821
|
+
quote: {
|
|
1822
|
+
...quote.quote,
|
|
1823
|
+
providerFee: providerFee.toString(10),
|
|
1824
|
+
networkFee: networkFee.toString(10),
|
|
1825
|
+
totalFees: nativeTotalFee.toString(10),
|
|
1826
|
+
},
|
|
1827
|
+
};
|
|
1828
|
+
}
|
|
1829
|
+
catch {
|
|
1830
|
+
return quote;
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1669
1833
|
/**
|
|
1670
1834
|
* Selects the best quote from a widened multi-provider response.
|
|
1671
1835
|
*
|
|
@@ -2335,6 +2499,132 @@ export class RampsController extends BaseController {
|
|
|
2335
2499
|
}
|
|
2336
2500
|
}
|
|
2337
2501
|
}
|
|
2502
|
+
/**
|
|
2503
|
+
* Hydrates the Mobile-routable VBA onboarding stage from KYC state and
|
|
2504
|
+
* completes wallet and autoramp setup after KYC acceptance.
|
|
2505
|
+
*
|
|
2506
|
+
* Overlapping calls share one run so polling cannot trigger duplicate wallet
|
|
2507
|
+
* signatures or autoramp creation.
|
|
2508
|
+
*
|
|
2509
|
+
* @param params - VBA onboarding parameters.
|
|
2510
|
+
* @param params.walletAddress - Monad Money Account wallet address.
|
|
2511
|
+
* @returns The hydrated onboarding stage.
|
|
2512
|
+
*/
|
|
2513
|
+
async hydrateVbaOnboarding({ walletAddress, }) {
|
|
2514
|
+
if (this.#vbaOnboardingHydrationPromise) {
|
|
2515
|
+
return await this.#vbaOnboardingHydrationPromise;
|
|
2516
|
+
}
|
|
2517
|
+
const hydrationPromise = this.#hydrateVbaOnboarding(walletAddress);
|
|
2518
|
+
this.#vbaOnboardingHydrationPromise = hydrationPromise;
|
|
2519
|
+
try {
|
|
2520
|
+
return await hydrationPromise;
|
|
2521
|
+
}
|
|
2522
|
+
finally {
|
|
2523
|
+
if (this.#vbaOnboardingHydrationPromise === hydrationPromise) {
|
|
2524
|
+
this.#vbaOnboardingHydrationPromise = null;
|
|
2525
|
+
}
|
|
2526
|
+
}
|
|
2527
|
+
}
|
|
2528
|
+
async #hydrateVbaOnboarding(walletAddress) {
|
|
2529
|
+
// Fetch the customer's latest session from the vendor account so each stage
|
|
2530
|
+
// reflects backend truth (e.g. re-verification required after a new
|
|
2531
|
+
// document) rather than only device-local state. A `null` session means no
|
|
2532
|
+
// customer/session exists yet, so onboarding starts at the email step.
|
|
2533
|
+
// Prefer the in-memory/persisted session status over the backend
|
|
2534
|
+
// latest-status endpoint: after SumSub the backend endpoint lags (it still
|
|
2535
|
+
// reports kycStatus 'new' right after an 'approved' applicant result), while
|
|
2536
|
+
// the controller state reflects the journey/SDK outcome. Fall back to a
|
|
2537
|
+
// backend fetch only when the controller has no session in state (e.g. a
|
|
2538
|
+
// reinstall/cleared state resuming an existing customer, or a brand-new user
|
|
2539
|
+
// with no session at all).
|
|
2540
|
+
let session = null;
|
|
2541
|
+
try {
|
|
2542
|
+
session = this.messenger.call('KycController:refreshSessionStatus');
|
|
2543
|
+
}
|
|
2544
|
+
catch {
|
|
2545
|
+
try {
|
|
2546
|
+
session = await this.messenger.call('KycController:getSessionStatusForVendor', 'iron');
|
|
2547
|
+
}
|
|
2548
|
+
catch {
|
|
2549
|
+
// No session exists for this customer yet: the backend returns 404
|
|
2550
|
+
// ("KYC session not found"), which surfaces as a rejection here. Treat
|
|
2551
|
+
// it as "start onboarding at the email step" rather than an error.
|
|
2552
|
+
session = null;
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
if (!session) {
|
|
2556
|
+
return this.#setVbaOnboardingStage(VbaOnboardingStage.EmailOtpRequired);
|
|
2557
|
+
}
|
|
2558
|
+
if (!(await this.messenger.call('KycController:hasCompletedVendorDisclaimers'))) {
|
|
2559
|
+
return this.#setVbaOnboardingStage(VbaOnboardingStage.VendorTermsRequired);
|
|
2560
|
+
}
|
|
2561
|
+
if (!(await this.messenger.call('KycController:hasCompletedSessionDisclaimers'))) {
|
|
2562
|
+
return this.#setVbaOnboardingStage(VbaOnboardingStage.ProviderTermsRequired);
|
|
2563
|
+
}
|
|
2564
|
+
// Status fields draw from the KYC vocabulary (new | pending | approved |
|
|
2565
|
+
// rejected | retry). `finalStatus` is the vendor's final decision, which
|
|
2566
|
+
// stays `pending` until Iron finalizes. `kycStatus` is the SumSub applicant
|
|
2567
|
+
// outcome (from the journey/SDK result): `new` before the applicant runs
|
|
2568
|
+
// SumSub, moving to `approved`/`pending` once they submit while the vendor
|
|
2569
|
+
// finalizes. So gate the SumSub screen on `kycStatus`, and only complete
|
|
2570
|
+
// onboarding once `finalStatus` is the terminal `approved`.
|
|
2571
|
+
const { finalStatus, kycStatus } = session;
|
|
2572
|
+
if (finalStatus === 'rejected' || kycStatus === 'rejected') {
|
|
2573
|
+
return this.#setVbaOnboardingStage(VbaOnboardingStage.KycRejected);
|
|
2574
|
+
}
|
|
2575
|
+
if (finalStatus !== 'approved') {
|
|
2576
|
+
if (kycStatus === 'new' || kycStatus === 'retry') {
|
|
2577
|
+
// Applicant still has to run (or re-run) SumSub document verification.
|
|
2578
|
+
return this.#setVbaOnboardingStage(VbaOnboardingStage.KycRequired);
|
|
2579
|
+
}
|
|
2580
|
+
// Submitted; vendor is finalizing → "verification in progress".
|
|
2581
|
+
return this.#setVbaOnboardingStage(VbaOnboardingStage.KycPending);
|
|
2582
|
+
}
|
|
2583
|
+
if (!walletAddress.trim()) {
|
|
2584
|
+
throw new Error('walletAddress is required after KYC acceptance.');
|
|
2585
|
+
}
|
|
2586
|
+
// KYC is approved; the remaining work activates the Money account (register
|
|
2587
|
+
// the wallet + ensure an autoramp). Those calls hit the neobank backend and
|
|
2588
|
+
// can fail transiently (e.g. an address-list lookup timeout). If they do,
|
|
2589
|
+
// keep the user on the "verification in progress" screen so a refresh
|
|
2590
|
+
// retries the activation, rather than dropping them onto the recoverable-
|
|
2591
|
+
// error screen — the KYC decision itself already succeeded.
|
|
2592
|
+
try {
|
|
2593
|
+
const registration = await this.registerMoneyAccountWallet({
|
|
2594
|
+
address: walletAddress,
|
|
2595
|
+
});
|
|
2596
|
+
if (registration.type === 'lookupUnavailable') {
|
|
2597
|
+
throw registration.error;
|
|
2598
|
+
}
|
|
2599
|
+
const remoteAutoramps = await this.messenger.call('NeoBankService:getAutoramps');
|
|
2600
|
+
const remoteAutorampIds = new Set(remoteAutoramps.map((autoramp) => autoramp.id));
|
|
2601
|
+
for (const autoramp of remoteAutoramps) {
|
|
2602
|
+
this.#applyAutorampRemoteSnapshot(autoramp);
|
|
2603
|
+
}
|
|
2604
|
+
this.update((state) => {
|
|
2605
|
+
state.autoramps = state.autoramps.filter((autoramp) => remoteAutorampIds.has(autoramp.id));
|
|
2606
|
+
});
|
|
2607
|
+
const normalizedWalletAddress = walletAddress.toLowerCase();
|
|
2608
|
+
const hasUsableAutoramp = this.state.autoramps.some((autoramp) => autoramp.walletAddress.toLowerCase() === normalizedWalletAddress &&
|
|
2609
|
+
autoramp.status !== AutorampStatus.Rejected &&
|
|
2610
|
+
autoramp.status !== AutorampStatus.Cancelled);
|
|
2611
|
+
if (!hasUsableAutoramp) {
|
|
2612
|
+
await this.createAutoramp({});
|
|
2613
|
+
}
|
|
2614
|
+
}
|
|
2615
|
+
catch {
|
|
2616
|
+
return this.#setVbaOnboardingStage(VbaOnboardingStage.KycPending);
|
|
2617
|
+
}
|
|
2618
|
+
return this.#setVbaOnboardingStage(VbaOnboardingStage.Completed);
|
|
2619
|
+
}
|
|
2620
|
+
#setVbaOnboardingStage(stage) {
|
|
2621
|
+
if (this.state.vbaOnboardingStage !== stage) {
|
|
2622
|
+
this.update((state) => {
|
|
2623
|
+
state.vbaOnboardingStage = stage;
|
|
2624
|
+
});
|
|
2625
|
+
}
|
|
2626
|
+
return stage;
|
|
2627
|
+
}
|
|
2338
2628
|
/**
|
|
2339
2629
|
* Removes a local autoramp last-seen cursor by id.
|
|
2340
2630
|
*
|
|
@@ -2825,16 +3115,18 @@ export class RampsController extends BaseController {
|
|
|
2825
3115
|
* @param network - The blockchain network identifier.
|
|
2826
3116
|
* @param paymentMethod - The payment method identifier.
|
|
2827
3117
|
* @param fiatAmount - The fiat amount as a string.
|
|
3118
|
+
* @param isFeeExcludedFromFiat - Whether fees are added to the fiat amount.
|
|
3119
|
+
* Defaults to true to preserve Unified Buy's native Transak behavior.
|
|
2828
3120
|
* @returns The buy quote with pricing and fee details.
|
|
2829
3121
|
*/
|
|
2830
|
-
async transakGetBuyQuote(fiatCurrency, cryptoCurrency, network, paymentMethod, fiatAmount) {
|
|
3122
|
+
async transakGetBuyQuote(fiatCurrency, cryptoCurrency, network, paymentMethod, fiatAmount, isFeeExcludedFromFiat = true) {
|
|
2831
3123
|
this.update((state) => {
|
|
2832
3124
|
state.nativeProviders.transak.buyQuote.isLoading = true;
|
|
2833
3125
|
state.nativeProviders.transak.buyQuote.error = null;
|
|
2834
3126
|
delete state.nativeProviders.transak.buyQuote.errorKey;
|
|
2835
3127
|
});
|
|
2836
3128
|
try {
|
|
2837
|
-
const quote = await this.messenger.call('TransakService:getBuyQuote', fiatCurrency, cryptoCurrency, network, paymentMethod, fiatAmount);
|
|
3129
|
+
const quote = await this.messenger.call('TransakService:getBuyQuote', fiatCurrency, cryptoCurrency, network, paymentMethod, fiatAmount, isFeeExcludedFromFiat);
|
|
2838
3130
|
this.update((state) => {
|
|
2839
3131
|
state.nativeProviders.transak.buyQuote.data = quote;
|
|
2840
3132
|
state.nativeProviders.transak.buyQuote.isLoading = false;
|