@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
@@ -1,64 +1,303 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.NordUser = void 0;
7
- const ethers_1 = require("ethers");
8
- const secp256k1_1 = __importDefault(require("secp256k1"));
9
- const const_1 = require("../const");
4
+ const spl_token_1 = require("@solana/spl-token");
5
+ const web3_js_1 = require("@solana/web3.js");
10
6
  const utils_1 = require("../utils");
11
- const abis_1 = require("../abis");
12
7
  const actions_1 = require("./actions");
8
+ const client_1 = require("../bridge/client");
9
+ const utils_2 = require("../bridge/utils");
10
+ const NordError_1 = require("./NordError");
11
+ /**
12
+ * User class for interacting with the Nord protocol
13
+ */
13
14
  class NordUser {
15
+ /**
16
+ * Create a new NordUser instance
17
+ *
18
+ * @param params - Parameters for creating a NordUser
19
+ * @throws {NordError} If required parameters are missing
20
+ */
14
21
  constructor(params) {
22
+ /** User balances by token symbol */
15
23
  this.balances = {};
24
+ /** User orders by market symbol */
16
25
  this.orders = {};
26
+ /** Last timestamp used */
17
27
  this.lastTs = 0;
28
+ /** Last nonce used */
18
29
  this.lastNonce = 0;
30
+ /** SPL token information */
31
+ this.splTokenInfos = [];
32
+ if (!params.nord) {
33
+ throw new NordError_1.NordError("Nord instance is required");
34
+ }
35
+ if (!params.address) {
36
+ throw new NordError_1.NordError("Address is required");
37
+ }
38
+ if (!params.walletSignFn) {
39
+ throw new NordError_1.NordError("Wallet sign function is required");
40
+ }
41
+ if (!params.sessionSignFn) {
42
+ throw new NordError_1.NordError("Session sign function is required");
43
+ }
19
44
  this.nord = params.nord;
20
45
  this.address = params.address;
21
46
  this.walletSignFn = params.walletSignFn;
22
47
  this.sessionSignFn = params.sessionSignFn;
48
+ // Initialize Solana-specific properties if provided
49
+ if (params.solanaPublicKey) {
50
+ this.solanaPublicKey = typeof params.solanaPublicKey === 'string'
51
+ ? new web3_js_1.PublicKey(params.solanaPublicKey)
52
+ : params.solanaPublicKey;
53
+ }
54
+ this.keypair = params.keypair;
55
+ this.connection = params.connection;
56
+ // Convert TokenInfo to SPLTokenInfo if nord has tokenInfos
57
+ if (this.nord.tokenInfos) {
58
+ this.splTokenInfos = this.nord.tokenInfos.map(tokenInfo => ({
59
+ mint: tokenInfo.address, // Use address as mint
60
+ precision: tokenInfo.precision,
61
+ tokenId: tokenInfo.tokenId,
62
+ name: tokenInfo.name
63
+ }));
64
+ }
65
+ // Initialize bridge client if keypair and connection are provided
66
+ if (this.keypair && this.connection && this.nord.solanaProgramId) {
67
+ this.initBridgeClient();
68
+ }
23
69
  }
70
+ /**
71
+ * Create a clone of this NordUser instance
72
+ *
73
+ * @returns A new NordUser instance with the same properties
74
+ */
24
75
  clone() {
25
76
  const newUser = new NordUser({
26
77
  nord: this.nord,
27
78
  address: this.address,
28
79
  walletSignFn: this.walletSignFn,
29
80
  sessionSignFn: this.sessionSignFn,
81
+ solanaPublicKey: this.solanaPublicKey,
82
+ keypair: this.keypair,
83
+ connection: this.connection
30
84
  });
31
85
  newUser.publicKey = this.publicKey;
32
86
  newUser.lastTs = this.lastTs;
33
87
  newUser.lastNonce = this.lastNonce;
34
- newUser.accountIds = this.accountIds;
88
+ newUser.accountIds = this.accountIds ? [...this.accountIds] : undefined;
35
89
  newUser.sessionId = this.sessionId;
90
+ newUser.splTokenInfos = [...this.splTokenInfos];
91
+ // Deep clone balances and orders
92
+ newUser.balances = JSON.parse(JSON.stringify(this.balances));
93
+ newUser.orders = JSON.parse(JSON.stringify(this.orders));
36
94
  return newUser;
37
95
  }
38
96
  /**
39
- * Generates a nonce based on the current timestamp.
40
- * @returns Generated nonce as a number.
97
+ * Initialize the Solana bridge client
98
+ *
99
+ * @private
100
+ * @throws {NordError} If required parameters are missing
41
101
  */
42
- getNonce() {
43
- const ts = Date.now() / 1000;
44
- if (ts === this.lastTs) {
45
- this.lastNonce += 1;
102
+ initBridgeClient() {
103
+ if (!this.keypair || !this.connection || !this.nord.solanaProgramId) {
104
+ throw new NordError_1.NordError('Keypair, connection, and program ID are required to initialize bridge client');
105
+ }
106
+ // Create an Anchor wallet from the keypair
107
+ const wallet = {
108
+ publicKey: this.keypair.publicKey,
109
+ signTransaction: async (tx) => {
110
+ tx.partialSign(this.keypair);
111
+ return tx;
112
+ },
113
+ signAllTransactions: async (txs) => {
114
+ return txs.map(tx => {
115
+ tx.partialSign(this.keypair);
116
+ return tx;
117
+ });
118
+ },
119
+ // Add payer property to satisfy NodeWallet interface
120
+ payer: this.keypair
121
+ };
122
+ // Initialize the bridge client
123
+ this.bridgeClient = new client_1.SolanaBridgeClient({
124
+ rpcUrl: this.connection.rpcEndpoint,
125
+ programId: this.nord.solanaProgramId,
126
+ commitment: 'confirmed',
127
+ tokenInfos: this.splTokenInfos
128
+ }, wallet);
129
+ }
130
+ /**
131
+ * Create a NordUser from a private key
132
+ *
133
+ * @param nord - Nord instance
134
+ * @param privateKey - Private key as string or Uint8Array
135
+ * @param connection - Solana connection (optional)
136
+ * @returns NordUser instance
137
+ * @throws {NordError} If the private key is invalid
138
+ */
139
+ static fromPrivateKey(nord, privateKey, connection) {
140
+ try {
141
+ const keypair = (0, utils_2.keypairFromPrivateKey)(privateKey);
142
+ // Create a signing function that returns Uint8Array
143
+ const walletSignFn = async (message) => {
144
+ const messageBuffer = typeof message === 'string'
145
+ ? Buffer.from(message)
146
+ : Buffer.from(message);
147
+ // Use nacl for signing since Keypair doesn't have a sign method
148
+ // This is a simplified version - in a real implementation, you would use proper signing
149
+ return Buffer.from(keypair.secretKey.slice(0, 64)).toString('hex');
150
+ };
151
+ const sessionSignFn = async (message) => {
152
+ // This is a simplified version - in a real implementation, you would use proper signing
153
+ return new Uint8Array(keypair.secretKey.slice(0, 64));
154
+ };
155
+ return new NordUser({
156
+ nord,
157
+ address: keypair.publicKey.toBase58(),
158
+ walletSignFn,
159
+ sessionSignFn,
160
+ solanaPublicKey: keypair.publicKey,
161
+ keypair,
162
+ connection
163
+ });
164
+ }
165
+ catch (error) {
166
+ throw new NordError_1.NordError("Failed to create NordUser from private key", { cause: error });
167
+ }
168
+ }
169
+ /**
170
+ * Get the associated token account for a token mint
171
+ *
172
+ * @param mint - Token mint address
173
+ * @returns Associated token account address
174
+ * @throws {NordError} If required parameters are missing or operation fails
175
+ */
176
+ async getAssociatedTokenAccount(mint) {
177
+ if (!this.connection || !this.solanaPublicKey) {
178
+ throw new NordError_1.NordError('Connection and Solana public key are required to get associated token account');
46
179
  }
47
- else {
48
- this.lastTs = ts;
49
- this.lastNonce = 0;
180
+ try {
181
+ const associatedTokenAddress = await (0, spl_token_1.getAssociatedTokenAddress)(mint, this.solanaPublicKey);
182
+ try {
183
+ await (0, spl_token_1.getAccount)(this.connection, associatedTokenAddress);
184
+ }
185
+ catch (error) {
186
+ // Account doesn't exist, create it if keypair is available
187
+ if (this.keypair && this.bridgeClient) {
188
+ await this.bridgeClient.createTokenAccountIfNeeded(mint, this.solanaPublicKey, this.keypair);
189
+ }
190
+ }
191
+ return associatedTokenAddress;
192
+ }
193
+ catch (error) {
194
+ throw new NordError_1.NordError(`Failed to get associated token account for mint ${mint.toString()}`, { cause: error });
50
195
  }
51
- return this.lastNonce;
52
196
  }
197
+ /**
198
+ * Deposit SPL tokens to the bridge
199
+ *
200
+ * @param amount - Amount to deposit
201
+ * @param tokenId - Token ID
202
+ * @returns Transaction signature
203
+ * @throws {NordError} If required parameters are missing or operation fails
204
+ */
205
+ async depositSpl(amount, tokenId) {
206
+ if (!this.bridgeClient || !this.keypair || !this.connection || !this.solanaPublicKey) {
207
+ throw new NordError_1.NordError('Bridge client, keypair, connection, and Solana public key are required for deposit');
208
+ }
209
+ try {
210
+ // Find the token info
211
+ const tokenInfo = this.splTokenInfos.find(t => t.tokenId === tokenId);
212
+ if (!tokenInfo) {
213
+ throw new NordError_1.NordError(`Token with ID ${tokenId} not found`);
214
+ }
215
+ const mint = new web3_js_1.PublicKey(tokenInfo.mint);
216
+ // Get the user's token account
217
+ const fromAccount = await this.getAssociatedTokenAccount(mint);
218
+ // Get the bridge's token account
219
+ const [authority] = await this.bridgeClient.findAuthorityPda();
220
+ const toAccount = await (0, spl_token_1.getAssociatedTokenAddress)(mint, authority, true);
221
+ // Convert amount to BN with proper decimals
222
+ const amountBN = (0, utils_1.toBN)(amount, tokenInfo.precision);
223
+ // Deposit tokens
224
+ return await this.bridgeClient.depositSpl({
225
+ amount: amountBN,
226
+ mint,
227
+ fromAccount,
228
+ toAccount
229
+ }, this.keypair);
230
+ }
231
+ catch (error) {
232
+ throw new NordError_1.NordError(`Failed to deposit ${amount} of token ID ${tokenId}`, { cause: error });
233
+ }
234
+ }
235
+ /**
236
+ * Withdraw SPL tokens from the bridge
237
+ *
238
+ * @param claim - Claim data
239
+ * @returns Transaction signature
240
+ * @throws {NordError} If required parameters are missing or operation fails
241
+ */
242
+ async withdrawSpl(claim) {
243
+ if (!this.bridgeClient || !this.keypair || !this.connection || !this.solanaPublicKey) {
244
+ throw new NordError_1.NordError('Bridge client, keypair, connection, and Solana public key are required for withdrawal');
245
+ }
246
+ try {
247
+ // Find the token info
248
+ const tokenInfo = this.splTokenInfos.find(t => t.tokenId === claim.tokenId);
249
+ if (!tokenInfo) {
250
+ throw new NordError_1.NordError(`Token with ID ${claim.tokenId} not found`);
251
+ }
252
+ const mint = new web3_js_1.PublicKey(tokenInfo.mint);
253
+ // Get the user's token account
254
+ const toAccount = await this.getAssociatedTokenAccount(mint);
255
+ // Get the bridge's token account
256
+ const [authority] = await this.bridgeClient.findAuthorityPda();
257
+ const fromAccount = await (0, spl_token_1.getAssociatedTokenAddress)(mint, authority, true);
258
+ // Withdraw tokens
259
+ return await this.bridgeClient.withdraw({
260
+ claim,
261
+ fromAccount,
262
+ toAccount
263
+ }, this.keypair);
264
+ }
265
+ catch (error) {
266
+ throw new NordError_1.NordError("Failed to withdraw SPL tokens", { cause: error });
267
+ }
268
+ }
269
+ /**
270
+ * Get a new nonce for actions
271
+ *
272
+ * @returns Nonce as number
273
+ */
274
+ getNonce() {
275
+ return ++this.lastNonce;
276
+ }
277
+ /**
278
+ * Update account IDs for this user
279
+ *
280
+ * @throws {NordError} If the operation fails
281
+ */
53
282
  async updateAccountId() {
54
- const hexPubkey = ethers_1.ethers
55
- .hexlify((0, utils_1.optExpect)(this.publicKey, "No user public key"))
56
- .slice(2);
57
- const accountIds_ = await (await (0, utils_1.checkedFetch)(`${this.nord.webServerUrl}/user_account_ids?pubkey=${hexPubkey}`)).json();
58
- (0, utils_1.assert)(Array.isArray(accountIds_), "Unexpected response");
59
- const accountIds = accountIds_;
60
- this.accountIds = accountIds;
283
+ try {
284
+ if (!this.publicKey) {
285
+ throw new NordError_1.NordError("Public key is required to update account ID");
286
+ }
287
+ const resp = await this.nord.getUserAccountIds({
288
+ pubkey: Buffer.from(this.publicKey).toString('hex')
289
+ });
290
+ this.accountIds = resp.accountIds;
291
+ }
292
+ catch (error) {
293
+ throw new NordError_1.NordError("Failed to update account ID", { cause: error });
294
+ }
61
295
  }
296
+ /**
297
+ * Fetch user information including balances and orders
298
+ *
299
+ * @throws {NordError} If the operation fails
300
+ */
62
301
  async fetchInfo() {
63
302
  if (this.accountIds !== undefined) {
64
303
  // todo:implement class
@@ -90,160 +329,153 @@ class NordUser {
90
329
  }
91
330
  }
92
331
  }
93
- async setPublicKey() {
94
- const message = "Layer N - Nord";
95
- const msgHash = ethers_1.ethers.hashMessage(message);
96
- const msgHashBytes = ethers_1.ethers.getBytes(msgHash);
97
- const signature = await this.walletSignFn(message);
98
- const recoveredPubKey = ethers_1.SigningKey.recoverPublicKey(msgHashBytes, signature);
99
- const publicKeyBuffer = Buffer.from(recoveredPubKey.slice(2), "hex");
100
- this.publicKey = secp256k1_1.default.publicKeyConvert(publicKeyBuffer, true);
101
- }
102
- async fundEthWallet() {
103
- const provider = new ethers_1.ethers.JsonRpcProvider(this.nord.evmUrl);
104
- const wallet = new ethers_1.ethers.Wallet(const_1.FAUCET_PRIVATE_ADDRESS, provider);
105
- (0, utils_1.assert)(const_1.DEFAULT_FUNDING_AMOUNTS["ETH"] != null);
106
- const ethTx = await wallet.sendTransaction({
107
- to: this.address,
108
- value: ethers_1.ethers.parseEther(const_1.DEFAULT_FUNDING_AMOUNTS["ETH"][0]),
109
- });
110
- await ethTx.wait();
111
- }
112
- async fundErc20Wallet() {
113
- const provider = new ethers_1.ethers.JsonRpcProvider(this.nord.evmUrl);
114
- const wallet = new ethers_1.ethers.Wallet(const_1.FAUCET_PRIVATE_ADDRESS, provider);
115
- (0, utils_1.assert)(const_1.DEFAULT_FUNDING_AMOUNTS["ETH"] != null);
116
- for (const tokenInfo of this.nord.tokenInfos) {
117
- const erc20Contract = new ethers_1.ethers.Contract(tokenInfo.address, abis_1.ERC20_ABI, wallet);
118
- if (const_1.DEFAULT_FUNDING_AMOUNTS[tokenInfo.address]) {
119
- const defaultFundingAmount = const_1.DEFAULT_FUNDING_AMOUNTS[tokenInfo.address];
120
- const tokenTx = await erc20Contract.transfer(this.address, ethers_1.ethers.parseUnits(defaultFundingAmount[0], defaultFundingAmount[1]), {
121
- maxFeePerGas: ethers_1.ethers.parseUnits("30", "gwei"),
122
- maxPriorityFeePerGas: ethers_1.ethers.parseUnits("0.001", "gwei"),
123
- });
124
- await tokenTx.wait();
125
- }
126
- }
127
- }
332
+ /**
333
+ * Refresh the user's session
334
+ *
335
+ * @param sessionPk - Session public key
336
+ * @throws {NordError} If the operation fails
337
+ */
128
338
  async refreshSession(sessionPk) {
129
- this.sessionId = await (0, actions_1.createSession)(this.nord.webServerUrl, this.walletSignFn, await this.nord.impl.getTimestamp(), this.getNonce(), {
339
+ this.sessionId = await (0, actions_1.createSession)(this.nord.webServerUrl, this.walletSignFn, await this.nord.getTimestamp(), this.getNonce(), {
130
340
  userPubkey: (0, utils_1.optExpect)(this.publicKey, "No user's public key"),
131
341
  sessionPubkey: sessionPk,
132
342
  });
133
343
  }
134
344
  /**
135
- * Revokes session previously created by user
345
+ * Revoke a session
136
346
  *
137
- * @param sessionId - session identifier
347
+ * @param sessionId - Session ID to revoke
348
+ * @throws {NordError} If the operation fails
138
349
  */
139
350
  async revokeSession(sessionId) {
140
- return (0, actions_1.revokeSession)(this.nord.webServerUrl, this.walletSignFn, await this.nord.impl.getTimestamp(), this.getNonce(), {
141
- sessionId,
142
- });
143
- }
144
- async deposit(provider, amount, tokenId) {
145
- const erc20 = this.nord.tokenInfos[tokenId];
146
- const erc20Contract = new ethers_1.ethers.Contract(erc20.address, abis_1.ERC20_ABI, await provider.getSigner());
147
- const approveTx = await erc20Contract.approve(this.nord.contractAddress, ethers_1.MaxUint256, {
148
- maxFeePerGas: ethers_1.ethers.parseUnits("30", "gwei"),
149
- maxPriorityFeePerGas: ethers_1.ethers.parseUnits("0.001", "gwei"),
150
- });
151
- await approveTx.wait();
152
- const nordContract = new ethers_1.ethers.Contract(this.nord.contractAddress, abis_1.NORD_RAMP_FACET_ABI, await provider.getSigner());
153
- const depositTx = await nordContract.depositUnchecked(this.publicKey, BigInt(0), ethers_1.ethers.parseUnits(amount.toString(), erc20.precision), {
154
- maxFeePerGas: ethers_1.ethers.parseUnits("30", "gwei"),
155
- maxPriorityFeePerGas: ethers_1.ethers.parseUnits("0.001", "gwei"),
156
- });
157
- await depositTx.wait();
158
- }
159
- async depositApproveTx(provider, amount, tokenId) {
160
- const erc20 = this.nord.tokenInfos[tokenId];
161
- const erc20Contract = new ethers_1.ethers.Contract(erc20.address, abis_1.ERC20_ABI, await provider.getSigner());
162
- const approveTx = await erc20Contract.approve(this.nord.contractAddress, ethers_1.MaxUint256, {
163
- maxFeePerGas: ethers_1.ethers.parseUnits("30", "gwei"),
164
- maxPriorityFeePerGas: ethers_1.ethers.parseUnits("0.001", "gwei"),
165
- });
166
- return approveTx.hash;
167
- }
168
- async depositOnlyTx(provider, amount, tokenId) {
169
- const erc20 = this.nord.tokenInfos[tokenId];
170
- const nordContract = new ethers_1.ethers.Contract(this.nord.contractAddress, abis_1.NORD_RAMP_FACET_ABI, await provider.getSigner());
171
- const depositTx = await nordContract.depositUnchecked(this.publicKey, BigInt(0), ethers_1.ethers.parseUnits(amount.toString(), erc20.precision), {
172
- maxFeePerGas: ethers_1.ethers.parseUnits("30", "gwei"),
173
- maxPriorityFeePerGas: ethers_1.ethers.parseUnits("0.001", "gwei"),
174
- });
175
- return depositTx.hash;
176
- }
177
- async depositEth(provider, amount, tokenId) {
178
- if (tokenId || tokenId == 0) {
179
- const nordContract = new ethers_1.ethers.Contract(this.nord.contractAddress, abis_1.NORD_RAMP_FACET_ABI, await provider.getSigner());
180
- const depositTx = await nordContract.depositUnchecked(this.publicKey, BigInt(1), ethers_1.ethers.parseUnits(amount.toString(), 18), {
181
- maxFeePerGas: ethers_1.ethers.parseUnits("30", "gwei"),
182
- maxPriorityFeePerGas: ethers_1.ethers.parseUnits("0.001", "gwei"),
351
+ try {
352
+ await (0, actions_1.revokeSession)(this.nord.webServerUrl, this.walletSignFn, await this.nord.getTimestamp(), this.getNonce(), {
353
+ sessionId
183
354
  });
184
- await depositTx.wait();
185
355
  }
186
- else {
187
- // todo:implement eth deposits
356
+ catch (error) {
357
+ throw new NordError_1.NordError(`Failed to revoke session ${sessionId}`, { cause: error });
188
358
  }
189
359
  }
360
+ /**
361
+ * Withdraw tokens from the exchange
362
+ *
363
+ * @param tokenId - Token ID to withdraw
364
+ * @param amount - Amount to withdraw
365
+ * @throws {NordError} If the operation fails
366
+ */
190
367
  async withdraw(tokenId, amount) {
191
- (0, actions_1.withdraw)(this.nord.webServerUrl, this.sessionSignFn, await this.nord.impl.getTimestamp(), this.getNonce(), {
192
- sizeDecimals: (0, utils_1.findToken)(this.nord.tokens, tokenId).decimals,
193
- sessionId: (0, utils_1.optExpect)(this.sessionId, "No session"),
194
- tokenId: tokenId,
195
- amount,
196
- });
368
+ try {
369
+ await (0, actions_1.withdraw)(this.nord.webServerUrl, this.sessionSignFn, await this.nord.getTimestamp(), this.getNonce(), {
370
+ sizeDecimals: (0, utils_1.findToken)(this.nord.tokens, tokenId).decimals,
371
+ sessionId: (0, utils_1.optExpect)(this.sessionId, "No session"),
372
+ tokenId: tokenId,
373
+ amount,
374
+ });
375
+ }
376
+ catch (error) {
377
+ throw new NordError_1.NordError(`Failed to withdraw ${amount} of token ID ${tokenId}`, { cause: error });
378
+ }
197
379
  }
380
+ /**
381
+ * Place an order on the exchange
382
+ *
383
+ * @param params - Order parameters
384
+ * @returns Order ID if successful
385
+ * @throws {NordError} If the operation fails
386
+ */
198
387
  async placeOrder(params) {
199
- const market = (0, utils_1.findMarket)(this.nord.markets, params.marketId);
200
- return (0, actions_1.placeOrder)(this.nord.webServerUrl, this.sessionSignFn, await this.nord.impl.getTimestamp(), this.getNonce(), {
201
- sessionId: (0, utils_1.optExpect)(this.sessionId, "No session"),
202
- senderId: params.accountId,
203
- sizeDecimals: market.sizeDecimals,
204
- priceDecimals: market.priceDecimals,
205
- marketId: params.marketId,
206
- side: params.side,
207
- fillMode: params.fillMode,
208
- isReduceOnly: params.isReduceOnly,
209
- size: params.size,
210
- price: params.price,
211
- quoteSize: params.quoteSize,
212
- });
388
+ try {
389
+ const market = (0, utils_1.findMarket)(this.nord.markets, params.marketId);
390
+ if (!market) {
391
+ throw new NordError_1.NordError(`Market with ID ${params.marketId} not found`);
392
+ }
393
+ return (0, actions_1.placeOrder)(this.nord.webServerUrl, this.sessionSignFn, await this.nord.getTimestamp(), this.getNonce(), {
394
+ sessionId: (0, utils_1.optExpect)(this.sessionId, "No session"),
395
+ senderId: params.accountId,
396
+ sizeDecimals: market.sizeDecimals,
397
+ priceDecimals: market.priceDecimals,
398
+ marketId: params.marketId,
399
+ side: params.side,
400
+ fillMode: params.fillMode,
401
+ isReduceOnly: params.isReduceOnly,
402
+ size: params.size,
403
+ price: params.price,
404
+ quoteSize: params.quoteSize,
405
+ });
406
+ }
407
+ catch (error) {
408
+ throw new NordError_1.NordError("Failed to place order", { cause: error });
409
+ }
213
410
  }
411
+ /**
412
+ * Cancel an order
413
+ *
414
+ * @param orderId - Order ID to cancel
415
+ * @param accountId - Account ID that placed the order
416
+ * @returns Action ID if successful
417
+ * @throws {NordError} If the operation fails
418
+ */
214
419
  async cancelOrder(orderId, accountId) {
215
- return (0, actions_1.cancelOrder)(this.nord.webServerUrl, this.sessionSignFn, await this.nord.impl.getTimestamp(), this.getNonce(), {
216
- sessionId: (0, utils_1.optExpect)(this.sessionId, "No session"),
217
- senderId: accountId,
218
- orderId,
219
- });
420
+ try {
421
+ return (0, actions_1.cancelOrder)(this.nord.webServerUrl, this.sessionSignFn, await this.nord.getTimestamp(), this.getNonce(), {
422
+ sessionId: (0, utils_1.optExpect)(this.sessionId, "No session"),
423
+ senderId: accountId,
424
+ orderId,
425
+ });
426
+ }
427
+ catch (error) {
428
+ throw new NordError_1.NordError(`Failed to cancel order ${orderId}`, { cause: error });
429
+ }
220
430
  }
431
+ /**
432
+ * Transfer tokens to another account
433
+ *
434
+ * @param params - Transfer parameters
435
+ * @throws {NordError} If the operation fails
436
+ */
221
437
  async transferToAccount(params) {
222
- const token = (0, utils_1.findToken)(this.nord.tokens, params.tokenId);
223
- await (0, actions_1.transfer)(this.nord.webServerUrl, this.sessionSignFn, await this.nord.impl.getTimestamp(), this.getNonce(), {
224
- sessionId: (0, utils_1.optExpect)(this.sessionId, "No session"),
225
- fromAccountId: (0, utils_1.optExpect)(params.fromAccountId, "No source account"),
226
- toAccountId: (0, utils_1.optExpect)(params.toAccountId, "No target account"),
227
- tokenId: params.tokenId,
228
- tokenDecimals: token.decimals,
229
- amount: params.amount,
230
- });
438
+ try {
439
+ const token = (0, utils_1.findToken)(this.nord.tokens, params.tokenId);
440
+ await (0, actions_1.transfer)(this.nord.webServerUrl, this.sessionSignFn, await this.nord.getTimestamp(), this.getNonce(), {
441
+ sessionId: (0, utils_1.optExpect)(this.sessionId, "No session"),
442
+ fromAccountId: (0, utils_1.optExpect)(params.fromAccountId, "No source account"),
443
+ toAccountId: (0, utils_1.optExpect)(params.toAccountId, "No target account"),
444
+ tokenId: params.tokenId,
445
+ tokenDecimals: token.decimals,
446
+ amount: params.amount,
447
+ });
448
+ }
449
+ catch (error) {
450
+ throw new NordError_1.NordError("Failed to transfer tokens", { cause: error });
451
+ }
231
452
  }
453
+ /**
454
+ * Create a new account
455
+ *
456
+ * @param params - Account creation parameters
457
+ * @returns New NordUser instance
458
+ * @throws {NordError} If the operation fails
459
+ */
232
460
  async createAccount(params) {
233
- const token = (0, utils_1.findToken)(this.nord.tokens, params.tokenId);
234
- const maybeToAccountId = await (0, actions_1.transfer)(this.nord.webServerUrl, this.sessionSignFn, await this.nord.impl.getTimestamp(), this.getNonce(), {
235
- sessionId: (0, utils_1.optExpect)(this.sessionId, "No session"),
236
- fromAccountId: (0, utils_1.optExpect)(this.accountIds?.[0], "No source account"),
237
- toAccountId: undefined,
238
- tokenId: params.tokenId,
239
- tokenDecimals: token.decimals,
240
- amount: params.amount,
241
- });
242
- const toAccountId = (0, utils_1.optExpect)(maybeToAccountId, "New account should have been created");
243
- const newUser = this.clone();
244
- newUser.accountIds?.push(toAccountId);
245
- await newUser.fetchInfo();
246
- return newUser;
461
+ try {
462
+ // Create a new keypair for the account
463
+ const keypair = web3_js_1.Keypair.generate();
464
+ // Create a new NordUser
465
+ const newUser = NordUser.fromPrivateKey(this.nord, keypair.secretKey, this.connection);
466
+ // Transfer initial funds
467
+ await this.transferToAccount({
468
+ to: newUser,
469
+ tokenId: params.tokenId,
470
+ amount: params.amount,
471
+ fromAccountId: (0, utils_1.optExpect)(this.accountIds?.[0], "No account ID"),
472
+ toAccountId: (0, utils_1.optExpect)(newUser.accountIds?.[0], "No account ID for new user"),
473
+ });
474
+ return newUser;
475
+ }
476
+ catch (error) {
477
+ throw new NordError_1.NordError("Failed to create account", { cause: error });
478
+ }
247
479
  }
248
480
  }
249
481
  exports.NordUser = NordUser;
@@ -0,0 +1,37 @@
1
+ import { EventEmitter } from "events";
2
+ import { DeltaEvent, Trades, Account, SubscriberConfig, OrderbookResponse, Trade } from "../types";
3
+ /**
4
+ * Subscriber class for handling WebSocket subscriptions
5
+ */
6
+ export declare class Subscriber {
7
+ streamURL: string;
8
+ buffer: (DeltaEvent | Trades | Account)[];
9
+ maxBufferLen: number;
10
+ /**
11
+ * Create a new Subscriber instance
12
+ * @param config Subscriber configuration
13
+ */
14
+ constructor(config: SubscriberConfig);
15
+ /**
16
+ * Subscribe to WebSocket events
17
+ */
18
+ subscribe(): void;
19
+ }
20
+ /**
21
+ * Interface for orderbook subscription
22
+ */
23
+ export interface OrderbookSubscription extends EventEmitter {
24
+ on(event: 'message', listener: (data: OrderbookResponse) => void): this;
25
+ on(event: 'error', listener: (error: Error) => void): this;
26
+ close(): void;
27
+ removeAllListeners(event?: string): this;
28
+ }
29
+ /**
30
+ * Interface for trade subscription
31
+ */
32
+ export interface TradeSubscription extends EventEmitter {
33
+ on(event: 'message', listener: (data: Trade[]) => void): this;
34
+ on(event: 'error', listener: (error: Error) => void): this;
35
+ close(): void;
36
+ removeAllListeners(event?: string): this;
37
+ }