@n1xyz/nord-ts 0.1.6 → 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/openapi.d.ts +40 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +29 -1
- package/dist/nord/client/NordAdmin.js +2 -0
- package/dist/types.d.ts +4 -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 +207 -210
- package/src/{nord/client → client}/NordAdmin.ts +123 -153
- package/src/{nord/client → client}/NordUser.ts +216 -305
- package/src/gen/openapi.ts +40 -0
- package/src/index.ts +7 -1
- package/src/types.ts +4 -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,24 +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,
|
|
242
253
|
protonUrl,
|
|
243
254
|
}: Readonly<NordConfig>): Promise<Nord> {
|
|
244
|
-
// TODO: we should parametrize the connectionn not have it done here.
|
|
245
|
-
// this is a dogshit api, only here to be compatible with the shitty
|
|
246
|
-
// vibecoded code and not break zero one team's workflow.
|
|
247
|
-
const connection = new Connection(solanaUrl, { commitment: "confirmed" });
|
|
248
255
|
const protonClient = await ProtonClient.init({
|
|
249
256
|
protonUrl: protonUrl ?? webServerUrl,
|
|
250
257
|
app: new PublicKey(app),
|
|
251
|
-
solConn:
|
|
258
|
+
solConn: solanaConnection,
|
|
252
259
|
});
|
|
253
260
|
const nord = new Nord({
|
|
254
261
|
protonClient,
|
|
255
|
-
|
|
262
|
+
solanaConnection,
|
|
256
263
|
webServerUrl,
|
|
257
264
|
});
|
|
258
265
|
await nord.init();
|
|
@@ -270,20 +277,20 @@ export class Nord {
|
|
|
270
277
|
/**
|
|
271
278
|
* Query a specific action
|
|
272
279
|
*
|
|
273
|
-
* @param
|
|
280
|
+
* @param actionId - Action identifier to fetch
|
|
274
281
|
* @returns Action response
|
|
275
282
|
* @throws {NordError} If the request fails
|
|
276
283
|
*/
|
|
277
284
|
async queryAction({
|
|
278
|
-
|
|
279
|
-
}: {
|
|
280
|
-
|
|
281
|
-
}): Promise<ActionResponse | null> {
|
|
285
|
+
actionId,
|
|
286
|
+
}: Readonly<{
|
|
287
|
+
actionId: number;
|
|
288
|
+
}>): Promise<ActionResponse | null> {
|
|
282
289
|
return (
|
|
283
290
|
(
|
|
284
291
|
await this.queryRecentActions({
|
|
285
|
-
from:
|
|
286
|
-
to:
|
|
292
|
+
from: actionId,
|
|
293
|
+
to: actionId,
|
|
287
294
|
})
|
|
288
295
|
)[0] ?? null
|
|
289
296
|
);
|
|
@@ -292,18 +299,21 @@ export class Nord {
|
|
|
292
299
|
/**
|
|
293
300
|
* Query recent actions
|
|
294
301
|
*
|
|
295
|
-
* @param from - Starting action index
|
|
296
|
-
* @param to - Ending action index
|
|
302
|
+
* @param from - Starting action index (inclusive)
|
|
303
|
+
* @param to - Ending action index (inclusive)
|
|
297
304
|
* @returns Actions response
|
|
298
305
|
* @throws {NordError} If the request fails
|
|
299
306
|
*/
|
|
300
|
-
async queryRecentActions(
|
|
307
|
+
async queryRecentActions({
|
|
308
|
+
from,
|
|
309
|
+
to,
|
|
310
|
+
}: Readonly<{
|
|
301
311
|
from: number;
|
|
302
312
|
to: number;
|
|
303
|
-
}): Promise<ActionResponse[]> {
|
|
313
|
+
}>): Promise<ActionResponse[]> {
|
|
304
314
|
const xs = await this.GET("/action", {
|
|
305
315
|
params: {
|
|
306
|
-
query,
|
|
316
|
+
query: { from, to },
|
|
307
317
|
},
|
|
308
318
|
});
|
|
309
319
|
return xs.map((x) => ({
|
|
@@ -326,79 +336,6 @@ export class Nord {
|
|
|
326
336
|
return await this.GET("/action/last-executed-id", {});
|
|
327
337
|
}
|
|
328
338
|
|
|
329
|
-
/**
|
|
330
|
-
* Fetch aggregate metrics from the Nord API
|
|
331
|
-
*
|
|
332
|
-
* @param txPeakTpsPeriod - Period for peak TPS calculation
|
|
333
|
-
* @param txPeakTpsPeriodUnit - Unit for peak TPS period
|
|
334
|
-
* @returns Aggregate metrics
|
|
335
|
-
* @throws {NordError} If the request fails
|
|
336
|
-
*/
|
|
337
|
-
async aggregateMetrics(
|
|
338
|
-
txPeakTpsPeriod = 1,
|
|
339
|
-
txPeakTpsPeriodUnit: PeakTpsPeriodUnit = PeakTpsPeriodUnit.Day,
|
|
340
|
-
): Promise<AggregateMetrics> {
|
|
341
|
-
return metrics.aggregateMetrics(
|
|
342
|
-
this.webServerUrl,
|
|
343
|
-
txPeakTpsPeriod,
|
|
344
|
-
txPeakTpsPeriodUnit,
|
|
345
|
-
);
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
/**
|
|
349
|
-
* Get current transactions per second
|
|
350
|
-
*
|
|
351
|
-
* @param period - Time period for the query
|
|
352
|
-
* @returns Current TPS value
|
|
353
|
-
* @throws {NordError} If the request fails
|
|
354
|
-
*/
|
|
355
|
-
async getCurrentTps(period: string = "1m") {
|
|
356
|
-
return metrics.getCurrentTps(this.webServerUrl, period);
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
/**
|
|
360
|
-
* Get peak transactions per second
|
|
361
|
-
*
|
|
362
|
-
* @param period - Time period for the query
|
|
363
|
-
* @returns Peak TPS value
|
|
364
|
-
* @throws {NordError} If the request fails
|
|
365
|
-
*/
|
|
366
|
-
async getPeakTps(period: string = "24h") {
|
|
367
|
-
return metrics.getPeakTps(this.webServerUrl, period);
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
/**
|
|
371
|
-
* Get median transaction latency
|
|
372
|
-
*
|
|
373
|
-
* @param period - Time period for the query
|
|
374
|
-
* @returns Median latency in milliseconds
|
|
375
|
-
* @throws {NordError} If the request fails
|
|
376
|
-
*/
|
|
377
|
-
async getMedianLatency(period: string = "1m") {
|
|
378
|
-
return metrics.getMedianLatency(this.webServerUrl, period);
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
/**
|
|
382
|
-
* Get total transaction count
|
|
383
|
-
*
|
|
384
|
-
* @returns Total transaction count
|
|
385
|
-
* @throws {NordError} If the request fails
|
|
386
|
-
*/
|
|
387
|
-
async getTotalTransactions() {
|
|
388
|
-
return metrics.getTotalTransactions(this.webServerUrl);
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
/**
|
|
392
|
-
* Query Prometheus metrics
|
|
393
|
-
*
|
|
394
|
-
* @param params - Prometheus query parameters
|
|
395
|
-
* @returns Query result as a number
|
|
396
|
-
* @throws {NordError} If the request fails
|
|
397
|
-
*/
|
|
398
|
-
async queryPrometheus(params: string): Promise<number> {
|
|
399
|
-
return metrics.queryPrometheus(this.webServerUrl, params);
|
|
400
|
-
}
|
|
401
|
-
|
|
402
339
|
/**
|
|
403
340
|
* Subscribe to orderbook updates for a market
|
|
404
341
|
*
|
|
@@ -519,39 +456,53 @@ export class Nord {
|
|
|
519
456
|
/**
|
|
520
457
|
* Get trades for a market
|
|
521
458
|
*
|
|
522
|
-
* @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
|
|
523
467
|
* @returns Trades response
|
|
524
468
|
* @throws {NordError} If the request fails
|
|
525
469
|
*/
|
|
526
|
-
public async getTrades(
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
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}`);
|
|
540
491
|
}
|
|
541
|
-
if (
|
|
542
|
-
throw new NordError(`Invalid RFC3339 timestamp: ${
|
|
492
|
+
if (until && !utils.isRfc3339(until)) {
|
|
493
|
+
throw new NordError(`Invalid RFC3339 timestamp: ${until}`);
|
|
543
494
|
}
|
|
544
495
|
return await this.GET("/trades", {
|
|
545
496
|
params: {
|
|
546
497
|
query: {
|
|
547
|
-
takerId
|
|
548
|
-
makerId
|
|
549
|
-
marketId
|
|
550
|
-
pageSize
|
|
551
|
-
takerSide
|
|
552
|
-
since
|
|
553
|
-
until
|
|
554
|
-
startInclusive
|
|
498
|
+
takerId,
|
|
499
|
+
makerId,
|
|
500
|
+
marketId,
|
|
501
|
+
pageSize,
|
|
502
|
+
takerSide,
|
|
503
|
+
since,
|
|
504
|
+
until,
|
|
505
|
+
startInclusive,
|
|
555
506
|
},
|
|
556
507
|
},
|
|
557
508
|
});
|
|
@@ -560,16 +511,18 @@ export class Nord {
|
|
|
560
511
|
/**
|
|
561
512
|
* Get user account IDs
|
|
562
513
|
*
|
|
563
|
-
* @param
|
|
514
|
+
* @param pubkey - User public key to query
|
|
564
515
|
* @returns User account IDs response
|
|
565
516
|
* @throws {NordError} If the request fails
|
|
566
517
|
*/
|
|
567
|
-
public async getUser(
|
|
518
|
+
public async getUser({
|
|
519
|
+
pubkey,
|
|
520
|
+
}: Readonly<{
|
|
568
521
|
pubkey: string | PublicKey;
|
|
569
|
-
}): Promise<User | null> {
|
|
522
|
+
}>): Promise<User | null> {
|
|
570
523
|
const r = await this.httpClient.GET("/user/{pubkey}", {
|
|
571
524
|
params: {
|
|
572
|
-
path: { pubkey:
|
|
525
|
+
path: { pubkey: pubkey.toString() },
|
|
573
526
|
},
|
|
574
527
|
});
|
|
575
528
|
if (r.response.status === 404) {
|
|
@@ -581,28 +534,32 @@ export class Nord {
|
|
|
581
534
|
/**
|
|
582
535
|
* Get orderbook for a market
|
|
583
536
|
*
|
|
584
|
-
* @param
|
|
537
|
+
* @param symbol - Market symbol to resolve into an id
|
|
538
|
+
* @param marketId - Market identifier
|
|
585
539
|
* @returns Orderbook response
|
|
586
540
|
* @throws {NordError} If the request fails or if the market symbol is unknown
|
|
587
541
|
* @remarks It's recommended to initialize the Nord client using the static `initNord` method
|
|
588
542
|
* to ensure market information is properly loaded before calling this method.
|
|
589
543
|
*/
|
|
590
|
-
public async getOrderbook(
|
|
544
|
+
public async getOrderbook({
|
|
545
|
+
symbol,
|
|
546
|
+
marketId,
|
|
547
|
+
}: OrderbookQuery): Promise<OrderbookResponse> {
|
|
591
548
|
// If only symbol is provided, convert it to market_id
|
|
592
|
-
let
|
|
593
|
-
if (
|
|
549
|
+
let _marketId: number;
|
|
550
|
+
if (symbol && marketId === undefined) {
|
|
594
551
|
// If the map is empty, try to fetch market information first
|
|
595
552
|
if (this.symbolToMarketId.size === 0) {
|
|
596
553
|
await this.fetchNordInfo();
|
|
597
554
|
}
|
|
598
555
|
|
|
599
|
-
const id = this.symbolToMarketId.get(
|
|
556
|
+
const id = this.symbolToMarketId.get(symbol);
|
|
600
557
|
if (id === undefined) {
|
|
601
|
-
throw new NordError(`Unknown market symbol: ${
|
|
558
|
+
throw new NordError(`Unknown market symbol: ${symbol}`);
|
|
602
559
|
}
|
|
603
|
-
|
|
604
|
-
} else if (
|
|
605
|
-
|
|
560
|
+
_marketId = id;
|
|
561
|
+
} else if (marketId !== undefined) {
|
|
562
|
+
_marketId = marketId;
|
|
606
563
|
} else {
|
|
607
564
|
throw new NordError(
|
|
608
565
|
"Either symbol or market_id must be provided for orderbook query",
|
|
@@ -611,7 +568,7 @@ export class Nord {
|
|
|
611
568
|
|
|
612
569
|
return await this.GET("/market/{market_id}/orderbook", {
|
|
613
570
|
params: {
|
|
614
|
-
path: { market_id:
|
|
571
|
+
path: { market_id: _marketId },
|
|
615
572
|
},
|
|
616
573
|
});
|
|
617
574
|
}
|
|
@@ -700,20 +657,27 @@ export class Nord {
|
|
|
700
657
|
* Get open orders for an account.
|
|
701
658
|
*
|
|
702
659
|
* @param accountId - Account id to query
|
|
703
|
-
* @param
|
|
660
|
+
* @param startInclusive - Pagination cursor (client order id) to resume from
|
|
661
|
+
* @param pageSize - Maximum number of orders to return
|
|
704
662
|
* @returns Page of orders keyed by client order id
|
|
705
663
|
* @throws {NordError} If the request fails
|
|
706
664
|
*/
|
|
707
665
|
public async getAccountOrders(
|
|
708
666
|
accountId: number,
|
|
709
|
-
|
|
667
|
+
{
|
|
668
|
+
startInclusive,
|
|
669
|
+
pageSize,
|
|
670
|
+
}: Readonly<{
|
|
671
|
+
startInclusive?: string | null;
|
|
672
|
+
pageSize?: number | null;
|
|
673
|
+
}> = {},
|
|
710
674
|
): Promise<PageResultStringOrderInfo> {
|
|
711
675
|
return await this.GET("/account/{account_id}/orders", {
|
|
712
676
|
params: {
|
|
713
677
|
path: { account_id: accountId },
|
|
714
678
|
query: {
|
|
715
|
-
startInclusive
|
|
716
|
-
pageSize
|
|
679
|
+
startInclusive,
|
|
680
|
+
pageSize,
|
|
717
681
|
},
|
|
718
682
|
},
|
|
719
683
|
});
|
|
@@ -721,16 +685,22 @@ export class Nord {
|
|
|
721
685
|
|
|
722
686
|
/**
|
|
723
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
|
|
724
691
|
*/
|
|
725
|
-
public async getAccountsFeeTiers(
|
|
692
|
+
public async getAccountsFeeTiers({
|
|
693
|
+
startInclusive,
|
|
694
|
+
pageSize,
|
|
695
|
+
}: Readonly<{
|
|
726
696
|
startInclusive?: number | null;
|
|
727
697
|
pageSize?: number | null;
|
|
728
|
-
}): Promise<AccountFeeTierPage> {
|
|
698
|
+
}> = {}): Promise<AccountFeeTierPage> {
|
|
729
699
|
return await this.GET("/accounts/fee-tiers", {
|
|
730
700
|
params: {
|
|
731
701
|
query: {
|
|
732
|
-
startInclusive:
|
|
733
|
-
pageSize:
|
|
702
|
+
startInclusive: startInclusive ?? undefined,
|
|
703
|
+
pageSize: pageSize ?? undefined,
|
|
734
704
|
},
|
|
735
705
|
},
|
|
736
706
|
});
|
|
@@ -740,22 +710,30 @@ export class Nord {
|
|
|
740
710
|
* Get profit and loss history for an account
|
|
741
711
|
*
|
|
742
712
|
* @param accountId - Account ID to query
|
|
743
|
-
* @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
|
|
744
717
|
* @returns Page of PnL entries ordered from latest to oldest
|
|
745
718
|
* @throws {NordError} If the request fails
|
|
746
719
|
*/
|
|
747
720
|
public async getAccountPnl(
|
|
748
721
|
accountId: number,
|
|
749
|
-
|
|
722
|
+
{
|
|
723
|
+
since,
|
|
724
|
+
until,
|
|
725
|
+
startInclusive,
|
|
726
|
+
pageSize,
|
|
727
|
+
}: Readonly<Partial<AccountPnlQuery>> = {},
|
|
750
728
|
): Promise<AccountPnlPage> {
|
|
751
729
|
return await this.GET("/account/{account_id}/pnl", {
|
|
752
730
|
params: {
|
|
753
731
|
path: { account_id: accountId },
|
|
754
732
|
query: {
|
|
755
|
-
since
|
|
756
|
-
until
|
|
757
|
-
startInclusive
|
|
758
|
-
pageSize
|
|
733
|
+
since,
|
|
734
|
+
until,
|
|
735
|
+
startInclusive,
|
|
736
|
+
pageSize,
|
|
759
737
|
},
|
|
760
738
|
},
|
|
761
739
|
});
|
|
@@ -764,13 +742,16 @@ export class Nord {
|
|
|
764
742
|
/**
|
|
765
743
|
* Get market statistics (alias for marketsStats for backward compatibility)
|
|
766
744
|
*
|
|
745
|
+
*
|
|
746
|
+
* @param marketId - Market identifier
|
|
747
|
+
*
|
|
767
748
|
* @returns Market statistics response
|
|
768
749
|
*/
|
|
769
750
|
public async getMarketStats({
|
|
770
751
|
marketId,
|
|
771
|
-
}: {
|
|
752
|
+
}: Readonly<{
|
|
772
753
|
marketId: number;
|
|
773
|
-
}): Promise<MarketStats> {
|
|
754
|
+
}>): Promise<MarketStats> {
|
|
774
755
|
return await this.GET("/market/{market_id}/stats", {
|
|
775
756
|
params: {
|
|
776
757
|
path: { market_id: marketId },
|
|
@@ -781,7 +762,9 @@ export class Nord {
|
|
|
781
762
|
/**
|
|
782
763
|
* Fetch the per-market fee quote for an account.
|
|
783
764
|
*
|
|
784
|
-
* @param
|
|
765
|
+
* @param marketId - Market identifier
|
|
766
|
+
* @param feeKind - Fill role (maker/taker) to quote
|
|
767
|
+
* @param accountId - Account identifier to quote
|
|
785
768
|
* @returns Fee in quote token units (negative means fee is charged)
|
|
786
769
|
* @throws {NordError} If the request fails
|
|
787
770
|
*/
|
|
@@ -789,11 +772,11 @@ export class Nord {
|
|
|
789
772
|
marketId,
|
|
790
773
|
feeKind,
|
|
791
774
|
accountId,
|
|
792
|
-
}: {
|
|
775
|
+
}: Readonly<{
|
|
793
776
|
marketId: number;
|
|
794
777
|
feeKind: FillRole;
|
|
795
778
|
accountId: number;
|
|
796
|
-
}): Promise<number> {
|
|
779
|
+
}>): Promise<number> {
|
|
797
780
|
return await this.GET("/market/{market_id}/fees/{fee_kind}/{account_id}", {
|
|
798
781
|
params: {
|
|
799
782
|
path: {
|
|
@@ -839,20 +822,27 @@ export class Nord {
|
|
|
839
822
|
* Get trade history for a specific order.
|
|
840
823
|
*
|
|
841
824
|
* @param orderId - Order identifier
|
|
842
|
-
* @param
|
|
825
|
+
* @param startInclusive - Trade pagination cursor
|
|
826
|
+
* @param pageSize - Maximum number of trades to return
|
|
843
827
|
* @returns Page of trades associated with the order
|
|
844
828
|
* @throws {NordError} If the request fails
|
|
845
829
|
*/
|
|
846
830
|
public async getOrderTrades(
|
|
847
831
|
orderId: string,
|
|
848
|
-
|
|
832
|
+
{
|
|
833
|
+
startInclusive,
|
|
834
|
+
pageSize,
|
|
835
|
+
}: Readonly<{
|
|
836
|
+
startInclusive?: string | null;
|
|
837
|
+
pageSize?: number | null;
|
|
838
|
+
}> = {},
|
|
849
839
|
): Promise<PageResultStringTrade> {
|
|
850
840
|
return await this.GET("/order/{order_id}/trades", {
|
|
851
841
|
params: {
|
|
852
842
|
path: { order_id: orderId },
|
|
853
843
|
query: {
|
|
854
|
-
startInclusive
|
|
855
|
-
pageSize
|
|
844
|
+
startInclusive,
|
|
845
|
+
pageSize,
|
|
856
846
|
},
|
|
857
847
|
},
|
|
858
848
|
});
|
|
@@ -872,14 +862,14 @@ export class Nord {
|
|
|
872
862
|
/**
|
|
873
863
|
* Fetch active triggers for an account.
|
|
874
864
|
*
|
|
875
|
-
* @param
|
|
865
|
+
* @param accountId - Account identifier owning the triggers
|
|
876
866
|
* @throws {NordError} If no account can be resolved or the request fails.
|
|
877
867
|
*/
|
|
878
|
-
async getAccountTriggers(
|
|
868
|
+
async getAccountTriggers({
|
|
869
|
+
accountId,
|
|
870
|
+
}: Readonly<{
|
|
879
871
|
accountId?: number;
|
|
880
|
-
}): Promise<AccountTriggerInfo[]> {
|
|
881
|
-
const accountId = params?.accountId;
|
|
882
|
-
|
|
872
|
+
}> = {}): Promise<AccountTriggerInfo[]> {
|
|
883
873
|
if (accountId == null) {
|
|
884
874
|
throw new NordError(
|
|
885
875
|
"Account ID is undefined. Make sure to call updateAccountId() before requesting triggers.",
|
|
@@ -901,30 +891,37 @@ export class Nord {
|
|
|
901
891
|
/**
|
|
902
892
|
* Fetch trigger history for an account.
|
|
903
893
|
*
|
|
904
|
-
* @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
|
|
905
899
|
* @throws {NordError} If no account can be resolved or the request fails.
|
|
906
900
|
*/
|
|
907
|
-
async getAccountTriggerHistory(
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
901
|
+
async getAccountTriggerHistory({
|
|
902
|
+
accountId,
|
|
903
|
+
since,
|
|
904
|
+
until,
|
|
905
|
+
pageSize,
|
|
906
|
+
startInclusive,
|
|
907
|
+
}: Readonly<
|
|
908
|
+
HistoryTriggerQuery & { accountId?: number }
|
|
909
|
+
>): Promise<TriggerHistoryPage> {
|
|
912
910
|
if (accountId == null) {
|
|
913
911
|
throw new NordError(
|
|
914
912
|
"Account ID is undefined. Make sure to call updateAccountId() before requesting trigger history.",
|
|
915
913
|
);
|
|
916
914
|
}
|
|
917
915
|
|
|
918
|
-
const { accountId: _, ...query } = params;
|
|
919
916
|
try {
|
|
920
917
|
return await this.GET("/account/{account_id}/triggers/history", {
|
|
921
918
|
params: {
|
|
922
919
|
path: { account_id: accountId },
|
|
923
920
|
query: {
|
|
924
|
-
since
|
|
925
|
-
until
|
|
926
|
-
pageSize
|
|
927
|
-
startInclusive
|
|
921
|
+
since,
|
|
922
|
+
until,
|
|
923
|
+
pageSize,
|
|
924
|
+
startInclusive,
|
|
928
925
|
},
|
|
929
926
|
},
|
|
930
927
|
});
|