@n1xyz/nord-ts 0.0.15 → 0.0.17

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 (195) hide show
  1. package/dist/bridge/client.js +45 -6
  2. package/dist/gen/common.js +1 -1
  3. package/dist/gen/nord.d.ts +61 -29
  4. package/dist/gen/nord.js +723 -130
  5. package/dist/idl/bridge.d.ts +569 -2
  6. package/dist/idl/bridge.js +5 -927
  7. package/dist/idl/bridge.json +75 -62
  8. package/dist/idl/index.d.ts +71 -49
  9. package/dist/index.d.ts +1 -3
  10. package/dist/index.js +6 -13
  11. package/dist/nord/api/actions.d.ts +7 -2
  12. package/dist/nord/api/actions.js +7 -1
  13. package/dist/nord/api/core.d.ts +1 -1
  14. package/dist/nord/api/core.js +3 -3
  15. package/dist/nord/api/market.js +1 -3
  16. package/dist/nord/api/queries.js +2 -2
  17. package/dist/nord/client/Nord.d.ts +9 -14
  18. package/dist/nord/client/Nord.js +27 -38
  19. package/dist/nord/client/NordUser.d.ts +7 -23
  20. package/dist/nord/client/NordUser.js +79 -151
  21. package/dist/nord/utils/NordError.js +5 -2
  22. package/dist/types.d.ts +34 -50
  23. package/dist/utils.d.ts +2 -0
  24. package/dist/utils.js +14 -0
  25. package/dist/websocket/NordWebSocketClient.js +0 -2
  26. package/package.json +20 -18
  27. package/protoc-generate.sh +0 -0
  28. package/src/idl/bridge.json +75 -62
  29. package/src/index.ts +9 -12
  30. package/src/nord/api/actions.ts +14 -3
  31. package/src/nord/api/core.ts +4 -2
  32. package/src/nord/api/market.ts +1 -4
  33. package/src/nord/api/queries.ts +2 -2
  34. package/src/nord/client/Nord.ts +45 -50
  35. package/src/nord/client/NordUser.ts +107 -178
  36. package/src/nord/utils/NordError.ts +6 -2
  37. package/src/types.ts +34 -49
  38. package/src/utils.ts +18 -0
  39. package/src/websocket/NordWebSocketClient.ts +0 -2
  40. package/tsconfig.json +1 -1
  41. package/docs/.nojekyll +0 -1
  42. package/docs/assets/hierarchy.js +0 -1
  43. package/docs/assets/highlight.css +0 -92
  44. package/docs/assets/icons.js +0 -18
  45. package/docs/assets/icons.svg +0 -1
  46. package/docs/assets/main.js +0 -60
  47. package/docs/assets/navigation.js +0 -1
  48. package/docs/assets/search.js +0 -1
  49. package/docs/assets/style.css +0 -1611
  50. package/docs/classes/Nord.html +0 -189
  51. package/docs/classes/NordError.html +0 -24
  52. package/docs/classes/NordUser.html +0 -115
  53. package/docs/classes/NordWebSocketClient.html +0 -330
  54. package/docs/classes/SolanaBridgeClient.html +0 -86
  55. package/docs/classes/Subscriber.html +0 -10
  56. package/docs/enums/FillMode.html +0 -5
  57. package/docs/enums/KeyType.html +0 -4
  58. package/docs/enums/MetricPeriod.html +0 -9
  59. package/docs/enums/PdaSeedType.html +0 -9
  60. package/docs/enums/PeakTpsPeriodUnit.html +0 -15
  61. package/docs/enums/Side.html +0 -3
  62. package/docs/enums/WebSocketMessageType.html +0 -7
  63. package/docs/functions/actionQueryRollman.html +0 -6
  64. package/docs/functions/actionsQueryRollman.html +0 -6
  65. package/docs/functions/aggregateMetrics-1.html +0 -7
  66. package/docs/functions/assert.html +0 -1
  67. package/docs/functions/bigIntToProtoU128.html +0 -4
  68. package/docs/functions/bridgeToBN.html +0 -5
  69. package/docs/functions/bufferToHex.html +0 -4
  70. package/docs/functions/cancelOrder.html +0 -1
  71. package/docs/functions/checkPubKeyLength.html +0 -1
  72. package/docs/functions/checkedFetch.html +0 -6
  73. package/docs/functions/createSession.html +0 -1
  74. package/docs/functions/decodeLengthDelimited.html +0 -11
  75. package/docs/functions/encodeLengthDelimited.html +0 -6
  76. package/docs/functions/fillModeToProtoFillMode.html +0 -5
  77. package/docs/functions/findMarket.html +0 -1
  78. package/docs/functions/findPda.html +0 -6
  79. package/docs/functions/findToken.html +0 -1
  80. package/docs/functions/fromBN.html +0 -5
  81. package/docs/functions/getAccount.html +0 -6
  82. package/docs/functions/getActionNonce.html +0 -5
  83. package/docs/functions/getCurrentTps.html +0 -6
  84. package/docs/functions/getInfo.html +0 -5
  85. package/docs/functions/getLastActionId.html +0 -5
  86. package/docs/functions/getMedianLatency.html +0 -6
  87. package/docs/functions/getOrderbook.html +0 -6
  88. package/docs/functions/getPeakTps.html +0 -6
  89. package/docs/functions/getTimestamp.html +0 -5
  90. package/docs/functions/getTotalTransactions.html +0 -5
  91. package/docs/functions/getTrades.html +0 -6
  92. package/docs/functions/getUserAccountIds.html +0 -6
  93. package/docs/functions/hexToBuffer.html +0 -4
  94. package/docs/functions/initWebSocketClient.html +0 -12
  95. package/docs/functions/keypairFromPrivateKey.html +0 -4
  96. package/docs/functions/makeSigningFunction.html +0 -4
  97. package/docs/functions/makeWalletSignFn.html +0 -6
  98. package/docs/functions/marketsStats.html +0 -5
  99. package/docs/functions/optExpect.html +0 -5
  100. package/docs/functions/optMap.html +0 -5
  101. package/docs/functions/optUnwrap.html +0 -2
  102. package/docs/functions/panic.html +0 -1
  103. package/docs/functions/placeOrder.html +0 -1
  104. package/docs/functions/queryAction.html +0 -6
  105. package/docs/functions/queryPrometheus.html +0 -6
  106. package/docs/functions/queryRecentActions.html +0 -7
  107. package/docs/functions/revokeSession.html +0 -1
  108. package/docs/functions/shortenPublicKey.html +0 -5
  109. package/docs/functions/signAction.html +0 -6
  110. package/docs/functions/toBN.html +0 -5
  111. package/docs/functions/toScaledU128.html +0 -8
  112. package/docs/functions/toScaledU64.html +0 -8
  113. package/docs/functions/transfer.html +0 -1
  114. package/docs/functions/withdraw.html +0 -1
  115. package/docs/hierarchy.html +0 -1
  116. package/docs/index.html +0 -40
  117. package/docs/interfaces/Account.html +0 -8
  118. package/docs/interfaces/ActionInfo.html +0 -8
  119. package/docs/interfaces/ActionNonceResponse.html +0 -3
  120. package/docs/interfaces/ActionQuery.html +0 -4
  121. package/docs/interfaces/ActionResponse.html +0 -8
  122. package/docs/interfaces/ActionsExtendedInfo.html +0 -10
  123. package/docs/interfaces/ActionsQuery.html +0 -5
  124. package/docs/interfaces/ActionsResponse.html +0 -6
  125. package/docs/interfaces/AggregateMetrics.html +0 -12
  126. package/docs/interfaces/BlockFacts.html +0 -10
  127. package/docs/interfaces/BlockQuery.html +0 -6
  128. package/docs/interfaces/BlockResponse.html +0 -6
  129. package/docs/interfaces/BlockSummary.html +0 -8
  130. package/docs/interfaces/BlockSummaryResponse.html +0 -6
  131. package/docs/interfaces/DeltaEvent.html +0 -6
  132. package/docs/interfaces/DepositSplParams.html +0 -10
  133. package/docs/interfaces/Info.html +0 -3
  134. package/docs/interfaces/Market.html +0 -8
  135. package/docs/interfaces/MarketStats.html +0 -7
  136. package/docs/interfaces/MarketsStatsResponse.html +0 -2
  137. package/docs/interfaces/NordConfig.html +0 -24
  138. package/docs/interfaces/NordWebSocketClientEvents.html +0 -4
  139. package/docs/interfaces/NordWebSocketEvents.html +0 -8
  140. package/docs/interfaces/Order.html +0 -6
  141. package/docs/interfaces/OrderInfo.html +0 -6
  142. package/docs/interfaces/OrderbookEntry.html +0 -4
  143. package/docs/interfaces/OrderbookQuery.html +0 -6
  144. package/docs/interfaces/OrderbookResponse.html +0 -6
  145. package/docs/interfaces/OrderbookSubscription.html +0 -159
  146. package/docs/interfaces/PerpMarketStats.html +0 -5
  147. package/docs/interfaces/RollmanActionExtendedInfo.html +0 -4
  148. package/docs/interfaces/RollmanActionInfo.html +0 -4
  149. package/docs/interfaces/RollmanActionResponse.html +0 -4
  150. package/docs/interfaces/RollmanActionsResponse.html +0 -2
  151. package/docs/interfaces/RollmanBlockResponse.html +0 -3
  152. package/docs/interfaces/SPLTokenInfo.html +0 -10
  153. package/docs/interfaces/SolanaBridgeConfig.html +0 -10
  154. package/docs/interfaces/StateFacts.html +0 -10
  155. package/docs/interfaces/SubscriberConfig.html +0 -3
  156. package/docs/interfaces/TimestampResponse.html +0 -3
  157. package/docs/interfaces/Token.html +0 -5
  158. package/docs/interfaces/TokenInfo.html +0 -6
  159. package/docs/interfaces/Trade.html +0 -5
  160. package/docs/interfaces/TradeSubscription.html +0 -159
  161. package/docs/interfaces/Trades.html +0 -5
  162. package/docs/interfaces/TradesQuery.html +0 -6
  163. package/docs/interfaces/TradesResponse.html +0 -7
  164. package/docs/interfaces/TransferParams.html +0 -8
  165. package/docs/interfaces/UserAccountIdsQuery.html +0 -3
  166. package/docs/interfaces/UserAccountIdsResponse.html +0 -3
  167. package/docs/interfaces/WebSocketAccountUpdate.html +0 -6
  168. package/docs/interfaces/WebSocketDeltaUpdate.html +0 -9
  169. package/docs/interfaces/WebSocketSubscription.html +0 -4
  170. package/docs/interfaces/WebSocketTradeUpdate.html +0 -6
  171. package/docs/interfaces/WithdrawalClaim.html +0 -14
  172. package/docs/interfaces/WithdrawalParams.html +0 -8
  173. package/docs/modules.html +0 -1
  174. package/docs/types/BigIntValue.html +0 -2
  175. package/docs/types/SubscriptionPattern.html +0 -4
  176. package/docs/types/SubscriptionType.html +0 -2
  177. package/docs/types/WebSocketMessage.html +0 -1
  178. package/docs/variables/DEBUG_KEYS.html +0 -1
  179. package/docs/variables/DEFAULT_FUNDING_AMOUNTS.html +0 -1
  180. package/docs/variables/DEV_TOKEN_INFOS.html +0 -1
  181. package/docs/variables/DEV_URL.html +0 -1
  182. package/docs/variables/MAX_BUFFER_LEN.html +0 -1
  183. package/docs/variables/SESSION_TTL.html +0 -1
  184. package/docs/variables/WEBSERVER_DEV_URL.html +0 -1
  185. package/docs/variables/ZERO_DECIMAL.html +0 -1
  186. package/docs/variables/_private.html +0 -2
  187. package/idl-generate.sh +0 -4
  188. package/src/bridge/client.ts +0 -498
  189. package/src/bridge/const.ts +0 -53
  190. package/src/bridge/index.ts +0 -6
  191. package/src/bridge/types.ts +0 -129
  192. package/src/bridge/utils.ts +0 -140
  193. package/src/gen/common.ts +0 -297
  194. package/src/gen/nord.ts +0 -6723
  195. package/src/idl/index.ts +0 -2
@@ -1,5 +1,4 @@
1
1
  import { EventEmitter } from "events";
2
- import { Connection, PublicKey } from "@solana/web3.js";
3
2
  import {
4
3
  Account,
5
4
  ActionQuery,
@@ -22,6 +21,7 @@ import {
22
21
  UserAccountIdsQuery,
23
22
  UserAccountIdsResponse,
24
23
  } from "../../types";
24
+ import { ProtonClient } from "@n1xyz/proton";
25
25
  import { NordWebSocketClient } from "../../websocket/index";
26
26
  import * as core from "../api/core";
27
27
  import * as market from "../api/market";
@@ -29,6 +29,7 @@ import * as metrics from "../api/metrics";
29
29
  import * as queries from "../api/queries";
30
30
  import { OrderbookSubscription, TradeSubscription } from "../models/Subscriber";
31
31
  import { NordError } from "../utils/NordError";
32
+ import { PublicKey, Connection } from "@solana/web3.js";
32
33
 
33
34
  /**
34
35
  * User subscription interface
@@ -57,10 +58,7 @@ export class Nord {
57
58
  public readonly webServerUrl: string;
58
59
 
59
60
  /** Bridge verification key */
60
- public readonly bridgeVk: string;
61
-
62
- /** Optional Solana program ID (will be derived from bridgeVk) */
63
- private _solanaProgramId!: string;
61
+ public readonly bridgeVk: PublicKey;
64
62
 
65
63
  /** Solana RPC URL */
66
64
  public readonly solanaUrl: string;
@@ -74,6 +72,9 @@ export class Nord {
74
72
  /** Map of symbol to market_id */
75
73
  private symbolToMarketId: Map<string, number> = new Map();
76
74
 
75
+ /** Proton client for bridge and indexd operations */
76
+ public protonClient: ProtonClient;
77
+
77
78
  /**
78
79
  * Create a new Nord client
79
80
  *
@@ -83,22 +84,21 @@ export class Nord {
83
84
  * @param config.solanaUrl - Solana cluster URL
84
85
  * @throws {Error} If required configuration is missing
85
86
  */
86
- constructor(config: NordConfig) {
87
- if (!config.webServerUrl) {
88
- throw new NordError("webServerUrl is required");
89
- }
90
-
91
- if (!config.bridgeVk) {
92
- throw new NordError("bridgeVk is required");
93
- }
94
-
95
- if (!config.solanaUrl) {
96
- throw new NordError("solanaUrl is required");
97
- }
98
-
99
- this.webServerUrl = config.webServerUrl;
100
- this.bridgeVk = config.bridgeVk;
101
- this.solanaUrl = config.solanaUrl;
87
+ private constructor({
88
+ bridgeVk,
89
+ solanaUrl,
90
+ webServerUrl,
91
+ protonClient,
92
+ }: Readonly<{
93
+ bridgeVk: PublicKey;
94
+ solanaUrl: string;
95
+ webServerUrl: string;
96
+ protonClient: ProtonClient;
97
+ }>) {
98
+ this.webServerUrl = webServerUrl;
99
+ this.bridgeVk = bridgeVk;
100
+ this.solanaUrl = solanaUrl;
101
+ this.protonClient = protonClient;
102
102
  }
103
103
 
104
104
  /**
@@ -173,13 +173,13 @@ export class Nord {
173
173
  }
174
174
 
175
175
  /**
176
- * Get the next action nonce from the Nord server
176
+ * Get the last event nonce from the Nord server
177
177
  *
178
178
  * @returns Next action nonce
179
179
  * @throws {NordError} If the request fails
180
180
  */
181
181
  async getActionNonce(): Promise<number> {
182
- return core.getActionNonce(this.webServerUrl);
182
+ return core.getLastEventNonce(this.webServerUrl);
183
183
  }
184
184
 
185
185
  /**
@@ -213,44 +213,39 @@ export class Nord {
213
213
  * @returns Initialized Nord client
214
214
  * @throws {NordError} If initialization fails
215
215
  */
216
- public static async initNord(nordConfig: NordConfig): Promise<Nord> {
217
- const nord = new Nord(nordConfig);
216
+ public static async initNord({
217
+ bridgeVk: bridgeVk_,
218
+ solanaUrl,
219
+ webServerUrl,
220
+ }: Readonly<NordConfig>): Promise<Nord> {
221
+ // TODO: we should parametrize the connectionn not have it done here.
222
+ // this is a dogshit api, only here to be compatible with the shitty
223
+ // vibecoded code and not break zero one team's workflow.
224
+ const connection = new Connection(solanaUrl, { commitment: "confirmed" });
225
+ const bridgeVk = new PublicKey(bridgeVk_);
226
+ const protonClient = await ProtonClient.init({
227
+ protonUrl: webServerUrl,
228
+ bridgeVk,
229
+ solConn: connection,
230
+ });
231
+ const nord = new Nord({
232
+ bridgeVk,
233
+ protonClient,
234
+ solanaUrl,
235
+ webServerUrl,
236
+ });
218
237
  await nord.init();
219
238
  return nord;
220
239
  }
221
240
 
222
241
  /**
223
- * Initialize the Nord client by deriving program ID and fetching info
242
+ * Initialize the Nord client
224
243
  * @private
225
244
  */
226
245
  private async init(): Promise<void> {
227
- const connection = new Connection(this.solanaUrl);
228
- const bridgeVkPubkey = new PublicKey(this.bridgeVk);
229
-
230
- const bridgeAccount = await connection.getAccountInfo(bridgeVkPubkey);
231
- if (!bridgeAccount) {
232
- throw new NordError(`Bridge account ${this.bridgeVk} not found`);
233
- }
234
-
235
- this._solanaProgramId = bridgeAccount.owner.toString();
236
246
  await this.fetchNordInfo();
237
247
  }
238
248
 
239
- /**
240
- * Get the Solana program ID derived from bridge VK
241
- *
242
- * @returns Program ID string
243
- * @throws {NordError} If program ID hasn't been initialized
244
- */
245
- public getSolanaProgramId(): string {
246
- if (!this._solanaProgramId) {
247
- throw new NordError(
248
- "Solana program ID not initialized. Have you called Nord.initNord()?",
249
- );
250
- }
251
- return this._solanaProgramId;
252
- }
253
-
254
249
  /**
255
250
  * Get market statistics
256
251
  *
@@ -1,15 +1,15 @@
1
- import * as anchor from "@coral-xyz/anchor";
2
1
  import {
3
2
  ASSOCIATED_TOKEN_PROGRAM_ID,
4
3
  getAssociatedTokenAddress,
4
+ TOKEN_PROGRAM_ID,
5
5
  TOKEN_2022_PROGRAM_ID,
6
6
  } from "@solana/spl-token";
7
- import { Connection, Keypair, PublicKey, Transaction } from "@solana/web3.js";
7
+ import { Connection, PublicKey, Transaction } from "@solana/web3.js";
8
8
  import Decimal from "decimal.js";
9
- import * as nacl from "tweetnacl";
10
- import { SolanaBridgeClient } from "../../bridge/client";
11
- import { SPLTokenInfo } from "../../bridge/types";
12
- import { keypairFromPrivateKey } from "../../bridge/utils";
9
+ import * as ed from "@noble/ed25519";
10
+ import { sha512 } from "@noble/hashes/sha512";
11
+ ed.etc.sha512Sync = sha512;
12
+ import { SPLTokenInfo, DepositSplParams } from "@n1xyz/proton";
13
13
  import { FillMode, Order, Side } from "../../types";
14
14
  import {
15
15
  BigIntValue,
@@ -18,6 +18,7 @@ import {
18
18
  findToken,
19
19
  optExpect,
20
20
  toBN as utilsToBN,
21
+ keypairFromPrivateKey,
21
22
  } from "../../utils";
22
23
  import {
23
24
  cancelOrder,
@@ -119,7 +120,7 @@ export class NordUser {
119
120
  public readonly nord: Nord;
120
121
 
121
122
  /** User's blockchain address */
122
- public readonly address: string;
123
+ public readonly address: PublicKey;
123
124
 
124
125
  /** Function to sign messages with the user's wallet */
125
126
  public readonly walletSignFn: (
@@ -189,10 +190,6 @@ export class NordUser {
189
190
  /** Last nonce used */
190
191
  public lastNonce = 0;
191
192
 
192
- // Solana-specific properties
193
- /** Solana bridge client */
194
- public bridgeClient?: SolanaBridgeClient;
195
-
196
193
  /** Solana connection */
197
194
  public connection: Connection;
198
195
 
@@ -205,46 +202,48 @@ export class NordUser {
205
202
  * @param params - Parameters for creating a NordUser
206
203
  * @throws {NordError} If required parameters are missing
207
204
  */
208
- constructor(params: NordUserParams) {
209
- if (!params.nord) {
210
- throw new NordError("Nord instance is required");
211
- }
212
- if (!params.address) {
213
- throw new NordError("Address is required");
214
- }
215
- if (!params.walletSignFn) {
205
+ constructor({
206
+ address,
207
+ nord,
208
+ publicKey,
209
+ sessionPubKey,
210
+ sessionSignFn,
211
+ transactionSignFn,
212
+ walletSignFn,
213
+ connection,
214
+ sessionId,
215
+ }: NordUserParams) {
216
+ if (!walletSignFn) {
216
217
  throw new NordError("Wallet sign function is required");
217
218
  }
218
- if (!params.sessionSignFn) {
219
+ if (!sessionSignFn) {
219
220
  throw new NordError("Session sign function is required");
220
221
  }
221
- if (!params.sessionPubKey) {
222
+ if (!sessionPubKey) {
222
223
  throw new NordError("Session public key is required");
223
224
  }
224
225
 
225
- this.nord = params.nord;
226
- this.address = params.address;
227
- this.walletSignFn = params.walletSignFn;
228
- this.sessionSignFn = params.sessionSignFn;
229
- this.transactionSignFn = params.transactionSignFn;
230
- this.sessionPubKey = params.sessionPubKey;
231
- this.publicKey = params.publicKey;
226
+ try {
227
+ this.address = new PublicKey(address);
228
+ } catch (error) {
229
+ throw new NordError("Invalid Solana address", { cause: error });
230
+ }
231
+
232
+ this.nord = nord;
233
+ this.walletSignFn = walletSignFn;
234
+ this.sessionSignFn = sessionSignFn;
235
+ this.transactionSignFn = transactionSignFn;
236
+ this.sessionPubKey = sessionPubKey;
237
+ this.publicKey = publicKey;
232
238
  this.connection =
233
- params.connection ||
234
- new Connection(params.nord.solanaUrl, {
239
+ connection ||
240
+ new Connection(nord.solanaUrl, {
235
241
  commitment: "confirmed",
236
242
  });
237
243
 
238
244
  // Set sessionId if provided
239
- if (params.sessionId !== undefined) {
240
- this.sessionId = params.sessionId;
241
- }
242
-
243
- // Initialize bridge client if needed
244
- try {
245
- this.initBridgeClient();
246
- } catch (error) {
247
- console.warn("Failed to initialize bridge client:", error);
245
+ if (sessionId !== undefined) {
246
+ this.sessionId = sessionId;
248
247
  }
249
248
 
250
249
  // Convert tokens from info endpoint to SPLTokenInfo
@@ -266,7 +265,7 @@ export class NordUser {
266
265
  clone(): NordUser {
267
266
  const cloned = new NordUser({
268
267
  nord: this.nord,
269
- address: this.address,
268
+ address: this.address.toBase58(),
270
269
  walletSignFn: this.walletSignFn,
271
270
  sessionSignFn: this.sessionSignFn,
272
271
  transactionSignFn: this.transactionSignFn,
@@ -290,56 +289,6 @@ export class NordUser {
290
289
  return cloned;
291
290
  }
292
291
 
293
- /**
294
- * Initialize the Solana bridge client
295
- *
296
- * @private
297
- * @throws {NordError} If required parameters are missing
298
- */
299
- private initBridgeClient(): void {
300
- if (
301
- !this.getSolanaPublicKey() ||
302
- !this.connection ||
303
- !this.nord.getSolanaProgramId()
304
- ) {
305
- throw new NordError(
306
- "Solana public key, connection, and program ID are required to initialize bridge client",
307
- );
308
- }
309
-
310
- // Create an Anchor wallet that uses walletSignFn for signing
311
- const wallet: anchor.Wallet = {
312
- publicKey: this.getSolanaPublicKey(),
313
- signTransaction: async (tx: any) => {
314
- return await this.transactionSignFn(tx);
315
- },
316
- signAllTransactions: async (txs: any[]) => {
317
- return Promise.all(
318
- txs.map(async (tx) => {
319
- return await this.transactionSignFn(tx);
320
- }),
321
- );
322
- },
323
- // Create a keypair-like object with just the public key
324
- payer: {
325
- publicKey: this.getSolanaPublicKey(),
326
- secretKey: new Uint8Array(64), // Dummy secret key to satisfy the type
327
- } as Keypair,
328
- };
329
-
330
- // Initialize the bridge client
331
- this.bridgeClient = new SolanaBridgeClient(
332
- {
333
- rpcUrl: this.connection.rpcEndpoint,
334
- programId: this.nord.getSolanaProgramId(),
335
- commitment: "confirmed",
336
- tokenInfos: this.splTokenInfos,
337
- bridgeVk: this.nord.bridgeVk,
338
- },
339
- wallet,
340
- );
341
- }
342
-
343
292
  /**
344
293
  * Create a NordUser from a private key
345
294
  *
@@ -362,29 +311,36 @@ export class NordUser {
362
311
  const walletSignFn = async (
363
312
  message: Uint8Array | string,
364
313
  ): Promise<Uint8Array> => {
365
- const messageBuffer =
366
- typeof message === "string"
367
- ? Buffer.from(message)
368
- : Buffer.from(message);
314
+ function toHex(buffer: Uint8Array) {
315
+ return Array.from(buffer)
316
+ .map((byte) => byte.toString(16).padStart(2, "0"))
317
+ .join("");
318
+ }
319
+ const messageBuffer = new TextEncoder().encode(
320
+ toHex(message as Uint8Array),
321
+ );
369
322
 
370
- // Use the keypair to sign the message
371
- const signature = nacl.sign.detached(messageBuffer, keypair.secretKey);
323
+ // Use ed25519 to sign the message
324
+ const signature = ed.sign(
325
+ messageBuffer,
326
+ keypair.secretKey.slice(0, 32),
327
+ );
372
328
  return signature;
373
329
  };
374
330
 
375
331
  const sessionSignFn = async (
376
332
  message: Uint8Array,
377
333
  ): Promise<Uint8Array> => {
378
- // Use the keypair to sign the message
379
- return nacl.sign.detached(message, keypair.secretKey);
334
+ // Use ed25519 to sign the message
335
+ return ed.sign(message, keypair.secretKey.slice(0, 32));
380
336
  };
381
337
 
382
338
  // Create a transaction signing function
383
339
  const transactionSignFn = async (transaction: any): Promise<any> => {
384
340
  // This is a basic implementation - actual implementation would depend on the transaction type
385
- if (transaction.serializeMessage) {
341
+ if (transaction.sign) {
386
342
  // Solana transaction
387
- transaction.sign([keypair]);
343
+ transaction.sign(keypair);
388
344
  return transaction;
389
345
  }
390
346
 
@@ -424,13 +380,31 @@ export class NordUser {
424
380
  }
425
381
 
426
382
  try {
427
- return await getAssociatedTokenAddress(
383
+ // Get the token program ID from the mint account
384
+ const mintAccount = await this.connection.getAccountInfo(mint);
385
+ if (!mintAccount) {
386
+ throw new NordError("Mint account not found");
387
+ }
388
+ const tokenProgramId = mintAccount.owner;
389
+
390
+ // Validate that the mint is owned by a supported SPL token program
391
+ if (
392
+ !tokenProgramId.equals(TOKEN_PROGRAM_ID) &&
393
+ !tokenProgramId.equals(TOKEN_2022_PROGRAM_ID)
394
+ ) {
395
+ throw new NordError(
396
+ "Mint Account is not owned by a supported SPL token program",
397
+ );
398
+ }
399
+
400
+ const associatedTokenAddress = await getAssociatedTokenAddress(
428
401
  mint,
429
402
  this.getSolanaPublicKey(),
430
403
  false,
431
- TOKEN_2022_PROGRAM_ID,
404
+ tokenProgramId,
432
405
  ASSOCIATED_TOKEN_PROGRAM_ID,
433
406
  );
407
+ return associatedTokenAddress;
434
408
  } catch (error) {
435
409
  throw new NordError("Failed to get associated token account", {
436
410
  cause: error,
@@ -447,12 +421,6 @@ export class NordUser {
447
421
  * @throws {NordError} If required parameters are missing or operation fails
448
422
  */
449
423
  async depositSpl(amount: number, tokenId: number): Promise<string> {
450
- if (!this.bridgeClient || !this.getSolanaPublicKey() || !this.connection) {
451
- throw new NordError(
452
- "Bridge client, Solana public key, and connection are required for deposit",
453
- );
454
- }
455
-
456
424
  try {
457
425
  // Find the token info
458
426
  const tokenInfo = this.splTokenInfos.find((t) => t.tokenId === tokenId);
@@ -463,82 +431,43 @@ export class NordUser {
463
431
  const mint = new PublicKey(tokenInfo.mint);
464
432
  // Get the user's token account
465
433
  const fromAccount = await this.getAssociatedTokenAccount(mint);
434
+
466
435
  // Convert amount to BN with proper decimals
467
436
  const amountBN = utilsToBN(amount, tokenInfo.precision);
468
437
 
469
- // Deposit tokens
470
- return await this.bridgeClient.depositSpl({
438
+ // Create deposit parameters
439
+ const depositParams: DepositSplParams = {
471
440
  amount: amountBN,
472
441
  mint,
473
442
  fromAccount,
474
- });
475
- } catch (error) {
476
- throw new NordError(
477
- `Failed to deposit ${amount} of token ID ${tokenId}`,
478
- { cause: error },
479
- );
480
- }
481
- }
443
+ };
482
444
 
483
- /**
484
- * Withdraw SPL tokens from the bridge
485
- *
486
- * @param claim - Claim data
487
- * @returns Transaction signature
488
- * @throws {NordError} If required parameters are missing or operation fails
489
- */
490
- async withdrawSpl(claim: any): Promise<string> {
491
- if (!this.bridgeClient || !this.getSolanaPublicKey() || !this.connection) {
492
- throw new NordError(
493
- "Bridge client, Solana public key, and connection are required for withdrawal",
445
+ // Build the deposit transaction using proton client
446
+ const depositTx = await this.nord.protonClient.buildDepositTx(
447
+ depositParams,
448
+ this.getSolanaPublicKey(),
449
+ this.connection,
494
450
  );
495
- }
496
451
 
497
- try {
498
- // Find the token info
499
- const tokenInfo = this.splTokenInfos.find(
500
- (t) => t.tokenId === claim.tokenId,
501
- );
502
- if (!tokenInfo) {
503
- throw new NordError(`Token with ID ${claim.tokenId} not found`);
504
- }
452
+ const { blockhash } = await this.connection.getLatestBlockhash();
505
453
 
506
- const mint = new PublicKey(tokenInfo.mint);
454
+ depositTx.recentBlockhash = blockhash;
455
+ depositTx.feePayer = this.getSolanaPublicKey();
507
456
 
508
- // Get the user's token account
509
- const toAccount = await this.getAssociatedTokenAccount(mint);
457
+ const signedTx = await this.transactionSignFn(depositTx);
510
458
 
511
- // Get the bridge's token account
512
- const [authority] = await this.bridgeClient.findAuthorityPda();
513
- const fromAccount = await getAssociatedTokenAddress(
514
- mint,
515
- authority,
516
- true,
517
- TOKEN_2022_PROGRAM_ID,
459
+ // TODO: should use `VersionedTransaction` and remove any for `transactionSignFn`,
460
+ // this is incredibly annoying to debug and i could've saved 30 mins.
461
+ const signature = await this.connection.sendRawTransaction(
462
+ signedTx.serialize(),
518
463
  );
519
464
 
520
- // Create a transaction signer that uses walletSignFn
521
- const transactionSigner = {
522
- publicKey: this.getSolanaPublicKey(),
523
- secretKey: new Uint8Array(64), // Dummy secret key, not actually used
524
- sign: async (tx: Transaction) => {
525
- const message = tx.serializeMessage();
526
- await this.walletSignFn(message);
527
- return tx;
528
- },
529
- };
530
-
531
- // Withdraw tokens
532
- return await this.bridgeClient.withdraw(
533
- {
534
- claim,
535
- fromAccount,
536
- toAccount,
537
- },
538
- transactionSigner as unknown as Keypair, // Type cast to satisfy the API
539
- );
465
+ return signature;
540
466
  } catch (error) {
541
- throw new NordError("Failed to withdraw SPL tokens", { cause: error });
467
+ throw new NordError(
468
+ `Failed to deposit ${amount} of token ID ${tokenId}`,
469
+ { cause: error },
470
+ );
542
471
  }
543
472
  }
544
473
 
@@ -738,10 +667,13 @@ export class NordUser {
738
667
  * @param amount - Amount to withdraw
739
668
  * @throws {NordError} If the operation fails
740
669
  */
741
- async withdraw(tokenId: number, amount: number): Promise<void> {
670
+ async withdraw(
671
+ tokenId: number,
672
+ amount: number,
673
+ ): Promise<{ actionId: bigint }> {
742
674
  try {
743
675
  this.checkSessionValidity();
744
- await withdraw(
676
+ const { actionId } = await withdraw(
745
677
  this.nord.webServerUrl,
746
678
  this.sessionSignFn,
747
679
  await this.nord.getTimestamp(),
@@ -753,6 +685,7 @@ export class NordUser {
753
685
  amount,
754
686
  },
755
687
  );
688
+ return { actionId };
756
689
  } catch (error) {
757
690
  throw new NordError(
758
691
  `Failed to withdraw ${amount} of token ID ${tokenId}`,
@@ -804,7 +737,7 @@ export class NordUser {
804
737
  * Cancel an order
805
738
  *
806
739
  * @param orderId - Order ID to cancel
807
- * @param accountId - Account ID that placed the order
740
+ * @param providedAccountId - Account ID that placed the order
808
741
  * @returns Action ID if successful
809
742
  * @throws {NordError} If the operation fails
810
743
  */
@@ -980,7 +913,7 @@ export class NordUser {
980
913
  try {
981
914
  const tokenBalance = await this.retryWithBackoff(
982
915
  () =>
983
- this.connection!.getTokenAccountBalance(
916
+ this.connection.getTokenAccountBalance(
984
917
  associatedTokenAddress,
985
918
  ),
986
919
  maxRetries,
@@ -1026,10 +959,6 @@ export class NordUser {
1026
959
  * @returns The Solana public key
1027
960
  */
1028
961
  getSolanaPublicKey(): PublicKey {
1029
- try {
1030
- return new PublicKey(this.address);
1031
- } catch (error) {
1032
- throw new NordError("Invalid Solana address", { cause: error });
1033
- }
962
+ return this.address;
1034
963
  }
1035
964
  }
@@ -60,11 +60,15 @@ export class NordError extends Error {
60
60
  let result = `${this.name}: ${this.message}`;
61
61
 
62
62
  if (this.statusCode) {
63
- result += ` (Status: ${this.statusCode})`;
63
+ result += ` \nstatus: ${this.statusCode}`;
64
64
  }
65
65
 
66
66
  if (this.details && Object.keys(this.details).length > 0) {
67
- result += `\nDetails: ${JSON.stringify(this.details, null, 2)}`;
67
+ result += ` \ndetails: ${JSON.stringify(this.details, null, 2)}`;
68
+ }
69
+
70
+ if (this.cause) {
71
+ result += ` \ncause: ${this.cause.toString()}`;
68
72
  }
69
73
 
70
74
  return result;