diff --git a/packages/ramps-controller/CHANGELOG.md b/packages/ramps-controller/CHANGELOG.md index c2017d48dc..c3573e3e5c 100644 --- a/packages/ramps-controller/CHANGELOG.md +++ b/packages/ramps-controller/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Export `TERMINAL_ORDER_STATUSES` and `isTerminalOrderStatus()` so consuming clients can share the controller's terminal order status set instead of maintaining duplicate copies. ([#9679](https://github.com/MetaMask/core/pull/9679)) + ## [20.0.0] ### Changed diff --git a/packages/ramps-controller/src/RampsController.ts b/packages/ramps-controller/src/RampsController.ts index 3f88e46e0c..aac160d882 100644 --- a/packages/ramps-controller/src/RampsController.ts +++ b/packages/ramps-controller/src/RampsController.ts @@ -15,6 +15,10 @@ import { isHeadlessAllProvidersEnabled, normalizeHeadlessProviderId, } from './featureFlags.js'; +import { + PENDING_ORDER_STATUSES, + TERMINAL_ORDER_STATUSES, +} from './orderStatus.js'; import { getProvidersServingAsset, providerServesAsset, @@ -780,20 +784,6 @@ export function getInternalOrderCode( // === ORDER POLLING CONSTANTS === -const TERMINAL_ORDER_STATUSES = new Set([ - RampsOrderStatus.Completed, - RampsOrderStatus.Failed, - RampsOrderStatus.Cancelled, - RampsOrderStatus.IdExpired, -]); - -const PENDING_ORDER_STATUSES = new Set([ - RampsOrderStatus.Pending, - RampsOrderStatus.Created, - RampsOrderStatus.Unknown, - RampsOrderStatus.Precreated, -]); - const DEFAULT_POLLING_INTERVAL_MS = 30_000; const MAX_ERROR_COUNT = 5; diff --git a/packages/ramps-controller/src/index.ts b/packages/ramps-controller/src/index.ts index b4633ad5b4..f1d1dcdbe6 100644 --- a/packages/ramps-controller/src/index.ts +++ b/packages/ramps-controller/src/index.ts @@ -161,6 +161,10 @@ export { isCustomActionQuote, isInAppOnlyQuote, } from './quoteClassification.js'; +export { + TERMINAL_ORDER_STATUSES, + isTerminalOrderStatus, +} from './orderStatus.js'; export type { TypedError } from './errorNormalization.js'; export { getErrorMessage, diff --git a/packages/ramps-controller/src/orderStatus.test.ts b/packages/ramps-controller/src/orderStatus.test.ts new file mode 100644 index 0000000000..021bea37a2 --- /dev/null +++ b/packages/ramps-controller/src/orderStatus.test.ts @@ -0,0 +1,43 @@ +import { + TERMINAL_ORDER_STATUSES, + isTerminalOrderStatus, +} from './orderStatus.js'; +import { RampsOrderStatus } from './RampsService.js'; + +describe('TERMINAL_ORDER_STATUSES', () => { + it('includes completed, failed, cancelled, and id expired', () => { + expect(TERMINAL_ORDER_STATUSES.has(RampsOrderStatus.Completed)).toBe(true); + expect(TERMINAL_ORDER_STATUSES.has(RampsOrderStatus.Failed)).toBe(true); + expect(TERMINAL_ORDER_STATUSES.has(RampsOrderStatus.Cancelled)).toBe(true); + expect(TERMINAL_ORDER_STATUSES.has(RampsOrderStatus.IdExpired)).toBe(true); + }); + + it('excludes non-terminal statuses', () => { + expect(TERMINAL_ORDER_STATUSES.has(RampsOrderStatus.Unknown)).toBe(false); + expect(TERMINAL_ORDER_STATUSES.has(RampsOrderStatus.Precreated)).toBe( + false, + ); + expect(TERMINAL_ORDER_STATUSES.has(RampsOrderStatus.Created)).toBe(false); + expect(TERMINAL_ORDER_STATUSES.has(RampsOrderStatus.Pending)).toBe(false); + }); +}); + +describe('isTerminalOrderStatus', () => { + it.each([ + RampsOrderStatus.Completed, + RampsOrderStatus.Failed, + RampsOrderStatus.Cancelled, + RampsOrderStatus.IdExpired, + ])('returns true for terminal status %s', (status) => { + expect(isTerminalOrderStatus(status)).toBe(true); + }); + + it.each([ + RampsOrderStatus.Unknown, + RampsOrderStatus.Precreated, + RampsOrderStatus.Created, + RampsOrderStatus.Pending, + ])('returns false for non-terminal status %s', (status) => { + expect(isTerminalOrderStatus(status)).toBe(false); + }); +}); diff --git a/packages/ramps-controller/src/orderStatus.ts b/packages/ramps-controller/src/orderStatus.ts new file mode 100644 index 0000000000..aacd1fc42a --- /dev/null +++ b/packages/ramps-controller/src/orderStatus.ts @@ -0,0 +1,32 @@ +import { RampsOrderStatus } from './RampsService.js'; + +/** + * Order statuses that no longer require polling or in-flow navigation. + * Shared by the controller and consuming clients so terminal checks stay in sync. + */ +export const TERMINAL_ORDER_STATUSES: ReadonlySet = new Set([ + RampsOrderStatus.Completed, + RampsOrderStatus.Failed, + RampsOrderStatus.Cancelled, + RampsOrderStatus.IdExpired, +]); + +/** + * Whether a ramps order has reached a terminal status. + * + * @param status - The order status to test. + * @returns Whether the status is terminal. + */ +export function isTerminalOrderStatus(status: RampsOrderStatus): boolean { + return TERMINAL_ORDER_STATUSES.has(status); +} + +/** + * Order statuses that are still in progress and may be polled. + */ +export const PENDING_ORDER_STATUSES: ReadonlySet = new Set([ + RampsOrderStatus.Pending, + RampsOrderStatus.Created, + RampsOrderStatus.Unknown, + RampsOrderStatus.Precreated, +]);