@n1xyz/nord-ts 0.0.1 → 0.0.4

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 (237) hide show
  1. package/.eslintrc.js +11 -0
  2. package/README.md +148 -65
  3. package/dist/bridge/NordUser.d.ts +78 -0
  4. package/dist/bridge/NordUser.js +196 -0
  5. package/dist/bridge/client.d.ts +150 -0
  6. package/dist/bridge/client.js +394 -0
  7. package/dist/bridge/const.d.ts +23 -0
  8. package/dist/bridge/const.js +47 -0
  9. package/dist/bridge/index.d.ts +5 -0
  10. package/dist/bridge/index.js +23 -0
  11. package/dist/bridge/types.d.ts +118 -0
  12. package/dist/bridge/types.js +16 -0
  13. package/dist/bridge/utils.d.ts +64 -0
  14. package/dist/bridge/utils.js +131 -0
  15. package/dist/client.d.ts +70 -0
  16. package/dist/client.js +129 -0
  17. package/dist/const.d.ts +2 -5
  18. package/dist/const.js +18 -22
  19. package/dist/constants/endpoints.d.ts +65 -0
  20. package/dist/constants/endpoints.js +68 -0
  21. package/dist/gen/common.d.ts +6 -1
  22. package/dist/gen/common.js +19 -9
  23. package/dist/gen/nord.d.ts +75 -17
  24. package/dist/gen/nord.js +987 -423
  25. package/dist/idl/bridge.d.ts +2 -0
  26. package/dist/idl/bridge.js +703 -0
  27. package/dist/index.d.ts +8 -5
  28. package/dist/index.js +18 -2
  29. package/dist/models/account.d.ts +58 -0
  30. package/dist/models/account.js +6 -0
  31. package/dist/models/index.d.ts +8 -0
  32. package/dist/models/index.js +28 -0
  33. package/dist/models/market.d.ts +137 -0
  34. package/dist/models/market.js +6 -0
  35. package/dist/models/order.d.ts +211 -0
  36. package/dist/models/order.js +6 -0
  37. package/dist/models/token.d.ts +50 -0
  38. package/dist/models/token.js +6 -0
  39. package/dist/nord/Nord.d.ts +222 -49
  40. package/dist/nord/Nord.js +290 -278
  41. package/dist/nord/NordError.d.ts +23 -0
  42. package/dist/nord/NordError.js +48 -0
  43. package/dist/nord/NordImpl.d.ts +6 -2
  44. package/dist/nord/NordImpl.js +21 -1
  45. package/dist/nord/NordUser.d.ts +208 -42
  46. package/dist/nord/NordUser.js +389 -157
  47. package/dist/nord/Subscriber.d.ts +37 -0
  48. package/dist/nord/Subscriber.js +29 -0
  49. package/dist/nord/api/actions.d.ts +101 -0
  50. package/dist/nord/api/actions.js +250 -0
  51. package/dist/nord/api/core.d.ts +49 -0
  52. package/dist/nord/api/core.js +121 -0
  53. package/dist/nord/api/index.d.ts +1 -0
  54. package/dist/nord/api/index.js +17 -0
  55. package/dist/nord/api/market.d.ts +36 -0
  56. package/dist/nord/api/market.js +98 -0
  57. package/dist/nord/api/metrics.d.ts +67 -0
  58. package/dist/nord/api/metrics.js +132 -0
  59. package/dist/nord/api/orderFunctions.d.ts +168 -0
  60. package/dist/nord/api/orderFunctions.js +133 -0
  61. package/dist/nord/api/queries.d.ts +81 -0
  62. package/dist/nord/api/queries.js +187 -0
  63. package/dist/nord/client/Nord.d.ts +335 -0
  64. package/dist/nord/client/Nord.js +532 -0
  65. package/dist/nord/client/NordUser.d.ts +320 -0
  66. package/dist/nord/client/NordUser.js +701 -0
  67. package/dist/nord/core.d.ts +48 -0
  68. package/dist/nord/core.js +97 -0
  69. package/dist/nord/index.d.ts +9 -2
  70. package/dist/nord/index.js +30 -6
  71. package/dist/nord/market.d.ts +36 -0
  72. package/dist/nord/market.js +90 -0
  73. package/dist/nord/metrics.d.ts +67 -0
  74. package/dist/nord/metrics.js +124 -0
  75. package/dist/nord/models/Subscriber.d.ts +37 -0
  76. package/dist/nord/models/Subscriber.js +29 -0
  77. package/dist/nord/queries.d.ts +81 -0
  78. package/dist/nord/queries.js +181 -0
  79. package/dist/nord/types.d.ts +88 -0
  80. package/dist/nord/types.js +2 -0
  81. package/dist/nord/utils/NordError.d.ts +35 -0
  82. package/dist/nord/utils/NordError.js +46 -0
  83. package/dist/nord/websocket.d.ts +49 -0
  84. package/dist/nord/websocket.js +107 -0
  85. package/dist/operations/account.d.ts +58 -0
  86. package/dist/operations/account.js +112 -0
  87. package/dist/operations/market.d.ts +65 -0
  88. package/dist/operations/market.js +131 -0
  89. package/dist/operations/orders.d.ts +57 -0
  90. package/dist/operations/orders.js +129 -0
  91. package/dist/solana/NordUser.d.ts +78 -0
  92. package/dist/solana/NordUser.js +196 -0
  93. package/dist/solana/client.d.ts +139 -0
  94. package/dist/solana/client.js +360 -0
  95. package/dist/solana/const.d.ts +23 -0
  96. package/dist/solana/const.js +47 -0
  97. package/dist/solana/index.d.ts +5 -0
  98. package/dist/solana/index.js +23 -0
  99. package/dist/solana/types.d.ts +118 -0
  100. package/dist/solana/types.js +16 -0
  101. package/dist/solana/utils.d.ts +64 -0
  102. package/dist/solana/utils.js +131 -0
  103. package/dist/types/api.d.ts +152 -0
  104. package/dist/types/api.js +6 -0
  105. package/dist/types/config.d.ts +34 -0
  106. package/dist/types/config.js +6 -0
  107. package/dist/types.d.ts +144 -87
  108. package/dist/types.js +13 -2
  109. package/dist/utils/errors.d.ts +96 -0
  110. package/dist/utils/errors.js +132 -0
  111. package/dist/utils/http.d.ts +35 -0
  112. package/dist/utils/http.js +105 -0
  113. package/dist/utils.d.ts +14 -5
  114. package/dist/utils.js +26 -7
  115. package/dist/websocket/NordWebSocketClient.d.ts +71 -0
  116. package/dist/websocket/NordWebSocketClient.js +343 -0
  117. package/dist/websocket/client.d.ts +93 -0
  118. package/dist/websocket/client.js +222 -0
  119. package/dist/websocket/events.d.ts +19 -0
  120. package/dist/websocket/events.js +2 -0
  121. package/dist/websocket/index.d.ts +2 -0
  122. package/dist/websocket/index.js +5 -0
  123. package/dist/websocket.d.ts +55 -0
  124. package/dist/websocket.js +211 -0
  125. package/docs/assets/navigation.js +1 -1
  126. package/docs/assets/search.js +1 -1
  127. package/docs/classes/Nord.html +2 -15
  128. package/docs/classes/NordUser.html +4 -4
  129. package/docs/enums/FillMode.html +2 -2
  130. package/docs/enums/KeyType.html +2 -2
  131. package/docs/enums/PeakTpsPeriodUnit.html +2 -2
  132. package/docs/enums/Side.html +2 -2
  133. package/docs/functions/assert.html +1 -1
  134. package/docs/functions/bigIntToProtoU128.html +1 -1
  135. package/docs/functions/checkPubKeyLength.html +1 -1
  136. package/docs/functions/checkedFetch.html +1 -1
  137. package/docs/functions/decodeLengthDelimited.html +1 -1
  138. package/docs/functions/encodeLengthDelimited.html +1 -1
  139. package/docs/functions/fillModeToProtoFillMode.html +1 -1
  140. package/docs/functions/findMarket.html +1 -1
  141. package/docs/functions/findToken.html +1 -1
  142. package/docs/functions/makeWalletSignFn.html +1 -1
  143. package/docs/functions/optExpect.html +1 -1
  144. package/docs/functions/optMap.html +1 -1
  145. package/docs/functions/optUnwrap.html +1 -1
  146. package/docs/functions/panic.html +1 -1
  147. package/docs/functions/signAction.html +1 -1
  148. package/docs/functions/toScaledU128.html +1 -1
  149. package/docs/functions/toScaledU64.html +1 -1
  150. package/docs/interfaces/Account.html +2 -2
  151. package/docs/interfaces/ActionInfo.html +2 -2
  152. package/docs/interfaces/ActionQuery.html +2 -2
  153. package/docs/interfaces/ActionResponse.html +2 -2
  154. package/docs/interfaces/ActionsExtendedInfo.html +2 -2
  155. package/docs/interfaces/ActionsQuery.html +2 -2
  156. package/docs/interfaces/ActionsResponse.html +2 -2
  157. package/docs/interfaces/AggregateMetrics.html +2 -2
  158. package/docs/interfaces/BlockQuery.html +2 -2
  159. package/docs/interfaces/BlockResponse.html +2 -2
  160. package/docs/interfaces/BlockSummary.html +2 -2
  161. package/docs/interfaces/BlockSummaryResponse.html +2 -2
  162. package/docs/interfaces/DeltaEvent.html +2 -2
  163. package/docs/interfaces/ERC20TokenInfo.html +2 -2
  164. package/docs/interfaces/Info.html +2 -2
  165. package/docs/interfaces/Market.html +2 -2
  166. package/docs/interfaces/MarketStats.html +2 -2
  167. package/docs/interfaces/MarketsStatsResponse.html +2 -2
  168. package/docs/interfaces/NordConfig.html +2 -2
  169. package/docs/interfaces/Order.html +2 -2
  170. package/docs/interfaces/OrderInfo.html +2 -2
  171. package/docs/interfaces/PerpMarketStats.html +2 -2
  172. package/docs/interfaces/RollmanActionExtendedInfo.html +2 -2
  173. package/docs/interfaces/RollmanActionInfo.html +2 -2
  174. package/docs/interfaces/RollmanActionResponse.html +2 -2
  175. package/docs/interfaces/RollmanActionsResponse.html +2 -2
  176. package/docs/interfaces/RollmanBlockResponse.html +2 -2
  177. package/docs/interfaces/SubscriberConfig.html +2 -2
  178. package/docs/interfaces/Token.html +2 -2
  179. package/docs/interfaces/Trade.html +2 -2
  180. package/docs/interfaces/Trades.html +2 -2
  181. package/docs/modules.html +0 -7
  182. package/docs/types/BigIntValue.html +1 -1
  183. package/docs/variables/DEBUG_KEYS.html +1 -1
  184. package/docs/variables/DEFAULT_FUNDING_AMOUNTS.html +1 -1
  185. package/docs/variables/DEV_CONTRACT_ADDRESS.html +1 -1
  186. package/docs/variables/DEV_TOKEN_INFOS.html +1 -1
  187. package/docs/variables/DEV_URL.html +1 -1
  188. package/docs/variables/ERC20_ABI.html +1 -1
  189. package/docs/variables/EVM_DEV_URL.html +1 -1
  190. package/docs/variables/FAUCET_PRIVATE_ADDRESS.html +1 -1
  191. package/docs/variables/MAX_BUFFER_LEN.html +1 -1
  192. package/docs/variables/NORD_GETTERS_FACET_ABI.html +1 -1
  193. package/docs/variables/NORD_RAMP_FACET_ABI.html +1 -1
  194. package/docs/variables/SESSION_TTL.html +1 -1
  195. package/docs/variables/WEBSERVER_DEV_URL.html +1 -1
  196. package/docs/variables/ZERO_DECIMAL.html +1 -1
  197. package/package.json +10 -12
  198. package/src/bridge/client.ts +487 -0
  199. package/src/bridge/const.ts +53 -0
  200. package/src/bridge/index.ts +7 -0
  201. package/src/bridge/types.ts +127 -0
  202. package/src/bridge/utils.ts +140 -0
  203. package/src/const.ts +20 -25
  204. package/src/gen/common.ts +27 -10
  205. package/src/gen/nord.ts +1044 -483
  206. package/src/idl/bridge.ts +702 -0
  207. package/src/index.ts +24 -5
  208. package/src/nord/{actions.ts → api/actions.ts} +33 -37
  209. package/src/nord/api/core.ts +130 -0
  210. package/src/nord/api/market.ts +125 -0
  211. package/src/nord/api/metrics.ts +154 -0
  212. package/src/nord/api/queries.ts +236 -0
  213. package/src/nord/client/Nord.ts +652 -0
  214. package/src/nord/client/NordUser.ts +1105 -0
  215. package/src/nord/index.ts +16 -2
  216. package/src/nord/models/Subscriber.ts +57 -0
  217. package/src/nord/utils/NordError.ts +72 -0
  218. package/src/types.ts +170 -99
  219. package/src/utils.ts +40 -19
  220. package/src/websocket/NordWebSocketClient.ts +432 -0
  221. package/src/websocket/events.ts +31 -0
  222. package/src/websocket/index.ts +2 -0
  223. package/tests/utils.spec.ts +24 -24
  224. package/docs/classes/Subscriber.html +0 -6
  225. package/docs/functions/createWebSocketSubscription.html +0 -12
  226. package/docs/interfaces/OrderbookOrder.html +0 -6
  227. package/docs/interfaces/OrderbookResponse.html +0 -10
  228. package/docs/interfaces/TradeInfo.html +0 -20
  229. package/docs/interfaces/TradesQueryParams.html +0 -10
  230. package/docs/interfaces/TradesResponse.html +0 -12
  231. package/src/abis/ERC20_ABI.ts +0 -310
  232. package/src/abis/NORD_GETTERS_FACET_ABI.ts +0 -192
  233. package/src/abis/NORD_RAMP_FACET_ABI.ts +0 -141
  234. package/src/abis/index.ts +0 -3
  235. package/src/nord/Nord.ts +0 -504
  236. package/src/nord/NordImpl.ts +0 -8
  237. package/src/nord/NordUser.ts +0 -469
@@ -0,0 +1,701 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.NordUser = void 0;
37
+ const spl_token_1 = require("@solana/spl-token");
38
+ const web3_js_1 = require("@solana/web3.js");
39
+ const nacl = __importStar(require("tweetnacl"));
40
+ const client_1 = require("../../bridge/client");
41
+ const utils_1 = require("../../bridge/utils");
42
+ const utils_2 = require("../../utils");
43
+ const actions_1 = require("../api/actions");
44
+ const NordError_1 = require("../utils/NordError");
45
+ /**
46
+ * User class for interacting with the Nord protocol
47
+ */
48
+ class NordUser {
49
+ /**
50
+ * Create a new NordUser instance
51
+ *
52
+ * @param params - Parameters for creating a NordUser
53
+ * @throws {NordError} If required parameters are missing
54
+ */
55
+ constructor(params) {
56
+ /** User balances by token symbol */
57
+ this.balances = {};
58
+ /** User orders by market symbol */
59
+ this.orders = {};
60
+ /** User positions by account ID */
61
+ this.positions = {};
62
+ /** User margins by account ID */
63
+ this.margins = {};
64
+ /** Last timestamp used */
65
+ this.lastTs = 0;
66
+ /** Last nonce used */
67
+ this.lastNonce = 0;
68
+ /** SPL token information */
69
+ this.splTokenInfos = [];
70
+ if (!params.nord) {
71
+ throw new NordError_1.NordError('Nord instance is required');
72
+ }
73
+ if (!params.address) {
74
+ throw new NordError_1.NordError('Address is required');
75
+ }
76
+ if (!params.walletSignFn) {
77
+ throw new NordError_1.NordError('Wallet sign function is required');
78
+ }
79
+ if (!params.sessionSignFn) {
80
+ throw new NordError_1.NordError('Session sign function is required');
81
+ }
82
+ if (!params.sessionPubKey) {
83
+ throw new NordError_1.NordError('Session public key is required');
84
+ }
85
+ this.nord = params.nord;
86
+ this.address = params.address;
87
+ this.walletSignFn = params.walletSignFn;
88
+ this.sessionSignFn = params.sessionSignFn;
89
+ this.transactionSignFn = params.transactionSignFn;
90
+ this.sessionPubKey = params.sessionPubKey;
91
+ this.publicKey = params.publicKey;
92
+ this.connection =
93
+ params.connection ||
94
+ new web3_js_1.Connection(params.nord.solanaUrl, {
95
+ commitment: 'confirmed',
96
+ });
97
+ // Set sessionId if provided
98
+ if (params.sessionId !== undefined) {
99
+ this.sessionId = params.sessionId;
100
+ }
101
+ // Initialize bridge client if needed
102
+ try {
103
+ this.initBridgeClient();
104
+ }
105
+ catch (error) {
106
+ console.warn('Failed to initialize bridge client:', error);
107
+ }
108
+ // Convert tokens from info endpoint to SPLTokenInfo
109
+ if (this.nord.tokens && this.nord.tokens.length > 0) {
110
+ this.splTokenInfos = this.nord.tokens.map((token) => ({
111
+ mint: token.mintAddr, // Use mintAddr as mint
112
+ precision: token.decimals,
113
+ tokenId: token.tokenId,
114
+ name: token.symbol,
115
+ }));
116
+ }
117
+ }
118
+ /**
119
+ * Create a clone of this NordUser instance
120
+ *
121
+ * @returns A new NordUser instance with the same properties
122
+ */
123
+ clone() {
124
+ const cloned = new NordUser({
125
+ nord: this.nord,
126
+ address: this.address,
127
+ walletSignFn: this.walletSignFn,
128
+ sessionSignFn: this.sessionSignFn,
129
+ transactionSignFn: this.transactionSignFn,
130
+ connection: this.connection,
131
+ sessionPubKey: this.sessionPubKey,
132
+ publicKey: this.publicKey,
133
+ });
134
+ // Copy other properties
135
+ cloned.balances = { ...this.balances };
136
+ cloned.orders = { ...this.orders };
137
+ cloned.positions = { ...this.positions };
138
+ cloned.margins = { ...this.margins };
139
+ cloned.accountIds = this.accountIds ? [...this.accountIds] : undefined;
140
+ cloned.sessionId = this.sessionId;
141
+ cloned.publicKey = this.publicKey;
142
+ cloned.lastTs = this.lastTs;
143
+ cloned.lastNonce = this.lastNonce;
144
+ cloned.splTokenInfos = [...this.splTokenInfos];
145
+ return cloned;
146
+ }
147
+ /**
148
+ * Initialize the Solana bridge client
149
+ *
150
+ * @private
151
+ * @throws {NordError} If required parameters are missing
152
+ */
153
+ initBridgeClient() {
154
+ if (!this.getSolanaPublicKey() ||
155
+ !this.connection ||
156
+ !this.nord.solanaProgramId) {
157
+ throw new NordError_1.NordError('Solana public key, connection, and program ID are required to initialize bridge client');
158
+ }
159
+ // Create an Anchor wallet that uses walletSignFn for signing
160
+ const wallet = {
161
+ publicKey: this.getSolanaPublicKey(),
162
+ signTransaction: async (tx) => {
163
+ await this.transactionSignFn(tx);
164
+ return tx;
165
+ },
166
+ signAllTransactions: async (txs) => {
167
+ return Promise.all(txs.map(async (tx) => {
168
+ await this.transactionSignFn(tx);
169
+ return tx;
170
+ }));
171
+ },
172
+ // Create a keypair-like object with just the public key
173
+ payer: {
174
+ publicKey: this.getSolanaPublicKey(),
175
+ secretKey: new Uint8Array(64), // Dummy secret key to satisfy the type
176
+ },
177
+ };
178
+ // Initialize the bridge client
179
+ this.bridgeClient = new client_1.SolanaBridgeClient({
180
+ rpcUrl: this.connection.rpcEndpoint,
181
+ programId: this.nord.solanaProgramId,
182
+ commitment: 'confirmed',
183
+ tokenInfos: this.splTokenInfos,
184
+ }, wallet);
185
+ }
186
+ /**
187
+ * Create a NordUser from a private key
188
+ *
189
+ * @param nord - Nord instance
190
+ * @param privateKey - Private key as string or Uint8Array
191
+ * @param connection - Solana connection (optional)
192
+ * @returns NordUser instance
193
+ * @throws {NordError} If the private key is invalid
194
+ */
195
+ static fromPrivateKey(nord, privateKey, connection) {
196
+ try {
197
+ const keypair = (0, utils_1.keypairFromPrivateKey)(privateKey);
198
+ const publicKey = keypair.publicKey;
199
+ // Create a signing function that uses the keypair but doesn't expose it
200
+ const walletSignFn = async (message) => {
201
+ const messageBuffer = typeof message === 'string'
202
+ ? Buffer.from(message)
203
+ : Buffer.from(message);
204
+ // Use the keypair to sign the message
205
+ const signature = nacl.sign.detached(messageBuffer, keypair.secretKey);
206
+ return signature;
207
+ };
208
+ const sessionSignFn = async (message) => {
209
+ // Use the keypair to sign the message
210
+ return nacl.sign.detached(message, keypair.secretKey);
211
+ };
212
+ // Create a transaction signing function
213
+ const transactionSignFn = async (transaction) => {
214
+ // This is a basic implementation - actual implementation would depend on the transaction type
215
+ if (transaction.serializeMessage) {
216
+ // Solana transaction
217
+ transaction.sign([keypair]);
218
+ return transaction;
219
+ }
220
+ // For other transaction types, would need specific implementation
221
+ throw new NordError_1.NordError('Unsupported transaction type for signing');
222
+ };
223
+ return new NordUser({
224
+ nord,
225
+ address: publicKey.toBase58(),
226
+ walletSignFn,
227
+ sessionSignFn,
228
+ transactionSignFn,
229
+ connection,
230
+ publicKey,
231
+ sessionPubKey: publicKey.toBytes(), // Use the public key derived from the private key as the session public key
232
+ });
233
+ }
234
+ catch (error) {
235
+ throw new NordError_1.NordError('Failed to create NordUser from private key', {
236
+ cause: error,
237
+ });
238
+ }
239
+ }
240
+ /**
241
+ * Get the associated token account for a token mint
242
+ *
243
+ * @param mint - Token mint address
244
+ * @returns Associated token account address
245
+ * @throws {NordError} If required parameters are missing or operation fails
246
+ */
247
+ async getAssociatedTokenAccount(mint) {
248
+ if (!this.getSolanaPublicKey()) {
249
+ throw new NordError_1.NordError('Solana public key is required to get associated token account');
250
+ }
251
+ try {
252
+ return await (0, spl_token_1.getAssociatedTokenAddress)(mint, this.getSolanaPublicKey(), false, spl_token_1.TOKEN_2022_PROGRAM_ID, spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID);
253
+ }
254
+ catch (error) {
255
+ throw new NordError_1.NordError('Failed to get associated token account', {
256
+ cause: error,
257
+ });
258
+ }
259
+ }
260
+ /**
261
+ * Deposit SPL tokens to the bridge
262
+ *
263
+ * @param amount - Amount to deposit
264
+ * @param tokenId - Token ID
265
+ * @returns Transaction signature
266
+ * @throws {NordError} If required parameters are missing or operation fails
267
+ */
268
+ async depositSpl(amount, tokenId) {
269
+ if (!this.bridgeClient || !this.getSolanaPublicKey() || !this.connection) {
270
+ throw new NordError_1.NordError('Bridge client, Solana public key, and connection are required for deposit');
271
+ }
272
+ try {
273
+ // Find the token info
274
+ const tokenInfo = this.splTokenInfos.find((t) => t.tokenId === tokenId);
275
+ if (!tokenInfo) {
276
+ throw new NordError_1.NordError(`Token with ID ${tokenId} not found`);
277
+ }
278
+ const mint = new web3_js_1.PublicKey(tokenInfo.mint);
279
+ // Get the user's token account
280
+ const fromAccount = await this.getAssociatedTokenAccount(mint);
281
+ // Get the bridge's token account
282
+ const [authority] = await this.bridgeClient.findAuthorityPda();
283
+ const toAccount = await (0, spl_token_1.getAssociatedTokenAddress)(mint, authority, true, spl_token_1.TOKEN_2022_PROGRAM_ID);
284
+ // Convert amount to BN with proper decimals
285
+ const amountBN = (0, utils_2.toBN)(amount, tokenInfo.precision);
286
+ // Deposit tokens
287
+ return await this.bridgeClient.depositSpl({
288
+ amount: amountBN,
289
+ mint,
290
+ fromAccount,
291
+ toAccount,
292
+ });
293
+ }
294
+ catch (error) {
295
+ throw new NordError_1.NordError(`Failed to deposit ${amount} of token ID ${tokenId}`, { cause: error });
296
+ }
297
+ }
298
+ /**
299
+ * Withdraw SPL tokens from the bridge
300
+ *
301
+ * @param claim - Claim data
302
+ * @returns Transaction signature
303
+ * @throws {NordError} If required parameters are missing or operation fails
304
+ */
305
+ async withdrawSpl(claim) {
306
+ if (!this.bridgeClient || !this.getSolanaPublicKey() || !this.connection) {
307
+ throw new NordError_1.NordError('Bridge client, Solana public key, and connection are required for withdrawal');
308
+ }
309
+ try {
310
+ // Find the token info
311
+ const tokenInfo = this.splTokenInfos.find((t) => t.tokenId === claim.tokenId);
312
+ if (!tokenInfo) {
313
+ throw new NordError_1.NordError(`Token with ID ${claim.tokenId} not found`);
314
+ }
315
+ const mint = new web3_js_1.PublicKey(tokenInfo.mint);
316
+ // Get the user's token account
317
+ const toAccount = await this.getAssociatedTokenAccount(mint);
318
+ // Get the bridge's token account
319
+ const [authority] = await this.bridgeClient.findAuthorityPda();
320
+ const fromAccount = await (0, spl_token_1.getAssociatedTokenAddress)(mint, authority, true, spl_token_1.TOKEN_2022_PROGRAM_ID);
321
+ // Create a transaction signer that uses walletSignFn
322
+ const transactionSigner = {
323
+ publicKey: this.getSolanaPublicKey(),
324
+ secretKey: new Uint8Array(64), // Dummy secret key, not actually used
325
+ sign: async (tx) => {
326
+ const message = tx.serializeMessage();
327
+ const signature = await this.walletSignFn(message);
328
+ // todo: fixxxxx
329
+ // tx.addSignature(this.getSolanaPublicKey()!, signature);
330
+ return tx;
331
+ },
332
+ };
333
+ // Withdraw tokens
334
+ return await this.bridgeClient.withdraw({
335
+ claim,
336
+ fromAccount,
337
+ toAccount,
338
+ }, transactionSigner);
339
+ }
340
+ catch (error) {
341
+ throw new NordError_1.NordError('Failed to withdraw SPL tokens', { cause: error });
342
+ }
343
+ }
344
+ /**
345
+ * Get a new nonce for actions
346
+ *
347
+ * @returns Nonce as number
348
+ */
349
+ getNonce() {
350
+ return ++this.lastNonce;
351
+ }
352
+ /**
353
+ * Update account IDs for this user
354
+ *
355
+ * @throws {NordError} If the operation fails
356
+ */
357
+ async updateAccountId() {
358
+ try {
359
+ if (!this.publicKey) {
360
+ throw new NordError_1.NordError('Public key is required to update account ID');
361
+ }
362
+ const resp = await this.nord.getUserAccountIds({
363
+ pubkey: this.publicKey.toBase58(),
364
+ });
365
+ this.accountIds = resp.accountIds;
366
+ }
367
+ catch (error) {
368
+ throw new NordError_1.NordError('Failed to update account ID', { cause: error });
369
+ }
370
+ }
371
+ /**
372
+ * Fetch user information including balances and orders
373
+ *
374
+ * @throws {NordError} If the operation fails
375
+ */
376
+ async fetchInfo() {
377
+ if (this.accountIds !== undefined) {
378
+ const accountsData = await Promise.all(this.accountIds.map(async (accountId) => {
379
+ const response = await (0, utils_2.checkedFetch)(`${this.nord.webServerUrl}/account?account_id=${accountId}`);
380
+ const accountData = (await response.json());
381
+ // Ensure we have the correct accountId
382
+ return {
383
+ ...accountData,
384
+ accountId,
385
+ };
386
+ }));
387
+ for (const accountData of accountsData) {
388
+ // Process balances
389
+ this.balances[accountData.accountId] = [];
390
+ for (const balance of accountData.balances) {
391
+ this.balances[accountData.accountId].push({
392
+ accountId: accountData.accountId,
393
+ balance: balance.amount,
394
+ symbol: balance.token,
395
+ });
396
+ }
397
+ // Process orders
398
+ this.orders[accountData.accountId] = accountData.orders.map((order) => {
399
+ return {
400
+ orderId: order.orderId,
401
+ isLong: order.side === 'bid',
402
+ size: order.size,
403
+ price: order.price,
404
+ marketId: order.marketId,
405
+ };
406
+ });
407
+ // Process positions
408
+ this.positions[accountData.accountId] = accountData.positions;
409
+ // Process margins
410
+ this.margins[accountData.accountId] = accountData.margins;
411
+ }
412
+ }
413
+ }
414
+ /**
415
+ * Refresh the user's session
416
+ *
417
+ * @throws {NordError} If the operation fails
418
+ */
419
+ async refreshSession() {
420
+ console.log(this.publicKey);
421
+ this.sessionId = await (0, actions_1.createSession)(this.nord.webServerUrl, this.walletSignFn, await this.nord.getTimestamp(), this.getNonce(), {
422
+ userPubkey: (0, utils_2.optExpect)(this.publicKey.toBytes(), "No user's public key"),
423
+ sessionPubkey: this.sessionPubKey,
424
+ });
425
+ }
426
+ /**
427
+ * Revoke a session
428
+ *
429
+ * @param sessionId - Session ID to revoke
430
+ * @throws {NordError} If the operation fails
431
+ */
432
+ async revokeSession(sessionId) {
433
+ try {
434
+ await (0, actions_1.revokeSession)(this.nord.webServerUrl, this.walletSignFn, await this.nord.getTimestamp(), this.getNonce(), {
435
+ sessionId,
436
+ });
437
+ }
438
+ catch (error) {
439
+ throw new NordError_1.NordError(`Failed to revoke session ${sessionId}`, {
440
+ cause: error,
441
+ });
442
+ }
443
+ }
444
+ /**
445
+ * Checks if the session is valid
446
+ * @private
447
+ * @throws {NordError} If the session is not valid
448
+ */
449
+ checkSessionValidity() {
450
+ if (this.sessionId === undefined || this.sessionId === BigInt(0)) {
451
+ throw new NordError_1.NordError('Invalid or empty session ID. Please create or refresh your session.');
452
+ }
453
+ }
454
+ /**
455
+ * Withdraw tokens from the exchange
456
+ *
457
+ * @param tokenId - Token ID to withdraw
458
+ * @param amount - Amount to withdraw
459
+ * @throws {NordError} If the operation fails
460
+ */
461
+ async withdraw(tokenId, amount) {
462
+ try {
463
+ this.checkSessionValidity();
464
+ await (0, actions_1.withdraw)(this.nord.webServerUrl, this.sessionSignFn, await this.nord.getTimestamp(), this.getNonce(), {
465
+ sizeDecimals: (0, utils_2.findToken)(this.nord.tokens, tokenId).decimals,
466
+ sessionId: (0, utils_2.optExpect)(this.sessionId, 'No session'),
467
+ tokenId: tokenId,
468
+ amount,
469
+ });
470
+ }
471
+ catch (error) {
472
+ throw new NordError_1.NordError(`Failed to withdraw ${amount} of token ID ${tokenId}`, { cause: error });
473
+ }
474
+ }
475
+ /**
476
+ * Place an order on the exchange
477
+ *
478
+ * @param params - Order parameters
479
+ * @returns Order ID if successful
480
+ * @throws {NordError} If the operation fails
481
+ */
482
+ async placeOrder(params) {
483
+ try {
484
+ this.checkSessionValidity();
485
+ const market = (0, utils_2.findMarket)(this.nord.markets, params.marketId);
486
+ if (!market) {
487
+ throw new NordError_1.NordError(`Market with ID ${params.marketId} not found`);
488
+ }
489
+ return (0, actions_1.placeOrder)(this.nord.webServerUrl, this.sessionSignFn, await this.nord.getTimestamp(), this.getNonce(), {
490
+ sessionId: (0, utils_2.optExpect)(this.sessionId, 'No session'),
491
+ senderId: params.accountId,
492
+ sizeDecimals: market.sizeDecimals,
493
+ priceDecimals: market.priceDecimals,
494
+ marketId: params.marketId,
495
+ side: params.side,
496
+ fillMode: params.fillMode,
497
+ isReduceOnly: params.isReduceOnly,
498
+ size: params.size,
499
+ price: params.price,
500
+ quoteSize: params.quoteSize,
501
+ });
502
+ }
503
+ catch (error) {
504
+ throw new NordError_1.NordError('Failed to place order', { cause: error });
505
+ }
506
+ }
507
+ /**
508
+ * Cancel an order
509
+ *
510
+ * @param orderId - Order ID to cancel
511
+ * @param accountId - Account ID that placed the order
512
+ * @returns Action ID if successful
513
+ * @throws {NordError} If the operation fails
514
+ */
515
+ async cancelOrder(orderId, providedAccountId) {
516
+ let accountId = providedAccountId != null ? providedAccountId : this.accountIds?.[0];
517
+ try {
518
+ this.checkSessionValidity();
519
+ return (0, actions_1.cancelOrder)(this.nord.webServerUrl, this.sessionSignFn, await this.nord.getTimestamp(), this.getNonce(), {
520
+ sessionId: (0, utils_2.optExpect)(this.sessionId, 'No session'),
521
+ senderId: accountId,
522
+ orderId,
523
+ });
524
+ }
525
+ catch (error) {
526
+ throw new NordError_1.NordError(`Failed to cancel order ${orderId}`, {
527
+ cause: error,
528
+ });
529
+ }
530
+ }
531
+ /**
532
+ * Transfer tokens to another account
533
+ *
534
+ * @param params - Transfer parameters
535
+ * @throws {NordError} If the operation fails
536
+ */
537
+ async transferToAccount(params) {
538
+ try {
539
+ this.checkSessionValidity();
540
+ const token = (0, utils_2.findToken)(this.nord.tokens, params.tokenId);
541
+ await (0, actions_1.transfer)(this.nord.webServerUrl, this.sessionSignFn, await this.nord.getTimestamp(), this.getNonce(), {
542
+ sessionId: (0, utils_2.optExpect)(this.sessionId, 'No session'),
543
+ fromAccountId: (0, utils_2.optExpect)(params.fromAccountId, 'No source account'),
544
+ toAccountId: (0, utils_2.optExpect)(params.toAccountId, 'No target account'),
545
+ tokenId: params.tokenId,
546
+ tokenDecimals: token.decimals,
547
+ amount: params.amount,
548
+ });
549
+ }
550
+ catch (error) {
551
+ throw new NordError_1.NordError('Failed to transfer tokens', { cause: error });
552
+ }
553
+ }
554
+ /**
555
+ * Create a new account
556
+ *
557
+ * @param params - Account creation parameters
558
+ * @returns New NordUser instance
559
+ * @throws {NordError} If the operation fails
560
+ */
561
+ async createAccount(params) {
562
+ try {
563
+ this.checkSessionValidity();
564
+ // Create a new keypair for the account
565
+ const keypair = web3_js_1.Keypair.generate();
566
+ // Create a new NordUser
567
+ const newUser = NordUser.fromPrivateKey(this.nord, keypair.secretKey, this.connection);
568
+ // Transfer initial funds
569
+ await this.transferToAccount({
570
+ to: newUser,
571
+ tokenId: params.tokenId,
572
+ amount: params.amount,
573
+ fromAccountId: (0, utils_2.optExpect)(this.accountIds?.[0], 'No account ID'),
574
+ toAccountId: (0, utils_2.optExpect)(newUser.accountIds?.[0], 'No account ID for new user'),
575
+ });
576
+ return newUser;
577
+ }
578
+ catch (error) {
579
+ throw new NordError_1.NordError('Failed to create account', { cause: error });
580
+ }
581
+ }
582
+ /**
583
+ * Helper function to retry a promise with exponential backoff
584
+ *
585
+ * @param fn - Function to retry
586
+ * @param maxRetries - Maximum number of retries
587
+ * @param initialDelay - Initial delay in milliseconds
588
+ * @returns Promise result
589
+ */
590
+ async retryWithBackoff(fn, maxRetries = 3, initialDelay = 500) {
591
+ let retries = 0;
592
+ let delay = initialDelay;
593
+ while (true) {
594
+ try {
595
+ return await fn();
596
+ }
597
+ catch (error) {
598
+ if (retries >= maxRetries) {
599
+ throw error;
600
+ }
601
+ // Check if error is rate limiting related
602
+ const isRateLimitError = error instanceof Error &&
603
+ (error.message.includes('rate limit') ||
604
+ error.message.includes('429') ||
605
+ error.message.includes('too many requests'));
606
+ if (!isRateLimitError) {
607
+ throw error;
608
+ }
609
+ retries++;
610
+ await new Promise((resolve) => setTimeout(resolve, delay));
611
+ delay *= 2; // Exponential backoff
612
+ }
613
+ }
614
+ }
615
+ /**
616
+ * Get user's token balances on Solana chain using mintAddr
617
+ *
618
+ * @param options - Optional parameters
619
+ * @param options.includeZeroBalances - Whether to include tokens with zero balance (default: true)
620
+ * @param options.includeTokenAccounts - Whether to include token account addresses in the result (default: false)
621
+ * @param options.maxConcurrent - Maximum number of concurrent requests (default: 5)
622
+ * @param options.maxRetries - Maximum number of retries for rate-limited requests (default: 3)
623
+ * @returns Object with token balances and optional token account addresses
624
+ * @throws {NordError} If required parameters are missing or operation fails
625
+ */
626
+ async getSolanaBalances(options = {}) {
627
+ const { includeZeroBalances = true, includeTokenAccounts = false, maxConcurrent = 5, maxRetries = 3, } = options;
628
+ if (!this.connection || !this.getSolanaPublicKey()) {
629
+ throw new NordError_1.NordError('Connection and Solana public key are required to get Solana balances');
630
+ }
631
+ const balances = {};
632
+ const tokenAccounts = {};
633
+ try {
634
+ // Get SOL balance (native token)
635
+ const solBalance = await this.retryWithBackoff(() => this.connection.getBalance(this.getSolanaPublicKey()), maxRetries);
636
+ balances['SOL'] = solBalance / 1e9; // Convert lamports to SOL
637
+ if (includeTokenAccounts) {
638
+ tokenAccounts['SOL'] = this.getSolanaPublicKey().toString();
639
+ }
640
+ // Get SPL token balances using mintAddr from Nord tokens
641
+ if (this.nord.tokens && this.nord.tokens.length > 0) {
642
+ const tokens = this.nord.tokens.filter((token) => !!token.mintAddr);
643
+ // Process tokens in batches to avoid rate limiting
644
+ for (let i = 0; i < tokens.length; i += maxConcurrent) {
645
+ const batch = tokens.slice(i, i + maxConcurrent);
646
+ // Process batch in parallel
647
+ const batchPromises = batch.map(async (token) => {
648
+ try {
649
+ const mint = new web3_js_1.PublicKey(token.mintAddr);
650
+ const associatedTokenAddress = await this.retryWithBackoff(() => (0, spl_token_1.getAssociatedTokenAddress)(mint, this.getSolanaPublicKey()), maxRetries);
651
+ if (includeTokenAccounts) {
652
+ tokenAccounts[token.symbol] = associatedTokenAddress.toString();
653
+ }
654
+ try {
655
+ const tokenBalance = await this.retryWithBackoff(() => this.connection.getTokenAccountBalance(associatedTokenAddress), maxRetries);
656
+ const balance = Number(tokenBalance.value.uiAmount);
657
+ if (balance > 0 || includeZeroBalances) {
658
+ balances[token.symbol] = balance;
659
+ }
660
+ }
661
+ catch (error) {
662
+ // Token account might not exist yet, set balance to 0
663
+ if (includeZeroBalances) {
664
+ balances[token.symbol] = 0;
665
+ }
666
+ }
667
+ }
668
+ catch (error) {
669
+ console.error(`Error getting balance for token ${token.symbol}:`, error);
670
+ if (includeZeroBalances) {
671
+ balances[token.symbol] = 0;
672
+ }
673
+ }
674
+ });
675
+ // Wait for current batch to complete before processing next batch
676
+ await Promise.all(batchPromises);
677
+ }
678
+ }
679
+ return includeTokenAccounts ? { balances, tokenAccounts } : { balances };
680
+ }
681
+ catch (error) {
682
+ throw new NordError_1.NordError('Failed to get Solana token balances', {
683
+ cause: error,
684
+ });
685
+ }
686
+ }
687
+ /**
688
+ * Get the Solana public key derived from the address
689
+ *
690
+ * @returns The Solana public key
691
+ */
692
+ getSolanaPublicKey() {
693
+ try {
694
+ return new web3_js_1.PublicKey(this.address);
695
+ }
696
+ catch (error) {
697
+ throw new NordError_1.NordError('Invalid Solana address', { cause: error });
698
+ }
699
+ }
700
+ }
701
+ exports.NordUser = NordUser;