@0xmonaco/types 1.0.51 → 1.0.53
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.
- package/dist/margin-accounts/index.d.ts +40 -1
- package/dist/portfolio/index.d.ts +39 -0
- package/dist/positions/index.d.ts +10 -4
- package/dist/trading/index.d.ts +4 -0
- package/dist/trading/responses.d.ts +2 -0
- package/dist/validation/margin-accounts.d.ts +9 -3
- package/dist/validation/margin-accounts.js +31 -3
- package/dist/validation/trading.d.ts +5 -0
- package/dist/validation/trading.js +8 -0
- package/dist/websocket/client.d.ts +67 -18
- package/dist/websocket/client.js +39 -0
- package/dist/websocket/index.d.ts +1 -0
- package/dist/websocket/index.js +1 -0
- package/dist/websocket/snapshots.d.ts +140 -0
- package/dist/websocket/snapshots.js +26 -0
- package/dist/wire/schema.d.ts +102 -11
- package/package.json +2 -2
|
@@ -161,9 +161,26 @@ export interface TransferCollateralToIsolatedRiskBucketRequest extends TransferC
|
|
|
161
161
|
*/
|
|
162
162
|
applyToPositionMargin?: boolean;
|
|
163
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* Fund the account's cross risk bucket from the parent's unallocated
|
|
166
|
+
* collateral (the bucket is created if needed). A cross transfer names no
|
|
167
|
+
* pairs: cross scope is derived from trading — a pair joins the bucket when a
|
|
168
|
+
* cross order on it succeeds and leaves when its positions close — so funding
|
|
169
|
+
* has nothing to declare. Read the current scope from the cross bucket's row
|
|
170
|
+
* in `listMarginAccounts()` (`selectedTradingPairIds`) or from this call's
|
|
171
|
+
* response; the parent summary row carries no scope. Pairs declared before
|
|
172
|
+
* scope became derived stay recorded until they trade and their positions
|
|
173
|
+
* close.
|
|
174
|
+
*/
|
|
164
175
|
export interface TransferCollateralToCrossRiskBucketRequest extends TransferCollateralToParentMarginAccountRequest {
|
|
165
176
|
marginMode: "CROSS";
|
|
166
|
-
|
|
177
|
+
/**
|
|
178
|
+
* Removed. This used to declare — and on every top-up REPLACE — the cross
|
|
179
|
+
* bucket's scope, which let a partial list silently evict every flat pair it
|
|
180
|
+
* forgot. The server now ignores the field; the SDK no longer sends it and
|
|
181
|
+
* rejects it here so a caller learns at compile time that it does nothing.
|
|
182
|
+
*/
|
|
183
|
+
selectedTradingPairIds?: never;
|
|
167
184
|
tradingPairId?: never;
|
|
168
185
|
strategyKey?: never;
|
|
169
186
|
/** Cross risk is pooled at bucket equity — there is no per-position margin; an explicit `true` is rejected. */
|
|
@@ -252,6 +269,28 @@ export interface SimulateOrderRiskResponse {
|
|
|
252
269
|
initialMarginRequiredAfter: string;
|
|
253
270
|
maintenanceMarginRequiredAfter: string;
|
|
254
271
|
freeCollateralAfter: string;
|
|
272
|
+
/**
|
|
273
|
+
* What this order pays in fees once its WHOLE size has executed, priced by the
|
|
274
|
+
* role each part of it plays against the book right now: the taker rate (plus
|
|
275
|
+
* the application's additional taker fee) on the quantity that would cross
|
|
276
|
+
* immediately, and the maker rate on the quantity that would rest and be
|
|
277
|
+
* filled later. Both are the caller's own tier-resolved rates. One figure
|
|
278
|
+
* covers an order that crosses entirely, one that rests entirely, and every
|
|
279
|
+
* split in between.
|
|
280
|
+
*
|
|
281
|
+
* Signed: NEGATIVE means a net rebate, the honest answer for a resting order
|
|
282
|
+
* on a pair whose maker fee is negative. Populated even when `accepted` is
|
|
283
|
+
* false, and for reduce-only orders — closing a position pays fees like any
|
|
284
|
+
* other fill.
|
|
285
|
+
*
|
|
286
|
+
* Assumes the resting part eventually fills, so it states what the order costs
|
|
287
|
+
* if it runs to completion: cancel before the remainder fills and only the
|
|
288
|
+
* crossing part was ever charged.
|
|
289
|
+
*
|
|
290
|
+
* Absent — never zero — when the engine could not price the order: it was
|
|
291
|
+
* refused before it could be matched, or its resolved maker tier exceeds the
|
|
292
|
+
* pair's cap. Treat `undefined` as unknown, never as a free order.
|
|
293
|
+
*/
|
|
255
294
|
estimatedFee?: string;
|
|
256
295
|
/**
|
|
257
296
|
* Estimated liquidation mark-price. In ISOLATED mode, this is the
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { BaseAPI } from "../api";
|
|
2
|
+
import type { MarginMode } from "../margin-accounts";
|
|
2
3
|
/** Closed rolling windows supported by the authoritative portfolio APIs. */
|
|
3
4
|
export type PortfolioAnalyticsPeriod = "1d" | "1w" | "1m" | "all";
|
|
4
5
|
export type PortfolioCoverage = "complete" | "partial" | "none";
|
|
@@ -215,6 +216,44 @@ export interface PortfolioRiskBucket {
|
|
|
215
216
|
* (the key is omitted, never null) on persisted-fallback reads.
|
|
216
217
|
*/
|
|
217
218
|
availableOrderCollateral?: string;
|
|
219
|
+
/**
|
|
220
|
+
* The mode this bucket is margined under.
|
|
221
|
+
*
|
|
222
|
+
* Always present — every row here IS a bucket, and its mode is a non-null
|
|
223
|
+
* column (unlike `MarginAccountSummary.marginMode`, which is optional
|
|
224
|
+
* because that shape also models a parent row belonging to no bucket). It
|
|
225
|
+
* lets you attribute bucket margin to cross or isolated from this response
|
|
226
|
+
* alone, instead of resolving the opaque `riskBucketId` against the
|
|
227
|
+
* margin-accounts surface.
|
|
228
|
+
*
|
|
229
|
+
* It does NOT reconcile with the `positions.cross` / `positions.isolated`
|
|
230
|
+
* counts beside it, and grouping these rows by mode will not reproduce
|
|
231
|
+
* them. Those counts come from a separate query with a wider scope — every
|
|
232
|
+
* margin account for your user/application pair, while these rows come from
|
|
233
|
+
* the single oldest (parent) account — and they attribute a legacy position
|
|
234
|
+
* carrying no risk-bucket reference to cross whether or not a cross bucket
|
|
235
|
+
* row exists. Treat the counts as account-wide totals, not as a checksum
|
|
236
|
+
* over `riskBuckets`.
|
|
237
|
+
*/
|
|
238
|
+
marginMode: MarginMode;
|
|
239
|
+
/**
|
|
240
|
+
* The trading pair this bucket is scoped to. Present for `ISOLATED`
|
|
241
|
+
* buckets; absent (the key is omitted, never null) for `CROSS`, which spans
|
|
242
|
+
* the pairs selected into it and is scoped to none of them individually.
|
|
243
|
+
*
|
|
244
|
+
* For a cross bucket's membership read
|
|
245
|
+
* `MarginAccountSummary.selectedTradingPairIds` — it is not carried here
|
|
246
|
+
* because it would cost this endpoint an extra query per request.
|
|
247
|
+
*
|
|
248
|
+
* These labels do not make this response row-for-row joinable with the
|
|
249
|
+
* margin-accounts surface on `(marginMode, tradingPairId)`. That surface
|
|
250
|
+
* emits rows this one has no counterpart for (a provisioned-but-unfunded
|
|
251
|
+
* auto bucket, and a parent row with no mode at all), and on a
|
|
252
|
+
* persisted-fallback read the two surfaces attribute a legacy position
|
|
253
|
+
* carrying no risk-bucket reference to opposite buckets. Use these fields
|
|
254
|
+
* to label and group this response, not to cross-foot it against another.
|
|
255
|
+
*/
|
|
256
|
+
tradingPairId?: string;
|
|
218
257
|
}
|
|
219
258
|
export interface PortfolioMargin {
|
|
220
259
|
asOf: string;
|
|
@@ -32,10 +32,16 @@ export interface Position {
|
|
|
32
32
|
unrealizedPnl: string;
|
|
33
33
|
realizedPnl: string;
|
|
34
34
|
/**
|
|
35
|
-
* Open rows:
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
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.
|
|
39
45
|
*/
|
|
40
46
|
isolatedMargin: string;
|
|
41
47
|
leverage?: string;
|
package/dist/trading/index.d.ts
CHANGED
|
@@ -55,6 +55,8 @@ export interface TradingAPI extends BaseAPI {
|
|
|
55
55
|
* replacement re-states it and inherits nothing from the original order.
|
|
56
56
|
*/
|
|
57
57
|
clientOrderId?: string;
|
|
58
|
+
/** The SDK generates a key once per call when omitted. Supply the same key to retry a logical order within 24 hours. */
|
|
59
|
+
idempotencyKey?: string;
|
|
58
60
|
takeProfit?: ParentTpSlLegParams;
|
|
59
61
|
stopLoss?: ParentTpSlLegParams;
|
|
60
62
|
}): Promise<CreateOrderResponse>;
|
|
@@ -90,6 +92,8 @@ export interface TradingAPI extends BaseAPI {
|
|
|
90
92
|
* replacement re-states it and inherits nothing from the original order.
|
|
91
93
|
*/
|
|
92
94
|
clientOrderId?: string;
|
|
95
|
+
/** The SDK generates a key once per call when omitted. Supply the same key to retry a logical order within 24 hours. */
|
|
96
|
+
idempotencyKey?: string;
|
|
93
97
|
takeProfit?: ParentTpSlLegParams;
|
|
94
98
|
stopLoss?: ParentTpSlLegParams;
|
|
95
99
|
}): Promise<CreateOrderResponse>;
|
|
@@ -385,6 +385,8 @@ export interface BatchCreateOrderParams {
|
|
|
385
385
|
* execute a second time.
|
|
386
386
|
*/
|
|
387
387
|
clientOrderId?: string;
|
|
388
|
+
/** The SDK generates a key once per item when omitted. Supply the same key for batch or single-create retries within 24 hours. */
|
|
389
|
+
idempotencyKey?: string;
|
|
388
390
|
}
|
|
389
391
|
/**
|
|
390
392
|
* Parameters for a single order in a batch replace request
|
|
@@ -38,7 +38,13 @@ export declare const TransferCollateralToParentMarginAccountSchema: z.ZodObject<
|
|
|
38
38
|
}, z.core.$strip>;
|
|
39
39
|
}, z.core.$strip>;
|
|
40
40
|
export declare const TransferCollateralToRiskBucketSchema: z.ZodObject<{
|
|
41
|
-
request: z.
|
|
41
|
+
request: z.ZodPipe<z.ZodObject<{
|
|
42
|
+
marginMode: z.ZodOptional<z.ZodEnum<{
|
|
43
|
+
ISOLATED: "ISOLATED";
|
|
44
|
+
CROSS: "CROSS";
|
|
45
|
+
}>>;
|
|
46
|
+
selectedTradingPairIds: z.ZodOptional<z.ZodUnknown>;
|
|
47
|
+
}, z.core.$loose>, z.ZodUnion<readonly [z.ZodObject<{
|
|
42
48
|
asset: z.ZodString;
|
|
43
49
|
amount: z.ZodString;
|
|
44
50
|
tradingPairId: z.ZodUUID;
|
|
@@ -50,10 +56,10 @@ export declare const TransferCollateralToRiskBucketSchema: z.ZodObject<{
|
|
|
50
56
|
asset: z.ZodString;
|
|
51
57
|
amount: z.ZodString;
|
|
52
58
|
marginMode: z.ZodLiteral<"CROSS">;
|
|
53
|
-
selectedTradingPairIds: z.
|
|
59
|
+
selectedTradingPairIds: z.ZodOptional<z.ZodNever>;
|
|
54
60
|
strategyKey: z.ZodOptional<z.ZodNever>;
|
|
55
61
|
tradingPairId: z.ZodOptional<z.ZodNever>;
|
|
56
|
-
}, z.core.$strict>]
|
|
62
|
+
}, z.core.$strict>]>>;
|
|
57
63
|
}, z.core.$strip>;
|
|
58
64
|
export declare const TransferCollateralFromParentMarginAccountSchema: z.ZodObject<{
|
|
59
65
|
request: z.ZodObject<{
|
|
@@ -56,12 +56,22 @@ const IsolatedRiskBucketRequestSchema = RiskBucketRequestSchema.extend({
|
|
|
56
56
|
// stays strict-rejected (no per-position margin to commit to).
|
|
57
57
|
applyToPositionMargin: z.boolean().optional(),
|
|
58
58
|
});
|
|
59
|
+
// Simulation still declares the scope it wants previewed: a preview of a
|
|
60
|
+
// bucket that may not exist yet has nothing recorded to read from.
|
|
59
61
|
const CrossRiskBucketScopeSchema = z.object({
|
|
60
62
|
marginMode: z.literal("CROSS"),
|
|
61
63
|
selectedTradingPairIds: SelectedCrossTradingPairIdsSchema,
|
|
62
64
|
strategyKey: z.never().optional(),
|
|
63
65
|
});
|
|
64
|
-
|
|
66
|
+
// A cross transfer-in names no pairs. Cross scope is derived from trading, so
|
|
67
|
+
// funding has nothing to declare; `selectedTradingPairIds` used to REPLACE the
|
|
68
|
+
// scope on every top-up (silently evicting any flat pair a partial list
|
|
69
|
+
// forgot) and is now ignored by the server. Rejected here so the caller learns
|
|
70
|
+
// it does nothing rather than believing it took effect.
|
|
71
|
+
const CrossRiskBucketRequestSchema = z.object({
|
|
72
|
+
marginMode: z.literal("CROSS"),
|
|
73
|
+
selectedTradingPairIds: z.never().optional(),
|
|
74
|
+
strategyKey: z.never().optional(),
|
|
65
75
|
tradingPairId: z.never().optional(),
|
|
66
76
|
});
|
|
67
77
|
export const TransferCollateralSchema = z.object({
|
|
@@ -71,11 +81,29 @@ export const TransferCollateralSchema = z.object({
|
|
|
71
81
|
export const TransferCollateralToParentMarginAccountSchema = z.object({
|
|
72
82
|
request: ParentMarginAccountCollateralRequestSchema,
|
|
73
83
|
});
|
|
84
|
+
// Named ahead of the union: a union of two strict members collapses every
|
|
85
|
+
// mismatch into a single "Invalid input" on `request`, which would hide the one
|
|
86
|
+
// mistake this schema most needs to name.
|
|
87
|
+
const CrossTransferNamesNoPairsSchema = z
|
|
88
|
+
.object({
|
|
89
|
+
marginMode: z.enum(["ISOLATED", "CROSS"]).optional(),
|
|
90
|
+
selectedTradingPairIds: z.unknown().optional(),
|
|
91
|
+
})
|
|
92
|
+
.loose()
|
|
93
|
+
.superRefine((request, ctx) => {
|
|
94
|
+
if (request.marginMode === "CROSS" && request.selectedTradingPairIds !== undefined) {
|
|
95
|
+
ctx.addIssue({
|
|
96
|
+
code: "custom",
|
|
97
|
+
path: ["selectedTradingPairIds"],
|
|
98
|
+
message: "selectedTradingPairIds is not accepted on a CROSS transfer: cross scope is derived from trading, so a funding call has nothing to declare",
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
});
|
|
74
102
|
export const TransferCollateralToRiskBucketSchema = z.object({
|
|
75
|
-
request: z.union([
|
|
103
|
+
request: CrossTransferNamesNoPairsSchema.pipe(z.union([
|
|
76
104
|
ParentMarginAccountCollateralRequestSchema.merge(IsolatedRiskBucketRequestSchema).strict(),
|
|
77
105
|
ParentMarginAccountCollateralRequestSchema.merge(CrossRiskBucketRequestSchema).strict(),
|
|
78
|
-
]),
|
|
106
|
+
])),
|
|
79
107
|
});
|
|
80
108
|
export const TransferCollateralFromParentMarginAccountSchema = z.object({
|
|
81
109
|
request: ParentMarginAccountCollateralRequestSchema,
|
|
@@ -88,6 +88,7 @@ export declare const ParentTpSlLegSchema: z.ZodObject<{
|
|
|
88
88
|
/**
|
|
89
89
|
* Place Limit Order validation schema
|
|
90
90
|
*/
|
|
91
|
+
export declare const OrderIdempotencyKeySchema: z.ZodString;
|
|
91
92
|
export declare const PlaceLimitOrderSchema: z.ZodObject<{
|
|
92
93
|
tradingPairId: z.ZodUUID;
|
|
93
94
|
side: z.ZodEnum<{
|
|
@@ -97,6 +98,7 @@ export declare const PlaceLimitOrderSchema: z.ZodObject<{
|
|
|
97
98
|
quantity: z.ZodString;
|
|
98
99
|
price: z.ZodString;
|
|
99
100
|
options: z.ZodOptional<z.ZodObject<{
|
|
101
|
+
idempotencyKey: z.ZodOptional<z.ZodString>;
|
|
100
102
|
tradingMode: z.ZodOptional<z.ZodEnum<{
|
|
101
103
|
SPOT: "SPOT";
|
|
102
104
|
MARGIN: "MARGIN";
|
|
@@ -169,6 +171,7 @@ export declare const PlaceMarketOrderSchema: z.ZodObject<{
|
|
|
169
171
|
}>;
|
|
170
172
|
quantity: z.ZodString;
|
|
171
173
|
options: z.ZodOptional<z.ZodObject<{
|
|
174
|
+
idempotencyKey: z.ZodOptional<z.ZodString>;
|
|
172
175
|
tradingMode: z.ZodOptional<z.ZodEnum<{
|
|
173
176
|
SPOT: "SPOT";
|
|
174
177
|
MARGIN: "MARGIN";
|
|
@@ -405,6 +408,7 @@ export declare const BatchCreateOrderItemSchema: z.ZodObject<{
|
|
|
405
408
|
}>;
|
|
406
409
|
price: z.ZodOptional<z.ZodString>;
|
|
407
410
|
quantity: z.ZodString;
|
|
411
|
+
idempotencyKey: z.ZodOptional<z.ZodString>;
|
|
408
412
|
tradingMode: z.ZodOptional<z.ZodEnum<{
|
|
409
413
|
SPOT: "SPOT";
|
|
410
414
|
MARGIN: "MARGIN";
|
|
@@ -458,6 +462,7 @@ export declare const BatchCreateOrdersSchema: z.ZodObject<{
|
|
|
458
462
|
}>;
|
|
459
463
|
price: z.ZodOptional<z.ZodString>;
|
|
460
464
|
quantity: z.ZodString;
|
|
465
|
+
idempotencyKey: z.ZodOptional<z.ZodString>;
|
|
461
466
|
tradingMode: z.ZodOptional<z.ZodEnum<{
|
|
462
467
|
SPOT: "SPOT";
|
|
463
468
|
MARGIN: "MARGIN";
|
|
@@ -126,6 +126,11 @@ const legacyPositionSideMatchesOrderSide = (side, positionSide) => positionSide
|
|
|
126
126
|
/**
|
|
127
127
|
* Place Limit Order validation schema
|
|
128
128
|
*/
|
|
129
|
+
export const OrderIdempotencyKeySchema = z
|
|
130
|
+
.string()
|
|
131
|
+
.min(1)
|
|
132
|
+
.max(64)
|
|
133
|
+
.regex(/^[A-Za-z0-9._:-]+$/, "idempotencyKey must contain only letters, digits, or . _ : -");
|
|
129
134
|
export const PlaceLimitOrderSchema = z
|
|
130
135
|
.object({
|
|
131
136
|
tradingPairId: UUIDSchema,
|
|
@@ -134,6 +139,7 @@ export const PlaceLimitOrderSchema = z
|
|
|
134
139
|
price: PositiveDecimalStringSchema,
|
|
135
140
|
options: z
|
|
136
141
|
.object({
|
|
142
|
+
idempotencyKey: OrderIdempotencyKeySchema.optional(),
|
|
137
143
|
tradingMode: TradingModeSchema.optional(),
|
|
138
144
|
useMasterBalance: z.boolean().optional(),
|
|
139
145
|
expirationDate: ISO8601DateSchema.optional(),
|
|
@@ -214,6 +220,7 @@ export const PlaceMarketOrderSchema = z
|
|
|
214
220
|
quantity: PositiveDecimalStringSchema,
|
|
215
221
|
options: z
|
|
216
222
|
.object({
|
|
223
|
+
idempotencyKey: OrderIdempotencyKeySchema.optional(),
|
|
217
224
|
tradingMode: TradingModeSchema.optional(),
|
|
218
225
|
slippageTolerance: SlippageToleranceSchema,
|
|
219
226
|
marginAccountId: UUIDSchema.optional(),
|
|
@@ -508,6 +515,7 @@ export const BatchCreateOrderItemSchema = z
|
|
|
508
515
|
side: OrderSideSchema,
|
|
509
516
|
price: PositiveDecimalStringSchema.optional(),
|
|
510
517
|
quantity: PositiveDecimalStringSchema,
|
|
518
|
+
idempotencyKey: OrderIdempotencyKeySchema.optional(),
|
|
511
519
|
tradingMode: TradingModeSchema.optional(),
|
|
512
520
|
slippageTolerance: SlippageToleranceSchema,
|
|
513
521
|
useMasterBalance: z.boolean().optional(),
|
|
@@ -7,13 +7,53 @@
|
|
|
7
7
|
* surface — the channel-coverage lock in
|
|
8
8
|
* `tests/websocket/channel-coverage.test.ts` parses this file as the source
|
|
9
9
|
* of truth for the SDK's channel surface.
|
|
10
|
+
*
|
|
11
|
+
* ## Subscribe-time snapshots
|
|
12
|
+
*
|
|
13
|
+
* Every subscription whose channel has a server-side baseline takes an
|
|
14
|
+
* optional trailing `onSnapshot`. It receives that channel's COMPLETE current
|
|
15
|
+
* state as one array, once, before the first live event — so a consumer can
|
|
16
|
+
* seed state from the socket instead of a REST read, and replace it wholesale
|
|
17
|
+
* after a reconnect.
|
|
18
|
+
*
|
|
19
|
+
* The argument is deliberately trailing and optional on every method: adding a
|
|
20
|
+
* required parameter, or inserting one ahead of an existing optional filter,
|
|
21
|
+
* would break every existing call site.
|
|
22
|
+
*
|
|
23
|
+
* Snapshot rows go to `onSnapshot` and nowhere else. They are the channel's
|
|
24
|
+
* terminal-state payload rather than its event envelope (see
|
|
25
|
+
* {@link SnapshotHandler}), so a consumer that reduced them through the event
|
|
26
|
+
* handler too would apply the same baseline twice.
|
|
27
|
+
*
|
|
28
|
+
* Snapshot frames are routed by the FULL canonical channel string, unlike live
|
|
29
|
+
* events, which are prefix-matched. That is what keeps two pair-scoped
|
|
30
|
+
* subscriptions' baselines on their own callbacks.
|
|
31
|
+
*
|
|
32
|
+
* **One baseline per wire subscription, not per call.** The client sends one
|
|
33
|
+
* `Subscribe` for a channel however many local handlers it has, and the server
|
|
34
|
+
* snapshots only genuinely new subscriptions — so on a channel this client
|
|
35
|
+
* already holds, a second subscriber's `onSnapshot` is not invoked until the
|
|
36
|
+
* next reconnect resubscribes. `instruments` is the exception: it caches its
|
|
37
|
+
* baseline locally and replays it to a late subscriber. The other channels
|
|
38
|
+
* cannot reuse that cache — `orders` snapshot rows are not the shape its live
|
|
39
|
+
* events carry, so there is nothing to keep the cache current with — and a
|
|
40
|
+
* stale replayed baseline would be worse than none. Subscribe once per channel
|
|
41
|
+
* and fan out in application code (a React hook already does this), or read the
|
|
42
|
+
* baseline over REST for the extra consumer.
|
|
43
|
+
*
|
|
44
|
+
* Where the server has no snapshot arm for a channel yet, the callback is
|
|
45
|
+
* simply never invoked — a silent no-op, not an error. `orderbook`, `ohlcv`,
|
|
46
|
+
* `trades` and `movements` take no `onSnapshot` at all: they stream events
|
|
47
|
+
* rather than state, and the channel-coverage lock pins that classification
|
|
48
|
+
* against the server's own snapshot dispatch.
|
|
10
49
|
*/
|
|
11
50
|
import type { SessionCredentials } from "../auth/index";
|
|
12
51
|
import type { Interval } from "../market";
|
|
13
52
|
import type { TradingMode } from "../trading";
|
|
14
53
|
import type { WebSocketStatus } from "./base";
|
|
15
54
|
import type { OrderbookQuotationMode } from "./clients/orderbook-client";
|
|
16
|
-
import type { AccountEvent, ConditionalOrderEvent, InstrumentEvent, LiquidationEvent, MarketStatsAllEvent, MarketStatsEvent, OHLCVEvent, OHLCVPriceType, OrderbookEvent, OrderEvent, PositionEvent, TradeEvent, TwapOrderEvent, UserBalanceEvent, UserMovementEvent } from "./events";
|
|
55
|
+
import type { AccountEvent, AccountEventData, ConditionalOrderEvent, ConditionalOrderEventData, InstrumentEvent, InstrumentEventData, LiquidationEvent, LiquidationEventData, MarketStatsAllEvent, MarketStatsData, MarketStatsEvent, MarketStatsSummary, OHLCVEvent, OHLCVPriceType, OrderbookEvent, OrderEvent, PositionEvent, PositionEventData, TradeEvent, TwapOrderEvent, TwapOrderEventData, UserBalanceEvent, UserBalanceEventData, UserMovementEvent } from "./events";
|
|
56
|
+
import type { OrderSnapshotItem, SnapshotHandler } from "./snapshots";
|
|
17
57
|
export type MessageHandler<T> = (data: T) => void;
|
|
18
58
|
export interface MonacoWebSocket {
|
|
19
59
|
/** Connect to the WebSocket server */
|
|
@@ -26,8 +66,8 @@ export interface MonacoWebSocket {
|
|
|
26
66
|
getStatus: () => WebSocketStatus;
|
|
27
67
|
/** Set (or clear) the session keypair used to authenticate the connection */
|
|
28
68
|
setSessionKeypair: (credentials: SessionCredentials | undefined) => void;
|
|
29
|
-
/** Subscribe to order events (requires authentication) */
|
|
30
|
-
orders: (tradingPairId: string, tradingMode: TradingMode, handler: MessageHandler<OrderEvent>) => () => void;
|
|
69
|
+
/** Subscribe to order events (requires authentication); `onSnapshot` receives every resting order on the pair */
|
|
70
|
+
orders: (tradingPairId: string, tradingMode: TradingMode, handler: MessageHandler<OrderEvent>, onSnapshot?: SnapshotHandler<OrderSnapshotItem>) => () => void;
|
|
31
71
|
/** Subscribe to orderbook events (public) */
|
|
32
72
|
orderbook: (tradingPairId: string, tradingMode: TradingMode, magnitude: number, quotationMode: OrderbookQuotationMode, handler: MessageHandler<OrderbookEvent>) => () => void;
|
|
33
73
|
/** Subscribe to OHLCV candlestick events (public) */
|
|
@@ -36,24 +76,33 @@ export interface MonacoWebSocket {
|
|
|
36
76
|
trades: (tradingPairId: string, handler: MessageHandler<TradeEvent>) => () => void;
|
|
37
77
|
/** Subscribe to user movement events (requires authentication) */
|
|
38
78
|
movements: (handler: MessageHandler<UserMovementEvent>) => () => void;
|
|
39
|
-
/** Subscribe to user order events for all trading pairs (requires authentication) */
|
|
40
|
-
userOrders: (handler: MessageHandler<OrderEvent>) => () => void;
|
|
41
|
-
/** Subscribe to user balance events (requires authentication) */
|
|
42
|
-
balances: (handler: MessageHandler<UserBalanceEvent>) => () => void;
|
|
43
|
-
/** Subscribe to conditional TP/SL lifecycle events (requires authentication) */
|
|
44
|
-
conditionalOrders: (handler: MessageHandler<ConditionalOrderEvent>, tradingPairId?: string) => () => void;
|
|
79
|
+
/** Subscribe to user order events for all trading pairs (requires authentication); `onSnapshot` receives every resting order */
|
|
80
|
+
userOrders: (handler: MessageHandler<OrderEvent>, onSnapshot?: SnapshotHandler<OrderSnapshotItem>) => () => void;
|
|
81
|
+
/** Subscribe to user balance events (requires authentication); `onSnapshot` receives the balance of every asset held */
|
|
82
|
+
balances: (handler: MessageHandler<UserBalanceEvent>, onSnapshot?: SnapshotHandler<UserBalanceEventData>) => () => void;
|
|
83
|
+
/** Subscribe to conditional TP/SL lifecycle events (requires authentication); `onSnapshot` receives every live conditional order */
|
|
84
|
+
conditionalOrders: (handler: MessageHandler<ConditionalOrderEvent>, tradingPairId?: string, onSnapshot?: SnapshotHandler<ConditionalOrderEventData>) => () => void;
|
|
45
85
|
/** Subscribe to TWAP parent-order lifecycle events (requires authentication) */
|
|
46
|
-
twapOrders: (handler: MessageHandler<TwapOrderEvent>, tradingPairId?: string) => () => void;
|
|
47
|
-
/** Subscribe to position state updates (requires authentication); omit `tradingPairId` for all pairs */
|
|
48
|
-
positions: (handler: MessageHandler<PositionEvent>, tradingPairId?: string) => () => void;
|
|
86
|
+
twapOrders: (handler: MessageHandler<TwapOrderEvent>, tradingPairId?: string, onSnapshot?: SnapshotHandler<TwapOrderEventData>) => () => void;
|
|
87
|
+
/** Subscribe to position state updates (requires authentication); omit `tradingPairId` for all pairs. `onSnapshot` receives every open position */
|
|
88
|
+
positions: (handler: MessageHandler<PositionEvent>, tradingPairId?: string, onSnapshot?: SnapshotHandler<PositionEventData>) => () => void;
|
|
49
89
|
/** Subscribe to liquidation alerts (requires authentication); omit `tradingPairId` for all pairs */
|
|
50
|
-
liquidations: (handler: MessageHandler<LiquidationEvent>, tradingPairId?: string) => () => void;
|
|
90
|
+
liquidations: (handler: MessageHandler<LiquidationEvent>, tradingPairId?: string, onSnapshot?: SnapshotHandler<LiquidationEventData>) => () => void;
|
|
51
91
|
/** Subscribe to account-level margin health updates for the authenticated user (requires authentication) */
|
|
52
|
-
account: (handler: MessageHandler<AccountEvent>) => () => void;
|
|
53
|
-
/**
|
|
54
|
-
|
|
92
|
+
account: (handler: MessageHandler<AccountEvent>, onSnapshot?: SnapshotHandler<AccountEventData>) => () => void;
|
|
93
|
+
/**
|
|
94
|
+
* Subscribe to market lifecycle + config changes (public); omit
|
|
95
|
+
* `tradingPairId` for all markets. `onSnapshot` receives the full current
|
|
96
|
+
* config of every active market.
|
|
97
|
+
*
|
|
98
|
+
* Opting in also changes how the baseline is delivered: without
|
|
99
|
+
* `onSnapshot`, the snapshot is fanned out to `handler` as one synthetic
|
|
100
|
+
* per-market event (the channel's original behaviour, kept for source and
|
|
101
|
+
* behaviour compatibility). With it, the rows arrive only as the array.
|
|
102
|
+
*/
|
|
103
|
+
instruments: (handler: MessageHandler<InstrumentEvent>, tradingPairId?: string, onSnapshot?: SnapshotHandler<InstrumentEventData>) => () => void;
|
|
55
104
|
/** Subscribe to per-market statistics for one trading pair (public) */
|
|
56
|
-
marketStats: (tradingPairId: string, handler: MessageHandler<MarketStatsEvent>) => () => void;
|
|
105
|
+
marketStats: (tradingPairId: string, handler: MessageHandler<MarketStatsEvent>, onSnapshot?: SnapshotHandler<MarketStatsData>) => () => void;
|
|
57
106
|
/** Subscribe to the all-markets statistics summary (public) */
|
|
58
|
-
marketStatsAll: (handler: MessageHandler<MarketStatsAllEvent>) => () => void;
|
|
107
|
+
marketStatsAll: (handler: MessageHandler<MarketStatsAllEvent>, onSnapshot?: SnapshotHandler<MarketStatsSummary>) => () => void;
|
|
59
108
|
}
|
package/dist/websocket/client.js
CHANGED
|
@@ -7,4 +7,43 @@
|
|
|
7
7
|
* surface — the channel-coverage lock in
|
|
8
8
|
* `tests/websocket/channel-coverage.test.ts` parses this file as the source
|
|
9
9
|
* of truth for the SDK's channel surface.
|
|
10
|
+
*
|
|
11
|
+
* ## Subscribe-time snapshots
|
|
12
|
+
*
|
|
13
|
+
* Every subscription whose channel has a server-side baseline takes an
|
|
14
|
+
* optional trailing `onSnapshot`. It receives that channel's COMPLETE current
|
|
15
|
+
* state as one array, once, before the first live event — so a consumer can
|
|
16
|
+
* seed state from the socket instead of a REST read, and replace it wholesale
|
|
17
|
+
* after a reconnect.
|
|
18
|
+
*
|
|
19
|
+
* The argument is deliberately trailing and optional on every method: adding a
|
|
20
|
+
* required parameter, or inserting one ahead of an existing optional filter,
|
|
21
|
+
* would break every existing call site.
|
|
22
|
+
*
|
|
23
|
+
* Snapshot rows go to `onSnapshot` and nowhere else. They are the channel's
|
|
24
|
+
* terminal-state payload rather than its event envelope (see
|
|
25
|
+
* {@link SnapshotHandler}), so a consumer that reduced them through the event
|
|
26
|
+
* handler too would apply the same baseline twice.
|
|
27
|
+
*
|
|
28
|
+
* Snapshot frames are routed by the FULL canonical channel string, unlike live
|
|
29
|
+
* events, which are prefix-matched. That is what keeps two pair-scoped
|
|
30
|
+
* subscriptions' baselines on their own callbacks.
|
|
31
|
+
*
|
|
32
|
+
* **One baseline per wire subscription, not per call.** The client sends one
|
|
33
|
+
* `Subscribe` for a channel however many local handlers it has, and the server
|
|
34
|
+
* snapshots only genuinely new subscriptions — so on a channel this client
|
|
35
|
+
* already holds, a second subscriber's `onSnapshot` is not invoked until the
|
|
36
|
+
* next reconnect resubscribes. `instruments` is the exception: it caches its
|
|
37
|
+
* baseline locally and replays it to a late subscriber. The other channels
|
|
38
|
+
* cannot reuse that cache — `orders` snapshot rows are not the shape its live
|
|
39
|
+
* events carry, so there is nothing to keep the cache current with — and a
|
|
40
|
+
* stale replayed baseline would be worse than none. Subscribe once per channel
|
|
41
|
+
* and fan out in application code (a React hook already does this), or read the
|
|
42
|
+
* baseline over REST for the extra consumer.
|
|
43
|
+
*
|
|
44
|
+
* Where the server has no snapshot arm for a channel yet, the callback is
|
|
45
|
+
* simply never invoked — a silent no-op, not an error. `orderbook`, `ohlcv`,
|
|
46
|
+
* `trades` and `movements` take no `onSnapshot` at all: they stream events
|
|
47
|
+
* rather than state, and the channel-coverage lock pins that classification
|
|
48
|
+
* against the server's own snapshot dispatch.
|
|
10
49
|
*/
|
package/dist/websocket/index.js
CHANGED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subscribe-time WebSocket snapshot types.
|
|
3
|
+
*
|
|
4
|
+
* The server injects one `Snapshot` frame per subscription, after the
|
|
5
|
+
* `Subscribed` ack and before that subscription's first live diff. Its `data`
|
|
6
|
+
* is the channel's COMPLETE current state as a flat array — a consumer that
|
|
7
|
+
* applies it wholesale needs no REST baseline read for that channel.
|
|
8
|
+
*
|
|
9
|
+
* Two rules hold across every channel:
|
|
10
|
+
*
|
|
11
|
+
* - **A snapshot row is the channel's terminal-state payload, not its event
|
|
12
|
+
* envelope.** The live frame wraps its payload (`{ event_type, user_id, data }`
|
|
13
|
+
* for the authenticated channels); a snapshot row IS the payload, with no
|
|
14
|
+
* wrapper and no change metadata. That is why the rows are delivered to their
|
|
15
|
+
* own callback instead of the event handler: reducing both would apply the
|
|
16
|
+
* same state twice, in two different shapes.
|
|
17
|
+
* - **The row type is the channel's own `…EventData`**, so the baseline and the
|
|
18
|
+
* diffs that follow it describe state identically. `orders` is the one
|
|
19
|
+
* exception and has its own {@link OrderSnapshotItem}: a resting order carries
|
|
20
|
+
* fields no single order event does (`status` alongside the fill totals) and
|
|
21
|
+
* carries none of the change-only fill metadata.
|
|
22
|
+
*
|
|
23
|
+
* A channel whose server arm is not implemented yet simply never sends the
|
|
24
|
+
* frame, so its callback is never invoked. That is a silent no-op, never an
|
|
25
|
+
* error.
|
|
26
|
+
*/
|
|
27
|
+
import type { OrderSide, OrderType, TimeInForce, TradingMode } from "../trading";
|
|
28
|
+
/**
|
|
29
|
+
* Receives one channel's complete subscribe-time state.
|
|
30
|
+
*
|
|
31
|
+
* Invoked at most once per `Snapshot` frame, always with an array — an empty
|
|
32
|
+
* baseline arrives as `[]` rather than being skipped, so a consumer can tell
|
|
33
|
+
* "nothing is open" apart from "no baseline yet".
|
|
34
|
+
*
|
|
35
|
+
* Delivery is all-or-nothing: a frame with any unreadable row is withheld
|
|
36
|
+
* entirely rather than delivered short, because the array is contractually
|
|
37
|
+
* COMPLETE and a consumer that replaced state from a truncated one would delete
|
|
38
|
+
* whatever the unreadable row described.
|
|
39
|
+
*
|
|
40
|
+
* A frame is produced per WIRE subscription, so on a channel this client
|
|
41
|
+
* already holds a second subscriber's callback waits for the next reconnect;
|
|
42
|
+
* see `MonacoWebSocket` for the full rule.
|
|
43
|
+
*/
|
|
44
|
+
export type SnapshotHandler<T> = (items: T[]) => void;
|
|
45
|
+
/**
|
|
46
|
+
* One resting order in an `orders` channel snapshot.
|
|
47
|
+
*
|
|
48
|
+
* The server builds this to be field-compatible with the live order event's
|
|
49
|
+
* `data` — same names, same casing, decimals as strings — and injects the three
|
|
50
|
+
* identity fields the read model does not itself carry (`userId`,
|
|
51
|
+
* `applicationId`, and the resolved `tradingPair` symbol).
|
|
52
|
+
*
|
|
53
|
+
* The change-only fill metadata of an order EVENT is deliberately absent: a
|
|
54
|
+
* snapshot describes resting state, not a fill, so there is no `eventType`,
|
|
55
|
+
* `tradeId`, `executionPrice`, `lastFillQuantity`, `role`, `fee`, `feeRaw`,
|
|
56
|
+
* `tradesCount` or slippage. The cumulative `filledQuantity` /
|
|
57
|
+
* `averageFillPrice` totals are present, because those are state.
|
|
58
|
+
*
|
|
59
|
+
* Nullability mirrors the wire exactly. Every optional field below is a Rust
|
|
60
|
+
* `Option` serialized WITHOUT `skip_serializing_if`, so the key is always
|
|
61
|
+
* present and carries `null` when unset — hence `| null` rather than `?`.
|
|
62
|
+
* `clientOrderId` is the sole field the server omits outright, so it is the
|
|
63
|
+
* sole `?`.
|
|
64
|
+
*
|
|
65
|
+
* The value unions are widened (`Union | (string & {})`) for the same reason
|
|
66
|
+
* the order event's are: the parser hands an unrecognized value through rather
|
|
67
|
+
* than dropping the row, so a closed type would promise something the runtime
|
|
68
|
+
* does not honour.
|
|
69
|
+
*/
|
|
70
|
+
export interface OrderSnapshotItem {
|
|
71
|
+
/** Order identifier (UUID) */
|
|
72
|
+
orderId: string;
|
|
73
|
+
/** Owning user (UUID), taken from the authenticated session */
|
|
74
|
+
userId: string;
|
|
75
|
+
/** Owning application (UUID), taken from the authenticated session */
|
|
76
|
+
applicationId: string;
|
|
77
|
+
/** Trading pair identifier (UUID) */
|
|
78
|
+
tradingPairId: string;
|
|
79
|
+
/** Trading pair symbol, e.g. "BTC/USDC" */
|
|
80
|
+
tradingPair: string;
|
|
81
|
+
/** Trading mode (e.g. "SPOT", "MARGIN") */
|
|
82
|
+
tradingMode: TradingMode | (string & {});
|
|
83
|
+
/** Order side */
|
|
84
|
+
side: OrderSide | (string & {});
|
|
85
|
+
/** Order type */
|
|
86
|
+
orderType: OrderType | (string & {});
|
|
87
|
+
/** Limit price (decimal string); `null` for a market order */
|
|
88
|
+
price: string | null;
|
|
89
|
+
/** Order quantity (decimal string) */
|
|
90
|
+
quantity: string;
|
|
91
|
+
/** `quantity` in RAW (integer, base-unit) precision */
|
|
92
|
+
quantityRaw: string;
|
|
93
|
+
/** Cumulative quantity filled (decimal string) */
|
|
94
|
+
filledQuantity: string;
|
|
95
|
+
/** `filledQuantity` in RAW (integer, base-unit) precision */
|
|
96
|
+
filledQuantityRaw: string;
|
|
97
|
+
/** Quantity still resting (decimal string) */
|
|
98
|
+
remainingQuantity: string | null;
|
|
99
|
+
/** `remainingQuantity` in RAW (integer, base-unit) precision */
|
|
100
|
+
remainingQuantityRaw: string | null;
|
|
101
|
+
/** Order status; the snapshot carries only resting statuses */
|
|
102
|
+
status: string;
|
|
103
|
+
/** Time in force */
|
|
104
|
+
timeInForce: TimeInForce | (string & {}) | null;
|
|
105
|
+
/** Average fill price (decimal string); `null` before the first fill */
|
|
106
|
+
averageFillPrice: string | null;
|
|
107
|
+
/** Order creation timestamp (ISO 8601) */
|
|
108
|
+
createdAt: string;
|
|
109
|
+
/** Last update timestamp (ISO 8601) */
|
|
110
|
+
updatedAt: string | null;
|
|
111
|
+
/** Margin account backing a margin/perp order (UUID) */
|
|
112
|
+
marginAccountId: string | null;
|
|
113
|
+
/** Position the order is linked to (UUID) */
|
|
114
|
+
positionId: string | null;
|
|
115
|
+
/** Leverage for a margin/perp order (decimal string) */
|
|
116
|
+
leverage: string | null;
|
|
117
|
+
/** Whether the order can only reduce existing exposure */
|
|
118
|
+
reduceOnly: boolean;
|
|
119
|
+
/**
|
|
120
|
+
* Client-assigned correlation handle, carried so the baseline and the live
|
|
121
|
+
* events that follow it identify orders the same way. Omitted — not `null` —
|
|
122
|
+
* when the order carried none, matching the live event payload.
|
|
123
|
+
*/
|
|
124
|
+
clientOrderId?: string;
|
|
125
|
+
/**
|
|
126
|
+
* Sequencer step this order's state was last written by — the SAME counter
|
|
127
|
+
* the live order events and the REST endpoints carry (0XM-2440).
|
|
128
|
+
*
|
|
129
|
+
* The one field here that is not resting state. It is carried because a
|
|
130
|
+
* reconnecting client ranks this frame against the events it has already
|
|
131
|
+
* applied by comparing exactly this value, so the frame would be unusable
|
|
132
|
+
* for its own purpose without it. Compare with `>=`, not `>`: on the stream
|
|
133
|
+
* equal versions mean the same sequencer step rather than identical state,
|
|
134
|
+
* and the snapshot row is that step's final state.
|
|
135
|
+
*
|
|
136
|
+
* Omitted — not `null` — when unknown, which is what an order last written
|
|
137
|
+
* before the field existed reports. Absent means unknown, never zero.
|
|
138
|
+
*/
|
|
139
|
+
version?: number;
|
|
140
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subscribe-time WebSocket snapshot types.
|
|
3
|
+
*
|
|
4
|
+
* The server injects one `Snapshot` frame per subscription, after the
|
|
5
|
+
* `Subscribed` ack and before that subscription's first live diff. Its `data`
|
|
6
|
+
* is the channel's COMPLETE current state as a flat array — a consumer that
|
|
7
|
+
* applies it wholesale needs no REST baseline read for that channel.
|
|
8
|
+
*
|
|
9
|
+
* Two rules hold across every channel:
|
|
10
|
+
*
|
|
11
|
+
* - **A snapshot row is the channel's terminal-state payload, not its event
|
|
12
|
+
* envelope.** The live frame wraps its payload (`{ event_type, user_id, data }`
|
|
13
|
+
* for the authenticated channels); a snapshot row IS the payload, with no
|
|
14
|
+
* wrapper and no change metadata. That is why the rows are delivered to their
|
|
15
|
+
* own callback instead of the event handler: reducing both would apply the
|
|
16
|
+
* same state twice, in two different shapes.
|
|
17
|
+
* - **The row type is the channel's own `…EventData`**, so the baseline and the
|
|
18
|
+
* diffs that follow it describe state identically. `orders` is the one
|
|
19
|
+
* exception and has its own {@link OrderSnapshotItem}: a resting order carries
|
|
20
|
+
* fields no single order event does (`status` alongside the fill totals) and
|
|
21
|
+
* carries none of the change-only fill metadata.
|
|
22
|
+
*
|
|
23
|
+
* A channel whose server arm is not implemented yet simply never sends the
|
|
24
|
+
* frame, so its callback is never invoked. That is a silent no-op, never an
|
|
25
|
+
* error.
|
|
26
|
+
*/
|
package/dist/wire/schema.d.ts
CHANGED
|
@@ -2828,6 +2828,8 @@ export interface components {
|
|
|
2828
2828
|
* @example quote-btc-1130-a
|
|
2829
2829
|
*/
|
|
2830
2830
|
clientOrderId?: string | null;
|
|
2831
|
+
/** @description Optional submission identity, distinct from clientOrderId. Use 1-64 characters from [A-Za-z0-9._:-], without whitespace. Scoped to your authenticated user/subaccount and application, shared by create and batch-create items. Retrying the same key and normalized order payload within 24 hours of the original acceptance returns the original committed submission result, even after a fill or cancellation, without executing again. Different payload returns IDEMPOTENCY_KEY_CONFLICT (HTTP 409 / gRPC ALREADY_EXISTS; per-item error in batches). Validation failures before acceptance do not reserve the key. The window does not extend on retries; after it expires the key may execute a new order, so never retry an unresolved submission after 24 hours. Generate a fresh key for each intended new order and retain it across transport retries. Without a key, a timeout or 5xx leaves the outcome unknown and must not be blindly retried. */
|
|
2832
|
+
idempotencyKey?: string | null;
|
|
2831
2833
|
};
|
|
2832
2834
|
BatchCreateOrdersRequest: {
|
|
2833
2835
|
orders: components["schemas"]["BatchCreateOrderItem"][];
|
|
@@ -3340,6 +3342,8 @@ export interface components {
|
|
|
3340
3342
|
* @example quote-btc-1130-a
|
|
3341
3343
|
*/
|
|
3342
3344
|
clientOrderId?: string | null;
|
|
3345
|
+
/** @description Optional submission identity, distinct from clientOrderId. Use 1-64 characters from [A-Za-z0-9._:-], without whitespace. Scoped to your authenticated user/subaccount and application, shared by create and batch-create items. Retrying the same key and normalized order payload within 24 hours of the original acceptance returns the original committed submission result, even after a fill or cancellation, without executing again. Different payload returns IDEMPOTENCY_KEY_CONFLICT (HTTP 409 / gRPC ALREADY_EXISTS; per-item error in batches). Validation failures before acceptance do not reserve the key. The window does not extend on retries; after it expires the key may execute a new order, so never retry an unresolved submission after 24 hours. Generate a fresh key for each intended new order and retain it across transport retries. Without a key, a timeout or 5xx leaves the outcome unknown and must not be blindly retried. */
|
|
3346
|
+
idempotencyKey?: string | null;
|
|
3343
3347
|
};
|
|
3344
3348
|
CreateOrderResponse: {
|
|
3345
3349
|
/**
|
|
@@ -4816,10 +4820,22 @@ export interface components {
|
|
|
4816
4820
|
unrealizedPnl?: string | null;
|
|
4817
4821
|
realizedPnl?: string | null;
|
|
4818
4822
|
/**
|
|
4819
|
-
* @description Open rows:
|
|
4820
|
-
*
|
|
4821
|
-
*
|
|
4822
|
-
*
|
|
4823
|
+
* @description Open ISOLATED rows: the position's current backing — its risk bucket's
|
|
4824
|
+
* allocated collateral adjusted by settled realized PnL and funding paid,
|
|
4825
|
+
* net of collateral reserved for the bucket's open orders, clamped at zero
|
|
4826
|
+
* (0XM-2558). Partial closes and partial liquidations shrink the posted
|
|
4827
|
+
* margin pro-rata while the realized loss stays in the bucket, so this,
|
|
4828
|
+
* not the posted margin, is the unrealized-return denominator. Not a hard
|
|
4829
|
+
* -100% bound: the liquidation trigger and liquidation_price measure the
|
|
4830
|
+
* bucket's whole equity, order reserves included, so with a resting order
|
|
4831
|
+
* the return can pass -100% by that order's earmark before liquidation
|
|
4832
|
+
* lands; a mark can gap past the backing before the asynchronous
|
|
4833
|
+
* liquidation; a fully drained bucket serves "0". Served from the live risk
|
|
4834
|
+
* engine; when only persisted state is reachable the value is gross of
|
|
4835
|
+
* order reserves. Open CROSS rows fall back to the position's posted
|
|
4836
|
+
* margin. Terminal rows: total initial margin allocated across the
|
|
4837
|
+
* position's reducing executions when available — the margin basis for
|
|
4838
|
+
* lifetime realized return.
|
|
4823
4839
|
*/
|
|
4824
4840
|
isolatedMargin?: string | null;
|
|
4825
4841
|
leverage?: string | null;
|
|
@@ -6176,6 +6192,33 @@ export interface components {
|
|
|
6176
6192
|
* reconstructable.
|
|
6177
6193
|
*/
|
|
6178
6194
|
availableOrderCollateral?: string | null;
|
|
6195
|
+
/**
|
|
6196
|
+
* @description The mode this risk bucket is margined under. Always present: every row here is a risk bucket and its mode is a non-null column, unlike MarginAccountSummary.marginMode which is optional because that shape also models a parent row belonging to no bucket. Labels each row so bucket margin can be attributed to cross or isolated from this response alone, instead of resolving the opaque riskBucketId against the margin-accounts surface. It does NOT reconcile with the positions.cross / positions.isolated counts beside it: those are counted by a separate query over every margin account for the caller's user/application pair (these rows come from the single oldest, parent account), and they attribute a legacy position carrying no risk-bucket reference to CROSS whether or not a cross bucket row exists. Treat the counts as account-wide totals, not as a checksum over these rows.
|
|
6197
|
+
* @example CROSS
|
|
6198
|
+
* @enum {string}
|
|
6199
|
+
*/
|
|
6200
|
+
marginMode: "ISOLATED" | "CROSS";
|
|
6201
|
+
/**
|
|
6202
|
+
* Format: uuid
|
|
6203
|
+
* @description Trading pair UUID this bucket is scoped to. Present for ISOLATED buckets;
|
|
6204
|
+
* absent for CROSS, which spans the pairs selected into it and is scoped to
|
|
6205
|
+
* none of them individually — the same invariant the transfer-in endpoint
|
|
6206
|
+
* enforces by rejecting a `trading_pair_id` in CROSS mode. Read the cross
|
|
6207
|
+
* bucket's membership from `MarginAccountSummary.selected_trading_pair_ids`;
|
|
6208
|
+
* it is not carried here because it lives in a separate table and would cost
|
|
6209
|
+
* this endpoint an extra query per request.
|
|
6210
|
+
*
|
|
6211
|
+
* These labels do NOT make this response row-for-row joinable with the
|
|
6212
|
+
* margin-accounts surface on (mode, pair). That surface emits rows this one
|
|
6213
|
+
* has no counterpart for — a provisioned-but-unfunded auto bucket, and a
|
|
6214
|
+
* parent row with no mode at all — and on a persisted-fallback read (no live
|
|
6215
|
+
* risk engine snapshot) the two surfaces attribute a legacy position
|
|
6216
|
+
* carrying no risk-bucket reference to OPPOSITE buckets: this endpoint reads
|
|
6217
|
+
* it as cross, the margin-accounts summary as isolated on pair match. Use
|
|
6218
|
+
* these fields to label and group this response, not to cross-foot it
|
|
6219
|
+
* against another.
|
|
6220
|
+
*/
|
|
6221
|
+
tradingPairId?: string | null;
|
|
6179
6222
|
};
|
|
6180
6223
|
PortfolioSeriesWindow: {
|
|
6181
6224
|
/**
|
|
@@ -6255,10 +6298,22 @@ export interface components {
|
|
|
6255
6298
|
unrealizedPnl?: string | null;
|
|
6256
6299
|
realizedPnl?: string | null;
|
|
6257
6300
|
/**
|
|
6258
|
-
* @description Open rows:
|
|
6259
|
-
*
|
|
6260
|
-
*
|
|
6261
|
-
*
|
|
6301
|
+
* @description Open ISOLATED rows: the position's current backing — its risk bucket's
|
|
6302
|
+
* allocated collateral adjusted by settled realized PnL and funding paid,
|
|
6303
|
+
* net of collateral reserved for the bucket's open orders, clamped at zero
|
|
6304
|
+
* (0XM-2558). Partial closes and partial liquidations shrink the posted
|
|
6305
|
+
* margin pro-rata while the realized loss stays in the bucket, so this,
|
|
6306
|
+
* not the posted margin, is the unrealized-return denominator. Not a hard
|
|
6307
|
+
* -100% bound: the liquidation trigger and liquidation_price measure the
|
|
6308
|
+
* bucket's whole equity, order reserves included, so with a resting order
|
|
6309
|
+
* the return can pass -100% by that order's earmark before liquidation
|
|
6310
|
+
* lands; a mark can gap past the backing before the asynchronous
|
|
6311
|
+
* liquidation; a fully drained bucket serves "0". Served from the live risk
|
|
6312
|
+
* engine; when only persisted state is reachable the value is gross of
|
|
6313
|
+
* order reserves. Open CROSS rows fall back to the position's posted
|
|
6314
|
+
* margin. Terminal rows: total initial margin allocated across the
|
|
6315
|
+
* position's reducing executions when available — the margin basis for
|
|
6316
|
+
* lifetime realized return.
|
|
6262
6317
|
*/
|
|
6263
6318
|
isolatedMargin?: string | null;
|
|
6264
6319
|
leverage?: string | null;
|
|
@@ -6909,6 +6964,28 @@ export interface components {
|
|
|
6909
6964
|
initialMarginRequiredAfter?: string | null;
|
|
6910
6965
|
maintenanceMarginRequiredAfter?: string | null;
|
|
6911
6966
|
freeCollateralAfter?: string | null;
|
|
6967
|
+
/**
|
|
6968
|
+
* @description What this order pays in fees once its WHOLE size has executed, priced by
|
|
6969
|
+
* the role each part of it plays against the book right now: the taker rate
|
|
6970
|
+
* (plus the application's additional taker fee) on the quantity that would
|
|
6971
|
+
* cross immediately, and the maker rate on the quantity that would rest and
|
|
6972
|
+
* be filled later. Both rates are the caller's own tier-resolved rates. One
|
|
6973
|
+
* figure covers both cases — an order that crosses entirely, one that rests
|
|
6974
|
+
* entirely, and every split in between.
|
|
6975
|
+
*
|
|
6976
|
+
* Signed: NEGATIVE means a net rebate, which is the honest answer for a
|
|
6977
|
+
* resting order on a pair whose maker fee is negative. Populated even when
|
|
6978
|
+
* `accepted` is false, and populated for reduce-only orders — closing a
|
|
6979
|
+
* position pays fees like any other fill.
|
|
6980
|
+
*
|
|
6981
|
+
* It assumes the resting part eventually fills, so it states what the order
|
|
6982
|
+
* costs if it runs to completion, not a probability-weighted figure: cancel
|
|
6983
|
+
* before the remainder fills and only the crossing part was ever charged.
|
|
6984
|
+
*
|
|
6985
|
+
* ABSENT — never zero — when the engine could not price the order: it was
|
|
6986
|
+
* refused before it could be matched, or its resolved maker tier exceeds the
|
|
6987
|
+
* pair's cap. Absence means unknown, so do not render it as a free order.
|
|
6988
|
+
*/
|
|
6912
6989
|
estimatedFee?: string | null;
|
|
6913
6990
|
/**
|
|
6914
6991
|
* @description Estimated liquidation mark-price. In ISOLATED mode, this is the
|
|
@@ -7387,7 +7464,13 @@ export interface components {
|
|
|
7387
7464
|
riskBucketId?: string | null;
|
|
7388
7465
|
/** @description Present when collateral was allocated to a risk bucket. Values: ISOLATED, CROSS. */
|
|
7389
7466
|
marginMode?: string | null;
|
|
7390
|
-
/**
|
|
7467
|
+
/**
|
|
7468
|
+
* @description The cross bucket's recorded pair scope: what trading has recorded (a pair
|
|
7469
|
+
* joins when a cross order on it fills and leaves when its positions close),
|
|
7470
|
+
* plus any pair declared before scope became derived, until it trades and
|
|
7471
|
+
* its positions close. Only on cross risk-bucket transfers, and omitted
|
|
7472
|
+
* while empty — i.e. until a cross order on the bucket has filled.
|
|
7473
|
+
*/
|
|
7391
7474
|
selectedTradingPairIds?: string[] | null;
|
|
7392
7475
|
/**
|
|
7393
7476
|
* @description Whether the transfer was committed to a position's stored margin.
|
|
@@ -7414,9 +7497,17 @@ export interface components {
|
|
|
7414
7497
|
*/
|
|
7415
7498
|
tradingPairId?: string | null;
|
|
7416
7499
|
strategyKey?: string | null;
|
|
7417
|
-
/**
|
|
7500
|
+
/**
|
|
7501
|
+
* @description Risk bucket mode. Defaults to ISOLATED. Values: ISOLATED, CROSS. A CROSS
|
|
7502
|
+
* transfer names no pairs: the cross bucket's scope is derived from trading —
|
|
7503
|
+
* a pair joins when a cross order on it succeeds and leaves when its positions
|
|
7504
|
+
* close — so funding the bucket has nothing to declare.
|
|
7505
|
+
*/
|
|
7418
7506
|
marginMode?: string | null;
|
|
7419
|
-
/**
|
|
7507
|
+
/**
|
|
7508
|
+
* @deprecated
|
|
7509
|
+
* @description Deprecated: accepted and ignored. Cross scope is derived from trading (a pair joins the cross bucket when a cross order on it succeeds and leaves when its positions close), so a cross transfer-in has nothing to declare and can no longer replace the scope. Rejected for ISOLATED, as before. Read the current scope from the cross bucket's row in the margin-accounts list or from this response's selectedTradingPairIds; the parent row carries no scope. Pairs declared before scope became derived stay recorded until they trade and their positions close.
|
|
7510
|
+
*/
|
|
7420
7511
|
selectedTradingPairIds?: string[] | null;
|
|
7421
7512
|
/**
|
|
7422
7513
|
* @description What the transferred collateral becomes when the ISOLATED bucket holds an
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@0xmonaco/types",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.53",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"homepage": "https://docs.0xmonaco.com/sdk/typescript",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"lint": "biome lint ."
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@0xmonaco/contracts": "1.0.
|
|
19
|
+
"@0xmonaco/contracts": "1.0.53",
|
|
20
20
|
"zod": "^4.1.12"
|
|
21
21
|
},
|
|
22
22
|
"peerDependencies": {
|