@0xmonaco/core 1.1.2 → 1.1.5
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/README.md +7 -1
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.js +1 -0
- package/dist/api/market/api.d.ts +3 -1
- package/dist/api/market/api.js +9 -0
- package/dist/api/orderbook/api.d.ts +1 -1
- package/dist/api/perp/routes.d.ts +13 -0
- package/dist/api/perp/routes.js +4 -0
- package/dist/api/rfq/api.d.ts +69 -0
- package/dist/api/rfq/api.js +129 -0
- package/dist/api/rfq/index.d.ts +6 -0
- package/dist/api/rfq/index.js +6 -0
- package/dist/api/trades/api.d.ts +24 -0
- package/dist/api/trades/api.js +28 -1
- package/dist/api/trading/api.d.ts +33 -1
- package/dist/api/trading/api.js +43 -1
- package/dist/api/websocket/websocket.js +189 -0
- package/dist/coverage.d.ts +12 -0
- package/dist/coverage.js +12 -0
- package/dist/sdk.d.ts +2 -1
- package/dist/sdk.js +4 -0
- package/dist/utils/magnitude.d.ts +5 -2
- package/dist/utils/magnitude.js +6 -3
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -118,7 +118,13 @@ async function marketExample() {
|
|
|
118
118
|
|
|
119
119
|
// Get specific trading pair
|
|
120
120
|
const btcPair = await monaco.market.getTradingPairBySymbol("BTC/USDC");
|
|
121
|
-
console.log("BTC pair:", btcPair?.symbol, btcPair?.
|
|
121
|
+
console.log("BTC pair:", btcPair?.symbol, btcPair?.tickSize);
|
|
122
|
+
|
|
123
|
+
// Fee rates are tiered: read the pair's schedule (public) or your own tier
|
|
124
|
+
if (btcPair) {
|
|
125
|
+
const { feeSchedule } = await monaco.fees.getFeeSchedule(btcPair.id);
|
|
126
|
+
console.log("Tier 1 taker fee (bps):", feeSchedule[0]?.takerFeeBps);
|
|
127
|
+
}
|
|
122
128
|
}
|
|
123
129
|
|
|
124
130
|
// Vault Operations
|
package/dist/api/index.d.ts
CHANGED
package/dist/api/index.js
CHANGED
package/dist/api/market/api.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
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";
|
|
1
|
+
import type { Candlestick, FundingState, GetCandlesticksParams, GetLiquidationMetricsParams, GetScreenerParams, GetScreenerResponse, GetTradeFlowParams, GetTradingPairsParams, GetTradingPairsResponse, IndexPrice, Interval, LiquidationMetrics, ListAllFundingHistoryParams, ListAllFundingHistoryResponse, ListAllLiquidationEventsParams, ListAllLiquidationEventsResponse, ListFundingHistoryParams, ListFundingHistoryResponse, ListInsuranceFundsResponse, 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
|
|
@@ -22,6 +22,8 @@ export declare class MarketAPIImpl extends BaseAPI implements MarketAPI {
|
|
|
22
22
|
getTraderMetrics(tradingPairId: string): Promise<TraderMetrics>;
|
|
23
23
|
getTradeFlow(tradingPairId: string, params: GetTradeFlowParams): Promise<TradeFlow>;
|
|
24
24
|
listLiquidationEvents(tradingPairId: string, params?: ListLiquidationEventsParams): Promise<ListLiquidationEventsResponse>;
|
|
25
|
+
listAllLiquidationEvents(params?: ListAllLiquidationEventsParams): Promise<ListAllLiquidationEventsResponse>;
|
|
26
|
+
listInsuranceFunds(): Promise<ListInsuranceFundsResponse>;
|
|
25
27
|
getLiquidationMetrics(tradingPairId: string, params: GetLiquidationMetricsParams): Promise<LiquidationMetrics>;
|
|
26
28
|
getScreener(params?: GetScreenerParams): Promise<GetScreenerResponse>;
|
|
27
29
|
getMarketStats(): Promise<MarketStats>;
|
package/dist/api/market/api.js
CHANGED
|
@@ -125,6 +125,15 @@ export class MarketAPIImpl extends BaseAPI {
|
|
|
125
125
|
validate(GetMarketMetadataSchema, { tradingPairId });
|
|
126
126
|
return await this.makePublicRequest(perpRoutes.market.listLiquidationEvents(tradingPairId, params));
|
|
127
127
|
}
|
|
128
|
+
async listAllLiquidationEvents(params) {
|
|
129
|
+
const response = await this.makePublicRequest(perpRoutes.market.listAllLiquidationEvents(params));
|
|
130
|
+
// An empty page omits the repeated field and the finished cursor.
|
|
131
|
+
return { ...response, events: response.events ?? [], nextPageToken: response.nextPageToken ?? "" };
|
|
132
|
+
}
|
|
133
|
+
async listInsuranceFunds() {
|
|
134
|
+
const response = await this.makePublicRequest(perpRoutes.market.listInsuranceFunds());
|
|
135
|
+
return { funds: response.funds ?? [] };
|
|
136
|
+
}
|
|
128
137
|
async getLiquidationMetrics(tradingPairId, params) {
|
|
129
138
|
validate(GetMarketMetadataSchema, { tradingPairId });
|
|
130
139
|
return await this.makePublicRequest(perpRoutes.market.getLiquidationMetrics(tradingPairId, params));
|
|
@@ -5,7 +5,7 @@ export interface GetOrderbookOptions {
|
|
|
5
5
|
depth?: number;
|
|
6
6
|
/** Trading mode: 'Spot' or 'Margin'. Defaults to 'Spot'. */
|
|
7
7
|
tradingMode?: TradingMode;
|
|
8
|
-
/** Price grouping magnitude. Valid values: 0.0001, 0.001, 0.01, 0.1, 1, 10, 100, 1000, 10000. */
|
|
8
|
+
/** Price grouping magnitude. Valid values: 0.000001, 0.00001, 0.0001, 0.001, 0.01, 0.1, 1, 10, 100, 1000, 10000. */
|
|
9
9
|
magnitude?: number;
|
|
10
10
|
/** Quantity denomination: 'BASE' or 'QUOTE'. When 'QUOTE', quantities are multiplied by price. */
|
|
11
11
|
denomination?: OrderbookQuotationMode;
|
|
@@ -15,6 +15,7 @@ export declare const perpRoutes: {
|
|
|
15
15
|
readonly batchCancel: () => string;
|
|
16
16
|
readonly batchCancelAll: () => string;
|
|
17
17
|
readonly batchCancelAllByPair: (tradingPairId: string) => string;
|
|
18
|
+
readonly cancelAllAfter: () => string;
|
|
18
19
|
readonly batchCreate: () => string;
|
|
19
20
|
readonly batchReplace: () => string;
|
|
20
21
|
readonly listConditional: (params?: {
|
|
@@ -109,6 +110,13 @@ export declare const perpRoutes: {
|
|
|
109
110
|
startTime: number;
|
|
110
111
|
endTime: number;
|
|
111
112
|
}) => string;
|
|
113
|
+
readonly listAllLiquidationEvents: (params?: {
|
|
114
|
+
startTime?: number;
|
|
115
|
+
endTime?: number;
|
|
116
|
+
pageSize?: number;
|
|
117
|
+
pageToken?: string;
|
|
118
|
+
}) => string;
|
|
119
|
+
readonly listInsuranceFunds: () => string;
|
|
112
120
|
readonly getScreener: (params?: {
|
|
113
121
|
page?: number;
|
|
114
122
|
pageSize?: number;
|
|
@@ -132,6 +140,11 @@ export declare const perpRoutes: {
|
|
|
132
140
|
limit?: number;
|
|
133
141
|
}) => string;
|
|
134
142
|
readonly byId: (tradeId: string) => string;
|
|
143
|
+
readonly feed: (params?: {
|
|
144
|
+
takerApplicationId?: string;
|
|
145
|
+
pageSize?: number;
|
|
146
|
+
pageToken?: string;
|
|
147
|
+
}) => string;
|
|
135
148
|
readonly user: (params?: {
|
|
136
149
|
marginAccountId?: string;
|
|
137
150
|
tradingPairId?: string;
|
package/dist/api/perp/routes.js
CHANGED
|
@@ -24,6 +24,7 @@ export const perpRoutes = {
|
|
|
24
24
|
batchCancel: () => `${API_V1}/orders/batch-cancel`,
|
|
25
25
|
batchCancelAll: () => `${API_V1}/orders/batch-cancel-all`,
|
|
26
26
|
batchCancelAllByPair: (tradingPairId) => `${API_V1}/orders/batch-cancel-all/${encodeSegment(tradingPairId)}`,
|
|
27
|
+
cancelAllAfter: () => `${API_V1}/orders/cancel-all-after`,
|
|
27
28
|
batchCreate: () => `${API_V1}/orders/batch-create`,
|
|
28
29
|
batchReplace: () => `${API_V1}/orders/batch-replace`,
|
|
29
30
|
listConditional: (params) => withQuery(`${API_V1}/orders/conditional`, params),
|
|
@@ -64,6 +65,8 @@ export const perpRoutes = {
|
|
|
64
65
|
getTradeFlow: (tradingPairId, params) => withQuery(`${API_V1}/market/pairs/${encodeSegment(tradingPairId)}/trade-flow`, params),
|
|
65
66
|
listLiquidationEvents: (tradingPairId, params) => withQuery(`${API_V1}/market/pairs/${encodeSegment(tradingPairId)}/liquidation-events`, params),
|
|
66
67
|
getLiquidationMetrics: (tradingPairId, params) => withQuery(`${API_V1}/market/pairs/${encodeSegment(tradingPairId)}/liquidation-metrics`, params),
|
|
68
|
+
listAllLiquidationEvents: (params) => withQuery(`${API_V1}/market/liquidation-events`, params),
|
|
69
|
+
listInsuranceFunds: () => `${API_V1}/market/insurance-funds`,
|
|
67
70
|
getScreener: (params) => withQuery(`${API_V1}/market/screener`, params),
|
|
68
71
|
getMarketStats: () => `${API_V1}/market/stats`,
|
|
69
72
|
},
|
|
@@ -73,6 +76,7 @@ export const perpRoutes = {
|
|
|
73
76
|
trades: {
|
|
74
77
|
publicByPair: (tradingPairId, params) => withQuery(`${API_V1}/trades/${encodeSegment(tradingPairId)}`, params),
|
|
75
78
|
byId: (tradeId) => `${API_V1}/trades/by-id/${encodeSegment(tradeId)}`,
|
|
79
|
+
feed: (params) => withQuery(`${API_V1}/trades`, params),
|
|
76
80
|
user: (params) => withQuery(`${API_V1}/accounts/trades`, params),
|
|
77
81
|
},
|
|
78
82
|
applications: {
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RFQ (block trading) API Implementation
|
|
3
|
+
*
|
|
4
|
+
* A taker requests quotes for a size; makers quote privately; the taker
|
|
5
|
+
* accepts one side of the best allocation, and each selected maker then has a
|
|
6
|
+
* short last look (reject or improve; silence executes). Available only to
|
|
7
|
+
* accounts RFQ is enabled for: other callers get `403` with code
|
|
8
|
+
* `RFQ_DISABLED`.
|
|
9
|
+
*
|
|
10
|
+
* Every call is signed. Every write carries an `idempotencyKey` (generated
|
|
11
|
+
* when omitted) and is sent as a keyed submission, so a write whose outcome
|
|
12
|
+
* is unknown is resent with the same key and body and the server replays the
|
|
13
|
+
* first result. The body is built key by key from validated params, because
|
|
14
|
+
* the gateway rejects unknown fields and stores a maker's request exactly as
|
|
15
|
+
* signed.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* // Taker
|
|
20
|
+
* const rfq = await sdk.rfq.createRfq({ tradingPairId, product: "PERPETUAL", quantity: "25" });
|
|
21
|
+
* const status = await sdk.rfq.getRfq(rfq.terms!.rfqId);
|
|
22
|
+
* await sdk.rfq.acceptRfq(rfq.terms!.rfqId, { side: "BUY", viewVersion: status.view!.viewVersion });
|
|
23
|
+
*
|
|
24
|
+
* // Maker
|
|
25
|
+
* const quote = await sdk.rfq.upsertQuote(rfqId, { expectedVersion: 0, ask: { price: "65001", capacity: "10" } });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
import type { AcceptRfqParams, CancelRfqParams, CreateRfqParams, GetRfqCapabilitiesResponse, RespondRfqLastLookParams, RespondRfqLastLookResponse, RfqAPI, RfqQuoteVersion, RfqStatus, UpsertRfqQuoteParams, WithdrawRfqQuoteParams, WithdrawRfqQuoteResponse } from "@0xmonaco/types";
|
|
29
|
+
import { BaseAPI } from "../base";
|
|
30
|
+
export declare class RfqAPIImpl extends BaseAPI implements RfqAPI {
|
|
31
|
+
/** Your RFQ limits and the markets RFQ is offered on. */
|
|
32
|
+
getCapabilities(): Promise<GetRfqCapabilitiesResponse>;
|
|
33
|
+
/**
|
|
34
|
+
* Request quotes for up to `quantity` (not a guaranteed fill). Omit `side`
|
|
35
|
+
* for a two-way RFQ, whose direction stays hidden from makers; set, makers
|
|
36
|
+
* see it and may quote only the side that fills it (`terms.quoteSide`). On a perpetual give `leverage`
|
|
37
|
+
* (and optionally `marginMode`) for the order you accept with, as on an
|
|
38
|
+
* order. Delegated agents cannot request quotes.
|
|
39
|
+
*/
|
|
40
|
+
createRfq(params: CreateRfqParams): Promise<RfqStatus>;
|
|
41
|
+
/**
|
|
42
|
+
* An RFQ's authoritative status. As taker: the current `view` and, once
|
|
43
|
+
* executed, the `outcome`. As maker: your latest quote, `ownLatestVersion`
|
|
44
|
+
* and, once selected, `ownSelection` for last look.
|
|
45
|
+
*/
|
|
46
|
+
getRfq(rfqId: string): Promise<RfqStatus>;
|
|
47
|
+
/**
|
|
48
|
+
* Accept one side of the view you last saw. Binding: the selected makers'
|
|
49
|
+
* last look follows, and silence executes. A newer view refuses an older
|
|
50
|
+
* `viewVersion` (409); read the RFQ again and accept the current one.
|
|
51
|
+
*/
|
|
52
|
+
acceptRfq(rfqId: string, params: AcceptRfqParams): Promise<RfqStatus>;
|
|
53
|
+
/** Cancel an RFQ you have not accepted, before its deadline. */
|
|
54
|
+
cancelRfq(rfqId: string, params?: CancelRfqParams): Promise<RfqStatus>;
|
|
55
|
+
/**
|
|
56
|
+
* As maker: place or replace your quote, a bid, an ask or both. Name your
|
|
57
|
+
* current version (`ownLatestVersion`; 0 for your first quote); a stale
|
|
58
|
+
* version is refused (409).
|
|
59
|
+
*/
|
|
60
|
+
upsertQuote(rfqId: string, params: UpsertRfqQuoteParams): Promise<RfqQuoteVersion>;
|
|
61
|
+
/** As maker: withdraw your current quote, naming your current version. */
|
|
62
|
+
withdrawQuote(rfqId: string, params: WithdrawRfqQuoteParams): Promise<WithdrawRfqQuoteResponse>;
|
|
63
|
+
/**
|
|
64
|
+
* As a selected maker: reject, or improve your frozen terms (a strictly
|
|
65
|
+
* better price or a higher capacity), before the last-look deadline. There
|
|
66
|
+
* is no accept: silence executes.
|
|
67
|
+
*/
|
|
68
|
+
respondLastLook(rfqId: string, params: RespondRfqLastLookParams): Promise<RespondRfqLastLookResponse>;
|
|
69
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RFQ (block trading) API Implementation
|
|
3
|
+
*
|
|
4
|
+
* A taker requests quotes for a size; makers quote privately; the taker
|
|
5
|
+
* accepts one side of the best allocation, and each selected maker then has a
|
|
6
|
+
* short last look (reject or improve; silence executes). Available only to
|
|
7
|
+
* accounts RFQ is enabled for: other callers get `403` with code
|
|
8
|
+
* `RFQ_DISABLED`.
|
|
9
|
+
*
|
|
10
|
+
* Every call is signed. Every write carries an `idempotencyKey` (generated
|
|
11
|
+
* when omitted) and is sent as a keyed submission, so a write whose outcome
|
|
12
|
+
* is unknown is resent with the same key and body and the server replays the
|
|
13
|
+
* first result. The body is built key by key from validated params, because
|
|
14
|
+
* the gateway rejects unknown fields and stores a maker's request exactly as
|
|
15
|
+
* signed.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* // Taker
|
|
20
|
+
* const rfq = await sdk.rfq.createRfq({ tradingPairId, product: "PERPETUAL", quantity: "25" });
|
|
21
|
+
* const status = await sdk.rfq.getRfq(rfq.terms!.rfqId);
|
|
22
|
+
* await sdk.rfq.acceptRfq(rfq.terms!.rfqId, { side: "BUY", viewVersion: status.view!.viewVersion });
|
|
23
|
+
*
|
|
24
|
+
* // Maker
|
|
25
|
+
* const quote = await sdk.rfq.upsertQuote(rfqId, { expectedVersion: 0, ask: { price: "65001", capacity: "10" } });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
import { AcceptRfqSchema, CancelRfqSchema, CreateRfqSchema, RespondRfqLastLookSchema, UpsertRfqQuoteSchema, UUIDSchema, validate, WithdrawRfqQuoteSchema, } from "@0xmonaco/types";
|
|
29
|
+
import { BaseAPI } from "../base";
|
|
30
|
+
const BASE = "/api/v1/rfqs";
|
|
31
|
+
/** The RFQ path for a validated RFQ id. */
|
|
32
|
+
function rfqPath(rfqId) {
|
|
33
|
+
return `${BASE}/${validate(UUIDSchema, rfqId)}`;
|
|
34
|
+
}
|
|
35
|
+
/** The caller's key, or a fresh one. */
|
|
36
|
+
function keyOf(idempotencyKey) {
|
|
37
|
+
return idempotencyKey ?? crypto.randomUUID();
|
|
38
|
+
}
|
|
39
|
+
export class RfqAPIImpl extends BaseAPI {
|
|
40
|
+
/** Your RFQ limits and the markets RFQ is offered on. */
|
|
41
|
+
async getCapabilities() {
|
|
42
|
+
return await this.makeAuthenticatedRequest("/api/v1/rfq/capabilities", { method: "GET" });
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Request quotes for up to `quantity` (not a guaranteed fill). Omit `side`
|
|
46
|
+
* for a two-way RFQ, whose direction stays hidden from makers; set, makers
|
|
47
|
+
* see it and may quote only the side that fills it (`terms.quoteSide`). On a perpetual give `leverage`
|
|
48
|
+
* (and optionally `marginMode`) for the order you accept with, as on an
|
|
49
|
+
* order. Delegated agents cannot request quotes.
|
|
50
|
+
*/
|
|
51
|
+
async createRfq(params) {
|
|
52
|
+
const { tradingPairId, product, quantity, side, leverage, marginMode, idempotencyKey } = validate(CreateRfqSchema, params);
|
|
53
|
+
const body = { idempotencyKey: keyOf(idempotencyKey), tradingPairId, product, quantity };
|
|
54
|
+
if (side !== undefined)
|
|
55
|
+
body.side = side;
|
|
56
|
+
if (leverage !== undefined)
|
|
57
|
+
body.leverage = leverage;
|
|
58
|
+
if (marginMode !== undefined)
|
|
59
|
+
body.marginMode = marginMode;
|
|
60
|
+
return await this.makeKeyedSubmission(BASE, { method: "POST", body: JSON.stringify(body) });
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* An RFQ's authoritative status. As taker: the current `view` and, once
|
|
64
|
+
* executed, the `outcome`. As maker: your latest quote, `ownLatestVersion`
|
|
65
|
+
* and, once selected, `ownSelection` for last look.
|
|
66
|
+
*/
|
|
67
|
+
async getRfq(rfqId) {
|
|
68
|
+
return await this.makeAuthenticatedRequest(rfqPath(rfqId), { method: "GET" });
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Accept one side of the view you last saw. Binding: the selected makers'
|
|
72
|
+
* last look follows, and silence executes. A newer view refuses an older
|
|
73
|
+
* `viewVersion` (409); read the RFQ again and accept the current one.
|
|
74
|
+
*/
|
|
75
|
+
async acceptRfq(rfqId, params) {
|
|
76
|
+
const path = rfqPath(rfqId);
|
|
77
|
+
const { side, viewVersion, idempotencyKey } = validate(AcceptRfqSchema, params);
|
|
78
|
+
const body = { idempotencyKey: keyOf(idempotencyKey), side, viewVersion };
|
|
79
|
+
return await this.makeKeyedSubmission(`${path}/accept`, { method: "POST", body: JSON.stringify(body) });
|
|
80
|
+
}
|
|
81
|
+
/** Cancel an RFQ you have not accepted, before its deadline. */
|
|
82
|
+
async cancelRfq(rfqId, params = {}) {
|
|
83
|
+
const path = rfqPath(rfqId);
|
|
84
|
+
const { idempotencyKey } = validate(CancelRfqSchema, params);
|
|
85
|
+
const body = { idempotencyKey: keyOf(idempotencyKey) };
|
|
86
|
+
return await this.makeKeyedSubmission(`${path}/cancel`, { method: "POST", body: JSON.stringify(body) });
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* As maker: place or replace your quote, a bid, an ask or both. Name your
|
|
90
|
+
* current version (`ownLatestVersion`; 0 for your first quote); a stale
|
|
91
|
+
* version is refused (409).
|
|
92
|
+
*/
|
|
93
|
+
async upsertQuote(rfqId, params) {
|
|
94
|
+
const path = rfqPath(rfqId);
|
|
95
|
+
const { expectedVersion, bid, ask, validityMs, leverage, marginMode, idempotencyKey } = validate(UpsertRfqQuoteSchema, params);
|
|
96
|
+
const body = { idempotencyKey: keyOf(idempotencyKey), expectedVersion };
|
|
97
|
+
if (bid !== undefined)
|
|
98
|
+
body.bid = { price: bid.price, capacity: bid.capacity };
|
|
99
|
+
if (ask !== undefined)
|
|
100
|
+
body.ask = { price: ask.price, capacity: ask.capacity };
|
|
101
|
+
if (validityMs !== undefined)
|
|
102
|
+
body.validityMs = validityMs;
|
|
103
|
+
if (leverage !== undefined)
|
|
104
|
+
body.leverage = leverage;
|
|
105
|
+
if (marginMode !== undefined)
|
|
106
|
+
body.marginMode = marginMode;
|
|
107
|
+
return await this.makeKeyedSubmission(`${path}/quote`, { method: "PUT", body: JSON.stringify(body) });
|
|
108
|
+
}
|
|
109
|
+
/** As maker: withdraw your current quote, naming your current version. */
|
|
110
|
+
async withdrawQuote(rfqId, params) {
|
|
111
|
+
const path = rfqPath(rfqId);
|
|
112
|
+
const { expectedVersion, idempotencyKey } = validate(WithdrawRfqQuoteSchema, params);
|
|
113
|
+
const body = { idempotencyKey: keyOf(idempotencyKey), expectedVersion };
|
|
114
|
+
return await this.makeKeyedSubmission(`${path}/quote`, { method: "DELETE", body: JSON.stringify(body) });
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* As a selected maker: reject, or improve your frozen terms (a strictly
|
|
118
|
+
* better price or a higher capacity), before the last-look deadline. There
|
|
119
|
+
* is no accept: silence executes.
|
|
120
|
+
*/
|
|
121
|
+
async respondLastLook(rfqId, params) {
|
|
122
|
+
const path = rfqPath(rfqId);
|
|
123
|
+
const { acceptanceId, response, improvedTerms, idempotencyKey } = validate(RespondRfqLastLookSchema, params);
|
|
124
|
+
const body = { idempotencyKey: keyOf(idempotencyKey), acceptanceId, response };
|
|
125
|
+
if (improvedTerms !== undefined)
|
|
126
|
+
body.improvedTerms = { price: improvedTerms.price, capacity: improvedTerms.capacity };
|
|
127
|
+
return await this.makeKeyedSubmission(`${path}/last-look`, { method: "POST", body: JSON.stringify(body) });
|
|
128
|
+
}
|
|
129
|
+
}
|
package/dist/api/trades/api.d.ts
CHANGED
|
@@ -16,6 +16,13 @@ interface RawTradeEvent {
|
|
|
16
16
|
makerSide: string;
|
|
17
17
|
/** Absent when the trade has no recorded execution time */
|
|
18
18
|
executedAt?: string;
|
|
19
|
+
/** CLOB or RFQ */
|
|
20
|
+
executionSource?: string;
|
|
21
|
+
makerAddress?: string;
|
|
22
|
+
takerAddress?: string;
|
|
23
|
+
takerFeeRaw?: string;
|
|
24
|
+
quoteVolumeRaw?: string;
|
|
25
|
+
takerApplicationId?: string;
|
|
19
26
|
};
|
|
20
27
|
}
|
|
21
28
|
/**
|
|
@@ -34,6 +41,13 @@ export interface GetTradesOptions {
|
|
|
34
41
|
*/
|
|
35
42
|
pageToken?: string;
|
|
36
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Options for the every-market trade feed.
|
|
46
|
+
*/
|
|
47
|
+
export interface ListTradesOptions extends GetTradesOptions {
|
|
48
|
+
/** Only the trades this application (frontend) took, as the taker's application. */
|
|
49
|
+
takerApplicationId?: string;
|
|
50
|
+
}
|
|
37
51
|
/**
|
|
38
52
|
* One page of a pair's trade feed.
|
|
39
53
|
*
|
|
@@ -74,6 +88,16 @@ export declare class TradesAPIImpl extends BaseAPI {
|
|
|
74
88
|
* ```
|
|
75
89
|
*/
|
|
76
90
|
getTrades(tradingPairId: string, options?: GetTradesOptions): Promise<GetTradesPage>;
|
|
91
|
+
/**
|
|
92
|
+
* Get one page of the trade feed: every market, newest first, recent and
|
|
93
|
+
* archived trades alike, or only the trades one application took when
|
|
94
|
+
* `takerApplicationId` is set. Each trade carries both wallets, the raw taker
|
|
95
|
+
* fee and quote volume, and the taker's application.
|
|
96
|
+
*
|
|
97
|
+
* Public; each client IP has a read budget (HTTP 429 over it). Start with no
|
|
98
|
+
* `pageToken` and follow `nextPageToken` until it comes back empty.
|
|
99
|
+
*/
|
|
100
|
+
listTrades(options?: ListTradesOptions): Promise<GetTradesPage>;
|
|
77
101
|
/**
|
|
78
102
|
* Get a single trade by its UUID.
|
|
79
103
|
*
|
package/dist/api/trades/api.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GetTradesSchema, validate } from "@0xmonaco/types";
|
|
1
|
+
import { GetTradesSchema, ListTradesSchema, validate } from "@0xmonaco/types";
|
|
2
2
|
import { BaseAPI } from "../base";
|
|
3
3
|
import { perpRoutes } from "../perp";
|
|
4
4
|
/**
|
|
@@ -15,6 +15,12 @@ export function parseRawTradeEvent(raw) {
|
|
|
15
15
|
quantity: raw.data.quantity,
|
|
16
16
|
makerSide: raw.data.makerSide.toUpperCase(),
|
|
17
17
|
executedAt: raw.data.executedAt ?? "",
|
|
18
|
+
...(raw.data.executionSource ? { executionSource: raw.data.executionSource } : {}),
|
|
19
|
+
...(raw.data.makerAddress ? { makerAddress: raw.data.makerAddress } : {}),
|
|
20
|
+
...(raw.data.takerAddress ? { takerAddress: raw.data.takerAddress } : {}),
|
|
21
|
+
...(raw.data.takerFeeRaw ? { takerFeeRaw: raw.data.takerFeeRaw } : {}),
|
|
22
|
+
...(raw.data.quoteVolumeRaw ? { quoteVolumeRaw: raw.data.quoteVolumeRaw } : {}),
|
|
23
|
+
...(raw.data.takerApplicationId ? { takerApplicationId: raw.data.takerApplicationId } : {}),
|
|
18
24
|
},
|
|
19
25
|
};
|
|
20
26
|
}
|
|
@@ -67,6 +73,27 @@ export class TradesAPIImpl extends BaseAPI {
|
|
|
67
73
|
nextPageToken: response.nextPageToken ?? "",
|
|
68
74
|
};
|
|
69
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Get one page of the trade feed: every market, newest first, recent and
|
|
78
|
+
* archived trades alike, or only the trades one application took when
|
|
79
|
+
* `takerApplicationId` is set. Each trade carries both wallets, the raw taker
|
|
80
|
+
* fee and quote volume, and the taker's application.
|
|
81
|
+
*
|
|
82
|
+
* Public; each client IP has a read budget (HTTP 429 over it). Start with no
|
|
83
|
+
* `pageToken` and follow `nextPageToken` until it comes back empty.
|
|
84
|
+
*/
|
|
85
|
+
async listTrades(options = {}) {
|
|
86
|
+
validate(ListTradesSchema, options);
|
|
87
|
+
const response = await this.makePublicRequest(perpRoutes.trades.feed({
|
|
88
|
+
...(options.takerApplicationId ? { takerApplicationId: options.takerApplicationId } : {}),
|
|
89
|
+
...(options.pageSize != null ? { pageSize: options.pageSize } : {}),
|
|
90
|
+
...(options.pageToken ? { pageToken: options.pageToken } : {}),
|
|
91
|
+
}));
|
|
92
|
+
return {
|
|
93
|
+
trades: (response.trades ?? []).map(parseRawTradeEvent),
|
|
94
|
+
nextPageToken: response.nextPageToken ?? "",
|
|
95
|
+
};
|
|
96
|
+
}
|
|
70
97
|
/**
|
|
71
98
|
* Get a single trade by its UUID.
|
|
72
99
|
*
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* );
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
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";
|
|
24
|
+
import type { BatchCancelOrdersResponse, BatchCreateOrderParams, BatchCreateOrdersResponse, BatchReplaceOrderParams, BatchReplaceOrdersResponse, CancelAllAfterOptions, CancelAllAfterResponse, 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
27
|
/**
|
|
@@ -241,6 +241,38 @@ export declare class TradingAPIImpl extends BaseAPI implements TradingAPI {
|
|
|
241
241
|
* ```
|
|
242
242
|
*/
|
|
243
243
|
batchCancelAll(tradingPairId?: string): Promise<BatchCancelOrdersResponse>;
|
|
244
|
+
/**
|
|
245
|
+
* Arms, refreshes or disarms a dead man's switch.
|
|
246
|
+
*
|
|
247
|
+
* Unless you call again before `timeoutMs` runs out, the exchange cancels
|
|
248
|
+
* your resting orders with terminalReason `CANCEL_ALL_AFTER`. Call it on an
|
|
249
|
+
* interval shorter than the timeout to keep pushing the deadline out; send
|
|
250
|
+
* 0 to disarm. A timer that fires is spent, so arm it again afterwards.
|
|
251
|
+
*
|
|
252
|
+
* @param timeoutMs - 0 disarms; otherwise 5000 to 900000 (5 s to 15 min)
|
|
253
|
+
* @param options - Optional `tradingPairId` to scope the timer to one market
|
|
254
|
+
* @returns Promise resolving to the deadline that was set
|
|
255
|
+
* @throws {ValidationError} When the timeout or trading pair id is invalid
|
|
256
|
+
* @throws {APIError} When API communication fails
|
|
257
|
+
*
|
|
258
|
+
* @example
|
|
259
|
+
* ```typescript
|
|
260
|
+
* // Cancel everything if this process stops refreshing for 30 seconds.
|
|
261
|
+
* const { cancelAt } = await tradingAPI.cancelAllAfter(30_000);
|
|
262
|
+
* // One refresh at a time, each after the previous call settles.
|
|
263
|
+
* let pending: Promise<unknown> = Promise.resolve();
|
|
264
|
+
* const refresh = setInterval(() => {
|
|
265
|
+
* pending = pending.then(() => tradingAPI.cancelAllAfter(30_000)).catch(() => undefined);
|
|
266
|
+
* }, 10_000);
|
|
267
|
+
*
|
|
268
|
+
* // Clean shutdown: let the last refresh settle before disarming, or it
|
|
269
|
+
* // could land after the disarm and re-arm the timer.
|
|
270
|
+
* clearInterval(refresh);
|
|
271
|
+
* await pending;
|
|
272
|
+
* await tradingAPI.cancelAllAfter(0);
|
|
273
|
+
* ```
|
|
274
|
+
*/
|
|
275
|
+
cancelAllAfter(timeoutMs: number, options?: CancelAllAfterOptions): Promise<CancelAllAfterResponse>;
|
|
244
276
|
replaceOrder(orderId: string, newOrder: {
|
|
245
277
|
price?: string;
|
|
246
278
|
quantity?: string;
|
package/dist/api/trading/api.js
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* );
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
|
-
import { BatchCreateOrdersSchema, BatchReplaceOrdersSchema, CancelConditionalOrderSchema, CancelOrderSchema, CancelTwapOrderSchema, CreateTwapOrderSchema, GetPaginatedOrdersSchema, ListConditionalOrdersSchema, ListTwapOrderSlicesSchema, ListTwapOrdersSchema, PlaceLimitOrderSchema, PlaceMarketOrderSchema, ReplaceOrderSchema, validate, } from "@0xmonaco/types";
|
|
24
|
+
import { BatchCreateOrdersSchema, BatchReplaceOrdersSchema, CancelAllAfterSchema, CancelConditionalOrderSchema, CancelOrderSchema, CancelTwapOrderSchema, CreateTwapOrderSchema, GetPaginatedOrdersSchema, ListConditionalOrdersSchema, ListTwapOrderSlicesSchema, ListTwapOrdersSchema, PlaceLimitOrderSchema, PlaceMarketOrderSchema, ReplaceOrderSchema, validate, } from "@0xmonaco/types";
|
|
25
25
|
import { BaseAPI } from "../base";
|
|
26
26
|
import { perpRoutes } from "../perp";
|
|
27
27
|
function parentTpSlLegToRequest(leg) {
|
|
@@ -353,6 +353,48 @@ export class TradingAPIImpl extends BaseAPI {
|
|
|
353
353
|
method: "POST",
|
|
354
354
|
});
|
|
355
355
|
}
|
|
356
|
+
/**
|
|
357
|
+
* Arms, refreshes or disarms a dead man's switch.
|
|
358
|
+
*
|
|
359
|
+
* Unless you call again before `timeoutMs` runs out, the exchange cancels
|
|
360
|
+
* your resting orders with terminalReason `CANCEL_ALL_AFTER`. Call it on an
|
|
361
|
+
* interval shorter than the timeout to keep pushing the deadline out; send
|
|
362
|
+
* 0 to disarm. A timer that fires is spent, so arm it again afterwards.
|
|
363
|
+
*
|
|
364
|
+
* @param timeoutMs - 0 disarms; otherwise 5000 to 900000 (5 s to 15 min)
|
|
365
|
+
* @param options - Optional `tradingPairId` to scope the timer to one market
|
|
366
|
+
* @returns Promise resolving to the deadline that was set
|
|
367
|
+
* @throws {ValidationError} When the timeout or trading pair id is invalid
|
|
368
|
+
* @throws {APIError} When API communication fails
|
|
369
|
+
*
|
|
370
|
+
* @example
|
|
371
|
+
* ```typescript
|
|
372
|
+
* // Cancel everything if this process stops refreshing for 30 seconds.
|
|
373
|
+
* const { cancelAt } = await tradingAPI.cancelAllAfter(30_000);
|
|
374
|
+
* // One refresh at a time, each after the previous call settles.
|
|
375
|
+
* let pending: Promise<unknown> = Promise.resolve();
|
|
376
|
+
* const refresh = setInterval(() => {
|
|
377
|
+
* pending = pending.then(() => tradingAPI.cancelAllAfter(30_000)).catch(() => undefined);
|
|
378
|
+
* }, 10_000);
|
|
379
|
+
*
|
|
380
|
+
* // Clean shutdown: let the last refresh settle before disarming, or it
|
|
381
|
+
* // could land after the disarm and re-arm the timer.
|
|
382
|
+
* clearInterval(refresh);
|
|
383
|
+
* await pending;
|
|
384
|
+
* await tradingAPI.cancelAllAfter(0);
|
|
385
|
+
* ```
|
|
386
|
+
*/
|
|
387
|
+
async cancelAllAfter(timeoutMs, options) {
|
|
388
|
+
validate(CancelAllAfterSchema, { timeoutMs, options });
|
|
389
|
+
const body = { timeoutMs };
|
|
390
|
+
if (options?.tradingPairId !== undefined) {
|
|
391
|
+
body.tradingPairId = options.tradingPairId;
|
|
392
|
+
}
|
|
393
|
+
return this.makeAuthenticatedRequest(perpRoutes.orders.cancelAllAfter(), {
|
|
394
|
+
method: "POST",
|
|
395
|
+
body: JSON.stringify(body),
|
|
396
|
+
});
|
|
397
|
+
}
|
|
356
398
|
async replaceOrder(orderId, newOrder) {
|
|
357
399
|
// Validate inputs before making API call
|
|
358
400
|
validate(ReplaceOrderSchema, { orderId, newOrder });
|
|
@@ -116,6 +116,17 @@ function readOptionalNumber(source, field) {
|
|
|
116
116
|
}
|
|
117
117
|
return value;
|
|
118
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* Read a wire integer that can be negative (a maker's fee rate is negative for
|
|
121
|
+
* a rebate): any safe integer, unlike {@link readSequence}.
|
|
122
|
+
*/
|
|
123
|
+
function readInteger(source, field) {
|
|
124
|
+
const value = source[field];
|
|
125
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value)) {
|
|
126
|
+
throw new Error(`Invalid WebSocket event: ${field} must be a safe integer`);
|
|
127
|
+
}
|
|
128
|
+
return value;
|
|
129
|
+
}
|
|
119
130
|
function readOptionalSequence(source, field) {
|
|
120
131
|
const value = source[field];
|
|
121
132
|
if (value === undefined || value === null)
|
|
@@ -395,6 +406,150 @@ function parseMarketLiquidationEvent(rawData) {
|
|
|
395
406
|
data: parseMarketLiquidationEventData(rawData.data),
|
|
396
407
|
};
|
|
397
408
|
}
|
|
409
|
+
/**
|
|
410
|
+
* Parse a new RFQ to quote. The `rfq` channel's wire keys are camelCase
|
|
411
|
+
* already (serde `rename_all = "camelCase"`), so they are read as sent, bar
|
|
412
|
+
* the `type` tag, surfaced as `eventType` (see {@link parseRfqEvent}). A
|
|
413
|
+
* two-way request carries neither side.
|
|
414
|
+
*/
|
|
415
|
+
function parseRfqRequestedEvent(raw) {
|
|
416
|
+
const oneWaySide = readOptionalEnumValue(raw, "oneWaySide");
|
|
417
|
+
const quoteSide = readOptionalEnumValue(raw, "quoteSide");
|
|
418
|
+
return {
|
|
419
|
+
eventType: "RfqRequested",
|
|
420
|
+
rfqId: readString(raw, "rfqId"),
|
|
421
|
+
tradingPairId: readString(raw, "tradingPairId"),
|
|
422
|
+
// Value fields: a product or side this SDK predates is passed through.
|
|
423
|
+
product: readString(raw, "product"),
|
|
424
|
+
quantity: readString(raw, "quantity"),
|
|
425
|
+
...(oneWaySide !== undefined && { oneWaySide }),
|
|
426
|
+
...(quoteSide !== undefined && { quoteSide }),
|
|
427
|
+
newQuoteCutoffAtMs: readSequence(raw, "newQuoteCutoffAtMs"),
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
function parseRfqSideViewEventData(raw) {
|
|
431
|
+
if (!isRecord(raw)) {
|
|
432
|
+
throw new Error("Invalid RFQ view: a side must be an object");
|
|
433
|
+
}
|
|
434
|
+
return {
|
|
435
|
+
vwap: readString(raw, "vwap"),
|
|
436
|
+
availableQuantity: readString(raw, "availableQuantity"),
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
/** Parse the taker's view. A side no maker quotes is absent. */
|
|
440
|
+
function parseRfqViewEventData(raw) {
|
|
441
|
+
if (!isRecord(raw)) {
|
|
442
|
+
throw new Error("Invalid RFQ view: view must be an object");
|
|
443
|
+
}
|
|
444
|
+
return {
|
|
445
|
+
viewVersion: readSequence(raw, "viewVersion"),
|
|
446
|
+
...(raw.bid != null && { bid: parseRfqSideViewEventData(raw.bid) }),
|
|
447
|
+
...(raw.ask != null && { ask: parseRfqSideViewEventData(raw.ask) }),
|
|
448
|
+
asOfMs: readSequence(raw, "asOfMs"),
|
|
449
|
+
sequence: readSequence(raw, "sequence"),
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
/** Parse a selected maker's own part of an acceptance. */
|
|
453
|
+
function parseRfqSelectionEventData(raw) {
|
|
454
|
+
if (!isRecord(raw)) {
|
|
455
|
+
throw new Error("Invalid RFQ selection: selection must be an object");
|
|
456
|
+
}
|
|
457
|
+
return {
|
|
458
|
+
acceptanceId: readString(raw, "acceptanceId"),
|
|
459
|
+
takerSide: readString(raw, "takerSide"),
|
|
460
|
+
makerAccountId: readString(raw, "makerAccountId"),
|
|
461
|
+
quoteId: readString(raw, "quoteId"),
|
|
462
|
+
quoteVersion: readSequence(raw, "quoteVersion"),
|
|
463
|
+
quantity: readString(raw, "quantity"),
|
|
464
|
+
price: readString(raw, "price"),
|
|
465
|
+
capacity: readString(raw, "capacity"),
|
|
466
|
+
makerFeeCbps: readInteger(raw, "makerFeeCbps"),
|
|
467
|
+
lastLookDeadlineAtMs: readSequence(raw, "lastLookDeadlineAtMs"),
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
function parseRfqFillEventData(raw) {
|
|
471
|
+
if (!isRecord(raw)) {
|
|
472
|
+
throw new Error("Invalid RFQ outcome: a fill must be an object");
|
|
473
|
+
}
|
|
474
|
+
return {
|
|
475
|
+
executionId: readString(raw, "executionId"),
|
|
476
|
+
price: readString(raw, "price"),
|
|
477
|
+
quantity: readString(raw, "quantity"),
|
|
478
|
+
fee: readString(raw, "fee"),
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
/** Parse the taker's outcome. Nothing filled leaves `vwap` absent and `fills` empty. */
|
|
482
|
+
function parseRfqOutcomeEventData(raw) {
|
|
483
|
+
if (!isRecord(raw)) {
|
|
484
|
+
throw new Error("Invalid RFQ outcome: outcome must be an object");
|
|
485
|
+
}
|
|
486
|
+
if (!Array.isArray(raw.fills)) {
|
|
487
|
+
throw new Error("Invalid RFQ outcome: fills must be an array");
|
|
488
|
+
}
|
|
489
|
+
const vwap = readOptionalDecimalString(raw, "vwap");
|
|
490
|
+
return {
|
|
491
|
+
executedQuantity: readString(raw, "executedQuantity"),
|
|
492
|
+
unfilledQuantity: readString(raw, "unfilledQuantity"),
|
|
493
|
+
...(vwap !== undefined && { vwap }),
|
|
494
|
+
fills: raw.fills.map(parseRfqFillEventData),
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
/** Parse an RFQ's end. Only the taker's push carries `outcome`. */
|
|
498
|
+
function parseRfqOutcomeEvent(raw) {
|
|
499
|
+
return {
|
|
500
|
+
eventType: "RfqOutcome",
|
|
501
|
+
rfqId: readString(raw, "rfqId"),
|
|
502
|
+
// A terminal state this SDK predates is passed through.
|
|
503
|
+
state: readString(raw, "state"),
|
|
504
|
+
...(raw.outcome != null && { outcome: parseRfqOutcomeEventData(raw.outcome) }),
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* Parse an `rfq` channel push. The wire's `type` is the channel-class
|
|
509
|
+
* discriminator that picks the payload shape, so it is matched strictly: a push
|
|
510
|
+
* of a type this SDK predates is rejected rather than parsed as the wrong
|
|
511
|
+
* shape. It is surfaced as `eventType`, the discriminator every other channel's
|
|
512
|
+
* events carry; no `type` key is kept.
|
|
513
|
+
*/
|
|
514
|
+
function parseRfqEvent(rawData) {
|
|
515
|
+
if (!isRecord(rawData)) {
|
|
516
|
+
throw new Error("Invalid RFQ event: payload must be an object");
|
|
517
|
+
}
|
|
518
|
+
const eventType = readEnum(rawData, "type", ["RfqRequested", "RfqView", "RfqSelected", "RfqOutcome"]);
|
|
519
|
+
switch (eventType) {
|
|
520
|
+
case "RfqRequested":
|
|
521
|
+
return parseRfqRequestedEvent(rawData);
|
|
522
|
+
case "RfqView":
|
|
523
|
+
return { eventType, rfqId: readString(rawData, "rfqId"), view: parseRfqViewEventData(rawData.view) };
|
|
524
|
+
case "RfqSelected":
|
|
525
|
+
return { eventType, rfqId: readString(rawData, "rfqId"), selection: parseRfqSelectionEventData(rawData.selection) };
|
|
526
|
+
case "RfqOutcome":
|
|
527
|
+
return parseRfqOutcomeEvent(rawData);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
function parseRfqTradeEventData(raw) {
|
|
531
|
+
if (!isRecord(raw)) {
|
|
532
|
+
throw new Error("Invalid RFQ trade event: data must be an object");
|
|
533
|
+
}
|
|
534
|
+
return {
|
|
535
|
+
executionId: readString(raw, "execution_id"),
|
|
536
|
+
price: readString(raw, "price"),
|
|
537
|
+
quantity: readString(raw, "quantity"),
|
|
538
|
+
executedAt: readString(raw, "executed_at"),
|
|
539
|
+
publishedAt: readString(raw, "published_at"),
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
/** Parse a public RFQ block print from `rfq_trades:<pair>`. */
|
|
543
|
+
function parseRfqTradeEvent(rawData) {
|
|
544
|
+
if (!isRecord(rawData)) {
|
|
545
|
+
throw new Error("Invalid RFQ trade event: payload must be an object");
|
|
546
|
+
}
|
|
547
|
+
return {
|
|
548
|
+
tradingPairId: readString(rawData, "trading_pair_id"),
|
|
549
|
+
tradingMode: readString(rawData, "trading_mode"),
|
|
550
|
+
data: parseRfqTradeEventData(rawData.data),
|
|
551
|
+
};
|
|
552
|
+
}
|
|
398
553
|
/**
|
|
399
554
|
* Parse an account's margin-health payload. Shared by the live event and the
|
|
400
555
|
* subscribe-time snapshot (see {@link parseConditionalOrderEventData}).
|
|
@@ -2310,6 +2465,38 @@ export function createMonacoWebSocket(baseUrl, options = {}, serverClock = new S
|
|
|
2310
2465
|
}
|
|
2311
2466
|
});
|
|
2312
2467
|
};
|
|
2468
|
+
/**
|
|
2469
|
+
* Subscribe to the authenticated account's RFQ pushes. The account comes from
|
|
2470
|
+
* the signed session, so the channel is just `rfq`; a subscribe the server
|
|
2471
|
+
* refuses for want of authentication is retried once the connection
|
|
2472
|
+
* authenticates, as on every private channel.
|
|
2473
|
+
*/
|
|
2474
|
+
const subscribeRfq = (handler) => {
|
|
2475
|
+
if (!handler) {
|
|
2476
|
+
throw new Error("rfq subscription requires a handler");
|
|
2477
|
+
}
|
|
2478
|
+
return subscribe("rfq", (rawData) => {
|
|
2479
|
+
try {
|
|
2480
|
+
handler(parseRfqEvent(rawData));
|
|
2481
|
+
}
|
|
2482
|
+
catch (err) {
|
|
2483
|
+
console.error("WebSocket: Error processing RFQ event", err);
|
|
2484
|
+
}
|
|
2485
|
+
});
|
|
2486
|
+
};
|
|
2487
|
+
const subscribeRfqTrades = (tradingPairId, handler) => {
|
|
2488
|
+
if (!handler) {
|
|
2489
|
+
throw new Error("rfqTrades subscription requires a handler");
|
|
2490
|
+
}
|
|
2491
|
+
return subscribe(`rfq_trades:${tradingPairId}`, (rawData) => {
|
|
2492
|
+
try {
|
|
2493
|
+
handler(parseRfqTradeEvent(rawData));
|
|
2494
|
+
}
|
|
2495
|
+
catch (err) {
|
|
2496
|
+
console.error("WebSocket: Error processing RFQ trade event", err);
|
|
2497
|
+
}
|
|
2498
|
+
});
|
|
2499
|
+
};
|
|
2313
2500
|
return {
|
|
2314
2501
|
connect,
|
|
2315
2502
|
disconnect,
|
|
@@ -2350,5 +2537,7 @@ export function createMonacoWebSocket(baseUrl, options = {}, serverClock = new S
|
|
|
2350
2537
|
marketStats: subscribeMarketStats,
|
|
2351
2538
|
marketStatsAll: subscribeMarketStatsAll,
|
|
2352
2539
|
marketLiquidations: subscribeMarketLiquidations,
|
|
2540
|
+
rfq: subscribeRfq,
|
|
2541
|
+
rfqTrades: subscribeRfqTrades,
|
|
2353
2542
|
};
|
|
2354
2543
|
}
|
package/dist/coverage.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export declare const COVERED: {
|
|
|
3
3
|
attach_position_tp_sl: string;
|
|
4
4
|
batch_cancel_all: string;
|
|
5
5
|
batch_cancel_all_by_pair: string;
|
|
6
|
+
cancel_all_after: string;
|
|
6
7
|
batch_cancel_orders: string;
|
|
7
8
|
batch_close_all_positions: string;
|
|
8
9
|
batch_create_orders: string;
|
|
@@ -26,6 +27,14 @@ export declare const COVERED: {
|
|
|
26
27
|
get_follow: string;
|
|
27
28
|
list_follow_leader_positions: string;
|
|
28
29
|
preview_follow: string;
|
|
30
|
+
get_rfq_capabilities: string;
|
|
31
|
+
create_rfq: string;
|
|
32
|
+
get_rfq: string;
|
|
33
|
+
accept_rfq: string;
|
|
34
|
+
cancel_rfq: string;
|
|
35
|
+
upsert_rfq_quote: string;
|
|
36
|
+
withdraw_rfq_quote: string;
|
|
37
|
+
respond_rfq_last_look: string;
|
|
29
38
|
cancel_twap_order: string;
|
|
30
39
|
create_twap_order: string;
|
|
31
40
|
get_twap_order: string;
|
|
@@ -98,6 +107,7 @@ export declare const COVERED: {
|
|
|
98
107
|
get_sub_account_limits: string;
|
|
99
108
|
get_trade_by_id: string;
|
|
100
109
|
get_trades: string;
|
|
110
|
+
list_trades: string;
|
|
101
111
|
get_trade_flow: string;
|
|
102
112
|
get_trader_metrics: string;
|
|
103
113
|
get_liquidation_metrics: string;
|
|
@@ -122,6 +132,8 @@ export declare const COVERED: {
|
|
|
122
132
|
list_delegated_agents: string;
|
|
123
133
|
list_funding_history: string;
|
|
124
134
|
list_liquidation_events: string;
|
|
135
|
+
list_all_liquidation_events: string;
|
|
136
|
+
list_insurance_funds: string;
|
|
125
137
|
list_funding_payments: string;
|
|
126
138
|
list_margin_accounts: string;
|
|
127
139
|
list_position_history: string;
|
package/dist/coverage.js
CHANGED
|
@@ -3,6 +3,7 @@ export const COVERED = {
|
|
|
3
3
|
attach_position_tp_sl: "attachPositionTpSl",
|
|
4
4
|
batch_cancel_all: "batchCancelAll",
|
|
5
5
|
batch_cancel_all_by_pair: "batchCancelAll (with tradingPairId)",
|
|
6
|
+
cancel_all_after: "cancelAllAfter",
|
|
6
7
|
batch_cancel_orders: "batchCancel",
|
|
7
8
|
batch_close_all_positions: "batchCloseAllPositions",
|
|
8
9
|
batch_create_orders: "batchCreate",
|
|
@@ -26,6 +27,14 @@ export const COVERED = {
|
|
|
26
27
|
get_follow: "copyTrading.getFollow",
|
|
27
28
|
list_follow_leader_positions: "copyTrading.listFollowLeaderPositions",
|
|
28
29
|
preview_follow: "copyTrading.previewFollow",
|
|
30
|
+
get_rfq_capabilities: "rfq.getCapabilities",
|
|
31
|
+
create_rfq: "rfq.createRfq",
|
|
32
|
+
get_rfq: "rfq.getRfq",
|
|
33
|
+
accept_rfq: "rfq.acceptRfq",
|
|
34
|
+
cancel_rfq: "rfq.cancelRfq",
|
|
35
|
+
upsert_rfq_quote: "rfq.upsertQuote",
|
|
36
|
+
withdraw_rfq_quote: "rfq.withdrawQuote",
|
|
37
|
+
respond_rfq_last_look: "rfq.respondLastLook",
|
|
29
38
|
cancel_twap_order: "cancelTwapOrder",
|
|
30
39
|
create_twap_order: "createTwapOrder",
|
|
31
40
|
get_twap_order: "getTwapOrder",
|
|
@@ -98,6 +107,7 @@ export const COVERED = {
|
|
|
98
107
|
get_sub_account_limits: "subAccounts.getLimits",
|
|
99
108
|
get_trade_by_id: "getTradeById",
|
|
100
109
|
get_trades: "getTrades",
|
|
110
|
+
list_trades: "listTrades",
|
|
101
111
|
get_trade_flow: "getTradeFlow",
|
|
102
112
|
get_trader_metrics: "getTraderMetrics",
|
|
103
113
|
get_liquidation_metrics: "getLiquidationMetrics",
|
|
@@ -122,6 +132,8 @@ export const COVERED = {
|
|
|
122
132
|
list_delegated_agents: "listDelegatedAgents",
|
|
123
133
|
list_funding_history: "listFundingHistory",
|
|
124
134
|
list_liquidation_events: "listLiquidationEvents",
|
|
135
|
+
list_all_liquidation_events: "listAllLiquidationEvents",
|
|
136
|
+
list_insurance_funds: "listInsuranceFunds",
|
|
125
137
|
list_funding_payments: "listFundingPayments",
|
|
126
138
|
list_margin_accounts: "listMarginAccounts",
|
|
127
139
|
list_position_history: "listPositionHistory",
|
package/dist/sdk.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ApplicationsAPI, AuthAPI, AuthState, BuildercodesAPI, ComplianceAPI, CopyTradingAPI, DelegatedAgentsAPI, FaucetAPI, FeesAPI, ManagedMarketsAPI, MarginAccountsAPI, MarketAPI, MonacoSDK, Network, PortfolioAPI, PositionsAPI, ProfileAPI, PulseAPI, SDKConfig, SubAccountsAPI, SweeperAPI, TraderCodesAPI, TradingAPI, VaultAPI, WithdrawalsAPI } from "@0xmonaco/types";
|
|
1
|
+
import type { ApplicationsAPI, AuthAPI, AuthState, BuildercodesAPI, ComplianceAPI, CopyTradingAPI, DelegatedAgentsAPI, FaucetAPI, FeesAPI, ManagedMarketsAPI, MarginAccountsAPI, MarketAPI, MonacoSDK, Network, PortfolioAPI, PositionsAPI, ProfileAPI, PulseAPI, RfqAPI, SDKConfig, SubAccountsAPI, SweeperAPI, TraderCodesAPI, TradingAPI, VaultAPI, WithdrawalsAPI } from "@0xmonaco/types";
|
|
2
2
|
import { type Address, type PublicClient, type TransactionReceipt, type WalletClient } from "viem";
|
|
3
3
|
import { type MonacoWebSocket, OrderbookAPIImpl, TradesAPIImpl } from "./api";
|
|
4
4
|
export declare class MonacoSDKImpl implements MonacoSDK {
|
|
@@ -8,6 +8,7 @@ export declare class MonacoSDKImpl implements MonacoSDK {
|
|
|
8
8
|
fees: FeesAPI;
|
|
9
9
|
buildercodes: BuildercodesAPI;
|
|
10
10
|
copyTrading: CopyTradingAPI;
|
|
11
|
+
rfq: RfqAPI;
|
|
11
12
|
tradercodes: TraderCodesAPI;
|
|
12
13
|
vault: VaultAPI;
|
|
13
14
|
withdrawals: WithdrawalsAPI;
|
package/dist/sdk.js
CHANGED
|
@@ -16,6 +16,7 @@ import { PortfolioAPIImpl } from "./api/portfolio";
|
|
|
16
16
|
import { PositionsAPIImpl } from "./api/positions";
|
|
17
17
|
import { ProfileAPIImpl } from "./api/profile";
|
|
18
18
|
import { PulseAPIImpl } from "./api/pulse";
|
|
19
|
+
import { RfqAPIImpl } from "./api/rfq";
|
|
19
20
|
import { SubAccountsAPIImpl } from "./api/sub-accounts";
|
|
20
21
|
import { SweeperAPIImpl } from "./api/sweeper";
|
|
21
22
|
import { TraderCodesAPIImpl } from "./api/tradercodes";
|
|
@@ -49,6 +50,7 @@ export class MonacoSDKImpl {
|
|
|
49
50
|
fees;
|
|
50
51
|
buildercodes;
|
|
51
52
|
copyTrading;
|
|
53
|
+
rfq;
|
|
52
54
|
tradercodes;
|
|
53
55
|
vault;
|
|
54
56
|
withdrawals;
|
|
@@ -83,6 +85,7 @@ export class MonacoSDKImpl {
|
|
|
83
85
|
this.fees.setSessionKeypair(credentials);
|
|
84
86
|
this.buildercodes.setSessionKeypair(credentials);
|
|
85
87
|
this.copyTrading.setSessionKeypair(credentials);
|
|
88
|
+
this.rfq.setSessionKeypair(credentials);
|
|
86
89
|
this.tradercodes.setSessionKeypair(credentials);
|
|
87
90
|
this.vault.setSessionKeypair(credentials);
|
|
88
91
|
this.withdrawals.setSessionKeypair(credentials);
|
|
@@ -173,6 +176,7 @@ export class MonacoSDKImpl {
|
|
|
173
176
|
this.fees = configureSigning(new FeesAPIImpl(apiUrl));
|
|
174
177
|
this.buildercodes = configureSigning(new BuildercodesAPIImpl(apiUrl));
|
|
175
178
|
this.copyTrading = configureSigning(new CopyTradingAPIImpl(apiUrl));
|
|
179
|
+
this.rfq = configureSigning(new RfqAPIImpl(apiUrl));
|
|
176
180
|
this.tradercodes = configureSigning(new TraderCodesAPIImpl(apiUrl));
|
|
177
181
|
this.profile = configureSigning(new ProfileAPIImpl(apiUrl));
|
|
178
182
|
this.vault = configureSigning(new VaultAPIImpl(this.publicClient, this.walletClient, this.chain, this.applications, this.profile, apiUrl));
|
|
@@ -7,7 +7,10 @@ export declare const MIN_BUCKETS_ALLOWED = 10;
|
|
|
7
7
|
*/
|
|
8
8
|
export declare const MAX_BUCKETS_ALLOWED = 10000000;
|
|
9
9
|
/**
|
|
10
|
-
* All possible magnitude values we support (from 0.
|
|
10
|
+
* All possible magnitude values we support (from 0.000001 to 10000).
|
|
11
|
+
*
|
|
12
|
+
* The finest grouping is the 6-decimal USDC unit, so every pair's tick has a
|
|
13
|
+
* grouping at its own precision (the SEI and FARTCOIN perps trade on 0.00001).
|
|
11
14
|
*/
|
|
12
15
|
export declare const ALL_MAGNITUDES: number[];
|
|
13
16
|
/**
|
|
@@ -21,6 +24,6 @@ export declare const ALL_MAGNITUDES: number[];
|
|
|
21
24
|
* @example
|
|
22
25
|
* calculateValidMagnitudes(112000); // [0.1, 1, 10, 100, 1000, 10000]
|
|
23
26
|
* calculateValidMagnitudes(4200); // [0.001, 0.01, 0.1, 1, 10, 100]
|
|
24
|
-
* calculateValidMagnitudes(0.5); // [0.0001, 0.001, 0.01]
|
|
27
|
+
* calculateValidMagnitudes(0.5); // [0.000001, 0.00001, 0.0001, 0.001, 0.01]
|
|
25
28
|
*/
|
|
26
29
|
export declare const calculateValidMagnitudes: (currentPrice: number) => number[];
|
package/dist/utils/magnitude.js
CHANGED
|
@@ -7,9 +7,12 @@ export const MIN_BUCKETS_ALLOWED = 10;
|
|
|
7
7
|
*/
|
|
8
8
|
export const MAX_BUCKETS_ALLOWED = 10_000_000;
|
|
9
9
|
/**
|
|
10
|
-
* All possible magnitude values we support (from 0.
|
|
10
|
+
* All possible magnitude values we support (from 0.000001 to 10000).
|
|
11
|
+
*
|
|
12
|
+
* The finest grouping is the 6-decimal USDC unit, so every pair's tick has a
|
|
13
|
+
* grouping at its own precision (the SEI and FARTCOIN perps trade on 0.00001).
|
|
11
14
|
*/
|
|
12
|
-
export const ALL_MAGNITUDES = [0.0001, 0.001, 0.01, 0.1, 1, 10, 100, 1000, 10000];
|
|
15
|
+
export const ALL_MAGNITUDES = [0.000001, 0.00001, 0.0001, 0.001, 0.01, 0.1, 1, 10, 100, 1000, 10000];
|
|
13
16
|
/**
|
|
14
17
|
* Calculate which magnitude levels are valid for a given price.
|
|
15
18
|
*
|
|
@@ -21,7 +24,7 @@ export const ALL_MAGNITUDES = [0.0001, 0.001, 0.01, 0.1, 1, 10, 100, 1000, 10000
|
|
|
21
24
|
* @example
|
|
22
25
|
* calculateValidMagnitudes(112000); // [0.1, 1, 10, 100, 1000, 10000]
|
|
23
26
|
* calculateValidMagnitudes(4200); // [0.001, 0.01, 0.1, 1, 10, 100]
|
|
24
|
-
* calculateValidMagnitudes(0.5); // [0.0001, 0.001, 0.01]
|
|
27
|
+
* calculateValidMagnitudes(0.5); // [0.000001, 0.00001, 0.0001, 0.001, 0.01]
|
|
25
28
|
*/
|
|
26
29
|
export const calculateValidMagnitudes = (currentPrice) => {
|
|
27
30
|
return ALL_MAGNITUDES.filter((magnitude) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@0xmonaco/core",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.5",
|
|
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.1.
|
|
23
|
-
"@0xmonaco/types": "1.1.
|
|
22
|
+
"@0xmonaco/contracts": "1.1.5",
|
|
23
|
+
"@0xmonaco/types": "1.1.5",
|
|
24
24
|
"@noble/curves": "^2.4.0",
|
|
25
25
|
"@noble/hashes": "^2.4.0",
|
|
26
26
|
"http-status-codes": "^2.3.0"
|