@0xmonaco/core 1.1.9 → 1.1.10
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 +35 -0
- package/dist/api/applications/api.d.ts +23 -2
- package/dist/api/applications/api.js +31 -2
- package/dist/api/perp/routes.d.ts +6 -0
- package/dist/api/perp/routes.js +1 -0
- package/dist/api/rfq/api.d.ts +9 -3
- package/dist/api/rfq/api.js +9 -3
- package/dist/api/rfq/index.d.ts +1 -0
- package/dist/api/rfq/index.js +1 -0
- package/dist/api/rfq/view.d.ts +45 -0
- package/dist/api/rfq/view.js +242 -0
- package/dist/api/trades/api.d.ts +66 -2
- package/dist/api/trades/api.js +58 -0
- package/dist/api/trading/api.d.ts +4 -5
- package/dist/api/trading/api.js +4 -5
- package/dist/api/websocket/websocket.js +5 -2
- package/dist/coverage.d.ts +1 -0
- package/dist/coverage.js +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -349,6 +349,41 @@ interface MarketAPI extends BaseAPI {
|
|
|
349
349
|
}
|
|
350
350
|
```
|
|
351
351
|
|
|
352
|
+
### RFQ API
|
|
353
|
+
|
|
354
|
+
RFQ (block trades): a taker requests quotes for a size, makers quote privately, the taker accepts one side of the aggregated view, and the selected makers get a 250 ms last look (silence executes). Available to accounts RFQ is enabled for; see the [RFQ guide](https://docs.0xmonaco.com/developers/rfq).
|
|
355
|
+
|
|
356
|
+
```typescript
|
|
357
|
+
interface RfqAPI extends BaseAPI {
|
|
358
|
+
getCapabilities(): Promise<GetRfqCapabilitiesResponse>;
|
|
359
|
+
// As taker
|
|
360
|
+
createRfq(params: CreateRfqParams): Promise<RfqStatus>;
|
|
361
|
+
getRfq(rfqId: string): Promise<RfqStatus>;
|
|
362
|
+
listRfqs(params?: ListRfqsParams): Promise<ListRfqsResponse>;
|
|
363
|
+
acceptRfq(rfqId: string, params: AcceptRfqParams): Promise<RfqStatus>;
|
|
364
|
+
cancelRfq(rfqId: string, params?: CancelRfqParams): Promise<RfqStatus>;
|
|
365
|
+
// As maker
|
|
366
|
+
upsertQuote(rfqId: string, params: UpsertRfqQuoteParams): Promise<RfqQuoteVersion>;
|
|
367
|
+
withdrawQuote(rfqId: string, params: WithdrawRfqQuoteParams): Promise<WithdrawRfqQuoteResponse>;
|
|
368
|
+
respondLastLook(rfqId: string, params: RespondRfqLastLookParams): Promise<RespondRfqLastLookResponse>;
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Pushes arrive on `sdk.ws.rfq(handler)` (authenticated), and public block prints on `sdk.ws.rfqTrades(tradingPairId, handler)`.
|
|
373
|
+
|
|
374
|
+
A taker waiting for quotes should follow its view on the `RfqView` pushes rather than poll `getRfq`: the view is pushed on every change, and every `getRfq` rebuilds it on the server. `waitForRfqView` does this, reading `getRfq` only when a push may have been missed (at the start, after a reconnect, while the socket is down, and at the timeout). It rejects with an `InvalidStateError` when no view matched by `timeoutMs` (default 10000) or the RFQ ended first.
|
|
375
|
+
|
|
376
|
+
```typescript
|
|
377
|
+
import { waitForRfqView } from "@0xmonaco/core";
|
|
378
|
+
|
|
379
|
+
const rfq = await sdk.rfq.createRfq({ tradingPairId, product: "PERPETUAL", quantity: "25", leverage: "2" });
|
|
380
|
+
const rfqId = rfq.terms!.rfqId;
|
|
381
|
+
const { view } = await waitForRfqView(sdk, rfqId, (view) => view.ask?.availableQuantity === "25", {
|
|
382
|
+
initialView: rfq.view,
|
|
383
|
+
});
|
|
384
|
+
await sdk.rfq.acceptRfq(rfqId, { side: "BUY", viewVersion: view.viewVersion });
|
|
385
|
+
```
|
|
386
|
+
|
|
352
387
|
### WebSocket Authentication
|
|
353
388
|
|
|
354
389
|
The SDK provides three WebSocket clients with different authentication requirements:
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* const orders = await applicationsAPI.listApplicationOrders({ clientId: config.clientId, status: "FILLED" });
|
|
19
19
|
* ```
|
|
20
20
|
*/
|
|
21
|
-
import type { ApplicationConfigResponse, ApplicationsAPI, GetAppStatsParams, GetAppStatsResponse, ListAppBalancesParams, ListAppBalancesResponse, ListAppMovementsParams, ListAppMovementsResponse, ListAppOrdersParams, ListAppOrdersResponse, ListAppUsersParams, ListAppUsersResponse } from "@0xmonaco/types";
|
|
21
|
+
import type { ApplicationConfigResponse, ApplicationsAPI, GetAppStatsParams, GetAppStatsResponse, ListAppBalancesParams, ListAppBalancesResponse, ListAppMarginAccountsParams, ListAppMarginAccountsResponse, ListAppMovementsParams, ListAppMovementsResponse, ListAppOrdersParams, ListAppOrdersResponse, ListAppUsersParams, ListAppUsersResponse } from "@0xmonaco/types";
|
|
22
22
|
import { BaseAPI } from "../base";
|
|
23
23
|
export declare class ApplicationsAPIImpl extends BaseAPI implements ApplicationsAPI {
|
|
24
24
|
/**
|
|
@@ -96,7 +96,11 @@ export declare class ApplicationsAPIImpl extends BaseAPI implements Applications
|
|
|
96
96
|
*/
|
|
97
97
|
listApplicationMovements(params: ListAppMovementsParams): Promise<ListAppMovementsResponse>;
|
|
98
98
|
/**
|
|
99
|
-
* Lists user balances held within the application.
|
|
99
|
+
* Lists user wallet balances held within the application.
|
|
100
|
+
*
|
|
101
|
+
* Funds held in a margin account are not included, so a user funded through
|
|
102
|
+
* margin can show zero here. Read those users from
|
|
103
|
+
* `GET /api/v1/applications/margin-accounts` (`listApplicationMarginAccounts`).
|
|
100
104
|
*
|
|
101
105
|
* Public — the application is selected by `params.clientId`.
|
|
102
106
|
*
|
|
@@ -113,6 +117,23 @@ export declare class ApplicationsAPIImpl extends BaseAPI implements Applications
|
|
|
113
117
|
* @throws {APIError} When the request fails (404 for an unknown, inactive or hidden client ID, 429 when rate limited)
|
|
114
118
|
*/
|
|
115
119
|
listApplicationBalances(params: ListAppBalancesParams): Promise<ListAppBalancesResponse>;
|
|
120
|
+
/**
|
|
121
|
+
* Lists the application's margin accounts, sub-accounts included.
|
|
122
|
+
*
|
|
123
|
+
* Margin collateral is not a wallet balance, so an application that funds its
|
|
124
|
+
* users through margin reads it here, not from `listApplicationBalances`.
|
|
125
|
+
* Figures are a persisted baseline repriced at the latest risk marks, so they
|
|
126
|
+
* can briefly lag the matching engine. Copy-trading accounts are not listed.
|
|
127
|
+
* Public — the application is selected by `params.clientId`.
|
|
128
|
+
*
|
|
129
|
+
* Cursor paged: omit `pageToken` or pass `""` to start, then follow
|
|
130
|
+
* `nextPageToken` until it comes back empty.
|
|
131
|
+
*
|
|
132
|
+
* @param params - Pagination and filter options
|
|
133
|
+
* @returns Promise resolving to a paginated list of margin accounts
|
|
134
|
+
* @throws {APIError} When the request fails (404 for an unknown, inactive or hidden client ID, 429 when rate limited)
|
|
135
|
+
*/
|
|
136
|
+
listApplicationMarginAccounts(params: ListAppMarginAccountsParams): Promise<ListAppMarginAccountsResponse>;
|
|
116
137
|
/**
|
|
117
138
|
* Gets aggregate volume and fee stats for the application.
|
|
118
139
|
*
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* const orders = await applicationsAPI.listApplicationOrders({ clientId: config.clientId, status: "FILLED" });
|
|
19
19
|
* ```
|
|
20
20
|
*/
|
|
21
|
-
import { ListAppBalancesSchema, ListAppMovementsSchema, ListAppOrdersSchema, ListAppUsersSchema, validate } from "@0xmonaco/types";
|
|
21
|
+
import { ListAppBalancesSchema, ListAppMarginAccountsSchema, ListAppMovementsSchema, ListAppOrdersSchema, ListAppUsersSchema, validate } from "@0xmonaco/types";
|
|
22
22
|
import { BaseAPI } from "../base";
|
|
23
23
|
import { perpRoutes } from "../perp/routes";
|
|
24
24
|
export class ApplicationsAPIImpl extends BaseAPI {
|
|
@@ -142,7 +142,11 @@ export class ApplicationsAPIImpl extends BaseAPI {
|
|
|
142
142
|
}));
|
|
143
143
|
}
|
|
144
144
|
/**
|
|
145
|
-
* Lists user balances held within the application.
|
|
145
|
+
* Lists user wallet balances held within the application.
|
|
146
|
+
*
|
|
147
|
+
* Funds held in a margin account are not included, so a user funded through
|
|
148
|
+
* margin can show zero here. Read those users from
|
|
149
|
+
* `GET /api/v1/applications/margin-accounts` (`listApplicationMarginAccounts`).
|
|
146
150
|
*
|
|
147
151
|
* Public — the application is selected by `params.clientId`.
|
|
148
152
|
*
|
|
@@ -168,6 +172,31 @@ export class ApplicationsAPIImpl extends BaseAPI {
|
|
|
168
172
|
assetId: params.assetId,
|
|
169
173
|
}));
|
|
170
174
|
}
|
|
175
|
+
/**
|
|
176
|
+
* Lists the application's margin accounts, sub-accounts included.
|
|
177
|
+
*
|
|
178
|
+
* Margin collateral is not a wallet balance, so an application that funds its
|
|
179
|
+
* users through margin reads it here, not from `listApplicationBalances`.
|
|
180
|
+
* Figures are a persisted baseline repriced at the latest risk marks, so they
|
|
181
|
+
* can briefly lag the matching engine. Copy-trading accounts are not listed.
|
|
182
|
+
* Public — the application is selected by `params.clientId`.
|
|
183
|
+
*
|
|
184
|
+
* Cursor paged: omit `pageToken` or pass `""` to start, then follow
|
|
185
|
+
* `nextPageToken` until it comes back empty.
|
|
186
|
+
*
|
|
187
|
+
* @param params - Pagination and filter options
|
|
188
|
+
* @returns Promise resolving to a paginated list of margin accounts
|
|
189
|
+
* @throws {APIError} When the request fails (404 for an unknown, inactive or hidden client ID, 429 when rate limited)
|
|
190
|
+
*/
|
|
191
|
+
async listApplicationMarginAccounts(params) {
|
|
192
|
+
validate(ListAppMarginAccountsSchema, params);
|
|
193
|
+
return await this.makePublicRequest(perpRoutes.applications.marginAccounts({
|
|
194
|
+
clientId: params.clientId,
|
|
195
|
+
address: params.address,
|
|
196
|
+
pageSize: params.pageSize,
|
|
197
|
+
pageToken: params.pageToken,
|
|
198
|
+
}));
|
|
199
|
+
}
|
|
171
200
|
/**
|
|
172
201
|
* Gets aggregate volume and fee stats for the application.
|
|
173
202
|
*
|
|
@@ -246,6 +246,12 @@ export declare const perpRoutes: {
|
|
|
246
246
|
userId?: string;
|
|
247
247
|
assetId?: string;
|
|
248
248
|
}) => string;
|
|
249
|
+
readonly marginAccounts: (params?: {
|
|
250
|
+
clientId?: string;
|
|
251
|
+
address?: string;
|
|
252
|
+
pageSize?: number;
|
|
253
|
+
pageToken?: string;
|
|
254
|
+
}) => string;
|
|
249
255
|
readonly stats: (params?: {
|
|
250
256
|
clientId?: string;
|
|
251
257
|
since?: string;
|
package/dist/api/perp/routes.js
CHANGED
|
@@ -102,6 +102,7 @@ export const perpRoutes = {
|
|
|
102
102
|
users: (params) => withQuery(`${API_V1}/applications/users`, params),
|
|
103
103
|
movements: (params) => withQuery(`${API_V1}/applications/movements`, params),
|
|
104
104
|
balances: (params) => withQuery(`${API_V1}/applications/balances`, params),
|
|
105
|
+
marginAccounts: (params) => withQuery(`${API_V1}/applications/margin-accounts`, params),
|
|
105
106
|
stats: (params) => withQuery(`${API_V1}/applications/stats`, params),
|
|
106
107
|
},
|
|
107
108
|
subAccounts: {
|
package/dist/api/rfq/api.d.ts
CHANGED
|
@@ -14,12 +14,17 @@
|
|
|
14
14
|
* the gateway rejects unknown fields and stores a maker's request exactly as
|
|
15
15
|
* signed.
|
|
16
16
|
*
|
|
17
|
+
* A taker waiting for quotes follows its view on the `rfq` WebSocket
|
|
18
|
+
* channel (`waitForRfqView`) rather than polling `getRfq`: the view is
|
|
19
|
+
* pushed on every change, and every `getRfq` rebuilds it on the server.
|
|
20
|
+
*
|
|
17
21
|
* @example
|
|
18
22
|
* ```typescript
|
|
19
23
|
* // Taker
|
|
20
24
|
* const rfq = await sdk.rfq.createRfq({ tradingPairId, product: "PERPETUAL", quantity: "25" });
|
|
21
|
-
* const
|
|
22
|
-
* await sdk
|
|
25
|
+
* const rfqId = rfq.terms!.rfqId;
|
|
26
|
+
* const { view } = await waitForRfqView(sdk, rfqId, (view) => view.ask?.availableQuantity === "25", { initialView: rfq.view });
|
|
27
|
+
* await sdk.rfq.acceptRfq(rfqId, { side: "BUY", viewVersion: view.viewVersion });
|
|
23
28
|
*
|
|
24
29
|
* // Maker
|
|
25
30
|
* const quote = await sdk.rfq.upsertQuote(rfqId, { expectedVersion: 0, ask: { price: "65001", capacity: "10" } });
|
|
@@ -41,7 +46,8 @@ export declare class RfqAPIImpl extends BaseAPI implements RfqAPI {
|
|
|
41
46
|
/**
|
|
42
47
|
* An RFQ's authoritative status. As taker: the current `view` and, once
|
|
43
48
|
* executed, the `outcome`. As maker: your latest quote, `ownLatestVersion`
|
|
44
|
-
* and, once selected, `ownSelection` for last look.
|
|
49
|
+
* and, once selected, `ownSelection` for last look. To wait for quotes,
|
|
50
|
+
* follow the `RfqView` pushes (`waitForRfqView`) instead of polling.
|
|
45
51
|
*/
|
|
46
52
|
getRfq(rfqId: string): Promise<RfqStatus>;
|
|
47
53
|
/**
|
package/dist/api/rfq/api.js
CHANGED
|
@@ -14,12 +14,17 @@
|
|
|
14
14
|
* the gateway rejects unknown fields and stores a maker's request exactly as
|
|
15
15
|
* signed.
|
|
16
16
|
*
|
|
17
|
+
* A taker waiting for quotes follows its view on the `rfq` WebSocket
|
|
18
|
+
* channel (`waitForRfqView`) rather than polling `getRfq`: the view is
|
|
19
|
+
* pushed on every change, and every `getRfq` rebuilds it on the server.
|
|
20
|
+
*
|
|
17
21
|
* @example
|
|
18
22
|
* ```typescript
|
|
19
23
|
* // Taker
|
|
20
24
|
* const rfq = await sdk.rfq.createRfq({ tradingPairId, product: "PERPETUAL", quantity: "25" });
|
|
21
|
-
* const
|
|
22
|
-
* await sdk
|
|
25
|
+
* const rfqId = rfq.terms!.rfqId;
|
|
26
|
+
* const { view } = await waitForRfqView(sdk, rfqId, (view) => view.ask?.availableQuantity === "25", { initialView: rfq.view });
|
|
27
|
+
* await sdk.rfq.acceptRfq(rfqId, { side: "BUY", viewVersion: view.viewVersion });
|
|
23
28
|
*
|
|
24
29
|
* // Maker
|
|
25
30
|
* const quote = await sdk.rfq.upsertQuote(rfqId, { expectedVersion: 0, ask: { price: "65001", capacity: "10" } });
|
|
@@ -62,7 +67,8 @@ export class RfqAPIImpl extends BaseAPI {
|
|
|
62
67
|
/**
|
|
63
68
|
* An RFQ's authoritative status. As taker: the current `view` and, once
|
|
64
69
|
* executed, the `outcome`. As maker: your latest quote, `ownLatestVersion`
|
|
65
|
-
* and, once selected, `ownSelection` for last look.
|
|
70
|
+
* and, once selected, `ownSelection` for last look. To wait for quotes,
|
|
71
|
+
* follow the `RfqView` pushes (`waitForRfqView`) instead of polling.
|
|
66
72
|
*/
|
|
67
73
|
async getRfq(rfqId) {
|
|
68
74
|
return await this.makeAuthenticatedRequest(rfqPath(rfqId), { method: "GET" });
|
package/dist/api/rfq/index.d.ts
CHANGED
package/dist/api/rfq/index.js
CHANGED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The taker's RFQ view from the `rfq` WebSocket channel.
|
|
3
|
+
*
|
|
4
|
+
* The RFQ service pushes the taker its view (`RfqView`) every time the quotes
|
|
5
|
+
* change, so a taker waiting for the quotes it wants should follow those
|
|
6
|
+
* pushes instead of polling `getRfq`: every `getRfq` builds the whole view on
|
|
7
|
+
* the RFQ service. {@link waitForRfqView} does that, and reads the RFQ only
|
|
8
|
+
* when a push may have been missed.
|
|
9
|
+
*/
|
|
10
|
+
import type { MonacoWebSocket, RfqAPI, RfqView, RfqViewMatch, WaitForRfqViewOptions } from "@0xmonaco/types";
|
|
11
|
+
/** What {@link waitForRfqView} reads from: the SDK itself (`sdk`) has both. */
|
|
12
|
+
export interface RfqViewSource {
|
|
13
|
+
rfq: Pick<RfqAPI, "getRfq">;
|
|
14
|
+
ws: Pick<MonacoWebSocket, "rfq" | "isConnected" | "getSubscriptionState" | "onSubscriptionChange">;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Wait for the taker's view of `rfqId` to satisfy `predicate`, from the
|
|
18
|
+
* `RfqView` pushes on the `rfq` channel (the one with the highest `sequence`
|
|
19
|
+
* wins; pushes can arrive out of order).
|
|
20
|
+
*
|
|
21
|
+
* `getRfq` is read only where a push may have been missed:
|
|
22
|
+
* - once at the start, or, while the `rfq` subscribe is unanswered, once
|
|
23
|
+
* when it is confirmed: pushes sent before the wait began (makers can
|
|
24
|
+
* quote before `createRfq` returns) are not replayed to it;
|
|
25
|
+
* - once more on every confirmed resubscribe (after a reconnect);
|
|
26
|
+
* - repeatedly (250 ms, doubling to 2 s) while the socket is not connected or
|
|
27
|
+
* the subscription is not confirmed, including when it drops mid-wait;
|
|
28
|
+
* - once when `timeoutMs` passes without a match.
|
|
29
|
+
* A read that a newer push overlapped is dropped (the pushes decide); the
|
|
30
|
+
* final read is retried, up to 3 times, until one is not overlapped.
|
|
31
|
+
*
|
|
32
|
+
* Resolves with the first view that matches. Rejects with an
|
|
33
|
+
* `InvalidStateError` when no view matched by the timeout, or when an
|
|
34
|
+
* `RfqOutcome` push says the RFQ ended; with the signal's reason when aborted;
|
|
35
|
+
* and with the error of the final read if that read fails.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* const rfq = await sdk.rfq.createRfq({ tradingPairId, product: "PERPETUAL", quantity: "25" });
|
|
40
|
+
* const rfqId = rfq.terms!.rfqId;
|
|
41
|
+
* const { view } = await waitForRfqView(sdk, rfqId, (view) => view.ask?.availableQuantity === "25", { initialView: rfq.view });
|
|
42
|
+
* await sdk.rfq.acceptRfq(rfqId, { side: "BUY", viewVersion: view.viewVersion });
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare function waitForRfqView(source: RfqViewSource, rfqId: string, predicate: (view: RfqView) => boolean, options?: WaitForRfqViewOptions): Promise<RfqViewMatch>;
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The taker's RFQ view from the `rfq` WebSocket channel.
|
|
3
|
+
*
|
|
4
|
+
* The RFQ service pushes the taker its view (`RfqView`) every time the quotes
|
|
5
|
+
* change, so a taker waiting for the quotes it wants should follow those
|
|
6
|
+
* pushes instead of polling `getRfq`: every `getRfq` builds the whole view on
|
|
7
|
+
* the RFQ service. {@link waitForRfqView} does that, and reads the RFQ only
|
|
8
|
+
* when a push may have been missed.
|
|
9
|
+
*/
|
|
10
|
+
import { UUIDSchema, validate } from "@0xmonaco/types";
|
|
11
|
+
import { InvalidStateError } from "../../errors";
|
|
12
|
+
const RFQ_CHANNEL = "rfq";
|
|
13
|
+
const DEFAULT_TIMEOUT_MS = 10_000;
|
|
14
|
+
/** Reads while no push can arrive start at this pause and double up to the cap. */
|
|
15
|
+
const FIRST_POLL_PAUSE_MS = 250;
|
|
16
|
+
const MAX_POLL_PAUSE_MS = 2_000;
|
|
17
|
+
/** Final reads tried when a newer push keeps overlapping them. */
|
|
18
|
+
const FINAL_READ_ATTEMPTS = 3;
|
|
19
|
+
/**
|
|
20
|
+
* Wait for the taker's view of `rfqId` to satisfy `predicate`, from the
|
|
21
|
+
* `RfqView` pushes on the `rfq` channel (the one with the highest `sequence`
|
|
22
|
+
* wins; pushes can arrive out of order).
|
|
23
|
+
*
|
|
24
|
+
* `getRfq` is read only where a push may have been missed:
|
|
25
|
+
* - once at the start, or, while the `rfq` subscribe is unanswered, once
|
|
26
|
+
* when it is confirmed: pushes sent before the wait began (makers can
|
|
27
|
+
* quote before `createRfq` returns) are not replayed to it;
|
|
28
|
+
* - once more on every confirmed resubscribe (after a reconnect);
|
|
29
|
+
* - repeatedly (250 ms, doubling to 2 s) while the socket is not connected or
|
|
30
|
+
* the subscription is not confirmed, including when it drops mid-wait;
|
|
31
|
+
* - once when `timeoutMs` passes without a match.
|
|
32
|
+
* A read that a newer push overlapped is dropped (the pushes decide); the
|
|
33
|
+
* final read is retried, up to 3 times, until one is not overlapped.
|
|
34
|
+
*
|
|
35
|
+
* Resolves with the first view that matches. Rejects with an
|
|
36
|
+
* `InvalidStateError` when no view matched by the timeout, or when an
|
|
37
|
+
* `RfqOutcome` push says the RFQ ended; with the signal's reason when aborted;
|
|
38
|
+
* and with the error of the final read if that read fails.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const rfq = await sdk.rfq.createRfq({ tradingPairId, product: "PERPETUAL", quantity: "25" });
|
|
43
|
+
* const rfqId = rfq.terms!.rfqId;
|
|
44
|
+
* const { view } = await waitForRfqView(sdk, rfqId, (view) => view.ask?.availableQuantity === "25", { initialView: rfq.view });
|
|
45
|
+
* await sdk.rfq.acceptRfq(rfqId, { side: "BUY", viewVersion: view.viewVersion });
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export function waitForRfqView(source, rfqId, predicate, options = {}) {
|
|
49
|
+
const id = validate(UUIDSchema, rfqId);
|
|
50
|
+
const { timeoutMs = DEFAULT_TIMEOUT_MS, initialView, signal } = options;
|
|
51
|
+
return new Promise((resolve, reject) => {
|
|
52
|
+
if (signal?.aborted) {
|
|
53
|
+
reject(signal.reason);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
let settled = false;
|
|
57
|
+
let latestSequence = -1;
|
|
58
|
+
/** `RfqView` pushes of this RFQ newer than every earlier one, so far. */
|
|
59
|
+
let pushesSeen = 0;
|
|
60
|
+
let pollTimer;
|
|
61
|
+
let pollPause = FIRST_POLL_PAUSE_MS;
|
|
62
|
+
let polling = false;
|
|
63
|
+
let reading = false;
|
|
64
|
+
let readAgain = false;
|
|
65
|
+
const cleanups = [];
|
|
66
|
+
const stop = () => {
|
|
67
|
+
settled = true;
|
|
68
|
+
polling = false;
|
|
69
|
+
clearTimeout(pollTimer);
|
|
70
|
+
for (const cleanup of cleanups.splice(0))
|
|
71
|
+
cleanup();
|
|
72
|
+
};
|
|
73
|
+
const finish = (match) => {
|
|
74
|
+
if (settled)
|
|
75
|
+
return;
|
|
76
|
+
stop();
|
|
77
|
+
resolve(match);
|
|
78
|
+
};
|
|
79
|
+
const fail = (error) => {
|
|
80
|
+
if (settled)
|
|
81
|
+
return;
|
|
82
|
+
stop();
|
|
83
|
+
reject(error);
|
|
84
|
+
};
|
|
85
|
+
/** True when `view` matched (and the wait is over). */
|
|
86
|
+
const consider = (view, from) => {
|
|
87
|
+
try {
|
|
88
|
+
if (predicate(view)) {
|
|
89
|
+
finish({ view, source: from });
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
fail(error);
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
return false;
|
|
98
|
+
};
|
|
99
|
+
if (initialView && consider(initialView, "initial"))
|
|
100
|
+
return;
|
|
101
|
+
/**
|
|
102
|
+
* One `getRfq`; errors only matter to the final read. `overlapped` when a
|
|
103
|
+
* newer push arrived while it was in flight: a read has no `sequence`, so
|
|
104
|
+
* it may be older than that push. Anything newer than the latest push is
|
|
105
|
+
* pushed too (the service always pushes the last change), so while the
|
|
106
|
+
* wait goes on the pushes decide.
|
|
107
|
+
*/
|
|
108
|
+
const read = async () => {
|
|
109
|
+
const before = pushesSeen;
|
|
110
|
+
const status = await source.rfq.getRfq(id);
|
|
111
|
+
return { view: status.view ?? undefined, overlapped: pushesSeen !== before };
|
|
112
|
+
};
|
|
113
|
+
const catchUp = async () => {
|
|
114
|
+
if (settled)
|
|
115
|
+
return;
|
|
116
|
+
if (reading) {
|
|
117
|
+
// The read in flight may predate what asked for this one.
|
|
118
|
+
readAgain = true;
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
reading = true;
|
|
122
|
+
try {
|
|
123
|
+
const { view, overlapped } = await read();
|
|
124
|
+
if (!settled && view && !overlapped)
|
|
125
|
+
consider(view, "read");
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
// A push or the final read decides.
|
|
129
|
+
}
|
|
130
|
+
finally {
|
|
131
|
+
reading = false;
|
|
132
|
+
}
|
|
133
|
+
if (readAgain) {
|
|
134
|
+
readAgain = false;
|
|
135
|
+
await catchUp();
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
const stopPolling = () => {
|
|
139
|
+
polling = false;
|
|
140
|
+
clearTimeout(pollTimer);
|
|
141
|
+
pollTimer = undefined;
|
|
142
|
+
pollPause = FIRST_POLL_PAUSE_MS;
|
|
143
|
+
};
|
|
144
|
+
const poll = async () => {
|
|
145
|
+
pollTimer = undefined;
|
|
146
|
+
if (!polling || settled)
|
|
147
|
+
return;
|
|
148
|
+
await catchUp();
|
|
149
|
+
if (!polling || settled)
|
|
150
|
+
return;
|
|
151
|
+
if (pushesFlow()) {
|
|
152
|
+
stopPolling();
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
pollTimer = setTimeout(poll, pollPause);
|
|
156
|
+
pollPause = Math.min(pollPause * 2, MAX_POLL_PAUSE_MS);
|
|
157
|
+
};
|
|
158
|
+
const startPolling = () => {
|
|
159
|
+
if (polling || settled)
|
|
160
|
+
return;
|
|
161
|
+
polling = true;
|
|
162
|
+
void poll();
|
|
163
|
+
};
|
|
164
|
+
const pushesFlow = () => source.ws.isConnected() && source.ws.getSubscriptionState(RFQ_CHANNEL) === "subscribed";
|
|
165
|
+
/** No push can arrive: the socket is down, or the subscribe was not taken. */
|
|
166
|
+
const pushesCannotArrive = () => {
|
|
167
|
+
const state = source.ws.getSubscriptionState(RFQ_CHANNEL);
|
|
168
|
+
return !source.ws.isConnected() || (state !== "subscribed" && state !== "pending");
|
|
169
|
+
};
|
|
170
|
+
// Subscribed first, so nothing pushed from here on is missed.
|
|
171
|
+
cleanups.push(source.ws.rfq((event) => {
|
|
172
|
+
if (settled || event.rfqId !== id)
|
|
173
|
+
return;
|
|
174
|
+
if (event.eventType === "RfqOutcome") {
|
|
175
|
+
fail(new InvalidStateError(`RFQ ${id} ended ${event.state} before a view matched`, event.state, "COLLECTING"));
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
if (event.eventType !== "RfqView" || event.view.sequence <= latestSequence)
|
|
179
|
+
return;
|
|
180
|
+
latestSequence = event.view.sequence;
|
|
181
|
+
pushesSeen += 1;
|
|
182
|
+
consider(event.view, "push");
|
|
183
|
+
}));
|
|
184
|
+
// A confirmed (re)subscribe: what changed before it was never pushed to
|
|
185
|
+
// this handler, so read once and stop any polling.
|
|
186
|
+
cleanups.push(source.ws.onSubscriptionChange((change) => {
|
|
187
|
+
if (settled || change.channel !== RFQ_CHANNEL)
|
|
188
|
+
return;
|
|
189
|
+
if (change.state === "subscribed") {
|
|
190
|
+
stopPolling();
|
|
191
|
+
void catchUp();
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
startPolling();
|
|
195
|
+
}
|
|
196
|
+
}));
|
|
197
|
+
// The last word: a read no newer push overlapped, tried a few times.
|
|
198
|
+
const timer = setTimeout(async () => {
|
|
199
|
+
if (settled)
|
|
200
|
+
return;
|
|
201
|
+
stopPolling();
|
|
202
|
+
try {
|
|
203
|
+
for (let attempt = 0; attempt < FINAL_READ_ATTEMPTS && !settled; attempt++) {
|
|
204
|
+
const { view, overlapped } = await read();
|
|
205
|
+
if (settled)
|
|
206
|
+
return;
|
|
207
|
+
if (overlapped)
|
|
208
|
+
continue;
|
|
209
|
+
if (view && consider(view, "read"))
|
|
210
|
+
return;
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
fail(new InvalidStateError(`No view of RFQ ${id} matched within ${timeoutMs} ms`));
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
fail(error);
|
|
217
|
+
}
|
|
218
|
+
}, timeoutMs);
|
|
219
|
+
cleanups.push(() => clearTimeout(timer));
|
|
220
|
+
if (signal) {
|
|
221
|
+
const onAbort = () => fail(signal.reason);
|
|
222
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
223
|
+
cleanups.push(() => signal.removeEventListener("abort", onAbort));
|
|
224
|
+
}
|
|
225
|
+
// A dropped socket fires no subscription change: check it locally, and
|
|
226
|
+
// read until pushes can arrive again.
|
|
227
|
+
const liveness = setInterval(() => {
|
|
228
|
+
if (!settled && pushesCannotArrive())
|
|
229
|
+
startPolling();
|
|
230
|
+
}, FIRST_POLL_PAUSE_MS);
|
|
231
|
+
cleanups.push(() => clearInterval(liveness));
|
|
232
|
+
// What was pushed before this wait subscribed is gone: read it once now,
|
|
233
|
+
// or, while the subscribe is unanswered, when it is confirmed. With no
|
|
234
|
+
// push able to arrive yet, read until one can.
|
|
235
|
+
if (pushesCannotArrive()) {
|
|
236
|
+
startPolling();
|
|
237
|
+
}
|
|
238
|
+
else if (source.ws.getSubscriptionState(RFQ_CHANNEL) === "subscribed") {
|
|
239
|
+
void catchUp();
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
}
|
package/dist/api/trades/api.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ export declare function parseRawTradeEvent(raw: RawTradeEvent): TradeEvent;
|
|
|
34
34
|
/**
|
|
35
35
|
* Options for fetching trades
|
|
36
36
|
*/
|
|
37
|
-
|
|
37
|
+
interface TradesPageOptions {
|
|
38
38
|
/** Maximum number of records to return (default: 25, max: 1000) */
|
|
39
39
|
pageSize?: number;
|
|
40
40
|
/**
|
|
@@ -43,10 +43,55 @@ export interface GetTradesOptions {
|
|
|
43
43
|
*/
|
|
44
44
|
pageToken?: string;
|
|
45
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Options for fetching a pair's trades
|
|
48
|
+
*/
|
|
49
|
+
export interface GetTradesOptions extends TradesPageOptions {
|
|
50
|
+
/**
|
|
51
|
+
* The execution source to keep: `"RFQ"` (RFQ block fills, the history
|
|
52
|
+
* behind `rfqTrades`) or `"CLOB"` (order-book fills), the values of each
|
|
53
|
+
* trade's `data.executionSource`. Omit for every fill. A page token is tied
|
|
54
|
+
* to the filter it was minted under.
|
|
55
|
+
*/
|
|
56
|
+
executionSource?: "RFQ" | "CLOB";
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Options for recovering missed RFQ prints.
|
|
60
|
+
*/
|
|
61
|
+
export interface RecoverRfqTradesOptions {
|
|
62
|
+
/**
|
|
63
|
+
* The newest `executionId` the caller already has. Recovery stops at it;
|
|
64
|
+
* omit to read only the newest page.
|
|
65
|
+
*/
|
|
66
|
+
sinceExecutionId?: string;
|
|
67
|
+
/** Rows per page (default: 100, max: 1000). */
|
|
68
|
+
pageSize?: number;
|
|
69
|
+
/**
|
|
70
|
+
* Most pages to read before giving up (default: 10). A `sinceExecutionId`
|
|
71
|
+
* not found within this many pages is reported as `complete: false`.
|
|
72
|
+
*/
|
|
73
|
+
maxPages?: number;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The RFQ prints a caller missed, oldest first.
|
|
77
|
+
*/
|
|
78
|
+
export interface RecoveredRfqTrades {
|
|
79
|
+
/**
|
|
80
|
+
* RFQ fills newer than `sinceExecutionId`, plus the other fills sharing its
|
|
81
|
+
* execution time, oldest first. Deduplicate by `executionId` on replay.
|
|
82
|
+
*/
|
|
83
|
+
trades: TradeEvent[];
|
|
84
|
+
/**
|
|
85
|
+
* `true` when the walk reached `sinceExecutionId` or the start of the
|
|
86
|
+
* pair's history; `false` when it stopped at `maxPages`, so older prints may
|
|
87
|
+
* still be missing.
|
|
88
|
+
*/
|
|
89
|
+
complete: boolean;
|
|
90
|
+
}
|
|
46
91
|
/**
|
|
47
92
|
* Options for the every-market trade feed.
|
|
48
93
|
*/
|
|
49
|
-
export interface ListTradesOptions extends
|
|
94
|
+
export interface ListTradesOptions extends TradesPageOptions {
|
|
50
95
|
/** Only the trades this application (frontend) took, as the taker's application. */
|
|
51
96
|
takerApplicationId?: string;
|
|
52
97
|
}
|
|
@@ -90,6 +135,25 @@ export declare class TradesAPIImpl extends BaseAPI {
|
|
|
90
135
|
* ```
|
|
91
136
|
*/
|
|
92
137
|
getTrades(tradingPairId: string, options?: GetTradesOptions): Promise<GetTradesPage>;
|
|
138
|
+
/**
|
|
139
|
+
* Recover the RFQ block prints a `rfqTrades` subscriber missed (RFQ-15).
|
|
140
|
+
*
|
|
141
|
+
* `rfq_trades` prints are best-effort, so a gap is possible. This pages the
|
|
142
|
+
* pair's public RFQ history (`getTrades` with `executionSource: "RFQ"`),
|
|
143
|
+
* newest first, until it reaches `sinceExecutionId`, and returns what is
|
|
144
|
+
* newer than it, oldest first, ready to replay. Each trade's `tradeId` is
|
|
145
|
+
* the print's `executionId`.
|
|
146
|
+
*
|
|
147
|
+
* It also returns every other fill with the same execution time as
|
|
148
|
+
* `sinceExecutionId`: an RFQ's fills share one execution time and need not
|
|
149
|
+
* arrive in id order, so a missed one can sort after the last print seen.
|
|
150
|
+
* Some of those may already have been received, so deduplicate replayed
|
|
151
|
+
* fills by `executionId`.
|
|
152
|
+
*
|
|
153
|
+
* @param tradingPairId - The trading pair UUID
|
|
154
|
+
* @param options - Where to stop, and how far to look
|
|
155
|
+
*/
|
|
156
|
+
recoverRfqTrades(tradingPairId: string, options?: RecoverRfqTradesOptions): Promise<RecoveredRfqTrades>;
|
|
93
157
|
/**
|
|
94
158
|
* Get one page of the trade feed: every market, newest first, recent and
|
|
95
159
|
* archived trades alike, or only the trades one application took when
|
package/dist/api/trades/api.js
CHANGED
|
@@ -63,6 +63,9 @@ export class TradesAPIImpl extends BaseAPI {
|
|
|
63
63
|
if (options.pageToken != null && options.pageToken !== "") {
|
|
64
64
|
params.set("pageToken", options.pageToken);
|
|
65
65
|
}
|
|
66
|
+
if (options.executionSource != null) {
|
|
67
|
+
params.set("executionSource", options.executionSource);
|
|
68
|
+
}
|
|
66
69
|
const query = params.toString();
|
|
67
70
|
const response = await this.makePublicRequest(`/api/v1/trades/${encodeURIComponent(tradingPairId)}${query === "" ? "" : `?${query}`}`);
|
|
68
71
|
return {
|
|
@@ -75,6 +78,61 @@ export class TradesAPIImpl extends BaseAPI {
|
|
|
75
78
|
nextPageToken: response.nextPageToken ?? "",
|
|
76
79
|
};
|
|
77
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Recover the RFQ block prints a `rfqTrades` subscriber missed (RFQ-15).
|
|
83
|
+
*
|
|
84
|
+
* `rfq_trades` prints are best-effort, so a gap is possible. This pages the
|
|
85
|
+
* pair's public RFQ history (`getTrades` with `executionSource: "RFQ"`),
|
|
86
|
+
* newest first, until it reaches `sinceExecutionId`, and returns what is
|
|
87
|
+
* newer than it, oldest first, ready to replay. Each trade's `tradeId` is
|
|
88
|
+
* the print's `executionId`.
|
|
89
|
+
*
|
|
90
|
+
* It also returns every other fill with the same execution time as
|
|
91
|
+
* `sinceExecutionId`: an RFQ's fills share one execution time and need not
|
|
92
|
+
* arrive in id order, so a missed one can sort after the last print seen.
|
|
93
|
+
* Some of those may already have been received, so deduplicate replayed
|
|
94
|
+
* fills by `executionId`.
|
|
95
|
+
*
|
|
96
|
+
* @param tradingPairId - The trading pair UUID
|
|
97
|
+
* @param options - Where to stop, and how far to look
|
|
98
|
+
*/
|
|
99
|
+
async recoverRfqTrades(tradingPairId, options = {}) {
|
|
100
|
+
const pageSize = options.pageSize ?? 100;
|
|
101
|
+
const maxPages = options.maxPages ?? 10;
|
|
102
|
+
if (!Number.isInteger(maxPages) || maxPages < 1) {
|
|
103
|
+
throw new Error("maxPages must be a positive integer");
|
|
104
|
+
}
|
|
105
|
+
const newestFirst = [];
|
|
106
|
+
// Set once the walk reaches `sinceExecutionId`: that print's execution
|
|
107
|
+
// time. RFQ children share one execution time and their ids need not
|
|
108
|
+
// follow receipt order, so a missed child can sort after the last seen
|
|
109
|
+
// one; the walk reads on through the whole group before it stops.
|
|
110
|
+
let anchorExecutedAt;
|
|
111
|
+
let pageToken;
|
|
112
|
+
for (let pages = 0; pages < maxPages; pages++) {
|
|
113
|
+
const page = await this.getTrades(tradingPairId, { pageSize, executionSource: "RFQ", ...(pageToken ? { pageToken } : {}) });
|
|
114
|
+
for (const trade of page.trades) {
|
|
115
|
+
if (anchorExecutedAt !== undefined) {
|
|
116
|
+
if (trade.data.executedAt !== anchorExecutedAt) {
|
|
117
|
+
return { trades: newestFirst.reverse(), complete: true };
|
|
118
|
+
}
|
|
119
|
+
newestFirst.push(trade);
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
if (options.sinceExecutionId != null && trade.data.tradeId === options.sinceExecutionId) {
|
|
123
|
+
anchorExecutedAt = trade.data.executedAt;
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
newestFirst.push(trade);
|
|
127
|
+
}
|
|
128
|
+
// Without a known last print, only the newest page is wanted.
|
|
129
|
+
if (options.sinceExecutionId == null || page.nextPageToken === "") {
|
|
130
|
+
return { trades: newestFirst.reverse(), complete: true };
|
|
131
|
+
}
|
|
132
|
+
pageToken = page.nextPageToken;
|
|
133
|
+
}
|
|
134
|
+
return { trades: newestFirst.reverse(), complete: false };
|
|
135
|
+
}
|
|
78
136
|
/**
|
|
79
137
|
* Get one page of the trade feed: every market, newest first, recent and
|
|
80
138
|
* archived trades alike, or only the trades one application took when
|
|
@@ -323,11 +323,10 @@ export declare class TradingAPIImpl extends BaseAPI implements TradingAPI {
|
|
|
323
323
|
* Failed replacements do not prevent other orders from being replaced.
|
|
324
324
|
*
|
|
325
325
|
* Pre-sequencing validation is scoped per item too, matching `batchCreate`:
|
|
326
|
-
* a malformed `orderId`, `price`, `quantity` or `clientOrderId
|
|
327
|
-
*
|
|
328
|
-
*
|
|
329
|
-
* `
|
|
330
|
-
* original is left untouched — while the valid items proceed. A `2xx`
|
|
326
|
+
* a malformed `orderId`, `price`, `quantity` or `clientOrderId` fails only
|
|
327
|
+
* that item — its result slot carries a structured `error.code`
|
|
328
|
+
* (`INVALID_ORDER_ID`, `INVALID_PRICE`, `INVALID_QUANTITY`,
|
|
329
|
+
* `INVALID_CLIENT_ORDER_ID`) and its original is left untouched — while the valid items proceed. A `2xx`
|
|
331
330
|
* response can therefore mix executed replacements and failed items: read
|
|
332
331
|
* `results[]` per item rather than treating the status code as the verdict.
|
|
333
332
|
* Only an empty or oversize (>100) batch rejects the whole request.
|
package/dist/api/trading/api.js
CHANGED
|
@@ -495,11 +495,10 @@ export class TradingAPIImpl extends BaseAPI {
|
|
|
495
495
|
* Failed replacements do not prevent other orders from being replaced.
|
|
496
496
|
*
|
|
497
497
|
* Pre-sequencing validation is scoped per item too, matching `batchCreate`:
|
|
498
|
-
* a malformed `orderId`, `price`, `quantity` or `clientOrderId
|
|
499
|
-
*
|
|
500
|
-
*
|
|
501
|
-
* `
|
|
502
|
-
* original is left untouched — while the valid items proceed. A `2xx`
|
|
498
|
+
* a malformed `orderId`, `price`, `quantity` or `clientOrderId` fails only
|
|
499
|
+
* that item — its result slot carries a structured `error.code`
|
|
500
|
+
* (`INVALID_ORDER_ID`, `INVALID_PRICE`, `INVALID_QUANTITY`,
|
|
501
|
+
* `INVALID_CLIENT_ORDER_ID`) and its original is left untouched — while the valid items proceed. A `2xx`
|
|
503
502
|
* response can therefore mix executed replacements and failed items: read
|
|
504
503
|
* `results[]` per item rather than treating the status code as the verdict.
|
|
505
504
|
* Only an empty or oversize (>100) batch rejects the whole request.
|
|
@@ -728,6 +728,7 @@ function parseMarketStatsSummary(raw) {
|
|
|
728
728
|
fundingRate: readOptionalString(data, "fundingRate"),
|
|
729
729
|
premium: readOptionalString(data, "premium"),
|
|
730
730
|
openInterestNotional: readOptionalString(data, "openInterestNotional"),
|
|
731
|
+
dailyVolumeBySource: parseDailyVolumeBySource(data.dailyVolumeBySource),
|
|
731
732
|
};
|
|
732
733
|
}
|
|
733
734
|
function parseMarketStatsAllEvent(rawData) {
|
|
@@ -3075,7 +3076,7 @@ export function createMonacoWebSocket(baseUrl, options = {}, serverClock = new S
|
|
|
3075
3076
|
}
|
|
3076
3077
|
});
|
|
3077
3078
|
};
|
|
3078
|
-
const subscribeRfqTrades = (tradingPairId, handler) => {
|
|
3079
|
+
const subscribeRfqTrades = (tradingPairId, handler, onSnapshot) => {
|
|
3079
3080
|
if (!handler) {
|
|
3080
3081
|
throw new Error("rfqTrades subscription requires a handler");
|
|
3081
3082
|
}
|
|
@@ -3086,7 +3087,9 @@ export function createMonacoWebSocket(baseUrl, options = {}, serverClock = new S
|
|
|
3086
3087
|
catch (err) {
|
|
3087
3088
|
console.error("WebSocket: Error processing RFQ trade event", err);
|
|
3088
3089
|
}
|
|
3089
|
-
}
|
|
3090
|
+
},
|
|
3091
|
+
// The pair's newest RFQ prints from the public RFQ history (RFQ-15).
|
|
3092
|
+
onSnapshot && snapshotFrameHandler("rfq_trades", parseRfqTradeEventData, onSnapshot));
|
|
3090
3093
|
};
|
|
3091
3094
|
return {
|
|
3092
3095
|
connect,
|
package/dist/coverage.d.ts
CHANGED
|
@@ -139,6 +139,7 @@ export declare const COVERED: {
|
|
|
139
139
|
list_pending_withdrawals: string;
|
|
140
140
|
list_all_funding_history: string;
|
|
141
141
|
list_application_balances: string;
|
|
142
|
+
list_application_margin_accounts: string;
|
|
142
143
|
list_application_movements: string;
|
|
143
144
|
list_application_orders: string;
|
|
144
145
|
list_application_users: string;
|
package/dist/coverage.js
CHANGED
|
@@ -139,6 +139,7 @@ export const COVERED = {
|
|
|
139
139
|
list_pending_withdrawals: "listPendingWithdrawals",
|
|
140
140
|
list_all_funding_history: "listAllFundingHistory",
|
|
141
141
|
list_application_balances: "listApplicationBalances",
|
|
142
|
+
list_application_margin_accounts: "listApplicationMarginAccounts",
|
|
142
143
|
list_application_movements: "listApplicationMovements",
|
|
143
144
|
list_application_orders: "listApplicationOrders",
|
|
144
145
|
list_application_users: "listApplicationUsers",
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { type RfqViewSource, waitForRfqView } from "./api/rfq";
|
|
1
2
|
export { createMonacoWebSocket, type MonacoWebSocket, type MonacoWebSocketOptions } from "./api/websocket";
|
|
2
3
|
export { APIError, ContractError, InvalidConfigError, InvalidStateError, MonacoCoreError, WithdrawalRateLimitedError } from "./errors";
|
|
3
4
|
export { resolveApiUrl, resolveWsUrl } from "./networks";
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { waitForRfqView } from "./api/rfq";
|
|
1
2
|
export { createMonacoWebSocket } from "./api/websocket";
|
|
2
3
|
export { APIError, ContractError, InvalidConfigError, InvalidStateError, MonacoCoreError, WithdrawalRateLimitedError } from "./errors";
|
|
3
4
|
export { resolveApiUrl, resolveWsUrl } from "./networks";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@0xmonaco/core",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"homepage": "https://docs.0xmonaco.com/sdk/typescript",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -19,15 +19,15 @@
|
|
|
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.10",
|
|
23
|
+
"@0xmonaco/types": "1.1.10",
|
|
24
24
|
"@noble/curves": "^2.4.0",
|
|
25
25
|
"@noble/hashes": "^2.4.0",
|
|
26
26
|
"http-status-codes": "^2.3.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"dotenv": "^18.0.8",
|
|
30
|
-
"ws": "^8.22.
|
|
30
|
+
"ws": "^8.22.1"
|
|
31
31
|
},
|
|
32
32
|
"exports": {
|
|
33
33
|
".": {
|