@nktkas/hyperliquid 0.21.0 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/CONTRIBUTING.md +19 -34
  2. package/README.md +212 -87
  3. package/esm/mod.d.ts +4 -3
  4. package/esm/mod.d.ts.map +1 -1
  5. package/esm/mod.js +3 -2
  6. package/esm/src/clients/exchange.d.ts +102 -59
  7. package/esm/src/clients/exchange.d.ts.map +1 -1
  8. package/esm/src/clients/exchange.js +233 -516
  9. package/esm/src/clients/info.d.ts +55 -55
  10. package/esm/src/clients/info.d.ts.map +1 -1
  11. package/esm/src/clients/info.js +57 -54
  12. package/esm/src/clients/multiSign.d.ts +1293 -0
  13. package/esm/src/clients/multiSign.d.ts.map +1 -0
  14. package/esm/src/clients/multiSign.js +2156 -0
  15. package/esm/src/clients/subscription.d.ts +19 -19
  16. package/esm/src/clients/subscription.d.ts.map +1 -1
  17. package/esm/src/clients/subscription.js +17 -17
  18. package/esm/src/signing.d.ts +164 -40
  19. package/esm/src/signing.d.ts.map +1 -1
  20. package/esm/src/signing.js +710 -9
  21. package/esm/src/types/exchange/requests.d.ts +240 -245
  22. package/esm/src/types/exchange/requests.d.ts.map +1 -1
  23. package/esm/src/types/info/accounts.d.ts +11 -0
  24. package/esm/src/types/info/accounts.d.ts.map +1 -1
  25. package/package.json +2 -1
  26. package/script/mod.d.ts +4 -3
  27. package/script/mod.d.ts.map +1 -1
  28. package/script/mod.js +4 -3
  29. package/script/src/clients/exchange.d.ts +102 -59
  30. package/script/src/clients/exchange.d.ts.map +1 -1
  31. package/script/src/clients/exchange.js +232 -515
  32. package/script/src/clients/info.d.ts +55 -55
  33. package/script/src/clients/info.d.ts.map +1 -1
  34. package/script/src/clients/info.js +57 -54
  35. package/script/src/clients/multiSign.d.ts +1293 -0
  36. package/script/src/clients/multiSign.d.ts.map +1 -0
  37. package/script/src/clients/multiSign.js +2170 -0
  38. package/script/src/clients/subscription.d.ts +19 -19
  39. package/script/src/clients/subscription.d.ts.map +1 -1
  40. package/script/src/clients/subscription.js +17 -17
  41. package/script/src/signing.d.ts +164 -40
  42. package/script/src/signing.d.ts.map +1 -1
  43. package/script/src/signing.js +711 -10
  44. package/script/src/types/exchange/requests.d.ts +240 -245
  45. package/script/src/types/exchange/requests.d.ts.map +1 -1
  46. package/script/src/types/info/accounts.d.ts +11 -0
  47. package/script/src/types/info/accounts.d.ts.map +1 -1
@@ -1,35 +1,35 @@
1
1
  import { HyperliquidError } from "../base.js";
2
- import { isAbstractEthersSigner, isAbstractEthersV5Signer, isAbstractExtendedViemWalletClient, isAbstractViemWalletClient, isAbstractWindowEthereum, signL1Action, signMultiSigAction, signUserSignedAction, } from "../signing.js";
2
+ import { actionSorter, isAbstractEthersSigner, isAbstractEthersV5Signer, isAbstractViemWalletClient, isAbstractWindowEthereum, signL1Action, signMultiSigAction, signUserSignedAction, userSignedActionEip712Types, } from "../signing.js";
3
3
  /** Error thrown when the API returns an error response. */
4
4
  export class ApiRequestError extends HyperliquidError {
5
5
  response;
6
6
  constructor(response) {
7
- let message = "Cannot process API request";
7
+ let message;
8
8
  if (response.status === "err") {
9
- // For ErrorResponse
10
- message += `: ${response.response}`;
9
+ // ErrorResponse
10
+ message = response.response;
11
11
  }
12
12
  else {
13
13
  if ("statuses" in response.response.data) {
14
- // For OrderResponse, CancelResponse
14
+ // OrderResponse | CancelResponse
15
15
  const errors = response.response.data.statuses.reduce((acc, status, index) => {
16
16
  if (typeof status === "object" && "error" in status) {
17
- acc.push(`Order ${index} failed: ${status.error}`);
17
+ acc.push(`Order ${index}: ${status.error}`);
18
18
  }
19
19
  return acc;
20
20
  }, []);
21
21
  if (errors.length > 0) {
22
- message += `: ${errors.join(", ")}`;
22
+ message = errors.join(", ");
23
23
  }
24
24
  }
25
25
  else {
26
- // For TwapOrderResponse, TwapCancelResponse
26
+ // TwapOrderResponse | TwapCancelResponse
27
27
  if (typeof response.response.data.status === "object" && "error" in response.response.data.status) {
28
- message += `: ${response.response.data.status.error}`;
28
+ message = response.response.data.status.error;
29
29
  }
30
30
  }
31
31
  }
32
- super(message);
32
+ super(message || "An unknown error occurred while processing an API request. See `response` for more details.");
33
33
  this.response = response;
34
34
  this.name = "ApiRequestError";
35
35
  }
@@ -56,7 +56,7 @@ class NonceManager {
56
56
  /**
57
57
  * Exchange client for interacting with the Hyperliquid API.
58
58
  * @typeParam T The transport used to connect to the Hyperliquid API.
59
- * @typeParam W The WalletClient/Account ([viem](https://viem.sh/docs/clients/wallet)) or Signer ([ethers.js](https://docs.ethers.io/v6/api/providers/#Signer)) used for signing transactions.
59
+ * @typeParam W The wallet used for signing transactions.
60
60
  */
61
61
  export class ExchangeClient {
62
62
  transport;
@@ -138,37 +138,33 @@ export class ExchangeClient {
138
138
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
139
139
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
140
140
  *
141
- * const result = await client.approveAgent({ agentAddress: "0x...", agentName: "agentName" });
141
+ * const data = await exchClient.approveAgent({ agentAddress: "0x...", agentName: "agentName" });
142
142
  * ```
143
143
  */
144
144
  async approveAgent(args, signal) {
145
+ // Destructure the parameters
146
+ const { ...actionArgs } = args;
145
147
  // Construct an action
148
+ const nonce = await this.nonceManager();
146
149
  const action = {
147
- ...args,
150
+ ...actionArgs,
148
151
  agentName: args.agentName ?? "",
149
152
  type: "approveAgent",
150
153
  hyperliquidChain: this._getHyperliquidChain(),
151
154
  signatureChainId: await this._getSignatureChainId(),
152
- nonce: await this.nonceManager(),
155
+ nonce,
153
156
  };
154
157
  // Sign the action
155
158
  const signature = await signUserSignedAction({
156
159
  wallet: this.wallet,
157
160
  action,
158
- types: {
159
- "HyperliquidTransaction:ApproveAgent": [
160
- { name: "hyperliquidChain", type: "string" },
161
- { name: "agentAddress", type: "address" },
162
- { name: "agentName", type: "string" },
163
- { name: "nonce", type: "uint64" },
164
- ],
165
- },
161
+ types: userSignedActionEip712Types[action.type],
166
162
  chainId: parseInt(action.signatureChainId, 16),
167
163
  });
168
164
  if (action.agentName === "")
169
165
  delete action.agentName;
170
166
  // Send a request
171
- return await this._request({ action, signature, nonce: action.nonce }, signal);
167
+ return await this._request({ action, signature, nonce }, signal);
172
168
  }
173
169
  /**
174
170
  * Approve a maximum fee rate for a builder.
@@ -187,34 +183,30 @@ export class ExchangeClient {
187
183
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
188
184
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
189
185
  *
190
- * const result = await client.approveBuilderFee({ maxFeeRate: "0.01%", builder: "0x..." });
186
+ * const data = await exchClient.approveBuilderFee({ maxFeeRate: "0.01%", builder: "0x..." });
191
187
  * ```
192
188
  */
193
189
  async approveBuilderFee(args, signal) {
190
+ // Destructure the parameters
191
+ const { ...actionArgs } = args;
194
192
  // Construct an action
193
+ const nonce = await this.nonceManager();
195
194
  const action = {
196
- ...args,
195
+ ...actionArgs,
197
196
  type: "approveBuilderFee",
198
197
  hyperliquidChain: this._getHyperliquidChain(),
199
198
  signatureChainId: await this._getSignatureChainId(),
200
- nonce: await this.nonceManager(),
199
+ nonce,
201
200
  };
202
201
  // Sign the action
203
202
  const signature = await signUserSignedAction({
204
203
  wallet: this.wallet,
205
204
  action,
206
- types: {
207
- "HyperliquidTransaction:ApproveBuilderFee": [
208
- { name: "hyperliquidChain", type: "string" },
209
- { name: "maxFeeRate", type: "string" },
210
- { name: "builder", type: "address" },
211
- { name: "nonce", type: "uint64" },
212
- ],
213
- },
205
+ types: userSignedActionEip712Types[action.type],
214
206
  chainId: parseInt(action.signatureChainId, 16),
215
207
  });
216
208
  // Send a request
217
- return await this._request({ action, signature, nonce: action.nonce }, signal);
209
+ return await this._request({ action, signature, nonce }, signal);
218
210
  }
219
211
  /**
220
212
  * Modify multiple orders.
@@ -233,7 +225,7 @@ export class ExchangeClient {
233
225
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
234
226
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
235
227
  *
236
- * const result = await client.batchModify({
228
+ * const data = await exchClient.batchModify({
237
229
  * modifies: [{
238
230
  * oid: 123,
239
231
  * order: {
@@ -247,7 +239,7 @@ export class ExchangeClient {
247
239
  * tif: "Gtc", // Good-til-cancelled
248
240
  * },
249
241
  * },
250
- * c: "0x...", // Optional: Client Order ID
242
+ * c: "0x...", // Client Order ID (optional)
251
243
  * },
252
244
  * }],
253
245
  * });
@@ -260,40 +252,12 @@ export class ExchangeClient {
260
252
  const nonce = await this.nonceManager();
261
253
  const action = {
262
254
  type: "batchModify",
263
- modifies: actionArgs.modifies.map((modify) => {
264
- const sortedModify = {
265
- oid: modify.oid,
266
- order: {
267
- a: modify.order.a,
268
- b: modify.order.b,
269
- p: this._formatDecimal(modify.order.p),
270
- s: this._formatDecimal(modify.order.s),
271
- r: modify.order.r,
272
- t: "limit" in modify.order.t
273
- ? {
274
- limit: {
275
- tif: modify.order.t.limit.tif,
276
- },
277
- }
278
- : {
279
- trigger: {
280
- isMarket: modify.order.t.trigger.isMarket,
281
- triggerPx: this._formatDecimal(modify.order.t.trigger.triggerPx),
282
- tpsl: modify.order.t.trigger.tpsl,
283
- },
284
- },
285
- c: modify.order.c,
286
- },
287
- };
288
- if (sortedModify.order.c === undefined)
289
- delete sortedModify.order.c;
290
- return sortedModify;
291
- }),
255
+ ...actionArgs,
292
256
  };
293
257
  // Sign the action
294
258
  const signature = await signL1Action({
295
259
  wallet: this.wallet,
296
- action,
260
+ action: actionSorter[action.type](action),
297
261
  nonce,
298
262
  isTestnet: this.isTestnet,
299
263
  vaultAddress,
@@ -319,7 +283,7 @@ export class ExchangeClient {
319
283
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
320
284
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
321
285
  *
322
- * const result = await client.cancel({
286
+ * const data = await exchClient.cancel({
323
287
  * cancels: [{
324
288
  * a: 0, // Asset index
325
289
  * o: 123, // Order ID
@@ -334,15 +298,12 @@ export class ExchangeClient {
334
298
  const nonce = await this.nonceManager();
335
299
  const action = {
336
300
  type: "cancel",
337
- cancels: actionArgs.cancels.map((cancel) => ({
338
- a: cancel.a,
339
- o: cancel.o,
340
- })),
301
+ ...actionArgs,
341
302
  };
342
303
  // Sign the action
343
304
  const signature = await signL1Action({
344
305
  wallet: this.wallet,
345
- action,
306
+ action: actionSorter[action.type](action),
346
307
  nonce,
347
308
  isTestnet: this.isTestnet,
348
309
  vaultAddress,
@@ -368,7 +329,7 @@ export class ExchangeClient {
368
329
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
369
330
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
370
331
  *
371
- * const result = await client.cancelByCloid({
332
+ * const data = await exchClient.cancelByCloid({
372
333
  * cancels: [
373
334
  * { asset: 0, cloid: "0x..." },
374
335
  * ],
@@ -382,15 +343,12 @@ export class ExchangeClient {
382
343
  const nonce = await this.nonceManager();
383
344
  const action = {
384
345
  type: "cancelByCloid",
385
- cancels: actionArgs.cancels.map((cancel) => ({
386
- asset: cancel.asset,
387
- cloid: cancel.cloid,
388
- })),
346
+ ...actionArgs,
389
347
  };
390
348
  // Sign the action
391
349
  const signature = await signL1Action({
392
350
  wallet: this.wallet,
393
- action,
351
+ action: actionSorter[action.type](action),
394
352
  nonce,
395
353
  isTestnet: this.isTestnet,
396
354
  vaultAddress,
@@ -416,33 +374,30 @@ export class ExchangeClient {
416
374
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
417
375
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
418
376
  *
419
- * const result = await client.cDeposit({ wei: 1 * 1e8 });
377
+ * const data = await exchClient.cDeposit({ wei: 1 * 1e8 });
420
378
  * ```
421
379
  */
422
380
  async cDeposit(args, signal) {
381
+ // Destructure the parameters
382
+ const { ...actionArgs } = args;
423
383
  // Construct an action
384
+ const nonce = await this.nonceManager();
424
385
  const action = {
425
- ...args,
386
+ ...actionArgs,
426
387
  type: "cDeposit",
427
388
  hyperliquidChain: this._getHyperliquidChain(),
428
389
  signatureChainId: await this._getSignatureChainId(),
429
- nonce: await this.nonceManager(),
390
+ nonce,
430
391
  };
431
392
  // Sign the action
432
393
  const signature = await signUserSignedAction({
433
394
  wallet: this.wallet,
434
395
  action,
435
- types: {
436
- "HyperliquidTransaction:CDeposit": [
437
- { name: "hyperliquidChain", type: "string" },
438
- { name: "wei", type: "uint64" },
439
- { name: "nonce", type: "uint64" },
440
- ],
441
- },
396
+ types: userSignedActionEip712Types[action.type],
442
397
  chainId: parseInt(action.signatureChainId, 16),
443
398
  });
444
399
  // Send a request
445
- return await this._request({ action, signature, nonce: action.nonce }, signal);
400
+ return await this._request({ action, signature, nonce }, signal);
446
401
  }
447
402
  /**
448
403
  * Claim rewards from referral program.
@@ -461,17 +416,19 @@ export class ExchangeClient {
461
416
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
462
417
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
463
418
  *
464
- * const result = await client.claimRewards();
419
+ * const data = await exchClient.claimRewards();
465
420
  * ```
466
421
  */
467
422
  async claimRewards(signal) {
468
423
  // Construct an action
469
424
  const nonce = await this.nonceManager();
470
- const action = { type: "claimRewards" };
425
+ const action = {
426
+ type: "claimRewards",
427
+ };
471
428
  // Sign the action
472
429
  const signature = await signL1Action({
473
430
  wallet: this.wallet,
474
- action,
431
+ action: actionSorter[action.type](action),
475
432
  nonce,
476
433
  isTestnet: this.isTestnet,
477
434
  });
@@ -479,7 +436,7 @@ export class ExchangeClient {
479
436
  return await this._request({ action, signature, nonce }, signal);
480
437
  }
481
438
  /**
482
- * Convert a single-signature account to a multi-signature account.
439
+ * Convert a single-signature account to a multi-signature account or vice versa.
483
440
  * @param args - The parameters for the request.
484
441
  * @param signal - An optional abort signal.
485
442
  * @returns Successful response without specific data.
@@ -495,36 +452,33 @@ export class ExchangeClient {
495
452
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
496
453
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
497
454
  *
498
- * const result = await client.convertToMultiSigUser({
499
- * authorizedUsers: ["0x...", "0x..."],
455
+ * const data = await exchClient.convertToMultiSigUser({ // convert to multi-sig user
456
+ * authorizedUsers: ["0x...", "0x...", "0x..."],
500
457
  * threshold: 2,
501
458
  * });
502
459
  * ```
503
460
  */
504
461
  async convertToMultiSigUser(args, signal) {
462
+ // Destructure the parameters
463
+ const { ...actionArgs } = args;
505
464
  // Construct an action
465
+ const nonce = await this.nonceManager();
506
466
  const action = {
507
467
  type: "convertToMultiSigUser",
508
468
  hyperliquidChain: this._getHyperliquidChain(),
509
469
  signatureChainId: await this._getSignatureChainId(),
510
- signers: JSON.stringify(args),
511
- nonce: await this.nonceManager(),
470
+ signers: JSON.stringify(actionArgs),
471
+ nonce,
512
472
  };
513
473
  // Sign the action
514
474
  const signature = await signUserSignedAction({
515
475
  wallet: this.wallet,
516
476
  action,
517
- types: {
518
- "HyperliquidTransaction:ConvertToMultiSigUser": [
519
- { name: "hyperliquidChain", type: "string" },
520
- { name: "signers", type: "string" },
521
- { name: "nonce", type: "uint64" },
522
- ],
523
- },
477
+ types: userSignedActionEip712Types[action.type],
524
478
  chainId: parseInt(action.signatureChainId, 16),
525
479
  });
526
480
  // Send a request
527
- return await this._request({ action, signature, nonce: action.nonce }, signal);
481
+ return await this._request({ action, signature, nonce }, signal);
528
482
  }
529
483
  /**
530
484
  * Create a sub-account.
@@ -543,20 +497,22 @@ export class ExchangeClient {
543
497
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
544
498
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
545
499
  *
546
- * const result = await client.createSubAccount({ name: "subAccountName" });
500
+ * const data = await exchClient.createSubAccount({ name: "subAccountName" });
547
501
  * ```
548
502
  */
549
503
  async createSubAccount(args, signal) {
504
+ // Destructure the parameters
505
+ const { ...actionArgs } = args;
550
506
  // Construct an action
551
507
  const nonce = await this.nonceManager();
552
508
  const action = {
553
509
  type: "createSubAccount",
554
- name: args.name,
510
+ ...actionArgs,
555
511
  };
556
512
  // Sign the action
557
513
  const signature = await signL1Action({
558
514
  wallet: this.wallet,
559
- action,
515
+ action: actionSorter[action.type](action),
560
516
  nonce,
561
517
  isTestnet: this.isTestnet,
562
518
  });
@@ -580,27 +536,27 @@ export class ExchangeClient {
580
536
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
581
537
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
582
538
  *
583
- * const result = await client.createVault({
539
+ * const data = await exchClient.createVault({
584
540
  * name: "VaultName",
585
- * description: "This is an example of a vault description",
541
+ * description: "Vault description",
586
542
  * initialUsd: 100 * 1e6,
587
543
  * });
588
544
  * ```
589
545
  */
590
546
  async createVault(args, signal) {
547
+ // Destructure the parameters
548
+ const { ...actionArgs } = args;
591
549
  // Construct an action
592
550
  const nonce = await this.nonceManager();
593
551
  const action = {
594
552
  type: "createVault",
595
- name: args.name,
596
- description: args.description,
597
- initialUsd: args.initialUsd,
598
553
  nonce,
554
+ ...actionArgs,
599
555
  };
600
556
  // Sign the action
601
557
  const signature = await signL1Action({
602
558
  wallet: this.wallet,
603
- action,
559
+ action: actionSorter[action.type](action),
604
560
  nonce,
605
561
  isTestnet: this.isTestnet,
606
562
  });
@@ -619,7 +575,7 @@ export class ExchangeClient {
619
575
  // Sign the action
620
576
  const signature = await signL1Action({
621
577
  wallet: this.wallet,
622
- action,
578
+ action: actionSorter[action.type](action),
623
579
  nonce,
624
580
  isTestnet: this.isTestnet,
625
581
  expiresAfter,
@@ -632,48 +588,14 @@ export class ExchangeClient {
632
588
  const { expiresAfter = await this._getDefaultExpiresAfter(), ...actionArgs } = args;
633
589
  // Construct an action
634
590
  const nonce = await this.nonceManager();
635
- let action;
636
- if ("changeProfile" in actionArgs) {
637
- action = {
638
- type: "CValidatorAction",
639
- changeProfile: {
640
- node_ip: actionArgs.changeProfile.node_ip ?? null,
641
- name: actionArgs.changeProfile.name ?? null,
642
- description: actionArgs.changeProfile.description ?? null,
643
- unjailed: actionArgs.changeProfile.unjailed,
644
- disable_delegations: actionArgs.changeProfile.disable_delegations ?? null,
645
- commission_bps: actionArgs.changeProfile.commission_bps ?? null,
646
- signer: actionArgs.changeProfile.signer?.toLowerCase() ?? null,
647
- },
648
- };
649
- }
650
- else if ("register" in actionArgs) {
651
- action = {
652
- type: "CValidatorAction",
653
- register: {
654
- profile: {
655
- node_ip: { Ip: actionArgs.register.profile.node_ip.Ip },
656
- name: actionArgs.register.profile.name,
657
- description: actionArgs.register.profile.description,
658
- delegations_disabled: actionArgs.register.profile.delegations_disabled,
659
- commission_bps: actionArgs.register.profile.commission_bps,
660
- signer: actionArgs.register.profile.signer?.toLowerCase(),
661
- },
662
- unjailed: actionArgs.register.unjailed,
663
- initial_wei: actionArgs.register.initial_wei,
664
- },
665
- };
666
- }
667
- else {
668
- action = {
669
- type: "CValidatorAction",
670
- unregister: actionArgs.unregister,
671
- };
672
- }
591
+ const action = {
592
+ type: "CValidatorAction",
593
+ ...actionArgs,
594
+ };
673
595
  // Sign the action
674
596
  const signature = await signL1Action({
675
597
  wallet: this.wallet,
676
- action,
598
+ action: actionSorter[action.type](action),
677
599
  nonce,
678
600
  isTestnet: this.isTestnet,
679
601
  expiresAfter,
@@ -698,33 +620,30 @@ export class ExchangeClient {
698
620
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
699
621
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
700
622
  *
701
- * const result = await client.cWithdraw({ wei: 1 * 1e8 });
623
+ * const data = await exchClient.cWithdraw({ wei: 1 * 1e8 });
702
624
  * ```
703
625
  */
704
626
  async cWithdraw(args, signal) {
627
+ // Destructure the parameters
628
+ const { ...actionArgs } = args;
705
629
  // Construct an action
630
+ const nonce = await this.nonceManager();
706
631
  const action = {
707
- ...args,
632
+ ...actionArgs,
708
633
  type: "cWithdraw",
709
634
  hyperliquidChain: this._getHyperliquidChain(),
710
635
  signatureChainId: await this._getSignatureChainId(),
711
- nonce: await this.nonceManager(),
636
+ nonce,
712
637
  };
713
638
  // Sign the action
714
639
  const signature = await signUserSignedAction({
715
640
  wallet: this.wallet,
716
641
  action,
717
- types: {
718
- "HyperliquidTransaction:CWithdraw": [
719
- { name: "hyperliquidChain", type: "string" },
720
- { name: "wei", type: "uint64" },
721
- { name: "nonce", type: "uint64" },
722
- ],
723
- },
642
+ types: userSignedActionEip712Types[action.type],
724
643
  chainId: parseInt(action.signatureChainId, 16),
725
644
  });
726
645
  // Send a request
727
- return await this._request({ action, signature, nonce: action.nonce }, signal);
646
+ return await this._request({ action, signature, nonce }, signal);
728
647
  }
729
648
  /**
730
649
  * Configure block type for EVM transactions.
@@ -743,20 +662,22 @@ export class ExchangeClient {
743
662
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
744
663
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
745
664
  *
746
- * const result = await client.evmUserModify({ usingBigBlocks: true });
665
+ * const data = await exchClient.evmUserModify({ usingBigBlocks: true });
747
666
  * ```
748
667
  */
749
668
  async evmUserModify(args, signal) {
669
+ // Destructure the parameters
670
+ const { ...actionArgs } = args;
750
671
  // Construct an action
751
672
  const nonce = await this.nonceManager();
752
673
  const action = {
753
674
  type: "evmUserModify",
754
- usingBigBlocks: args.usingBigBlocks,
675
+ ...actionArgs,
755
676
  };
756
677
  // Sign the action
757
678
  const signature = await signL1Action({
758
679
  wallet: this.wallet,
759
- action,
680
+ action: actionSorter[action.type](action),
760
681
  nonce,
761
682
  isTestnet: this.isTestnet,
762
683
  });
@@ -780,7 +701,7 @@ export class ExchangeClient {
780
701
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
781
702
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
782
703
  *
783
- * const result = await client.modify({
704
+ * const data = await exchClient.modify({
784
705
  * oid: 123,
785
706
  * order: {
786
707
  * a: 0, // Asset index
@@ -793,7 +714,7 @@ export class ExchangeClient {
793
714
  * tif: "Gtc", // Good-til-cancelled
794
715
  * },
795
716
  * },
796
- * c: "0x...", // Optional: Client Order ID
717
+ * c: "0x...", // Client Order ID (optional)
797
718
  * },
798
719
  * });
799
720
  * ```
@@ -805,35 +726,12 @@ export class ExchangeClient {
805
726
  const nonce = await this.nonceManager();
806
727
  const action = {
807
728
  type: "modify",
808
- oid: actionArgs.oid,
809
- order: {
810
- a: actionArgs.order.a,
811
- b: actionArgs.order.b,
812
- p: this._formatDecimal(actionArgs.order.p),
813
- s: this._formatDecimal(actionArgs.order.s),
814
- r: actionArgs.order.r,
815
- t: "limit" in actionArgs.order.t
816
- ? {
817
- limit: {
818
- tif: actionArgs.order.t.limit.tif,
819
- },
820
- }
821
- : {
822
- trigger: {
823
- isMarket: actionArgs.order.t.trigger.isMarket,
824
- triggerPx: this._formatDecimal(actionArgs.order.t.trigger.triggerPx),
825
- tpsl: actionArgs.order.t.trigger.tpsl,
826
- },
827
- },
828
- c: actionArgs.order.c,
829
- },
729
+ ...actionArgs,
830
730
  };
831
- if (action.order.c === undefined)
832
- delete action.order.c;
833
731
  // Sign the action
834
732
  const signature = await signL1Action({
835
733
  wallet: this.wallet,
836
- action,
734
+ action: actionSorter[action.type](action),
837
735
  nonce,
838
736
  isTestnet: this.isTestnet,
839
737
  vaultAddress,
@@ -871,7 +769,7 @@ export class ExchangeClient {
871
769
  * isTestnet: true,
872
770
  * });
873
771
  *
874
- * const result = await client.multiSig({
772
+ * const data = await exchClient.multiSig({
875
773
  * signatures: [signature],
876
774
  * payload: {
877
775
  * multiSigUser,
@@ -881,29 +779,18 @@ export class ExchangeClient {
881
779
  * nonce,
882
780
  * });
883
781
  * ```
884
- * @unstable May not behave as expected and the interface may change in the future.
885
782
  */
886
783
  async multiSig(args, signal) {
887
784
  // Destructure the parameters
888
785
  const { vaultAddress = this.defaultVaultAddress, expiresAfter = await this._getDefaultExpiresAfter(), nonce, ...actionArgs } = args;
889
786
  // Construct an action
890
- const hyperliquidChain = this._getHyperliquidChain();
891
787
  const action = {
892
788
  type: "multiSig",
893
789
  signatureChainId: await this._getSignatureChainId(),
894
- signatures: actionArgs.signatures.map((signature) => ({
895
- r: signature.r.replace(/^0x0+/, "0x").toLowerCase(),
896
- s: signature.s.replace(/^0x0+/, "0x").toLowerCase(),
897
- v: signature.v,
898
- })),
899
- payload: {
900
- multiSigUser: actionArgs.payload.multiSigUser.toLowerCase(),
901
- outerSigner: actionArgs.payload.outerSigner.toLowerCase(),
902
- action: actionArgs.payload.action,
903
- },
790
+ ...actionArgs,
904
791
  };
905
792
  // Sign the action
906
- const actionForMultiSig = structuredClone(action);
793
+ const actionForMultiSig = actionSorter[action.type](action);
907
794
  delete actionForMultiSig.type;
908
795
  const signature = await signMultiSigAction({
909
796
  wallet: this.wallet,
@@ -911,7 +798,7 @@ export class ExchangeClient {
911
798
  nonce,
912
799
  vaultAddress,
913
800
  expiresAfter,
914
- hyperliquidChain,
801
+ hyperliquidChain: this._getHyperliquidChain(),
915
802
  signatureChainId: action.signatureChainId,
916
803
  });
917
804
  // Send a request
@@ -934,7 +821,7 @@ export class ExchangeClient {
934
821
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
935
822
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
936
823
  *
937
- * const result = await client.order({
824
+ * const data = await exchClient.order({
938
825
  * orders: [{
939
826
  * a: 0, // Asset index
940
827
  * b: true, // Buy order
@@ -946,7 +833,7 @@ export class ExchangeClient {
946
833
  * tif: "Gtc", // Good-til-cancelled
947
834
  * },
948
835
  * },
949
- * c: "0x...", // Optional: Client Order ID
836
+ * c: "0x...", // Client Order ID (optional)
950
837
  * }],
951
838
  * grouping: "na", // No grouping
952
839
  * });
@@ -959,46 +846,12 @@ export class ExchangeClient {
959
846
  const nonce = await this.nonceManager();
960
847
  const action = {
961
848
  type: "order",
962
- orders: actionArgs.orders.map((order) => {
963
- const sortedOrder = {
964
- a: order.a,
965
- b: order.b,
966
- p: this._formatDecimal(order.p),
967
- s: this._formatDecimal(order.s),
968
- r: order.r,
969
- t: "limit" in order.t
970
- ? {
971
- limit: {
972
- tif: order.t.limit.tif,
973
- },
974
- }
975
- : {
976
- trigger: {
977
- isMarket: order.t.trigger.isMarket,
978
- triggerPx: this._formatDecimal(order.t.trigger.triggerPx),
979
- tpsl: order.t.trigger.tpsl,
980
- },
981
- },
982
- c: order.c,
983
- };
984
- if (order.c === undefined)
985
- delete sortedOrder.c;
986
- return sortedOrder;
987
- }),
988
- grouping: actionArgs.grouping,
989
- builder: actionArgs.builder
990
- ? {
991
- b: actionArgs.builder.b.toLowerCase(),
992
- f: actionArgs.builder.f,
993
- }
994
- : actionArgs.builder,
849
+ ...actionArgs,
995
850
  };
996
- if (action.builder === undefined)
997
- delete action.builder;
998
851
  // Sign the action
999
852
  const signature = await signL1Action({
1000
853
  wallet: this.wallet,
1001
- action,
854
+ action: actionSorter[action.type](action),
1002
855
  nonce,
1003
856
  isTestnet: this.isTestnet,
1004
857
  vaultAddress,
@@ -1008,47 +861,18 @@ export class ExchangeClient {
1008
861
  return await this._request({ action, signature, nonce, vaultAddress, expiresAfter }, signal);
1009
862
  }
1010
863
  async perpDeploy(args, signal) {
864
+ // Destructure the parameters
865
+ const { ...actionArgs } = args;
1011
866
  // Construct an action
1012
867
  const nonce = await this.nonceManager();
1013
- let action;
1014
- if ("registerAsset" in args) {
1015
- action = {
1016
- type: "perpDeploy",
1017
- registerAsset: {
1018
- maxGas: args.registerAsset.maxGas ?? null,
1019
- assetRequest: {
1020
- coin: args.registerAsset.assetRequest.coin,
1021
- szDecimals: args.registerAsset.assetRequest.szDecimals,
1022
- oraclePx: args.registerAsset.assetRequest.oraclePx,
1023
- marginTableId: args.registerAsset.assetRequest.marginTableId,
1024
- onlyIsolated: args.registerAsset.assetRequest.onlyIsolated,
1025
- },
1026
- dex: args.registerAsset.dex,
1027
- schema: args.registerAsset.schema
1028
- ? {
1029
- fullName: args.registerAsset.schema.fullName,
1030
- collateralToken: args.registerAsset.schema.collateralToken,
1031
- oracleUpdater: args.registerAsset.schema.oracleUpdater?.toLowerCase() ??
1032
- null,
1033
- }
1034
- : null,
1035
- },
1036
- };
1037
- }
1038
- else {
1039
- action = {
1040
- type: "perpDeploy",
1041
- setOracle: {
1042
- dex: args.setOracle.dex,
1043
- oraclePxs: args.setOracle.oraclePxs,
1044
- markPxs: args.setOracle.markPxs,
1045
- },
1046
- };
1047
- }
868
+ const action = {
869
+ type: "perpDeploy",
870
+ ...actionArgs,
871
+ };
1048
872
  // Sign the action
1049
873
  const signature = await signL1Action({
1050
874
  wallet: this.wallet,
1051
- action,
875
+ action: actionSorter[action.type](action),
1052
876
  nonce,
1053
877
  isTestnet: this.isTestnet,
1054
878
  });
@@ -1072,7 +896,7 @@ export class ExchangeClient {
1072
896
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
1073
897
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
1074
898
  *
1075
- * const result = await client.perpDexClassTransfer({
899
+ * const data = await exchClient.perpDexClassTransfer({
1076
900
  * dex: "test",
1077
901
  * token: "USDC",
1078
902
  * amount: "1",
@@ -1081,32 +905,26 @@ export class ExchangeClient {
1081
905
  * ```
1082
906
  */
1083
907
  async perpDexClassTransfer(args, signal) {
908
+ // Destructure the parameters
909
+ const { ...actionArgs } = args;
1084
910
  // Construct an action
911
+ const nonce = await this.nonceManager();
1085
912
  const action = {
1086
- ...args,
913
+ ...actionArgs,
1087
914
  type: "PerpDexClassTransfer",
1088
915
  hyperliquidChain: this._getHyperliquidChain(),
1089
916
  signatureChainId: await this._getSignatureChainId(),
1090
- nonce: await this.nonceManager(),
917
+ nonce,
1091
918
  };
1092
919
  // Sign the action
1093
920
  const signature = await signUserSignedAction({
1094
921
  wallet: this.wallet,
1095
922
  action,
1096
- types: {
1097
- "HyperliquidTransaction:PerpDexClassTransfer": [
1098
- { name: "hyperliquidChain", type: "string" },
1099
- { name: "dex", type: "string" },
1100
- { name: "token", type: "string" },
1101
- { name: "amount", type: "string" },
1102
- { name: "toPerp", type: "bool" },
1103
- { name: "nonce", type: "uint64" },
1104
- ],
1105
- },
923
+ types: userSignedActionEip712Types[action.type],
1106
924
  chainId: parseInt(action.signatureChainId, 16),
1107
925
  });
1108
926
  // Send a request
1109
- return await this._request({ action, signature, nonce: action.nonce }, signal);
927
+ return await this._request({ action, signature, nonce }, signal);
1110
928
  }
1111
929
  /**
1112
930
  * Create a referral code.
@@ -1125,20 +943,22 @@ export class ExchangeClient {
1125
943
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
1126
944
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
1127
945
  *
1128
- * const result = await client.registerReferrer({ code: "TEST" });
946
+ * const data = await exchClient.registerReferrer({ code: "TEST" });
1129
947
  * ```
1130
948
  */
1131
949
  async registerReferrer(args, signal) {
950
+ // Destructure the parameters
951
+ const { ...actionArgs } = args;
1132
952
  // Construct an action
1133
953
  const nonce = await this.nonceManager();
1134
954
  const action = {
1135
955
  type: "registerReferrer",
1136
- code: args.code,
956
+ ...actionArgs,
1137
957
  };
1138
958
  // Sign the action
1139
959
  const signature = await signL1Action({
1140
960
  wallet: this.wallet,
1141
- action,
961
+ action: actionSorter[action.type](action),
1142
962
  nonce,
1143
963
  isTestnet: this.isTestnet,
1144
964
  });
@@ -1162,7 +982,7 @@ export class ExchangeClient {
1162
982
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
1163
983
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
1164
984
  *
1165
- * const result = await client.reserveRequestWeight({ weight: 10 });
985
+ * const data = await exchClient.reserveRequestWeight({ weight: 10 });
1166
986
  * ```
1167
987
  */
1168
988
  async reserveRequestWeight(args, signal) {
@@ -1172,12 +992,12 @@ export class ExchangeClient {
1172
992
  const nonce = await this.nonceManager();
1173
993
  const action = {
1174
994
  type: "reserveRequestWeight",
1175
- weight: actionArgs.weight,
995
+ ...actionArgs,
1176
996
  };
1177
997
  // Sign the action
1178
998
  const signature = await signL1Action({
1179
999
  wallet: this.wallet,
1180
- action,
1000
+ action: actionSorter[action.type](action),
1181
1001
  nonce,
1182
1002
  isTestnet: this.isTestnet,
1183
1003
  expiresAfter,
@@ -1194,14 +1014,12 @@ export class ExchangeClient {
1194
1014
  const nonce = await this.nonceManager();
1195
1015
  const action = {
1196
1016
  type: "scheduleCancel",
1197
- time: actionArgs.time,
1017
+ ...actionArgs,
1198
1018
  };
1199
- if (action.time === undefined)
1200
- delete action.time;
1201
1019
  // Sign the action
1202
1020
  const signature = await signL1Action({
1203
1021
  wallet: this.wallet,
1204
- action,
1022
+ action: actionSorter[action.type](action),
1205
1023
  nonce,
1206
1024
  isTestnet: this.isTestnet,
1207
1025
  vaultAddress,
@@ -1227,20 +1045,22 @@ export class ExchangeClient {
1227
1045
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
1228
1046
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
1229
1047
  *
1230
- * const result = await client.setDisplayName({ displayName: "My Name" });
1048
+ * const data = await exchClient.setDisplayName({ displayName: "My Name" });
1231
1049
  * ```
1232
1050
  */
1233
1051
  async setDisplayName(args, signal) {
1052
+ // Destructure the parameters
1053
+ const { ...actionArgs } = args;
1234
1054
  // Construct an action
1235
1055
  const nonce = await this.nonceManager();
1236
1056
  const action = {
1237
1057
  type: "setDisplayName",
1238
- displayName: args.displayName,
1058
+ ...actionArgs,
1239
1059
  };
1240
1060
  // Sign the action
1241
1061
  const signature = await signL1Action({
1242
1062
  wallet: this.wallet,
1243
- action,
1063
+ action: actionSorter[action.type](action),
1244
1064
  nonce,
1245
1065
  isTestnet: this.isTestnet,
1246
1066
  });
@@ -1264,20 +1084,22 @@ export class ExchangeClient {
1264
1084
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
1265
1085
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
1266
1086
  *
1267
- * const result = await client.setReferrer({ code: "TEST" });
1087
+ * const data = await exchClient.setReferrer({ code: "TEST" });
1268
1088
  * ```
1269
1089
  */
1270
1090
  async setReferrer(args, signal) {
1091
+ // Destructure the parameters
1092
+ const { ...actionArgs } = args;
1271
1093
  // Construct an action
1272
1094
  const nonce = await this.nonceManager();
1273
1095
  const action = {
1274
1096
  type: "setReferrer",
1275
- code: args.code,
1097
+ ...actionArgs,
1276
1098
  };
1277
1099
  // Sign the action
1278
1100
  const signature = await signL1Action({
1279
1101
  wallet: this.wallet,
1280
- action,
1102
+ action: actionSorter[action.type](action),
1281
1103
  nonce,
1282
1104
  isTestnet: this.isTestnet,
1283
1105
  });
@@ -1285,89 +1107,18 @@ export class ExchangeClient {
1285
1107
  return await this._request({ action, signature, nonce }, signal);
1286
1108
  }
1287
1109
  async spotDeploy(args, signal) {
1110
+ // Destructure the parameters
1111
+ const { ...actionArgs } = args;
1288
1112
  // Construct an action
1289
1113
  const nonce = await this.nonceManager();
1290
- let action;
1291
- if ("registerToken2" in args) {
1292
- action = {
1293
- type: "spotDeploy",
1294
- registerToken2: {
1295
- spec: {
1296
- name: args.registerToken2.spec.name,
1297
- szDecimals: args.registerToken2.spec.szDecimals,
1298
- weiDecimals: args.registerToken2.spec.weiDecimals,
1299
- },
1300
- maxGas: args.registerToken2.maxGas,
1301
- fullName: args.registerToken2.fullName,
1302
- },
1303
- };
1304
- if (action.registerToken2.fullName === undefined) {
1305
- delete action.registerToken2.fullName;
1306
- }
1307
- }
1308
- else if ("userGenesis" in args) {
1309
- action = {
1310
- type: "spotDeploy",
1311
- userGenesis: {
1312
- token: args.userGenesis.token,
1313
- userAndWei: args.userGenesis.userAndWei,
1314
- existingTokenAndWei: args.userGenesis.existingTokenAndWei,
1315
- blacklistUsers: args.userGenesis.blacklistUsers,
1316
- },
1317
- };
1318
- if (action.userGenesis.blacklistUsers === undefined) {
1319
- delete action.userGenesis.blacklistUsers;
1320
- }
1321
- }
1322
- else if ("genesis" in args) {
1323
- action = {
1324
- type: "spotDeploy",
1325
- genesis: {
1326
- token: args.genesis.token,
1327
- maxSupply: args.genesis.maxSupply,
1328
- noHyperliquidity: args.genesis.noHyperliquidity,
1329
- },
1330
- };
1331
- if (action.genesis.noHyperliquidity === undefined) {
1332
- delete action.genesis.noHyperliquidity;
1333
- }
1334
- }
1335
- else if ("registerSpot" in args) {
1336
- action = {
1337
- type: "spotDeploy",
1338
- registerSpot: {
1339
- tokens: args.registerSpot.tokens,
1340
- },
1341
- };
1342
- }
1343
- else if ("registerHyperliquidity" in args) {
1344
- action = {
1345
- type: "spotDeploy",
1346
- registerHyperliquidity: {
1347
- spot: args.registerHyperliquidity.spot,
1348
- startPx: args.registerHyperliquidity.startPx,
1349
- orderSz: args.registerHyperliquidity.orderSz,
1350
- nOrders: args.registerHyperliquidity.nOrders,
1351
- nSeededLevels: args.registerHyperliquidity.nSeededLevels,
1352
- },
1353
- };
1354
- if (action.registerHyperliquidity.nSeededLevels === undefined) {
1355
- delete action.registerHyperliquidity.nSeededLevels;
1356
- }
1357
- }
1358
- else {
1359
- action = {
1360
- type: "spotDeploy",
1361
- setDeployerTradingFeeShare: {
1362
- token: args.setDeployerTradingFeeShare.token,
1363
- share: args.setDeployerTradingFeeShare.share,
1364
- },
1365
- };
1366
- }
1114
+ const action = {
1115
+ type: "spotDeploy",
1116
+ ...actionArgs,
1117
+ };
1367
1118
  // Sign the action
1368
1119
  const signature = await signL1Action({
1369
1120
  wallet: this.wallet,
1370
- action,
1121
+ action: actionSorter[action.type](action),
1371
1122
  nonce,
1372
1123
  isTestnet: this.isTestnet,
1373
1124
  });
@@ -1391,7 +1142,7 @@ export class ExchangeClient {
1391
1142
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
1392
1143
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
1393
1144
  *
1394
- * const result = await client.spotSend({
1145
+ * const data = await exchClient.spotSend({
1395
1146
  * destination: "0x...",
1396
1147
  * token: "USDC:0xeb62eee3685fc4c43992febcd9e75443",
1397
1148
  * amount: "1",
@@ -1399,31 +1150,26 @@ export class ExchangeClient {
1399
1150
  * ```
1400
1151
  */
1401
1152
  async spotSend(args, signal) {
1153
+ // Destructure the parameters
1154
+ const { ...actionArgs } = args;
1402
1155
  // Construct an action
1156
+ const nonce = await this.nonceManager();
1403
1157
  const action = {
1404
- ...args,
1158
+ ...actionArgs,
1405
1159
  type: "spotSend",
1406
1160
  hyperliquidChain: this._getHyperliquidChain(),
1407
1161
  signatureChainId: await this._getSignatureChainId(),
1408
- time: await this.nonceManager(),
1162
+ time: nonce,
1409
1163
  };
1410
1164
  // Sign the action
1411
1165
  const signature = await signUserSignedAction({
1412
1166
  wallet: this.wallet,
1413
1167
  action,
1414
- types: {
1415
- "HyperliquidTransaction:SpotSend": [
1416
- { name: "hyperliquidChain", type: "string" },
1417
- { name: "destination", type: "string" },
1418
- { name: "token", type: "string" },
1419
- { name: "amount", type: "string" },
1420
- { name: "time", type: "uint64" },
1421
- ],
1422
- },
1168
+ types: userSignedActionEip712Types[action.type],
1423
1169
  chainId: parseInt(action.signatureChainId, 16),
1424
1170
  });
1425
1171
  // Send a request
1426
- return await this._request({ action, signature, nonce: action.time }, signal);
1172
+ return await this._request({ action, signature, nonce }, signal);
1427
1173
  }
1428
1174
  /**
1429
1175
  * Opt Out of Spot Dusting.
@@ -1442,22 +1188,22 @@ export class ExchangeClient {
1442
1188
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
1443
1189
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
1444
1190
  *
1445
- * const result = await client.spotUser({ toggleSpotDusting: { optOut: false } });
1191
+ * const data = await exchClient.spotUser({ toggleSpotDusting: { optOut: false } });
1446
1192
  * ```
1447
1193
  */
1448
1194
  async spotUser(args, signal) {
1195
+ // Destructure the parameters
1196
+ const { ...actionArgs } = args;
1449
1197
  // Construct an action
1450
1198
  const nonce = await this.nonceManager();
1451
1199
  const action = {
1452
1200
  type: "spotUser",
1453
- toggleSpotDusting: {
1454
- optOut: args.toggleSpotDusting.optOut,
1455
- },
1201
+ ...actionArgs,
1456
1202
  };
1457
1203
  // Sign the action
1458
1204
  const signature = await signL1Action({
1459
1205
  wallet: this.wallet,
1460
- action,
1206
+ action: actionSorter[action.type](action),
1461
1207
  nonce,
1462
1208
  isTestnet: this.isTestnet,
1463
1209
  });
@@ -1481,7 +1227,7 @@ export class ExchangeClient {
1481
1227
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
1482
1228
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
1483
1229
  *
1484
- * const result = await client.subAccountSpotTransfer({
1230
+ * const data = await exchClient.subAccountSpotTransfer({
1485
1231
  * subAccountUser: "0x...",
1486
1232
  * isDeposit: true,
1487
1233
  * token: "USDC:0xeb62eee3685fc4c43992febcd9e75443",
@@ -1490,19 +1236,18 @@ export class ExchangeClient {
1490
1236
  * ```
1491
1237
  */
1492
1238
  async subAccountSpotTransfer(args, signal) {
1239
+ // Destructure the parameters
1240
+ const { ...actionArgs } = args;
1493
1241
  // Construct an action
1494
1242
  const nonce = await this.nonceManager();
1495
1243
  const action = {
1496
1244
  type: "subAccountSpotTransfer",
1497
- subAccountUser: args.subAccountUser,
1498
- isDeposit: args.isDeposit,
1499
- token: args.token,
1500
- amount: args.amount,
1245
+ ...actionArgs,
1501
1246
  };
1502
1247
  // Sign the action
1503
1248
  const signature = await signL1Action({
1504
1249
  wallet: this.wallet,
1505
- action,
1250
+ action: actionSorter[action.type](action),
1506
1251
  nonce,
1507
1252
  isTestnet: this.isTestnet,
1508
1253
  });
@@ -1526,7 +1271,7 @@ export class ExchangeClient {
1526
1271
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
1527
1272
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
1528
1273
  *
1529
- * const result = await client.subAccountTransfer({
1274
+ * const data = await exchClient.subAccountTransfer({
1530
1275
  * subAccountUser: "0x...",
1531
1276
  * isDeposit: true,
1532
1277
  * usd: 1 * 1e6,
@@ -1534,18 +1279,18 @@ export class ExchangeClient {
1534
1279
  * ```
1535
1280
  */
1536
1281
  async subAccountTransfer(args, signal) {
1282
+ // Destructure the parameters
1283
+ const { ...actionArgs } = args;
1537
1284
  // Construct an action
1538
1285
  const nonce = await this.nonceManager();
1539
1286
  const action = {
1540
1287
  type: "subAccountTransfer",
1541
- subAccountUser: args.subAccountUser,
1542
- isDeposit: args.isDeposit,
1543
- usd: args.usd,
1288
+ ...actionArgs,
1544
1289
  };
1545
1290
  // Sign the action
1546
1291
  const signature = await signL1Action({
1547
1292
  wallet: this.wallet,
1548
- action,
1293
+ action: actionSorter[action.type](action),
1549
1294
  nonce,
1550
1295
  isTestnet: this.isTestnet,
1551
1296
  });
@@ -1569,7 +1314,7 @@ export class ExchangeClient {
1569
1314
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
1570
1315
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
1571
1316
  *
1572
- * const result = await client.tokenDelegate({
1317
+ * const data = await exchClient.tokenDelegate({
1573
1318
  * validator: "0x...",
1574
1319
  * isUndelegate: true,
1575
1320
  * wei: 1 * 1e8,
@@ -1577,31 +1322,26 @@ export class ExchangeClient {
1577
1322
  * ```
1578
1323
  */
1579
1324
  async tokenDelegate(args, signal) {
1325
+ // Destructure the parameters
1326
+ const { ...actionArgs } = args;
1580
1327
  // Construct an action
1328
+ const nonce = await this.nonceManager();
1581
1329
  const action = {
1582
- ...args,
1330
+ ...actionArgs,
1583
1331
  type: "tokenDelegate",
1584
1332
  hyperliquidChain: this._getHyperliquidChain(),
1585
1333
  signatureChainId: await this._getSignatureChainId(),
1586
- nonce: await this.nonceManager(),
1334
+ nonce,
1587
1335
  };
1588
1336
  // Sign the action
1589
1337
  const signature = await signUserSignedAction({
1590
1338
  wallet: this.wallet,
1591
1339
  action,
1592
- types: {
1593
- "HyperliquidTransaction:TokenDelegate": [
1594
- { name: "hyperliquidChain", type: "string" },
1595
- { name: "validator", type: "address" },
1596
- { name: "wei", type: "uint64" },
1597
- { name: "isUndelegate", type: "bool" },
1598
- { name: "nonce", type: "uint64" },
1599
- ],
1600
- },
1340
+ types: userSignedActionEip712Types[action.type],
1601
1341
  chainId: parseInt(action.signatureChainId, 16),
1602
1342
  });
1603
1343
  // Send a request
1604
- return await this._request({ action, signature, nonce: action.nonce }, signal);
1344
+ return await this._request({ action, signature, nonce }, signal);
1605
1345
  }
1606
1346
  /**
1607
1347
  * Cancel a TWAP order.
@@ -1620,7 +1360,7 @@ export class ExchangeClient {
1620
1360
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
1621
1361
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
1622
1362
  *
1623
- * const result = await client.twapCancel({
1363
+ * const data = await exchClient.twapCancel({
1624
1364
  * a: 0, // Asset index
1625
1365
  * t: 1, // TWAP ID
1626
1366
  * });
@@ -1633,13 +1373,12 @@ export class ExchangeClient {
1633
1373
  const nonce = await this.nonceManager();
1634
1374
  const action = {
1635
1375
  type: "twapCancel",
1636
- a: actionArgs.a,
1637
- t: actionArgs.t,
1376
+ ...actionArgs,
1638
1377
  };
1639
1378
  // Sign the action
1640
1379
  const signature = await signL1Action({
1641
1380
  wallet: this.wallet,
1642
- action,
1381
+ action: actionSorter[action.type](action),
1643
1382
  nonce,
1644
1383
  isTestnet: this.isTestnet,
1645
1384
  vaultAddress,
@@ -1665,7 +1404,7 @@ export class ExchangeClient {
1665
1404
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
1666
1405
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
1667
1406
  *
1668
- * const result = await client.twapOrder({
1407
+ * const data = await exchClient.twapOrder({
1669
1408
  * a: 0, // Asset index
1670
1409
  * b: true, // Buy order
1671
1410
  * s: "1", // Size
@@ -1683,18 +1422,13 @@ export class ExchangeClient {
1683
1422
  const action = {
1684
1423
  type: "twapOrder",
1685
1424
  twap: {
1686
- a: actionArgs.a,
1687
- b: actionArgs.b,
1688
- s: this._formatDecimal(actionArgs.s),
1689
- r: actionArgs.r,
1690
- m: actionArgs.m,
1691
- t: actionArgs.t,
1425
+ ...actionArgs,
1692
1426
  },
1693
1427
  };
1694
1428
  // Sign the action
1695
1429
  const signature = await signL1Action({
1696
1430
  wallet: this.wallet,
1697
- action,
1431
+ action: actionSorter[action.type](action),
1698
1432
  nonce,
1699
1433
  isTestnet: this.isTestnet,
1700
1434
  vaultAddress,
@@ -1720,7 +1454,11 @@ export class ExchangeClient {
1720
1454
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
1721
1455
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
1722
1456
  *
1723
- * const result = await client.updateIsolatedMargin({ asset: 0, isBuy: true, ntli: 1 * 1e6 });
1457
+ * const data = await exchClient.updateIsolatedMargin({
1458
+ * asset: 0,
1459
+ * isBuy: true,
1460
+ * ntli: 1 * 1e6,
1461
+ * });
1724
1462
  * ```
1725
1463
  */
1726
1464
  async updateIsolatedMargin(args, signal) {
@@ -1730,14 +1468,12 @@ export class ExchangeClient {
1730
1468
  const nonce = await this.nonceManager();
1731
1469
  const action = {
1732
1470
  type: "updateIsolatedMargin",
1733
- asset: actionArgs.asset,
1734
- isBuy: actionArgs.isBuy,
1735
- ntli: actionArgs.ntli,
1471
+ ...actionArgs,
1736
1472
  };
1737
1473
  // Sign the action
1738
1474
  const signature = await signL1Action({
1739
1475
  wallet: this.wallet,
1740
- action,
1476
+ action: actionSorter[action.type](action),
1741
1477
  nonce,
1742
1478
  isTestnet: this.isTestnet,
1743
1479
  vaultAddress,
@@ -1763,7 +1499,11 @@ export class ExchangeClient {
1763
1499
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
1764
1500
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
1765
1501
  *
1766
- * const result = await client.updateLeverage({ asset: 0, isCross: true, leverage: 5 });
1502
+ * const data = await exchClient.updateLeverage({
1503
+ * asset: 0,
1504
+ * isCross: true,
1505
+ * leverage: 5,
1506
+ * });
1767
1507
  * ```
1768
1508
  */
1769
1509
  async updateLeverage(args, signal) {
@@ -1773,14 +1513,12 @@ export class ExchangeClient {
1773
1513
  const nonce = await this.nonceManager();
1774
1514
  const action = {
1775
1515
  type: "updateLeverage",
1776
- asset: actionArgs.asset,
1777
- isCross: actionArgs.isCross,
1778
- leverage: actionArgs.leverage,
1516
+ ...actionArgs,
1779
1517
  };
1780
1518
  // Sign the action
1781
1519
  const signature = await signL1Action({
1782
1520
  wallet: this.wallet,
1783
- action,
1521
+ action: actionSorter[action.type](action),
1784
1522
  nonce,
1785
1523
  isTestnet: this.isTestnet,
1786
1524
  vaultAddress,
@@ -1806,34 +1544,30 @@ export class ExchangeClient {
1806
1544
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
1807
1545
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
1808
1546
  *
1809
- * const result = await client.usdClassTransfer({ amount: "1", toPerp: true });
1547
+ * const data = await exchClient.usdClassTransfer({ amount: "1", toPerp: true });
1810
1548
  * ```
1811
1549
  */
1812
1550
  async usdClassTransfer(args, signal) {
1551
+ // Destructure the parameters
1552
+ const { ...actionArgs } = args;
1813
1553
  // Construct an action
1554
+ const nonce = await this.nonceManager();
1814
1555
  const action = {
1815
- ...args,
1556
+ ...actionArgs,
1816
1557
  type: "usdClassTransfer",
1817
1558
  hyperliquidChain: this._getHyperliquidChain(),
1818
1559
  signatureChainId: await this._getSignatureChainId(),
1819
- nonce: await this.nonceManager(),
1560
+ nonce,
1820
1561
  };
1821
1562
  // Sign the action
1822
1563
  const signature = await signUserSignedAction({
1823
1564
  wallet: this.wallet,
1824
1565
  action,
1825
- types: {
1826
- "HyperliquidTransaction:UsdClassTransfer": [
1827
- { name: "hyperliquidChain", type: "string" },
1828
- { name: "amount", type: "string" },
1829
- { name: "toPerp", type: "bool" },
1830
- { name: "nonce", type: "uint64" },
1831
- ],
1832
- },
1566
+ types: userSignedActionEip712Types[action.type],
1833
1567
  chainId: parseInt(action.signatureChainId, 16),
1834
1568
  });
1835
1569
  // Send a request
1836
- return await this._request({ action, signature, nonce: action.nonce }, signal);
1570
+ return await this._request({ action, signature, nonce }, signal);
1837
1571
  }
1838
1572
  /**
1839
1573
  * Send usd to another address.
@@ -1852,34 +1586,30 @@ export class ExchangeClient {
1852
1586
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
1853
1587
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
1854
1588
  *
1855
- * const result = await client.usdSend({ destination: "0x...", amount: "1" });
1589
+ * const data = await exchClient.usdSend({ destination: "0x...", amount: "1" });
1856
1590
  * ```
1857
1591
  */
1858
1592
  async usdSend(args, signal) {
1593
+ // Destructure the parameters
1594
+ const { ...actionArgs } = args;
1859
1595
  // Construct an action
1596
+ const nonce = await this.nonceManager();
1860
1597
  const action = {
1861
- ...args,
1598
+ ...actionArgs,
1862
1599
  type: "usdSend",
1863
1600
  hyperliquidChain: this._getHyperliquidChain(),
1864
1601
  signatureChainId: await this._getSignatureChainId(),
1865
- time: await this.nonceManager(),
1602
+ time: nonce,
1866
1603
  };
1867
1604
  // Sign the action
1868
1605
  const signature = await signUserSignedAction({
1869
1606
  wallet: this.wallet,
1870
1607
  action,
1871
- types: {
1872
- "HyperliquidTransaction:UsdSend": [
1873
- { name: "hyperliquidChain", type: "string" },
1874
- { name: "destination", type: "string" },
1875
- { name: "amount", type: "string" },
1876
- { name: "time", type: "uint64" },
1877
- ],
1878
- },
1608
+ types: userSignedActionEip712Types[action.type],
1879
1609
  chainId: parseInt(action.signatureChainId, 16),
1880
1610
  });
1881
1611
  // Send a request
1882
- return await this._request({ action, signature, nonce: action.time }, signal);
1612
+ return await this._request({ action, signature, nonce }, signal);
1883
1613
  }
1884
1614
  /**
1885
1615
  * Distribute funds from a vault between followers.
@@ -1898,21 +1628,22 @@ export class ExchangeClient {
1898
1628
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
1899
1629
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
1900
1630
  *
1901
- * const result = await client.vaultDistribute({ vaultAddress: "0x...", usd: 10 * 1e6 });
1631
+ * const data = await exchClient.vaultDistribute({ vaultAddress: "0x...", usd: 10 * 1e6 });
1902
1632
  * ```
1903
1633
  */
1904
1634
  async vaultDistribute(args, signal) {
1635
+ // Destructure the parameters
1636
+ const { ...actionArgs } = args;
1905
1637
  // Construct an action
1906
1638
  const nonce = await this.nonceManager();
1907
1639
  const action = {
1908
1640
  type: "vaultDistribute",
1909
- vaultAddress: args.vaultAddress,
1910
- usd: args.usd,
1641
+ ...actionArgs,
1911
1642
  };
1912
1643
  // Sign the action
1913
1644
  const signature = await signL1Action({
1914
1645
  wallet: this.wallet,
1915
- action,
1646
+ action: actionSorter[action.type](action),
1916
1647
  nonce,
1917
1648
  isTestnet: this.isTestnet,
1918
1649
  });
@@ -1936,7 +1667,7 @@ export class ExchangeClient {
1936
1667
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
1937
1668
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
1938
1669
  *
1939
- * const result = await client.vaultModify({
1670
+ * const data = await exchClient.vaultModify({
1940
1671
  * vaultAddress: "0x...",
1941
1672
  * allowDeposits: true,
1942
1673
  * alwaysCloseOnWithdraw: false,
@@ -1944,18 +1675,18 @@ export class ExchangeClient {
1944
1675
  * ```
1945
1676
  */
1946
1677
  async vaultModify(args, signal) {
1678
+ // Destructure the parameters
1679
+ const { ...actionArgs } = args;
1947
1680
  // Construct an action
1948
1681
  const nonce = await this.nonceManager();
1949
1682
  const action = {
1950
1683
  type: "vaultModify",
1951
- vaultAddress: args.vaultAddress,
1952
- allowDeposits: args.allowDeposits,
1953
- alwaysCloseOnWithdraw: args.alwaysCloseOnWithdraw,
1684
+ ...actionArgs,
1954
1685
  };
1955
1686
  // Sign the action
1956
1687
  const signature = await signL1Action({
1957
1688
  wallet: this.wallet,
1958
- action,
1689
+ action: actionSorter[action.type](action),
1959
1690
  nonce,
1960
1691
  isTestnet: this.isTestnet,
1961
1692
  });
@@ -1979,7 +1710,7 @@ export class ExchangeClient {
1979
1710
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
1980
1711
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
1981
1712
  *
1982
- * const result = await client.vaultTransfer({
1713
+ * const data = await exchClient.vaultTransfer({
1983
1714
  * vaultAddress: "0x...",
1984
1715
  * isDeposit: true,
1985
1716
  * usd: 10 * 1e6,
@@ -1993,14 +1724,12 @@ export class ExchangeClient {
1993
1724
  const nonce = await this.nonceManager();
1994
1725
  const action = {
1995
1726
  type: "vaultTransfer",
1996
- vaultAddress: actionArgs.vaultAddress,
1997
- isDeposit: actionArgs.isDeposit,
1998
- usd: actionArgs.usd,
1727
+ ...actionArgs,
1999
1728
  };
2000
1729
  // Sign the action
2001
1730
  const signature = await signL1Action({
2002
1731
  wallet: this.wallet,
2003
- action,
1732
+ action: actionSorter[action.type](action),
2004
1733
  nonce,
2005
1734
  isTestnet: this.isTestnet,
2006
1735
  expiresAfter,
@@ -2025,34 +1754,30 @@ export class ExchangeClient {
2025
1754
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
2026
1755
  * const exchClient = new hl.ExchangeClient({ wallet, transport });
2027
1756
  *
2028
- * const result = await client.withdraw3({ destination: "0x...", amount: "1" });
1757
+ * const data = await exchClient.withdraw3({ destination: "0x...", amount: "1" });
2029
1758
  * ```
2030
1759
  */
2031
1760
  async withdraw3(args, signal) {
1761
+ // Destructure the parameters
1762
+ const { ...actionArgs } = args;
2032
1763
  // Construct an action
1764
+ const nonce = await this.nonceManager();
2033
1765
  const action = {
2034
- ...args,
1766
+ ...actionArgs,
2035
1767
  type: "withdraw3",
2036
1768
  hyperliquidChain: this._getHyperliquidChain(),
2037
1769
  signatureChainId: await this._getSignatureChainId(),
2038
- time: await this.nonceManager(),
1770
+ time: nonce,
2039
1771
  };
2040
1772
  // Sign the action
2041
1773
  const signature = await signUserSignedAction({
2042
1774
  wallet: this.wallet,
2043
1775
  action,
2044
- types: {
2045
- "HyperliquidTransaction:Withdraw": [
2046
- { name: "hyperliquidChain", type: "string" },
2047
- { name: "destination", type: "string" },
2048
- { name: "amount", type: "string" },
2049
- { name: "time", type: "uint64" },
2050
- ],
2051
- },
1776
+ types: userSignedActionEip712Types[action.type],
2052
1777
  chainId: parseInt(action.signatureChainId, 16),
2053
1778
  });
2054
1779
  // Send a request
2055
- return await this._request({ action, signature, nonce: action.time }, signal);
1780
+ return await this._request({ action, signature, nonce }, signal);
2056
1781
  }
2057
1782
  /** Send an API request and validate the response. */
2058
1783
  async _request(payload, signal) {
@@ -2060,18 +1785,10 @@ export class ExchangeClient {
2060
1785
  this._validateResponse(response);
2061
1786
  return response;
2062
1787
  }
2063
- /** Formats a decimal number as a string, removing trailing zeros. */
2064
- _formatDecimal(numStr) {
2065
- if (!numStr.includes("."))
2066
- return numStr;
2067
- const [intPart, fracPart] = numStr.split(".");
2068
- const newFrac = fracPart.replace(/0+$/, "");
2069
- return newFrac ? `${intPart}.${newFrac}` : intPart;
2070
- }
2071
1788
  /** Guesses the chain ID based on the wallet type or the isTestnet flag. */
2072
1789
  async _guessSignatureChainId() {
2073
1790
  // Trying to get chain ID of the wallet
2074
- if (isAbstractViemWalletClient(this.wallet) || isAbstractExtendedViemWalletClient(this.wallet)) {
1791
+ if (isAbstractViemWalletClient(this.wallet)) {
2075
1792
  if ("getChainId" in this.wallet && typeof this.wallet.getChainId === "function") {
2076
1793
  const chainId = await this.wallet.getChainId();
2077
1794
  return `0x${chainId.toString(16)}`;