@0xmonaco/types 1.0.36 → 1.0.38-develop.ebf8e8c

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.
@@ -13,7 +13,20 @@ export interface MarginAccountSummary {
13
13
  equity: string;
14
14
  initialMarginRequired: string;
15
15
  maintenanceMarginRequired: string;
16
+ /** Equity headroom: equity less the initial margin requirement. */
16
17
  freeCollateral: string;
18
+ /**
19
+ * The largest amount a transfer-out of this scope will actually accept.
20
+ *
21
+ * Not a clamped `freeCollateral`. Free collateral is equity headroom, and
22
+ * equity includes realized PnL, accrued funding and mark-to-market gains
23
+ * that are not principal a transfer can move — so the two can differ
24
+ * without limit. An unrealized gain never counts toward this figure.
25
+ *
26
+ * For a risk bucket this is capped by the bucket's allocated collateral;
27
+ * for a parent margin account, by deposited collateral that no risk bucket
28
+ * has earmarked. Size transfers against this field, not `freeCollateral`.
29
+ */
17
30
  withdrawableCollateral: string;
18
31
  totalPositionNotional: string;
19
32
  unrealizedPnl: string;
@@ -44,10 +57,21 @@ export interface GetAvailableCollateralResponse {
44
57
  walletLocked: string;
45
58
  marginTransferable?: string;
46
59
  /**
47
- * Free collateral held in the user's parent margin account for this asset
48
- * (equity minus initial margin required) — collateral already inside margin
49
- * and available to open new positions or transfer back out. Absent when the
50
- * user has no margin account yet.
60
+ * The largest amount that can currently leave the user's parent margin
61
+ * account for this asset — the same bound as
62
+ * `MarginAccountSummary.withdrawableCollateral`, and served from the same
63
+ * value, so the two surfaces cannot disagree. Absent when the user has no
64
+ * margin account yet.
65
+ *
66
+ * This is **not** trading headroom. It is bounded by allocation (principal
67
+ * not earmarked by risk buckets) as well as by margin requirements, and an
68
+ * unrealized gain does not raise it: a mark-to-market gain is initial margin
69
+ * for new positions but may not fund an exit. Size new positions from
70
+ * `MarginAccountSummary.freeCollateral`, which credits that gain in full.
71
+ *
72
+ * Note the two `margin*` fields answer opposite questions:
73
+ * {@link marginTransferable} is wallet-to-margin capacity, this is the
74
+ * amount that can come back out.
51
75
  */
52
76
  marginAvailableCollateral?: string;
53
77
  }
@@ -122,12 +122,6 @@ export interface GetUserBalancesParams {
122
122
  * Response from getting user movements
123
123
  */
124
124
  export interface GetPaginatedUserMovementsResponse {
125
- /**
126
- * Latest movements from the live engine cache (real-time, instant updates).
127
- * These are the most recent movements that may not yet be in PostgreSQL.
128
- * Only populated on page 1; empty for subsequent pages.
129
- */
130
- latest_movements?: LedgerMovement[];
131
125
  /** All movements from PostgreSQL (historical, paginated) */
132
126
  movements: LedgerMovement[];
133
127
  /** Current page number */
@@ -15,7 +15,7 @@ import type { SubAccountsAPI } from "../sub-accounts";
15
15
  import type { SweeperAPI } from "../sweeper";
16
16
  import type { TradingAPI, TradingMode } from "../trading";
17
17
  import type { VaultAPI } from "../vault";
18
- import type { ConditionalOrderEvent, OHLCVEvent, OrderbookEvent, OrderbookQuotationMode, OrderEvent, TradeEvent, UserBalanceEvent, UserMovementEvent } from "../websocket";
18
+ import type { ConditionalOrderEvent, MonacoWebSocketConfig, OHLCVEvent, OrderbookEvent, OrderbookQuotationMode, OrderEvent, TradeEvent, UserBalanceEvent, UserMovementEvent } from "../websocket";
19
19
  import type { WhitelistAPI } from "../whitelist";
20
20
  import type { WithdrawalsAPI } from "../withdrawals";
21
21
  import type { Network } from "./network";
@@ -66,6 +66,16 @@ export interface SDKConfig {
66
66
  * 750ms when omitted. Must be a positive finite number when provided.
67
67
  */
68
68
  pollingInterval?: number;
69
+ /**
70
+ * WebSocket reconnect/resync configuration. The `onStatusChange` /
71
+ * `onResync` callbacks and the reconnect knobs (`autoReconnect`,
72
+ * `maxReconnectAttempts`, `reconnectBaseDelayMs`, `connectionTimeoutMs`) are
73
+ * threaded into the WebSocket client the SDK builds internally, so an app can
74
+ * observe connection status and drive snapshot resyncs without dropping to
75
+ * the low-level `createMonacoWebSocket` factory. The session keypair is not
76
+ * part of this surface — it flows from {@link MonacoSDK.login}.
77
+ */
78
+ ws?: MonacoWebSocketConfig;
69
79
  }
70
80
  /**
71
81
  * Core SDK interface providing access to all Monaco functionality.
@@ -38,6 +38,13 @@ export interface TradingAPI extends BaseAPI {
38
38
  positionSide?: PositionSide;
39
39
  leverage?: string;
40
40
  reduceOnly?: boolean;
41
+ /**
42
+ * Maker-only: rejected with a 400 carrying the structured error code
43
+ * `POST_ONLY_WOULD_CROSS` if this limit order would cross the book.
44
+ * LIMIT orders with GTC/GTD only; rejected together with IOC/FOK.
45
+ * Echoed back as `postOnly` on order detail and list reads.
46
+ */
47
+ postOnly?: boolean;
41
48
  takeProfit?: ParentTpSlLegParams;
42
49
  stopLoss?: ParentTpSlLegParams;
43
50
  }): Promise<CreateOrderResponse>;
@@ -104,12 +111,14 @@ export interface TradingAPI extends BaseAPI {
104
111
  * @param newOrder.price - New order price as string (optional)
105
112
  * @param newOrder.quantity - New order quantity as string
106
113
  * @param newOrder.useMasterBalance - Whether to use master balance (optional, defaults to false)
114
+ * @param newOrder.postOnly - Re-states post-only intent for the replacement (nothing is inherited from the original order)
107
115
  * @returns Promise resolving to a `ReplaceOrderResponse`
108
116
  */
109
117
  replaceOrder(orderId: string, newOrder: {
110
118
  price?: string;
111
119
  quantity?: string;
112
120
  useMasterBalance?: boolean;
121
+ postOnly?: boolean;
113
122
  }): Promise<ReplaceOrderResponse>;
114
123
  /**
115
124
  * Batch creates multiple orders in a single request.
@@ -68,6 +68,8 @@ export interface Order {
68
68
  leverage?: string;
69
69
  /** Whether the order can only reduce existing exposure */
70
70
  reduceOnly?: boolean;
71
+ /** Whether the order was placed post-only (maker-only). Absent for orders placed before the flag was persisted. */
72
+ postOnly?: boolean;
71
73
  /** Position ID linked to the order, when available */
72
74
  positionId?: string;
73
75
  /** Stable cause when status is CANCELLED */
@@ -167,11 +167,6 @@ export interface GetPaginatedOrdersParams {
167
167
  * Response from getting paginated orders
168
168
  */
169
169
  export interface GetPaginatedOrdersResponse {
170
- /** Latest orders from the live engine cache (real-time, instant updates).
171
- * These are the most recently created/updated orders that may not yet be in PostgreSQL.
172
- * Only populated on page 1.
173
- */
174
- latest_orders?: Order[];
175
170
  /** Array of historical orders from PostgreSQL (paginated) */
176
171
  orders: Order[];
177
172
  /**
@@ -356,6 +351,14 @@ export interface BatchCreateOrderParams {
356
351
  leverage?: string;
357
352
  /** Whether the order can only reduce existing exposure */
358
353
  reduceOnly?: boolean;
354
+ /**
355
+ * Maker-only: rejected with a structured `error.code` of
356
+ * `POST_ONLY_WOULD_CROSS` on this item's result if the limit order would
357
+ * cross the book. LIMIT orders with GTC/GTD only; rejected on MARKET
358
+ * orders and combined with IOC/FOK. Echoed back as `postOnly` on order
359
+ * detail and list reads.
360
+ */
361
+ postOnly?: boolean;
359
362
  }
360
363
  /**
361
364
  * Parameters for a single order in a batch replace request
@@ -369,6 +372,11 @@ export interface BatchReplaceOrderParams {
369
372
  quantity?: string;
370
373
  /** For sub-accounts: use master's balance (optional) */
371
374
  useMasterBalance?: boolean;
375
+ /**
376
+ * Re-states post-only intent for the replacement (optional). Nothing is
377
+ * inherited from the original order — see `TradingAPI.replaceOrder`.
378
+ */
379
+ postOnly?: boolean;
372
380
  }
373
381
  export interface CancelConditionalOrderResponse {
374
382
  conditionalOrderId: string;
@@ -119,6 +119,7 @@ export declare const PlaceLimitOrderSchema: z.ZodObject<{
119
119
  }>>;
120
120
  leverage: z.ZodOptional<z.ZodString>;
121
121
  reduceOnly: z.ZodOptional<z.ZodBoolean>;
122
+ postOnly: z.ZodOptional<z.ZodBoolean>;
122
123
  takeProfit: z.ZodOptional<z.ZodObject<{
123
124
  triggerPrice: z.ZodString;
124
125
  orderType: z.ZodEnum<{
@@ -230,6 +231,7 @@ export declare const ReplaceOrderSchema: z.ZodObject<{
230
231
  price: z.ZodOptional<z.ZodString>;
231
232
  quantity: z.ZodOptional<z.ZodString>;
232
233
  useMasterBalance: z.ZodOptional<z.ZodBoolean>;
234
+ postOnly: z.ZodOptional<z.ZodBoolean>;
233
235
  }, z.core.$strip>;
234
236
  }, z.core.$strip>;
235
237
  /**
@@ -356,6 +358,7 @@ export declare const BatchCreateOrderItemSchema: z.ZodObject<{
356
358
  }>>;
357
359
  leverage: z.ZodOptional<z.ZodString>;
358
360
  reduceOnly: z.ZodOptional<z.ZodBoolean>;
361
+ postOnly: z.ZodOptional<z.ZodBoolean>;
359
362
  }, z.core.$strip>;
360
363
  /**
361
364
  * Batch Create Orders validation schema
@@ -402,6 +405,7 @@ export declare const BatchCreateOrdersSchema: z.ZodObject<{
402
405
  }>>;
403
406
  leverage: z.ZodOptional<z.ZodString>;
404
407
  reduceOnly: z.ZodOptional<z.ZodBoolean>;
408
+ postOnly: z.ZodOptional<z.ZodBoolean>;
405
409
  }, z.core.$strip>>;
406
410
  }, z.core.$strip>;
407
411
  /**
@@ -415,6 +419,7 @@ export declare const BatchReplaceOrderItemSchema: z.ZodObject<{
415
419
  price: z.ZodOptional<z.ZodString>;
416
420
  quantity: z.ZodOptional<z.ZodString>;
417
421
  useMasterBalance: z.ZodOptional<z.ZodBoolean>;
422
+ postOnly: z.ZodOptional<z.ZodBoolean>;
418
423
  }, z.core.$strip>;
419
424
  /**
420
425
  * Batch Replace Orders validation schema
@@ -427,5 +432,6 @@ export declare const BatchReplaceOrdersSchema: z.ZodObject<{
427
432
  price: z.ZodOptional<z.ZodString>;
428
433
  quantity: z.ZodOptional<z.ZodString>;
429
434
  useMasterBalance: z.ZodOptional<z.ZodBoolean>;
435
+ postOnly: z.ZodOptional<z.ZodBoolean>;
430
436
  }, z.core.$strip>>;
431
437
  }, z.core.$strip>;
@@ -128,6 +128,7 @@ export const PlaceLimitOrderSchema = z
128
128
  positionSide: PositionSideSchema.optional(),
129
129
  leverage: PositiveDecimalStringSchema.optional(),
130
130
  reduceOnly: z.boolean().optional(),
131
+ postOnly: z.boolean().optional(),
131
132
  takeProfit: ParentTpSlLegSchema.optional(),
132
133
  stopLoss: ParentTpSlLegSchema.optional(),
133
134
  })
@@ -180,6 +181,10 @@ export const PlaceLimitOrderSchema = z
180
181
  .refine((data) => data.options?.riskBucketCollateral === undefined || data.options?.reduceOnly !== true, {
181
182
  message: "reduceOnly orders cannot create a new risk bucket",
182
183
  path: ["options", "reduceOnly"],
184
+ })
185
+ .refine((data) => data.options?.postOnly !== true || data.options?.timeInForce === undefined || (data.options.timeInForce !== "IOC" && data.options.timeInForce !== "FOK"), {
186
+ message: "postOnly cannot be combined with IOC/FOK time in force",
187
+ path: ["options", "timeInForce"],
183
188
  });
184
189
  /**
185
190
  * Place Market Order validation schema
@@ -274,6 +279,10 @@ export const ReplaceOrderSchema = z.object({
274
279
  price: PositiveDecimalStringSchema.optional(),
275
280
  quantity: PositiveDecimalStringSchema.optional(),
276
281
  useMasterBalance: z.boolean().optional(),
282
+ // No MARKET/IOC-FOK refine here: order type and time-in-force are not
283
+ // replaceable fields — the server validates postOnly against the
284
+ // persisted original order, which this client-side schema cannot see.
285
+ postOnly: z.boolean().optional(),
277
286
  }),
278
287
  });
279
288
  /**
@@ -358,6 +367,7 @@ export const BatchCreateOrderItemSchema = z
358
367
  positionSide: PositionSideSchema.optional(),
359
368
  leverage: PositiveDecimalStringSchema.optional(),
360
369
  reduceOnly: z.boolean().optional(),
370
+ postOnly: z.boolean().optional(),
361
371
  })
362
372
  .refine((data) => data.orderType !== "LIMIT" || data.price !== undefined, {
363
373
  message: "Price is required for LIMIT orders",
@@ -370,6 +380,14 @@ export const BatchCreateOrderItemSchema = z
370
380
  .refine((data) => data.orderType !== "MARKET" || data.timeInForce === undefined, {
371
381
  message: "timeInForce must not be provided for MARKET orders",
372
382
  path: ["timeInForce"],
383
+ })
384
+ .refine((data) => data.orderType !== "MARKET" || data.postOnly !== true, {
385
+ message: "postOnly must not be provided for MARKET orders",
386
+ path: ["postOnly"],
387
+ })
388
+ .refine((data) => data.postOnly !== true || data.timeInForce === undefined || (data.timeInForce !== "IOC" && data.timeInForce !== "FOK"), {
389
+ message: "postOnly cannot be combined with IOC/FOK time in force",
390
+ path: ["postOnly"],
373
391
  })
374
392
  .refine((data) => data.riskBucketCollateral === undefined || data.tradingMode === "MARGIN", {
375
393
  message: "riskBucketCollateral is only supported for MARGIN orders",
@@ -431,6 +449,10 @@ export const BatchReplaceOrderItemSchema = z
431
449
  price: PositiveDecimalStringSchema.optional(),
432
450
  quantity: PositiveDecimalStringSchema.optional(),
433
451
  useMasterBalance: z.boolean().optional(),
452
+ // No MARKET/IOC-FOK refine here: order type and time-in-force are not
453
+ // replaceable fields — the server validates postOnly against the
454
+ // persisted original order, which this client-side schema cannot see.
455
+ postOnly: z.boolean().optional(),
434
456
  })
435
457
  .refine((data) => data.price !== undefined || data.quantity !== undefined, {
436
458
  message: "At least one of price or quantity must be provided",
@@ -7,6 +7,62 @@
7
7
  * WebSocket connection status
8
8
  */
9
9
  export type WebSocketStatus = "connected" | "connecting" | "disconnected" | "reconnecting";
10
+ /** Handler invoked whenever the WebSocket connection status changes. */
11
+ export type StatusHandler = (status: WebSocketStatus) => void;
12
+ /**
13
+ * Why the connection was re-established. Delivered by
14
+ * {@link MonacoWebSocketConfig.onResync} after the client has reconnected,
15
+ * re-authenticated, and re-subscribed — the point where the app should refetch
16
+ * REST snapshots and reconcile by `(id, updatedAt)`.
17
+ */
18
+ export interface WebSocketResyncInfo {
19
+ /** WebSocket close code of the connection that was lost. */
20
+ code: number;
21
+ /**
22
+ * True when the server closed with 1013 (try again later): the client fell
23
+ * behind a sequential stream (orders, conditional orders, liquidations,
24
+ * trades, movements) and the stream has a gap. There is no wire sequence
25
+ * number — the 1013 close is the gap signal, and a snapshot refetch is the
26
+ * only safe repair.
27
+ */
28
+ slowClient: boolean;
29
+ }
30
+ /** Handler invoked after a reconnect resumes the live stream. */
31
+ export type ResyncHandler = (info: WebSocketResyncInfo) => void;
32
+ /**
33
+ * Reconnect/resync knobs and callbacks for the Monaco WebSocket client.
34
+ *
35
+ * These are settable from the main SDK config ({@link SDKConfig.ws}) so an app
36
+ * can observe connection status and drive snapshot resyncs without reaching for
37
+ * the low-level `createMonacoWebSocket` factory. The session keypair is not
38
+ * part of this surface — it flows from {@link MonacoSDK.login}.
39
+ */
40
+ export interface MonacoWebSocketConfig {
41
+ /** Enable auto-reconnect on disconnect (default: true) */
42
+ autoReconnect?: boolean;
43
+ /**
44
+ * Maximum reconnection attempts (default: unlimited). Retry delay is
45
+ * full-jitter exponential backoff capped at 30s, so unlimited retries are
46
+ * capped-rate, not a tight loop.
47
+ */
48
+ maxReconnectAttempts?: number;
49
+ /** Base delay for the exponential backoff in milliseconds (default: 1000) */
50
+ reconnectBaseDelayMs?: number;
51
+ /**
52
+ * How long a connection attempt may stay CONNECTING before it is failed and
53
+ * retried, in milliseconds (default: 10000)
54
+ */
55
+ connectionTimeoutMs?: number;
56
+ /** Callback for connection status changes */
57
+ onStatusChange?: StatusHandler;
58
+ /**
59
+ * Called after every automatic reconnect once the live stream is resumed
60
+ * (re-authenticated and re-subscribed). Refetch REST snapshots here and
61
+ * reconcile by `(id, updatedAt)`, last-writer-wins; events that arrived while
62
+ * the snapshot was in flight are newer than the snapshot rows they duplicate.
63
+ */
64
+ onResync?: ResyncHandler;
65
+ }
10
66
  /**
11
67
  * Raw event message interface
12
68
  * This is the raw message received from the backend
@@ -1,7 +1,9 @@
1
1
  export * from "./balance-events";
2
2
  export * from "./conditional-order-events";
3
+ export * from "./liquidation-events";
3
4
  export * from "./movement-events";
4
5
  export * from "./ohlcv-events";
5
6
  export * from "./orderbook-events";
6
7
  export * from "./orders-events";
8
+ export * from "./position-events";
7
9
  export * from "./trade-events";
@@ -1,7 +1,9 @@
1
1
  export * from "./balance-events";
2
2
  export * from "./conditional-order-events";
3
+ export * from "./liquidation-events";
3
4
  export * from "./movement-events";
4
5
  export * from "./ohlcv-events";
5
6
  export * from "./orderbook-events";
6
7
  export * from "./orders-events";
8
+ export * from "./position-events";
7
9
  export * from "./trade-events";
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Liquidation WebSocket Event Types
3
+ *
4
+ * Types for real-time liquidation alerts (an account crossed a maintenance
5
+ * threshold and a liquidation record was opened / advanced).
6
+ *
7
+ * This is an authenticated channel - requires the signed session-key handshake.
8
+ * Lag policy is Disconnect: a subscriber that falls behind is closed with
9
+ * `1013` (try again later). There is no wire sequence number, so the `1013`
10
+ * close is the gap signal - resync by refetching a REST/SDK snapshot.
11
+ */
12
+ /**
13
+ * Liquidation alert event data.
14
+ *
15
+ * `status` and `accountState` are free-form strings on the wire (they mirror
16
+ * server-side enums that carry no wire-level rename), so they are typed as
17
+ * `string` rather than a closed union to avoid dropping a risk-critical alert
18
+ * on an unexpected value.
19
+ */
20
+ export interface LiquidationEventData {
21
+ /** Liquidation record identifier (UUID) */
22
+ liquidationId: string;
23
+ /** Margin account under liquidation (UUID) */
24
+ marginAccountId: string;
25
+ /** Position being liquidated, when the alert is position-scoped (UUID) */
26
+ positionId?: string;
27
+ /** Trading pair of the liquidated position, when position-scoped (UUID) */
28
+ tradingPairId?: string;
29
+ /** Liquidation record status (e.g. "UNRESOLVED", free-form) */
30
+ status: string;
31
+ /** Margin-account risk state at alert time (e.g. "PENDING", free-form) */
32
+ accountState: string;
33
+ /** Position liquidation price, when known (decimal string) */
34
+ liquidationPrice?: string;
35
+ /** Mark price at alert time, when known (decimal string) */
36
+ markPrice?: string;
37
+ /** Estimated collateral shortfall (decimal string) */
38
+ estimatedShortfall: string;
39
+ /** Human-readable alert message */
40
+ message: string;
41
+ /** Timestamp when the alert was triggered (ISO 8601) */
42
+ triggeredAt: string;
43
+ }
44
+ /**
45
+ * Liquidation alert event emitted when a user's account is being liquidated.
46
+ */
47
+ export interface LiquidationEvent {
48
+ /** Event type identifier */
49
+ eventType: "liquidation_alert";
50
+ /** User ID (UUID) */
51
+ userId: string;
52
+ /** Liquidation data */
53
+ data: LiquidationEventData;
54
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Liquidation WebSocket Event Types
3
+ *
4
+ * Types for real-time liquidation alerts (an account crossed a maintenance
5
+ * threshold and a liquidation record was opened / advanced).
6
+ *
7
+ * This is an authenticated channel - requires the signed session-key handshake.
8
+ * Lag policy is Disconnect: a subscriber that falls behind is closed with
9
+ * `1013` (try again later). There is no wire sequence number, so the `1013`
10
+ * close is the gap signal - resync by refetching a REST/SDK snapshot.
11
+ */
@@ -37,8 +37,14 @@ export interface CommonOrderEventData {
37
37
  tradingPairId?: string;
38
38
  /** Application ID (UUID) - present in several events */
39
39
  applicationId?: string;
40
- /** Trading pair symbol (e.g., "BTC/USDC") */
41
- symbol: string;
40
+ /**
41
+ * Trading pair symbol (e.g., "BTC/USDC").
42
+ *
43
+ * The wire field is `trading_pair` (→ `tradingPair` after camelCasing), not
44
+ * `symbol`; the previous `symbol` declaration never matched what the matching
45
+ * engine emits.
46
+ */
47
+ tradingPair: string;
42
48
  /** Trading mode (e.g., "SPOT", "MARGIN") */
43
49
  tradingMode: TradingMode;
44
50
  /** Order type - present in most events */
@@ -49,6 +55,8 @@ export interface CommonOrderEventData {
49
55
  price?: string;
50
56
  /** Order quantity - present in most events */
51
57
  quantity?: string;
58
+ /** Order quantity in RAW (integer, base-unit) precision. Wire: `quantity_raw`. */
59
+ quantityRaw?: string;
52
60
  /** Time in force - present in most events */
53
61
  timeInForce?: TimeInForce;
54
62
  }
@@ -131,10 +139,22 @@ export interface OrderPartiallyFilledEvent extends OrderEvent {
131
139
  tradeId?: string;
132
140
  /** Execution price (maker orders only) */
133
141
  executionPrice?: string;
134
- /** Execution quantity (maker orders only) */
135
- executionQuantity?: string;
136
- /** Maker fee (maker orders only) */
137
- makerFee?: string;
142
+ /**
143
+ * Quantity filled in this event (maker orders only). The wire field is
144
+ * `filled_quantity` (→ `filledQuantity`); for a maker this is the current
145
+ * trade's quantity. The previous `executionQuantity` never matched the
146
+ * wire. For a taker the same-named field carries the cumulative order fill.
147
+ */
148
+ filledQuantity?: string;
149
+ /** `filledQuantity` in RAW (integer, base-unit) precision. Wire: `filled_quantity_raw`. */
150
+ filledQuantityRaw?: string;
151
+ /** `remainingQuantity` in RAW (integer, base-unit) precision. Wire: `remaining_quantity_raw`. */
152
+ remainingQuantityRaw?: string;
153
+ /**
154
+ * Fee charged for this fill (maker orders only). The wire field is `fee`
155
+ * (→ `fee`), not `makerFee`; taker fills carry the same `fee` field.
156
+ */
157
+ fee?: string;
138
158
  /** Trade execution timestamp (maker orders only) */
139
159
  executedAt?: string;
140
160
  /** Role of the order in the trade (taker or maker) */
@@ -179,10 +199,22 @@ export interface OrderFilledEvent extends OrderEvent {
179
199
  tradeId?: string;
180
200
  /** Execution price (maker orders only) */
181
201
  executionPrice?: string;
182
- /** Execution quantity (maker orders only) */
183
- executionQuantity?: string;
184
- /** Maker fee (maker orders only) */
185
- makerFee?: string;
202
+ /**
203
+ * Quantity filled in this event (maker orders only). The wire field is
204
+ * `filled_quantity` (→ `filledQuantity`); for a maker this is the current
205
+ * trade's quantity. The previous `executionQuantity` never matched the
206
+ * wire. For a taker the same-named field carries the cumulative order fill.
207
+ */
208
+ filledQuantity?: string;
209
+ /** `filledQuantity` in RAW (integer, base-unit) precision. Wire: `filled_quantity_raw`. */
210
+ filledQuantityRaw?: string;
211
+ /** `remainingQuantity` in RAW (integer, base-unit) precision. Wire: `remaining_quantity_raw`. */
212
+ remainingQuantityRaw?: string;
213
+ /**
214
+ * Fee charged for this fill (maker orders only). The wire field is `fee`
215
+ * (→ `fee`), not `makerFee`; taker fills carry the same `fee` field.
216
+ */
217
+ fee?: string;
186
218
  /** Trade execution timestamp (maker orders only) */
187
219
  executedAt?: string;
188
220
  /** Role of the order in the trade (taker or maker) */
@@ -201,8 +233,12 @@ export interface OrderCancelledEvent extends OrderEvent {
201
233
  terminalReason?: OrderTerminalReason;
202
234
  /** Total filled quantity before cancellation */
203
235
  totalFilled?: string;
236
+ /** `totalFilled` in RAW (integer, base-unit) precision. Wire: `total_filled_raw`. */
237
+ totalFilledRaw?: string;
204
238
  /** Remaining quantity when canceled */
205
239
  remainingQuantity?: string;
240
+ /** `remainingQuantity` in RAW (integer, base-unit) precision. Wire: `remaining_quantity_raw`. */
241
+ remainingQuantityRaw?: string;
206
242
  /** Number of trades executed before cancellation */
207
243
  tradesCount?: number;
208
244
  };
@@ -279,8 +315,8 @@ export interface BackendCommonOrderEventData {
279
315
  user_id: string;
280
316
  /** Trading pair ID (UUID) */
281
317
  trading_pair_id?: string;
282
- /** Trading pair symbol (e.g., "BTC/USDC") */
283
- symbol: string;
318
+ /** Trading pair symbol (e.g., "BTC/USDC"), from the wire `trading_pair` field. */
319
+ trading_pair: string;
284
320
  /** Trading mode (e.g., "Spot", "Margin") */
285
321
  trading_mode: string;
286
322
  }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Position WebSocket Event Types
3
+ *
4
+ * Types for real-time position state updates (open/close, mark price, PnL,
5
+ * liquidation price, isolated margin, leverage).
6
+ *
7
+ * This is an authenticated channel - requires the signed session-key handshake.
8
+ * Lag policy is Conflate: a lagging subscriber is fast-forwarded to the latest
9
+ * state rather than disconnected, so there is no gap signal to reconcile.
10
+ */
11
+ /**
12
+ * Position side. The server emits `LONG` or `SHORT` for an open position.
13
+ */
14
+ export type PositionEventSide = "LONG" | "SHORT";
15
+ /**
16
+ * Position lifecycle status.
17
+ *
18
+ * NOTE: this is PascalCase on the wire (`Open`, not `OPEN`) - the underlying
19
+ * enum has no serde rename, unlike side/trading-mode fields. That asymmetry is
20
+ * the live wire format and is preserved verbatim here.
21
+ */
22
+ export type PositionEventStatus = "Open" | "Closing" | "Closed" | "Liquidated" | "Expired";
23
+ /**
24
+ * Position event data containing the current state of a single position.
25
+ */
26
+ export interface PositionEventData {
27
+ /** Position identifier (UUID) */
28
+ positionId: string;
29
+ /** Margin account that owns the position (UUID) */
30
+ marginAccountId: string;
31
+ /** Trading pair identifier (UUID) */
32
+ tradingPairId: string;
33
+ /** Position side */
34
+ side: PositionEventSide;
35
+ /** Position lifecycle status (PascalCase on the wire) */
36
+ status: PositionEventStatus;
37
+ /** Absolute position size (decimal string) */
38
+ size: string;
39
+ /** Average entry price (decimal string) */
40
+ entryPrice: string;
41
+ /** Current mark price (decimal string) */
42
+ markPrice?: string;
43
+ /** Unrealized PnL at the current mark price (decimal string) */
44
+ unrealizedPnl?: string;
45
+ /** Estimated liquidation price (decimal string) */
46
+ liquidationPrice?: string;
47
+ /** Isolated margin / collateral backing the position (decimal string) */
48
+ isolatedMargin: string;
49
+ /** Effective leverage (decimal string) */
50
+ leverage: string;
51
+ /** What triggered the update (e.g. "trade", free-form) */
52
+ reason: string;
53
+ /** Timestamp when the position state was updated (ISO 8601) */
54
+ updatedAt: string;
55
+ }
56
+ /**
57
+ * Position event emitted when a user's position state changes.
58
+ */
59
+ export interface PositionEvent {
60
+ /** Event type identifier */
61
+ eventType: "position_update";
62
+ /** User ID (UUID) */
63
+ userId: string;
64
+ /** Position data */
65
+ data: PositionEventData;
66
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Position WebSocket Event Types
3
+ *
4
+ * Types for real-time position state updates (open/close, mark price, PnL,
5
+ * liquidation price, isolated margin, leverage).
6
+ *
7
+ * This is an authenticated channel - requires the signed session-key handshake.
8
+ * Lag policy is Conflate: a lagging subscriber is fast-forwarded to the latest
9
+ * state rather than disconnected, so there is no gap signal to reconcile.
10
+ */
@@ -51,4 +51,15 @@ export type WireCovered<Ergo, Wire> = [MissingWireFields<Ergo, Wire>] extends [n
51
51
  * `tsc` reports the missing wire fields at this line.
52
52
  */
53
53
  export type Expect<T extends true> = T;
54
+ /**
55
+ * Resolves to `true` when `K` is NOT a key of `T`, otherwise `false`. Pair with
56
+ * {@link Expect} to guard that a field stays absent from a public type, so a
57
+ * removed field cannot silently reappear:
58
+ *
59
+ * type _NoLatestOrders = Expect<KeyAbsent<GetPaginatedOrdersResponse, "latest_orders">>;
60
+ *
61
+ * If the key is present, `KeyAbsent` resolves to `false`, `T extends true`
62
+ * fails, and `tsc` reports the reintroduced field at this line.
63
+ */
64
+ export type KeyAbsent<T, K extends PropertyKey> = K extends keyof T ? false : true;
54
65
  export {};
@@ -13,7 +13,7 @@
13
13
  * It also exports the generated runtime `OPERATION_IDS` list and the
14
14
  * `auditSurface` helper that power the MON-1489 endpoint-coverage gate.
15
15
  */
16
- export type { Expect, MissingWireFields, WireCovered, WireSchema, WireSchemas } from "./assert";
16
+ export type { Expect, KeyAbsent, MissingWireFields, WireCovered, WireSchema, WireSchemas } from "./assert";
17
17
  export type { CoverageAudit, SurfaceClassification } from "./audit";
18
18
  export { auditSurface } from "./audit";
19
19
  export type { OperationId } from "./operations";
@@ -2714,6 +2714,11 @@ export interface components {
2714
2714
  * @enum {string|null}
2715
2715
  */
2716
2716
  marginMode?: "ISOLATED" | "CROSS" | null;
2717
+ /**
2718
+ * @description Post-only: reject instead of matching if this limit order would cross the book — rejected with HTTP 400 / gRPC INVALID_ARGUMENT carrying the structured error code POST_ONLY_WOULD_CROSS (REST error-envelope 'code' field; gRPC google.rpc.ErrorInfo reason; batch per-item error.code). Matching the 'post-only order would cross' message substring is a legacy fallback. LIMIT orders with GTC/GTD only; rejected on MARKET orders and IOC/FOK.
2719
+ * @example false
2720
+ */
2721
+ postOnly?: boolean | null;
2717
2722
  };
2718
2723
  BatchCreateOrdersRequest: {
2719
2724
  orders: components["schemas"]["BatchCreateOrderItem"][];
@@ -2783,6 +2788,11 @@ export interface components {
2783
2788
  * @example false
2784
2789
  */
2785
2790
  useMasterBalance?: boolean | null;
2791
+ /**
2792
+ * @description Post-only: reject instead of matching if this limit order would cross the book — rejected with HTTP 400 / gRPC INVALID_ARGUMENT carrying the structured error code POST_ONLY_WOULD_CROSS (REST error-envelope 'code' field; gRPC google.rpc.ErrorInfo reason; batch per-item error.code). Matching the 'post-only order would cross' message substring is a legacy fallback. LIMIT orders with GTC/GTD only; rejected on MARKET orders and IOC/FOK.
2793
+ * @example false
2794
+ */
2795
+ postOnly?: boolean | null;
2786
2796
  };
2787
2797
  BatchReplaceOrdersRequest: {
2788
2798
  orders: components["schemas"]["BatchReplaceOrderItem"][];
@@ -3177,6 +3187,11 @@ export interface components {
3177
3187
  * @enum {string|null}
3178
3188
  */
3179
3189
  marginMode?: "ISOLATED" | "CROSS" | null;
3190
+ /**
3191
+ * @description Post-only: reject instead of matching if this limit order would cross the book — rejected with HTTP 400 / gRPC INVALID_ARGUMENT carrying the structured error code POST_ONLY_WOULD_CROSS (REST error-envelope 'code' field; gRPC google.rpc.ErrorInfo reason; batch per-item error.code). Matching the 'post-only order would cross' message substring is a legacy fallback. LIMIT orders with GTC/GTD only; rejected on MARKET orders and IOC/FOK.
3192
+ * @example false
3193
+ */
3194
+ postOnly?: boolean | null;
3180
3195
  };
3181
3196
  CreateOrderResponse: {
3182
3197
  /**
@@ -3515,10 +3530,21 @@ export interface components {
3515
3530
  walletLocked?: string | null;
3516
3531
  marginTransferable?: string | null;
3517
3532
  /**
3518
- * @description Free collateral currently held in the user's parent margin account for this
3519
- * asset (equity minus initial margin required), i.e. collateral already inside
3520
- * margin and available to open new positions or transfer back out. Absent when
3521
- * the user has no margin account yet.
3533
+ * @description The largest amount that can currently leave the user's parent margin
3534
+ * account for this asset — the same bound as
3535
+ * `MarginAccountSummary.withdrawable_collateral`, and served from the same
3536
+ * value, so the two surfaces cannot disagree. Absent when the user has no
3537
+ * margin account yet.
3538
+ *
3539
+ * This is NOT trading headroom. It is bounded by allocation (principal not
3540
+ * earmarked by risk buckets) as well as by margin requirements, and an
3541
+ * unrealized gain does not raise it: a mark-to-market gain is initial margin
3542
+ * for new positions but may not fund an exit. Size new positions from
3543
+ * `MarginAccountSummary.free_collateral`, which credits that gain in full.
3544
+ *
3545
+ * Note the two `margin_*` fields answer opposite questions:
3546
+ * `margin_transferable` is wallet-to-margin capacity, this is the amount that
3547
+ * can come back out.
3522
3548
  */
3523
3549
  marginAvailableCollateral?: string | null;
3524
3550
  };
@@ -3711,6 +3737,28 @@ export interface components {
3711
3737
  initialMarginRequired?: string | null;
3712
3738
  maintenanceMarginRequired?: string | null;
3713
3739
  freeCollateral?: string | null;
3740
+ /**
3741
+ * @description The largest amount a transfer-out of this scope will actually accept.
3742
+ *
3743
+ * NOT a clamped `free_collateral`. Free collateral is equity headroom, and
3744
+ * equity includes realized PnL, accrued funding and mark-to-market gains
3745
+ * that are not principal a transfer can move — so the two can differ
3746
+ * without limit. An unrealized gain never counts toward this figure.
3747
+ *
3748
+ * For a risk bucket this is capped by the bucket's allocated collateral;
3749
+ * for a parent margin account, by deposited collateral that no risk bucket
3750
+ * has earmarked.
3751
+ *
3752
+ * This is the largest accepted transfer-out, NOT a promise that every
3753
+ * smaller one is accepted. Acceptance is not monotone in the amount: a risk
3754
+ * bucket whose realized loss exceeds its remaining value accepts the full
3755
+ * close-out reported here — which settles that loss to the parent margin
3756
+ * account — while refusing a partial withdrawal that would leave the bucket
3757
+ * holding less collateral than the loss it has already taken. For such a
3758
+ * bucket the accepted amounts are everything up to its equity, plus this
3759
+ * figure itself, with a gap in between. Size a transfer directly from this
3760
+ * field rather than shaving a margin off it.
3761
+ */
3714
3762
  withdrawableCollateral?: string | null;
3715
3763
  totalPositionNotional?: string | null;
3716
3764
  unrealizedPnl?: string | null;
@@ -4139,6 +4187,11 @@ export interface components {
4139
4187
  * @example REDUCE_ONLY_EXHAUSTED
4140
4188
  */
4141
4189
  terminalReason?: string | null;
4190
+ /**
4191
+ * @description Whether the order was placed post-only (maker-only). Absent for orders placed before the flag was persisted.
4192
+ * @example false
4193
+ */
4194
+ postOnly?: boolean | null;
4142
4195
  };
4143
4196
  /** @description Orderbook snapshot with token metadata and sequence number. */
4144
4197
  GetOrderbookResponse: {
@@ -5172,6 +5225,28 @@ export interface components {
5172
5225
  initialMarginRequired?: string | null;
5173
5226
  maintenanceMarginRequired?: string | null;
5174
5227
  freeCollateral?: string | null;
5228
+ /**
5229
+ * @description The largest amount a transfer-out of this scope will actually accept.
5230
+ *
5231
+ * NOT a clamped `free_collateral`. Free collateral is equity headroom, and
5232
+ * equity includes realized PnL, accrued funding and mark-to-market gains
5233
+ * that are not principal a transfer can move — so the two can differ
5234
+ * without limit. An unrealized gain never counts toward this figure.
5235
+ *
5236
+ * For a risk bucket this is capped by the bucket's allocated collateral;
5237
+ * for a parent margin account, by deposited collateral that no risk bucket
5238
+ * has earmarked.
5239
+ *
5240
+ * This is the largest accepted transfer-out, NOT a promise that every
5241
+ * smaller one is accepted. Acceptance is not monotone in the amount: a risk
5242
+ * bucket whose realized loss exceeds its remaining value accepts the full
5243
+ * close-out reported here — which settles that loss to the parent margin
5244
+ * account — while refusing a partial withdrawal that would leave the bucket
5245
+ * holding less collateral than the loss it has already taken. For such a
5246
+ * bucket the accepted amounts are everything up to its equity, plus this
5247
+ * figure itself, with a gap in between. Size a transfer directly from this
5248
+ * field rather than shaving a margin off it.
5249
+ */
5175
5250
  withdrawableCollateral?: string | null;
5176
5251
  totalPositionNotional?: string | null;
5177
5252
  unrealizedPnl?: string | null;
@@ -5902,10 +5977,10 @@ export interface components {
5902
5977
  };
5903
5978
  ReplaceOrderRequest: {
5904
5979
  /**
5905
- * @description Use master account balance for sub-account orders
5980
+ * @description Post-only: reject instead of matching if this limit order would cross the book — rejected with HTTP 400 / gRPC INVALID_ARGUMENT carrying the structured error code POST_ONLY_WOULD_CROSS (REST error-envelope 'code' field; gRPC google.rpc.ErrorInfo reason; batch per-item error.code). Matching the 'post-only order would cross' message substring is a legacy fallback. LIMIT orders with GTC/GTD only; rejected on MARKET orders and IOC/FOK.
5906
5981
  * @example false
5907
5982
  */
5908
- useMasterBalance?: boolean | null;
5983
+ postOnly?: boolean | null;
5909
5984
  /**
5910
5985
  * @description New limit price (if changing)
5911
5986
  * @example 35500.00
@@ -5916,6 +5991,11 @@ export interface components {
5916
5991
  * @example 0.7
5917
5992
  */
5918
5993
  quantity?: string | null;
5994
+ /**
5995
+ * @description Use master account balance for sub-account orders
5996
+ * @example false
5997
+ */
5998
+ useMasterBalance?: boolean | null;
5919
5999
  };
5920
6000
  ReplaceOrderResponse: {
5921
6001
  /**
@@ -6632,6 +6712,11 @@ export interface components {
6632
6712
  status?: string | null;
6633
6713
  newEquity?: string | null;
6634
6714
  newTotalCollateralValue?: string | null;
6715
+ /**
6716
+ * @description The largest amount a further transfer-out will accept after this one.
6717
+ * See `MarginAccountSummary.withdrawable_collateral`: this is an
6718
+ * allocation-bounded figure, not clamped equity headroom.
6719
+ */
6635
6720
  newWithdrawableCollateral?: string | null;
6636
6721
  strategyKey?: string | null;
6637
6722
  };
@@ -6662,6 +6747,11 @@ export interface components {
6662
6747
  status?: string | null;
6663
6748
  newEquity?: string | null;
6664
6749
  newTotalCollateralValue?: string | null;
6750
+ /**
6751
+ * @description The largest amount a further transfer-out will accept after this one.
6752
+ * See `MarginAccountSummary.withdrawable_collateral`: this is an
6753
+ * allocation-bounded figure, not clamped equity headroom.
6754
+ */
6665
6755
  newWithdrawableCollateral?: string | null;
6666
6756
  strategyKey?: string | null;
6667
6757
  /** @description Present when collateral was allocated to a risk bucket. */
@@ -7941,7 +8031,7 @@ export interface operations {
7941
8031
  };
7942
8032
  content?: never;
7943
8033
  };
7944
- /** @description Unauthorized - Invalid or missing JWT */
8034
+ /** @description Authentication required */
7945
8035
  401: {
7946
8036
  headers: {
7947
8037
  [name: string]: unknown;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@0xmonaco/types",
3
- "version": "1.0.36",
3
+ "version": "1.0.38-develop.ebf8e8c",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -20,7 +20,7 @@
20
20
  "lint": "biome lint ."
21
21
  },
22
22
  "dependencies": {
23
- "@0xmonaco/contracts": "1.0.36",
23
+ "@0xmonaco/contracts": "1.0.38-develop.ebf8e8c",
24
24
  "zod": "^4.1.12"
25
25
  },
26
26
  "peerDependencies": {