diff --git a/.yarn/patches/@metamask-ramps-controller-npm-17.0.0-f649ad5caf.patch b/.yarn/patches/@metamask-ramps-controller-npm-17.0.0-f649ad5caf.patch new file mode 100644 index 00000000000..deb1df4e789 --- /dev/null +++ b/.yarn/patches/@metamask-ramps-controller-npm-17.0.0-f649ad5caf.patch @@ -0,0 +1,112 @@ +diff --git a/dist/index.cjs b/dist/index.cjs +index 40aae3dc544edbdbf492eaf3b513eb21c2919ab2..1aee8cdb6e1a4990feeaa18957dd6f7bf5b0e31e 100644 +--- a/dist/index.cjs ++++ b/dist/index.cjs +@@ -49,4 +49,7 @@ Object.defineProperty(exports, "TransakOrderIdTransformer", { enumerable: true, + var transakApiErrorUtils_1 = require("./transakApiErrorUtils.cjs"); + Object.defineProperty(exports, "getTransakApiMessage", { enumerable: true, get: function () { return transakApiErrorUtils_1.getTransakApiMessage; } }); + Object.defineProperty(exports, "isTransakPhoneRegisteredError", { enumerable: true, get: function () { return transakApiErrorUtils_1.isTransakPhoneRegisteredError; } }); ++var orderStatus_1 = require("./orderStatus.cjs"); ++Object.defineProperty(exports, "TERMINAL_ORDER_STATUSES", { enumerable: true, get: function () { return orderStatus_1.TERMINAL_ORDER_STATUSES; } }); ++Object.defineProperty(exports, "isTerminalOrderStatus", { enumerable: true, get: function () { return orderStatus_1.isTerminalOrderStatus; } }); + //# sourceMappingURL=index.cjs.map +\ No newline at end of file +diff --git a/dist/index.d.cts b/dist/index.d.cts +index 965895c55dad8fc609ae5eb84df09cc22f6b5057..032116e5d0e923e621bec8f89092c9ebb2c290b7 100644 +--- a/dist/index.d.cts ++++ b/dist/index.d.cts +@@ -19,5 +19,6 @@ export { getErrorMessage, extractExplicitTypedError, normalizeToTypedError, } fr + export type { TransakServiceActions, TransakServiceEvents, TransakServiceMessenger, TransakAccessToken, TransakUserDetails, TransakUserDetailsAddress, TransakUserDetailsKycDetails, TransakBuyQuote, TransakKycRequirement, TransakAdditionalRequirement, TransakAdditionalRequirementsResponse, TransakOttResponse, TransakOrderPaymentMethod, TransakDepositOrder, TransakDepositNetwork, TransakDepositCryptoCurrency, TransakDepositPaymentMethod, TransakDepositRegion, TransakOrder, TransakQuoteTranslation, TransakTranslationRequest, TransakUserLimits, TransakIdProofStatus, PatchUserRequestBody as TransakPatchUserRequestBody, } from "./TransakService.cjs"; + export { TransakApiError, TransakService, TransakEnvironment, TransakOrderIdTransformer, } from "./TransakService.cjs"; + export { getTransakApiMessage, isTransakPhoneRegisteredError, } from "./transakApiErrorUtils.cjs"; ++export { TERMINAL_ORDER_STATUSES, isTerminalOrderStatus, } from "./orderStatus.cjs"; + export type { TransakServiceMethodActions, TransakServiceSendUserOtpAction, TransakServiceVerifyUserOtpAction, TransakServiceGetUserDetailsAction, TransakServiceGetBuyQuoteAction, TransakServiceGetKycRequirementAction, TransakServiceCreateOrderAction, TransakServiceGetOrderAction, TransakServiceRequestOttAction, TransakServiceGeneratePaymentWidgetUrlAction, } from "./TransakService-method-action-types.cjs"; + //# sourceMappingURL=index.d.cts.map +\ No newline at end of file +diff --git a/dist/index.d.mts b/dist/index.d.mts +index ccb7079fb66a3a2c5c02d70c2d9e781ed8f0c7a8..e462cb8b6570e98c8524a68f99613f912b1592e2 100644 +--- a/dist/index.d.mts ++++ b/dist/index.d.mts +@@ -19,5 +19,6 @@ export { getErrorMessage, extractExplicitTypedError, normalizeToTypedError, } fr + export type { TransakServiceActions, TransakServiceEvents, TransakServiceMessenger, TransakAccessToken, TransakUserDetails, TransakUserDetailsAddress, TransakUserDetailsKycDetails, TransakBuyQuote, TransakKycRequirement, TransakAdditionalRequirement, TransakAdditionalRequirementsResponse, TransakOttResponse, TransakOrderPaymentMethod, TransakDepositOrder, TransakDepositNetwork, TransakDepositCryptoCurrency, TransakDepositPaymentMethod, TransakDepositRegion, TransakOrder, TransakQuoteTranslation, TransakTranslationRequest, TransakUserLimits, TransakIdProofStatus, PatchUserRequestBody as TransakPatchUserRequestBody, } from "./TransakService.mjs"; + export { TransakApiError, TransakService, TransakEnvironment, TransakOrderIdTransformer, } from "./TransakService.mjs"; + export { getTransakApiMessage, isTransakPhoneRegisteredError, } from "./transakApiErrorUtils.mjs"; ++export { TERMINAL_ORDER_STATUSES, isTerminalOrderStatus, } from "./orderStatus.mjs"; + export type { TransakServiceMethodActions, TransakServiceSendUserOtpAction, TransakServiceVerifyUserOtpAction, TransakServiceGetUserDetailsAction, TransakServiceGetBuyQuoteAction, TransakServiceGetKycRequirementAction, TransakServiceCreateOrderAction, TransakServiceGetOrderAction, TransakServiceRequestOttAction, TransakServiceGeneratePaymentWidgetUrlAction, } from "./TransakService-method-action-types.mjs"; + //# sourceMappingURL=index.d.mts.map +\ No newline at end of file +diff --git a/dist/index.mjs b/dist/index.mjs +index 8c74256d67dee57e5bcea0857f9aa1924a1907a6..f15dce8e89377d849e8816afabf3018eb20253eb 100644 +--- a/dist/index.mjs ++++ b/dist/index.mjs +@@ -9,4 +9,5 @@ export { isExternalBrowserQuote, isCustomActionQuote, isInAppOnlyQuote } from ". + export { getErrorMessage, extractExplicitTypedError, normalizeToTypedError } from "./errorNormalization.mjs"; + export { TransakApiError, TransakService, TransakEnvironment, TransakOrderIdTransformer } from "./TransakService.mjs"; + export { getTransakApiMessage, isTransakPhoneRegisteredError } from "./transakApiErrorUtils.mjs"; ++export { TERMINAL_ORDER_STATUSES, isTerminalOrderStatus } from "./orderStatus.mjs"; + //# sourceMappingURL=index.mjs.map +\ No newline at end of file +diff --git a/dist/orderStatus.cjs b/dist/orderStatus.cjs +new file mode 100644 +index 0000000000000000000000000000000000000000..72d0819672e92fe9e4934fe63644e7b179a7e643 +--- /dev/null ++++ b/dist/orderStatus.cjs +@@ -0,0 +1,14 @@ ++"use strict"; ++Object.defineProperty(exports, "__esModule", { value: true }); ++exports.isTerminalOrderStatus = exports.TERMINAL_ORDER_STATUSES = void 0; ++const RampsService_1 = require("./RampsService.cjs"); ++exports.TERMINAL_ORDER_STATUSES = new Set([ ++ RampsService_1.RampsOrderStatus.Completed, ++ RampsService_1.RampsOrderStatus.Failed, ++ RampsService_1.RampsOrderStatus.Cancelled, ++ RampsService_1.RampsOrderStatus.IdExpired, ++]); ++function isTerminalOrderStatus(status) { ++ return exports.TERMINAL_ORDER_STATUSES.has(status); ++} ++exports.isTerminalOrderStatus = isTerminalOrderStatus; +diff --git a/dist/orderStatus.d.cts b/dist/orderStatus.d.cts +new file mode 100644 +index 0000000000000000000000000000000000000000..167fa02f3f9dd1fc464e3b2ba507e210a970117b +--- /dev/null ++++ b/dist/orderStatus.d.cts +@@ -0,0 +1,7 @@ ++import type { RampsOrderStatus } from "./RampsService.cjs"; ++ ++export declare const TERMINAL_ORDER_STATUSES: ReadonlySet; ++ ++export declare function isTerminalOrderStatus( ++ status: RampsOrderStatus, ++): boolean; +diff --git a/dist/orderStatus.d.mts b/dist/orderStatus.d.mts +new file mode 100644 +index 0000000000000000000000000000000000000000..1db214f23ff516d326b6e0d40099c03c72435951 +--- /dev/null ++++ b/dist/orderStatus.d.mts +@@ -0,0 +1,7 @@ ++import type { RampsOrderStatus } from "./RampsService.mjs"; ++ ++export declare const TERMINAL_ORDER_STATUSES: ReadonlySet; ++ ++export declare function isTerminalOrderStatus( ++ status: RampsOrderStatus, ++): boolean; +diff --git a/dist/orderStatus.mjs b/dist/orderStatus.mjs +new file mode 100644 +index 0000000000000000000000000000000000000000..b70f2eeeb3542573642f090e3a01f246bc0bda72 +--- /dev/null ++++ b/dist/orderStatus.mjs +@@ -0,0 +1,12 @@ ++import { RampsOrderStatus } from "./RampsService.mjs"; ++ ++export const TERMINAL_ORDER_STATUSES = new Set([ ++ RampsOrderStatus.Completed, ++ RampsOrderStatus.Failed, ++ RampsOrderStatus.Cancelled, ++ RampsOrderStatus.IdExpired, ++]); ++ ++export function isTerminalOrderStatus(status) { ++ return TERMINAL_ORDER_STATUSES.has(status); ++} diff --git a/app/components/UI/Ramp/Views/NativeFlow/BankDetails.test.tsx b/app/components/UI/Ramp/Views/NativeFlow/BankDetails.test.tsx index e64f9f042c7..ad357b1df20 100644 --- a/app/components/UI/Ramp/Views/NativeFlow/BankDetails.test.tsx +++ b/app/components/UI/Ramp/Views/NativeFlow/BankDetails.test.tsx @@ -470,6 +470,19 @@ describe('V2BankDetails', () => { }); }); + it('replaces current screen with RAMPS_ORDER_DETAILS when order status is ID_EXPIRED', () => { + mockGetOrderById.mockReturnValue( + createMockV2Order({ status: 'ID_EXPIRED' as RampsOrder['status'] }), + ); + + renderWithTheme(); + + expect(mockReplace).toHaveBeenCalledWith('RampsOrderDetails', { + orderId: 'test-order-id', + showCloseButton: true, + }); + }); + it('replaces current screen with RAMPS_ORDER_DETAILS when order status is PENDING', () => { mockGetOrderById.mockReturnValue( createMockV2Order({ status: 'PENDING' as RampsOrder['status'] }), diff --git a/app/components/UI/Ramp/Views/NativeFlow/BankDetails.tsx b/app/components/UI/Ramp/Views/NativeFlow/BankDetails.tsx index 137a7943dcf..936ae34fb7f 100644 --- a/app/components/UI/Ramp/Views/NativeFlow/BankDetails.tsx +++ b/app/components/UI/Ramp/Views/NativeFlow/BankDetails.tsx @@ -26,6 +26,7 @@ import BankDetailRow from '../../components/BankDetailRow'; import { RampsOrderStatus, type TransakDepositOrder, + isTerminalOrderStatus, } from '@metamask/ramps-controller'; import { useTheme } from '../../../../../util/theme'; import PrivacySection from '../../components/PrivacySection'; @@ -46,12 +47,6 @@ export interface BankDetailsParams { shouldUpdate?: boolean; } -const TERMINAL_STATUSES = new Set([ - RampsOrderStatus.Completed, - RampsOrderStatus.Failed, - RampsOrderStatus.Cancelled, -]); - /** * V2 bank details screen. Reads order lifecycle from controller state * and fetches deposit-specific data (paymentDetails) from TransakService. @@ -141,7 +136,7 @@ const V2BankDetails = () => { useEffect(() => { if (!order?.status) return; if ( - TERMINAL_STATUSES.has(order.status) || + isTerminalOrderStatus(order.status) || order.status === RampsOrderStatus.Pending ) { // @ts-expect-error navigation prop mismatch diff --git a/app/components/UI/Ramp/Views/OrderDetails/OrderContent.tsx b/app/components/UI/Ramp/Views/OrderDetails/OrderContent.tsx index 18b1b9f8dfd..5ea9427fd8a 100644 --- a/app/components/UI/Ramp/Views/OrderDetails/OrderContent.tsx +++ b/app/components/UI/Ramp/Views/OrderDetails/OrderContent.tsx @@ -3,7 +3,11 @@ import { StyleSheet, TouchableOpacity } from 'react-native'; import InAppBrowser from 'react-native-inappbrowser-reborn'; import Clipboard from '@react-native-clipboard/clipboard'; import { useNavigation } from '@react-navigation/native'; -import { type RampsOrder, RampsOrderStatus } from '@metamask/ramps-controller'; +import { + type RampsOrder, + RampsOrderStatus, + isTerminalOrderStatus, +} from '@metamask/ramps-controller'; import { useAnalytics } from '../../../../hooks/useAnalytics/useAnalytics'; import { MetaMetricsEvents } from '../../../../../core/Analytics'; import { createProcessingInfoModalNavigationDetails } from '../Modals/ProcessingInfoModal/ProcessingInfoModal'; @@ -39,12 +43,6 @@ import Routes from '../../../../../constants/navigation/Routes'; import { RampsOrderDetailsSelectorsIDs } from './OrderDetails.testIds'; const AMOUNT_PLACEHOLDER = '...'; -const TERMINAL_STATUSES = new Set([ - RampsOrderStatus.Completed, - RampsOrderStatus.Failed, - RampsOrderStatus.Cancelled, - RampsOrderStatus.IdExpired, -]); const localStyles = StyleSheet.create({ badgeWrapperCenter: { @@ -190,7 +188,7 @@ const OrderContent: React.FC = ({ ((order.fiatAmount != null && Number(order.fiatAmount) > 0) || (order.cryptoAmount != null && Number(order.cryptoAmount) > 0)), ); - const isTerminal = TERMINAL_STATUSES.has(order.status); + const isTerminal = isTerminalOrderStatus(order.status); const isLoading = !hasAmounts && !isTerminal; const handleClose = useCallback(() => { diff --git a/app/components/Views/confirmations/hooks/activity/useFiatOrderStatus.ts b/app/components/Views/confirmations/hooks/activity/useFiatOrderStatus.ts index ff70ba1092c..1518817ad56 100644 --- a/app/components/Views/confirmations/hooks/activity/useFiatOrderStatus.ts +++ b/app/components/Views/confirmations/hooks/activity/useFiatOrderStatus.ts @@ -1,19 +1,12 @@ import { useEffect, useRef, useState } from 'react'; import { TransactionStatus } from '@metamask/transaction-controller'; -import { RampsOrderStatus } from '@metamask/ramps-controller'; +import { RampsOrderStatus, isTerminalOrderStatus } from '@metamask/ramps-controller'; import Engine from '../../../../../core/Engine'; import type { Severity } from '../../components/status-icon'; const POLL_INTERVAL_MS = 5000; -const TERMINAL_STATUSES = new Set([ - RampsOrderStatus.Completed, - RampsOrderStatus.Failed, - RampsOrderStatus.Cancelled, - RampsOrderStatus.IdExpired, -]); - export interface FiatOrderStatusResult { severity: Severity; statusText: string; @@ -52,7 +45,7 @@ export function useFiatOrderStatus( setCryptoSymbol(order.cryptoCurrency?.symbol); setPaymentMethodName(order.paymentMethod?.name); - if (TERMINAL_STATUSES.has(order.status)) { + if (isTerminalOrderStatus(order.status)) { clearInterval(intervalRef.current); } }) diff --git a/app/core/Engine/controllers/ramps-controller/event-handlers/analytics.ts b/app/core/Engine/controllers/ramps-controller/event-handlers/analytics.ts index c68c8ff33b2..2fa25a930c7 100644 --- a/app/core/Engine/controllers/ramps-controller/event-handlers/analytics.ts +++ b/app/core/Engine/controllers/ramps-controller/event-handlers/analytics.ts @@ -2,6 +2,7 @@ import { type RampsOrder, type RampsOrderStatus, RampsOrderStatus as Status, + isTerminalOrderStatus, } from '@metamask/ramps-controller'; import { MetaMetricsEvents } from '../../../../Analytics'; import { AnalyticsEventBuilder } from '../../../../../util/analytics/AnalyticsEventBuilder'; @@ -21,18 +22,6 @@ import { // `useAnalytics` without importing the hook. import type { AnalyticsEvents } from '../../../../../components/UI/Ramp/types/depositAnalytics'; -/** - * Terminal order statuses. `@metamask/ramps-controller` keeps its - * `TERMINAL_ORDER_STATUSES` internal, so mirror it here from the exported - * `RampsOrderStatus` enum. Kept in lockstep with the controller's set. - */ -const TERMINAL_ORDER_STATUSES = new Set([ - Status.Completed, - Status.Failed, - Status.Cancelled, - Status.IdExpired, -]); - /** * Builds the `RAMPS_TRANSACTION_FAILED` payload for a headless order. Mirrors * the headless `RAMPS_TRANSACTION_CONFIRMED` payload emitted by @@ -191,7 +180,7 @@ export function handleOrderStatusChangedForMetrics({ // subscription and the direct callback emit (`emitTerminalOrderAnalyticsFromCallback`), // so the two paths cannot double-emit regardless of arrival order. if ( - TERMINAL_ORDER_STATUSES.has(order.status) && + isTerminalOrderStatus(order.status) && hasEmittedTerminalOrderAnalytics(order) ) { return; @@ -293,7 +282,7 @@ export function handleOrderStatusChangedForMetrics({ export function emitTerminalOrderAnalyticsFromCallback( order: RampsOrder, ): void { - if (!TERMINAL_ORDER_STATUSES.has(order.status)) { + if (!isTerminalOrderStatus(order.status)) { return; } try { diff --git a/package.json b/package.json index ffded7aa74b..14ea2dc4716 100644 --- a/package.json +++ b/package.json @@ -236,7 +236,8 @@ "@metamask/assets-controllers@npm:^109.2.1": "patch:@metamask/assets-controllers@npm%3A109.4.0#~/.yarn/patches/@metamask-assets-controllers-npm-109.4.0-25a362106e.patch", "@metamask/assets-controllers@npm:^109.3.0": "patch:@metamask/assets-controllers@npm%3A109.4.0#~/.yarn/patches/@metamask-assets-controllers-npm-109.4.0-25a362106e.patch", "@metamask/assets-controllers@npm:^109.4.0": "patch:@metamask/assets-controllers@npm%3A109.4.0#~/.yarn/patches/@metamask-assets-controllers-npm-109.4.0-25a362106e.patch", - "@metamask/network-enablement-controller@npm:^5.4.1": "patch:@metamask/network-enablement-controller@npm%3A5.4.1#~/.yarn/patches/@metamask-network-enablement-controller-npm-5.4.1-020a82a308.patch" + "@metamask/network-enablement-controller@npm:^5.4.1": "patch:@metamask/network-enablement-controller@npm%3A5.4.1#~/.yarn/patches/@metamask-network-enablement-controller-npm-5.4.1-020a82a308.patch", + "@metamask/ramps-controller@npm:^17.0.0": "patch:@metamask/ramps-controller@npm%3A17.0.0#~/.yarn/patches/@metamask-ramps-controller-npm-17.0.0-f649ad5caf.patch" }, "dependencies": { "@braze/react-native-sdk": "patch:@braze/react-native-sdk@npm%3A19.1.0#~/.yarn/patches/@braze-react-native-sdk-npm-19.1.0-076-reactmoduleinfo.patch", @@ -338,7 +339,7 @@ "@metamask/preinstalled-example-snap": "^0.8.1", "@metamask/profile-metrics-controller": "^4.0.1", "@metamask/profile-sync-controller": "^28.3.0", - "@metamask/ramps-controller": "^17.0.0", + "@metamask/ramps-controller": "patch:@metamask/ramps-controller@npm%3A17.0.0#~/.yarn/patches/@metamask-ramps-controller-npm-17.0.0-f649ad5caf.patch", "@metamask/react-data-query": "^0.2.0", "@metamask/react-native-acm": "patch:@metamask/react-native-acm@npm%3A1.2.0#~/.yarn/patches/@metamask-react-native-acm-npm-1.2.0-944bf863eb.patch", "@metamask/react-native-actionsheet": "2.4.2", diff --git a/yarn.lock b/yarn.lock index c84026b24d3..36416075ce3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9961,7 +9961,7 @@ __metadata: languageName: node linkType: hard -"@metamask/ramps-controller@npm:^17.0.0": +"@metamask/ramps-controller@npm:17.0.0": version: 17.0.0 resolution: "@metamask/ramps-controller@npm:17.0.0" dependencies: @@ -9974,6 +9974,19 @@ __metadata: languageName: node linkType: hard +"@metamask/ramps-controller@patch:@metamask/ramps-controller@npm%3A17.0.0#~/.yarn/patches/@metamask-ramps-controller-npm-17.0.0-f649ad5caf.patch": + version: 17.0.0 + resolution: "@metamask/ramps-controller@patch:@metamask/ramps-controller@npm%3A17.0.0#~/.yarn/patches/@metamask-ramps-controller-npm-17.0.0-f649ad5caf.patch::version=17.0.0&hash=bb4e84" + dependencies: + "@metamask/base-controller": "npm:^9.1.0" + "@metamask/controller-utils": "npm:^12.3.0" + "@metamask/messenger": "npm:^2.0.0" + "@metamask/profile-sync-controller": "npm:^28.3.0" + "@metamask/remote-feature-flag-controller": "npm:^4.2.2" + checksum: 10/ae12485de77ea07ee43db87254b11783e53db9e342386dfbff0b4db4423381bf9e3c8b9a54b382edca1fa9f591252b554155bcb7e7aaa3e9efceedec063870be + languageName: node + linkType: hard + "@metamask/react-data-query@npm:^0.2.0": version: 0.2.0 resolution: "@metamask/react-data-query@npm:0.2.0" @@ -35971,7 +35984,7 @@ __metadata: "@metamask/profile-metrics-controller": "npm:^4.0.1" "@metamask/profile-sync-controller": "npm:^28.3.0" "@metamask/providers": "npm:^18.3.1" - "@metamask/ramps-controller": "npm:^17.0.0" + "@metamask/ramps-controller": "patch:@metamask/ramps-controller@npm%3A17.0.0#~/.yarn/patches/@metamask-ramps-controller-npm-17.0.0-f649ad5caf.patch" "@metamask/react-data-query": "npm:^0.2.0" "@metamask/react-native-acm": "patch:@metamask/react-native-acm@npm%3A1.2.0#~/.yarn/patches/@metamask-react-native-acm-npm-1.2.0-944bf863eb.patch" "@metamask/react-native-actionsheet": "npm:2.4.2"