@n1xyz/nord-ts 0.1.12 → 0.2.0

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.
@@ -3,7 +3,7 @@ import { Connection, PublicKey } from "@solana/web3.js";
3
3
  import { EventEmitter } from "events";
4
4
  import { Client } from "openapi-fetch";
5
5
  import type { paths } from "../gen/openapi.ts";
6
- import { Account, AccountPnlPage, PagedQuery, ActionResponse, MarketsInfo, Market, MarketStats, NordConfig, OrderbookQuery, OrderbookResponse, FeeTierConfig, Token, TradesResponse, User, AccountTriggerInfo, TriggerHistoryPage, WithdrawalHistoryPage, FeeTierId, AccountFeeTierPage, PageResultStringOrderInfo, PageResultStringTrade, OrderInfoFromApi, TokenStats, FillRole, AdminInfo, AccountVolumeInfo, GetAccountVolumeQuery, PreviousMarketPrice } from "../types";
6
+ import { Account, AccountPnlInfoPage, PagedQuery, ActionResponse, MarketsInfo, Market, MarketStats, NordConfig, OrderbookQuery, OrderbookResponse, FeeTierConfig, Token, TradesResponse, User, AccountTriggerInfo, TriggerHistoryPage, WithdrawalHistoryPage, FeeTierId, AccountFeeTierPage, PageResultStringOrderInfo, PageResultStringTrade, OrderInfoFromApi, TokenStats, FillRole, AdminInfo, AccountVolumeInfo, GetAccountVolumeQuery, PreviousMarketPrice } from "../types";
7
7
  import { NordWebSocketClient } from "../websocket/index";
8
8
  import { OrderbookSubscription, TradeSubscription } from "../websocket/Subscriber";
9
9
  /**
@@ -302,7 +302,7 @@ export declare class Nord {
302
302
  * @returns Page of PnL entries ordered from latest to oldest
303
303
  * @throws {NordError} If the request fails
304
304
  */
305
- getAccountPnl(accountId: number, { since, until, startInclusive, pageSize, }?: Readonly<Partial<PagedQuery>>): Promise<AccountPnlPage>;
305
+ getAccountPnl(accountId: number, { since, until, startInclusive, pageSize, }?: Readonly<Partial<PagedQuery>>): Promise<AccountPnlInfoPage>;
306
306
  /**
307
307
  * Get market statistics (alias for marketsStats for backward compatibility)
308
308
  *
@@ -265,7 +265,7 @@ export class Nord {
265
265
  deltas: [symbol],
266
266
  });
267
267
  const handleDelta = (update) => {
268
- if (update.symbol !== symbol) {
268
+ if (update.market_symbol !== symbol) {
269
269
  return;
270
270
  }
271
271
  subscription.emit("message", update);
@@ -50,6 +50,17 @@ export declare class NordUser {
50
50
  symbol: string;
51
51
  }[];
52
52
  };
53
+ orders: {
54
+ [key: string]: {
55
+ orderId: string;
56
+ marketId: number;
57
+ side: "ask" | "bid";
58
+ size: number;
59
+ price: number;
60
+ originalOrderSize: number;
61
+ clientOrderId: number | null;
62
+ }[];
63
+ };
53
64
  /** User positions by account ID */
54
65
  positions: {
55
66
  [key: string]: {
@@ -4,7 +4,7 @@ import * as ed from "@noble/ed25519";
4
4
  import { floatToScaledBigIntLossy } from "@n1xyz/proton";
5
5
  import { Side, TriggerKind, fillModeToProtoFillMode, } from "../types";
6
6
  import * as proto from "../gen/nord_pb";
7
- import { checkedFetch, assert, findMarket, findToken, optExpect, keypairFromPrivateKey, toScaledU64, } from "../utils";
7
+ import { assert, findMarket, findToken, optExpect, keypairFromPrivateKey, toScaledU64, } from "../utils";
8
8
  import { create } from "@bufbuild/protobuf";
9
9
  import { createSession, revokeSession, atomic, expectReceiptKind, createAction, sendAction, } from "../actions";
10
10
  import { NordError } from "../error";
@@ -23,6 +23,7 @@ export class NordUser {
23
23
  nonce = 0;
24
24
  /** User balances by token symbol */
25
25
  balances = {};
26
+ orders = {};
26
27
  /** User positions by account ID */
27
28
  positions = {};
28
29
  /** User margins by account ID */
@@ -93,10 +94,10 @@ export class NordUser {
93
94
  return tx;
94
95
  },
95
96
  signMessageFn: async (xs) => {
96
- return ed.sign(xs, wallet.secretKey);
97
+ return await ed.signAsync(xs, wallet.secretKey.slice(0, 32));
97
98
  },
98
99
  signSessionFn: async (xs) => {
99
- return ed.sign(xs, sessionKey.secretKey);
100
+ return await ed.signAsync(xs, sessionKey.secretKey.slice(0, 32));
100
101
  },
101
102
  });
102
103
  }
@@ -244,8 +245,7 @@ export class NordUser {
244
245
  async fetchInfo() {
245
246
  if (this.accountIds !== undefined) {
246
247
  const accountsData = await Promise.all(this.accountIds.map(async (accountId) => {
247
- const response = await checkedFetch(`${this.nord.webServerUrl}/account/${accountId}`);
248
- const accountData = (await response.json());
248
+ const accountData = await this.nord.getAccount(accountId);
249
249
  // Ensure we have the correct accountId
250
250
  return {
251
251
  ...accountData,
@@ -253,6 +253,15 @@ export class NordUser {
253
253
  };
254
254
  }));
255
255
  for (const accountData of accountsData) {
256
+ this.orders[accountData.accountId] = accountData.orders.map((o) => ({
257
+ orderId: o.orderId,
258
+ marketId: o.marketId,
259
+ side: o.side,
260
+ size: o.size,
261
+ price: o.price,
262
+ originalOrderSize: o.originalOrderSize,
263
+ clientOrderId: o.clientOrderId ?? null,
264
+ }));
256
265
  // Process balances
257
266
  this.balances[accountData.accountId] = [];
258
267
  for (const balance of accountData.balances) {
@@ -263,7 +272,12 @@ export class NordUser {
263
272
  });
264
273
  }
265
274
  // Process positions
266
- this.positions[accountData.accountId] = accountData.positions;
275
+ this.positions[accountData.accountId] = accountData.positions.map((p) => ({
276
+ marketId: p.marketId,
277
+ openOrders: p.openOrders,
278
+ actionId: p.actionId,
279
+ ...(p.perp != null ? { perp: p.perp } : {}),
280
+ }));
267
281
  // Process margins
268
282
  this.margins[accountData.accountId] = accountData.margins;
269
283
  }
@@ -4238,6 +4238,9 @@ export declare enum Error {
4238
4238
  POSITION_STATE_ORDER_SIDE = 205,
4239
4239
  /**
4240
4240
  * 1100_1110
4241
+ * Maximuma size of single position exceeded.
4242
+ * See `POSITION_SIZE_LIMIT` constant default limit for exacat value and
4243
+ * details.
4241
4244
  *
4242
4245
  * @generated from enum value: POSITION_SIZE_LIMIT = 206;
4243
4246
  */
@@ -4270,6 +4273,9 @@ export declare enum Error {
4270
4273
  SIGNATURE_VERIFICATION_INVALID_LENGTH = 219,
4271
4274
  /**
4272
4275
  * 11011_000
4276
+ * Error prefix which indicates that some actions cannot to be executed,
4277
+ * if they move account into unhealthy(liquidatable) state
4278
+ * or if liquidaiton handling action as parameterized cannot be executed
4273
4279
  *
4274
4280
  * @generated from enum value: RISK = 224;
4275
4281
  */
@@ -4287,6 +4293,8 @@ export declare enum Error {
4287
4293
  */
4288
4294
  RISK_OMF_LESS_THAN_OR_EQUAL_CMF = 227,
4289
4295
  /**
4296
+ * See `OMF < CMF` rule in MARKETS.md.
4297
+ *
4290
4298
  * @generated from enum value: RISK_TRADE_OMF_LESS_THAN_OR_EQUAL_CMF = 229;
4291
4299
  */
4292
4300
  RISK_TRADE_OMF_LESS_THAN_OR_EQUAL_CMF = 229,
@@ -873,6 +873,9 @@ export var Error;
873
873
  Error[Error["POSITION_STATE_ORDER_SIDE"] = 205] = "POSITION_STATE_ORDER_SIDE";
874
874
  /**
875
875
  * 1100_1110
876
+ * Maximuma size of single position exceeded.
877
+ * See `POSITION_SIZE_LIMIT` constant default limit for exacat value and
878
+ * details.
876
879
  *
877
880
  * @generated from enum value: POSITION_SIZE_LIMIT = 206;
878
881
  */
@@ -905,6 +908,9 @@ export var Error;
905
908
  Error[Error["SIGNATURE_VERIFICATION_INVALID_LENGTH"] = 219] = "SIGNATURE_VERIFICATION_INVALID_LENGTH";
906
909
  /**
907
910
  * 11011_000
911
+ * Error prefix which indicates that some actions cannot to be executed,
912
+ * if they move account into unhealthy(liquidatable) state
913
+ * or if liquidaiton handling action as parameterized cannot be executed
908
914
  *
909
915
  * @generated from enum value: RISK = 224;
910
916
  */
@@ -922,6 +928,8 @@ export var Error;
922
928
  */
923
929
  Error[Error["RISK_OMF_LESS_THAN_OR_EQUAL_CMF"] = 227] = "RISK_OMF_LESS_THAN_OR_EQUAL_CMF";
924
930
  /**
931
+ * See `OMF < CMF` rule in MARKETS.md.
932
+ *
925
933
  * @generated from enum value: RISK_TRADE_OMF_LESS_THAN_OR_EQUAL_CMF = 229;
926
934
  */
927
935
  Error[Error["RISK_TRADE_OMF_LESS_THAN_OR_EQUAL_CMF"] = 229] = "RISK_TRADE_OMF_LESS_THAN_OR_EQUAL_CMF";
@@ -725,7 +725,44 @@ export interface paths {
725
725
  [name: string]: unknown;
726
726
  };
727
727
  content: {
728
- "application/json": components["schemas"]["PageResult_for_uint64_and_AccountPnl"];
728
+ "application/json": components["schemas"]["PageResult_for_uint64_and_AccountPnlInfo"];
729
+ };
730
+ };
731
+ };
732
+ };
733
+ put?: never;
734
+ post?: never;
735
+ delete?: never;
736
+ options?: never;
737
+ head?: never;
738
+ patch?: never;
739
+ trace?: never;
740
+ };
741
+ "/account/{account_id}/pnl/history/PT1H": {
742
+ parameters: {
743
+ query?: never;
744
+ header?: never;
745
+ path?: never;
746
+ cookie?: never;
747
+ };
748
+ get: {
749
+ parameters: {
750
+ query?: never;
751
+ header?: never;
752
+ path: {
753
+ /** @description Account for which to retrieve PnL history */
754
+ account_id: number;
755
+ };
756
+ cookie?: never;
757
+ };
758
+ requestBody?: never;
759
+ responses: {
760
+ 200: {
761
+ headers: {
762
+ [name: string]: unknown;
763
+ };
764
+ content: {
765
+ "application/json": components["schemas"]["AccountPnlHistInfo"][];
729
766
  };
730
767
  };
731
768
  };
@@ -2656,24 +2693,62 @@ export interface components {
2656
2693
  */
2657
2694
  pageSize: number | null;
2658
2695
  };
2659
- PageResult_for_uint64_and_AccountPnl: {
2696
+ PageResult_for_uint64_and_AccountPnlInfo: {
2660
2697
  /** @description Set of items for requested by query. */
2661
- items: components["schemas"]["AccountPnl"][];
2698
+ items: components["schemas"]["AccountPnlInfo"][];
2662
2699
  /**
2663
2700
  * Format: uint64
2664
2701
  * @description If request contains more data, this is the id is set with which next request should be performed to get next page. If no more data, then it is undefined.
2665
2702
  */
2666
2703
  nextStartInclusive?: number | null;
2667
2704
  };
2668
- AccountPnl: {
2705
+ AccountPnlInfo: {
2669
2706
  time: string;
2670
2707
  /** Format: uint64 */
2671
2708
  actionId: number;
2672
2709
  /** Format: uint32 */
2673
2710
  accountId: number;
2674
2711
  /** Format: double */
2712
+ pricePnlDelta: number;
2713
+ /** Format: double */
2714
+ fundingPnlDelta: number;
2715
+ /**
2716
+ * Format: double
2717
+ * @description Total PnL update
2718
+ */
2675
2719
  pnl: number;
2676
2720
  };
2721
+ AccountPnlHistInfo: {
2722
+ /** @description Same time when funding is applied */
2723
+ time: string;
2724
+ /** Format: double */
2725
+ fundingPnl: number;
2726
+ /**
2727
+ * Format: double
2728
+ * @description in USDC, PnL from position price and price and trade price difference
2729
+ */
2730
+ tradedPnl: number;
2731
+ /**
2732
+ * Format: double
2733
+ * @description Funding rate used to calculate this funding payment
2734
+ */
2735
+ fundingRate: number;
2736
+ /**
2737
+ * Format: double
2738
+ * @description Size used to calculated funding payment
2739
+ */
2740
+ fundingSize: number;
2741
+ /** @description Side on time of funding application. */
2742
+ side?: components["schemas"]["Side"] | null;
2743
+ /** Format: double */
2744
+ positionSizeTraded: number;
2745
+ market: components["schemas"]["MarketIdInfo"];
2746
+ };
2747
+ MarketIdInfo: {
2748
+ /** Format: uint32 */
2749
+ market_id: number;
2750
+ market_symbol: string;
2751
+ };
2677
2752
  PageResult_for_uint64_and_Trigger: {
2678
2753
  /** @description Set of items for requested by query. */
2679
2754
  items: components["schemas"]["Trigger"][];
package/dist/types.d.ts CHANGED
@@ -60,8 +60,8 @@ export type FillModeFromApi = components["schemas"]["FillMode"];
60
60
  export type PlacementOrigin = components["schemas"]["PlacementOrigin"];
61
61
  export type FinalizationReason = components["schemas"]["FinalizationReason"];
62
62
  export type PagedQuery = components["schemas"]["PagedQuery"];
63
- export type AccountPnl = components["schemas"]["AccountPnl"];
64
- export type AccountPnlPage = components["schemas"]["PageResult_for_uint64_and_AccountPnl"];
63
+ export type AccountPnlInfo = components["schemas"]["AccountPnlInfo"];
64
+ export type AccountPnlInfoPage = components["schemas"]["PageResult_for_uint64_and_AccountPnlInfo"];
65
65
  export type AccountTriggerInfo = components["schemas"]["AccountTriggerInfo"];
66
66
  export type TriggerHistoryPage = components["schemas"]["PageResult_for_uint64_and_Trigger"];
67
67
  export type WithdrawalHistoryPage = components["schemas"]["PageResult_for_uint64_and_Withdrawal"];
@@ -217,16 +217,27 @@ export interface WebSocketDeltaUpdate {
217
217
  bids: OrderbookEntry[];
218
218
  timestamp: number;
219
219
  }
220
- /**
221
- * WebSocket user update message
222
- */
223
220
  export interface WebSocketAccountUpdate {
224
- e: WebSocketMessageType.AccountUpdate;
225
- accountId: number;
226
- account: Account;
227
- timestamp: number;
221
+ last_update_id: number;
222
+ update_id: number;
223
+ account_id: number;
224
+ fills: Record<string, unknown>;
225
+ places: Record<string, unknown>;
226
+ cancels: Record<string, {
227
+ side: "bid" | "ask";
228
+ current_size: number;
229
+ price: number;
230
+ market_id: number;
231
+ }>;
232
+ balances: Record<string, unknown>;
228
233
  }
229
- export type WebSocketMessage = WebSocketTradeUpdate | WebSocketDeltaUpdate | WebSocketAccountUpdate;
234
+ export type WebSocketMessage = {
235
+ trades: WebSocketTradeUpdate;
236
+ } | {
237
+ delta: WebSocketDeltaUpdate;
238
+ } | {
239
+ account: WebSocketAccountUpdate;
240
+ };
230
241
  export interface SPLTokenInfo {
231
242
  mint: string;
232
243
  precision: number;
@@ -212,15 +212,15 @@ export class NordWebSocketClient extends EventEmitter {
212
212
  }
213
213
  const hasOwn = (k) => Object.prototype.hasOwnProperty.call(message, k);
214
214
  if (hasOwn("trades")) {
215
- this.emit("trades", message);
215
+ this.emit("trades", message.trades);
216
216
  return;
217
217
  }
218
218
  if (hasOwn("delta")) {
219
- this.emit("delta", message);
219
+ this.emit("delta", message.delta);
220
220
  return;
221
221
  }
222
222
  if (hasOwn("account")) {
223
- this.emit("account", message);
223
+ this.emit("account", message.account);
224
224
  return;
225
225
  }
226
226
  this.emit("error", new Error(`Unexpected message type: ${message}`));
@@ -1,5 +1,5 @@
1
1
  import { EventEmitter } from "events";
2
- import { Account, DeltaEvent, OrderbookResponse, SubscriberConfig, StreamTrade, Trades } from "../types";
2
+ import { Account, DeltaEvent, WebSocketDeltaUpdate, SubscriberConfig, StreamTrade, Trades } from "../types";
3
3
  /**
4
4
  * Subscriber class for handling WebSocket subscriptions
5
5
  */
@@ -21,7 +21,7 @@ export declare class Subscriber {
21
21
  * Interface for orderbook subscription
22
22
  */
23
23
  export interface OrderbookSubscription extends EventEmitter {
24
- on(event: "message", listener: (data: OrderbookResponse) => void): this;
24
+ on(event: "message", listener: (data: WebSocketDeltaUpdate) => void): this;
25
25
  on(event: "error", listener: (error: Error) => void): this;
26
26
  close(): void;
27
27
  removeAllListeners(event?: string): this;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@n1xyz/nord-ts",
3
- "version": "0.1.12",
3
+ "version": "0.2.0",
4
4
  "description": "Typescript for Nord",
5
5
  "keywords": [],
6
6
  "author": "",
@@ -44,7 +44,7 @@
44
44
  },
45
45
  "dependencies": {
46
46
  "@bufbuild/protobuf": "^2.6.3",
47
- "@n1xyz/proton": "0.0.7",
47
+ "@n1xyz/proton": "0.1.0",
48
48
  "@noble/curves": "^1.9.6",
49
49
  "@noble/ed25519": "^2.3.0",
50
50
  "@noble/hashes": "^1.8.0",