@0xmonaco/types 1.0.65 → 1.0.67

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.
@@ -191,6 +191,8 @@ export interface ScreenerSnapshotPoint {
191
191
  quoteVolume: string;
192
192
  /** Percent price change (close - open) / open * 100 for the day */
193
193
  priceChangePercent: string;
194
+ /** Daily average of the valued completed-UTC-minute open interest notionals; null for spot or when fewer than 95% of the day's 1440 minutes (1368) are valued */
195
+ openInterestNotionalAvg: string | null;
194
196
  }
195
197
  /**
196
198
  * Per-pair screener row. Window fields are null when there is insufficient history.
@@ -251,6 +253,12 @@ export interface ScreenerItem {
251
253
  * getOpenInterest
252
254
  */
253
255
  openInterestNotional: string | null;
256
+ /** Average of the valued completed-UTC-minute gross open-interest notionals over the last 60 minutes; null for spot or when fewer than 95% of them (57) are valued */
257
+ openInterestNotionalAvg1h: string | null;
258
+ /** Average of the valued completed-UTC-minute gross open-interest notionals over the last 1440 minutes; null for spot or when fewer than 95% of them (1368) are valued */
259
+ openInterestNotionalAvg24h: string | null;
260
+ /** Average of the valued completed-UTC-minute gross open-interest notionals over the last 10080 minutes; null for spot or when fewer than 95% of them (9576) are valued */
261
+ openInterestNotionalAvg7d: string | null;
254
262
  }
255
263
  /**
256
264
  * Paginated screener response, sorted by quoteVolume24h desc (nulls last)
@@ -32,16 +32,13 @@ export interface Position {
32
32
  unrealizedPnl: string;
33
33
  realizedPnl: string;
34
34
  /**
35
- * Open ISOLATED rows: the position's current backing — its risk bucket's
36
- * allocated collateral adjusted by settled realized PnL and funding paid,
37
- * net of collateral reserved for the bucket's open orders, clamped at zero
38
- * (0XM-2558). Partial closes shrink the posted margin pro-rata while the
39
- * realized loss stays in the bucket, so this is the unrealized-return
40
- * denominator. Not a hard -100% bound: liquidation measures the bucket's
41
- * whole equity, order reserves included, and a mark can gap past the
42
- * backing. Open CROSS rows: the position's posted margin. Terminal rows:
43
- * total initial margin allocated across the position's reducing executions
44
- * when available — the margin basis for lifetime realized return.
35
+ * Open ISOLATED rows: principal committed to the filled position, adjusted
36
+ * by settled realized PnL, fees and funding, clamped at zero. Unfilled-order
37
+ * collateral is excluded. This is the unrealized-return denominator and
38
+ * the same backing used by isolated liquidation, on live and persisted reads.
39
+ * A price gap can pass the backing before asynchronous liquidation occurs.
40
+ * Open CROSS rows: posted margin. Terminal rows: total initial margin
41
+ * allocated across reducing executions, the lifetime-return denominator.
45
42
  */
46
43
  isolatedMargin: string;
47
44
  leverage?: string;
@@ -249,16 +246,56 @@ export interface TpSlLeg {
249
246
  slippageToleranceBps?: number;
250
247
  expiresAt?: string;
251
248
  }
249
+ /**
250
+ * A trailing stop attached to an open position (0XM-2827).
251
+ *
252
+ * A reduce-only MARKET close whose trigger trails the best mark price reached
253
+ * since it armed (the watermark) by `trailBps`: for a long, trigger =
254
+ * watermark × (1 − trailBps/10000) and it fires when the mark falls to or below
255
+ * it; a short mirrors it. The trigger only ever moves in the position's
256
+ * favour. One trailing stop per position — a second attach is rejected with
257
+ * HTTP 409. It coexists with `takeProfit` / `stopLoss` and never joins `oco`.
258
+ * There is no modify: cancel and recreate. Fires through the standard
259
+ * conditional market close (1,200 bps protective band, optional slippage cap).
260
+ */
261
+ export interface TrailingStopLeg {
262
+ /** Retracement behind the watermark in basis points; integer, 10 to 2000 inclusive */
263
+ trailBps: number;
264
+ /**
265
+ * Mark level at which tracking starts, seeding the watermark there. Omitted,
266
+ * tracking starts at the current mark. Rejected if the mark has already
267
+ * reached it. The row stays `ACTIVE` while waiting and `trailArmedAt` is set
268
+ * once it arms.
269
+ */
270
+ activationPrice?: string;
271
+ /**
272
+ * Deliberate partial size that never resizes. Mutually exclusive with
273
+ * `closePosition: true`; required when `closePosition: false`.
274
+ */
275
+ quantity?: string;
276
+ /**
277
+ * Resolve the full live position size when triggered. Mutually exclusive
278
+ * with `quantity`. Omitting both also means full-position close.
279
+ */
280
+ closePosition?: boolean;
281
+ /** Slippage cap for the triggered MARKET close, 0 to 10000 basis points */
282
+ slippageToleranceBps?: number;
283
+ /** Optional conditional order expiry timestamp (ISO 8601) */
284
+ expiresAt?: string;
285
+ }
252
286
  export interface AttachPositionTpSlRequest {
253
287
  takeProfit?: TpSlLeg;
254
288
  stopLoss?: TpSlLeg;
255
- /** Cancel the sibling after one leg triggers. Requires both legs. */
289
+ /** Trailing stop; may be the only leg. Never part of `oco`. */
290
+ trailingStop?: TrailingStopLeg;
291
+ /** Cancel the sibling after one leg triggers. Requires both fixed legs. */
256
292
  oco?: boolean;
257
293
  }
258
294
  export interface AttachPositionTpSlResponse {
259
295
  positionId: string;
260
296
  takeProfitOrderId?: string;
261
297
  stopLossOrderId?: string;
298
+ trailingStopOrderId?: string;
262
299
  status: "SUCCESS" | "FAILED";
263
300
  message: string;
264
301
  }
@@ -6,7 +6,7 @@
6
6
  import type { BaseAPI } from "../api/index";
7
7
  import type { MarginMode } from "../margin-accounts";
8
8
  import type { Order, OrderSide, PositionSide, SelfTradePreventionMode, TimeInForce, TradingMode } from "./orders";
9
- import type { BatchCancelOrdersResponse, BatchCreateOrderParams, BatchCreateOrdersResponse, BatchReplaceOrderParams, BatchReplaceOrdersResponse, CancelConditionalOrderResponse, CancelOrderResponse, CancelTwapOrderResponse, ConditionalOrder, CreateOrderResponse, CreateTwapOrderOptions, CreateTwapOrderResponse, GetOrderResponse, GetPaginatedOrdersParams, GetPaginatedOrdersResponse, GetTwapOrderTcaResponse, ListConditionalOrdersParams, ListConditionalOrdersResponse, ListTwapOrdersParams, ListTwapOrdersResponse, ParentTpSlLegParams, ReplaceOrderResponse, TwapOrder } from "./responses";
9
+ import type { BatchCancelOrdersResponse, BatchCreateOrderParams, BatchCreateOrdersResponse, BatchReplaceOrderParams, BatchReplaceOrdersResponse, CancelConditionalOrderResponse, CancelOrderResponse, CancelTwapOrderResponse, ConditionalOrder, CreateOrderResponse, CreateTwapOrderOptions, CreateTwapOrderResponse, GetOrderResponse, GetPaginatedOrdersParams, GetPaginatedOrdersResponse, GetTwapOrderTcaResponse, ListConditionalOrdersParams, ListConditionalOrdersResponse, ListTwapOrdersParams, ListTwapOrdersResponse, ParentTpSlLegParams, ParentTrailingStopLegParams, ReplaceOrderResponse, TwapOrder } from "./responses";
10
10
  /**
11
11
  * Trading API interface.
12
12
  * Provides methods for placing and managing orders.
@@ -32,6 +32,7 @@ export interface TradingAPI extends BaseAPI {
32
32
  marginAccountId?: string;
33
33
  marginMode?: MarginMode;
34
34
  riskBucketId?: string;
35
+ /** Initial order budget; unfilled funds do not back the isolated position. */
35
36
  riskBucketCollateral?: string;
36
37
  strategyKey?: string;
37
38
  /** @deprecated Order side is authoritative. */
@@ -66,6 +67,8 @@ export interface TradingAPI extends BaseAPI {
66
67
  idempotencyKey?: string;
67
68
  takeProfit?: ParentTpSlLegParams;
68
69
  stopLoss?: ParentTpSlLegParams;
70
+ /** Trailing stop that arms when this order fully fills; margin entry orders only. */
71
+ trailingStop?: ParentTrailingStopLegParams;
69
72
  }): Promise<CreateOrderResponse>;
70
73
  /**
71
74
  * Places a market order for immediate execution.
@@ -83,6 +86,7 @@ export interface TradingAPI extends BaseAPI {
83
86
  marginAccountId?: string;
84
87
  marginMode?: MarginMode;
85
88
  riskBucketId?: string;
89
+ /** Initial order budget; unfilled funds do not back the isolated position. */
86
90
  riskBucketCollateral?: string;
87
91
  strategyKey?: string;
88
92
  /** @deprecated Order side is authoritative. */
@@ -110,6 +114,8 @@ export interface TradingAPI extends BaseAPI {
110
114
  idempotencyKey?: string;
111
115
  takeProfit?: ParentTpSlLegParams;
112
116
  stopLoss?: ParentTpSlLegParams;
117
+ /** Trailing stop that arms when this order fully fills; margin entry orders only. */
118
+ trailingStop?: ParentTrailingStopLegParams;
113
119
  }): Promise<CreateOrderResponse>;
114
120
  /**
115
121
  * Cancels an existing order.
@@ -263,4 +269,4 @@ export interface TradingAPI extends BaseAPI {
263
269
  }
264
270
  export type { ConditionalOrderConditionType, ConditionalOrderState, ConditionalOrderTriggerSource, ListedOrderType, Order, OrderRole, OrderSide, OrderStatus, OrderStatusFilter, OrderTerminalReason, OrderType, PositionSide, SelfTradePreventionMode, TimeInForce, TradingMode, TwapExecutionStyle, TwapOrderState, } from "./orders";
265
271
  export { ORDER_STATUS_VALUES } from "./orders";
266
- export type { BatchCancelError, BatchCancelOrdersResponse, BatchCancelResult, BatchCreateOrderParams, BatchCreateOrdersResponse, BatchCreateResult, BatchError, BatchReplaceOrderParams, BatchReplaceOrdersResponse, BatchReplaceResult, CancelConditionalOrderResponse, CancelOrderResponse, CancelTwapOrderResponse, ConditionalOrder, CreateOrderResponse, CreateTwapOrderOptions, CreateTwapOrderResponse, GetOrderResponse, GetPaginatedOrdersParams, GetPaginatedOrdersResponse, GetTwapOrderTcaResponse, ListConditionalOrdersParams, ListConditionalOrdersResponse, ListTwapOrdersParams, ListTwapOrdersResponse, MatchResult, ParentTpSlLegParams, ReplaceOrderResponse, TriggeredOrderSummary, TwapOrder, UpdatedFields, } from "./responses";
272
+ export type { BatchCancelError, BatchCancelOrdersResponse, BatchCancelResult, BatchCreateOrderParams, BatchCreateOrdersResponse, BatchCreateResult, BatchError, BatchReplaceOrderParams, BatchReplaceOrdersResponse, BatchReplaceResult, CancelConditionalOrderResponse, CancelOrderResponse, CancelTwapOrderResponse, ConditionalOrder, CreateOrderResponse, CreateTwapOrderOptions, CreateTwapOrderResponse, GetOrderResponse, GetPaginatedOrdersParams, GetPaginatedOrdersResponse, GetTwapOrderTcaResponse, ListConditionalOrdersParams, ListConditionalOrdersResponse, ListTwapOrdersParams, ListTwapOrdersResponse, MatchResult, ParentTpSlLegParams, ParentTrailingStopLegParams, ReplaceOrderResponse, TriggeredOrderSummary, TwapOrder, UpdatedFields, } from "./responses";
@@ -265,9 +265,11 @@ export type TimeInForce = "GTC" | "IOC" | "FOK" | "GTD";
265
265
  */
266
266
  export type SelfTradePreventionMode = "CANCEL_MAKER" | "CANCEL_TAKER" | "CANCEL_BOTH" | "SKIP";
267
267
  /**
268
- * Conditional TP/SL condition type.
268
+ * Conditional order condition type: a fixed stop-loss or take-profit, or a
269
+ * trailing stop whose trigger follows the best mark reached since it armed
270
+ * (0XM-2827).
269
271
  */
270
- export type ConditionalOrderConditionType = "STOP_LOSS" | "TAKE_PROFIT";
272
+ export type ConditionalOrderConditionType = "STOP_LOSS" | "TAKE_PROFIT" | "TRAILING_STOP";
271
273
  /**
272
274
  * Conditional order trigger source. v1 supports mark-price triggers.
273
275
  */
@@ -71,6 +71,42 @@ export interface ParentTpSlLegParams {
71
71
  */
72
72
  closePosition?: boolean;
73
73
  }
74
+ /**
75
+ * A trailing stop attached to a margin entry order at placement (0XM-2827).
76
+ *
77
+ * A reduce-only MARKET close whose trigger trails the best mark price reached
78
+ * since it armed (the watermark) by `trailBps`: for a long, trigger =
79
+ * watermark × (1 − trailBps/10000) and it fires when the mark falls to or below
80
+ * it; a short mirrors it. The trigger only ever moves in the position's
81
+ * favour. It arms only when the entry order FULLY fills and is cancelled with
82
+ * the order otherwise. One trailing stop per position — a second is rejected
83
+ * with HTTP 409. It coexists with `takeProfit` / `stopLoss` and never joins
84
+ * their OCO link. There is no modify: cancel and recreate.
85
+ */
86
+ export interface ParentTrailingStopLegParams {
87
+ /** Retracement behind the watermark in basis points; integer, 10 to 2000 inclusive */
88
+ trailBps: number;
89
+ /**
90
+ * Mark level at which tracking starts, seeding the watermark there. Omitted,
91
+ * tracking starts at the first mark after the fill. Rejected if the mark has
92
+ * already reached it.
93
+ */
94
+ activationPrice?: string;
95
+ /**
96
+ * Deliberate partial size that never resizes. Mutually exclusive with
97
+ * `closePosition: true`; required when `closePosition: false`.
98
+ */
99
+ quantity?: string;
100
+ /**
101
+ * Resolve the full live position size when triggered. Mutually exclusive
102
+ * with `quantity`. Omitting both also means full-position close.
103
+ */
104
+ closePosition?: boolean;
105
+ /** Slippage cap for the triggered MARKET close, 0 to 10000 basis points */
106
+ slippageToleranceBps?: number;
107
+ /** Optional conditional order expiry timestamp (ISO 8601) */
108
+ expiresAt?: string;
109
+ }
74
110
  /**
75
111
  * Response from creating an order.
76
112
  *
@@ -99,6 +135,8 @@ export interface CreateOrderResponse {
99
135
  takeProfitOrderId?: string;
100
136
  /** Conditional order ID for an attached stop-loss leg */
101
137
  stopLossOrderId?: string;
138
+ /** Conditional order ID for an attached trailing stop */
139
+ trailingStopOrderId?: string;
102
140
  }
103
141
  /**
104
142
  * Response from cancelling an order.
@@ -449,8 +487,31 @@ export interface ListConditionalOrdersParams {
449
487
  marginAccountId?: string;
450
488
  tradingPairId?: string;
451
489
  state?: ConditionalOrderState;
490
+ /**
491
+ * Page number for legacy offset pagination.
492
+ *
493
+ * @deprecated Use cursor pagination (`pageToken`) instead. Passing `page`
494
+ * selects legacy page-number mode; omitting both `page` and `pageToken`
495
+ * drives cursor mode.
496
+ */
452
497
  page?: number;
498
+ /** Items per page (max 100 in page-number mode, up to 1000 when `pageToken` is present) */
453
499
  pageSize?: number;
500
+ /**
501
+ * Pagination cursor with three distinct states:
502
+ * - Omitted (`undefined`): the SDK starts a cursor walk (it sends
503
+ * `pageToken=""`) unless the deprecated `page` param was passed, in which
504
+ * case the request uses legacy page-number pagination.
505
+ * - Empty string (`""`): start a cursor walk with no prior position, from
506
+ * the newest conditional order.
507
+ * - Non-empty: an opaque cursor from a previous response's `nextPageToken`;
508
+ * results resume immediately after that position.
509
+ *
510
+ * In either cursor-walk state, `page` and `total` come back as 0 — cursor
511
+ * mode runs no COUNT (AIP-158). Follow `nextPageToken` until it comes back
512
+ * empty. Filters must match the request that produced the token.
513
+ */
514
+ pageToken?: string;
454
515
  }
455
516
  /**
456
517
  * What the order a conditional fired into has done so far — a projection of
@@ -518,6 +579,29 @@ export interface ConditionalOrder {
518
579
  cancelledAt?: string;
519
580
  expiresAt?: string;
520
581
  failureReason?: string;
582
+ /**
583
+ * `TRAILING_STOP` only: retracement in basis points behind the watermark.
584
+ * Absent on TP/SL rows. Wire: `trailBps`.
585
+ */
586
+ trailBps?: number;
587
+ /**
588
+ * `TRAILING_STOP` only: the mark level that starts tracking. Absent when the
589
+ * stop armed immediately. Wire: `activationPrice`.
590
+ */
591
+ activationPrice?: string;
592
+ /**
593
+ * `TRAILING_STOP` only: best mark (highest for a long, lowest for a short)
594
+ * observed since arming. `triggerPrice` is derived from it and only ever
595
+ * moves in the position's favour. Absent until the first mark is observed
596
+ * after arming. Wire: `watermarkPrice`.
597
+ */
598
+ watermarkPrice?: string;
599
+ /**
600
+ * `TRAILING_STOP` only: when tracking began (ISO 8601). Absent while the
601
+ * stop is still waiting for `activationPrice` — `state` stays `ACTIVE` in
602
+ * both phases. Wire: `trailArmedAt`.
603
+ */
604
+ trailArmedAt?: string;
521
605
  createdAt: string;
522
606
  updatedAt: string;
523
607
  /**
@@ -557,14 +641,28 @@ export interface ConditionalOrder {
557
641
  export interface ListConditionalOrdersResponse {
558
642
  orders: ConditionalOrder[];
559
643
  /**
560
- * Matching conditional orders. Exact up to 10,000 pages of the requested
561
- * page size (`pageSize` x 10,000 rows) and saturates there, so a caller with
562
- * more matching conditional orders than the listing can page through reads
563
- * the cap, not its lifetime total. `page` is capped at 10,000.
644
+ * Matching conditional orders in page-number (offset) mode: exact up to
645
+ * 10,000 pages of the requested page size (`pageSize` x 10,000 rows) and
646
+ * saturates there, so a caller with more matching conditional orders than the
647
+ * listing can page through reads the cap, not its lifetime total. `0` in
648
+ * cursor (`pageToken`) mode, which runs no COUNT (AIP-158).
564
649
  */
565
650
  total: number;
651
+ /**
652
+ * Current page number in legacy offset mode; `0` in cursor mode.
653
+ *
654
+ * @deprecated Use cursor pagination (`pageToken`/`nextPageToken`) instead.
655
+ */
566
656
  page: number;
567
657
  pageSize: number;
658
+ /**
659
+ * Cursor for the next page, minted only while a further page exists (the read
660
+ * over-fetches one row to decide). Empty on every page-number response and on
661
+ * the final cursor page — an empty token is the definitive end of the walk,
662
+ * so no extra request is needed. Do not feed the empty token back as
663
+ * `pageToken`; an empty input restarts the walk from the newest row.
664
+ */
665
+ nextPageToken: string;
568
666
  }
569
667
  /**
570
668
  * Options for creating a server-side TWAP parent order.
@@ -820,10 +918,31 @@ export interface ListTwapOrdersParams {
820
918
  state?: TwapOrderState;
821
919
  /** Filter by trading pair UUID */
822
920
  tradingPairId?: string;
823
- /** Page number (1-indexed) */
921
+ /**
922
+ * Page number for legacy offset pagination.
923
+ *
924
+ * @deprecated Use cursor pagination (`pageToken`) instead. Passing `page`
925
+ * selects legacy page-number mode; omitting both `page` and `pageToken`
926
+ * drives cursor mode.
927
+ */
824
928
  page?: number;
825
- /** Items per page (max 100) */
929
+ /** Items per page (max 100 in page-number mode, up to 1000 when `pageToken` is present) */
826
930
  pageSize?: number;
931
+ /**
932
+ * Pagination cursor with three distinct states:
933
+ * - Omitted (`undefined`): the SDK starts a cursor walk (it sends
934
+ * `pageToken=""`) unless the deprecated `page` param was passed, in which
935
+ * case the request uses legacy page-number pagination.
936
+ * - Empty string (`""`): start a cursor walk with no prior position, from
937
+ * the newest TWAP parent.
938
+ * - Non-empty: an opaque cursor from a previous response's `nextPageToken`;
939
+ * results resume immediately after that position.
940
+ *
941
+ * In either cursor-walk state, `page` and `total` come back as 0 — cursor
942
+ * mode runs no COUNT (AIP-158). Follow `nextPageToken` until it comes back
943
+ * empty. Filters must match the request that produced the token.
944
+ */
945
+ pageToken?: string;
827
946
  }
828
947
  /**
829
948
  * Response from listing TWAP parent orders.
@@ -831,14 +950,27 @@ export interface ListTwapOrdersParams {
831
950
  export interface ListTwapOrdersResponse {
832
951
  orders: TwapOrder[];
833
952
  /**
834
- * Matching TWAP orders. Exact up to 10,000 pages of the requested page size
835
- * (`pageSize` x 10,000 rows) and saturates there, so a caller with more
836
- * matching TWAP orders than the listing can page through reads the cap, not
837
- * its lifetime total. `page` is capped at 10,000.
953
+ * Matching TWAP orders in page-number (offset) mode: exact up to 10,000 pages
954
+ * of the requested page size (`pageSize` x 10,000 rows) and saturates there,
955
+ * so a caller with more matching TWAP orders than the listing can page through
956
+ * reads the cap, not its lifetime total. `0` in cursor (`pageToken`) mode,
957
+ * which runs no COUNT (AIP-158).
838
958
  */
839
959
  total: number;
840
- /** Current page number */
960
+ /**
961
+ * Current page number in legacy offset mode; `0` in cursor mode.
962
+ *
963
+ * @deprecated Use cursor pagination (`pageToken`/`nextPageToken`) instead.
964
+ */
841
965
  page: number;
842
966
  /** Items per page */
843
967
  pageSize: number;
968
+ /**
969
+ * Cursor for the next page, minted only while a further page exists (the read
970
+ * over-fetches one row to decide). Empty on every page-number response and on
971
+ * the final cursor page — an empty token is the definitive end of the walk,
972
+ * so no extra request is needed. Do not feed the empty token back as
973
+ * `pageToken`; an empty input restarts the walk from the newest row.
974
+ */
975
+ nextPageToken: string;
844
976
  }
@@ -72,6 +72,14 @@ export declare const AttachPositionTpSlSchema: z.ZodObject<{
72
72
  slippageToleranceBps: z.ZodOptional<z.ZodNumber>;
73
73
  expiresAt: z.ZodOptional<z.ZodISODateTime>;
74
74
  }, z.core.$strip>>;
75
+ trailingStop: z.ZodOptional<z.ZodObject<{
76
+ trailBps: z.ZodNumber;
77
+ activationPrice: z.ZodOptional<z.ZodString>;
78
+ quantity: z.ZodOptional<z.ZodString>;
79
+ closePosition: z.ZodOptional<z.ZodBoolean>;
80
+ slippageToleranceBps: z.ZodOptional<z.ZodNumber>;
81
+ expiresAt: z.ZodOptional<z.ZodISODateTime>;
82
+ }, z.core.$strip>>;
75
83
  oco: z.ZodOptional<z.ZodBoolean>;
76
84
  }, z.core.$strip>;
77
85
  }, z.core.$strip>;
@@ -2,7 +2,7 @@
2
2
  * Positions API Validation Schemas
3
3
  */
4
4
  import { z } from "zod";
5
- import { ConditionalTimeInForceSchema, ISO8601DateSchema, OrderTypeSchema, PositiveDecimalStringSchema, SlippageToleranceBpsSchema, UUIDSchema, } from "./trading";
5
+ import { ConditionalTimeInForceSchema, ISO8601DateSchema, OrderTypeSchema, PositiveDecimalStringSchema, SlippageToleranceBpsSchema, TrailingStopLegSchema, UUIDSchema, } from "./trading";
6
6
  const PaginationSchema = z.object({
7
7
  page: z.number().int().min(1, "Page must be at least 1").optional(),
8
8
  pageSize: z.number().int().min(1, "Page size must be at least 1").max(100, "Page size cannot exceed 100").optional(),
@@ -88,11 +88,13 @@ export const AttachPositionTpSlSchema = PositionIdSchema.extend({
88
88
  .object({
89
89
  takeProfit: TpSlLegSchema.optional(),
90
90
  stopLoss: TpSlLegSchema.optional(),
91
+ trailingStop: TrailingStopLegSchema.optional(),
91
92
  oco: z.boolean().optional(),
92
93
  })
93
- .refine((data) => data.takeProfit !== undefined || data.stopLoss !== undefined, {
94
- message: "At least one of takeProfit or stopLoss is required",
94
+ .refine((data) => data.takeProfit !== undefined || data.stopLoss !== undefined || data.trailingStop !== undefined, {
95
+ message: "At least one of takeProfit, stopLoss, or trailingStop is required",
95
96
  })
97
+ // A trailing stop never takes part in OCO: the pair is the two fixed legs.
96
98
  .refine((data) => data.oco !== true || (data.takeProfit !== undefined && data.stopLoss !== undefined), {
97
99
  message: "oco=true requires both takeProfit and stopLoss",
98
100
  path: ["oco"],
@@ -101,6 +101,31 @@ export declare const ParentTpSlLegSchema: z.ZodObject<{
101
101
  slippageToleranceBps: z.ZodOptional<z.ZodNumber>;
102
102
  expiresAt: z.ZodOptional<z.ZodISODateTime>;
103
103
  }, z.core.$strip>;
104
+ /** Trailing-stop retracement: an integer from 10 to 2000 basis points (0XM-2827). */
105
+ export declare const TrailBpsSchema: z.ZodNumber;
106
+ /**
107
+ * The trailing-stop leg, shared by the position-attached rail and the
108
+ * entry-order rail: the shape is identical on both. The close is always a
109
+ * reduce-only MARKET order, so there is no order type, limit price or time in
110
+ * force to check — only the ratchet distance, the optional activation level,
111
+ * the same sizing contract a TP/SL leg carries, and the slippage cap.
112
+ */
113
+ export declare const TrailingStopLegSchema: z.ZodObject<{
114
+ trailBps: z.ZodNumber;
115
+ activationPrice: z.ZodOptional<z.ZodString>;
116
+ quantity: z.ZodOptional<z.ZodString>;
117
+ closePosition: z.ZodOptional<z.ZodBoolean>;
118
+ slippageToleranceBps: z.ZodOptional<z.ZodNumber>;
119
+ expiresAt: z.ZodOptional<z.ZodISODateTime>;
120
+ }, z.core.$strip>;
121
+ export declare const ParentTrailingStopLegSchema: z.ZodObject<{
122
+ trailBps: z.ZodNumber;
123
+ activationPrice: z.ZodOptional<z.ZodString>;
124
+ quantity: z.ZodOptional<z.ZodString>;
125
+ closePosition: z.ZodOptional<z.ZodBoolean>;
126
+ slippageToleranceBps: z.ZodOptional<z.ZodNumber>;
127
+ expiresAt: z.ZodOptional<z.ZodISODateTime>;
128
+ }, z.core.$strip>;
104
129
  /**
105
130
  * Place Limit Order validation schema
106
131
  */
@@ -180,6 +205,14 @@ export declare const PlaceLimitOrderSchema: z.ZodObject<{
180
205
  slippageToleranceBps: z.ZodOptional<z.ZodNumber>;
181
206
  expiresAt: z.ZodOptional<z.ZodISODateTime>;
182
207
  }, z.core.$strip>>;
208
+ trailingStop: z.ZodOptional<z.ZodObject<{
209
+ trailBps: z.ZodNumber;
210
+ activationPrice: z.ZodOptional<z.ZodString>;
211
+ quantity: z.ZodOptional<z.ZodString>;
212
+ closePosition: z.ZodOptional<z.ZodBoolean>;
213
+ slippageToleranceBps: z.ZodOptional<z.ZodNumber>;
214
+ expiresAt: z.ZodOptional<z.ZodISODateTime>;
215
+ }, z.core.$strip>>;
183
216
  }, z.core.$strip>>;
184
217
  }, z.core.$strip>;
185
218
  /**
@@ -252,6 +285,14 @@ export declare const PlaceMarketOrderSchema: z.ZodObject<{
252
285
  slippageToleranceBps: z.ZodOptional<z.ZodNumber>;
253
286
  expiresAt: z.ZodOptional<z.ZodISODateTime>;
254
287
  }, z.core.$strip>>;
288
+ trailingStop: z.ZodOptional<z.ZodObject<{
289
+ trailBps: z.ZodNumber;
290
+ activationPrice: z.ZodOptional<z.ZodString>;
291
+ quantity: z.ZodOptional<z.ZodString>;
292
+ closePosition: z.ZodOptional<z.ZodBoolean>;
293
+ slippageToleranceBps: z.ZodOptional<z.ZodNumber>;
294
+ expiresAt: z.ZodOptional<z.ZodISODateTime>;
295
+ }, z.core.$strip>>;
255
296
  }, z.core.$strip>>;
256
297
  }, z.core.$strip>;
257
298
  /**
@@ -327,6 +368,7 @@ export declare const GetPaginatedOrdersSchema: z.ZodObject<{
327
368
  export declare const ConditionalOrderConditionTypeSchema: z.ZodEnum<{
328
369
  STOP_LOSS: "STOP_LOSS";
329
370
  TAKE_PROFIT: "TAKE_PROFIT";
371
+ TRAILING_STOP: "TRAILING_STOP";
330
372
  }>;
331
373
  export declare const ConditionalOrderTriggerSourceSchema: z.ZodEnum<{
332
374
  MARK_PRICE: "MARK_PRICE";
@@ -361,6 +403,7 @@ export declare const ListConditionalOrdersSchema: z.ZodObject<{
361
403
  }>>;
362
404
  page: z.ZodOptional<z.ZodNumber>;
363
405
  pageSize: z.ZodOptional<z.ZodNumber>;
406
+ pageToken: z.ZodOptional<z.ZodString>;
364
407
  }, z.core.$strip>;
365
408
  export declare const TwapOrderStateSchema: z.ZodEnum<{
366
409
  CANCELLED: "CANCELLED";
@@ -422,6 +465,7 @@ export declare const ListTwapOrdersSchema: z.ZodObject<{
422
465
  tradingPairId: z.ZodOptional<z.ZodUUID>;
423
466
  page: z.ZodOptional<z.ZodNumber>;
424
467
  pageSize: z.ZodOptional<z.ZodNumber>;
468
+ pageToken: z.ZodOptional<z.ZodString>;
425
469
  }, z.core.$strip>;
426
470
  /**
427
471
  * Single batch create order item validation schema
@@ -138,7 +138,38 @@ export const ParentTpSlLegSchema = z
138
138
  message: "quantity is required when closePosition is false",
139
139
  path: ["closePosition"],
140
140
  });
141
- const hasParentTpSl = (options) => options?.takeProfit !== undefined || options?.stopLoss !== undefined;
141
+ /** Trailing-stop retracement: an integer from 10 to 2000 basis points (0XM-2827). */
142
+ export const TrailBpsSchema = z
143
+ .number()
144
+ .int("trailBps must be an integer number of basis points")
145
+ .min(10, "trailBps must be at least 10 bps")
146
+ .max(2000, "trailBps cannot exceed 2000 bps");
147
+ /**
148
+ * The trailing-stop leg, shared by the position-attached rail and the
149
+ * entry-order rail: the shape is identical on both. The close is always a
150
+ * reduce-only MARKET order, so there is no order type, limit price or time in
151
+ * force to check — only the ratchet distance, the optional activation level,
152
+ * the same sizing contract a TP/SL leg carries, and the slippage cap.
153
+ */
154
+ export const TrailingStopLegSchema = z
155
+ .object({
156
+ trailBps: TrailBpsSchema,
157
+ activationPrice: PositiveDecimalStringSchema.optional(),
158
+ quantity: PositiveDecimalStringSchema.optional(),
159
+ closePosition: z.boolean().optional(),
160
+ slippageToleranceBps: SlippageToleranceBpsSchema.optional(),
161
+ expiresAt: ISO8601DateSchema.optional(),
162
+ })
163
+ .refine((data) => data.closePosition !== true || data.quantity === undefined, {
164
+ message: "quantity must be omitted when closePosition is true",
165
+ path: ["quantity"],
166
+ })
167
+ .refine((data) => data.quantity !== undefined || data.closePosition !== false, {
168
+ message: "quantity is required when closePosition is false",
169
+ path: ["closePosition"],
170
+ });
171
+ export const ParentTrailingStopLegSchema = TrailingStopLegSchema;
172
+ const hasParentTpSl = (options) => options?.takeProfit !== undefined || options?.stopLoss !== undefined || options?.trailingStop !== undefined;
142
173
  const legacyPositionSideMatchesOrderSide = (side, positionSide) => positionSide === undefined || (positionSide !== "NONE" && ((side === "BUY" && positionSide === "LONG") || (side === "SELL" && positionSide === "SHORT")));
143
174
  /**
144
175
  * Place Limit Order validation schema
@@ -173,6 +204,7 @@ export const PlaceLimitOrderSchema = z
173
204
  selfTradePreventionMode: SelfTradePreventionModeSchema.optional(),
174
205
  takeProfit: ParentTpSlLegSchema.optional(),
175
206
  stopLoss: ParentTpSlLegSchema.optional(),
207
+ trailingStop: ParentTrailingStopLegSchema.optional(),
176
208
  })
177
209
  .optional(),
178
210
  })
@@ -185,11 +217,11 @@ export const PlaceLimitOrderSchema = z
185
217
  path: ["options", "leverage"],
186
218
  })
187
219
  .refine((data) => !hasParentTpSl(data.options) || data.options?.tradingMode === "MARGIN", {
188
- message: "takeProfit/stopLoss are only supported for MARGIN orders",
220
+ message: "takeProfit/stopLoss/trailingStop are only supported for MARGIN orders",
189
221
  path: ["options"],
190
222
  })
191
223
  .refine((data) => !hasParentTpSl(data.options) || data.options?.reduceOnly !== true, {
192
- message: "takeProfit/stopLoss cannot be attached to reduce-only orders",
224
+ message: "takeProfit/stopLoss/trailingStop cannot be attached to reduce-only orders",
193
225
  path: ["options"],
194
226
  })
195
227
  .refine((data) => data.options?.riskBucketCollateral === undefined || data.options?.tradingMode === "MARGIN", {
@@ -252,6 +284,7 @@ export const PlaceMarketOrderSchema = z
252
284
  selfTradePreventionMode: SelfTradePreventionModeSchema.optional(),
253
285
  takeProfit: ParentTpSlLegSchema.optional(),
254
286
  stopLoss: ParentTpSlLegSchema.optional(),
287
+ trailingStop: ParentTrailingStopLegSchema.optional(),
255
288
  })
256
289
  .optional(),
257
290
  })
@@ -264,11 +297,11 @@ export const PlaceMarketOrderSchema = z
264
297
  path: ["options", "leverage"],
265
298
  })
266
299
  .refine((data) => !hasParentTpSl(data.options) || data.options?.tradingMode === "MARGIN", {
267
- message: "takeProfit/stopLoss are only supported for MARGIN orders",
300
+ message: "takeProfit/stopLoss/trailingStop are only supported for MARGIN orders",
268
301
  path: ["options"],
269
302
  })
270
303
  .refine((data) => !hasParentTpSl(data.options) || data.options?.reduceOnly !== true, {
271
- message: "takeProfit/stopLoss cannot be attached to reduce-only orders",
304
+ message: "takeProfit/stopLoss/trailingStop cannot be attached to reduce-only orders",
272
305
  path: ["options"],
273
306
  })
274
307
  .refine((data) => data.options?.riskBucketCollateral === undefined || data.options?.tradingMode === "MARGIN", {
@@ -372,8 +405,8 @@ export const GetPaginatedOrdersSchema = z
372
405
  });
373
406
  }
374
407
  });
375
- export const ConditionalOrderConditionTypeSchema = z.enum(["STOP_LOSS", "TAKE_PROFIT"], {
376
- message: 'conditionType must be "STOP_LOSS" or "TAKE_PROFIT"',
408
+ export const ConditionalOrderConditionTypeSchema = z.enum(["STOP_LOSS", "TAKE_PROFIT", "TRAILING_STOP"], {
409
+ message: 'conditionType must be "STOP_LOSS", "TAKE_PROFIT", or "TRAILING_STOP"',
377
410
  });
378
411
  export const ConditionalOrderTriggerSourceSchema = z.enum(["MARK_PRICE"], {
379
412
  message: 'triggerSource must be "MARK_PRICE"',
@@ -387,12 +420,27 @@ export const ClosePositionSideSchema = z.enum(["LONG", "SHORT"], {
387
420
  export const CancelConditionalOrderSchema = z.object({
388
421
  conditionalOrderId: UUIDSchema,
389
422
  });
390
- export const ListConditionalOrdersSchema = z.object({
423
+ export const ListConditionalOrdersSchema = z
424
+ .object({
391
425
  marginAccountId: UUIDSchema.optional(),
392
426
  tradingPairId: UUIDSchema.optional(),
393
427
  state: ConditionalOrderStateSchema.optional(),
394
428
  page: z.number().int().min(1, "Page must be at least 1").optional(),
395
- pageSize: z.number().int().min(1, "Page size must be at least 1").max(100, "Page size cannot exceed 100").optional(),
429
+ pageSize: z.number().int().min(1, "Page size must be at least 1").max(1000, "Page size cannot exceed 1000").optional(),
430
+ pageToken: z.string().optional(),
431
+ })
432
+ .superRefine((params, ctx) => {
433
+ // The higher 1000 cap only applies to cursor (pageToken) requests; the
434
+ // server keeps the 100 cap for page-number requests (offset scans).
435
+ // Legacy page-number mode is selected only by passing `page` without
436
+ // `pageToken` — omitting both starts a cursor walk.
437
+ if (params.page !== undefined && params.pageToken === undefined && params.pageSize !== undefined && params.pageSize > 100) {
438
+ ctx.addIssue({
439
+ code: z.ZodIssueCode.custom,
440
+ message: "Page size cannot exceed 100 in page-number mode (page without pageToken)",
441
+ path: ["pageSize"],
442
+ });
443
+ }
396
444
  });
397
445
  export const TwapOrderStateSchema = z.enum(["PENDING", "ACTIVE", "COMPLETED", "CANCELLED"], {
398
446
  message: "Invalid TWAP order state",
@@ -516,11 +564,26 @@ export const CreateTwapOrderSchema = z
516
564
  export const CancelTwapOrderSchema = z.object({
517
565
  twapOrderId: UUIDSchema,
518
566
  });
519
- export const ListTwapOrdersSchema = z.object({
567
+ export const ListTwapOrdersSchema = z
568
+ .object({
520
569
  state: TwapOrderStateSchema.optional(),
521
570
  tradingPairId: UUIDSchema.optional(),
522
571
  page: z.number().int().min(1, "Page must be at least 1").optional(),
523
- pageSize: z.number().int().min(1, "Page size must be at least 1").max(100, "Page size cannot exceed 100").optional(),
572
+ pageSize: z.number().int().min(1, "Page size must be at least 1").max(1000, "Page size cannot exceed 1000").optional(),
573
+ pageToken: z.string().optional(),
574
+ })
575
+ .superRefine((params, ctx) => {
576
+ // The higher 1000 cap only applies to cursor (pageToken) requests; the
577
+ // server keeps the 100 cap for page-number requests (offset scans).
578
+ // Legacy page-number mode is selected only by passing `page` without
579
+ // `pageToken` — omitting both starts a cursor walk.
580
+ if (params.page !== undefined && params.pageToken === undefined && params.pageSize !== undefined && params.pageSize > 100) {
581
+ ctx.addIssue({
582
+ code: z.ZodIssueCode.custom,
583
+ message: "Page size cannot exceed 100 in page-number mode (page without pageToken)",
584
+ path: ["pageSize"],
585
+ });
586
+ }
524
587
  });
525
588
  /**
526
589
  * Single batch create order item validation schema