@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.
Files changed (47) hide show
  1. package/dist/actions.d.ts +57 -0
  2. package/dist/actions.js +229 -0
  3. package/dist/client/Nord.d.ts +379 -0
  4. package/dist/client/Nord.js +718 -0
  5. package/dist/client/NordAdmin.d.ts +225 -0
  6. package/dist/client/NordAdmin.js +394 -0
  7. package/dist/client/NordUser.d.ts +350 -0
  8. package/dist/client/NordUser.js +743 -0
  9. package/dist/error.d.ts +35 -0
  10. package/dist/error.js +49 -0
  11. package/dist/gen/nord_pb.d.ts +233 -7
  12. package/dist/gen/nord_pb.js +34 -8
  13. package/dist/gen/openapi.d.ts +40 -0
  14. package/dist/index.d.ts +6 -1
  15. package/dist/index.js +29 -1
  16. package/dist/nord/client/Nord.d.ts +1 -1
  17. package/dist/nord/client/Nord.js +2 -2
  18. package/dist/nord/client/NordAdmin.d.ts +24 -1
  19. package/dist/nord/client/NordAdmin.js +63 -5
  20. package/dist/nord/index.d.ts +1 -1
  21. package/dist/nord/index.js +2 -1
  22. package/dist/types.d.ts +6 -50
  23. package/dist/types.js +1 -24
  24. package/dist/utils.d.ts +8 -11
  25. package/dist/utils.js +54 -41
  26. package/dist/websocket/Subscriber.d.ts +37 -0
  27. package/dist/websocket/Subscriber.js +25 -0
  28. package/dist/websocket/index.d.ts +19 -2
  29. package/dist/websocket/index.js +82 -2
  30. package/package.json +1 -1
  31. package/src/actions.ts +333 -0
  32. package/src/{nord/client → client}/Nord.ts +209 -211
  33. package/src/{nord/client → client}/NordAdmin.ts +196 -153
  34. package/src/{nord/client → client}/NordUser.ts +216 -305
  35. package/src/gen/nord_pb.ts +271 -9
  36. package/src/gen/openapi.ts +40 -0
  37. package/src/index.ts +7 -1
  38. package/src/types.ts +7 -54
  39. package/src/utils.ts +44 -47
  40. package/src/{nord/models → websocket}/Subscriber.ts +2 -2
  41. package/src/websocket/index.ts +105 -2
  42. package/src/nord/api/actions.ts +0 -648
  43. package/src/nord/api/core.ts +0 -96
  44. package/src/nord/api/metrics.ts +0 -269
  45. package/src/nord/client/NordClient.ts +0 -79
  46. package/src/nord/index.ts +0 -25
  47. /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 "../../gen/nord_pb";
6
- import type { paths } from "../../gen/openapi.ts";
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 "../../types";
36
- import * as utils from "../../utils";
37
- import { NordWebSocketClient } from "../../websocket/index";
38
- import * as core from "../api/core";
39
- import * as metrics from "../api/metrics";
40
- import { OrderbookSubscription, TradeSubscription } from "../models/Subscriber";
41
- import { NordError } from "../utils/NordError";
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 solanaUrl: string;
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
- private httpClient: Client<paths>;
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
- solanaUrl,
84
+ solanaConnection,
97
85
  webServerUrl,
98
86
  protonClient,
99
87
  }: Readonly<{
100
- solanaUrl: string;
88
+ solanaConnection: Connection;
101
89
  webServerUrl: string;
102
90
  protonClient: ProtonClient;
103
91
  }>) {
104
92
  this.webServerUrl = webServerUrl;
105
- this.solanaUrl = solanaUrl;
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 options - Subscription options that specify which data streams to subscribe to
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
- options: WebSocketSubscriptionOptions,
133
- ): NordWebSocketClient {
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 (options.trades && options.trades.length > 0) {
138
- options.trades.forEach((symbol) => {
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 (options.deltas && options.deltas.length > 0) {
145
- options.deltas.forEach((symbol) => {
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 (options.accounts && options.accounts.length > 0) {
152
- options.accounts.forEach((accountId) => {
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 core.initWebSocketClient(this.webServerUrl, subscriptions);
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 initNord({
249
+ public static async new({
239
250
  app,
240
- solanaUrl,
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: connection,
258
+ solConn: solanaConnection,
251
259
  });
252
260
  const nord = new Nord({
253
261
  protonClient,
254
- solanaUrl,
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 query - Action query parameters
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
- action_id,
278
- }: {
279
- action_id: number;
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: action_id,
285
- to: action_id,
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(query: {
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 query - Trades query parameters
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
- query: Readonly<{
527
- marketId?: number;
528
- takerId?: number;
529
- makerId?: number;
530
- takerSide?: "bid" | "ask";
531
- pageSize?: number;
532
- sinceRcf3339?: string;
533
- untilRfc3339?: string;
534
- pageId?: string;
535
- }>,
536
- ): Promise<TradesResponse> {
537
- if (query.sinceRcf3339 && !utils.isRfc3339(query.sinceRcf3339)) {
538
- throw new NordError(`Invalid RFC3339 timestamp: ${query.sinceRcf3339}`);
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 (query.untilRfc3339 && !utils.isRfc3339(query.untilRfc3339)) {
541
- throw new NordError(`Invalid RFC3339 timestamp: ${query.untilRfc3339}`);
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: query.takerId,
547
- makerId: query.makerId,
548
- marketId: query.marketId,
549
- pageSize: query.pageSize,
550
- takerSide: query.takerSide,
551
- since: query.sinceRcf3339,
552
- until: query.untilRfc3339,
553
- startInclusive: query.pageId,
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 query - User account IDs query parameters
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(query: {
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: query.pubkey.toString() },
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 query - Orderbook query parameters (either market_id or symbol must be provided)
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(query: OrderbookQuery): Promise<OrderbookResponse> {
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 marketId: number;
592
- if (query.symbol && query.market_id === undefined) {
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(query.symbol);
556
+ const id = this.symbolToMarketId.get(symbol);
599
557
  if (id === undefined) {
600
- throw new NordError(`Unknown market symbol: ${query.symbol}`);
558
+ throw new NordError(`Unknown market symbol: ${symbol}`);
601
559
  }
602
- marketId = id;
603
- } else if (query.market_id !== undefined) {
604
- marketId = query.market_id;
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: marketId },
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 query - Optional pagination parameters
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
- query?: { startInclusive?: string | null; pageSize?: number | null },
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: query?.startInclusive,
715
- pageSize: query?.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(query?: {
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: query?.startInclusive ?? undefined,
732
- pageSize: query?.pageSize ?? undefined,
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 query - Optional time and pagination filters
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
- query?: Partial<AccountPnlQuery>,
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: query?.since,
755
- until: query?.until,
756
- startInclusive: query?.startInclusive,
757
- pageSize: query?.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 params - Market id, fee kind, and account id to quote
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 query - Optional pagination parameters
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
- query?: { startInclusive?: string | null; pageSize?: number | null },
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: query?.startInclusive,
854
- pageSize: query?.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 params Optional parameters containing an explicit account id.
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(params?: {
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 params Optional parameters with account id and history query filters.
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
- params: HistoryTriggerQuery & { accountId?: number },
908
- ): Promise<TriggerHistoryPage> {
909
- const accountId = params?.accountId;
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: query.since,
924
- until: query.until,
925
- pageSize: query.pageSize,
926
- startInclusive: query.startInclusive,
921
+ since,
922
+ until,
923
+ pageSize,
924
+ startInclusive,
927
925
  },
928
926
  },
929
927
  });