From d63fcbaa27334ab3fad18386922cc32d05887b4d Mon Sep 17 00:00:00 2001 From: Alex Mendonca Date: Tue, 28 Jul 2026 14:06:42 +0100 Subject: [PATCH 1/3] feat(ramps-controller): export terminal order status helpers Share TERMINAL_ORDER_STATUSES and isTerminalOrderStatus() so mobile and other consumers stop duplicating the terminal status set (TRAM-3703). Co-authored-by: Cursor --- packages/ramps-controller/CHANGELOG.md | 4 ++ .../ramps-controller/src/RampsController.ts | 18 ++------ packages/ramps-controller/src/index.ts | 4 ++ .../ramps-controller/src/orderStatus.test.ts | 43 +++++++++++++++++++ packages/ramps-controller/src/orderStatus.ts | 32 ++++++++++++++ 5 files changed, 87 insertions(+), 14 deletions(-) create mode 100644 packages/ramps-controller/src/orderStatus.test.ts create mode 100644 packages/ramps-controller/src/orderStatus.ts diff --git a/packages/ramps-controller/CHANGELOG.md b/packages/ramps-controller/CHANGELOG.md index 7ac40b86c98..acff4333e83 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. + ## [17.1.0] ### Added diff --git a/packages/ramps-controller/src/RampsController.ts b/packages/ramps-controller/src/RampsController.ts index db1f47da68e..687158701da 100644 --- a/packages/ramps-controller/src/RampsController.ts +++ b/packages/ramps-controller/src/RampsController.ts @@ -11,6 +11,10 @@ import type { Json } from '@metamask/utils'; import type { Draft } from 'immer'; import { isHeadlessAllProvidersEnabled } from './featureFlags.js'; +import { + PENDING_ORDER_STATUSES, + TERMINAL_ORDER_STATUSES, +} from './orderStatus.js'; import { getProvidersServingAsset } from './providerAvailability.js'; import type { RampsControllerMethodActions } from './RampsController-method-action-types.js'; import type { RampsErrorCode } from './rampsErrorCodes.js'; @@ -781,20 +785,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 efed83468ad..79512b89bae 100644 --- a/packages/ramps-controller/src/index.ts +++ b/packages/ramps-controller/src/index.ts @@ -156,6 +156,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 00000000000..021bea37a20 --- /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 00000000000..aacd1fc42af --- /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, +]); From cd457b6697dee8624f24bbac9489859cfb620d83 Mon Sep 17 00:00:00 2001 From: Alex Mendonca Date: Tue, 28 Jul 2026 14:12:43 +0100 Subject: [PATCH 2/3] fix(ramps-controller): remove duplicate Unreleased changelog header Merge resolution left two [Unreleased] sections, which failed changelog validation in CI. Co-authored-by: Cursor --- packages/ramps-controller/CHANGELOG.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/ramps-controller/CHANGELOG.md b/packages/ramps-controller/CHANGELOG.md index ea08cf04d02..26172880513 100644 --- a/packages/ramps-controller/CHANGELOG.md +++ b/packages/ramps-controller/CHANGELOG.md @@ -7,8 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [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. From ff22b464a58ec7408d915a69b81b8121eccc0c93 Mon Sep 17 00:00:00 2001 From: Alex Mendonca Date: Tue, 28 Jul 2026 14:15:55 +0100 Subject: [PATCH 3/3] fix(ramps-controller): link changelog entry to PR 9679 Required by the changelog check workflow for user-facing changes. Co-authored-by: Cursor --- packages/ramps-controller/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ramps-controller/CHANGELOG.md b/packages/ramps-controller/CHANGELOG.md index 26172880513..f99f00bb722 100644 --- a/packages/ramps-controller/CHANGELOG.md +++ b/packages/ramps-controller/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- Export `TERMINAL_ORDER_STATUSES` and `isTerminalOrderStatus()` so consuming clients can share the controller's terminal order status set instead of maintaining duplicate copies. +- 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)) ## [18.0.0]