@0xmonaco/core 1.0.88 → 1.0.91
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/api/base.d.ts +20 -1
- package/dist/api/base.js +115 -3
- package/dist/api/buildercodes/api.d.ts +2 -1
- package/dist/api/buildercodes/api.js +2 -1
- package/dist/api/margin-accounts/api.d.ts +6 -2
- package/dist/api/margin-accounts/api.js +14 -6
- package/dist/api/market/api.d.ts +5 -1
- package/dist/api/market/api.js +16 -0
- package/dist/api/perp/routes.d.ts +22 -0
- package/dist/api/perp/routes.js +6 -0
- package/dist/api/profile/api.d.ts +4 -2
- package/dist/api/profile/api.js +10 -2
- package/dist/api/sweeper/api.d.ts +28 -1
- package/dist/api/sweeper/api.js +46 -0
- package/dist/api/trading/api.d.ts +11 -3
- package/dist/api/trading/api.js +16 -9
- package/dist/api/websocket/websocket.js +42 -0
- package/dist/coverage.d.ts +6 -0
- package/dist/coverage.js +6 -0
- package/dist/sdk.js +4 -5
- package/package.json +3 -3
package/dist/api/base.d.ts
CHANGED
|
@@ -82,6 +82,7 @@ export declare abstract class BaseAPI {
|
|
|
82
82
|
*
|
|
83
83
|
* @param endpoint - The API endpoint to call (should start with /)
|
|
84
84
|
* @param options - Request options (method, body, headers, etc.)
|
|
85
|
+
* @param resendDeadline - Epoch ms after which a clock-skew 401 is returned instead of re-signed
|
|
85
86
|
* @returns Promise resolving to the response data
|
|
86
87
|
* @throws {APIError} When access token is not set or API request fails
|
|
87
88
|
*
|
|
@@ -100,7 +101,25 @@ export declare abstract class BaseAPI {
|
|
|
100
101
|
* );
|
|
101
102
|
* ```
|
|
102
103
|
*/
|
|
103
|
-
protected makeAuthenticatedRequest<T>(endpoint: string, options?: RequestInit): Promise<T>;
|
|
104
|
+
protected makeAuthenticatedRequest<T>(endpoint: string, options?: RequestInit, resendDeadline?: number): Promise<T>;
|
|
105
|
+
/**
|
|
106
|
+
* Sends a keyed submission, re-sending the identical body while its outcome
|
|
107
|
+
* is unknown (network failure or a 5xx), for at most `maxRetries` extra
|
|
108
|
+
* attempts with exponential backoff.
|
|
109
|
+
*
|
|
110
|
+
* Only safe for a body that carries an `idempotencyKey`: the server replays
|
|
111
|
+
* the original result for a repeated key instead of executing again. A
|
|
112
|
+
* maintenance `OPERATIONS_BLOCKED` refusal and every 4xx are definitive and
|
|
113
|
+
* returned at once. A `Retry-After` beyond {@link MAX_SUBMISSION_RETRY_DELAY_MS},
|
|
114
|
+
* a resend later than {@link MAX_SUBMISSION_RETRY_WINDOW_MS} after the first
|
|
115
|
+
* send, or a session change during backoff also stops the loop: keys are
|
|
116
|
+
* scoped per account, so a resend signed by another session would be a new order.
|
|
117
|
+
*
|
|
118
|
+
* @throws {APIError} The last failure, naming the key to reuse, when every attempt is ambiguous
|
|
119
|
+
*/
|
|
120
|
+
protected makeKeyedSubmission<T>(endpoint: string, options: RequestInit & {
|
|
121
|
+
body: string;
|
|
122
|
+
}): Promise<T>;
|
|
104
123
|
/**
|
|
105
124
|
* Compute the per-request ed25519 signature headers.
|
|
106
125
|
*
|
package/dist/api/base.js
CHANGED
|
@@ -37,6 +37,56 @@ import { CLOCK_CORRECTION_THRESHOLD_MS, ServerClock } from "../utils/server-cloc
|
|
|
37
37
|
* only takes effect in server runtimes (Node/undici, Bun, Deno).
|
|
38
38
|
*/
|
|
39
39
|
const SDK_USER_AGENT = "@0xmonaco/core";
|
|
40
|
+
/** Longest server-requested wait a keyed submission retry will honour. */
|
|
41
|
+
const MAX_SUBMISSION_RETRY_DELAY_MS = 5000;
|
|
42
|
+
/**
|
|
43
|
+
* Keyed submission retries stop this long after the first send, far inside
|
|
44
|
+
* the server's 15-minute key window even if a suspended tab stretches a wait.
|
|
45
|
+
*/
|
|
46
|
+
const MAX_SUBMISSION_RETRY_WINDOW_MS = 60_000;
|
|
47
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
48
|
+
/**
|
|
49
|
+
* True when a submission may or may not have been applied: no response came
|
|
50
|
+
* back at all, a 2xx body could not be read, or the server answered 5xx.
|
|
51
|
+
* Maintenance (`OPERATIONS_BLOCKED`) is a deliberate refusal before the book,
|
|
52
|
+
* not an unknown outcome.
|
|
53
|
+
*/
|
|
54
|
+
function isUnknownSubmissionOutcome(error) {
|
|
55
|
+
if (!(error instanceof APIError))
|
|
56
|
+
return false;
|
|
57
|
+
if (error.statusCode === undefined)
|
|
58
|
+
return error.cause !== undefined;
|
|
59
|
+
if (error.statusCode >= StatusCodes.OK && error.statusCode < StatusCodes.MULTIPLE_CHOICES)
|
|
60
|
+
return error.cause !== undefined;
|
|
61
|
+
if (error.statusCode < StatusCodes.INTERNAL_SERVER_ERROR)
|
|
62
|
+
return false;
|
|
63
|
+
const body = error.responseBody;
|
|
64
|
+
return !(body && typeof body === "object" && body.error === "OPERATIONS_BLOCKED");
|
|
65
|
+
}
|
|
66
|
+
function hasIdempotencyKey(body) {
|
|
67
|
+
try {
|
|
68
|
+
const key = JSON.parse(body)?.idempotencyKey;
|
|
69
|
+
return typeof key === "string" && key.length > 0;
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function unresolvedSubmissionError(last, attempts, reason, cause = last) {
|
|
76
|
+
const key = last.requestBody?.idempotencyKey;
|
|
77
|
+
const stopped = reason ? ` (stopped: ${reason})` : "";
|
|
78
|
+
return new APIError(`Submission outcome unknown after ${attempts} attempts${stopped}: ${last.message}. Retry with idempotencyKey ${String(key)} and the same payload within 15 minutes of the first attempt, under the same account; a new key can execute again.`, {
|
|
79
|
+
endpoint: last.endpoint,
|
|
80
|
+
// A 2xx whose body never arrived is no answer at all: report no status
|
|
81
|
+
// so callers branching on it treat the outcome as unknown.
|
|
82
|
+
statusCode: last.statusCode !== undefined && last.statusCode < StatusCodes.MULTIPLE_CHOICES ? undefined : last.statusCode,
|
|
83
|
+
responseBody: last.responseBody,
|
|
84
|
+
cause,
|
|
85
|
+
requestBody: last.requestBody,
|
|
86
|
+
requestId: last.requestId,
|
|
87
|
+
retryAfter: last.retryAfter,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
40
90
|
export class BaseAPI {
|
|
41
91
|
apiUrl;
|
|
42
92
|
/** Active session keypair (raw bytes) used to sign authenticated requests. */
|
|
@@ -260,6 +310,7 @@ export class BaseAPI {
|
|
|
260
310
|
*
|
|
261
311
|
* @param endpoint - The API endpoint to call (should start with /)
|
|
262
312
|
* @param options - Request options (method, body, headers, etc.)
|
|
313
|
+
* @param resendDeadline - Epoch ms after which a clock-skew 401 is returned instead of re-signed
|
|
263
314
|
* @returns Promise resolving to the response data
|
|
264
315
|
* @throws {APIError} When access token is not set or API request fails
|
|
265
316
|
*
|
|
@@ -278,7 +329,7 @@ export class BaseAPI {
|
|
|
278
329
|
* );
|
|
279
330
|
* ```
|
|
280
331
|
*/
|
|
281
|
-
async makeAuthenticatedRequest(endpoint, options = {}) {
|
|
332
|
+
async makeAuthenticatedRequest(endpoint, options = {}, resendDeadline) {
|
|
282
333
|
if (!this.sessionKeypair) {
|
|
283
334
|
throw new APIError("Session keypair not set. Authenticate (login) first.", {
|
|
284
335
|
endpoint: `${this.apiUrl}${endpoint}`,
|
|
@@ -305,19 +356,80 @@ export class BaseAPI {
|
|
|
305
356
|
},
|
|
306
357
|
}, requestBody);
|
|
307
358
|
// A 401 whose response moved the server clock was most likely a
|
|
308
|
-
// timestamp-skew rejection: re-sign once with the corrected time
|
|
359
|
+
// timestamp-skew rejection: re-sign once with the corrected time, but
|
|
360
|
+
// only under the session that signed the rejected request and before the
|
|
361
|
+
// caller's resend deadline.
|
|
309
362
|
const offsetBefore = this.serverClock.offsetMs;
|
|
363
|
+
const signer = this.sessionKeypair;
|
|
310
364
|
try {
|
|
311
365
|
return await send();
|
|
312
366
|
}
|
|
313
367
|
catch (error) {
|
|
314
368
|
const clockMoved = Math.abs(this.serverClock.offsetMs - offsetBefore) >= CLOCK_CORRECTION_THRESHOLD_MS;
|
|
315
|
-
if (error instanceof APIError &&
|
|
369
|
+
if (error instanceof APIError &&
|
|
370
|
+
error.statusCode === StatusCodes.UNAUTHORIZED &&
|
|
371
|
+
clockMoved &&
|
|
372
|
+
this.sessionKeypair === signer &&
|
|
373
|
+
(resendDeadline === undefined || Date.now() <= resendDeadline)) {
|
|
316
374
|
return send();
|
|
317
375
|
}
|
|
318
376
|
throw error;
|
|
319
377
|
}
|
|
320
378
|
}
|
|
379
|
+
/**
|
|
380
|
+
* Sends a keyed submission, re-sending the identical body while its outcome
|
|
381
|
+
* is unknown (network failure or a 5xx), for at most `maxRetries` extra
|
|
382
|
+
* attempts with exponential backoff.
|
|
383
|
+
*
|
|
384
|
+
* Only safe for a body that carries an `idempotencyKey`: the server replays
|
|
385
|
+
* the original result for a repeated key instead of executing again. A
|
|
386
|
+
* maintenance `OPERATIONS_BLOCKED` refusal and every 4xx are definitive and
|
|
387
|
+
* returned at once. A `Retry-After` beyond {@link MAX_SUBMISSION_RETRY_DELAY_MS},
|
|
388
|
+
* a resend later than {@link MAX_SUBMISSION_RETRY_WINDOW_MS} after the first
|
|
389
|
+
* send, or a session change during backoff also stops the loop: keys are
|
|
390
|
+
* scoped per account, so a resend signed by another session would be a new order.
|
|
391
|
+
*
|
|
392
|
+
* @throws {APIError} The last failure, naming the key to reuse, when every attempt is ambiguous
|
|
393
|
+
*/
|
|
394
|
+
async makeKeyedSubmission(endpoint, options) {
|
|
395
|
+
if (!hasIdempotencyKey(options.body))
|
|
396
|
+
throw new Error("Keyed submission requires a JSON body with an idempotencyKey");
|
|
397
|
+
const { maxRetries, baseDelayMs } = this.retryOptions;
|
|
398
|
+
const session = this.sessionKeypair;
|
|
399
|
+
const startedAt = Date.now();
|
|
400
|
+
let unknownOutcome;
|
|
401
|
+
for (let attempt = 0;; attempt++) {
|
|
402
|
+
try {
|
|
403
|
+
return await this.makeAuthenticatedRequest(endpoint, options, startedAt + MAX_SUBMISSION_RETRY_WINDOW_MS);
|
|
404
|
+
}
|
|
405
|
+
catch (error) {
|
|
406
|
+
const attempts = attempt + 1;
|
|
407
|
+
if (!isUnknownSubmissionOutcome(error)) {
|
|
408
|
+
// A refusal of a resend says nothing about the earlier attempt,
|
|
409
|
+
// which may have executed: report that outcome as still unknown.
|
|
410
|
+
if (!unknownOutcome)
|
|
411
|
+
throw error;
|
|
412
|
+
const refusal = error instanceof Error ? error : new Error(String(error));
|
|
413
|
+
throw unresolvedSubmissionError(unknownOutcome, attempts, `retry refused: ${refusal.message}`, refusal);
|
|
414
|
+
}
|
|
415
|
+
unknownOutcome = error;
|
|
416
|
+
const retryAfterMs = (error.retryAfter ?? 0) * 1000;
|
|
417
|
+
if (attempt >= maxRetries || retryAfterMs > MAX_SUBMISSION_RETRY_DELAY_MS) {
|
|
418
|
+
throw unresolvedSubmissionError(error, attempts);
|
|
419
|
+
}
|
|
420
|
+
const delayMs = Math.max(baseDelayMs * 2 ** attempt, retryAfterMs);
|
|
421
|
+
if (Date.now() + delayMs - startedAt > MAX_SUBMISSION_RETRY_WINDOW_MS) {
|
|
422
|
+
throw unresolvedSubmissionError(error, attempts, "retry window passed");
|
|
423
|
+
}
|
|
424
|
+
await sleep(delayMs);
|
|
425
|
+
if (Date.now() - startedAt > MAX_SUBMISSION_RETRY_WINDOW_MS) {
|
|
426
|
+
throw unresolvedSubmissionError(error, attempts, "retry window passed");
|
|
427
|
+
}
|
|
428
|
+
if (this.sessionKeypair !== session)
|
|
429
|
+
throw unresolvedSubmissionError(error, attempts, "session changed");
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
321
433
|
/**
|
|
322
434
|
* Compute the per-request ed25519 signature headers.
|
|
323
435
|
*
|
|
@@ -61,7 +61,8 @@ export declare class BuildercodesAPIImpl extends BaseAPI implements Buildercodes
|
|
|
61
61
|
* Read the authenticated wallet's available BuilderCodes reward balances.
|
|
62
62
|
*
|
|
63
63
|
* Current enrollment is not required: a former payout wallet can still see
|
|
64
|
-
* and claim
|
|
64
|
+
* and claim whatever remains in its bucket. Shortly after a payout-address
|
|
65
|
+
* change the old wallet's unclaimed balance moves to the new wallet.
|
|
65
66
|
*/
|
|
66
67
|
getRewardsBalance(): Promise<GetBuildercodeRewardsBalanceResponse>;
|
|
67
68
|
/**
|
|
@@ -173,7 +173,8 @@ export class BuildercodesAPIImpl extends BaseAPI {
|
|
|
173
173
|
* Read the authenticated wallet's available BuilderCodes reward balances.
|
|
174
174
|
*
|
|
175
175
|
* Current enrollment is not required: a former payout wallet can still see
|
|
176
|
-
* and claim
|
|
176
|
+
* and claim whatever remains in its bucket. Shortly after a payout-address
|
|
177
|
+
* change the old wallet's unclaimed balance moves to the new wallet.
|
|
177
178
|
*/
|
|
178
179
|
async getRewardsBalance() {
|
|
179
180
|
return this.makeAuthenticatedRequest("/api/v1/buildercodes/rewards/balance", { method: "GET" });
|
|
@@ -5,8 +5,12 @@ export declare class MarginAccountsAPIImpl extends BaseAPI implements MarginAcco
|
|
|
5
5
|
closeMarginSubAccount(marginAccountId: string): Promise<CloseMarginSubAccountResponse>;
|
|
6
6
|
getMarginAccountPnl(marginAccountId: string): Promise<MarginAccountPnl>;
|
|
7
7
|
transferMarginCollateral(request: TransferMarginCollateralRequest): Promise<TransferMarginCollateralResponse>;
|
|
8
|
-
transferCollateralToSubAccount(marginAccountId: string, amount: string
|
|
9
|
-
|
|
8
|
+
transferCollateralToSubAccount(marginAccountId: string, amount: string, options?: {
|
|
9
|
+
idempotencyKey?: string;
|
|
10
|
+
}): Promise<TransferMarginCollateralResponse>;
|
|
11
|
+
transferCollateralFromSubAccount(marginAccountId: string, amount: string, options?: {
|
|
12
|
+
idempotencyKey?: string;
|
|
13
|
+
}): Promise<TransferMarginCollateralResponse>;
|
|
10
14
|
listMarginAccounts(params?: ListMarginAccountsParams): Promise<ListMarginAccountsResponse>;
|
|
11
15
|
getMarginAccountSummary(marginAccountId: string, params?: GetMarginAccountSummaryParams): Promise<MarginAccountSummary>;
|
|
12
16
|
getParentMarginAccountSummary(params?: GetMarginAccountSummaryParams): Promise<MarginAccountSummary>;
|
|
@@ -29,21 +29,24 @@ export class MarginAccountsAPIImpl extends BaseAPI {
|
|
|
29
29
|
amount: request.amount,
|
|
30
30
|
from: request.from,
|
|
31
31
|
to: request.to,
|
|
32
|
+
idempotencyKey: request.idempotencyKey,
|
|
32
33
|
}),
|
|
33
34
|
});
|
|
34
35
|
}
|
|
35
|
-
async transferCollateralToSubAccount(marginAccountId, amount) {
|
|
36
|
-
|
|
36
|
+
async transferCollateralToSubAccount(marginAccountId, amount, options) {
|
|
37
|
+
const idempotencyKey = options?.idempotencyKey;
|
|
38
|
+
validate(SubAccountCollateralTransferSchema, { marginAccountId, amount, idempotencyKey });
|
|
37
39
|
return await this.makeAuthenticatedRequest(perpRoutes.marginAccounts.subAccountTransferIn(marginAccountId), {
|
|
38
40
|
method: "POST",
|
|
39
|
-
body: JSON.stringify({ amount }),
|
|
41
|
+
body: JSON.stringify({ amount, idempotencyKey }),
|
|
40
42
|
});
|
|
41
43
|
}
|
|
42
|
-
async transferCollateralFromSubAccount(marginAccountId, amount) {
|
|
43
|
-
|
|
44
|
+
async transferCollateralFromSubAccount(marginAccountId, amount, options) {
|
|
45
|
+
const idempotencyKey = options?.idempotencyKey;
|
|
46
|
+
validate(SubAccountCollateralTransferSchema, { marginAccountId, amount, idempotencyKey });
|
|
44
47
|
return await this.makeAuthenticatedRequest(perpRoutes.marginAccounts.subAccountTransferOut(marginAccountId), {
|
|
45
48
|
method: "POST",
|
|
46
|
-
body: JSON.stringify({ amount }),
|
|
49
|
+
body: JSON.stringify({ amount, idempotencyKey }),
|
|
47
50
|
});
|
|
48
51
|
}
|
|
49
52
|
async listMarginAccounts(params) {
|
|
@@ -90,6 +93,7 @@ export class MarginAccountsAPIImpl extends BaseAPI {
|
|
|
90
93
|
amount: request.amount,
|
|
91
94
|
tradingPairId: request.tradingPairId,
|
|
92
95
|
strategyKey: request.strategyKey,
|
|
96
|
+
idempotencyKey: request.idempotencyKey,
|
|
93
97
|
}),
|
|
94
98
|
});
|
|
95
99
|
}
|
|
@@ -100,6 +104,7 @@ export class MarginAccountsAPIImpl extends BaseAPI {
|
|
|
100
104
|
body: JSON.stringify({
|
|
101
105
|
asset: request.asset,
|
|
102
106
|
amount: request.amount,
|
|
107
|
+
idempotencyKey: request.idempotencyKey,
|
|
103
108
|
}),
|
|
104
109
|
});
|
|
105
110
|
}
|
|
@@ -121,6 +126,7 @@ export class MarginAccountsAPIImpl extends BaseAPI {
|
|
|
121
126
|
// the wire or the server applies its Adjust Margin default and every
|
|
122
127
|
// funding-loop top-up converts into initial margin requirement.
|
|
123
128
|
applyToPositionMargin: request.applyToPositionMargin,
|
|
129
|
+
idempotencyKey: request.idempotencyKey,
|
|
124
130
|
}),
|
|
125
131
|
});
|
|
126
132
|
}
|
|
@@ -134,6 +140,7 @@ export class MarginAccountsAPIImpl extends BaseAPI {
|
|
|
134
140
|
tradingPairId: request.tradingPairId,
|
|
135
141
|
strategyKey: request.strategyKey,
|
|
136
142
|
marginMode: request.marginMode,
|
|
143
|
+
idempotencyKey: request.idempotencyKey,
|
|
137
144
|
}),
|
|
138
145
|
});
|
|
139
146
|
}
|
|
@@ -144,6 +151,7 @@ export class MarginAccountsAPIImpl extends BaseAPI {
|
|
|
144
151
|
body: JSON.stringify({
|
|
145
152
|
asset: request.asset,
|
|
146
153
|
amount: request.amount,
|
|
154
|
+
idempotencyKey: request.idempotencyKey,
|
|
147
155
|
}),
|
|
148
156
|
});
|
|
149
157
|
}
|
package/dist/api/market/api.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Candlestick, FundingState, GetCandlesticksParams, GetScreenerParams, GetScreenerResponse, GetTradingPairsParams, GetTradingPairsResponse, IndexPrice, Interval, ListAllFundingHistoryParams, ListAllFundingHistoryResponse, ListFundingHistoryParams, ListFundingHistoryResponse, MarketAPI, MarketMetadata, MarketStats, MarkPrice, OpenInterest, PerpMarketConfig, PerpMarketSummary, TradingMode, TradingPair } from "@0xmonaco/types";
|
|
1
|
+
import type { Candlestick, FundingState, GetCandlesticksParams, GetLiquidationMetricsParams, GetScreenerParams, GetScreenerResponse, GetTradeFlowParams, GetTradingPairsParams, GetTradingPairsResponse, IndexPrice, Interval, LiquidationMetrics, ListAllFundingHistoryParams, ListAllFundingHistoryResponse, ListFundingHistoryParams, ListFundingHistoryResponse, ListLiquidationEventsParams, ListLiquidationEventsResponse, MarketAPI, MarketMetadata, MarketStats, MarkPrice, OpenInterest, PerpMarketConfig, PerpMarketSummary, TradeFlow, TraderMetrics, TradingMode, TradingPair } from "@0xmonaco/types";
|
|
2
2
|
import { BaseAPI } from "../base";
|
|
3
3
|
/**
|
|
4
4
|
* Market API Implementation
|
|
@@ -19,6 +19,10 @@ export declare class MarketAPIImpl extends BaseAPI implements MarketAPI {
|
|
|
19
19
|
listFundingHistory(tradingPairId: string, params?: ListFundingHistoryParams): Promise<ListFundingHistoryResponse>;
|
|
20
20
|
listAllFundingHistory(params?: ListAllFundingHistoryParams): Promise<ListAllFundingHistoryResponse>;
|
|
21
21
|
getOpenInterest(tradingPairId: string): Promise<OpenInterest>;
|
|
22
|
+
getTraderMetrics(tradingPairId: string): Promise<TraderMetrics>;
|
|
23
|
+
getTradeFlow(tradingPairId: string, params: GetTradeFlowParams): Promise<TradeFlow>;
|
|
24
|
+
listLiquidationEvents(tradingPairId: string, params?: ListLiquidationEventsParams): Promise<ListLiquidationEventsResponse>;
|
|
25
|
+
getLiquidationMetrics(tradingPairId: string, params: GetLiquidationMetricsParams): Promise<LiquidationMetrics>;
|
|
22
26
|
getScreener(params?: GetScreenerParams): Promise<GetScreenerResponse>;
|
|
23
27
|
getMarketStats(): Promise<MarketStats>;
|
|
24
28
|
}
|
package/dist/api/market/api.js
CHANGED
|
@@ -113,6 +113,22 @@ export class MarketAPIImpl extends BaseAPI {
|
|
|
113
113
|
validate(GetMarketMetadataSchema, { tradingPairId });
|
|
114
114
|
return await this.makePublicRequest(perpRoutes.market.getOpenInterest(tradingPairId));
|
|
115
115
|
}
|
|
116
|
+
async getTraderMetrics(tradingPairId) {
|
|
117
|
+
validate(GetMarketMetadataSchema, { tradingPairId });
|
|
118
|
+
return await this.makePublicRequest(perpRoutes.market.getTraderMetrics(tradingPairId));
|
|
119
|
+
}
|
|
120
|
+
async getTradeFlow(tradingPairId, params) {
|
|
121
|
+
validate(GetMarketMetadataSchema, { tradingPairId });
|
|
122
|
+
return await this.makePublicRequest(perpRoutes.market.getTradeFlow(tradingPairId, params));
|
|
123
|
+
}
|
|
124
|
+
async listLiquidationEvents(tradingPairId, params) {
|
|
125
|
+
validate(GetMarketMetadataSchema, { tradingPairId });
|
|
126
|
+
return await this.makePublicRequest(perpRoutes.market.listLiquidationEvents(tradingPairId, params));
|
|
127
|
+
}
|
|
128
|
+
async getLiquidationMetrics(tradingPairId, params) {
|
|
129
|
+
validate(GetMarketMetadataSchema, { tradingPairId });
|
|
130
|
+
return await this.makePublicRequest(perpRoutes.market.getLiquidationMetrics(tradingPairId, params));
|
|
131
|
+
}
|
|
116
132
|
async getScreener(params) {
|
|
117
133
|
return await this.makePublicRequest(perpRoutes.market.getScreener(params));
|
|
118
134
|
}
|
|
@@ -92,6 +92,23 @@ export declare const perpRoutes: {
|
|
|
92
92
|
orderBy?: string;
|
|
93
93
|
}) => string;
|
|
94
94
|
readonly getOpenInterest: (tradingPairId: string) => string;
|
|
95
|
+
readonly getTraderMetrics: (tradingPairId: string) => string;
|
|
96
|
+
readonly getTradeFlow: (tradingPairId: string, params: {
|
|
97
|
+
interval: string;
|
|
98
|
+
startTime: number;
|
|
99
|
+
endTime: number;
|
|
100
|
+
}) => string;
|
|
101
|
+
readonly listLiquidationEvents: (tradingPairId: string, params?: {
|
|
102
|
+
startTime?: number;
|
|
103
|
+
endTime?: number;
|
|
104
|
+
pageSize?: number;
|
|
105
|
+
pageToken?: string;
|
|
106
|
+
}) => string;
|
|
107
|
+
readonly getLiquidationMetrics: (tradingPairId: string, params: {
|
|
108
|
+
interval: string;
|
|
109
|
+
startTime: number;
|
|
110
|
+
endTime: number;
|
|
111
|
+
}) => string;
|
|
95
112
|
readonly getScreener: (params?: {
|
|
96
113
|
page?: number;
|
|
97
114
|
pageSize?: number;
|
|
@@ -175,6 +192,11 @@ export declare const perpRoutes: {
|
|
|
175
192
|
readonly sweeper: {
|
|
176
193
|
readonly register: () => string;
|
|
177
194
|
readonly chains: () => string;
|
|
195
|
+
readonly deposits: (txHash: string) => string;
|
|
196
|
+
readonly listDeposits: (params?: {
|
|
197
|
+
pageSize?: number;
|
|
198
|
+
pageToken?: string;
|
|
199
|
+
}) => string;
|
|
178
200
|
};
|
|
179
201
|
readonly whitelist: {
|
|
180
202
|
readonly submit: () => string;
|
package/dist/api/perp/routes.js
CHANGED
|
@@ -60,6 +60,10 @@ export const perpRoutes = {
|
|
|
60
60
|
listFundingHistory: (tradingPairId, params) => withQuery(`${API_V1}/market/pairs/${encodeSegment(tradingPairId)}/funding/history`, params),
|
|
61
61
|
listAllFundingHistory: (params) => withQuery(`${API_V1}/market/funding/history`, params),
|
|
62
62
|
getOpenInterest: (tradingPairId) => `${API_V1}/market/pairs/${encodeSegment(tradingPairId)}/open-interest`,
|
|
63
|
+
getTraderMetrics: (tradingPairId) => `${API_V1}/market/pairs/${encodeSegment(tradingPairId)}/trader-metrics`,
|
|
64
|
+
getTradeFlow: (tradingPairId, params) => withQuery(`${API_V1}/market/pairs/${encodeSegment(tradingPairId)}/trade-flow`, params),
|
|
65
|
+
listLiquidationEvents: (tradingPairId, params) => withQuery(`${API_V1}/market/pairs/${encodeSegment(tradingPairId)}/liquidation-events`, params),
|
|
66
|
+
getLiquidationMetrics: (tradingPairId, params) => withQuery(`${API_V1}/market/pairs/${encodeSegment(tradingPairId)}/liquidation-metrics`, params),
|
|
63
67
|
getScreener: (params) => withQuery(`${API_V1}/market/screener`, params),
|
|
64
68
|
getMarketStats: () => `${API_V1}/market/stats`,
|
|
65
69
|
},
|
|
@@ -91,6 +95,8 @@ export const perpRoutes = {
|
|
|
91
95
|
sweeper: {
|
|
92
96
|
register: () => `${API_V1}/sweeper/register`,
|
|
93
97
|
chains: () => `${API_V1}/sweeper/chains`,
|
|
98
|
+
deposits: (txHash) => `${API_V1}/sweeper/deposits/${encodeSegment(txHash)}`,
|
|
99
|
+
listDeposits: (params) => withQuery(`${API_V1}/sweeper/deposits`, params),
|
|
94
100
|
},
|
|
95
101
|
whitelist: {
|
|
96
102
|
submit: () => `${API_V1}/whitelist`,
|
|
@@ -200,14 +200,16 @@ export declare class ProfileAPIImpl extends BaseAPI implements ProfileAPI {
|
|
|
200
200
|
*
|
|
201
201
|
* An unfiltered response carries `total` and `totalPages`, bounded by the
|
|
202
202
|
* server count ceiling; `totalCapped` is `true` when more than that matched,
|
|
203
|
-
* so `total` is a lower bound. A response
|
|
204
|
-
*
|
|
203
|
+
* so `total` is a lower bound. A filtered response carries neither (counting
|
|
204
|
+
* one pair, account or order would read the user's whole trade history), nor
|
|
205
205
|
* does one whose count ran out of its server time budget: treat absent as
|
|
206
206
|
* unknown. Do not drive a paging loop off `total`; follow `nextPageToken`.
|
|
207
207
|
*
|
|
208
208
|
* @param params - Optional query parameters for pagination and filtering
|
|
209
209
|
* @param params.pageSize - Number of items per page (default: 20; up to 1000)
|
|
210
210
|
* @param params.tradingPairId - Filter by trading pair ID (UUID)
|
|
211
|
+
* @param params.marginAccountId - Filter by the margin account this user's side was placed from (UUID)
|
|
212
|
+
* @param params.orderId - Filter by the order that placed this user's side (UUID)
|
|
211
213
|
* @param params.pageToken - Pagination cursor: pass `""` to start a cursor walk from
|
|
212
214
|
* the newest row; pass a previous response's `nextPageToken` to resume. Omitting it
|
|
213
215
|
* starts the same walk. Every walk covers full trade history, hot and archived rows
|
package/dist/api/profile/api.js
CHANGED
|
@@ -261,14 +261,16 @@ export class ProfileAPIImpl extends BaseAPI {
|
|
|
261
261
|
*
|
|
262
262
|
* An unfiltered response carries `total` and `totalPages`, bounded by the
|
|
263
263
|
* server count ceiling; `totalCapped` is `true` when more than that matched,
|
|
264
|
-
* so `total` is a lower bound. A response
|
|
265
|
-
*
|
|
264
|
+
* so `total` is a lower bound. A filtered response carries neither (counting
|
|
265
|
+
* one pair, account or order would read the user's whole trade history), nor
|
|
266
266
|
* does one whose count ran out of its server time budget: treat absent as
|
|
267
267
|
* unknown. Do not drive a paging loop off `total`; follow `nextPageToken`.
|
|
268
268
|
*
|
|
269
269
|
* @param params - Optional query parameters for pagination and filtering
|
|
270
270
|
* @param params.pageSize - Number of items per page (default: 20; up to 1000)
|
|
271
271
|
* @param params.tradingPairId - Filter by trading pair ID (UUID)
|
|
272
|
+
* @param params.marginAccountId - Filter by the margin account this user's side was placed from (UUID)
|
|
273
|
+
* @param params.orderId - Filter by the order that placed this user's side (UUID)
|
|
272
274
|
* @param params.pageToken - Pagination cursor: pass `""` to start a cursor walk from
|
|
273
275
|
* the newest row; pass a previous response's `nextPageToken` to resume. Omitting it
|
|
274
276
|
* starts the same walk. Every walk covers full trade history, hot and archived rows
|
|
@@ -302,6 +304,12 @@ export class ProfileAPIImpl extends BaseAPI {
|
|
|
302
304
|
if (params?.tradingPairId !== undefined) {
|
|
303
305
|
searchParams.append("tradingPairId", params.tradingPairId);
|
|
304
306
|
}
|
|
307
|
+
if (params?.marginAccountId !== undefined) {
|
|
308
|
+
searchParams.append("marginAccountId", params.marginAccountId);
|
|
309
|
+
}
|
|
310
|
+
if (params?.orderId !== undefined) {
|
|
311
|
+
searchParams.append("orderId", params.orderId);
|
|
312
|
+
}
|
|
305
313
|
// One pagination mode. `pageToken` is sent even as the empty string — the
|
|
306
314
|
// server selects the walk by the token's PRESENCE, not its value — so it
|
|
307
315
|
// must not be dropped the way a falsy value usually would be.
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* const margin = await sdk.sweeper.register({ depositTarget: "margin" });
|
|
23
23
|
* ```
|
|
24
24
|
*/
|
|
25
|
-
import type { GetSweeperChainsResponse, RegisterSweeperRequest, RegisterSweeperResponse, SweeperAPI } from "@0xmonaco/types";
|
|
25
|
+
import type { GetSweeperChainsResponse, GetSweeperDepositStatusResponse, ListSweeperDepositsParams, ListSweeperDepositsResponse, RegisterSweeperRequest, RegisterSweeperResponse, SweeperAPI } from "@0xmonaco/types";
|
|
26
26
|
import { BaseAPI } from "../base";
|
|
27
27
|
export declare class SweeperAPIImpl extends BaseAPI implements SweeperAPI {
|
|
28
28
|
/**
|
|
@@ -63,4 +63,31 @@ export declare class SweeperAPIImpl extends BaseAPI implements SweeperAPI {
|
|
|
63
63
|
* @returns Promise resolving to the supported chain/asset listing
|
|
64
64
|
*/
|
|
65
65
|
getChains(): Promise<GetSweeperChainsResponse>;
|
|
66
|
+
/**
|
|
67
|
+
* Where the caller's deposits made by one transaction are, by the hash of
|
|
68
|
+
* the transaction that sent funds to the caller's deposit address (any
|
|
69
|
+
* supported chain). Requires authentication; only the session's own
|
|
70
|
+
* deposits are returned.
|
|
71
|
+
*
|
|
72
|
+
* Empty until the sweeper has indexed the transaction — poll until each
|
|
73
|
+
* deposit reads `DEPOSITED` (or `FAILED`).
|
|
74
|
+
*
|
|
75
|
+
* @param txHash - The deposit transaction's hash, 0x-prefixed 32-byte hex
|
|
76
|
+
* @returns Promise resolving to the transaction's deposits, in chain then
|
|
77
|
+
* log order
|
|
78
|
+
*/
|
|
79
|
+
getDepositStatus(txHash: string): Promise<GetSweeperDepositStatusResponse>;
|
|
80
|
+
/**
|
|
81
|
+
* The caller's sweeper deposits, newest recorded first, by cursor. Each
|
|
82
|
+
* entry is the same {@link SweeperDeposit} `getDepositStatus` returns; a
|
|
83
|
+
* swept CCTP deposit is listed once, by its source-chain transfer, and a
|
|
84
|
+
* burn made straight to the hub deposit address by its hub mint. Requires
|
|
85
|
+
* authentication; only the session's own deposits are returned.
|
|
86
|
+
*
|
|
87
|
+
* @param params - `pageSize` (1-100, default 20) and the previous page's
|
|
88
|
+
* `nextPageToken`
|
|
89
|
+
* @returns Promise resolving to one page and the cursor for the next (empty
|
|
90
|
+
* on the last page)
|
|
91
|
+
*/
|
|
92
|
+
listDeposits(params?: ListSweeperDepositsParams): Promise<ListSweeperDepositsResponse>;
|
|
66
93
|
}
|
package/dist/api/sweeper/api.js
CHANGED
|
@@ -101,4 +101,50 @@ export class SweeperAPIImpl extends BaseAPI {
|
|
|
101
101
|
method: "GET",
|
|
102
102
|
});
|
|
103
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Where the caller's deposits made by one transaction are, by the hash of
|
|
106
|
+
* the transaction that sent funds to the caller's deposit address (any
|
|
107
|
+
* supported chain). Requires authentication; only the session's own
|
|
108
|
+
* deposits are returned.
|
|
109
|
+
*
|
|
110
|
+
* Empty until the sweeper has indexed the transaction — poll until each
|
|
111
|
+
* deposit reads `DEPOSITED` (or `FAILED`).
|
|
112
|
+
*
|
|
113
|
+
* @param txHash - The deposit transaction's hash, 0x-prefixed 32-byte hex
|
|
114
|
+
* @returns Promise resolving to the transaction's deposits, in chain then
|
|
115
|
+
* log order
|
|
116
|
+
*/
|
|
117
|
+
async getDepositStatus(txHash) {
|
|
118
|
+
if (!TX_HASH_PATTERN.test(txHash)) {
|
|
119
|
+
throw new InvalidConfigError(`Invalid transaction hash: ${JSON.stringify(txHash)}. Expected a 0x-prefixed 32-byte hex hash.`);
|
|
120
|
+
}
|
|
121
|
+
return await this.makeAuthenticatedRequest(perpRoutes.sweeper.deposits(txHash), {
|
|
122
|
+
method: "GET",
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* The caller's sweeper deposits, newest recorded first, by cursor. Each
|
|
127
|
+
* entry is the same {@link SweeperDeposit} `getDepositStatus` returns; a
|
|
128
|
+
* swept CCTP deposit is listed once, by its source-chain transfer, and a
|
|
129
|
+
* burn made straight to the hub deposit address by its hub mint. Requires
|
|
130
|
+
* authentication; only the session's own deposits are returned.
|
|
131
|
+
*
|
|
132
|
+
* @param params - `pageSize` (1-100, default 20) and the previous page's
|
|
133
|
+
* `nextPageToken`
|
|
134
|
+
* @returns Promise resolving to one page and the cursor for the next (empty
|
|
135
|
+
* on the last page)
|
|
136
|
+
*/
|
|
137
|
+
async listDeposits(params = {}) {
|
|
138
|
+
const { pageSize, pageToken } = params;
|
|
139
|
+
if (pageSize !== undefined && !(Number.isInteger(pageSize) && pageSize >= 1 && pageSize <= MAX_DEPOSIT_PAGE_SIZE)) {
|
|
140
|
+
throw new InvalidConfigError(`Invalid pageSize: ${pageSize}. Expected an integer between 1 and ${MAX_DEPOSIT_PAGE_SIZE}.`);
|
|
141
|
+
}
|
|
142
|
+
return await this.makeAuthenticatedRequest(perpRoutes.sweeper.listDeposits({ pageSize, pageToken }), {
|
|
143
|
+
method: "GET",
|
|
144
|
+
});
|
|
145
|
+
}
|
|
104
146
|
}
|
|
147
|
+
/** The deposit listing's page size bounds, matching the endpoint's schema. */
|
|
148
|
+
const MAX_DEPOSIT_PAGE_SIZE = 100;
|
|
149
|
+
/** A 0x-prefixed 32-byte hex transaction hash, matching the endpoint's schema. */
|
|
150
|
+
const TX_HASH_PATTERN = /^0x[0-9a-fA-F]{64}$/;
|
|
@@ -24,6 +24,12 @@
|
|
|
24
24
|
import type { BatchCancelOrdersResponse, BatchCreateOrderParams, BatchCreateOrdersResponse, BatchReplaceOrderParams, BatchReplaceOrdersResponse, CancelConditionalOrderResponse, CancelOrderResponse, CancelTwapOrderResponse, ConditionalOrder, CreateOrderResponse, CreateTwapOrderOptions, CreateTwapOrderResponse, GetOrderResponse, GetPaginatedOrdersParams, GetPaginatedOrdersResponse, GetTwapOrderTcaResponse, ListConditionalOrdersParams, ListConditionalOrdersResponse, ListTwapOrderSlicesParams, ListTwapOrderSlicesResponse, ListTwapOrdersParams, ListTwapOrdersResponse, MarginMode, OrderSide, ParentTpSlLegParams, ParentTrailingStopLegParams, PositionSide, ReplaceOrderResponse, SelfTradePreventionMode, TimeInForce, TradingAPI, TradingMode, TwapOrder } from "@0xmonaco/types";
|
|
25
25
|
import { BaseAPI } from "../base";
|
|
26
26
|
export declare class TradingAPIImpl extends BaseAPI implements TradingAPI {
|
|
27
|
+
/**
|
|
28
|
+
* Sends a single create. A key the SDK generated for this call is resent
|
|
29
|
+
* after a lost response; a caller-supplied key is sent once, because it may
|
|
30
|
+
* be a recovery of an earlier submission whose 15-minute window is nearly over.
|
|
31
|
+
*/
|
|
32
|
+
private submitCreate;
|
|
27
33
|
/**
|
|
28
34
|
* Places a limit order on the order book.
|
|
29
35
|
*
|
|
@@ -90,7 +96,7 @@ export declare class TradingAPIImpl extends BaseAPI implements TradingAPI {
|
|
|
90
96
|
postOnly?: boolean;
|
|
91
97
|
selfTradePreventionMode?: SelfTradePreventionMode;
|
|
92
98
|
clientOrderId?: string;
|
|
93
|
-
/** Generated once per call when omitted.
|
|
99
|
+
/** Generated once per call when omitted, and then re-sent inside the call after a lost response. A supplied key is sent once: reuse it with the same order to recover across calls within 15 minutes. */
|
|
94
100
|
idempotencyKey?: string;
|
|
95
101
|
takeProfit?: ParentTpSlLegParams;
|
|
96
102
|
stopLoss?: ParentTpSlLegParams;
|
|
@@ -157,7 +163,7 @@ export declare class TradingAPIImpl extends BaseAPI implements TradingAPI {
|
|
|
157
163
|
/** Trailing stop that arms when this order fully fills; margin entry orders only. */
|
|
158
164
|
trailingStop?: ParentTrailingStopLegParams;
|
|
159
165
|
clientOrderId?: string;
|
|
160
|
-
/** Generated once per call when omitted.
|
|
166
|
+
/** Generated once per call when omitted, and then re-sent inside the call after a lost response. A supplied key is sent once: reuse it with the same order to recover across calls within 15 minutes. */
|
|
161
167
|
idempotencyKey?: string;
|
|
162
168
|
}): Promise<CreateOrderResponse>;
|
|
163
169
|
/**
|
|
@@ -426,7 +432,9 @@ export declare class TradingAPIImpl extends BaseAPI implements TradingAPI {
|
|
|
426
432
|
* @param options.slippageToleranceBps - Per-slice protective price band in
|
|
427
433
|
* basis points (default 100 = 1%)
|
|
428
434
|
* @param options.clientTwapId - Idempotency key (max 36 chars), unique per
|
|
429
|
-
* user and application
|
|
435
|
+
* user and application while the parent is live and for a reservation
|
|
436
|
+
* lifetime after it ends (30 days by default); a duplicate inside that
|
|
437
|
+
* window is rejected with 409
|
|
430
438
|
* @returns Promise resolving to CreateTwapOrderResponse with the parent id,
|
|
431
439
|
* initial state, and the planned schedule summary
|
|
432
440
|
* @throws {APIError} When API communication fails
|
package/dist/api/trading/api.js
CHANGED
|
@@ -55,6 +55,17 @@ function parentTrailingStopLegToRequest(leg) {
|
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
57
|
export class TradingAPIImpl extends BaseAPI {
|
|
58
|
+
/**
|
|
59
|
+
* Sends a single create. A key the SDK generated for this call is resent
|
|
60
|
+
* after a lost response; a caller-supplied key is sent once, because it may
|
|
61
|
+
* be a recovery of an earlier submission whose 15-minute window is nearly over.
|
|
62
|
+
*/
|
|
63
|
+
submitCreate(requestBody, keyGenerated) {
|
|
64
|
+
const request = { method: "POST", body: JSON.stringify(requestBody) };
|
|
65
|
+
return keyGenerated
|
|
66
|
+
? this.makeKeyedSubmission(perpRoutes.orders.create(), request)
|
|
67
|
+
: this.makeAuthenticatedRequest(perpRoutes.orders.create(), request);
|
|
68
|
+
}
|
|
58
69
|
/**
|
|
59
70
|
* Places a limit order on the order book.
|
|
60
71
|
*
|
|
@@ -140,10 +151,7 @@ export class TradingAPIImpl extends BaseAPI {
|
|
|
140
151
|
stopLoss: parentTpSlLegToRequest(options?.stopLoss),
|
|
141
152
|
trailingStop: parentTrailingStopLegToRequest(options?.trailingStop),
|
|
142
153
|
};
|
|
143
|
-
return await this.
|
|
144
|
-
method: "POST",
|
|
145
|
-
body: JSON.stringify(requestBody),
|
|
146
|
-
});
|
|
154
|
+
return await this.submitCreate(requestBody, options?.idempotencyKey === undefined);
|
|
147
155
|
}
|
|
148
156
|
/**
|
|
149
157
|
* Places a market order for immediate execution.
|
|
@@ -219,10 +227,7 @@ export class TradingAPIImpl extends BaseAPI {
|
|
|
219
227
|
clientOrderId: options?.clientOrderId,
|
|
220
228
|
idempotencyKey: options?.idempotencyKey === undefined ? crypto.randomUUID() : options.idempotencyKey,
|
|
221
229
|
};
|
|
222
|
-
return await this.
|
|
223
|
-
method: "POST",
|
|
224
|
-
body: JSON.stringify(requestBody),
|
|
225
|
-
});
|
|
230
|
+
return await this.submitCreate(requestBody, options?.idempotencyKey === undefined);
|
|
226
231
|
}
|
|
227
232
|
/**
|
|
228
233
|
* Cancels an existing order.
|
|
@@ -660,7 +665,9 @@ export class TradingAPIImpl extends BaseAPI {
|
|
|
660
665
|
* @param options.slippageToleranceBps - Per-slice protective price band in
|
|
661
666
|
* basis points (default 100 = 1%)
|
|
662
667
|
* @param options.clientTwapId - Idempotency key (max 36 chars), unique per
|
|
663
|
-
* user and application
|
|
668
|
+
* user and application while the parent is live and for a reservation
|
|
669
|
+
* lifetime after it ends (30 days by default); a duplicate inside that
|
|
670
|
+
* window is rejected with 409
|
|
664
671
|
* @returns Promise resolving to CreateTwapOrderResponse with the parent id,
|
|
665
672
|
* initial state, and the planned schedule summary
|
|
666
673
|
* @throws {APIError} When API communication fails
|
|
@@ -366,6 +366,34 @@ function parseLiquidationEvent(rawData) {
|
|
|
366
366
|
data: parseLiquidationEventData(rawData.data),
|
|
367
367
|
};
|
|
368
368
|
}
|
|
369
|
+
function parseMarketLiquidationEventData(raw) {
|
|
370
|
+
if (!isRecord(raw)) {
|
|
371
|
+
throw new Error("Invalid market liquidation event: data must be an object");
|
|
372
|
+
}
|
|
373
|
+
const data = keysToCamelCase(raw);
|
|
374
|
+
return {
|
|
375
|
+
eventId: readString(data, "eventId"),
|
|
376
|
+
timestamp: readSequence(data, "timestamp"),
|
|
377
|
+
wallet: readString(data, "wallet"),
|
|
378
|
+
// Side is a value field: preserve a future server label so an SDK version
|
|
379
|
+
// skew cannot drop the entire persisted liquidation event.
|
|
380
|
+
side: readString(data, "side"),
|
|
381
|
+
positionSize: readString(data, "positionSize"),
|
|
382
|
+
markPrice: readString(data, "markPrice"),
|
|
383
|
+
markNotional: readString(data, "markNotional"),
|
|
384
|
+
quoteAssetSymbol: readString(data, "quoteAssetSymbol"),
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
function parseMarketLiquidationEvent(rawData) {
|
|
388
|
+
if (!isRecord(rawData)) {
|
|
389
|
+
throw new Error("Invalid market liquidation event: payload must be an object");
|
|
390
|
+
}
|
|
391
|
+
return {
|
|
392
|
+
eventType: readEnum(rawData, "event_type", ["liquidation_event"]),
|
|
393
|
+
tradingPairId: readString(rawData, "trading_pair_id"),
|
|
394
|
+
data: parseMarketLiquidationEventData(rawData.data),
|
|
395
|
+
};
|
|
396
|
+
}
|
|
369
397
|
/**
|
|
370
398
|
* Parse an account's margin-health payload. Shared by the live event and the
|
|
371
399
|
* subscribe-time snapshot (see {@link parseConditionalOrderEventData}).
|
|
@@ -2155,6 +2183,19 @@ export function createMonacoWebSocket(baseUrl, options = {}, serverClock = new S
|
|
|
2155
2183
|
// reach the event handler.
|
|
2156
2184
|
onSnapshot && snapshotFrameHandler("all-markets stats", parseMarketStatsSummary, onSnapshot));
|
|
2157
2185
|
};
|
|
2186
|
+
const subscribeMarketLiquidations = (tradingPairId, handler) => {
|
|
2187
|
+
if (!handler) {
|
|
2188
|
+
throw new Error("marketLiquidations subscription requires a handler");
|
|
2189
|
+
}
|
|
2190
|
+
return subscribe(`market_liquidations:${tradingPairId}`, (rawData) => {
|
|
2191
|
+
try {
|
|
2192
|
+
handler(parseMarketLiquidationEvent(rawData));
|
|
2193
|
+
}
|
|
2194
|
+
catch (err) {
|
|
2195
|
+
console.error("WebSocket: Error processing market liquidation event", err);
|
|
2196
|
+
}
|
|
2197
|
+
});
|
|
2198
|
+
};
|
|
2158
2199
|
return {
|
|
2159
2200
|
connect,
|
|
2160
2201
|
disconnect,
|
|
@@ -2194,5 +2235,6 @@ export function createMonacoWebSocket(baseUrl, options = {}, serverClock = new S
|
|
|
2194
2235
|
instruments: subscribeInstruments,
|
|
2195
2236
|
marketStats: subscribeMarketStats,
|
|
2196
2237
|
marketStatsAll: subscribeMarketStatsAll,
|
|
2238
|
+
marketLiquidations: subscribeMarketLiquidations,
|
|
2197
2239
|
};
|
|
2198
2240
|
}
|
package/dist/coverage.d.ts
CHANGED
|
@@ -61,6 +61,8 @@ export declare const COVERED: {
|
|
|
61
61
|
claim_managed_market_lease: string;
|
|
62
62
|
refresh_managed_market_quotes: string;
|
|
63
63
|
get_sweeper_chains: string;
|
|
64
|
+
get_sweeper_deposit_status: string;
|
|
65
|
+
list_sweeper_deposits: string;
|
|
64
66
|
get_my_trader_code: string;
|
|
65
67
|
get_rewards_balance: string;
|
|
66
68
|
get_my_referral_position: string;
|
|
@@ -94,6 +96,9 @@ export declare const COVERED: {
|
|
|
94
96
|
get_sub_account_limits: string;
|
|
95
97
|
get_trade_by_id: string;
|
|
96
98
|
get_trades: string;
|
|
99
|
+
get_trade_flow: string;
|
|
100
|
+
get_trader_metrics: string;
|
|
101
|
+
get_liquidation_metrics: string;
|
|
97
102
|
get_trading_pair_by_id: string;
|
|
98
103
|
get_user_balance_by_asset: string;
|
|
99
104
|
get_user_balances: string;
|
|
@@ -114,6 +119,7 @@ export declare const COVERED: {
|
|
|
114
119
|
list_delegated_agent_owners: string;
|
|
115
120
|
list_delegated_agents: string;
|
|
116
121
|
list_funding_history: string;
|
|
122
|
+
list_liquidation_events: string;
|
|
117
123
|
list_funding_payments: string;
|
|
118
124
|
list_margin_accounts: string;
|
|
119
125
|
list_position_history: string;
|
package/dist/coverage.js
CHANGED
|
@@ -61,6 +61,8 @@ export const COVERED = {
|
|
|
61
61
|
claim_managed_market_lease: "managedMarkets.claimLease",
|
|
62
62
|
refresh_managed_market_quotes: "managedMarkets.refreshQuotes",
|
|
63
63
|
get_sweeper_chains: "sweeper.getChains",
|
|
64
|
+
get_sweeper_deposit_status: "sweeper.getDepositStatus",
|
|
65
|
+
list_sweeper_deposits: "sweeper.listDeposits",
|
|
64
66
|
get_my_trader_code: "tradercodes.getMyTraderCode",
|
|
65
67
|
get_rewards_balance: "tradercodes.getRewardsBalance",
|
|
66
68
|
get_my_referral_position: "tradercodes.getMyReferralPosition",
|
|
@@ -94,6 +96,9 @@ export const COVERED = {
|
|
|
94
96
|
get_sub_account_limits: "subAccounts.getLimits",
|
|
95
97
|
get_trade_by_id: "getTradeById",
|
|
96
98
|
get_trades: "getTrades",
|
|
99
|
+
get_trade_flow: "getTradeFlow",
|
|
100
|
+
get_trader_metrics: "getTraderMetrics",
|
|
101
|
+
get_liquidation_metrics: "getLiquidationMetrics",
|
|
97
102
|
get_trading_pair_by_id: "getTradingPair",
|
|
98
103
|
get_user_balance_by_asset: "getUserBalanceByAssetId",
|
|
99
104
|
get_user_balances: "getUserBalances",
|
|
@@ -114,6 +119,7 @@ export const COVERED = {
|
|
|
114
119
|
list_delegated_agent_owners: "listDelegatedOwners",
|
|
115
120
|
list_delegated_agents: "listDelegatedAgents",
|
|
116
121
|
list_funding_history: "listFundingHistory",
|
|
122
|
+
list_liquidation_events: "listLiquidationEvents",
|
|
117
123
|
list_funding_payments: "listFundingPayments",
|
|
118
124
|
list_margin_accounts: "listMarginAccounts",
|
|
119
125
|
list_position_history: "listPositionHistory",
|
package/dist/sdk.js
CHANGED
|
@@ -27,12 +27,11 @@ import { APIError, InvalidConfigError, InvalidStateError } from "./errors";
|
|
|
27
27
|
import { resolveApiUrl, resolveWsUrl } from "./networks";
|
|
28
28
|
import { ServerClock } from "./utils/server-clock";
|
|
29
29
|
/**
|
|
30
|
-
* Default receipt-polling frequency for the SDK's internal viem public client
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* two blocks while staying gentle on public RPC endpoints.
|
|
30
|
+
* Default receipt-polling frequency for the SDK's internal viem public client:
|
|
31
|
+
* about half a Sei block (~400ms). viem's 4000ms default adds seconds of slack
|
|
32
|
+
* to every `waitForTransactionReceipt`.
|
|
34
33
|
*/
|
|
35
|
-
const DEFAULT_POLLING_INTERVAL_MS =
|
|
34
|
+
const DEFAULT_POLLING_INTERVAL_MS = 200;
|
|
36
35
|
/** Validate a user-supplied URL override, returning it unchanged when valid. */
|
|
37
36
|
function validateUrl(value, field) {
|
|
38
37
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@0xmonaco/core",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.91",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"homepage": "https://docs.0xmonaco.com/sdk/typescript",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
"viem": "^2.45.2"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@0xmonaco/contracts": "1.0.
|
|
23
|
-
"@0xmonaco/types": "1.0.
|
|
22
|
+
"@0xmonaco/contracts": "1.0.91",
|
|
23
|
+
"@0xmonaco/types": "1.0.91",
|
|
24
24
|
"@noble/curves": "^1.9.1",
|
|
25
25
|
"@noble/hashes": "^2.4.0",
|
|
26
26
|
"http-status-codes": "^2.3.0"
|