@nktkas/hyperliquid 0.23.1 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. package/CONTRIBUTING.md +3 -2
  2. package/README.md +154 -170
  3. package/esm/mod.d.ts +1 -1
  4. package/esm/mod.d.ts.map +1 -1
  5. package/esm/src/base.d.ts +0 -5
  6. package/esm/src/base.d.ts.map +1 -1
  7. package/esm/src/clients/exchange.d.ts +430 -393
  8. package/esm/src/clients/exchange.d.ts.map +1 -1
  9. package/esm/src/clients/exchange.js +467 -927
  10. package/esm/src/clients/info.d.ts +228 -203
  11. package/esm/src/clients/info.d.ts.map +1 -1
  12. package/esm/src/clients/info.js +236 -368
  13. package/esm/src/clients/multiSign.d.ts +14 -1184
  14. package/esm/src/clients/multiSign.d.ts.map +1 -1
  15. package/esm/src/clients/multiSign.js +37 -2004
  16. package/esm/src/clients/subscription.d.ts +95 -93
  17. package/esm/src/clients/subscription.d.ts.map +1 -1
  18. package/esm/src/clients/subscription.js +101 -146
  19. package/esm/src/signing/_signTypedData/ethers.d.ts +16 -4
  20. package/esm/src/signing/_signTypedData/ethers.d.ts.map +1 -1
  21. package/esm/src/signing/_signTypedData/ethers.js +1 -1
  22. package/esm/src/signing/_signTypedData/mod.d.ts +12 -12
  23. package/esm/src/signing/_signTypedData/mod.d.ts.map +1 -1
  24. package/esm/src/signing/_signTypedData/mod.js +52 -24
  25. package/esm/src/signing/_signTypedData/private_key.d.ts +6 -5
  26. package/esm/src/signing/_signTypedData/private_key.d.ts.map +1 -1
  27. package/esm/src/signing/_signTypedData/private_key.js +40 -19
  28. package/esm/src/signing/_signTypedData/viem.d.ts +27 -6
  29. package/esm/src/signing/_signTypedData/viem.d.ts.map +1 -1
  30. package/esm/src/signing/_signTypedData/viem.js +1 -1
  31. package/esm/src/signing/_sorter.d.ts +12 -21
  32. package/esm/src/signing/_sorter.d.ts.map +1 -1
  33. package/esm/src/signing/_sorter.js +30 -63
  34. package/esm/src/signing/mod.d.ts +177 -127
  35. package/esm/src/signing/mod.d.ts.map +1 -1
  36. package/esm/src/signing/mod.js +182 -130
  37. package/esm/src/transports/base.d.ts +2 -1
  38. package/esm/src/transports/base.d.ts.map +1 -1
  39. package/esm/src/transports/http/http_transport.d.ts +3 -2
  40. package/esm/src/transports/http/http_transport.d.ts.map +1 -1
  41. package/esm/src/transports/http/http_transport.js +4 -4
  42. package/esm/src/transports/websocket/_hyperliquid_event_target.d.ts +14 -6
  43. package/esm/src/transports/websocket/_hyperliquid_event_target.d.ts.map +1 -1
  44. package/esm/src/transports/websocket/_hyperliquid_event_target.js +1 -2
  45. package/esm/src/transports/websocket/_reconnecting_websocket.d.ts +2 -1
  46. package/esm/src/transports/websocket/_reconnecting_websocket.d.ts.map +1 -1
  47. package/esm/src/transports/websocket/_reconnecting_websocket.js +1 -0
  48. package/esm/src/transports/websocket/_websocket_async_request.d.ts.map +1 -1
  49. package/esm/src/transports/websocket/_websocket_async_request.js +17 -21
  50. package/esm/src/transports/websocket/websocket_transport.d.ts +4 -4
  51. package/esm/src/transports/websocket/websocket_transport.d.ts.map +1 -1
  52. package/esm/src/transports/websocket/websocket_transport.js +6 -6
  53. package/esm/src/types/exchange/requests.d.ts +492 -306
  54. package/esm/src/types/exchange/requests.d.ts.map +1 -1
  55. package/esm/src/types/exchange/responses.d.ts +105 -25
  56. package/esm/src/types/exchange/responses.d.ts.map +1 -1
  57. package/esm/src/types/explorer/requests.d.ts +3 -3
  58. package/esm/src/types/explorer/requests.d.ts.map +1 -1
  59. package/esm/src/types/explorer/responses.d.ts +1 -1
  60. package/esm/src/types/explorer/responses.d.ts.map +1 -1
  61. package/esm/src/types/info/accounts.d.ts +403 -98
  62. package/esm/src/types/info/accounts.d.ts.map +1 -1
  63. package/esm/src/types/info/assets.d.ts +131 -35
  64. package/esm/src/types/info/assets.d.ts.map +1 -1
  65. package/esm/src/types/info/markets.d.ts +29 -8
  66. package/esm/src/types/info/markets.d.ts.map +1 -1
  67. package/esm/src/types/info/orders.d.ts +62 -17
  68. package/esm/src/types/info/orders.d.ts.map +1 -1
  69. package/esm/src/types/info/requests.d.ts +117 -51
  70. package/esm/src/types/info/requests.d.ts.map +1 -1
  71. package/esm/src/types/info/validators.d.ts +44 -14
  72. package/esm/src/types/info/validators.d.ts.map +1 -1
  73. package/esm/src/types/info/vaults.d.ts +25 -10
  74. package/esm/src/types/info/vaults.d.ts.map +1 -1
  75. package/esm/src/types/mod.d.ts +1 -1
  76. package/esm/src/types/mod.d.ts.map +1 -1
  77. package/esm/src/types/subscriptions/requests.d.ts +21 -66
  78. package/esm/src/types/subscriptions/requests.d.ts.map +1 -1
  79. package/esm/src/types/subscriptions/responses.d.ts +46 -55
  80. package/esm/src/types/subscriptions/responses.d.ts.map +1 -1
  81. package/package.json +2 -3
  82. package/script/mod.d.ts +1 -1
  83. package/script/mod.d.ts.map +1 -1
  84. package/script/src/base.d.ts +0 -5
  85. package/script/src/base.d.ts.map +1 -1
  86. package/script/src/clients/exchange.d.ts +430 -393
  87. package/script/src/clients/exchange.d.ts.map +1 -1
  88. package/script/src/clients/exchange.js +466 -926
  89. package/script/src/clients/info.d.ts +228 -203
  90. package/script/src/clients/info.d.ts.map +1 -1
  91. package/script/src/clients/info.js +236 -368
  92. package/script/src/clients/multiSign.d.ts +14 -1184
  93. package/script/src/clients/multiSign.d.ts.map +1 -1
  94. package/script/src/clients/multiSign.js +38 -2005
  95. package/script/src/clients/subscription.d.ts +95 -93
  96. package/script/src/clients/subscription.d.ts.map +1 -1
  97. package/script/src/clients/subscription.js +101 -146
  98. package/script/src/signing/_signTypedData/ethers.d.ts +16 -4
  99. package/script/src/signing/_signTypedData/ethers.d.ts.map +1 -1
  100. package/script/src/signing/_signTypedData/ethers.js +2 -2
  101. package/script/src/signing/_signTypedData/mod.d.ts +12 -12
  102. package/script/src/signing/_signTypedData/mod.d.ts.map +1 -1
  103. package/script/src/signing/_signTypedData/mod.js +51 -26
  104. package/script/src/signing/_signTypedData/private_key.d.ts +6 -5
  105. package/script/src/signing/_signTypedData/private_key.d.ts.map +1 -1
  106. package/script/src/signing/_signTypedData/private_key.js +40 -18
  107. package/script/src/signing/_signTypedData/viem.d.ts +27 -6
  108. package/script/src/signing/_signTypedData/viem.d.ts.map +1 -1
  109. package/script/src/signing/_signTypedData/viem.js +2 -2
  110. package/script/src/signing/_sorter.d.ts +12 -21
  111. package/script/src/signing/_sorter.d.ts.map +1 -1
  112. package/script/src/signing/_sorter.js +30 -63
  113. package/script/src/signing/mod.d.ts +177 -127
  114. package/script/src/signing/mod.d.ts.map +1 -1
  115. package/script/src/signing/mod.js +185 -148
  116. package/script/src/transports/base.d.ts +2 -1
  117. package/script/src/transports/base.d.ts.map +1 -1
  118. package/script/src/transports/http/http_transport.d.ts +3 -2
  119. package/script/src/transports/http/http_transport.d.ts.map +1 -1
  120. package/script/src/transports/http/http_transport.js +4 -4
  121. package/script/src/transports/websocket/_hyperliquid_event_target.d.ts +14 -6
  122. package/script/src/transports/websocket/_hyperliquid_event_target.d.ts.map +1 -1
  123. package/script/src/transports/websocket/_hyperliquid_event_target.js +1 -2
  124. package/script/src/transports/websocket/_reconnecting_websocket.d.ts +2 -1
  125. package/script/src/transports/websocket/_reconnecting_websocket.d.ts.map +1 -1
  126. package/script/src/transports/websocket/_reconnecting_websocket.js +1 -0
  127. package/script/src/transports/websocket/_websocket_async_request.d.ts.map +1 -1
  128. package/script/src/transports/websocket/_websocket_async_request.js +17 -21
  129. package/script/src/transports/websocket/websocket_transport.d.ts +4 -4
  130. package/script/src/transports/websocket/websocket_transport.d.ts.map +1 -1
  131. package/script/src/transports/websocket/websocket_transport.js +6 -6
  132. package/script/src/types/exchange/requests.d.ts +492 -306
  133. package/script/src/types/exchange/requests.d.ts.map +1 -1
  134. package/script/src/types/exchange/responses.d.ts +105 -25
  135. package/script/src/types/exchange/responses.d.ts.map +1 -1
  136. package/script/src/types/explorer/requests.d.ts +3 -3
  137. package/script/src/types/explorer/requests.d.ts.map +1 -1
  138. package/script/src/types/explorer/responses.d.ts +1 -1
  139. package/script/src/types/explorer/responses.d.ts.map +1 -1
  140. package/script/src/types/info/accounts.d.ts +403 -98
  141. package/script/src/types/info/accounts.d.ts.map +1 -1
  142. package/script/src/types/info/assets.d.ts +131 -35
  143. package/script/src/types/info/assets.d.ts.map +1 -1
  144. package/script/src/types/info/markets.d.ts +29 -8
  145. package/script/src/types/info/markets.d.ts.map +1 -1
  146. package/script/src/types/info/orders.d.ts +62 -17
  147. package/script/src/types/info/orders.d.ts.map +1 -1
  148. package/script/src/types/info/requests.d.ts +117 -51
  149. package/script/src/types/info/requests.d.ts.map +1 -1
  150. package/script/src/types/info/validators.d.ts +44 -14
  151. package/script/src/types/info/validators.d.ts.map +1 -1
  152. package/script/src/types/info/vaults.d.ts +25 -10
  153. package/script/src/types/info/vaults.d.ts.map +1 -1
  154. package/script/src/types/mod.d.ts +1 -1
  155. package/script/src/types/mod.d.ts.map +1 -1
  156. package/script/src/types/subscriptions/requests.d.ts +21 -66
  157. package/script/src/types/subscriptions/requests.d.ts.map +1 -1
  158. package/script/src/types/subscriptions/responses.d.ts +46 -55
  159. package/script/src/types/subscriptions/responses.d.ts.map +1 -1
  160. package/esm/src/signing/_signTypedData/window.d.ts +0 -29
  161. package/esm/src/signing/_signTypedData/window.d.ts.map +0 -1
  162. package/esm/src/signing/_signTypedData/window.js +0 -30
  163. package/script/src/signing/_signTypedData/window.d.ts +0 -29
  164. package/script/src/signing/_signTypedData/window.d.ts.map +0 -1
  165. package/script/src/signing/_signTypedData/window.js +0 -34
@@ -1,6 +1,6 @@
1
1
  import { HyperliquidError } from "../base.js";
2
- import { actionSorter, isAbstractEthersSigner, isAbstractEthersV5Signer, isAbstractViemWalletClient, isAbstractWindowEthereum, signL1Action, signMultiSigAction, signUserSignedAction, userSignedActionEip712Types, } from "../signing/mod.js";
3
- /** Error thrown when the API returns an error response. */
2
+ import { actionSorter, getWalletChainId, signL1Action, signMultiSigAction, signUserSignedAction, userSignedActionEip712Types, } from "../signing/mod.js";
3
+ /** Custom error class for API request errors. */
4
4
  export class ApiRequestError extends HyperliquidError {
5
5
  response;
6
6
  constructor(response) {
@@ -114,15 +114,6 @@ export class ExchangeClient {
114
114
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
115
115
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
116
116
  * ```
117
- *
118
- * @example External wallet (e.g. MetaMask) via [`window.ethereum`](https://eips.ethereum.org/EIPS/eip-1193)
119
- * ```ts
120
- * import * as hl from "@nktkas/hyperliquid";
121
- *
122
- * const ethereum = (window as any).ethereum;
123
- * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
124
- * const exchClient = new hl.ExchangeClient({ wallet: ethereum, transport });
125
- * ```
126
117
  */
127
118
  constructor(args) {
128
119
  this.transport = args.transport;
@@ -130,13 +121,13 @@ export class ExchangeClient {
130
121
  this.isTestnet = args.isTestnet ?? false;
131
122
  this.defaultVaultAddress = args.defaultVaultAddress;
132
123
  this.defaultExpiresAfter = args.defaultExpiresAfter;
133
- this.signatureChainId = args.signatureChainId ?? this._guessSignatureChainId;
124
+ this.signatureChainId = args.signatureChainId ?? (() => getWalletChainId(this.wallet));
134
125
  this.nonceManager = args.nonceManager ?? new NonceManager().getNonce;
135
126
  }
136
127
  /**
137
128
  * Approve an agent to sign on behalf of the master account.
138
- * @param args - The parameters for the request.
139
- * @param signal - An optional abort signal
129
+ * @param params - Action-specific parameters.
130
+ * @param opts - Request execution options.
140
131
  * @returns Successful response without specific data.
141
132
  *
142
133
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -147,42 +138,27 @@ export class ExchangeClient {
147
138
  * ```ts
148
139
  * import * as hl from "@nktkas/hyperliquid";
149
140
  *
150
- * const privateKey = "0x..."; // or `viem`, `ethers`
141
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
151
142
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
152
143
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
153
144
  *
154
145
  * await exchClient.approveAgent({ agentAddress: "0x...", agentName: "..." });
155
146
  * ```
156
147
  */
157
- async approveAgent(args, signal) {
158
- // Destructure the parameters
159
- const { ...actionArgs } = args;
160
- // Construct an action
161
- const nonce = await this.nonceManager();
148
+ async approveAgent(params, opts) {
162
149
  const action = actionSorter.approveAgent({
163
150
  type: "approveAgent",
164
151
  hyperliquidChain: this._getHyperliquidChain(),
165
152
  signatureChainId: await this._getSignatureChainId(),
166
- nonce,
167
- ...actionArgs,
168
- });
169
- // Sign the action
170
- const signature = await signUserSignedAction({
171
- wallet: this.wallet,
172
- action,
173
- types: userSignedActionEip712Types[action.type],
153
+ nonce: await this.nonceManager(),
154
+ ...params,
174
155
  });
175
- if (action.agentName === "")
176
- action.agentName = null;
177
- // Send a request
178
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
179
- this._validateResponse(response);
180
- return response;
156
+ return await this._executeUserSignedAction({ action }, opts?.signal);
181
157
  }
182
158
  /**
183
159
  * Approve a maximum fee rate for a builder.
184
- * @param args - The parameters for the request.
185
- * @param signal - An optional abort signal.
160
+ * @param params - Action-specific parameters.
161
+ * @param opts - Request execution options.
186
162
  * @returns Successful response without specific data.
187
163
  *
188
164
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -193,40 +169,27 @@ export class ExchangeClient {
193
169
  * ```ts
194
170
  * import * as hl from "@nktkas/hyperliquid";
195
171
  *
196
- * const privateKey = "0x..."; // or `viem`, `ethers`
172
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
197
173
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
198
174
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
199
175
  *
200
176
  * await exchClient.approveBuilderFee({ maxFeeRate: "0.01%", builder: "0x..." });
201
177
  * ```
202
178
  */
203
- async approveBuilderFee(args, signal) {
204
- // Destructure the parameters
205
- const { ...actionArgs } = args;
206
- // Construct an action
207
- const nonce = await this.nonceManager();
179
+ async approveBuilderFee(params, opts) {
208
180
  const action = actionSorter.approveBuilderFee({
209
181
  type: "approveBuilderFee",
210
182
  hyperliquidChain: this._getHyperliquidChain(),
211
183
  signatureChainId: await this._getSignatureChainId(),
212
- nonce,
213
- ...actionArgs,
214
- });
215
- // Sign the action
216
- const signature = await signUserSignedAction({
217
- wallet: this.wallet,
218
- action,
219
- types: userSignedActionEip712Types[action.type],
184
+ nonce: await this.nonceManager(),
185
+ ...params,
220
186
  });
221
- // Send a request
222
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
223
- this._validateResponse(response);
224
- return response;
187
+ return await this._executeUserSignedAction({ action }, opts?.signal);
225
188
  }
226
189
  /**
227
190
  * Modify multiple orders.
228
- * @param args - The parameters for the request.
229
- * @param signal - An optional abort signal.
191
+ * @param params - Action-specific parameters.
192
+ * @param opts - Request execution options.
230
193
  * @returns Successful variant of {@link OrderResponse} without error statuses.
231
194
  *
232
195
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -237,7 +200,7 @@ export class ExchangeClient {
237
200
  * ```ts
238
201
  * import * as hl from "@nktkas/hyperliquid";
239
202
  *
240
- * const privateKey = "0x..."; // or `viem`, `ethers`
203
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
241
204
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
242
205
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
243
206
  *
@@ -258,30 +221,19 @@ export class ExchangeClient {
258
221
  * });
259
222
  * ```
260
223
  */
261
- async batchModify(args, signal) {
262
- // Destructure the parameters
263
- const { vaultAddress = this.defaultVaultAddress, expiresAfter = await this._getDefaultExpiresAfter(), ...actionArgs } = args;
264
- // Construct an action
265
- const nonce = await this.nonceManager();
266
- const action = actionSorter.batchModify({ type: "batchModify", ...actionArgs });
267
- // Sign the action
268
- const signature = await signL1Action({
269
- wallet: this.wallet,
270
- action,
271
- nonce,
272
- isTestnet: this.isTestnet,
273
- vaultAddress,
274
- expiresAfter,
224
+ async batchModify(params, opts) {
225
+ const action = actionSorter.batchModify({
226
+ type: "batchModify",
227
+ ...params,
275
228
  });
276
- // Send a request
277
- const response = await this.transport.request("exchange", { action, signature, nonce, vaultAddress, expiresAfter }, signal);
278
- this._validateResponse(response);
279
- return response;
229
+ const vaultAddress = opts?.vaultAddress ?? this.defaultVaultAddress;
230
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
231
+ return await this._executeL1Action({ action, vaultAddress, expiresAfter }, opts?.signal);
280
232
  }
281
233
  /**
282
234
  * Cancel order(s).
283
- * @param args - The parameters for the request.
284
- * @param signal - An optional abort signal.
235
+ * @param params - Action-specific parameters.
236
+ * @param opts - Request execution options.
285
237
  * @returns Successful variant of {@link CancelResponse} without error statuses.
286
238
  *
287
239
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -292,7 +244,7 @@ export class ExchangeClient {
292
244
  * ```ts
293
245
  * import * as hl from "@nktkas/hyperliquid";
294
246
  *
295
- * const privateKey = "0x..."; // or `viem`, `ethers`
247
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
296
248
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
297
249
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
298
250
  *
@@ -303,30 +255,19 @@ export class ExchangeClient {
303
255
  * });
304
256
  * ```
305
257
  */
306
- async cancel(args, signal) {
307
- // Destructure the parameters
308
- const { vaultAddress = this.defaultVaultAddress, expiresAfter = await this._getDefaultExpiresAfter(), ...actionArgs } = args;
309
- // Construct an action
310
- const nonce = await this.nonceManager();
311
- const action = actionSorter.cancel({ type: "cancel", ...actionArgs });
312
- // Sign the action
313
- const signature = await signL1Action({
314
- wallet: this.wallet,
315
- action,
316
- nonce,
317
- isTestnet: this.isTestnet,
318
- vaultAddress,
319
- expiresAfter,
258
+ async cancel(params, opts) {
259
+ const action = actionSorter.cancel({
260
+ type: "cancel",
261
+ ...params,
320
262
  });
321
- // Send a request
322
- const response = await this.transport.request("exchange", { action, signature, nonce, vaultAddress, expiresAfter }, signal);
323
- this._validateResponse(response);
324
- return response;
263
+ const vaultAddress = opts?.vaultAddress ?? this.defaultVaultAddress;
264
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
265
+ return await this._executeL1Action({ action, vaultAddress, expiresAfter }, opts?.signal);
325
266
  }
326
267
  /**
327
268
  * Cancel order(s) by cloid.
328
- * @param args - The parameters for the request.
329
- * @param signal - An optional abort signal.
269
+ * @param params - Action-specific parameters.
270
+ * @param opts - Request execution options.
330
271
  * @returns Successful variant of {@link CancelResponse} without error statuses.
331
272
  *
332
273
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -337,7 +278,7 @@ export class ExchangeClient {
337
278
  * ```ts
338
279
  * import * as hl from "@nktkas/hyperliquid";
339
280
  *
340
- * const privateKey = "0x..."; // or `viem`, `ethers`
281
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
341
282
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
342
283
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
343
284
  *
@@ -348,30 +289,19 @@ export class ExchangeClient {
348
289
  * });
349
290
  * ```
350
291
  */
351
- async cancelByCloid(args, signal) {
352
- // Destructure the parameters
353
- const { vaultAddress = this.defaultVaultAddress, expiresAfter = await this._getDefaultExpiresAfter(), ...actionArgs } = args;
354
- // Construct an action
355
- const nonce = await this.nonceManager();
356
- const action = actionSorter.cancelByCloid({ type: "cancelByCloid", ...actionArgs });
357
- // Sign the action
358
- const signature = await signL1Action({
359
- wallet: this.wallet,
360
- action,
361
- nonce,
362
- isTestnet: this.isTestnet,
363
- vaultAddress,
364
- expiresAfter,
292
+ async cancelByCloid(params, opts) {
293
+ const action = actionSorter.cancelByCloid({
294
+ type: "cancelByCloid",
295
+ ...params,
365
296
  });
366
- // Send a request
367
- const response = await this.transport.request("exchange", { action, signature, nonce, vaultAddress, expiresAfter }, signal);
368
- this._validateResponse(response);
369
- return response;
297
+ const vaultAddress = opts?.vaultAddress ?? this.defaultVaultAddress;
298
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
299
+ return await this._executeL1Action({ action, vaultAddress, expiresAfter }, opts?.signal);
370
300
  }
371
301
  /**
372
302
  * Transfer native token from the user's spot account into staking for delegating to validators.
373
- * @param args - The parameters for the request.
374
- * @param signal - An optional abort signal.
303
+ * @param params - Action-specific parameters.
304
+ * @param opts - Request execution options.
375
305
  * @returns Successful response without specific data.
376
306
  *
377
307
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -382,40 +312,26 @@ export class ExchangeClient {
382
312
  * ```ts
383
313
  * import * as hl from "@nktkas/hyperliquid";
384
314
  *
385
- * const privateKey = "0x..."; // or `viem`, `ethers`
315
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
386
316
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
387
317
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
388
318
  *
389
319
  * await exchClient.cDeposit({ wei: 1 * 1e8 });
390
320
  * ```
391
321
  */
392
- async cDeposit(args, signal) {
393
- // Destructure the parameters
394
- const { ...actionArgs } = args;
395
- // Construct an action
396
- const nonce = await this.nonceManager();
322
+ async cDeposit(params, opts) {
397
323
  const action = actionSorter.cDeposit({
398
324
  type: "cDeposit",
399
325
  hyperliquidChain: this._getHyperliquidChain(),
400
326
  signatureChainId: await this._getSignatureChainId(),
401
- nonce,
402
- ...actionArgs,
403
- });
404
- // Sign the action
405
- const signature = await signUserSignedAction({
406
- wallet: this.wallet,
407
- action,
408
- types: userSignedActionEip712Types[action.type],
327
+ nonce: await this.nonceManager(),
328
+ ...params,
409
329
  });
410
- // Send a request
411
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
412
- this._validateResponse(response);
413
- return response;
330
+ return await this._executeUserSignedAction({ action }, opts?.signal);
414
331
  }
415
332
  /**
416
333
  * Claim rewards from referral program.
417
- * @param args - The parameters for the request.
418
- * @param signal - An optional abort signal.
334
+ * @param opts - Request execution options.
419
335
  * @returns Successful response without specific data.
420
336
  *
421
337
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -426,33 +342,24 @@ export class ExchangeClient {
426
342
  * ```ts
427
343
  * import * as hl from "@nktkas/hyperliquid";
428
344
  *
429
- * const privateKey = "0x..."; // or `viem`, `ethers`
345
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
430
346
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
431
347
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
432
348
  *
433
349
  * await exchClient.claimRewards();
434
350
  * ```
435
351
  */
436
- async claimRewards(signal) {
437
- // Construct an action
438
- const nonce = await this.nonceManager();
439
- const action = actionSorter.claimRewards({ type: "claimRewards" });
440
- // Sign the action
441
- const signature = await signL1Action({
442
- wallet: this.wallet,
443
- action,
444
- nonce,
445
- isTestnet: this.isTestnet,
352
+ async claimRewards(opts) {
353
+ const action = actionSorter.claimRewards({
354
+ type: "claimRewards",
446
355
  });
447
- // Send a request
448
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
449
- this._validateResponse(response);
450
- return response;
356
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
357
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
451
358
  }
452
359
  /**
453
360
  * Convert a single-signature account to a multi-signature account or vice versa.
454
- * @param args - The parameters for the request.
455
- * @param signal - An optional abort signal.
361
+ * @param params - Action-specific parameters.
362
+ * @param opts - Request execution options.
456
363
  * @returns Successful response without specific data.
457
364
  *
458
365
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -463,47 +370,36 @@ export class ExchangeClient {
463
370
  * ```ts
464
371
  * import * as hl from "@nktkas/hyperliquid";
465
372
  *
466
- * const privateKey = "0x..."; // or `viem`, `ethers`
373
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
467
374
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
468
375
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
469
376
  *
470
377
  * // Convert to multi-sig user
471
378
  * await exchClient.convertToMultiSigUser({
472
- * authorizedUsers: ["0x...", "0x...", "0x..."],
473
- * threshold: 2,
379
+ * signers: {
380
+ * authorizedUsers: ["0x...", "0x...", "0x..."],
381
+ * threshold: 2,
382
+ * },
474
383
  * });
475
384
  *
476
385
  * // Convert to single-sig user
477
- * await exchClient.convertToMultiSigUser(null);
386
+ * await exchClient.convertToMultiSigUser({ signers: null });
478
387
  * ```
479
388
  */
480
- async convertToMultiSigUser(args, signal) {
481
- // Destructure the parameters
482
- const actionArgs = args;
483
- // Construct an action
484
- const nonce = await this.nonceManager();
389
+ async convertToMultiSigUser(params, opts) {
485
390
  const action = actionSorter.convertToMultiSigUser({
486
391
  type: "convertToMultiSigUser",
487
392
  hyperliquidChain: this._getHyperliquidChain(),
488
393
  signatureChainId: await this._getSignatureChainId(),
489
- signers: JSON.stringify(actionArgs),
490
- nonce,
491
- });
492
- // Sign the action
493
- const signature = await signUserSignedAction({
494
- wallet: this.wallet,
495
- action,
496
- types: userSignedActionEip712Types[action.type],
394
+ nonce: await this.nonceManager(),
395
+ ...params,
497
396
  });
498
- // Send a request
499
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
500
- this._validateResponse(response);
501
- return response;
397
+ return await this._executeUserSignedAction({ action }, opts?.signal);
502
398
  }
503
399
  /**
504
400
  * Create a sub-account.
505
- * @param args - The parameters for the request.
506
- * @param signal - An optional abort signal.
401
+ * @param params - Action-specific parameters.
402
+ * @param opts - Request execution options.
507
403
  * @returns Response for creating a sub-account.
508
404
  *
509
405
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -514,35 +410,25 @@ export class ExchangeClient {
514
410
  * ```ts
515
411
  * import * as hl from "@nktkas/hyperliquid";
516
412
  *
517
- * const privateKey = "0x..."; // or `viem`, `ethers`
413
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
518
414
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
519
415
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
520
416
  *
521
417
  * const data = await exchClient.createSubAccount({ name: "..." });
522
418
  * ```
523
419
  */
524
- async createSubAccount(args, signal) {
525
- // Destructure the parameters
526
- const { ...actionArgs } = args;
527
- // Construct an action
528
- const nonce = await this.nonceManager();
529
- const action = actionSorter.createSubAccount({ type: "createSubAccount", ...actionArgs });
530
- // Sign the action
531
- const signature = await signL1Action({
532
- wallet: this.wallet,
533
- action,
534
- nonce,
535
- isTestnet: this.isTestnet,
420
+ async createSubAccount(params, opts) {
421
+ const action = actionSorter.createSubAccount({
422
+ type: "createSubAccount",
423
+ ...params,
536
424
  });
537
- // Send a request
538
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
539
- this._validateResponse(response);
540
- return response;
425
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
426
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
541
427
  }
542
428
  /**
543
429
  * Create a vault.
544
- * @param args - The parameters for the request.
545
- * @param signal - An optional abort signal.
430
+ * @param params - Action-specific parameters.
431
+ * @param opts - Request execution options.
546
432
  * @returns Response for creating a vault.
547
433
  *
548
434
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -553,35 +439,30 @@ export class ExchangeClient {
553
439
  * ```ts
554
440
  * import * as hl from "@nktkas/hyperliquid";
555
441
  *
556
- * const privateKey = "0x..."; // or `viem`, `ethers`
442
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
557
443
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
558
444
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
559
445
  *
560
- * const data = await exchClient.createVault({ name: "...", description: "...", initialUsd: 100 * 1e6 });
446
+ * const data = await exchClient.createVault({
447
+ * name: "...",
448
+ * description: "...",
449
+ * initialUsd: 100 * 1e6,
450
+ * nonce: Date.now(),
451
+ * });
561
452
  * ```
562
453
  */
563
- async createVault(args, signal) {
564
- // Destructure the parameters
565
- const { ...actionArgs } = args;
566
- // Construct an action
567
- const nonce = await this.nonceManager();
568
- const action = actionSorter.createVault({ type: "createVault", nonce, ...actionArgs });
569
- // Sign the action
570
- const signature = await signL1Action({
571
- wallet: this.wallet,
572
- action,
573
- nonce,
574
- isTestnet: this.isTestnet,
454
+ async createVault(params, opts) {
455
+ const action = actionSorter.createVault({
456
+ type: "createVault",
457
+ ...params,
575
458
  });
576
- // Send a request
577
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
578
- this._validateResponse(response);
579
- return response;
459
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
460
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
580
461
  }
581
462
  /**
582
463
  * Jail or unjail self as a validator signer.
583
- * @param args - The parameters for the request.
584
- * @param signal - An optional abort signal.
464
+ * @param params - Action-specific parameters.
465
+ * @param opts - Request execution options.
585
466
  * @returns Successful response without specific data.
586
467
  *
587
468
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -592,7 +473,7 @@ export class ExchangeClient {
592
473
  * ```ts
593
474
  * import * as hl from "@nktkas/hyperliquid";
594
475
  *
595
- * const privateKey = "0x..."; // or `viem`, `ethers`
476
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
596
477
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
597
478
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
598
479
  *
@@ -603,29 +484,18 @@ export class ExchangeClient {
603
484
  * await exchClient.cSignerAction({ unjailSelf: null });
604
485
  * ```
605
486
  */
606
- async cSignerAction(args, signal) {
607
- // Destructure the parameters
608
- const { expiresAfter = await this._getDefaultExpiresAfter(), ...actionArgs } = args;
609
- // Construct an action
610
- const nonce = await this.nonceManager();
611
- const action = actionSorter.CSignerAction({ type: "CSignerAction", ...actionArgs });
612
- // Sign the action
613
- const signature = await signL1Action({
614
- wallet: this.wallet,
615
- action,
616
- nonce,
617
- isTestnet: this.isTestnet,
618
- expiresAfter,
487
+ async cSignerAction(params, opts) {
488
+ const action = actionSorter.CSignerAction({
489
+ type: "CSignerAction",
490
+ ...params,
619
491
  });
620
- // Send a request
621
- const response = await this.transport.request("exchange", { action, signature, nonce, expiresAfter }, signal);
622
- this._validateResponse(response);
623
- return response;
492
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
493
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
624
494
  }
625
495
  /**
626
496
  * Action related to validator management.
627
- * @param args - The parameters for the request.
628
- * @param signal - An optional abort signal.
497
+ * @param params - Action-specific parameters.
498
+ * @param opts - Request execution options.
629
499
  * @returns Successful response without specific data.
630
500
  *
631
501
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -636,17 +506,21 @@ export class ExchangeClient {
636
506
  * ```ts
637
507
  * import * as hl from "@nktkas/hyperliquid";
638
508
  *
639
- * const privateKey = "0x..."; // or `viem`, `ethers`
509
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
640
510
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
641
511
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
642
512
  *
643
513
  * // Change validator profile
644
514
  * await exchClient.cValidatorAction({
645
515
  * changeProfile: {
516
+ * node_ip: { Ip: "1.2.3.4" },
646
517
  * name: "...",
647
518
  * description: "...",
648
519
  * unjailed: true,
649
- * }
520
+ * disable_delegations: false,
521
+ * commission_bps: null,
522
+ * signer: null,
523
+ * },
650
524
  * });
651
525
  *
652
526
  * // Register a new validator
@@ -669,29 +543,18 @@ export class ExchangeClient {
669
543
  * await exchClient.cValidatorAction({ unregister: null });
670
544
  * ```
671
545
  */
672
- async cValidatorAction(args, signal) {
673
- // Destructure the parameters
674
- const { expiresAfter = await this._getDefaultExpiresAfter(), ...actionArgs } = args;
675
- // Construct an action
676
- const nonce = await this.nonceManager();
677
- const action = actionSorter.CValidatorAction({ type: "CValidatorAction", ...actionArgs });
678
- // Sign the action
679
- const signature = await signL1Action({
680
- wallet: this.wallet,
681
- action,
682
- nonce,
683
- isTestnet: this.isTestnet,
684
- expiresAfter,
546
+ async cValidatorAction(params, opts) {
547
+ const action = actionSorter.CValidatorAction({
548
+ type: "CValidatorAction",
549
+ ...params,
685
550
  });
686
- // Send a request
687
- const response = await this.transport.request("exchange", { action, signature, nonce, expiresAfter }, signal);
688
- this._validateResponse(response);
689
- return response;
551
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
552
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
690
553
  }
691
554
  /**
692
555
  * Transfer native token from staking into the user's spot account.
693
- * @param args - The parameters for the request.
694
- * @param signal - An optional abort signal.
556
+ * @param params - Action-specific parameters.
557
+ * @param opts - Request execution options.
695
558
  * @returns Successful response without specific data.
696
559
  *
697
560
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -702,79 +565,56 @@ export class ExchangeClient {
702
565
  * ```ts
703
566
  * import * as hl from "@nktkas/hyperliquid";
704
567
  *
705
- * const privateKey = "0x..."; // or `viem`, `ethers`
568
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
706
569
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
707
570
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
708
571
  *
709
572
  * await exchClient.cWithdraw({ wei: 1 * 1e8 });
710
573
  * ```
711
574
  */
712
- async cWithdraw(args, signal) {
713
- // Destructure the parameters
714
- const { ...actionArgs } = args;
715
- // Construct an action
716
- const nonce = await this.nonceManager();
575
+ async cWithdraw(params, opts) {
717
576
  const action = actionSorter.cWithdraw({
718
577
  type: "cWithdraw",
719
578
  hyperliquidChain: this._getHyperliquidChain(),
720
579
  signatureChainId: await this._getSignatureChainId(),
721
- nonce,
722
- ...actionArgs,
723
- });
724
- // Sign the action
725
- const signature = await signUserSignedAction({
726
- wallet: this.wallet,
727
- action,
728
- types: userSignedActionEip712Types[action.type],
580
+ nonce: await this.nonceManager(),
581
+ ...params,
729
582
  });
730
- // Send a request
731
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
732
- this._validateResponse(response);
733
- return response;
583
+ return await this._executeUserSignedAction({ action }, opts?.signal);
734
584
  }
735
585
  /**
736
586
  * Configure block type for EVM transactions.
737
- * @param args - The parameters for the request.
738
- * @param signal - An optional abort signal.
587
+ * @param params - Action-specific parameters.
588
+ * @param opts - Request execution options.
739
589
  * @returns Response for creating a sub-account.
740
590
  *
741
591
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
742
592
  * @throws {TransportError} When the transport layer throws an error.
743
593
  *
744
- * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/evm/dual-block-architecture
594
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/hyperevm/dual-block-architecture
745
595
  * @example
746
596
  * ```ts
747
597
  * import * as hl from "@nktkas/hyperliquid";
748
598
  *
749
- * const privateKey = "0x..."; // or `viem`, `ethers`
599
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
750
600
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
751
601
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
752
602
  *
753
603
  * const data = await exchClient.evmUserModify({ usingBigBlocks: true });
754
604
  * ```
755
605
  */
756
- async evmUserModify(args, signal) {
757
- // Destructure the parameters
758
- const { ...actionArgs } = args;
759
- // Construct an action
760
- const nonce = await this.nonceManager();
761
- const action = actionSorter.evmUserModify({ type: "evmUserModify", ...actionArgs });
762
- // Sign the action
763
- const signature = await signL1Action({
764
- wallet: this.wallet,
765
- action,
766
- nonce,
767
- isTestnet: this.isTestnet,
606
+ async evmUserModify(params, opts) {
607
+ const action = actionSorter.evmUserModify({
608
+ type: "evmUserModify",
609
+ ...params,
768
610
  });
769
- // Send a request
770
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
771
- this._validateResponse(response);
772
- return response;
611
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
612
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
773
613
  }
774
614
  /**
775
615
  * Modify an order.
776
- * @param args - The parameters for the request.
777
- * @param signal - An optional abort signal.
616
+ * @param params - Action-specific parameters.
617
+ * @param opts - Request execution options.
778
618
  * @returns Successful response without specific data.
779
619
  *
780
620
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -785,7 +625,7 @@ export class ExchangeClient {
785
625
  * ```ts
786
626
  * import * as hl from "@nktkas/hyperliquid";
787
627
  *
788
- * const privateKey = "0x..."; // or `viem`, `ethers`
628
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
789
629
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
790
630
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
791
631
  *
@@ -803,30 +643,19 @@ export class ExchangeClient {
803
643
  * });
804
644
  * ```
805
645
  */
806
- async modify(args, signal) {
807
- // Destructure the parameters
808
- const { vaultAddress = this.defaultVaultAddress, expiresAfter = await this._getDefaultExpiresAfter(), ...actionArgs } = args;
809
- // Construct an action
810
- const nonce = await this.nonceManager();
811
- const action = actionSorter.modify({ type: "modify", ...actionArgs });
812
- // Sign the action
813
- const signature = await signL1Action({
814
- wallet: this.wallet,
815
- action,
816
- nonce,
817
- isTestnet: this.isTestnet,
818
- vaultAddress,
819
- expiresAfter,
646
+ async modify(params, opts) {
647
+ const action = actionSorter.modify({
648
+ type: "modify",
649
+ ...params,
820
650
  });
821
- // Send a request
822
- const response = await this.transport.request("exchange", { action, signature, nonce, vaultAddress, expiresAfter }, signal);
823
- this._validateResponse(response);
824
- return response;
651
+ const vaultAddress = opts?.vaultAddress ?? this.defaultVaultAddress;
652
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
653
+ return await this._executeL1Action({ action, vaultAddress, expiresAfter }, opts?.signal);
825
654
  }
826
655
  /**
827
656
  * A multi-signature request.
828
- * @param args - The parameters for the request.
829
- * @param signal - An optional abort signal.
657
+ * @param params - Action-specific parameters.
658
+ * @param opts - Request execution options.
830
659
  * @returns Any successful response.
831
660
  *
832
661
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -846,20 +675,36 @@ export class ExchangeClient {
846
675
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
847
676
  *
848
677
  * const nonce = Date.now();
849
- * const action = {
678
+ * const action = actionSorter.scheduleCancel({
850
679
  * type: "scheduleCancel",
851
680
  * time: Date.now() + 10000,
852
- * } as const;
853
- *
854
- * // Create the required number of signatures
855
- * const signature = await signL1Action({
856
- * wallet,
857
- * action: [multiSigUser.toLowerCase(), wallet.address.toLowerCase(), actionSorter[action.type](action)],
858
- * nonce,
859
681
  * });
860
682
  *
683
+ * // Create the required number of signatures
684
+ * const signatures = await Promise.all(["0x...", "0x..."].map(async (signerPrivKey) => {
685
+ * return await signL1Action({
686
+ * wallet: signerPrivKey as `0x${string}`,
687
+ * action: [multiSigUser.toLowerCase(), wallet.address.toLowerCase(), action],
688
+ * nonce,
689
+ * });
690
+ * }));
691
+ *
692
+ * // or user-signed action
693
+ * // const signatures = await Promise.all(["0x...", "0x..."].map(async (signerPrivKey) => {
694
+ * // return await signUserSignedAction({
695
+ * // wallet: signerPrivKey as `0x${string}`,
696
+ * // action: {
697
+ * // ...action,
698
+ * // payloadMultiSigUser: multiSigUser,
699
+ * // outerSigner: wallet.address,
700
+ * // },
701
+ * // types: userSignedActionEip712Types[action.type],
702
+ * // });
703
+ * // }));
704
+ *
705
+ * // Then use signatures in the `multiSig` action
861
706
  * const data = await exchClient.multiSig({
862
- * signatures: [signature],
707
+ * signatures,
863
708
  * payload: {
864
709
  * multiSigUser,
865
710
  * outerSigner: wallet.address,
@@ -869,36 +714,21 @@ export class ExchangeClient {
869
714
  * });
870
715
  * ```
871
716
  */
872
- async multiSig(args, signal) {
873
- // Destructure the parameters
874
- const { vaultAddress = this.defaultVaultAddress, expiresAfter = await this._getDefaultExpiresAfter(), nonce, ...actionArgs } = args;
875
- // Construct an action
717
+ async multiSig(params_and_nonce, opts) {
718
+ const { nonce, ...params } = params_and_nonce;
876
719
  const action = actionSorter.multiSig({
877
720
  type: "multiSig",
878
721
  signatureChainId: await this._getSignatureChainId(),
879
- ...actionArgs,
880
- });
881
- // Sign the action
882
- // deno-lint-ignore no-explicit-any
883
- const actionWithoutType = structuredClone(action);
884
- delete actionWithoutType.type;
885
- const signature = await signMultiSigAction({
886
- wallet: this.wallet,
887
- action: actionWithoutType,
888
- nonce,
889
- isTestnet: this.isTestnet,
890
- vaultAddress,
891
- expiresAfter,
722
+ ...params,
892
723
  });
893
- // Send a request
894
- const response = await this.transport.request("exchange", { action, signature, nonce, vaultAddress, expiresAfter }, signal);
895
- this._validateResponse(response);
896
- return response;
724
+ const vaultAddress = opts?.vaultAddress ?? this.defaultVaultAddress;
725
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
726
+ return await this._executeMultiSigAction({ action, vaultAddress, expiresAfter, nonce }, opts?.signal);
897
727
  }
898
728
  /**
899
729
  * Place an order(s).
900
- * @param args - The parameters for the request.
901
- * @param signal - An optional abort signal.
730
+ * @param params - Action-specific parameters.
731
+ * @param opts - Request execution options.
902
732
  * @returns Successful variant of {@link OrderResponse} without error statuses.
903
733
  *
904
734
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -909,7 +739,7 @@ export class ExchangeClient {
909
739
  * ```ts
910
740
  * import * as hl from "@nktkas/hyperliquid";
911
741
  *
912
- * const privateKey = "0x..."; // or `viem`, `ethers`
742
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
913
743
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
914
744
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
915
745
  *
@@ -929,30 +759,19 @@ export class ExchangeClient {
929
759
  * });
930
760
  * ```
931
761
  */
932
- async order(args, signal) {
933
- // Destructure the parameters
934
- const { vaultAddress = this.defaultVaultAddress, expiresAfter = await this._getDefaultExpiresAfter(), ...actionArgs } = args;
935
- // Construct an action
936
- const nonce = await this.nonceManager();
937
- const action = actionSorter.order({ type: "order", ...actionArgs });
938
- // Sign the action
939
- const signature = await signL1Action({
940
- wallet: this.wallet,
941
- action,
942
- nonce,
943
- isTestnet: this.isTestnet,
944
- vaultAddress,
945
- expiresAfter,
762
+ async order(params, opts) {
763
+ const action = actionSorter.order({
764
+ type: "order",
765
+ ...params,
946
766
  });
947
- // Send a request
948
- const response = await this.transport.request("exchange", { action, signature, nonce, vaultAddress, expiresAfter }, signal);
949
- this._validateResponse(response);
950
- return response;
767
+ const vaultAddress = opts?.vaultAddress ?? this.defaultVaultAddress;
768
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
769
+ return await this._executeL1Action({ action, vaultAddress, expiresAfter }, opts?.signal);
951
770
  }
952
771
  /**
953
772
  * Deploying HIP-3 assets.
954
- * @param args - The parameters for the request.
955
- * @param signal - An optional abort signal.
773
+ * @param params - Action-specific parameters.
774
+ * @param opts - Request execution options.
956
775
  * @returns Successful response without specific data.
957
776
  *
958
777
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -963,7 +782,7 @@ export class ExchangeClient {
963
782
  * ```ts
964
783
  * import * as hl from "@nktkas/hyperliquid";
965
784
  *
966
- * const privateKey = "0x..."; // or `viem`, `ethers`
785
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
967
786
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
968
787
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
969
788
  *
@@ -978,120 +797,93 @@ export class ExchangeClient {
978
797
  * onlyIsolated: false,
979
798
  * },
980
799
  * dex: "test",
800
+ * schema: null,
981
801
  * },
982
802
  * });
983
803
  * ```
984
804
  */
985
- async perpDeploy(args, signal) {
986
- // Destructure the parameters
987
- const { ...actionArgs } = args;
988
- // Construct an action
989
- const nonce = await this.nonceManager();
990
- const action = actionSorter.perpDeploy({ type: "perpDeploy", ...actionArgs });
991
- // Sign the action
992
- const signature = await signL1Action({
993
- wallet: this.wallet,
994
- action,
995
- nonce,
996
- isTestnet: this.isTestnet,
805
+ async perpDeploy(params, opts) {
806
+ const action = actionSorter.perpDeploy({
807
+ type: "perpDeploy",
808
+ ...params,
997
809
  });
998
- // Send a request
999
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1000
- this._validateResponse(response);
1001
- return response;
810
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
811
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
1002
812
  }
1003
813
  /**
1004
- * Transfer funds between Spot account and Perp dex account.
1005
- * @param args - The parameters for the request.
1006
- * @param signal - An optional abort signal.
814
+ * Create a referral code.
815
+ * @param params - Action-specific parameters.
816
+ * @param opts - Request execution options.
1007
817
  * @returns Successful response without specific data.
1008
818
  *
1009
819
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
1010
820
  * @throws {TransportError} When the transport layer throws an error.
1011
821
  *
1012
- * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#transfer-from-spot-account-to-perp-account-and-vice-versa
822
+ * @see null
1013
823
  * @example
1014
824
  * ```ts
1015
825
  * import * as hl from "@nktkas/hyperliquid";
1016
826
  *
1017
- * const privateKey = "0x..."; // or `viem`, `ethers`
827
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1018
828
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1019
829
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1020
830
  *
1021
- * await exchClient.perpDexClassTransfer({ dex: "test", token: "USDC", amount: "1", toPerp: true });
831
+ * await exchClient.registerReferrer({ code: "..." });
1022
832
  * ```
1023
833
  */
1024
- async perpDexClassTransfer(args, signal) {
1025
- // Destructure the parameters
1026
- const { ...actionArgs } = args;
1027
- // Construct an action
1028
- const nonce = await this.nonceManager();
1029
- const action = actionSorter.PerpDexClassTransfer({
1030
- type: "PerpDexClassTransfer",
1031
- hyperliquidChain: this._getHyperliquidChain(),
1032
- signatureChainId: await this._getSignatureChainId(),
1033
- nonce,
1034
- ...actionArgs,
1035
- });
1036
- // Sign the action
1037
- const signature = await signUserSignedAction({
1038
- wallet: this.wallet,
1039
- action,
1040
- types: userSignedActionEip712Types[action.type],
834
+ async registerReferrer(params, opts) {
835
+ const action = actionSorter.registerReferrer({
836
+ type: "registerReferrer",
837
+ ...params,
1041
838
  });
1042
- // Send a request
1043
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1044
- this._validateResponse(response);
1045
- return response;
839
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
840
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
1046
841
  }
1047
842
  /**
1048
- * Transfer collateral tokens between different perp dexes for the same user.
1049
- * @param args - The parameters for the request.
1050
- * @param signal - An optional abort signal.
843
+ * Reserve additional rate-limited actions for a fee.
844
+ * @param params - Action-specific parameters.
845
+ * @param opts - Request execution options.
1051
846
  * @returns Successful response without specific data.
1052
847
  *
1053
848
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
1054
849
  * @throws {TransportError} When the transport layer throws an error.
1055
850
  *
1056
- * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#transfer-from-perp-account-to-perp-account-for-builder-deployed-dex
851
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#reserve-additional-actions
1057
852
  * @example
1058
853
  * ```ts
1059
854
  * import * as hl from "@nktkas/hyperliquid";
1060
855
  *
1061
- * const privateKey = "0x..."; // or `viem`, `ethers`
856
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1062
857
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1063
858
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1064
859
  *
1065
- * await exchClient.perpDexTransfer({ sourceDex: "", destinationDex: "test", amount: "1" });
860
+ * await exchClient.reserveRequestWeight({ weight: 10 });
1066
861
  * ```
1067
862
  */
1068
- async perpDexTransfer(args, signal) {
1069
- // Destructure the parameters
1070
- const { ...actionArgs } = args;
1071
- // Construct an action
1072
- const nonce = await this.nonceManager();
1073
- const action = actionSorter.PerpDexTransfer({
1074
- type: "PerpDexTransfer",
1075
- hyperliquidChain: this._getHyperliquidChain(),
1076
- signatureChainId: await this._getSignatureChainId(),
1077
- nonce,
1078
- ...actionArgs,
863
+ async reserveRequestWeight(params, opts) {
864
+ const action = actionSorter.reserveRequestWeight({
865
+ type: "reserveRequestWeight",
866
+ ...params,
1079
867
  });
1080
- // Sign the action
1081
- const signature = await signUserSignedAction({
1082
- wallet: this.wallet,
1083
- action,
1084
- types: userSignedActionEip712Types[action.type],
868
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
869
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
870
+ }
871
+ async scheduleCancel(params_or_opts, maybeOpts) {
872
+ const isFirstArgParams = params_or_opts && "time" in params_or_opts;
873
+ const params = isFirstArgParams ? params_or_opts : {};
874
+ const opts = isFirstArgParams ? maybeOpts : params_or_opts;
875
+ const action = actionSorter.scheduleCancel({
876
+ type: "scheduleCancel",
877
+ ...params,
1085
878
  });
1086
- // Send a request
1087
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1088
- this._validateResponse(response);
1089
- return response;
879
+ const vaultAddress = opts?.vaultAddress ?? this.defaultVaultAddress;
880
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
881
+ return await this._executeL1Action({ action, vaultAddress, expiresAfter }, opts?.signal);
1090
882
  }
1091
883
  /**
1092
- * Create a referral code.
1093
- * @param args - The parameters for the request.
1094
- * @param signal - An optional abort signal.
884
+ * Set the display name in the leaderboard.
885
+ * @param params - Action-specific parameters.
886
+ * @param opts - Request execution options.
1095
887
  * @returns Successful response without specific data.
1096
888
  *
1097
889
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1102,136 +894,25 @@ export class ExchangeClient {
1102
894
  * ```ts
1103
895
  * import * as hl from "@nktkas/hyperliquid";
1104
896
  *
1105
- * const privateKey = "0x..."; // or `viem`, `ethers`
897
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1106
898
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1107
899
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1108
900
  *
1109
- * await exchClient.registerReferrer({ code: "..." });
901
+ * await exchClient.setDisplayName({ displayName: "..." });
1110
902
  * ```
1111
903
  */
1112
- async registerReferrer(args, signal) {
1113
- // Destructure the parameters
1114
- const { ...actionArgs } = args;
1115
- // Construct an action
1116
- const nonce = await this.nonceManager();
1117
- const action = actionSorter.registerReferrer({ type: "registerReferrer", ...actionArgs });
1118
- // Sign the action
1119
- const signature = await signL1Action({
1120
- wallet: this.wallet,
1121
- action,
1122
- nonce,
1123
- isTestnet: this.isTestnet,
904
+ async setDisplayName(params, opts) {
905
+ const action = actionSorter.setDisplayName({
906
+ type: "setDisplayName",
907
+ ...params,
1124
908
  });
1125
- // Send a request
1126
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1127
- this._validateResponse(response);
1128
- return response;
1129
- }
1130
- /**
1131
- * Reserve additional rate-limited actions for a fee.
1132
- * @param args - The parameters for the request.
1133
- * @param signal - An optional abort signal.
1134
- * @returns Successful response without specific data.
1135
- *
1136
- * @throws {ApiRequestError} When the API returns an unsuccessful response.
1137
- * @throws {TransportError} When the transport layer throws an error.
1138
- *
1139
- * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#reserve-additional-actions
1140
- * @example
1141
- * ```ts
1142
- * import * as hl from "@nktkas/hyperliquid";
1143
- *
1144
- * const privateKey = "0x..."; // or `viem`, `ethers`
1145
- * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1146
- * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1147
- *
1148
- * await exchClient.reserveRequestWeight({ weight: 10 });
1149
- * ```
1150
- */
1151
- async reserveRequestWeight(args, signal) {
1152
- // Destructure the parameters
1153
- const { expiresAfter = await this._getDefaultExpiresAfter(), ...actionArgs } = args;
1154
- // Construct an action
1155
- const nonce = await this.nonceManager();
1156
- const action = actionSorter.reserveRequestWeight({ type: "reserveRequestWeight", ...actionArgs });
1157
- // Sign the action
1158
- const signature = await signL1Action({
1159
- wallet: this.wallet,
1160
- action,
1161
- nonce,
1162
- isTestnet: this.isTestnet,
1163
- expiresAfter,
1164
- });
1165
- // Send a request
1166
- const response = await this.transport.request("exchange", { action, signature, nonce, expiresAfter }, signal);
1167
- this._validateResponse(response);
1168
- return response;
1169
- }
1170
- async scheduleCancel(args_or_signal, maybeSignal) {
1171
- const args = args_or_signal instanceof AbortSignal ? {} : args_or_signal ?? {};
1172
- const signal = args_or_signal instanceof AbortSignal ? args_or_signal : maybeSignal;
1173
- // Destructure the parameters
1174
- const { vaultAddress = this.defaultVaultAddress, expiresAfter = await this._getDefaultExpiresAfter(), ...actionArgs } = args;
1175
- // Construct an action
1176
- const nonce = await this.nonceManager();
1177
- const action = actionSorter.scheduleCancel({ type: "scheduleCancel", ...actionArgs });
1178
- // Sign the action
1179
- const signature = await signL1Action({
1180
- wallet: this.wallet,
1181
- action,
1182
- nonce,
1183
- isTestnet: this.isTestnet,
1184
- vaultAddress,
1185
- expiresAfter,
1186
- });
1187
- // Send a request
1188
- const response = await this.transport.request("exchange", { action, signature, nonce, vaultAddress, expiresAfter }, signal);
1189
- this._validateResponse(response);
1190
- return response;
1191
- }
1192
- /**
1193
- * Set the display name in the leaderboard.
1194
- * @param args - The parameters for the request.
1195
- * @param signal - An optional abort signal.
1196
- * @returns Successful response without specific data.
1197
- *
1198
- * @throws {ApiRequestError} When the API returns an unsuccessful response.
1199
- * @throws {TransportError} When the transport layer throws an error.
1200
- *
1201
- * @see null
1202
- * @example
1203
- * ```ts
1204
- * import * as hl from "@nktkas/hyperliquid";
1205
- *
1206
- * const privateKey = "0x..."; // or `viem`, `ethers`
1207
- * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1208
- * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1209
- *
1210
- * await exchClient.setDisplayName({ displayName: "..." });
1211
- * ```
1212
- */
1213
- async setDisplayName(args, signal) {
1214
- // Destructure the parameters
1215
- const { ...actionArgs } = args;
1216
- // Construct an action
1217
- const nonce = await this.nonceManager();
1218
- const action = actionSorter.setDisplayName({ type: "setDisplayName", ...actionArgs });
1219
- // Sign the action
1220
- const signature = await signL1Action({
1221
- wallet: this.wallet,
1222
- action,
1223
- nonce,
1224
- isTestnet: this.isTestnet,
1225
- });
1226
- // Send a request
1227
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1228
- this._validateResponse(response);
1229
- return response;
909
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
910
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
1230
911
  }
1231
912
  /**
1232
913
  * Set a referral code.
1233
- * @param args - The parameters for the request.
1234
- * @param signal - An optional abort signal.
914
+ * @param params - Action-specific parameters.
915
+ * @param opts - Request execution options.
1235
916
  * @returns Successful response without specific data.
1236
917
  *
1237
918
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1242,35 +923,25 @@ export class ExchangeClient {
1242
923
  * ```ts
1243
924
  * import * as hl from "@nktkas/hyperliquid";
1244
925
  *
1245
- * const privateKey = "0x..."; // or `viem`, `ethers`
926
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1246
927
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1247
928
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1248
929
  *
1249
930
  * await exchClient.setReferrer({ code: "..." });
1250
931
  * ```
1251
932
  */
1252
- async setReferrer(args, signal) {
1253
- // Destructure the parameters
1254
- const { ...actionArgs } = args;
1255
- // Construct an action
1256
- const nonce = await this.nonceManager();
1257
- const action = actionSorter.setReferrer({ type: "setReferrer", ...actionArgs });
1258
- // Sign the action
1259
- const signature = await signL1Action({
1260
- wallet: this.wallet,
1261
- action,
1262
- nonce,
1263
- isTestnet: this.isTestnet,
933
+ async setReferrer(params, opts) {
934
+ const action = actionSorter.setReferrer({
935
+ type: "setReferrer",
936
+ ...params,
1264
937
  });
1265
- // Send a request
1266
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1267
- this._validateResponse(response);
1268
- return response;
938
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
939
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
1269
940
  }
1270
941
  /**
1271
942
  * Deploying HIP-1 and HIP-2 assets.
1272
- * @param args - The parameters for the request.
1273
- * @param signal - An optional abort signal.
943
+ * @param params - Action-specific parameters.
944
+ * @param opts - Request execution options.
1274
945
  * @returns Successful response without specific data.
1275
946
  *
1276
947
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1281,7 +952,7 @@ export class ExchangeClient {
1281
952
  * ```ts
1282
953
  * import * as hl from "@nktkas/hyperliquid";
1283
954
  *
1284
- * const privateKey = "0x..."; // or `viem`, `ethers`
955
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1285
956
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1286
957
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1287
958
  *
@@ -1298,28 +969,18 @@ export class ExchangeClient {
1298
969
  * });
1299
970
  * ```
1300
971
  */
1301
- async spotDeploy(args, signal) {
1302
- // Destructure the parameters
1303
- const { ...actionArgs } = args;
1304
- // Construct an action
1305
- const nonce = await this.nonceManager();
1306
- const action = actionSorter.spotDeploy({ type: "spotDeploy", ...actionArgs });
1307
- // Sign the action
1308
- const signature = await signL1Action({
1309
- wallet: this.wallet,
1310
- action,
1311
- nonce,
1312
- isTestnet: this.isTestnet,
972
+ async spotDeploy(params, opts) {
973
+ const action = actionSorter.spotDeploy({
974
+ type: "spotDeploy",
975
+ ...params,
1313
976
  });
1314
- // Send a request
1315
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1316
- this._validateResponse(response);
1317
- return response;
977
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
978
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
1318
979
  }
1319
980
  /**
1320
981
  * Send spot assets to another address.
1321
- * @param args - The parameters for the request.
1322
- * @param signal - An optional abort signal.
982
+ * @param params - Action-specific parameters.
983
+ * @param opts - Request execution options.
1323
984
  * @returns Successful response without specific data.
1324
985
  *
1325
986
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1330,7 +991,7 @@ export class ExchangeClient {
1330
991
  * ```ts
1331
992
  * import * as hl from "@nktkas/hyperliquid";
1332
993
  *
1333
- * const privateKey = "0x..."; // or `viem`, `ethers`
994
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1334
995
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1335
996
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1336
997
  *
@@ -1341,33 +1002,20 @@ export class ExchangeClient {
1341
1002
  * });
1342
1003
  * ```
1343
1004
  */
1344
- async spotSend(args, signal) {
1345
- // Destructure the parameters
1346
- const { ...actionArgs } = args;
1347
- // Construct an action
1348
- const nonce = await this.nonceManager();
1005
+ async spotSend(params, opts) {
1349
1006
  const action = actionSorter.spotSend({
1350
1007
  type: "spotSend",
1351
1008
  hyperliquidChain: this._getHyperliquidChain(),
1352
1009
  signatureChainId: await this._getSignatureChainId(),
1353
- time: nonce,
1354
- ...actionArgs,
1355
- });
1356
- // Sign the action
1357
- const signature = await signUserSignedAction({
1358
- wallet: this.wallet,
1359
- action,
1360
- types: userSignedActionEip712Types[action.type],
1010
+ time: await this.nonceManager(),
1011
+ ...params,
1361
1012
  });
1362
- // Send a request
1363
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1364
- this._validateResponse(response);
1365
- return response;
1013
+ return await this._executeUserSignedAction({ action }, opts?.signal);
1366
1014
  }
1367
1015
  /**
1368
1016
  * Opt Out of Spot Dusting.
1369
- * @param args - The parameters for the request.
1370
- * @param signal - An optional abort signal.
1017
+ * @param params - Action-specific parameters.
1018
+ * @param opts - Request execution options.
1371
1019
  * @returns Successful response without specific data.
1372
1020
  *
1373
1021
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1378,35 +1026,54 @@ export class ExchangeClient {
1378
1026
  * ```ts
1379
1027
  * import * as hl from "@nktkas/hyperliquid";
1380
1028
  *
1381
- * const privateKey = "0x..."; // or `viem`, `ethers`
1029
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1382
1030
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1383
1031
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1384
1032
  *
1385
1033
  * await exchClient.spotUser({ toggleSpotDusting: { optOut: false } });
1386
1034
  * ```
1387
1035
  */
1388
- async spotUser(args, signal) {
1389
- // Destructure the parameters
1390
- const { ...actionArgs } = args;
1391
- // Construct an action
1392
- const nonce = await this.nonceManager();
1393
- const action = actionSorter.spotUser({ type: "spotUser", ...actionArgs });
1394
- // Sign the action
1395
- const signature = await signL1Action({
1396
- wallet: this.wallet,
1397
- action,
1398
- nonce,
1399
- isTestnet: this.isTestnet,
1036
+ async spotUser(params, opts) {
1037
+ const action = actionSorter.spotUser({
1038
+ type: "spotUser",
1039
+ ...params,
1400
1040
  });
1401
- // Send a request
1402
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1403
- this._validateResponse(response);
1404
- return response;
1041
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
1042
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
1043
+ }
1044
+ /**
1045
+ * Modify a sub-account's.
1046
+ * @param params - Action-specific parameters.
1047
+ * @param opts - Request execution options.
1048
+ * @returns Successful response without specific data.
1049
+ *
1050
+ * @throws {ApiRequestError} When the API returns an unsuccessful response.
1051
+ * @throws {TransportError} When the transport layer throws an error.
1052
+ *
1053
+ * @see null
1054
+ * @example
1055
+ * ```ts
1056
+ * import * as hl from "@nktkas/hyperliquid";
1057
+ *
1058
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1059
+ * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1060
+ * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1061
+ *
1062
+ * await exchClient.subAccountModify({ subAccountUser: "0x...", name: "..." });
1063
+ * ```
1064
+ */
1065
+ async subAccountModify(params, opts) {
1066
+ const action = actionSorter.subAccountModify({
1067
+ type: "subAccountModify",
1068
+ ...params,
1069
+ });
1070
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
1071
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
1405
1072
  }
1406
1073
  /**
1407
1074
  * Transfer between sub-accounts (spot).
1408
- * @param args - The parameters for the request.
1409
- * @param signal - An optional abort signal.
1075
+ * @param params - Action-specific parameters.
1076
+ * @param opts - Request execution options.
1410
1077
  * @returns Successful response without specific data.
1411
1078
  *
1412
1079
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1417,7 +1084,7 @@ export class ExchangeClient {
1417
1084
  * ```ts
1418
1085
  * import * as hl from "@nktkas/hyperliquid";
1419
1086
  *
1420
- * const privateKey = "0x..."; // or `viem`, `ethers`
1087
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1421
1088
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1422
1089
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1423
1090
  *
@@ -1429,28 +1096,18 @@ export class ExchangeClient {
1429
1096
  * });
1430
1097
  * ```
1431
1098
  */
1432
- async subAccountSpotTransfer(args, signal) {
1433
- // Destructure the parameters
1434
- const { ...actionArgs } = args;
1435
- // Construct an action
1436
- const nonce = await this.nonceManager();
1437
- const action = actionSorter.subAccountSpotTransfer({ type: "subAccountSpotTransfer", ...actionArgs });
1438
- // Sign the action
1439
- const signature = await signL1Action({
1440
- wallet: this.wallet,
1441
- action,
1442
- nonce,
1443
- isTestnet: this.isTestnet,
1099
+ async subAccountSpotTransfer(params, opts) {
1100
+ const action = actionSorter.subAccountSpotTransfer({
1101
+ type: "subAccountSpotTransfer",
1102
+ ...params,
1444
1103
  });
1445
- // Send a request
1446
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1447
- this._validateResponse(response);
1448
- return response;
1104
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
1105
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
1449
1106
  }
1450
1107
  /**
1451
1108
  * Transfer between sub-accounts (perpetual).
1452
- * @param args - The parameters for the request.
1453
- * @param signal - An optional abort signal.
1109
+ * @param params - Action-specific parameters.
1110
+ * @param opts - Request execution options.
1454
1111
  * @returns Successful response without specific data.
1455
1112
  *
1456
1113
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1461,35 +1118,25 @@ export class ExchangeClient {
1461
1118
  * ```ts
1462
1119
  * import * as hl from "@nktkas/hyperliquid";
1463
1120
  *
1464
- * const privateKey = "0x..."; // or `viem`, `ethers`
1121
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1465
1122
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1466
1123
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1467
1124
  *
1468
1125
  * await exchClient.subAccountTransfer({ subAccountUser: "0x...", isDeposit: true, usd: 1 * 1e6 });
1469
1126
  * ```
1470
1127
  */
1471
- async subAccountTransfer(args, signal) {
1472
- // Destructure the parameters
1473
- const { ...actionArgs } = args;
1474
- // Construct an action
1475
- const nonce = await this.nonceManager();
1476
- const action = actionSorter.subAccountTransfer({ type: "subAccountTransfer", ...actionArgs });
1477
- // Sign the action
1478
- const signature = await signL1Action({
1479
- wallet: this.wallet,
1480
- action,
1481
- nonce,
1482
- isTestnet: this.isTestnet,
1128
+ async subAccountTransfer(params, opts) {
1129
+ const action = actionSorter.subAccountTransfer({
1130
+ type: "subAccountTransfer",
1131
+ ...params,
1483
1132
  });
1484
- // Send a request
1485
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1486
- this._validateResponse(response);
1487
- return response;
1133
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
1134
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
1488
1135
  }
1489
1136
  /**
1490
1137
  * Delegate or undelegate native tokens to or from a validator.
1491
- * @param args - The parameters for the request.
1492
- * @param signal - An optional abort signal.
1138
+ * @param params - Action-specific parameters.
1139
+ * @param opts - Request execution options.
1493
1140
  * @returns Successful response without specific data.
1494
1141
  *
1495
1142
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1500,40 +1147,27 @@ export class ExchangeClient {
1500
1147
  * ```ts
1501
1148
  * import * as hl from "@nktkas/hyperliquid";
1502
1149
  *
1503
- * const privateKey = "0x..."; // or `viem`, `ethers`
1150
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1504
1151
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1505
1152
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1506
1153
  *
1507
1154
  * await exchClient.tokenDelegate({ validator: "0x...", isUndelegate: true, wei: 1 * 1e8 });
1508
1155
  * ```
1509
1156
  */
1510
- async tokenDelegate(args, signal) {
1511
- // Destructure the parameters
1512
- const { ...actionArgs } = args;
1513
- // Construct an action
1514
- const nonce = await this.nonceManager();
1157
+ async tokenDelegate(params, opts) {
1515
1158
  const action = actionSorter.tokenDelegate({
1516
1159
  type: "tokenDelegate",
1517
1160
  hyperliquidChain: this._getHyperliquidChain(),
1518
1161
  signatureChainId: await this._getSignatureChainId(),
1519
- nonce,
1520
- ...actionArgs,
1521
- });
1522
- // Sign the action
1523
- const signature = await signUserSignedAction({
1524
- wallet: this.wallet,
1525
- action,
1526
- types: userSignedActionEip712Types[action.type],
1162
+ nonce: await this.nonceManager(),
1163
+ ...params,
1527
1164
  });
1528
- // Send a request
1529
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1530
- this._validateResponse(response);
1531
- return response;
1165
+ return await this._executeUserSignedAction({ action }, opts?.signal);
1532
1166
  }
1533
1167
  /**
1534
1168
  * Cancel a TWAP order.
1535
- * @param args - The parameters for the request.
1536
- * @param signal - An optional abort signal.
1169
+ * @param params - Action-specific parameters.
1170
+ * @param opts - Request execution options.
1537
1171
  * @returns Successful variant of {@link TwapCancelResponse} without error status.
1538
1172
  *
1539
1173
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1544,37 +1178,26 @@ export class ExchangeClient {
1544
1178
  * ```ts
1545
1179
  * import * as hl from "@nktkas/hyperliquid";
1546
1180
  *
1547
- * const privateKey = "0x..."; // or `viem`, `ethers`
1181
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1548
1182
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1549
1183
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1550
1184
  *
1551
1185
  * const data = await exchClient.twapCancel({ a: 0, t: 1 });
1552
1186
  * ```
1553
1187
  */
1554
- async twapCancel(args, signal) {
1555
- // Destructure the parameters
1556
- const { vaultAddress = this.defaultVaultAddress, expiresAfter = await this._getDefaultExpiresAfter(), ...actionArgs } = args;
1557
- // Construct an action
1558
- const nonce = await this.nonceManager();
1559
- const action = actionSorter.twapCancel({ type: "twapCancel", ...actionArgs });
1560
- // Sign the action
1561
- const signature = await signL1Action({
1562
- wallet: this.wallet,
1563
- action,
1564
- nonce,
1565
- isTestnet: this.isTestnet,
1566
- vaultAddress,
1567
- expiresAfter,
1188
+ async twapCancel(params, opts) {
1189
+ const action = actionSorter.twapCancel({
1190
+ type: "twapCancel",
1191
+ ...params,
1568
1192
  });
1569
- // Send a request
1570
- const response = await this.transport.request("exchange", { action, signature, nonce, vaultAddress, expiresAfter }, signal);
1571
- this._validateResponse(response);
1572
- return response;
1193
+ const vaultAddress = opts?.vaultAddress ?? this.defaultVaultAddress;
1194
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
1195
+ return await this._executeL1Action({ action, vaultAddress, expiresAfter }, opts?.signal);
1573
1196
  }
1574
1197
  /**
1575
1198
  * Place a TWAP order.
1576
- * @param args - The parameters for the request.
1577
- * @param signal - An optional abort signal.
1199
+ * @param params - Action-specific parameters.
1200
+ * @param opts - Request execution options.
1578
1201
  * @returns Successful variant of {@link TwapOrderResponse} without error status.
1579
1202
  *
1580
1203
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1585,44 +1208,35 @@ export class ExchangeClient {
1585
1208
  * ```ts
1586
1209
  * import * as hl from "@nktkas/hyperliquid";
1587
1210
  *
1588
- * const privateKey = "0x..."; // or `viem`, `ethers`
1211
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1589
1212
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1590
1213
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1591
1214
  *
1592
1215
  * const data = await exchClient.twapOrder({
1593
- * a: 0,
1594
- * b: true,
1595
- * s: "1",
1596
- * r: false,
1597
- * m: 10,
1598
- * t: true,
1216
+ * twap: {
1217
+ * a: 0,
1218
+ * b: true,
1219
+ * s: "1",
1220
+ * r: false,
1221
+ * m: 10,
1222
+ * t: true,
1223
+ * },
1599
1224
  * });
1600
1225
  * ```
1601
1226
  */
1602
- async twapOrder(args, signal) {
1603
- // Destructure the parameters
1604
- const { vaultAddress = this.defaultVaultAddress, expiresAfter = await this._getDefaultExpiresAfter(), ...actionArgs } = args;
1605
- // Construct an action
1606
- const nonce = await this.nonceManager();
1607
- const action = actionSorter.twapOrder({ type: "twapOrder", twap: { ...actionArgs } });
1608
- // Sign the action
1609
- const signature = await signL1Action({
1610
- wallet: this.wallet,
1611
- action,
1612
- nonce,
1613
- isTestnet: this.isTestnet,
1614
- vaultAddress,
1615
- expiresAfter,
1227
+ async twapOrder(params, opts) {
1228
+ const action = actionSorter.twapOrder({
1229
+ type: "twapOrder",
1230
+ ...params,
1616
1231
  });
1617
- // Send a request
1618
- const response = await this.transport.request("exchange", { action, signature, nonce, vaultAddress, expiresAfter }, signal);
1619
- this._validateResponse(response);
1620
- return response;
1232
+ const vaultAddress = opts?.vaultAddress ?? this.defaultVaultAddress;
1233
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
1234
+ return await this._executeL1Action({ action, vaultAddress, expiresAfter }, opts?.signal);
1621
1235
  }
1622
1236
  /**
1623
1237
  * Add or remove margin from isolated position.
1624
- * @param args - The parameters for the request.
1625
- * @param signal - An optional abort signal.
1238
+ * @param params - Action-specific parameters.
1239
+ * @param opts - Request execution options.
1626
1240
  * @returns Successful response without specific data.
1627
1241
  *
1628
1242
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1633,37 +1247,26 @@ export class ExchangeClient {
1633
1247
  * ```ts
1634
1248
  * import * as hl from "@nktkas/hyperliquid";
1635
1249
  *
1636
- * const privateKey = "0x..."; // or `viem`, `ethers`
1250
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1637
1251
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1638
1252
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1639
1253
  *
1640
1254
  * await exchClient.updateIsolatedMargin({ asset: 0, isBuy: true, ntli: 1 * 1e6 });
1641
1255
  * ```
1642
1256
  */
1643
- async updateIsolatedMargin(args, signal) {
1644
- // Destructure the parameters
1645
- const { vaultAddress = this.defaultVaultAddress, expiresAfter = await this._getDefaultExpiresAfter(), ...actionArgs } = args;
1646
- // Construct an action
1647
- const nonce = await this.nonceManager();
1648
- const action = actionSorter.updateIsolatedMargin({ type: "updateIsolatedMargin", ...actionArgs });
1649
- // Sign the action
1650
- const signature = await signL1Action({
1651
- wallet: this.wallet,
1652
- action,
1653
- nonce,
1654
- isTestnet: this.isTestnet,
1655
- vaultAddress,
1656
- expiresAfter,
1257
+ async updateIsolatedMargin(params, opts) {
1258
+ const action = actionSorter.updateIsolatedMargin({
1259
+ type: "updateIsolatedMargin",
1260
+ ...params,
1657
1261
  });
1658
- // Send a request
1659
- const response = await this.transport.request("exchange", { action, signature, nonce, vaultAddress, expiresAfter }, signal);
1660
- this._validateResponse(response);
1661
- return response;
1262
+ const vaultAddress = opts?.vaultAddress ?? this.defaultVaultAddress;
1263
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
1264
+ return await this._executeL1Action({ action, vaultAddress, expiresAfter }, opts?.signal);
1662
1265
  }
1663
1266
  /**
1664
1267
  * Update cross or isolated leverage on a coin.
1665
- * @param args - The parameters for the request.
1666
- * @param signal - An optional abort signal.
1268
+ * @param params - Action-specific parameters.
1269
+ * @param opts - Request execution options.
1667
1270
  * @returns Successful response without specific data.
1668
1271
  *
1669
1272
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1674,37 +1277,26 @@ export class ExchangeClient {
1674
1277
  * ```ts
1675
1278
  * import * as hl from "@nktkas/hyperliquid";
1676
1279
  *
1677
- * const privateKey = "0x..."; // or `viem`, `ethers`
1280
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1678
1281
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1679
1282
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1680
1283
  *
1681
1284
  * await exchClient.updateLeverage({ asset: 0, isCross: true, leverage: 5 });
1682
1285
  * ```
1683
1286
  */
1684
- async updateLeverage(args, signal) {
1685
- // Destructure the parameters
1686
- const { vaultAddress = this.defaultVaultAddress, expiresAfter = await this._getDefaultExpiresAfter(), ...actionArgs } = args;
1687
- // Construct an action
1688
- const nonce = await this.nonceManager();
1689
- const action = actionSorter.updateLeverage({ type: "updateLeverage", ...actionArgs });
1690
- // Sign the action
1691
- const signature = await signL1Action({
1692
- wallet: this.wallet,
1693
- action,
1694
- nonce,
1695
- isTestnet: this.isTestnet,
1696
- vaultAddress,
1697
- expiresAfter,
1287
+ async updateLeverage(params, opts) {
1288
+ const action = actionSorter.updateLeverage({
1289
+ type: "updateLeverage",
1290
+ ...params,
1698
1291
  });
1699
- // Send a request
1700
- const response = await this.transport.request("exchange", { action, signature, nonce, vaultAddress, expiresAfter }, signal);
1701
- this._validateResponse(response);
1702
- return response;
1292
+ const vaultAddress = opts?.vaultAddress ?? this.defaultVaultAddress;
1293
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
1294
+ return await this._executeL1Action({ action, vaultAddress, expiresAfter }, opts?.signal);
1703
1295
  }
1704
1296
  /**
1705
1297
  * Transfer funds between Spot account and Perp account.
1706
- * @param args - The parameters for the request.
1707
- * @param signal - An optional abort signal.
1298
+ * @param params - Action-specific parameters.
1299
+ * @param opts - Request execution options.
1708
1300
  * @returns Successful response without specific data.
1709
1301
  *
1710
1302
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1715,40 +1307,27 @@ export class ExchangeClient {
1715
1307
  * ```ts
1716
1308
  * import * as hl from "@nktkas/hyperliquid";
1717
1309
  *
1718
- * const privateKey = "0x..."; // or `viem`, `ethers`
1310
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1719
1311
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1720
1312
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1721
1313
  *
1722
1314
  * await exchClient.usdClassTransfer({ amount: "1", toPerp: true });
1723
1315
  * ```
1724
1316
  */
1725
- async usdClassTransfer(args, signal) {
1726
- // Destructure the parameters
1727
- const { ...actionArgs } = args;
1728
- // Construct an action
1729
- const nonce = await this.nonceManager();
1317
+ async usdClassTransfer(params, opts) {
1730
1318
  const action = actionSorter.usdClassTransfer({
1731
1319
  type: "usdClassTransfer",
1732
1320
  hyperliquidChain: this._getHyperliquidChain(),
1733
1321
  signatureChainId: await this._getSignatureChainId(),
1734
- nonce,
1735
- ...actionArgs,
1322
+ nonce: await this.nonceManager(),
1323
+ ...params,
1736
1324
  });
1737
- // Sign the action
1738
- const signature = await signUserSignedAction({
1739
- wallet: this.wallet,
1740
- action,
1741
- types: userSignedActionEip712Types[action.type],
1742
- });
1743
- // Send a request
1744
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1745
- this._validateResponse(response);
1746
- return response;
1325
+ return await this._executeUserSignedAction({ action }, opts?.signal);
1747
1326
  }
1748
1327
  /**
1749
1328
  * Send usd to another address.
1750
- * @param args - The parameters for the request.
1751
- * @param signal - An optional abort signal.
1329
+ * @param params - Action-specific parameters.
1330
+ * @param opts - Request execution options.
1752
1331
  * @returns Successful response without specific data.
1753
1332
  *
1754
1333
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1759,40 +1338,27 @@ export class ExchangeClient {
1759
1338
  * ```ts
1760
1339
  * import * as hl from "@nktkas/hyperliquid";
1761
1340
  *
1762
- * const privateKey = "0x..."; // or `viem`, `ethers`
1341
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1763
1342
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1764
1343
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1765
1344
  *
1766
1345
  * await exchClient.usdSend({ destination: "0x...", amount: "1" });
1767
1346
  * ```
1768
1347
  */
1769
- async usdSend(args, signal) {
1770
- // Destructure the parameters
1771
- const { ...actionArgs } = args;
1772
- // Construct an action
1773
- const nonce = await this.nonceManager();
1348
+ async usdSend(params, opts) {
1774
1349
  const action = actionSorter.usdSend({
1775
1350
  type: "usdSend",
1776
1351
  hyperliquidChain: this._getHyperliquidChain(),
1777
1352
  signatureChainId: await this._getSignatureChainId(),
1778
- time: nonce,
1779
- ...actionArgs,
1780
- });
1781
- // Sign the action
1782
- const signature = await signUserSignedAction({
1783
- wallet: this.wallet,
1784
- action,
1785
- types: userSignedActionEip712Types[action.type],
1353
+ time: await this.nonceManager(),
1354
+ ...params,
1786
1355
  });
1787
- // Send a request
1788
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1789
- this._validateResponse(response);
1790
- return response;
1356
+ return await this._executeUserSignedAction({ action }, opts?.signal);
1791
1357
  }
1792
1358
  /**
1793
1359
  * Distribute funds from a vault between followers.
1794
- * @param args - The parameters for the request.
1795
- * @param signal - An optional abort signal.
1360
+ * @param params - Action-specific parameters.
1361
+ * @param opts - Request execution options.
1796
1362
  * @returns Successful response without specific data.
1797
1363
  *
1798
1364
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1803,35 +1369,25 @@ export class ExchangeClient {
1803
1369
  * ```ts
1804
1370
  * import * as hl from "@nktkas/hyperliquid";
1805
1371
  *
1806
- * const privateKey = "0x..."; // or `viem`, `ethers`
1372
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1807
1373
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1808
1374
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1809
1375
  *
1810
1376
  * await exchClient.vaultDistribute({ vaultAddress: "0x...", usd: 10 * 1e6 });
1811
1377
  * ```
1812
1378
  */
1813
- async vaultDistribute(args, signal) {
1814
- // Destructure the parameters
1815
- const { ...actionArgs } = args;
1816
- // Construct an action
1817
- const nonce = await this.nonceManager();
1818
- const action = actionSorter.vaultDistribute({ type: "vaultDistribute", ...actionArgs });
1819
- // Sign the action
1820
- const signature = await signL1Action({
1821
- wallet: this.wallet,
1822
- action,
1823
- nonce,
1824
- isTestnet: this.isTestnet,
1379
+ async vaultDistribute(params, opts) {
1380
+ const action = actionSorter.vaultDistribute({
1381
+ type: "vaultDistribute",
1382
+ ...params,
1825
1383
  });
1826
- // Send a request
1827
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1828
- this._validateResponse(response);
1829
- return response;
1384
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
1385
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
1830
1386
  }
1831
1387
  /**
1832
1388
  * Modify a vault's configuration.
1833
- * @param args - The parameters for the request.
1834
- * @param signal - An optional abort signal.
1389
+ * @param params - Action-specific parameters.
1390
+ * @param opts - Request execution options.
1835
1391
  * @returns Successful response without specific data.
1836
1392
  *
1837
1393
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1842,7 +1398,7 @@ export class ExchangeClient {
1842
1398
  * ```ts
1843
1399
  * import * as hl from "@nktkas/hyperliquid";
1844
1400
  *
1845
- * const privateKey = "0x..."; // or `viem`, `ethers`
1401
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1846
1402
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1847
1403
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1848
1404
  *
@@ -1853,28 +1409,18 @@ export class ExchangeClient {
1853
1409
  * });
1854
1410
  * ```
1855
1411
  */
1856
- async vaultModify(args, signal) {
1857
- // Destructure the parameters
1858
- const { ...actionArgs } = args;
1859
- // Construct an action
1860
- const nonce = await this.nonceManager();
1861
- const action = actionSorter.vaultModify({ type: "vaultModify", ...actionArgs });
1862
- // Sign the action
1863
- const signature = await signL1Action({
1864
- wallet: this.wallet,
1865
- action,
1866
- nonce,
1867
- isTestnet: this.isTestnet,
1412
+ async vaultModify(params, opts) {
1413
+ const action = actionSorter.vaultModify({
1414
+ type: "vaultModify",
1415
+ ...params,
1868
1416
  });
1869
- // Send a request
1870
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1871
- this._validateResponse(response);
1872
- return response;
1417
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
1418
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
1873
1419
  }
1874
1420
  /**
1875
1421
  * Deposit or withdraw from a vault.
1876
- * @param args - The parameters for the request.
1877
- * @param signal - An optional abort signal.
1422
+ * @param params - Action-specific parameters.
1423
+ * @param opts - Request execution options.
1878
1424
  * @returns Successful response without specific data.
1879
1425
  *
1880
1426
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1885,36 +1431,25 @@ export class ExchangeClient {
1885
1431
  * ```ts
1886
1432
  * import * as hl from "@nktkas/hyperliquid";
1887
1433
  *
1888
- * const privateKey = "0x..."; // or `viem`, `ethers`
1434
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1889
1435
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1890
1436
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1891
1437
  *
1892
1438
  * await exchClient.vaultTransfer({ vaultAddress: "0x...", isDeposit: true, usd: 10 * 1e6 });
1893
1439
  * ```
1894
1440
  */
1895
- async vaultTransfer(args, signal) {
1896
- // Destructure the parameters
1897
- const { expiresAfter = await this._getDefaultExpiresAfter(), ...actionArgs } = args;
1898
- // Construct an action
1899
- const nonce = await this.nonceManager();
1900
- const action = actionSorter.vaultTransfer({ type: "vaultTransfer", ...actionArgs });
1901
- // Sign the action
1902
- const signature = await signL1Action({
1903
- wallet: this.wallet,
1904
- action,
1905
- nonce,
1906
- isTestnet: this.isTestnet,
1907
- expiresAfter,
1441
+ async vaultTransfer(params, opts) {
1442
+ const action = actionSorter.vaultTransfer({
1443
+ type: "vaultTransfer",
1444
+ ...params,
1908
1445
  });
1909
- // Send a request
1910
- const response = await this.transport.request("exchange", { action, signature, nonce, expiresAfter }, signal);
1911
- this._validateResponse(response);
1912
- return response;
1446
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
1447
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
1913
1448
  }
1914
1449
  /**
1915
1450
  * Initiate a withdrawal request.
1916
- * @param args - The parameters for the request.
1917
- * @param signal - An optional abort signal.
1451
+ * @param params - Action-specific parameters.
1452
+ * @param opts - Request execution options.
1918
1453
  * @returns Successful response without specific data.
1919
1454
  *
1920
1455
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1925,26 +1460,44 @@ export class ExchangeClient {
1925
1460
  * ```ts
1926
1461
  * import * as hl from "@nktkas/hyperliquid";
1927
1462
  *
1928
- * const privateKey = "0x..."; // or `viem`, `ethers`
1463
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1929
1464
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1930
1465
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1931
1466
  *
1932
1467
  * await exchClient.withdraw3({ destination: "0x...", amount: "1" });
1933
1468
  * ```
1934
1469
  */
1935
- async withdraw3(args, signal) {
1936
- // Destructure the parameters
1937
- const { ...actionArgs } = args;
1938
- // Construct an action
1939
- const nonce = await this.nonceManager();
1470
+ async withdraw3(params, opts) {
1940
1471
  const action = actionSorter.withdraw3({
1941
1472
  type: "withdraw3",
1942
1473
  hyperliquidChain: this._getHyperliquidChain(),
1943
1474
  signatureChainId: await this._getSignatureChainId(),
1944
- time: nonce,
1945
- ...actionArgs,
1475
+ time: await this.nonceManager(),
1476
+ ...params,
1946
1477
  });
1947
- // Sign the action
1478
+ return await this._executeUserSignedAction({ action }, opts?.signal);
1479
+ }
1480
+ async _executeL1Action(request, signal) {
1481
+ const { action, vaultAddress, expiresAfter } = request;
1482
+ // Sign an L1 action
1483
+ const nonce = await this.nonceManager();
1484
+ const signature = await signL1Action({
1485
+ wallet: this.wallet,
1486
+ action,
1487
+ nonce,
1488
+ isTestnet: this.isTestnet,
1489
+ vaultAddress,
1490
+ expiresAfter,
1491
+ });
1492
+ // Send a request
1493
+ const response = await this.transport.request("exchange", { action, signature, nonce, vaultAddress, expiresAfter }, signal);
1494
+ this._validateResponse(response);
1495
+ return response;
1496
+ }
1497
+ async _executeUserSignedAction(request, signal) {
1498
+ const { action } = request;
1499
+ // Sign a user-signed action
1500
+ const nonce = "nonce" in action ? action.nonce : action.time;
1948
1501
  const signature = await signUserSignedAction({
1949
1502
  wallet: this.wallet,
1950
1503
  action,
@@ -1955,46 +1508,33 @@ export class ExchangeClient {
1955
1508
  this._validateResponse(response);
1956
1509
  return response;
1957
1510
  }
1958
- /** Guesses the chain ID based on the wallet type or the isTestnet flag. */
1959
- async _guessSignatureChainId() {
1960
- // Trying to get chain ID of the wallet
1961
- if (isAbstractViemWalletClient(this.wallet)) {
1962
- if ("getChainId" in this.wallet && typeof this.wallet.getChainId === "function") {
1963
- const chainId = await this.wallet.getChainId();
1964
- return `0x${chainId.toString(16)}`;
1965
- }
1966
- }
1967
- else if (isAbstractEthersSigner(this.wallet) || isAbstractEthersV5Signer(this.wallet)) {
1968
- if ("provider" in this.wallet &&
1969
- typeof this.wallet.provider === "object" && this.wallet.provider !== null &&
1970
- "getNetwork" in this.wallet.provider &&
1971
- typeof this.wallet.provider.getNetwork === "function") {
1972
- const network = await this.wallet.provider.getNetwork();
1973
- return `0x${network.chainId.toString(16)}`;
1974
- }
1975
- }
1976
- else if (isAbstractWindowEthereum(this.wallet)) {
1977
- const [chainId] = await this.wallet.request({ method: "eth_chainId", params: [] });
1978
- return chainId;
1979
- }
1980
- // Attempt to guess chain ID based on isTestnet
1981
- return this.isTestnet ? "0x66eee" : "0xa4b1";
1511
+ async _executeMultiSigAction(request, signal) {
1512
+ const { action, nonce, vaultAddress, expiresAfter } = request;
1513
+ // Sign a multi-signature action
1514
+ const signature = await signMultiSigAction({
1515
+ wallet: this.wallet,
1516
+ action,
1517
+ nonce,
1518
+ isTestnet: this.isTestnet,
1519
+ vaultAddress,
1520
+ expiresAfter,
1521
+ });
1522
+ // Send a request
1523
+ const response = await this.transport.request("exchange", { action, signature, nonce, vaultAddress, expiresAfter }, signal);
1524
+ this._validateResponse(response);
1525
+ return response;
1982
1526
  }
1983
- /** Get the default expiration time for an action. */
1984
1527
  async _getDefaultExpiresAfter() {
1985
1528
  return typeof this.defaultExpiresAfter === "number"
1986
1529
  ? this.defaultExpiresAfter
1987
1530
  : await this.defaultExpiresAfter?.();
1988
1531
  }
1989
- /** Get the signature chain ID for the wallet. */
1990
1532
  async _getSignatureChainId() {
1991
1533
  return typeof this.signatureChainId === "string" ? this.signatureChainId : await this.signatureChainId();
1992
1534
  }
1993
- /** Get the Hyperliquid chain based on the isTestnet flag. */
1994
1535
  _getHyperliquidChain() {
1995
1536
  return this.isTestnet ? "Testnet" : "Mainnet";
1996
1537
  }
1997
- /** Validate a response from the API. */
1998
1538
  _validateResponse(response) {
1999
1539
  if (response.status === "err") {
2000
1540
  throw new ApiRequestError(response);