@nktkas/hyperliquid 0.23.1 → 0.24.1

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 +178 -194
  3. package/esm/mod.d.ts +2 -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 +485 -392
  8. package/esm/src/clients/exchange.d.ts.map +1 -1
  9. package/esm/src/clients/exchange.js +517 -912
  10. package/esm/src/clients/info.d.ts +249 -203
  11. package/esm/src/clients/info.d.ts.map +1 -1
  12. package/esm/src/clients/info.js +258 -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 +101 -99
  17. package/esm/src/clients/subscription.d.ts.map +1 -1
  18. package/esm/src/clients/subscription.js +107 -152
  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 +18 -19
  32. package/esm/src/signing/_sorter.d.ts.map +1 -1
  33. package/esm/src/signing/_sorter.js +57 -59
  34. package/esm/src/signing/mod.d.ts +179 -129
  35. package/esm/src/signing/mod.d.ts.map +1 -1
  36. package/esm/src/signing/mod.js +184 -132
  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 +547 -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 +405 -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 +64 -17
  68. package/esm/src/types/info/orders.d.ts.map +1 -1
  69. package/esm/src/types/info/requests.d.ts +126 -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 +2 -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 +485 -392
  87. package/script/src/clients/exchange.d.ts.map +1 -1
  88. package/script/src/clients/exchange.js +516 -911
  89. package/script/src/clients/info.d.ts +249 -203
  90. package/script/src/clients/info.d.ts.map +1 -1
  91. package/script/src/clients/info.js +258 -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 +101 -99
  96. package/script/src/clients/subscription.d.ts.map +1 -1
  97. package/script/src/clients/subscription.js +107 -152
  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 +18 -19
  111. package/script/src/signing/_sorter.d.ts.map +1 -1
  112. package/script/src/signing/_sorter.js +57 -59
  113. package/script/src/signing/mod.d.ts +179 -129
  114. package/script/src/signing/mod.d.ts.map +1 -1
  115. package/script/src/signing/mod.js +187 -150
  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 +547 -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 +405 -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 +64 -17
  147. package/script/src/types/info/orders.d.ts.map +1 -1
  148. package/script/src/types/info/requests.d.ts +126 -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) {
@@ -83,7 +83,7 @@ export class ExchangeClient {
83
83
  * @example [Viem](https://viem.sh/docs/clients/wallet#local-accounts-private-key-mnemonic-etc)
84
84
  * ```ts
85
85
  * import * as hl from "@nktkas/hyperliquid";
86
- * import { privateKeyToAccount } from "viem/accounts";
86
+ * import { privateKeyToAccount } from "npm:viem/accounts";
87
87
  *
88
88
  * const account = privateKeyToAccount("0x...");
89
89
  *
@@ -94,7 +94,7 @@ export class ExchangeClient {
94
94
  * @example [ethers.js](https://docs.ethers.org/v6/api/wallet/#Wallet) or [ethers.js v5](https://docs.ethers.org/v5/api/signer/#Wallet)
95
95
  * ```ts
96
96
  * import * as hl from "@nktkas/hyperliquid";
97
- * import { ethers } from "ethers";
97
+ * import { ethers } from "npm:ethers";
98
98
  *
99
99
  * const wallet = new ethers.Wallet("0x...");
100
100
  *
@@ -105,24 +105,15 @@ export class ExchangeClient {
105
105
  * @example External wallet (e.g. MetaMask) via [viem](https://viem.sh/docs/clients/wallet)
106
106
  * ```ts
107
107
  * import * as hl from "@nktkas/hyperliquid";
108
- * import { createWalletClient, custom } from "viem";
108
+ * import { createWalletClient, custom } from "npm:viem";
109
109
  *
110
110
  * const ethereum = (window as any).ethereum;
111
- * const [account] = await ethereum.request({ method: "eth_requestAccounts" });
111
+ * const [account] = await ethereum.request({ method: "eth_requestAccounts" }) as `0x${string}`[];
112
112
  * const wallet = createWalletClient({ account, transport: custom(ethereum) });
113
113
  *
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.
@@ -837,7 +666,7 @@ export class ExchangeClient {
837
666
  * ```ts
838
667
  * import * as hl from "@nktkas/hyperliquid";
839
668
  * import { actionSorter, signL1Action } from "@nktkas/hyperliquid/signing";
840
- * import { privateKeyToAccount } from "viem/accounts";
669
+ * import { privateKeyToAccount } from "npm:viem/accounts";
841
670
  *
842
671
  * const wallet = privateKeyToAccount("0x..."); // or any other wallet libraries
843
672
  * const multiSigUser = "0x...";
@@ -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,46 @@ 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);
770
+ }
771
+ /**
772
+ * This action does not do anything (no operation), but causes the nonce to be marked as used.
773
+ * @param opts - Request execution options.
774
+ * @returns Successful response without specific data.
775
+ *
776
+ * @throws {ApiRequestError} When the API returns an unsuccessful response.
777
+ * @throws {TransportError} When the transport layer throws an error.
778
+ *
779
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#place-an-order
780
+ * @example
781
+ * ```ts
782
+ * import * as hl from "@nktkas/hyperliquid";
783
+ *
784
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
785
+ * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
786
+ * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
787
+ *
788
+ * await exchClient.noop();
789
+ * ```
790
+ */
791
+ async noop(opts) {
792
+ const action = actionSorter.noop({
793
+ type: "noop",
794
+ });
795
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
796
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
951
797
  }
952
798
  /**
953
799
  * Deploying HIP-3 assets.
954
- * @param args - The parameters for the request.
955
- * @param signal - An optional abort signal.
800
+ * @param params - Action-specific parameters.
801
+ * @param opts - Request execution options.
956
802
  * @returns Successful response without specific data.
957
803
  *
958
804
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -963,7 +809,7 @@ export class ExchangeClient {
963
809
  * ```ts
964
810
  * import * as hl from "@nktkas/hyperliquid";
965
811
  *
966
- * const privateKey = "0x..."; // or `viem`, `ethers`
812
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
967
813
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
968
814
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
969
815
  *
@@ -978,221 +824,131 @@ export class ExchangeClient {
978
824
  * onlyIsolated: false,
979
825
  * },
980
826
  * dex: "test",
827
+ * schema: null,
981
828
  * },
982
829
  * });
983
830
  * ```
984
831
  */
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,
832
+ async perpDeploy(params, opts) {
833
+ const action = actionSorter.perpDeploy({
834
+ type: "perpDeploy",
835
+ ...params,
997
836
  });
998
- // Send a request
999
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1000
- this._validateResponse(response);
1001
- return response;
837
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
838
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
1002
839
  }
1003
840
  /**
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.
841
+ * Create a referral code.
842
+ * @param params - Action-specific parameters.
843
+ * @param opts - Request execution options.
1007
844
  * @returns Successful response without specific data.
1008
845
  *
1009
846
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
1010
847
  * @throws {TransportError} When the transport layer throws an error.
1011
848
  *
1012
- * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#transfer-from-spot-account-to-perp-account-and-vice-versa
849
+ * @see null
1013
850
  * @example
1014
851
  * ```ts
1015
852
  * import * as hl from "@nktkas/hyperliquid";
1016
853
  *
1017
- * const privateKey = "0x..."; // or `viem`, `ethers`
854
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1018
855
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1019
856
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1020
857
  *
1021
- * await exchClient.perpDexClassTransfer({ dex: "test", token: "USDC", amount: "1", toPerp: true });
858
+ * await exchClient.registerReferrer({ code: "..." });
1022
859
  * ```
1023
860
  */
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],
861
+ async registerReferrer(params, opts) {
862
+ const action = actionSorter.registerReferrer({
863
+ type: "registerReferrer",
864
+ ...params,
1041
865
  });
1042
- // Send a request
1043
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1044
- this._validateResponse(response);
1045
- return response;
866
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
867
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
1046
868
  }
1047
869
  /**
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.
870
+ * Reserve additional rate-limited actions for a fee.
871
+ * @param params - Action-specific parameters.
872
+ * @param opts - Request execution options.
1051
873
  * @returns Successful response without specific data.
1052
874
  *
1053
875
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
1054
876
  * @throws {TransportError} When the transport layer throws an error.
1055
877
  *
1056
- * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#transfer-from-perp-account-to-perp-account-for-builder-deployed-dex
878
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#reserve-additional-actions
1057
879
  * @example
1058
880
  * ```ts
1059
881
  * import * as hl from "@nktkas/hyperliquid";
1060
882
  *
1061
- * const privateKey = "0x..."; // or `viem`, `ethers`
883
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1062
884
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1063
885
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1064
886
  *
1065
- * await exchClient.perpDexTransfer({ sourceDex: "", destinationDex: "test", amount: "1" });
887
+ * await exchClient.reserveRequestWeight({ weight: 10 });
1066
888
  * ```
1067
889
  */
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,
890
+ async reserveRequestWeight(params, opts) {
891
+ const action = actionSorter.reserveRequestWeight({
892
+ type: "reserveRequestWeight",
893
+ ...params,
1079
894
  });
1080
- // Sign the action
1081
- const signature = await signUserSignedAction({
1082
- wallet: this.wallet,
1083
- action,
1084
- types: userSignedActionEip712Types[action.type],
1085
- });
1086
- // Send a request
1087
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1088
- this._validateResponse(response);
1089
- return response;
895
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
896
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
1090
897
  }
1091
- /**
1092
- * Create a referral code.
1093
- * @param args - The parameters for the request.
1094
- * @param signal - An optional abort signal.
1095
- * @returns Successful response without specific data.
1096
- *
1097
- * @throws {ApiRequestError} When the API returns an unsuccessful response.
1098
- * @throws {TransportError} When the transport layer throws an error.
1099
- *
1100
- * @see null
1101
- * @example
1102
- * ```ts
1103
- * import * as hl from "@nktkas/hyperliquid";
1104
- *
1105
- * const privateKey = "0x..."; // or `viem`, `ethers`
1106
- * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1107
- * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1108
- *
1109
- * await exchClient.registerReferrer({ code: "..." });
1110
- * ```
1111
- */
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,
898
+ async scheduleCancel(params_or_opts, maybeOpts) {
899
+ const isFirstArgParams = params_or_opts && "time" in params_or_opts;
900
+ const params = isFirstArgParams ? params_or_opts : {};
901
+ const opts = isFirstArgParams ? maybeOpts : params_or_opts;
902
+ const action = actionSorter.scheduleCancel({
903
+ type: "scheduleCancel",
904
+ ...params,
1124
905
  });
1125
- // Send a request
1126
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1127
- this._validateResponse(response);
1128
- return response;
906
+ const vaultAddress = opts?.vaultAddress ?? this.defaultVaultAddress;
907
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
908
+ return await this._executeL1Action({ action, vaultAddress, expiresAfter }, opts?.signal);
1129
909
  }
1130
910
  /**
1131
- * Reserve additional rate-limited actions for a fee.
1132
- * @param args - The parameters for the request.
1133
- * @param signal - An optional abort signal.
911
+ * Transfer tokens between different perp DEXs, spot balance, users, and/or sub-accounts.
912
+ * @param params - Action-specific parameters.
913
+ * @param opts - Request execution options.
1134
914
  * @returns Successful response without specific data.
1135
915
  *
1136
916
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
1137
917
  * @throws {TransportError} When the transport layer throws an error.
1138
918
  *
1139
- * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#reserve-additional-actions
919
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#send-asset-testnet-only
1140
920
  * @example
1141
921
  * ```ts
1142
922
  * import * as hl from "@nktkas/hyperliquid";
1143
923
  *
1144
- * const privateKey = "0x..."; // or `viem`, `ethers`
924
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1145
925
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1146
926
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1147
927
  *
1148
- * await exchClient.reserveRequestWeight({ weight: 10 });
928
+ * await exchClient.sendAsset({
929
+ * destination: "0x0000000000000000000000000000000000000001",
930
+ * sourceDex: "",
931
+ * destinationDex: "test",
932
+ * token: "USDC:0xeb62eee3685fc4c43992febcd9e75443",
933
+ * amount: "1",
934
+ * fromSubAccount: "",
935
+ * });
1149
936
  * ```
1150
937
  */
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,
938
+ async sendAsset(params, opts) {
939
+ const action = actionSorter.sendAsset({
940
+ type: "sendAsset",
941
+ hyperliquidChain: this._getHyperliquidChain(),
942
+ signatureChainId: await this._getSignatureChainId(),
943
+ nonce: await this.nonceManager(),
944
+ ...params,
1186
945
  });
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;
946
+ return await this._executeUserSignedAction({ action }, opts?.signal);
1191
947
  }
1192
948
  /**
1193
949
  * Set the display name in the leaderboard.
1194
- * @param args - The parameters for the request.
1195
- * @param signal - An optional abort signal.
950
+ * @param params - Action-specific parameters.
951
+ * @param opts - Request execution options.
1196
952
  * @returns Successful response without specific data.
1197
953
  *
1198
954
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1203,35 +959,25 @@ export class ExchangeClient {
1203
959
  * ```ts
1204
960
  * import * as hl from "@nktkas/hyperliquid";
1205
961
  *
1206
- * const privateKey = "0x..."; // or `viem`, `ethers`
962
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1207
963
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1208
964
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1209
965
  *
1210
966
  * await exchClient.setDisplayName({ displayName: "..." });
1211
967
  * ```
1212
968
  */
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,
969
+ async setDisplayName(params, opts) {
970
+ const action = actionSorter.setDisplayName({
971
+ type: "setDisplayName",
972
+ ...params,
1225
973
  });
1226
- // Send a request
1227
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1228
- this._validateResponse(response);
1229
- return response;
974
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
975
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
1230
976
  }
1231
977
  /**
1232
978
  * Set a referral code.
1233
- * @param args - The parameters for the request.
1234
- * @param signal - An optional abort signal.
979
+ * @param params - Action-specific parameters.
980
+ * @param opts - Request execution options.
1235
981
  * @returns Successful response without specific data.
1236
982
  *
1237
983
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1242,35 +988,25 @@ export class ExchangeClient {
1242
988
  * ```ts
1243
989
  * import * as hl from "@nktkas/hyperliquid";
1244
990
  *
1245
- * const privateKey = "0x..."; // or `viem`, `ethers`
991
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1246
992
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1247
993
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1248
994
  *
1249
995
  * await exchClient.setReferrer({ code: "..." });
1250
996
  * ```
1251
997
  */
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,
998
+ async setReferrer(params, opts) {
999
+ const action = actionSorter.setReferrer({
1000
+ type: "setReferrer",
1001
+ ...params,
1264
1002
  });
1265
- // Send a request
1266
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1267
- this._validateResponse(response);
1268
- return response;
1003
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
1004
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
1269
1005
  }
1270
1006
  /**
1271
1007
  * Deploying HIP-1 and HIP-2 assets.
1272
- * @param args - The parameters for the request.
1273
- * @param signal - An optional abort signal.
1008
+ * @param params - Action-specific parameters.
1009
+ * @param opts - Request execution options.
1274
1010
  * @returns Successful response without specific data.
1275
1011
  *
1276
1012
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1281,7 +1017,7 @@ export class ExchangeClient {
1281
1017
  * ```ts
1282
1018
  * import * as hl from "@nktkas/hyperliquid";
1283
1019
  *
1284
- * const privateKey = "0x..."; // or `viem`, `ethers`
1020
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1285
1021
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1286
1022
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1287
1023
  *
@@ -1298,28 +1034,18 @@ export class ExchangeClient {
1298
1034
  * });
1299
1035
  * ```
1300
1036
  */
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,
1037
+ async spotDeploy(params, opts) {
1038
+ const action = actionSorter.spotDeploy({
1039
+ type: "spotDeploy",
1040
+ ...params,
1313
1041
  });
1314
- // Send a request
1315
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1316
- this._validateResponse(response);
1317
- return response;
1042
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
1043
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
1318
1044
  }
1319
1045
  /**
1320
1046
  * Send spot assets to another address.
1321
- * @param args - The parameters for the request.
1322
- * @param signal - An optional abort signal.
1047
+ * @param params - Action-specific parameters.
1048
+ * @param opts - Request execution options.
1323
1049
  * @returns Successful response without specific data.
1324
1050
  *
1325
1051
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1330,7 +1056,7 @@ export class ExchangeClient {
1330
1056
  * ```ts
1331
1057
  * import * as hl from "@nktkas/hyperliquid";
1332
1058
  *
1333
- * const privateKey = "0x..."; // or `viem`, `ethers`
1059
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1334
1060
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1335
1061
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1336
1062
  *
@@ -1341,33 +1067,20 @@ export class ExchangeClient {
1341
1067
  * });
1342
1068
  * ```
1343
1069
  */
1344
- async spotSend(args, signal) {
1345
- // Destructure the parameters
1346
- const { ...actionArgs } = args;
1347
- // Construct an action
1348
- const nonce = await this.nonceManager();
1070
+ async spotSend(params, opts) {
1349
1071
  const action = actionSorter.spotSend({
1350
1072
  type: "spotSend",
1351
1073
  hyperliquidChain: this._getHyperliquidChain(),
1352
1074
  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],
1075
+ time: await this.nonceManager(),
1076
+ ...params,
1361
1077
  });
1362
- // Send a request
1363
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1364
- this._validateResponse(response);
1365
- return response;
1078
+ return await this._executeUserSignedAction({ action }, opts?.signal);
1366
1079
  }
1367
1080
  /**
1368
1081
  * Opt Out of Spot Dusting.
1369
- * @param args - The parameters for the request.
1370
- * @param signal - An optional abort signal.
1082
+ * @param params - Action-specific parameters.
1083
+ * @param opts - Request execution options.
1371
1084
  * @returns Successful response without specific data.
1372
1085
  *
1373
1086
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1378,35 +1091,54 @@ export class ExchangeClient {
1378
1091
  * ```ts
1379
1092
  * import * as hl from "@nktkas/hyperliquid";
1380
1093
  *
1381
- * const privateKey = "0x..."; // or `viem`, `ethers`
1094
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1382
1095
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1383
1096
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1384
1097
  *
1385
1098
  * await exchClient.spotUser({ toggleSpotDusting: { optOut: false } });
1386
1099
  * ```
1387
1100
  */
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,
1101
+ async spotUser(params, opts) {
1102
+ const action = actionSorter.spotUser({
1103
+ type: "spotUser",
1104
+ ...params,
1400
1105
  });
1401
- // Send a request
1402
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1403
- this._validateResponse(response);
1404
- return response;
1106
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
1107
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
1108
+ }
1109
+ /**
1110
+ * Modify a sub-account's.
1111
+ * @param params - Action-specific parameters.
1112
+ * @param opts - Request execution options.
1113
+ * @returns Successful response without specific data.
1114
+ *
1115
+ * @throws {ApiRequestError} When the API returns an unsuccessful response.
1116
+ * @throws {TransportError} When the transport layer throws an error.
1117
+ *
1118
+ * @see null
1119
+ * @example
1120
+ * ```ts
1121
+ * import * as hl from "@nktkas/hyperliquid";
1122
+ *
1123
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1124
+ * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1125
+ * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1126
+ *
1127
+ * await exchClient.subAccountModify({ subAccountUser: "0x...", name: "..." });
1128
+ * ```
1129
+ */
1130
+ async subAccountModify(params, opts) {
1131
+ const action = actionSorter.subAccountModify({
1132
+ type: "subAccountModify",
1133
+ ...params,
1134
+ });
1135
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
1136
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
1405
1137
  }
1406
1138
  /**
1407
1139
  * Transfer between sub-accounts (spot).
1408
- * @param args - The parameters for the request.
1409
- * @param signal - An optional abort signal.
1140
+ * @param params - Action-specific parameters.
1141
+ * @param opts - Request execution options.
1410
1142
  * @returns Successful response without specific data.
1411
1143
  *
1412
1144
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1417,7 +1149,7 @@ export class ExchangeClient {
1417
1149
  * ```ts
1418
1150
  * import * as hl from "@nktkas/hyperliquid";
1419
1151
  *
1420
- * const privateKey = "0x..."; // or `viem`, `ethers`
1152
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1421
1153
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1422
1154
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1423
1155
  *
@@ -1429,28 +1161,18 @@ export class ExchangeClient {
1429
1161
  * });
1430
1162
  * ```
1431
1163
  */
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,
1164
+ async subAccountSpotTransfer(params, opts) {
1165
+ const action = actionSorter.subAccountSpotTransfer({
1166
+ type: "subAccountSpotTransfer",
1167
+ ...params,
1444
1168
  });
1445
- // Send a request
1446
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1447
- this._validateResponse(response);
1448
- return response;
1169
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
1170
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
1449
1171
  }
1450
1172
  /**
1451
1173
  * Transfer between sub-accounts (perpetual).
1452
- * @param args - The parameters for the request.
1453
- * @param signal - An optional abort signal.
1174
+ * @param params - Action-specific parameters.
1175
+ * @param opts - Request execution options.
1454
1176
  * @returns Successful response without specific data.
1455
1177
  *
1456
1178
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1461,35 +1183,25 @@ export class ExchangeClient {
1461
1183
  * ```ts
1462
1184
  * import * as hl from "@nktkas/hyperliquid";
1463
1185
  *
1464
- * const privateKey = "0x..."; // or `viem`, `ethers`
1186
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1465
1187
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1466
1188
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1467
1189
  *
1468
1190
  * await exchClient.subAccountTransfer({ subAccountUser: "0x...", isDeposit: true, usd: 1 * 1e6 });
1469
1191
  * ```
1470
1192
  */
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,
1193
+ async subAccountTransfer(params, opts) {
1194
+ const action = actionSorter.subAccountTransfer({
1195
+ type: "subAccountTransfer",
1196
+ ...params,
1483
1197
  });
1484
- // Send a request
1485
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1486
- this._validateResponse(response);
1487
- return response;
1198
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
1199
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
1488
1200
  }
1489
1201
  /**
1490
1202
  * 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.
1203
+ * @param params - Action-specific parameters.
1204
+ * @param opts - Request execution options.
1493
1205
  * @returns Successful response without specific data.
1494
1206
  *
1495
1207
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1500,40 +1212,27 @@ export class ExchangeClient {
1500
1212
  * ```ts
1501
1213
  * import * as hl from "@nktkas/hyperliquid";
1502
1214
  *
1503
- * const privateKey = "0x..."; // or `viem`, `ethers`
1215
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1504
1216
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1505
1217
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1506
1218
  *
1507
1219
  * await exchClient.tokenDelegate({ validator: "0x...", isUndelegate: true, wei: 1 * 1e8 });
1508
1220
  * ```
1509
1221
  */
1510
- async tokenDelegate(args, signal) {
1511
- // Destructure the parameters
1512
- const { ...actionArgs } = args;
1513
- // Construct an action
1514
- const nonce = await this.nonceManager();
1222
+ async tokenDelegate(params, opts) {
1515
1223
  const action = actionSorter.tokenDelegate({
1516
1224
  type: "tokenDelegate",
1517
1225
  hyperliquidChain: this._getHyperliquidChain(),
1518
1226
  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],
1227
+ nonce: await this.nonceManager(),
1228
+ ...params,
1527
1229
  });
1528
- // Send a request
1529
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1530
- this._validateResponse(response);
1531
- return response;
1230
+ return await this._executeUserSignedAction({ action }, opts?.signal);
1532
1231
  }
1533
1232
  /**
1534
1233
  * Cancel a TWAP order.
1535
- * @param args - The parameters for the request.
1536
- * @param signal - An optional abort signal.
1234
+ * @param params - Action-specific parameters.
1235
+ * @param opts - Request execution options.
1537
1236
  * @returns Successful variant of {@link TwapCancelResponse} without error status.
1538
1237
  *
1539
1238
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1544,37 +1243,26 @@ export class ExchangeClient {
1544
1243
  * ```ts
1545
1244
  * import * as hl from "@nktkas/hyperliquid";
1546
1245
  *
1547
- * const privateKey = "0x..."; // or `viem`, `ethers`
1246
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1548
1247
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1549
1248
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1550
1249
  *
1551
1250
  * const data = await exchClient.twapCancel({ a: 0, t: 1 });
1552
1251
  * ```
1553
1252
  */
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,
1253
+ async twapCancel(params, opts) {
1254
+ const action = actionSorter.twapCancel({
1255
+ type: "twapCancel",
1256
+ ...params,
1568
1257
  });
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;
1258
+ const vaultAddress = opts?.vaultAddress ?? this.defaultVaultAddress;
1259
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
1260
+ return await this._executeL1Action({ action, vaultAddress, expiresAfter }, opts?.signal);
1573
1261
  }
1574
1262
  /**
1575
1263
  * Place a TWAP order.
1576
- * @param args - The parameters for the request.
1577
- * @param signal - An optional abort signal.
1264
+ * @param params - Action-specific parameters.
1265
+ * @param opts - Request execution options.
1578
1266
  * @returns Successful variant of {@link TwapOrderResponse} without error status.
1579
1267
  *
1580
1268
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1585,44 +1273,35 @@ export class ExchangeClient {
1585
1273
  * ```ts
1586
1274
  * import * as hl from "@nktkas/hyperliquid";
1587
1275
  *
1588
- * const privateKey = "0x..."; // or `viem`, `ethers`
1276
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1589
1277
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1590
1278
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1591
1279
  *
1592
1280
  * const data = await exchClient.twapOrder({
1593
- * a: 0,
1594
- * b: true,
1595
- * s: "1",
1596
- * r: false,
1597
- * m: 10,
1598
- * t: true,
1281
+ * twap: {
1282
+ * a: 0,
1283
+ * b: true,
1284
+ * s: "1",
1285
+ * r: false,
1286
+ * m: 10,
1287
+ * t: true,
1288
+ * },
1599
1289
  * });
1600
1290
  * ```
1601
1291
  */
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,
1292
+ async twapOrder(params, opts) {
1293
+ const action = actionSorter.twapOrder({
1294
+ type: "twapOrder",
1295
+ ...params,
1616
1296
  });
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;
1297
+ const vaultAddress = opts?.vaultAddress ?? this.defaultVaultAddress;
1298
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
1299
+ return await this._executeL1Action({ action, vaultAddress, expiresAfter }, opts?.signal);
1621
1300
  }
1622
1301
  /**
1623
1302
  * Add or remove margin from isolated position.
1624
- * @param args - The parameters for the request.
1625
- * @param signal - An optional abort signal.
1303
+ * @param params - Action-specific parameters.
1304
+ * @param opts - Request execution options.
1626
1305
  * @returns Successful response without specific data.
1627
1306
  *
1628
1307
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1633,37 +1312,26 @@ export class ExchangeClient {
1633
1312
  * ```ts
1634
1313
  * import * as hl from "@nktkas/hyperliquid";
1635
1314
  *
1636
- * const privateKey = "0x..."; // or `viem`, `ethers`
1315
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1637
1316
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1638
1317
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1639
1318
  *
1640
1319
  * await exchClient.updateIsolatedMargin({ asset: 0, isBuy: true, ntli: 1 * 1e6 });
1641
1320
  * ```
1642
1321
  */
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,
1322
+ async updateIsolatedMargin(params, opts) {
1323
+ const action = actionSorter.updateIsolatedMargin({
1324
+ type: "updateIsolatedMargin",
1325
+ ...params,
1657
1326
  });
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;
1327
+ const vaultAddress = opts?.vaultAddress ?? this.defaultVaultAddress;
1328
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
1329
+ return await this._executeL1Action({ action, vaultAddress, expiresAfter }, opts?.signal);
1662
1330
  }
1663
1331
  /**
1664
1332
  * Update cross or isolated leverage on a coin.
1665
- * @param args - The parameters for the request.
1666
- * @param signal - An optional abort signal.
1333
+ * @param params - Action-specific parameters.
1334
+ * @param opts - Request execution options.
1667
1335
  * @returns Successful response without specific data.
1668
1336
  *
1669
1337
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1674,37 +1342,26 @@ export class ExchangeClient {
1674
1342
  * ```ts
1675
1343
  * import * as hl from "@nktkas/hyperliquid";
1676
1344
  *
1677
- * const privateKey = "0x..."; // or `viem`, `ethers`
1345
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1678
1346
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1679
1347
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1680
1348
  *
1681
1349
  * await exchClient.updateLeverage({ asset: 0, isCross: true, leverage: 5 });
1682
1350
  * ```
1683
1351
  */
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,
1352
+ async updateLeverage(params, opts) {
1353
+ const action = actionSorter.updateLeverage({
1354
+ type: "updateLeverage",
1355
+ ...params,
1698
1356
  });
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;
1357
+ const vaultAddress = opts?.vaultAddress ?? this.defaultVaultAddress;
1358
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
1359
+ return await this._executeL1Action({ action, vaultAddress, expiresAfter }, opts?.signal);
1703
1360
  }
1704
1361
  /**
1705
1362
  * Transfer funds between Spot account and Perp account.
1706
- * @param args - The parameters for the request.
1707
- * @param signal - An optional abort signal.
1363
+ * @param params - Action-specific parameters.
1364
+ * @param opts - Request execution options.
1708
1365
  * @returns Successful response without specific data.
1709
1366
  *
1710
1367
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1715,40 +1372,27 @@ export class ExchangeClient {
1715
1372
  * ```ts
1716
1373
  * import * as hl from "@nktkas/hyperliquid";
1717
1374
  *
1718
- * const privateKey = "0x..."; // or `viem`, `ethers`
1375
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1719
1376
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1720
1377
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1721
1378
  *
1722
1379
  * await exchClient.usdClassTransfer({ amount: "1", toPerp: true });
1723
1380
  * ```
1724
1381
  */
1725
- async usdClassTransfer(args, signal) {
1726
- // Destructure the parameters
1727
- const { ...actionArgs } = args;
1728
- // Construct an action
1729
- const nonce = await this.nonceManager();
1382
+ async usdClassTransfer(params, opts) {
1730
1383
  const action = actionSorter.usdClassTransfer({
1731
1384
  type: "usdClassTransfer",
1732
1385
  hyperliquidChain: this._getHyperliquidChain(),
1733
1386
  signatureChainId: await this._getSignatureChainId(),
1734
- nonce,
1735
- ...actionArgs,
1387
+ nonce: await this.nonceManager(),
1388
+ ...params,
1736
1389
  });
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;
1390
+ return await this._executeUserSignedAction({ action }, opts?.signal);
1747
1391
  }
1748
1392
  /**
1749
1393
  * Send usd to another address.
1750
- * @param args - The parameters for the request.
1751
- * @param signal - An optional abort signal.
1394
+ * @param params - Action-specific parameters.
1395
+ * @param opts - Request execution options.
1752
1396
  * @returns Successful response without specific data.
1753
1397
  *
1754
1398
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1759,40 +1403,27 @@ export class ExchangeClient {
1759
1403
  * ```ts
1760
1404
  * import * as hl from "@nktkas/hyperliquid";
1761
1405
  *
1762
- * const privateKey = "0x..."; // or `viem`, `ethers`
1406
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1763
1407
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1764
1408
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1765
1409
  *
1766
1410
  * await exchClient.usdSend({ destination: "0x...", amount: "1" });
1767
1411
  * ```
1768
1412
  */
1769
- async usdSend(args, signal) {
1770
- // Destructure the parameters
1771
- const { ...actionArgs } = args;
1772
- // Construct an action
1773
- const nonce = await this.nonceManager();
1413
+ async usdSend(params, opts) {
1774
1414
  const action = actionSorter.usdSend({
1775
1415
  type: "usdSend",
1776
1416
  hyperliquidChain: this._getHyperliquidChain(),
1777
1417
  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],
1418
+ time: await this.nonceManager(),
1419
+ ...params,
1786
1420
  });
1787
- // Send a request
1788
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1789
- this._validateResponse(response);
1790
- return response;
1421
+ return await this._executeUserSignedAction({ action }, opts?.signal);
1791
1422
  }
1792
1423
  /**
1793
1424
  * Distribute funds from a vault between followers.
1794
- * @param args - The parameters for the request.
1795
- * @param signal - An optional abort signal.
1425
+ * @param params - Action-specific parameters.
1426
+ * @param opts - Request execution options.
1796
1427
  * @returns Successful response without specific data.
1797
1428
  *
1798
1429
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1803,35 +1434,25 @@ export class ExchangeClient {
1803
1434
  * ```ts
1804
1435
  * import * as hl from "@nktkas/hyperliquid";
1805
1436
  *
1806
- * const privateKey = "0x..."; // or `viem`, `ethers`
1437
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1807
1438
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1808
1439
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1809
1440
  *
1810
1441
  * await exchClient.vaultDistribute({ vaultAddress: "0x...", usd: 10 * 1e6 });
1811
1442
  * ```
1812
1443
  */
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,
1444
+ async vaultDistribute(params, opts) {
1445
+ const action = actionSorter.vaultDistribute({
1446
+ type: "vaultDistribute",
1447
+ ...params,
1825
1448
  });
1826
- // Send a request
1827
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1828
- this._validateResponse(response);
1829
- return response;
1449
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
1450
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
1830
1451
  }
1831
1452
  /**
1832
1453
  * Modify a vault's configuration.
1833
- * @param args - The parameters for the request.
1834
- * @param signal - An optional abort signal.
1454
+ * @param params - Action-specific parameters.
1455
+ * @param opts - Request execution options.
1835
1456
  * @returns Successful response without specific data.
1836
1457
  *
1837
1458
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1842,7 +1463,7 @@ export class ExchangeClient {
1842
1463
  * ```ts
1843
1464
  * import * as hl from "@nktkas/hyperliquid";
1844
1465
  *
1845
- * const privateKey = "0x..."; // or `viem`, `ethers`
1466
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1846
1467
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1847
1468
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1848
1469
  *
@@ -1853,28 +1474,18 @@ export class ExchangeClient {
1853
1474
  * });
1854
1475
  * ```
1855
1476
  */
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,
1477
+ async vaultModify(params, opts) {
1478
+ const action = actionSorter.vaultModify({
1479
+ type: "vaultModify",
1480
+ ...params,
1868
1481
  });
1869
- // Send a request
1870
- const response = await this.transport.request("exchange", { action, signature, nonce }, signal);
1871
- this._validateResponse(response);
1872
- return response;
1482
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
1483
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
1873
1484
  }
1874
1485
  /**
1875
1486
  * Deposit or withdraw from a vault.
1876
- * @param args - The parameters for the request.
1877
- * @param signal - An optional abort signal.
1487
+ * @param params - Action-specific parameters.
1488
+ * @param opts - Request execution options.
1878
1489
  * @returns Successful response without specific data.
1879
1490
  *
1880
1491
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1885,36 +1496,25 @@ export class ExchangeClient {
1885
1496
  * ```ts
1886
1497
  * import * as hl from "@nktkas/hyperliquid";
1887
1498
  *
1888
- * const privateKey = "0x..."; // or `viem`, `ethers`
1499
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1889
1500
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1890
1501
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1891
1502
  *
1892
1503
  * await exchClient.vaultTransfer({ vaultAddress: "0x...", isDeposit: true, usd: 10 * 1e6 });
1893
1504
  * ```
1894
1505
  */
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,
1506
+ async vaultTransfer(params, opts) {
1507
+ const action = actionSorter.vaultTransfer({
1508
+ type: "vaultTransfer",
1509
+ ...params,
1908
1510
  });
1909
- // Send a request
1910
- const response = await this.transport.request("exchange", { action, signature, nonce, expiresAfter }, signal);
1911
- this._validateResponse(response);
1912
- return response;
1511
+ const expiresAfter = opts?.expiresAfter ?? await this._getDefaultExpiresAfter();
1512
+ return await this._executeL1Action({ action, expiresAfter }, opts?.signal);
1913
1513
  }
1914
1514
  /**
1915
1515
  * Initiate a withdrawal request.
1916
- * @param args - The parameters for the request.
1917
- * @param signal - An optional abort signal.
1516
+ * @param params - Action-specific parameters.
1517
+ * @param opts - Request execution options.
1918
1518
  * @returns Successful response without specific data.
1919
1519
  *
1920
1520
  * @throws {ApiRequestError} When the API returns an unsuccessful response.
@@ -1925,26 +1525,44 @@ export class ExchangeClient {
1925
1525
  * ```ts
1926
1526
  * import * as hl from "@nktkas/hyperliquid";
1927
1527
  *
1928
- * const privateKey = "0x..."; // or `viem`, `ethers`
1528
+ * const privateKey = "0x..."; // `viem`, `ethers`, or private key directly`
1929
1529
  * const transport = new hl.HttpTransport(); // or `WebSocketTransport`
1930
1530
  * const exchClient = new hl.ExchangeClient({ wallet: privateKey, transport });
1931
1531
  *
1932
1532
  * await exchClient.withdraw3({ destination: "0x...", amount: "1" });
1933
1533
  * ```
1934
1534
  */
1935
- async withdraw3(args, signal) {
1936
- // Destructure the parameters
1937
- const { ...actionArgs } = args;
1938
- // Construct an action
1939
- const nonce = await this.nonceManager();
1535
+ async withdraw3(params, opts) {
1940
1536
  const action = actionSorter.withdraw3({
1941
1537
  type: "withdraw3",
1942
1538
  hyperliquidChain: this._getHyperliquidChain(),
1943
1539
  signatureChainId: await this._getSignatureChainId(),
1944
- time: nonce,
1945
- ...actionArgs,
1540
+ time: await this.nonceManager(),
1541
+ ...params,
1946
1542
  });
1947
- // Sign the action
1543
+ return await this._executeUserSignedAction({ action }, opts?.signal);
1544
+ }
1545
+ async _executeL1Action(request, signal) {
1546
+ const { action, vaultAddress, expiresAfter } = request;
1547
+ // Sign an L1 action
1548
+ const nonce = await this.nonceManager();
1549
+ const signature = await signL1Action({
1550
+ wallet: this.wallet,
1551
+ action,
1552
+ nonce,
1553
+ isTestnet: this.isTestnet,
1554
+ vaultAddress,
1555
+ expiresAfter,
1556
+ });
1557
+ // Send a request
1558
+ const response = await this.transport.request("exchange", { action, signature, nonce, vaultAddress, expiresAfter }, signal);
1559
+ this._validateResponse(response);
1560
+ return response;
1561
+ }
1562
+ async _executeUserSignedAction(request, signal) {
1563
+ const { action } = request;
1564
+ // Sign a user-signed action
1565
+ const nonce = "nonce" in action ? action.nonce : action.time;
1948
1566
  const signature = await signUserSignedAction({
1949
1567
  wallet: this.wallet,
1950
1568
  action,
@@ -1955,46 +1573,33 @@ export class ExchangeClient {
1955
1573
  this._validateResponse(response);
1956
1574
  return response;
1957
1575
  }
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";
1576
+ async _executeMultiSigAction(request, signal) {
1577
+ const { action, nonce, vaultAddress, expiresAfter } = request;
1578
+ // Sign a multi-signature action
1579
+ const signature = await signMultiSigAction({
1580
+ wallet: this.wallet,
1581
+ action,
1582
+ nonce,
1583
+ isTestnet: this.isTestnet,
1584
+ vaultAddress,
1585
+ expiresAfter,
1586
+ });
1587
+ // Send a request
1588
+ const response = await this.transport.request("exchange", { action, signature, nonce, vaultAddress, expiresAfter }, signal);
1589
+ this._validateResponse(response);
1590
+ return response;
1982
1591
  }
1983
- /** Get the default expiration time for an action. */
1984
1592
  async _getDefaultExpiresAfter() {
1985
1593
  return typeof this.defaultExpiresAfter === "number"
1986
1594
  ? this.defaultExpiresAfter
1987
1595
  : await this.defaultExpiresAfter?.();
1988
1596
  }
1989
- /** Get the signature chain ID for the wallet. */
1990
1597
  async _getSignatureChainId() {
1991
1598
  return typeof this.signatureChainId === "string" ? this.signatureChainId : await this.signatureChainId();
1992
1599
  }
1993
- /** Get the Hyperliquid chain based on the isTestnet flag. */
1994
1600
  _getHyperliquidChain() {
1995
1601
  return this.isTestnet ? "Testnet" : "Mainnet";
1996
1602
  }
1997
- /** Validate a response from the API. */
1998
1603
  _validateResponse(response) {
1999
1604
  if (response.status === "err") {
2000
1605
  throw new ApiRequestError(response);