@n1xyz/nord-ts 0.1.3 → 0.1.5

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.
@@ -21,39 +21,30 @@ import {
21
21
  SPLTokenInfo,
22
22
  QuoteSize,
23
23
  TriggerKind,
24
+ fillModeToProtoFillMode,
24
25
  } from "../../types";
25
26
  import * as proto from "../../gen/nord_pb";
26
27
  import {
27
28
  BigIntValue,
28
29
  checkedFetch,
30
+ assert,
29
31
  findMarket,
30
32
  findToken,
31
33
  optExpect,
32
34
  keypairFromPrivateKey,
35
+ toScaledU64,
33
36
  } from "../../utils";
37
+ import { create } from "@bufbuild/protobuf";
34
38
  import {
35
- cancelOrder,
36
39
  createSession,
37
- placeOrder,
38
40
  revokeSession,
39
- transfer,
40
- withdraw,
41
- atomic as atomicAction,
42
- AtomicSubaction as ApiAtomicSubaction,
43
- addTrigger as addTriggerAction,
44
- removeTrigger as removeTriggerAction,
41
+ atomic,
42
+ expectReceiptKind,
43
+ AtomicSubaction,
45
44
  } from "../api/actions";
46
- import type {
47
- AccountTriggerInfo,
48
- TriggerHistoryPage,
49
- HistoryTriggerQuery,
50
- } from "../api/triggers";
51
- import {
52
- getAccountTriggers as fetchAccountTriggers,
53
- getAccountTriggerHistory as fetchAccountTriggerHistory,
54
- } from "../api/triggers";
55
45
  import { NordError } from "../utils/NordError";
56
46
  import { Nord } from "./Nord";
47
+ import { NordClient } from "./NordClient";
57
48
 
58
49
  /**
59
50
  * Parameters for creating a NordUser instance
@@ -114,6 +105,8 @@ export interface PlaceOrderParams {
114
105
 
115
106
  /** Account ID to place the order from */
116
107
  accountId?: number;
108
+
109
+ clientOrderId?: BigIntValue;
117
110
  }
118
111
 
119
112
  export interface AddTriggerParams {
@@ -190,26 +183,7 @@ export interface UserAtomicSubaction {
190
183
  /**
191
184
  * User class for interacting with the Nord protocol
192
185
  */
193
- export class NordUser {
194
- /** Nord client instance */
195
- public readonly nord: Nord;
196
-
197
- /** User's blockchain address */
198
- public readonly address: PublicKey;
199
-
200
- /** Function to sign messages with the user's wallet */
201
- public readonly walletSignFn: (
202
- message: Uint8Array | string,
203
- ) => Promise<Uint8Array>;
204
-
205
- /** Function to sign messages with the user's session key */
206
- public readonly sessionSignFn: (message: Uint8Array) => Promise<Uint8Array>;
207
-
208
- /** Function to sign transactions with the user's wallet */
209
- public readonly transactionSignFn: <T extends Transaction>(
210
- tx: T,
211
- ) => Promise<T>;
212
-
186
+ export class NordUser extends NordClient {
213
187
  /** User balances by token symbol */
214
188
  public balances: {
215
189
  [key: string]: { accountId: number; balance: number; symbol: string }[];
@@ -249,24 +223,6 @@ export class NordUser {
249
223
  /** User's account IDs */
250
224
  public accountIds?: number[];
251
225
 
252
- /** Current session ID */
253
- public sessionId?: bigint;
254
-
255
- /** User's public key */
256
- public publicKey: PublicKey;
257
-
258
- /** Session public key */
259
- public sessionPubKey: Uint8Array;
260
-
261
- /** Last timestamp used */
262
- public lastTs = 0;
263
-
264
- /** Last nonce used */
265
- public lastNonce = 0;
266
-
267
- /** Solana connection */
268
- public connection: Connection;
269
-
270
226
  /** SPL token information */
271
227
  public splTokenInfos: SPLTokenInfo[] = [];
272
228
 
@@ -297,28 +253,24 @@ export class NordUser {
297
253
  throw new NordError("Session public key is required");
298
254
  }
299
255
 
256
+ let parsedAddress: PublicKey;
300
257
  try {
301
- this.address = new PublicKey(address);
258
+ parsedAddress = new PublicKey(address);
302
259
  } catch (error) {
303
260
  throw new NordError("Invalid Solana address", { cause: error });
304
261
  }
305
262
 
306
- this.nord = nord;
307
- this.walletSignFn = walletSignFn;
308
- this.sessionSignFn = sessionSignFn;
309
- this.transactionSignFn = transactionSignFn;
310
- this.sessionPubKey = sessionPubKey;
311
- this.publicKey = publicKey;
312
- this.connection =
313
- connection ||
314
- new Connection(nord.solanaUrl, {
315
- commitment: "confirmed",
316
- });
317
-
318
- // Set sessionId if provided
319
- if (sessionId !== undefined) {
320
- this.sessionId = sessionId;
321
- }
263
+ super({
264
+ nord,
265
+ address: parsedAddress,
266
+ walletSignFn,
267
+ sessionSignFn,
268
+ transactionSignFn,
269
+ connection,
270
+ sessionId,
271
+ sessionPubKey,
272
+ publicKey,
273
+ });
322
274
 
323
275
  // Convert tokens from info endpoint to SPLTokenInfo
324
276
  if (this.nord.tokens && this.nord.tokens.length > 0) {
@@ -344,8 +296,9 @@ export class NordUser {
344
296
  sessionSignFn: this.sessionSignFn,
345
297
  transactionSignFn: this.transactionSignFn,
346
298
  connection: this.connection,
347
- sessionPubKey: this.sessionPubKey,
299
+ sessionPubKey: new Uint8Array(this.sessionPubKey),
348
300
  publicKey: this.publicKey,
301
+ sessionId: this.sessionId,
349
302
  });
350
303
 
351
304
  // Copy other properties
@@ -353,11 +306,8 @@ export class NordUser {
353
306
  cloned.positions = { ...this.positions };
354
307
  cloned.margins = { ...this.margins };
355
308
  cloned.accountIds = this.accountIds ? [...this.accountIds] : undefined;
356
- cloned.sessionId = this.sessionId;
357
- cloned.publicKey = this.publicKey;
358
- cloned.lastTs = this.lastTs;
359
- cloned.lastNonce = this.lastNonce;
360
309
  cloned.splTokenInfos = [...this.splTokenInfos];
310
+ this.cloneClientState(cloned);
361
311
 
362
312
  return cloned;
363
313
  }
@@ -486,7 +436,7 @@ export class NordUser {
486
436
  }
487
437
 
488
438
  /**
489
- * Deposit SPL tokens to the bridge
439
+ * Deposit SPL tokens to the app
490
440
  *
491
441
  * @param amount - Amount to deposit
492
442
  * @param tokenId - Token ID
@@ -504,7 +454,7 @@ export class NordUser {
504
454
  }
505
455
 
506
456
  /**
507
- * Deposit SPL tokens to the bridge
457
+ * Deposit SPL tokens to the app
508
458
  *
509
459
  * @param amount - Amount to deposit
510
460
  * @param tokenId - Token ID
@@ -573,7 +523,19 @@ export class NordUser {
573
523
  * @returns Nonce as number
574
524
  */
575
525
  getNonce(): number {
576
- return ++this.lastNonce;
526
+ return this.nextActionNonce();
527
+ }
528
+
529
+ private async submitSessionAction(
530
+ kind: proto.Action["kind"],
531
+ ): Promise<proto.Receipt> {
532
+ return this.submitSignedAction(kind, async (message) => {
533
+ const signature = await this.sessionSignFn(message);
534
+ const signed = new Uint8Array(message.length + signature.length);
535
+ signed.set(message);
536
+ signed.set(signature, message.length);
537
+ return signed;
538
+ });
577
539
  }
578
540
 
579
541
  /**
@@ -763,19 +725,21 @@ export class NordUser {
763
725
  }>): Promise<{ actionId: bigint }> {
764
726
  try {
765
727
  this.checkSessionValidity();
766
- const { actionId } = await withdraw(
767
- this.nord.webServerUrl,
768
- this.sessionSignFn,
769
- await this.nord.getTimestamp(),
770
- this.getNonce(),
771
- {
772
- sizeDecimals: findToken(this.nord.tokens, tokenId).decimals,
773
- sessionId: optExpect(this.sessionId, "No session"),
774
- tokenId: tokenId,
775
- amount,
776
- },
777
- );
778
- return { actionId };
728
+ const token = findToken(this.nord.tokens, tokenId);
729
+ const scaledAmount = toScaledU64(amount, token.decimals);
730
+ if (scaledAmount <= 0n) {
731
+ throw new NordError("Withdraw amount must be positive");
732
+ }
733
+ const receipt = await this.submitSessionAction({
734
+ case: "withdraw",
735
+ value: create(proto.Action_WithdrawSchema, {
736
+ sessionId: BigInt(optExpect(this.sessionId, "No session")),
737
+ tokenId,
738
+ amount: scaledAmount,
739
+ }),
740
+ });
741
+ expectReceiptKind(receipt, "withdrawResult", "withdraw");
742
+ return { actionId: receipt.actionId };
779
743
  } catch (error) {
780
744
  throw new NordError(
781
745
  `Failed to withdraw ${amount} of token ID ${tokenId}`,
@@ -802,27 +766,48 @@ export class NordUser {
802
766
  if (!market) {
803
767
  throw new NordError(`Market with ID ${params.marketId} not found`);
804
768
  }
769
+ const sessionId = optExpect(this.sessionId, "No session");
770
+ const price = toScaledU64(params.price ?? 0, market.priceDecimals);
771
+ const size = toScaledU64(params.size ?? 0, market.sizeDecimals);
772
+ const scaledQuote = params.quoteSize
773
+ ? params.quoteSize.toWire(market.priceDecimals, market.sizeDecimals)
774
+ : undefined;
775
+ assert(
776
+ price > 0n || size > 0n || scaledQuote !== undefined,
777
+ "OrderLimit must include at least one of: size, price, or quoteSize",
778
+ );
805
779
 
806
- const result = await placeOrder(
807
- this.nord.webServerUrl,
808
- this.sessionSignFn,
809
- await this.nord.getTimestamp(),
810
- this.getNonce(),
811
- {
812
- sessionId: optExpect(this.sessionId, "No session"),
813
- senderId: params.accountId,
814
- sizeDecimals: market.sizeDecimals,
815
- priceDecimals: market.priceDecimals,
780
+ const receipt = await this.submitSessionAction({
781
+ case: "placeOrder",
782
+ value: create(proto.Action_PlaceOrderSchema, {
783
+ sessionId: BigInt(sessionId),
784
+ senderAccountId: params.accountId,
816
785
  marketId: params.marketId,
817
- side: params.side,
818
- fillMode: params.fillMode,
786
+ side: params.side === Side.Bid ? proto.Side.BID : proto.Side.ASK,
787
+ fillMode: fillModeToProtoFillMode(params.fillMode),
819
788
  isReduceOnly: params.isReduceOnly,
820
- size: params.size,
821
- price: params.price,
822
- quoteSize: params.quoteSize,
823
- },
824
- );
825
- return result;
789
+ price,
790
+ size,
791
+ quoteSize:
792
+ scaledQuote === undefined
793
+ ? undefined
794
+ : create(proto.QuoteSizeSchema, {
795
+ size: scaledQuote.size,
796
+ price: scaledQuote.price,
797
+ }),
798
+ clientOrderId:
799
+ params.clientOrderId === undefined
800
+ ? undefined
801
+ : BigInt(params.clientOrderId),
802
+ }),
803
+ });
804
+ expectReceiptKind(receipt, "placeOrderResult", "place order");
805
+ const result = receipt.kind.value;
806
+ return {
807
+ actionId: receipt.actionId,
808
+ orderId: result.posted?.orderId,
809
+ fills: result.fills,
810
+ };
826
811
  } catch (error) {
827
812
  throw new NordError("Failed to place order", { cause: error });
828
813
  }
@@ -848,18 +833,20 @@ export class NordUser {
848
833
  providedAccountId != null ? providedAccountId : this.accountIds?.[0];
849
834
  try {
850
835
  this.checkSessionValidity();
851
- const result = await cancelOrder(
852
- this.nord.webServerUrl,
853
- this.sessionSignFn,
854
- await this.nord.getTimestamp(),
855
- this.getNonce(),
856
- {
857
- sessionId: optExpect(this.sessionId, "No session"),
858
- senderId: accountId,
859
- orderId,
860
- },
861
- );
862
- return result;
836
+ const receipt = await this.submitSessionAction({
837
+ case: "cancelOrderById",
838
+ value: create(proto.Action_CancelOrderByIdSchema, {
839
+ orderId: BigInt(orderId),
840
+ sessionId: BigInt(optExpect(this.sessionId, "No session")),
841
+ senderAccountId: accountId,
842
+ }),
843
+ });
844
+ expectReceiptKind(receipt, "cancelOrderResult", "cancel order");
845
+ return {
846
+ actionId: receipt.actionId,
847
+ orderId: receipt.kind.value.orderId,
848
+ accountId: receipt.kind.value.accountId,
849
+ };
863
850
  } catch (error) {
864
851
  throw new NordError(`Failed to cancel order ${orderId}`, {
865
852
  cause: error,
@@ -881,23 +868,41 @@ export class NordUser {
881
868
  if (!market) {
882
869
  throw new NordError(`Market with ID ${params.marketId} not found`);
883
870
  }
884
- const result = await addTriggerAction(
885
- this.nord.webServerUrl,
886
- this.sessionSignFn,
887
- await this.nord.getTimestamp(),
888
- this.getNonce(),
889
- {
890
- sessionId: optExpect(this.sessionId, "No session"),
871
+ const triggerPrice = toScaledU64(
872
+ params.triggerPrice,
873
+ market.priceDecimals,
874
+ );
875
+ assert(triggerPrice > 0n, "Trigger price must be positive");
876
+ const limitPrice =
877
+ params.limitPrice === undefined
878
+ ? undefined
879
+ : toScaledU64(params.limitPrice, market.priceDecimals);
880
+ if (limitPrice !== undefined) {
881
+ assert(limitPrice > 0n, "Limit price must be positive");
882
+ }
883
+ const key = create(proto.TriggerKeySchema, {
884
+ kind:
885
+ params.kind === TriggerKind.StopLoss
886
+ ? proto.TriggerKind.STOP_LOSS
887
+ : proto.TriggerKind.TAKE_PROFIT,
888
+ side: params.side === Side.Bid ? proto.Side.BID : proto.Side.ASK,
889
+ });
890
+ const prices = create(proto.Action_TriggerPricesSchema, {
891
+ triggerPrice,
892
+ limitPrice,
893
+ });
894
+ const receipt = await this.submitSessionAction({
895
+ case: "addTrigger",
896
+ value: create(proto.Action_AddTriggerSchema, {
897
+ sessionId: BigInt(optExpect(this.sessionId, "No session")),
891
898
  marketId: params.marketId,
892
- side: params.side,
893
- kind: params.kind,
894
- priceDecimals: market.priceDecimals,
895
- triggerPrice: params.triggerPrice,
896
- limitPrice: params.limitPrice,
899
+ key,
900
+ prices,
897
901
  accountId: params.accountId,
898
- },
899
- );
900
- return result;
902
+ }),
903
+ });
904
+ expectReceiptKind(receipt, "triggerAdded", "add trigger");
905
+ return { actionId: receipt.actionId };
901
906
  } catch (error) {
902
907
  throw new NordError("Failed to add trigger", { cause: error });
903
908
  }
@@ -919,80 +924,29 @@ export class NordUser {
919
924
  if (!market) {
920
925
  throw new NordError(`Market with ID ${params.marketId} not found`);
921
926
  }
922
- const result = await removeTriggerAction(
923
- this.nord.webServerUrl,
924
- this.sessionSignFn,
925
- await this.nord.getTimestamp(),
926
- this.getNonce(),
927
- {
928
- sessionId: optExpect(this.sessionId, "No session"),
927
+ const key = create(proto.TriggerKeySchema, {
928
+ kind:
929
+ params.kind === TriggerKind.StopLoss
930
+ ? proto.TriggerKind.STOP_LOSS
931
+ : proto.TriggerKind.TAKE_PROFIT,
932
+ side: params.side === Side.Bid ? proto.Side.BID : proto.Side.ASK,
933
+ });
934
+ const receipt = await this.submitSessionAction({
935
+ case: "removeTrigger",
936
+ value: create(proto.Action_RemoveTriggerSchema, {
937
+ sessionId: BigInt(optExpect(this.sessionId, "No session")),
929
938
  marketId: params.marketId,
930
- side: params.side,
931
- kind: params.kind,
939
+ key,
932
940
  accountId: params.accountId,
933
- },
934
- );
935
- return result;
941
+ }),
942
+ });
943
+ expectReceiptKind(receipt, "triggerRemoved", "remove trigger");
944
+ return { actionId: receipt.actionId };
936
945
  } catch (error) {
937
946
  throw new NordError("Failed to remove trigger", { cause: error });
938
947
  }
939
948
  }
940
949
 
941
- /**
942
- * Fetch active triggers for an account.
943
- *
944
- * @param params Optional parameters containing an explicit account id.
945
- * @throws {NordError} If no account can be resolved or the request fails.
946
- */
947
- async getAccountTriggers(params?: {
948
- accountId?: number;
949
- }): Promise<AccountTriggerInfo[]> {
950
- const accountId = params?.accountId ?? this.accountIds?.[0];
951
-
952
- if (accountId == null) {
953
- throw new NordError(
954
- "Account ID is undefined. Make sure to call updateAccountId() before requesting triggers.",
955
- );
956
- }
957
-
958
- try {
959
- return await fetchAccountTriggers(this.nord.webServerUrl, accountId);
960
- } catch (error) {
961
- throw new NordError("Failed to fetch account triggers", { cause: error });
962
- }
963
- }
964
-
965
- /**
966
- * Fetch trigger history for an account.
967
- *
968
- * @param params Optional parameters with account id and history query filters.
969
- * @throws {NordError} If no account can be resolved or the request fails.
970
- */
971
- async getAccountTriggerHistory(
972
- params: HistoryTriggerQuery & { accountId?: number },
973
- ): Promise<TriggerHistoryPage> {
974
- const { accountId: providedAccountId, ...query } = params;
975
- const accountId = providedAccountId ?? this.accountIds?.[0];
976
-
977
- if (accountId == null) {
978
- throw new NordError(
979
- "Account ID is undefined. Make sure to call updateAccountId() before requesting trigger history.",
980
- );
981
- }
982
-
983
- try {
984
- return await fetchAccountTriggerHistory(
985
- this.nord.webServerUrl,
986
- accountId,
987
- query,
988
- );
989
- } catch (error) {
990
- throw new NordError("Failed to fetch account trigger history", {
991
- cause: error,
992
- });
993
- }
994
- }
995
-
996
950
  /**
997
951
  * Transfer tokens to another account
998
952
  *
@@ -1004,20 +958,22 @@ export class NordUser {
1004
958
  this.checkSessionValidity();
1005
959
  const token = findToken(this.nord.tokens, params.tokenId);
1006
960
 
1007
- await transfer(
1008
- this.nord.webServerUrl,
1009
- this.sessionSignFn,
1010
- await this.nord.getTimestamp(),
1011
- this.getNonce(),
1012
- {
1013
- sessionId: optExpect(this.sessionId, "No session"),
961
+ const amount = toScaledU64(params.amount, token.decimals);
962
+ if (amount <= 0n) {
963
+ throw new NordError("Transfer amount must be positive");
964
+ }
965
+
966
+ const receipt = await this.submitSessionAction({
967
+ case: "transfer",
968
+ value: create(proto.Action_TransferSchema, {
969
+ sessionId: BigInt(optExpect(this.sessionId, "No session")),
1014
970
  fromAccountId: optExpect(params.fromAccountId, "No source account"),
1015
971
  toAccountId: optExpect(params.toAccountId, "No target account"),
1016
972
  tokenId: params.tokenId,
1017
- tokenDecimals: token.decimals,
1018
- amount: params.amount,
1019
- },
1020
- );
973
+ amount,
974
+ }),
975
+ });
976
+ expectReceiptKind(receipt, "transferred", "transfer tokens");
1021
977
  } catch (error) {
1022
978
  throw new NordError("Failed to transfer tokens", { cause: error });
1023
979
  }
@@ -1054,7 +1010,7 @@ export class NordUser {
1054
1010
  );
1055
1011
  }
1056
1012
 
1057
- const apiActions: ApiAtomicSubaction[] = userActions.map((act) => {
1013
+ const apiActions: AtomicSubaction[] = userActions.map((act) => {
1058
1014
  if (act.kind === "place") {
1059
1015
  const market = findMarket(this.nord.markets, act.marketId!);
1060
1016
  if (!market) {
@@ -1072,15 +1028,15 @@ export class NordUser {
1072
1028
  price: act.price,
1073
1029
  quoteSize: act.quoteSize,
1074
1030
  clientOrderId: act.clientOrderId,
1075
- } as ApiAtomicSubaction;
1031
+ } as AtomicSubaction;
1076
1032
  }
1077
1033
  return {
1078
1034
  kind: "cancel",
1079
1035
  orderId: act.orderId,
1080
- } as ApiAtomicSubaction;
1036
+ } as AtomicSubaction;
1081
1037
  });
1082
1038
 
1083
- const result = await atomicAction(
1039
+ const result = await atomic(
1084
1040
  this.nord.webServerUrl,
1085
1041
  this.sessionSignFn,
1086
1042
  await this.nord.getTimestamp(),
@@ -1252,13 +1208,4 @@ export class NordUser {
1252
1208
  });
1253
1209
  }
1254
1210
  }
1255
-
1256
- /**
1257
- * Get the Solana public key derived from the address
1258
- *
1259
- * @returns The Solana public key
1260
- */
1261
- getSolanaPublicKey(): PublicKey {
1262
- return this.address;
1263
- }
1264
1211
  }
package/src/nord/index.ts CHANGED
@@ -1,6 +1,17 @@
1
1
  // Export main client classes
2
2
  export { Nord } from "./client/Nord";
3
3
  export { NordUser } from "./client/NordUser";
4
+ export { NordAdmin } from "./client/NordAdmin";
5
+ export { NordClient } from "./client/NordClient";
6
+ export type { NordClientParams } from "./client/NordClient";
7
+ export type {
8
+ CreateTokenParams,
9
+ CreateMarketParams,
10
+ PythSetWormholeGuardiansParams,
11
+ PythSetSymbolFeedParams,
12
+ FreezeMarketParams,
13
+ UnfreezeMarketParams,
14
+ } from "./client/NordAdmin";
4
15
 
5
16
  // Export utility classes
6
17
  export { NordError } from "./utils/NordError";
package/src/types.ts CHANGED
@@ -38,8 +38,8 @@ export type SubscriptionPattern = `${SubscriptionType}@${string}` | string;
38
38
  export interface NordConfig {
39
39
  /** Base URL for the Nord web server */
40
40
  webServerUrl: string;
41
- /** Bridge verification key */
42
- bridgeVk: string;
41
+ /** App address */
42
+ app: string;
43
43
  /** Solana cluster URL */
44
44
  solanaUrl: string;
45
45
  /**
@@ -49,9 +49,9 @@ export interface NordConfig {
49
49
  initWebSockets?: boolean;
50
50
  }
51
51
 
52
- export type Info = components["schemas"]["Info2"];
53
- export type Market = Info["markets"][number];
54
- export type Token = Info["tokens"][number];
52
+ export type MarketsInfo = components["schemas"]["MarketsInfo"];
53
+ export type Market = MarketsInfo["markets"][number];
54
+ export type Token = MarketsInfo["tokens"][number];
55
55
  export type Account = components["schemas"]["Account"];
56
56
  export type TradesResponse =
57
57
  components["schemas"]["PageResult_for_String_and_Trade"];
@@ -92,6 +92,16 @@ export type AccountPnlQuery = components["schemas"]["AccountPnlQuery"];
92
92
  export type AccountPnl = components["schemas"]["AccountPnl"];
93
93
  export type AccountPnlPage =
94
94
  components["schemas"]["PageResult_for_uint64_and_AccountPnl"];
95
+ export type AccountTriggerInfo = components["schemas"]["AccountTriggerInfo"];
96
+ export type TriggerHistoryPage =
97
+ components["schemas"]["PageResult_for_uint64_and_HistoryTriggerInfo"];
98
+ export type HistoryTriggerQuery = components["schemas"]["AccountTriggersQuery"];
99
+ export type FeeTierConfig = components["schemas"]["FeeTierConfig"];
100
+ export type FeeTierId = components["schemas"]["FeeTierId"];
101
+ export type TokenStats = components["schemas"]["TokenStats"];
102
+ export type AccountFeeTier = components["schemas"]["AccountFeeTier"];
103
+ export type AccountFeeTierPage =
104
+ components["schemas"]["PageResult_for_uint32_and_AccountFeeTier"];
95
105
 
96
106
  /**
97
107
  * Configuration options for the Nord client
package/src/utils.ts CHANGED
@@ -233,6 +233,11 @@ export function checkPubKeyLength(keyType: KeyType, len: number): void {
233
233
  }
234
234
  }
235
235
 
236
+ export function decodeHex(value: string): Uint8Array {
237
+ const hex = value.startsWith("0x") ? value.slice(2) : value;
238
+ return Uint8Array.from(Buffer.from(hex, "hex"));
239
+ }
240
+
236
241
  export function findMarket(markets: Market[], marketId: number): Market {
237
242
  if (marketId < 0 || markets.length - 1 < marketId) {
238
243
  throw new Error(`The market with marketId=${marketId} not found`);