diff --git a/packages/perps-controller/CHANGELOG.md b/packages/perps-controller/CHANGELOG.md index aa75828e2e..2e7dbf0a5a 100644 --- a/packages/perps-controller/CHANGELOG.md +++ b/packages/perps-controller/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- **BREAKING:** Add `positionsSideFilter`, `positionsSortField`, and `positionsSortDirection` to the flat `ProLayoutPreferences` object (defaults `'all'`, `'positionValue'`, `'desc'`) so Pro Positions/Orders panel sort and side-filter preferences persist across markets and app restarts via the existing `getProLayoutPreferences()` / `setProLayoutPreferences(patch)` API; export `ProPositionsSideFilter`, `ProPositionsSortField`, and `ProPositionsSortDirection` ([#9838](https://github.com/MetaMask/core/pull/9838)) + - Consumers that construct a full `ProLayoutPreferences` object (instead of using `DEFAULT_PRO_LAYOUT_PREFERENCES`, the getter, or the patch setter) must include the new fields. Persisted state that predates them remains valid at runtime because the getter/selector merge over defaults. - **BREAKING:** Add strategy placement order types to `OrderType`: `twap`, `scale`, and `chase`, placeable through `placeOrder` alongside the existing `market`, `limit`, and trigger types ([#9832](https://github.com/MetaMask/core/pull/9832)) - `OrderType` is a wider union again, so — exactly as for the trigger types added in 11.0.0 — any consumer signature that narrows it back to a smaller set no longer accepts a value typed `OrderType`. Such signatures must widen to `OrderType` or narrow explicitly at the call site. - A strategy placement expands one request into an execution schedule rather than a single resting order, so `OrderResult.orderId` carries a _handle_ — a venue TWAP id, or a client-generated group/session id — rather than an exchange order id. Its documentation says so; the individual exchange ids are in `childOrderIds`. diff --git a/packages/perps-controller/src/PerpsController.ts b/packages/perps-controller/src/PerpsController.ts index aa3492a67b..243d6d921e 100644 --- a/packages/perps-controller/src/PerpsController.ts +++ b/packages/perps-controller/src/PerpsController.ts @@ -250,7 +250,12 @@ export { DEFAULT_PERPS_MODE, DEFAULT_PRO_LAYOUT_PREFERENCES, } from './constants/perpsConfig.js'; -export type { ProLayoutPreferences } from './constants/perpsConfig.js'; +export type { + ProLayoutPreferences, + ProPositionsSideFilter, + ProPositionsSortDirection, + ProPositionsSortField, +} from './constants/perpsConfig.js'; /** * State shape for PerpsController diff --git a/packages/perps-controller/src/constants/perpsConfig.ts b/packages/perps-controller/src/constants/perpsConfig.ts index 1b2f713139..8ea127d834 100644 --- a/packages/perps-controller/src/constants/perpsConfig.ts +++ b/packages/perps-controller/src/constants/perpsConfig.ts @@ -486,19 +486,44 @@ export enum PerpsMode { Pro = 'pro', } +/** + * Side filter for the Pro Positions/Orders panel (long/short/all). + * + * Shared across markets via `proLayoutPreferences.positionsSideFilter`. + */ +export type ProPositionsSideFilter = 'all' | 'long' | 'short'; + +/** + * Sort fields available on the Pro Positions list. + */ +export type ProPositionsSortField = + | 'positionValue' + | 'unrealizedPnl' + | 'fundingRate'; + +/** + * Sort direction for the Pro Positions list. + */ +export type ProPositionsSortDirection = 'asc' | 'desc'; + /** * Pro-mode layout preferences (network-independent). * * Flat object that persists across markets (unlike the per-market * `tradeConfigurations`). `chartExpanded` and the `*Position` fields are - * reserved for future container-position UI and are kept here now so no - * state-shape migration is needed when that UI ships. + * reserved for future container-position UI. `positionsSideFilter` / + * `positionsSortField` / `positionsSortDirection` back the Positions/Orders + * panel sort and side filter so they survive market navigation and app + * restarts. */ export type ProLayoutPreferences = { orderBookExpanded: boolean; chartExpanded: boolean; orderBookPosition: 'left' | 'right'; orderFormPosition: 'left' | 'right'; + positionsSideFilter: ProPositionsSideFilter; + positionsSortField: ProPositionsSortField; + positionsSortDirection: ProPositionsSortDirection; }; /** @@ -513,6 +538,9 @@ export const DEFAULT_PRO_LAYOUT_PREFERENCES: ProLayoutPreferences = { chartExpanded: false, orderBookPosition: 'left', orderFormPosition: 'right', + positionsSideFilter: 'all', + positionsSortField: 'positionValue', + positionsSortDirection: 'desc', }; /** diff --git a/packages/perps-controller/src/index.ts b/packages/perps-controller/src/index.ts index 4e1b7bf80e..d19405776e 100644 --- a/packages/perps-controller/src/index.ts +++ b/packages/perps-controller/src/index.ts @@ -44,6 +44,9 @@ export type { PerpsControllerActions, PerpsControllerEvents, ProLayoutPreferences, + ProPositionsSideFilter, + ProPositionsSortDirection, + ProPositionsSortField, } from './PerpsController.js'; export type { PerpsControllerCalculateFeesAction, diff --git a/packages/perps-controller/tests/src/PerpsController.configuration.test.ts b/packages/perps-controller/tests/src/PerpsController.configuration.test.ts index ecdfd09ad7..d5de543eb8 100644 --- a/packages/perps-controller/tests/src/PerpsController.configuration.test.ts +++ b/packages/perps-controller/tests/src/PerpsController.configuration.test.ts @@ -694,12 +694,15 @@ describe('PerpsController', () => { }); describe('pro layout preferences', () => { - it('defaults to collapsed order book, collapsed chart, and reserved positions', () => { + it('defaults to collapsed order book, collapsed chart, reserved positions, and positions sort/filter defaults', () => { expect(controller.getProLayoutPreferences()).toEqual({ orderBookExpanded: false, chartExpanded: false, orderBookPosition: 'left', orderFormPosition: 'right', + positionsSideFilter: 'all', + positionsSortField: 'positionValue', + positionsSortDirection: 'desc', }); }); @@ -711,6 +714,9 @@ describe('PerpsController', () => { chartExpanded: false, orderBookPosition: 'left', orderFormPosition: 'right', + positionsSideFilter: 'all', + positionsSortField: 'positionValue', + positionsSortDirection: 'desc', }); }); @@ -718,12 +724,40 @@ describe('PerpsController', () => { controller.setProLayoutPreferences({ orderBookExpanded: true }); controller.setProLayoutPreferences({ orderBookPosition: 'right' }); controller.setProLayoutPreferences({ orderFormPosition: 'left' }); + controller.setProLayoutPreferences({ positionsSideFilter: 'long' }); + controller.setProLayoutPreferences({ + positionsSortField: 'unrealizedPnl', + positionsSortDirection: 'asc', + }); expect(controller.getProLayoutPreferences()).toEqual({ orderBookExpanded: true, chartExpanded: false, orderBookPosition: 'right', orderFormPosition: 'left', + positionsSideFilter: 'long', + positionsSortField: 'unrealizedPnl', + positionsSortDirection: 'asc', + }); + }); + + it('updates sort field without clobbering sort direction', () => { + controller.setProLayoutPreferences({ + positionsSortField: 'fundingRate', + positionsSortDirection: 'asc', + }); + controller.setProLayoutPreferences({ + positionsSortField: 'unrealizedPnl', + }); + + expect(controller.getProLayoutPreferences()).toEqual({ + orderBookExpanded: false, + chartExpanded: false, + orderBookPosition: 'left', + orderFormPosition: 'right', + positionsSideFilter: 'all', + positionsSortField: 'unrealizedPnl', + positionsSortDirection: 'asc', }); }); @@ -746,6 +780,9 @@ describe('PerpsController', () => { chartExpanded: false, orderBookPosition: 'left', orderFormPosition: 'right', + positionsSideFilter: 'all', + positionsSortField: 'positionValue', + positionsSortDirection: 'desc', }); }); }); diff --git a/packages/perps-controller/tests/src/selectors.test.ts b/packages/perps-controller/tests/src/selectors.test.ts index 220fede9c5..01983cd655 100644 --- a/packages/perps-controller/tests/src/selectors.test.ts +++ b/packages/perps-controller/tests/src/selectors.test.ts @@ -636,6 +636,9 @@ describe('PerpsController selectors', () => { chartExpanded: false, orderBookPosition: 'left', orderFormPosition: 'right', + positionsSideFilter: 'all', + positionsSortField: 'positionValue', + positionsSortDirection: 'desc', }; it('returns the pro-mode layout preferences', () => { @@ -644,6 +647,9 @@ describe('PerpsController selectors', () => { chartExpanded: true, orderBookPosition: 'right' as const, orderFormPosition: 'left' as const, + positionsSideFilter: 'long' as const, + positionsSortField: 'unrealizedPnl' as const, + positionsSortDirection: 'asc' as const, }; const state = { proLayoutPreferences,