@n1xyz/nord-ts 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/actions.d.ts +57 -0
- package/dist/actions.js +229 -0
- package/dist/client/Nord.d.ts +379 -0
- package/dist/client/Nord.js +718 -0
- package/dist/client/NordAdmin.d.ts +225 -0
- package/dist/client/NordAdmin.js +394 -0
- package/dist/client/NordUser.d.ts +350 -0
- package/dist/client/NordUser.js +743 -0
- package/dist/error.d.ts +35 -0
- package/dist/error.js +49 -0
- package/dist/gen/nord_pb.d.ts +233 -7
- package/dist/gen/nord_pb.js +34 -8
- package/dist/gen/openapi.d.ts +40 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +29 -1
- package/dist/nord/client/Nord.d.ts +1 -1
- package/dist/nord/client/Nord.js +2 -2
- package/dist/nord/client/NordAdmin.d.ts +24 -1
- package/dist/nord/client/NordAdmin.js +63 -5
- package/dist/nord/index.d.ts +1 -1
- package/dist/nord/index.js +2 -1
- package/dist/types.d.ts +6 -50
- package/dist/types.js +1 -24
- package/dist/utils.d.ts +8 -11
- package/dist/utils.js +54 -41
- package/dist/websocket/Subscriber.d.ts +37 -0
- package/dist/websocket/Subscriber.js +25 -0
- package/dist/websocket/index.d.ts +19 -2
- package/dist/websocket/index.js +82 -2
- package/package.json +1 -1
- package/src/actions.ts +333 -0
- package/src/{nord/client → client}/Nord.ts +209 -211
- package/src/{nord/client → client}/NordAdmin.ts +196 -153
- package/src/{nord/client → client}/NordUser.ts +216 -305
- package/src/gen/nord_pb.ts +271 -9
- package/src/gen/openapi.ts +40 -0
- package/src/index.ts +7 -1
- package/src/types.ts +7 -54
- package/src/utils.ts +44 -47
- package/src/{nord/models → websocket}/Subscriber.ts +2 -2
- package/src/websocket/index.ts +105 -2
- package/src/nord/api/actions.ts +0 -648
- package/src/nord/api/core.ts +0 -96
- package/src/nord/api/metrics.ts +0 -269
- package/src/nord/client/NordClient.ts +0 -79
- package/src/nord/index.ts +0 -25
- /package/src/{nord/utils/NordError.ts → error.ts} +0 -0
|
@@ -2,14 +2,13 @@ import { ProtonClient } from "@n1xyz/proton";
|
|
|
2
2
|
import { Connection, PublicKey } from "@solana/web3.js";
|
|
3
3
|
import { EventEmitter } from "events";
|
|
4
4
|
import createClient, { Client, FetchOptions } from "openapi-fetch";
|
|
5
|
-
import * as proto from "
|
|
6
|
-
import type { paths } from "
|
|
5
|
+
import * as proto from "../gen/nord_pb";
|
|
6
|
+
import type { paths } from "../gen/openapi.ts";
|
|
7
7
|
import {
|
|
8
8
|
Account,
|
|
9
9
|
AccountPnlPage,
|
|
10
10
|
AccountPnlQuery,
|
|
11
11
|
ActionResponse,
|
|
12
|
-
AggregateMetrics,
|
|
13
12
|
MarketsInfo,
|
|
14
13
|
Market,
|
|
15
14
|
MarketStats,
|
|
@@ -17,7 +16,6 @@ import {
|
|
|
17
16
|
OrderbookQuery,
|
|
18
17
|
OrderbookResponse,
|
|
19
18
|
FeeTierConfig,
|
|
20
|
-
PeakTpsPeriodUnit,
|
|
21
19
|
SubscriptionPattern,
|
|
22
20
|
Token,
|
|
23
21
|
TradesResponse,
|
|
@@ -32,13 +30,15 @@ import {
|
|
|
32
30
|
OrderInfoFromApi,
|
|
33
31
|
TokenStats,
|
|
34
32
|
FillRole,
|
|
35
|
-
} from "
|
|
36
|
-
import * as utils from "
|
|
37
|
-
import { NordWebSocketClient } from "
|
|
38
|
-
import
|
|
39
|
-
import
|
|
40
|
-
|
|
41
|
-
|
|
33
|
+
} from "../types";
|
|
34
|
+
import * as utils from "../utils";
|
|
35
|
+
import { NordWebSocketClient } from "../websocket/index";
|
|
36
|
+
import { initWebSocketClient } from "../websocket";
|
|
37
|
+
import {
|
|
38
|
+
OrderbookSubscription,
|
|
39
|
+
TradeSubscription,
|
|
40
|
+
} from "../websocket/Subscriber";
|
|
41
|
+
import { NordError } from "../error";
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
44
|
* User subscription interface
|
|
@@ -47,18 +47,6 @@ export interface UserSubscription extends EventEmitter {
|
|
|
47
47
|
close: () => void;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
/**
|
|
51
|
-
* WebSocket subscription options interface
|
|
52
|
-
*/
|
|
53
|
-
export interface WebSocketSubscriptionOptions {
|
|
54
|
-
/** Market symbols to subscribe to for trade updates */
|
|
55
|
-
trades?: string[];
|
|
56
|
-
/** Market symbols to subscribe to for orderbook delta updates */
|
|
57
|
-
deltas?: string[];
|
|
58
|
-
/** Account IDs to subscribe to for account updates */
|
|
59
|
-
accounts?: number[];
|
|
60
|
-
}
|
|
61
|
-
|
|
62
50
|
/**
|
|
63
51
|
* Main Nord client class for interacting with the Nord API
|
|
64
52
|
*/
|
|
@@ -67,7 +55,7 @@ export class Nord {
|
|
|
67
55
|
public readonly webServerUrl: string;
|
|
68
56
|
|
|
69
57
|
/** Solana RPC URL */
|
|
70
|
-
public readonly
|
|
58
|
+
public readonly solanaConnection: Connection;
|
|
71
59
|
|
|
72
60
|
/** Available markets */
|
|
73
61
|
public markets: Market[] = [];
|
|
@@ -82,7 +70,7 @@ export class Nord {
|
|
|
82
70
|
public protonClient: ProtonClient;
|
|
83
71
|
|
|
84
72
|
/** HTTP client for Nord operations */
|
|
85
|
-
|
|
73
|
+
public readonly httpClient: Client<paths>;
|
|
86
74
|
|
|
87
75
|
/**
|
|
88
76
|
* Create a new Nord client
|
|
@@ -93,16 +81,16 @@ export class Nord {
|
|
|
93
81
|
* @throws {Error} If required configuration is missing
|
|
94
82
|
*/
|
|
95
83
|
private constructor({
|
|
96
|
-
|
|
84
|
+
solanaConnection,
|
|
97
85
|
webServerUrl,
|
|
98
86
|
protonClient,
|
|
99
87
|
}: Readonly<{
|
|
100
|
-
|
|
88
|
+
solanaConnection: Connection;
|
|
101
89
|
webServerUrl: string;
|
|
102
90
|
protonClient: ProtonClient;
|
|
103
91
|
}>) {
|
|
104
92
|
this.webServerUrl = webServerUrl;
|
|
105
|
-
this.
|
|
93
|
+
this.solanaConnection = solanaConnection;
|
|
106
94
|
this.protonClient = protonClient;
|
|
107
95
|
this.httpClient = createClient<paths>({ baseUrl: webServerUrl });
|
|
108
96
|
}
|
|
@@ -110,7 +98,9 @@ export class Nord {
|
|
|
110
98
|
/**
|
|
111
99
|
* Create a WebSocket client with specific subscriptions
|
|
112
100
|
*
|
|
113
|
-
* @param
|
|
101
|
+
* @param trades - Market symbols to subscribe to for trade updates
|
|
102
|
+
* @param deltas - Market symbols to subscribe to for orderbook delta updates
|
|
103
|
+
* @param accounts - Account IDs to subscribe to for account updates
|
|
114
104
|
* @returns A new WebSocket client with the requested subscriptions
|
|
115
105
|
* @throws {NordError} If invalid subscription options are provided
|
|
116
106
|
*
|
|
@@ -128,28 +118,34 @@ export class Nord {
|
|
|
128
118
|
* trades: ["BTCUSDC", "ETHUSDC"]
|
|
129
119
|
* });
|
|
130
120
|
*/
|
|
131
|
-
public createWebSocketClient(
|
|
132
|
-
|
|
133
|
-
|
|
121
|
+
public createWebSocketClient({
|
|
122
|
+
trades,
|
|
123
|
+
deltas,
|
|
124
|
+
accounts,
|
|
125
|
+
}: Readonly<{
|
|
126
|
+
trades?: string[];
|
|
127
|
+
deltas?: string[];
|
|
128
|
+
accounts?: number[];
|
|
129
|
+
}>): NordWebSocketClient {
|
|
134
130
|
const subscriptions: SubscriptionPattern[] = [];
|
|
135
131
|
|
|
136
132
|
// Add trade subscriptions
|
|
137
|
-
if (
|
|
138
|
-
|
|
133
|
+
if (trades && trades.length > 0) {
|
|
134
|
+
trades.forEach((symbol) => {
|
|
139
135
|
subscriptions.push(`trades@${symbol}` as SubscriptionPattern);
|
|
140
136
|
});
|
|
141
137
|
}
|
|
142
138
|
|
|
143
139
|
// Add delta subscriptions
|
|
144
|
-
if (
|
|
145
|
-
|
|
140
|
+
if (deltas && deltas.length > 0) {
|
|
141
|
+
deltas.forEach((symbol) => {
|
|
146
142
|
subscriptions.push(`deltas@${symbol}` as SubscriptionPattern);
|
|
147
143
|
});
|
|
148
144
|
}
|
|
149
145
|
|
|
150
146
|
// Add account subscriptions
|
|
151
|
-
if (
|
|
152
|
-
|
|
147
|
+
if (accounts && accounts.length > 0) {
|
|
148
|
+
accounts.forEach((accountId) => {
|
|
153
149
|
if (isNaN(accountId) || accountId <= 0) {
|
|
154
150
|
throw new NordError(
|
|
155
151
|
`Invalid account ID: ${accountId}. Must be a positive number.`,
|
|
@@ -165,7 +161,7 @@ export class Nord {
|
|
|
165
161
|
}
|
|
166
162
|
|
|
167
163
|
// Create and return a new WebSocket client
|
|
168
|
-
return
|
|
164
|
+
return initWebSocketClient(this.webServerUrl, subscriptions);
|
|
169
165
|
}
|
|
170
166
|
|
|
171
167
|
private async GET<P extends keyof paths & string>(
|
|
@@ -204,6 +200,16 @@ export class Nord {
|
|
|
204
200
|
return await this.GET("/event/last-acked-nonce", {});
|
|
205
201
|
}
|
|
206
202
|
|
|
203
|
+
/**
|
|
204
|
+
* Get the admin list from the Nord server
|
|
205
|
+
*
|
|
206
|
+
* @returns List of admin registration keys paired with their ACL role mask
|
|
207
|
+
* @throws {NordError} If the request fails
|
|
208
|
+
*/
|
|
209
|
+
async getAdminList(): Promise<Array<[string, number]>> {
|
|
210
|
+
return await this.GET("/admin", {});
|
|
211
|
+
}
|
|
212
|
+
|
|
207
213
|
/**
|
|
208
214
|
* Fetch information about Nord markets and tokens
|
|
209
215
|
*
|
|
@@ -225,6 +231,11 @@ export class Nord {
|
|
|
225
231
|
}
|
|
226
232
|
}
|
|
227
233
|
|
|
234
|
+
/** @deprecated use Nord.new */
|
|
235
|
+
public static async initNord(x: Readonly<NordConfig>): Promise<Nord> {
|
|
236
|
+
return await Nord.new(x);
|
|
237
|
+
}
|
|
238
|
+
|
|
228
239
|
/**
|
|
229
240
|
* Initialize a new Nord client
|
|
230
241
|
*
|
|
@@ -235,23 +246,20 @@ export class Nord {
|
|
|
235
246
|
* @returns Initialized Nord client
|
|
236
247
|
* @throws {NordError} If initialization fails
|
|
237
248
|
*/
|
|
238
|
-
public static async
|
|
249
|
+
public static async new({
|
|
239
250
|
app,
|
|
240
|
-
|
|
251
|
+
solanaConnection,
|
|
241
252
|
webServerUrl,
|
|
253
|
+
protonUrl,
|
|
242
254
|
}: Readonly<NordConfig>): Promise<Nord> {
|
|
243
|
-
// TODO: we should parametrize the connectionn not have it done here.
|
|
244
|
-
// this is a dogshit api, only here to be compatible with the shitty
|
|
245
|
-
// vibecoded code and not break zero one team's workflow.
|
|
246
|
-
const connection = new Connection(solanaUrl, { commitment: "confirmed" });
|
|
247
255
|
const protonClient = await ProtonClient.init({
|
|
248
|
-
protonUrl: webServerUrl,
|
|
256
|
+
protonUrl: protonUrl ?? webServerUrl,
|
|
249
257
|
app: new PublicKey(app),
|
|
250
|
-
solConn:
|
|
258
|
+
solConn: solanaConnection,
|
|
251
259
|
});
|
|
252
260
|
const nord = new Nord({
|
|
253
261
|
protonClient,
|
|
254
|
-
|
|
262
|
+
solanaConnection,
|
|
255
263
|
webServerUrl,
|
|
256
264
|
});
|
|
257
265
|
await nord.init();
|
|
@@ -269,20 +277,20 @@ export class Nord {
|
|
|
269
277
|
/**
|
|
270
278
|
* Query a specific action
|
|
271
279
|
*
|
|
272
|
-
* @param
|
|
280
|
+
* @param actionId - Action identifier to fetch
|
|
273
281
|
* @returns Action response
|
|
274
282
|
* @throws {NordError} If the request fails
|
|
275
283
|
*/
|
|
276
284
|
async queryAction({
|
|
277
|
-
|
|
278
|
-
}: {
|
|
279
|
-
|
|
280
|
-
}): Promise<ActionResponse | null> {
|
|
285
|
+
actionId,
|
|
286
|
+
}: Readonly<{
|
|
287
|
+
actionId: number;
|
|
288
|
+
}>): Promise<ActionResponse | null> {
|
|
281
289
|
return (
|
|
282
290
|
(
|
|
283
291
|
await this.queryRecentActions({
|
|
284
|
-
from:
|
|
285
|
-
to:
|
|
292
|
+
from: actionId,
|
|
293
|
+
to: actionId,
|
|
286
294
|
})
|
|
287
295
|
)[0] ?? null
|
|
288
296
|
);
|
|
@@ -291,18 +299,21 @@ export class Nord {
|
|
|
291
299
|
/**
|
|
292
300
|
* Query recent actions
|
|
293
301
|
*
|
|
294
|
-
* @param from - Starting action index
|
|
295
|
-
* @param to - Ending action index
|
|
302
|
+
* @param from - Starting action index (inclusive)
|
|
303
|
+
* @param to - Ending action index (inclusive)
|
|
296
304
|
* @returns Actions response
|
|
297
305
|
* @throws {NordError} If the request fails
|
|
298
306
|
*/
|
|
299
|
-
async queryRecentActions(
|
|
307
|
+
async queryRecentActions({
|
|
308
|
+
from,
|
|
309
|
+
to,
|
|
310
|
+
}: Readonly<{
|
|
300
311
|
from: number;
|
|
301
312
|
to: number;
|
|
302
|
-
}): Promise<ActionResponse[]> {
|
|
313
|
+
}>): Promise<ActionResponse[]> {
|
|
303
314
|
const xs = await this.GET("/action", {
|
|
304
315
|
params: {
|
|
305
|
-
query,
|
|
316
|
+
query: { from, to },
|
|
306
317
|
},
|
|
307
318
|
});
|
|
308
319
|
return xs.map((x) => ({
|
|
@@ -325,79 +336,6 @@ export class Nord {
|
|
|
325
336
|
return await this.GET("/action/last-executed-id", {});
|
|
326
337
|
}
|
|
327
338
|
|
|
328
|
-
/**
|
|
329
|
-
* Fetch aggregate metrics from the Nord API
|
|
330
|
-
*
|
|
331
|
-
* @param txPeakTpsPeriod - Period for peak TPS calculation
|
|
332
|
-
* @param txPeakTpsPeriodUnit - Unit for peak TPS period
|
|
333
|
-
* @returns Aggregate metrics
|
|
334
|
-
* @throws {NordError} If the request fails
|
|
335
|
-
*/
|
|
336
|
-
async aggregateMetrics(
|
|
337
|
-
txPeakTpsPeriod = 1,
|
|
338
|
-
txPeakTpsPeriodUnit: PeakTpsPeriodUnit = PeakTpsPeriodUnit.Day,
|
|
339
|
-
): Promise<AggregateMetrics> {
|
|
340
|
-
return metrics.aggregateMetrics(
|
|
341
|
-
this.webServerUrl,
|
|
342
|
-
txPeakTpsPeriod,
|
|
343
|
-
txPeakTpsPeriodUnit,
|
|
344
|
-
);
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
/**
|
|
348
|
-
* Get current transactions per second
|
|
349
|
-
*
|
|
350
|
-
* @param period - Time period for the query
|
|
351
|
-
* @returns Current TPS value
|
|
352
|
-
* @throws {NordError} If the request fails
|
|
353
|
-
*/
|
|
354
|
-
async getCurrentTps(period: string = "1m") {
|
|
355
|
-
return metrics.getCurrentTps(this.webServerUrl, period);
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
/**
|
|
359
|
-
* Get peak transactions per second
|
|
360
|
-
*
|
|
361
|
-
* @param period - Time period for the query
|
|
362
|
-
* @returns Peak TPS value
|
|
363
|
-
* @throws {NordError} If the request fails
|
|
364
|
-
*/
|
|
365
|
-
async getPeakTps(period: string = "24h") {
|
|
366
|
-
return metrics.getPeakTps(this.webServerUrl, period);
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
/**
|
|
370
|
-
* Get median transaction latency
|
|
371
|
-
*
|
|
372
|
-
* @param period - Time period for the query
|
|
373
|
-
* @returns Median latency in milliseconds
|
|
374
|
-
* @throws {NordError} If the request fails
|
|
375
|
-
*/
|
|
376
|
-
async getMedianLatency(period: string = "1m") {
|
|
377
|
-
return metrics.getMedianLatency(this.webServerUrl, period);
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
/**
|
|
381
|
-
* Get total transaction count
|
|
382
|
-
*
|
|
383
|
-
* @returns Total transaction count
|
|
384
|
-
* @throws {NordError} If the request fails
|
|
385
|
-
*/
|
|
386
|
-
async getTotalTransactions() {
|
|
387
|
-
return metrics.getTotalTransactions(this.webServerUrl);
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
/**
|
|
391
|
-
* Query Prometheus metrics
|
|
392
|
-
*
|
|
393
|
-
* @param params - Prometheus query parameters
|
|
394
|
-
* @returns Query result as a number
|
|
395
|
-
* @throws {NordError} If the request fails
|
|
396
|
-
*/
|
|
397
|
-
async queryPrometheus(params: string): Promise<number> {
|
|
398
|
-
return metrics.queryPrometheus(this.webServerUrl, params);
|
|
399
|
-
}
|
|
400
|
-
|
|
401
339
|
/**
|
|
402
340
|
* Subscribe to orderbook updates for a market
|
|
403
341
|
*
|
|
@@ -518,39 +456,53 @@ export class Nord {
|
|
|
518
456
|
/**
|
|
519
457
|
* Get trades for a market
|
|
520
458
|
*
|
|
521
|
-
* @param
|
|
459
|
+
* @param marketId - Market identifier to filter by
|
|
460
|
+
* @param takerId - Taker account identifier
|
|
461
|
+
* @param makerId - Maker account identifier
|
|
462
|
+
* @param takerSide - Side executed by the taker
|
|
463
|
+
* @param pageSize - Maximum number of trades to return
|
|
464
|
+
* @param since - RFC3339 timestamp to start from (inclusive)
|
|
465
|
+
* @param until - RFC3339 timestamp to end at (exclusive)
|
|
466
|
+
* @param pageId - Pagination cursor returned from a prior call
|
|
522
467
|
* @returns Trades response
|
|
523
468
|
* @throws {NordError} If the request fails
|
|
524
469
|
*/
|
|
525
|
-
public async getTrades(
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
470
|
+
public async getTrades({
|
|
471
|
+
marketId,
|
|
472
|
+
takerId,
|
|
473
|
+
makerId,
|
|
474
|
+
takerSide,
|
|
475
|
+
pageSize,
|
|
476
|
+
since,
|
|
477
|
+
until,
|
|
478
|
+
startInclusive,
|
|
479
|
+
}: Readonly<{
|
|
480
|
+
marketId?: number;
|
|
481
|
+
takerId?: number;
|
|
482
|
+
makerId?: number;
|
|
483
|
+
takerSide?: "bid" | "ask";
|
|
484
|
+
pageSize?: number;
|
|
485
|
+
since?: string;
|
|
486
|
+
until?: string;
|
|
487
|
+
startInclusive?: string;
|
|
488
|
+
}>): Promise<TradesResponse> {
|
|
489
|
+
if (since && !utils.isRfc3339(since)) {
|
|
490
|
+
throw new NordError(`Invalid RFC3339 timestamp: ${since}`);
|
|
539
491
|
}
|
|
540
|
-
if (
|
|
541
|
-
throw new NordError(`Invalid RFC3339 timestamp: ${
|
|
492
|
+
if (until && !utils.isRfc3339(until)) {
|
|
493
|
+
throw new NordError(`Invalid RFC3339 timestamp: ${until}`);
|
|
542
494
|
}
|
|
543
495
|
return await this.GET("/trades", {
|
|
544
496
|
params: {
|
|
545
497
|
query: {
|
|
546
|
-
takerId
|
|
547
|
-
makerId
|
|
548
|
-
marketId
|
|
549
|
-
pageSize
|
|
550
|
-
takerSide
|
|
551
|
-
since
|
|
552
|
-
until
|
|
553
|
-
startInclusive
|
|
498
|
+
takerId,
|
|
499
|
+
makerId,
|
|
500
|
+
marketId,
|
|
501
|
+
pageSize,
|
|
502
|
+
takerSide,
|
|
503
|
+
since,
|
|
504
|
+
until,
|
|
505
|
+
startInclusive,
|
|
554
506
|
},
|
|
555
507
|
},
|
|
556
508
|
});
|
|
@@ -559,16 +511,18 @@ export class Nord {
|
|
|
559
511
|
/**
|
|
560
512
|
* Get user account IDs
|
|
561
513
|
*
|
|
562
|
-
* @param
|
|
514
|
+
* @param pubkey - User public key to query
|
|
563
515
|
* @returns User account IDs response
|
|
564
516
|
* @throws {NordError} If the request fails
|
|
565
517
|
*/
|
|
566
|
-
public async getUser(
|
|
518
|
+
public async getUser({
|
|
519
|
+
pubkey,
|
|
520
|
+
}: Readonly<{
|
|
567
521
|
pubkey: string | PublicKey;
|
|
568
|
-
}): Promise<User | null> {
|
|
522
|
+
}>): Promise<User | null> {
|
|
569
523
|
const r = await this.httpClient.GET("/user/{pubkey}", {
|
|
570
524
|
params: {
|
|
571
|
-
path: { pubkey:
|
|
525
|
+
path: { pubkey: pubkey.toString() },
|
|
572
526
|
},
|
|
573
527
|
});
|
|
574
528
|
if (r.response.status === 404) {
|
|
@@ -580,28 +534,32 @@ export class Nord {
|
|
|
580
534
|
/**
|
|
581
535
|
* Get orderbook for a market
|
|
582
536
|
*
|
|
583
|
-
* @param
|
|
537
|
+
* @param symbol - Market symbol to resolve into an id
|
|
538
|
+
* @param marketId - Market identifier
|
|
584
539
|
* @returns Orderbook response
|
|
585
540
|
* @throws {NordError} If the request fails or if the market symbol is unknown
|
|
586
541
|
* @remarks It's recommended to initialize the Nord client using the static `initNord` method
|
|
587
542
|
* to ensure market information is properly loaded before calling this method.
|
|
588
543
|
*/
|
|
589
|
-
public async getOrderbook(
|
|
544
|
+
public async getOrderbook({
|
|
545
|
+
symbol,
|
|
546
|
+
marketId,
|
|
547
|
+
}: OrderbookQuery): Promise<OrderbookResponse> {
|
|
590
548
|
// If only symbol is provided, convert it to market_id
|
|
591
|
-
let
|
|
592
|
-
if (
|
|
549
|
+
let _marketId: number;
|
|
550
|
+
if (symbol && marketId === undefined) {
|
|
593
551
|
// If the map is empty, try to fetch market information first
|
|
594
552
|
if (this.symbolToMarketId.size === 0) {
|
|
595
553
|
await this.fetchNordInfo();
|
|
596
554
|
}
|
|
597
555
|
|
|
598
|
-
const id = this.symbolToMarketId.get(
|
|
556
|
+
const id = this.symbolToMarketId.get(symbol);
|
|
599
557
|
if (id === undefined) {
|
|
600
|
-
throw new NordError(`Unknown market symbol: ${
|
|
558
|
+
throw new NordError(`Unknown market symbol: ${symbol}`);
|
|
601
559
|
}
|
|
602
|
-
|
|
603
|
-
} else if (
|
|
604
|
-
|
|
560
|
+
_marketId = id;
|
|
561
|
+
} else if (marketId !== undefined) {
|
|
562
|
+
_marketId = marketId;
|
|
605
563
|
} else {
|
|
606
564
|
throw new NordError(
|
|
607
565
|
"Either symbol or market_id must be provided for orderbook query",
|
|
@@ -610,7 +568,7 @@ export class Nord {
|
|
|
610
568
|
|
|
611
569
|
return await this.GET("/market/{market_id}/orderbook", {
|
|
612
570
|
params: {
|
|
613
|
-
path: { market_id:
|
|
571
|
+
path: { market_id: _marketId },
|
|
614
572
|
},
|
|
615
573
|
});
|
|
616
574
|
}
|
|
@@ -699,20 +657,27 @@ export class Nord {
|
|
|
699
657
|
* Get open orders for an account.
|
|
700
658
|
*
|
|
701
659
|
* @param accountId - Account id to query
|
|
702
|
-
* @param
|
|
660
|
+
* @param startInclusive - Pagination cursor (client order id) to resume from
|
|
661
|
+
* @param pageSize - Maximum number of orders to return
|
|
703
662
|
* @returns Page of orders keyed by client order id
|
|
704
663
|
* @throws {NordError} If the request fails
|
|
705
664
|
*/
|
|
706
665
|
public async getAccountOrders(
|
|
707
666
|
accountId: number,
|
|
708
|
-
|
|
667
|
+
{
|
|
668
|
+
startInclusive,
|
|
669
|
+
pageSize,
|
|
670
|
+
}: Readonly<{
|
|
671
|
+
startInclusive?: string | null;
|
|
672
|
+
pageSize?: number | null;
|
|
673
|
+
}> = {},
|
|
709
674
|
): Promise<PageResultStringOrderInfo> {
|
|
710
675
|
return await this.GET("/account/{account_id}/orders", {
|
|
711
676
|
params: {
|
|
712
677
|
path: { account_id: accountId },
|
|
713
678
|
query: {
|
|
714
|
-
startInclusive
|
|
715
|
-
pageSize
|
|
679
|
+
startInclusive,
|
|
680
|
+
pageSize,
|
|
716
681
|
},
|
|
717
682
|
},
|
|
718
683
|
});
|
|
@@ -720,16 +685,22 @@ export class Nord {
|
|
|
720
685
|
|
|
721
686
|
/**
|
|
722
687
|
* List account fee tiers with pagination support.
|
|
688
|
+
*
|
|
689
|
+
* @param startInclusive - Account id cursor to resume from
|
|
690
|
+
* @param pageSize - Maximum number of entries to return
|
|
723
691
|
*/
|
|
724
|
-
public async getAccountsFeeTiers(
|
|
692
|
+
public async getAccountsFeeTiers({
|
|
693
|
+
startInclusive,
|
|
694
|
+
pageSize,
|
|
695
|
+
}: Readonly<{
|
|
725
696
|
startInclusive?: number | null;
|
|
726
697
|
pageSize?: number | null;
|
|
727
|
-
}): Promise<AccountFeeTierPage> {
|
|
698
|
+
}> = {}): Promise<AccountFeeTierPage> {
|
|
728
699
|
return await this.GET("/accounts/fee-tiers", {
|
|
729
700
|
params: {
|
|
730
701
|
query: {
|
|
731
|
-
startInclusive:
|
|
732
|
-
pageSize:
|
|
702
|
+
startInclusive: startInclusive ?? undefined,
|
|
703
|
+
pageSize: pageSize ?? undefined,
|
|
733
704
|
},
|
|
734
705
|
},
|
|
735
706
|
});
|
|
@@ -739,22 +710,30 @@ export class Nord {
|
|
|
739
710
|
* Get profit and loss history for an account
|
|
740
711
|
*
|
|
741
712
|
* @param accountId - Account ID to query
|
|
742
|
-
* @param
|
|
713
|
+
* @param since - RFC3339 timestamp to start from (inclusive)
|
|
714
|
+
* @param until - RFC3339 timestamp to end at (exclusive)
|
|
715
|
+
* @param startInclusive - Pagination cursor to resume from
|
|
716
|
+
* @param pageSize - Maximum number of entries to return
|
|
743
717
|
* @returns Page of PnL entries ordered from latest to oldest
|
|
744
718
|
* @throws {NordError} If the request fails
|
|
745
719
|
*/
|
|
746
720
|
public async getAccountPnl(
|
|
747
721
|
accountId: number,
|
|
748
|
-
|
|
722
|
+
{
|
|
723
|
+
since,
|
|
724
|
+
until,
|
|
725
|
+
startInclusive,
|
|
726
|
+
pageSize,
|
|
727
|
+
}: Readonly<Partial<AccountPnlQuery>> = {},
|
|
749
728
|
): Promise<AccountPnlPage> {
|
|
750
729
|
return await this.GET("/account/{account_id}/pnl", {
|
|
751
730
|
params: {
|
|
752
731
|
path: { account_id: accountId },
|
|
753
732
|
query: {
|
|
754
|
-
since
|
|
755
|
-
until
|
|
756
|
-
startInclusive
|
|
757
|
-
pageSize
|
|
733
|
+
since,
|
|
734
|
+
until,
|
|
735
|
+
startInclusive,
|
|
736
|
+
pageSize,
|
|
758
737
|
},
|
|
759
738
|
},
|
|
760
739
|
});
|
|
@@ -763,13 +742,16 @@ export class Nord {
|
|
|
763
742
|
/**
|
|
764
743
|
* Get market statistics (alias for marketsStats for backward compatibility)
|
|
765
744
|
*
|
|
745
|
+
*
|
|
746
|
+
* @param marketId - Market identifier
|
|
747
|
+
*
|
|
766
748
|
* @returns Market statistics response
|
|
767
749
|
*/
|
|
768
750
|
public async getMarketStats({
|
|
769
751
|
marketId,
|
|
770
|
-
}: {
|
|
752
|
+
}: Readonly<{
|
|
771
753
|
marketId: number;
|
|
772
|
-
}): Promise<MarketStats> {
|
|
754
|
+
}>): Promise<MarketStats> {
|
|
773
755
|
return await this.GET("/market/{market_id}/stats", {
|
|
774
756
|
params: {
|
|
775
757
|
path: { market_id: marketId },
|
|
@@ -780,7 +762,9 @@ export class Nord {
|
|
|
780
762
|
/**
|
|
781
763
|
* Fetch the per-market fee quote for an account.
|
|
782
764
|
*
|
|
783
|
-
* @param
|
|
765
|
+
* @param marketId - Market identifier
|
|
766
|
+
* @param feeKind - Fill role (maker/taker) to quote
|
|
767
|
+
* @param accountId - Account identifier to quote
|
|
784
768
|
* @returns Fee in quote token units (negative means fee is charged)
|
|
785
769
|
* @throws {NordError} If the request fails
|
|
786
770
|
*/
|
|
@@ -788,11 +772,11 @@ export class Nord {
|
|
|
788
772
|
marketId,
|
|
789
773
|
feeKind,
|
|
790
774
|
accountId,
|
|
791
|
-
}: {
|
|
775
|
+
}: Readonly<{
|
|
792
776
|
marketId: number;
|
|
793
777
|
feeKind: FillRole;
|
|
794
778
|
accountId: number;
|
|
795
|
-
}): Promise<number> {
|
|
779
|
+
}>): Promise<number> {
|
|
796
780
|
return await this.GET("/market/{market_id}/fees/{fee_kind}/{account_id}", {
|
|
797
781
|
params: {
|
|
798
782
|
path: {
|
|
@@ -838,20 +822,27 @@ export class Nord {
|
|
|
838
822
|
* Get trade history for a specific order.
|
|
839
823
|
*
|
|
840
824
|
* @param orderId - Order identifier
|
|
841
|
-
* @param
|
|
825
|
+
* @param startInclusive - Trade pagination cursor
|
|
826
|
+
* @param pageSize - Maximum number of trades to return
|
|
842
827
|
* @returns Page of trades associated with the order
|
|
843
828
|
* @throws {NordError} If the request fails
|
|
844
829
|
*/
|
|
845
830
|
public async getOrderTrades(
|
|
846
831
|
orderId: string,
|
|
847
|
-
|
|
832
|
+
{
|
|
833
|
+
startInclusive,
|
|
834
|
+
pageSize,
|
|
835
|
+
}: Readonly<{
|
|
836
|
+
startInclusive?: string | null;
|
|
837
|
+
pageSize?: number | null;
|
|
838
|
+
}> = {},
|
|
848
839
|
): Promise<PageResultStringTrade> {
|
|
849
840
|
return await this.GET("/order/{order_id}/trades", {
|
|
850
841
|
params: {
|
|
851
842
|
path: { order_id: orderId },
|
|
852
843
|
query: {
|
|
853
|
-
startInclusive
|
|
854
|
-
pageSize
|
|
844
|
+
startInclusive,
|
|
845
|
+
pageSize,
|
|
855
846
|
},
|
|
856
847
|
},
|
|
857
848
|
});
|
|
@@ -871,14 +862,14 @@ export class Nord {
|
|
|
871
862
|
/**
|
|
872
863
|
* Fetch active triggers for an account.
|
|
873
864
|
*
|
|
874
|
-
* @param
|
|
865
|
+
* @param accountId - Account identifier owning the triggers
|
|
875
866
|
* @throws {NordError} If no account can be resolved or the request fails.
|
|
876
867
|
*/
|
|
877
|
-
async getAccountTriggers(
|
|
868
|
+
async getAccountTriggers({
|
|
869
|
+
accountId,
|
|
870
|
+
}: Readonly<{
|
|
878
871
|
accountId?: number;
|
|
879
|
-
}): Promise<AccountTriggerInfo[]> {
|
|
880
|
-
const accountId = params?.accountId;
|
|
881
|
-
|
|
872
|
+
}> = {}): Promise<AccountTriggerInfo[]> {
|
|
882
873
|
if (accountId == null) {
|
|
883
874
|
throw new NordError(
|
|
884
875
|
"Account ID is undefined. Make sure to call updateAccountId() before requesting triggers.",
|
|
@@ -900,30 +891,37 @@ export class Nord {
|
|
|
900
891
|
/**
|
|
901
892
|
* Fetch trigger history for an account.
|
|
902
893
|
*
|
|
903
|
-
* @param
|
|
894
|
+
* @param accountId - Account identifier owning the triggers
|
|
895
|
+
* @param since - RFC3339 timestamp to start from (inclusive)
|
|
896
|
+
* @param until - RFC3339 timestamp to end at (exclusive)
|
|
897
|
+
* @param pageSize - Maximum number of entries to return
|
|
898
|
+
* @param startInclusive - Pagination cursor to resume from
|
|
904
899
|
* @throws {NordError} If no account can be resolved or the request fails.
|
|
905
900
|
*/
|
|
906
|
-
async getAccountTriggerHistory(
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
901
|
+
async getAccountTriggerHistory({
|
|
902
|
+
accountId,
|
|
903
|
+
since,
|
|
904
|
+
until,
|
|
905
|
+
pageSize,
|
|
906
|
+
startInclusive,
|
|
907
|
+
}: Readonly<
|
|
908
|
+
HistoryTriggerQuery & { accountId?: number }
|
|
909
|
+
>): Promise<TriggerHistoryPage> {
|
|
911
910
|
if (accountId == null) {
|
|
912
911
|
throw new NordError(
|
|
913
912
|
"Account ID is undefined. Make sure to call updateAccountId() before requesting trigger history.",
|
|
914
913
|
);
|
|
915
914
|
}
|
|
916
915
|
|
|
917
|
-
const { accountId: _, ...query } = params;
|
|
918
916
|
try {
|
|
919
917
|
return await this.GET("/account/{account_id}/triggers/history", {
|
|
920
918
|
params: {
|
|
921
919
|
path: { account_id: accountId },
|
|
922
920
|
query: {
|
|
923
|
-
since
|
|
924
|
-
until
|
|
925
|
-
pageSize
|
|
926
|
-
startInclusive
|
|
921
|
+
since,
|
|
922
|
+
until,
|
|
923
|
+
pageSize,
|
|
924
|
+
startInclusive,
|
|
927
925
|
},
|
|
928
926
|
},
|
|
929
927
|
});
|