@nktkas/hyperliquid 0.16.0 → 0.17.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 (50) hide show
  1. package/README.md +44 -92
  2. package/esm/src/clients/wallet.d.ts +117 -90
  3. package/esm/src/clients/wallet.d.ts.map +1 -1
  4. package/esm/src/clients/wallet.js +278 -222
  5. package/esm/src/signing.d.ts +105 -32
  6. package/esm/src/signing.d.ts.map +1 -1
  7. package/esm/src/signing.js +79 -15
  8. package/esm/src/transports/http/http_transport.d.ts +14 -24
  9. package/esm/src/transports/http/http_transport.d.ts.map +1 -1
  10. package/esm/src/transports/http/http_transport.js +20 -15
  11. package/esm/src/transports/websocket/websocket_transport.d.ts +6 -2
  12. package/esm/src/transports/websocket/websocket_transport.d.ts.map +1 -1
  13. package/esm/src/types/exchange/requests.d.ts +28 -14
  14. package/esm/src/types/exchange/requests.d.ts.map +1 -1
  15. package/esm/src/types/info/accounts.d.ts +4 -0
  16. package/esm/src/types/info/accounts.d.ts.map +1 -1
  17. package/esm/src/types/info/assets.d.ts +2 -0
  18. package/esm/src/types/info/assets.d.ts.map +1 -1
  19. package/esm/src/types/info/orders.d.ts +28 -20
  20. package/esm/src/types/info/orders.d.ts.map +1 -1
  21. package/esm/src/types/info/vaults.d.ts +2 -0
  22. package/esm/src/types/info/vaults.d.ts.map +1 -1
  23. package/esm/src/types/mod.d.ts +23 -0
  24. package/esm/src/types/mod.d.ts.map +1 -1
  25. package/esm/src/types/mod.js +23 -0
  26. package/package.json +4 -1
  27. package/script/src/clients/wallet.d.ts +117 -90
  28. package/script/src/clients/wallet.d.ts.map +1 -1
  29. package/script/src/clients/wallet.js +278 -222
  30. package/script/src/signing.d.ts +105 -32
  31. package/script/src/signing.d.ts.map +1 -1
  32. package/script/src/signing.js +80 -16
  33. package/script/src/transports/http/http_transport.d.ts +14 -24
  34. package/script/src/transports/http/http_transport.d.ts.map +1 -1
  35. package/script/src/transports/http/http_transport.js +20 -15
  36. package/script/src/transports/websocket/websocket_transport.d.ts +6 -2
  37. package/script/src/transports/websocket/websocket_transport.d.ts.map +1 -1
  38. package/script/src/types/exchange/requests.d.ts +28 -14
  39. package/script/src/types/exchange/requests.d.ts.map +1 -1
  40. package/script/src/types/info/accounts.d.ts +4 -0
  41. package/script/src/types/info/accounts.d.ts.map +1 -1
  42. package/script/src/types/info/assets.d.ts +2 -0
  43. package/script/src/types/info/assets.d.ts.map +1 -1
  44. package/script/src/types/info/orders.d.ts +28 -20
  45. package/script/src/types/info/orders.d.ts.map +1 -1
  46. package/script/src/types/info/vaults.d.ts +2 -0
  47. package/script/src/types/info/vaults.d.ts.map +1 -1
  48. package/script/src/types/mod.d.ts +23 -0
  49. package/script/src/types/mod.d.ts.map +1 -1
  50. package/script/src/types/mod.js +23 -0
@@ -40,23 +40,38 @@ export class ApiRequestError extends HyperliquidError {
40
40
  }
41
41
  }
42
42
  // ——————————————— Client ———————————————
43
- /**
44
- * Wallet client for interacting with the Hyperliquid API.
45
- * @typeParam T The transport used to connect to the Hyperliquid API.
46
- * @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.
47
- */
48
- export class WalletClient {
49
- /** Gets the next nonce for signing transactions. */
50
- get _nonce() {
43
+ /** Nonce manager for generating unique nonces for signing transactions. */
44
+ class NonceManager {
45
+ constructor() {
46
+ /** The last nonce used for signing transactions. */
47
+ Object.defineProperty(this, "lastNonce", {
48
+ enumerable: true,
49
+ configurable: true,
50
+ writable: true,
51
+ value: 0
52
+ });
53
+ }
54
+ /**
55
+ * Gets the next nonce for signing transactions.
56
+ * @returns The next nonce.
57
+ */
58
+ getNonce() {
51
59
  let nonce = Date.now();
52
- if (nonce <= this._lastNonce) {
53
- nonce = ++this._lastNonce;
60
+ if (nonce <= this.lastNonce) {
61
+ nonce = ++this.lastNonce;
54
62
  }
55
63
  else {
56
- this._lastNonce = nonce;
64
+ this.lastNonce = nonce;
57
65
  }
58
66
  return nonce;
59
67
  }
68
+ }
69
+ /**
70
+ * Wallet client for interacting with the Hyperliquid API.
71
+ * @typeParam T The transport used to connect to the Hyperliquid API.
72
+ * @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.
73
+ */
74
+ export class WalletClient {
60
75
  /**
61
76
  * Initialises a new instance.
62
77
  * @param args - The parameters for the client.
@@ -142,41 +157,19 @@ export class WalletClient {
142
157
  writable: true,
143
158
  value: void 0
144
159
  });
145
- /** The last nonce used for signing transactions. */
146
- Object.defineProperty(this, "_lastNonce", {
160
+ /** Function to get the next nonce for signing transactions. */
161
+ Object.defineProperty(this, "nonceManager", {
147
162
  enumerable: true,
148
163
  configurable: true,
149
164
  writable: true,
150
- value: 0
165
+ value: void 0
151
166
  });
152
167
  this.transport = args.transport;
153
168
  this.wallet = args.wallet;
154
169
  this.isTestnet = args.isTestnet ?? false;
155
170
  this.defaultVaultAddress = args.defaultVaultAddress;
156
- this.signatureChainId = args.signatureChainId ?? (async () => {
157
- // Trying to get chain id of the wallet
158
- if (isAbstractViemWalletClient(this.wallet)) {
159
- if ("getChainId" in this.wallet && typeof this.wallet.getChainId === "function") {
160
- const chainId = await this.wallet.getChainId();
161
- return `0x${chainId.toString(16)}`;
162
- }
163
- }
164
- else if (isAbstractEthersSigner(this.wallet) || isAbstractEthersV5Signer(this.wallet)) {
165
- if ("provider" in this.wallet &&
166
- typeof this.wallet.provider === "object" && this.wallet.provider !== null &&
167
- "getNetwork" in this.wallet.provider &&
168
- typeof this.wallet.provider.getNetwork === "function") {
169
- const network = await this.wallet.provider.getNetwork();
170
- return `0x${network.chainId.toString(16)}`;
171
- }
172
- }
173
- else if (isAbstractWindowEthereum(this.wallet)) {
174
- const [chainId] = await this.wallet.request({ method: "eth_chainId", params: [] });
175
- return chainId;
176
- }
177
- // Trying to guess chain id based on isTestnet
178
- return this.isTestnet ? "0x66eee" : "0xa4b1";
179
- });
171
+ this.signatureChainId = args.signatureChainId ?? this._guessSignatureChainId;
172
+ this.nonceManager = args.nonceManager ?? new NonceManager().getNonce;
180
173
  }
181
174
  // ——————————————— Exchange API ———————————————
182
175
  /**
@@ -211,7 +204,7 @@ export class WalletClient {
211
204
  signatureChainId: typeof this.signatureChainId === "string"
212
205
  ? this.signatureChainId
213
206
  : await this.signatureChainId(),
214
- nonce: args.nonce ?? this._nonce,
207
+ nonce: await this.nonceManager(),
215
208
  };
216
209
  // Sign the action
217
210
  const signature = await signUserSignedAction({
@@ -266,7 +259,7 @@ export class WalletClient {
266
259
  signatureChainId: typeof this.signatureChainId === "string"
267
260
  ? this.signatureChainId
268
261
  : await this.signatureChainId(),
269
- nonce: args.nonce ?? this._nonce,
262
+ nonce: await this.nonceManager(),
270
263
  };
271
264
  // Sign the action
272
265
  const signature = await signUserSignedAction({
@@ -328,8 +321,9 @@ export class WalletClient {
328
321
  */
329
322
  async batchModify(args, signal) {
330
323
  // Destructure the parameters
331
- const { vaultAddress = this.defaultVaultAddress, nonce = this._nonce, ...actionArgs } = args;
324
+ const { vaultAddress = this.defaultVaultAddress, ...actionArgs } = args;
332
325
  // Construct an action
326
+ const nonce = await this.nonceManager();
333
327
  const action = {
334
328
  type: "batchModify",
335
329
  modifies: actionArgs.modifies.map((modify) => {
@@ -404,8 +398,9 @@ export class WalletClient {
404
398
  */
405
399
  async cancel(args, signal) {
406
400
  // Destructure the parameters
407
- const { vaultAddress = this.defaultVaultAddress, nonce = this._nonce, ...actionArgs } = args;
401
+ const { vaultAddress = this.defaultVaultAddress, ...actionArgs } = args;
408
402
  // Construct an action
403
+ const nonce = await this.nonceManager();
409
404
  const action = {
410
405
  type: "cancel",
411
406
  cancels: actionArgs.cancels.map((cancel) => ({
@@ -428,6 +423,58 @@ export class WalletClient {
428
423
  this._validateResponse(response);
429
424
  return response;
430
425
  }
426
+ /**
427
+ * Cancel order(s) by cloid.
428
+ * @param args - The parameters for the request.
429
+ * @param signal - An optional abort signal.
430
+ * @returns Successful variant of {@link CancelResponse} without error statuses.
431
+ * @throws {ApiRequestError} When the API returns an error response.
432
+ *
433
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#cancel-order-s-by-cloid
434
+ * @example
435
+ * ```ts
436
+ * import * as hl from "@nktkas/hyperliquid";
437
+ * import { privateKeyToAccount } from "viem/accounts";
438
+ *
439
+ * const wallet = privateKeyToAccount("0x...");
440
+ * const transport = new hl.HttpTransport(); // or WebSocketTransport
441
+ * const client = new hl.WalletClient({ wallet, transport });
442
+ *
443
+ * const result = await client.cancelByCloid({
444
+ * cancels: [{
445
+ * asset: 0,
446
+ * cloid: "0x...", // Client Order ID
447
+ * }],
448
+ * });
449
+ * ```
450
+ */
451
+ async cancelByCloid(args, signal) {
452
+ // Destructure the parameters
453
+ const { vaultAddress = this.defaultVaultAddress, ...actionArgs } = args;
454
+ // Construct an action
455
+ const nonce = await this.nonceManager();
456
+ const action = {
457
+ type: "cancelByCloid",
458
+ cancels: actionArgs.cancels.map((cancel) => ({
459
+ asset: cancel.asset,
460
+ cloid: cancel.cloid,
461
+ })),
462
+ };
463
+ // Sign the action
464
+ const signature = await signL1Action({
465
+ wallet: this.wallet,
466
+ action,
467
+ nonce,
468
+ isTestnet: this.isTestnet,
469
+ vaultAddress,
470
+ });
471
+ // Send a request
472
+ const request = { action, signature, nonce, vaultAddress };
473
+ const response = await this.transport.request("exchange", request, signal);
474
+ // Validate a response
475
+ this._validateResponse(response);
476
+ return response;
477
+ }
431
478
  /**
432
479
  * Deposit into staking balance.
433
480
  * @param args - The parameters for the request.
@@ -457,7 +504,7 @@ export class WalletClient {
457
504
  signatureChainId: typeof this.signatureChainId === "string"
458
505
  ? this.signatureChainId
459
506
  : await this.signatureChainId(),
460
- nonce: args.nonce ?? this._nonce,
507
+ nonce: await this.nonceManager(),
461
508
  };
462
509
  // Sign the action
463
510
  const signature = await signUserSignedAction({
@@ -499,10 +546,9 @@ export class WalletClient {
499
546
  * const result = await client.claimRewards();
500
547
  * ```
501
548
  */
502
- async claimRewards(args = {}, signal) {
503
- // Destructure the parameters
504
- const { nonce = this._nonce, } = args;
549
+ async claimRewards(signal) {
505
550
  // Construct an action
551
+ const nonce = await this.nonceManager();
506
552
  const sortedAction = { type: "claimRewards" };
507
553
  // Sign the action
508
554
  const signature = await signL1Action({
@@ -519,13 +565,13 @@ export class WalletClient {
519
565
  return response;
520
566
  }
521
567
  /**
522
- * Cancel order(s) by cloid.
568
+ * Create a sub-account.
523
569
  * @param args - The parameters for the request.
524
570
  * @param signal - An optional abort signal.
525
- * @returns Successful variant of {@link CancelResponse} without error statuses.
571
+ * @returns Response for creating a sub-account.
526
572
  * @throws {ApiRequestError} When the API returns an error response.
527
573
  *
528
- * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#cancel-order-s-by-cloid
574
+ * @see null - no documentation
529
575
  * @example
530
576
  * ```ts
531
577
  * import * as hl from "@nktkas/hyperliquid";
@@ -535,24 +581,15 @@ export class WalletClient {
535
581
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
536
582
  * const client = new hl.WalletClient({ wallet, transport });
537
583
  *
538
- * const result = await client.cancelByCloid({
539
- * cancels: [{
540
- * asset: 0,
541
- * cloid: "0x...", // Client Order ID
542
- * }],
543
- * });
584
+ * const result = await client.createSubAccount({ name: "subAccountName" });
544
585
  * ```
545
586
  */
546
- async cancelByCloid(args, signal) {
547
- // Destructure the parameters
548
- const { vaultAddress = this.defaultVaultAddress, nonce = this._nonce, ...actionArgs } = args;
587
+ async createSubAccount(args, signal) {
549
588
  // Construct an action
589
+ const nonce = await this.nonceManager();
550
590
  const action = {
551
- type: "cancelByCloid",
552
- cancels: actionArgs.cancels.map((cancel) => ({
553
- asset: cancel.asset,
554
- cloid: cancel.cloid,
555
- })),
591
+ type: "createSubAccount",
592
+ name: args.name,
556
593
  };
557
594
  // Sign the action
558
595
  const signature = await signL1Action({
@@ -560,74 +597,22 @@ export class WalletClient {
560
597
  action,
561
598
  nonce,
562
599
  isTestnet: this.isTestnet,
563
- vaultAddress,
564
600
  });
565
601
  // Send a request
566
- const request = { action, signature, nonce, vaultAddress };
567
- const response = await this.transport.request("exchange", request, signal);
568
- // Validate a response
569
- this._validateResponse(response);
570
- return response;
571
- }
572
- /**
573
- * Withdraw from staking balance.
574
- * @param args - The parameters for the request.
575
- * @param signal - An optional abort signal.
576
- * @returns Successful response without specific data.
577
- * @throws {ApiRequestError} When the API returns an error response.
578
- *
579
- * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#withdraw-from-staking
580
- * @example
581
- * ```ts
582
- * import * as hl from "@nktkas/hyperliquid";
583
- * import { privateKeyToAccount } from "viem/accounts";
584
- *
585
- * const wallet = privateKeyToAccount("0x...");
586
- * const transport = new hl.HttpTransport(); // or WebSocketTransport
587
- * const client = new hl.WalletClient({ wallet, transport });
588
- *
589
- * const result = await client.cWithdraw({ wei: 1 * 1e8 });
590
- * ```
591
- */
592
- async cWithdraw(args, signal) {
593
- // Construct an action
594
- const action = {
595
- ...args,
596
- type: "cWithdraw",
597
- hyperliquidChain: this.isTestnet ? "Testnet" : "Mainnet",
598
- signatureChainId: typeof this.signatureChainId === "string"
599
- ? this.signatureChainId
600
- : await this.signatureChainId(),
601
- nonce: args.nonce ?? this._nonce,
602
- };
603
- // Sign the action
604
- const signature = await signUserSignedAction({
605
- wallet: this.wallet,
606
- action,
607
- types: {
608
- "HyperliquidTransaction:CWithdraw": [
609
- { name: "hyperliquidChain", type: "string" },
610
- { name: "wei", type: "uint64" },
611
- { name: "nonce", type: "uint64" },
612
- ],
613
- },
614
- chainId: parseInt(action.signatureChainId, 16),
615
- });
616
- // Send a request
617
- const request = { action, signature, nonce: action.nonce };
602
+ const request = { action, signature, nonce };
618
603
  const response = await this.transport.request("exchange", request, signal);
619
604
  // Validate a response
620
605
  this._validateResponse(response);
621
606
  return response;
622
607
  }
623
608
  /**
624
- * Configure block type for EVM transactions.
609
+ * Create a vault.
625
610
  * @param args - The parameters for the request.
626
611
  * @param signal - An optional abort signal.
627
- * @returns Response for creating a sub-account.
612
+ * @returns Response for creating a vault.
628
613
  * @throws {ApiRequestError} When the API returns an error response.
629
614
  *
630
- * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/evm/dual-block-architecture
615
+ * @see null - no documentation
631
616
  * @example
632
617
  * ```ts
633
618
  * import * as hl from "@nktkas/hyperliquid";
@@ -637,16 +622,22 @@ export class WalletClient {
637
622
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
638
623
  * const client = new hl.WalletClient({ wallet, transport });
639
624
  *
640
- * const result = await client.evmUserModify({ usingBigBlocks: true });
625
+ * const result = await client.createVault({
626
+ * name: "VaultName",
627
+ * description: "This is an example of a vault description",
628
+ * initialUsd: 100 * 1e6,
629
+ * });
641
630
  * ```
642
631
  */
643
- async evmUserModify(args, signal) {
644
- // Destructure the parameters
645
- const { nonce = this._nonce, ...actionArgs } = args;
632
+ async createVault(args, signal) {
646
633
  // Construct an action
634
+ const nonce = await this.nonceManager();
647
635
  const action = {
648
- type: "evmUserModify",
649
- usingBigBlocks: actionArgs.usingBigBlocks,
636
+ type: "createVault",
637
+ name: args.name,
638
+ description: args.description,
639
+ initialUsd: args.initialUsd,
640
+ nonce,
650
641
  };
651
642
  // Sign the action
652
643
  const signature = await signL1Action({
@@ -663,13 +654,13 @@ export class WalletClient {
663
654
  return response;
664
655
  }
665
656
  /**
666
- * Create a sub-account.
657
+ * Withdraw from staking balance.
667
658
  * @param args - The parameters for the request.
668
659
  * @param signal - An optional abort signal.
669
- * @returns Response for creating a sub-account.
660
+ * @returns Successful response without specific data.
670
661
  * @throws {ApiRequestError} When the API returns an error response.
671
662
  *
672
- * @see null - no documentation
663
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#withdraw-from-staking
673
664
  * @example
674
665
  * ```ts
675
666
  * import * as hl from "@nktkas/hyperliquid";
@@ -679,39 +670,48 @@ export class WalletClient {
679
670
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
680
671
  * const client = new hl.WalletClient({ wallet, transport });
681
672
  *
682
- * const result = await client.createSubAccount({ name: "subAccountName" });
673
+ * const result = await client.cWithdraw({ wei: 1 * 1e8 });
683
674
  * ```
684
675
  */
685
- async createSubAccount(args, signal) {
686
- // Destructure the parameters
687
- const { nonce = this._nonce, ...actionArgs } = args;
676
+ async cWithdraw(args, signal) {
688
677
  // Construct an action
689
678
  const action = {
690
- type: "createSubAccount",
691
- name: actionArgs.name,
679
+ ...args,
680
+ type: "cWithdraw",
681
+ hyperliquidChain: this.isTestnet ? "Testnet" : "Mainnet",
682
+ signatureChainId: typeof this.signatureChainId === "string"
683
+ ? this.signatureChainId
684
+ : await this.signatureChainId(),
685
+ nonce: await this.nonceManager(),
692
686
  };
693
687
  // Sign the action
694
- const signature = await signL1Action({
688
+ const signature = await signUserSignedAction({
695
689
  wallet: this.wallet,
696
690
  action,
697
- nonce,
698
- isTestnet: this.isTestnet,
691
+ types: {
692
+ "HyperliquidTransaction:CWithdraw": [
693
+ { name: "hyperliquidChain", type: "string" },
694
+ { name: "wei", type: "uint64" },
695
+ { name: "nonce", type: "uint64" },
696
+ ],
697
+ },
698
+ chainId: parseInt(action.signatureChainId, 16),
699
699
  });
700
700
  // Send a request
701
- const request = { action, signature, nonce };
701
+ const request = { action, signature, nonce: action.nonce };
702
702
  const response = await this.transport.request("exchange", request, signal);
703
703
  // Validate a response
704
704
  this._validateResponse(response);
705
705
  return response;
706
706
  }
707
707
  /**
708
- * Create a vault.
708
+ * Configure block type for EVM transactions.
709
709
  * @param args - The parameters for the request.
710
710
  * @param signal - An optional abort signal.
711
- * @returns Response for creating a vault.
711
+ * @returns Response for creating a sub-account.
712
712
  * @throws {ApiRequestError} When the API returns an error response.
713
713
  *
714
- * @see null - no documentation
714
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/evm/dual-block-architecture
715
715
  * @example
716
716
  * ```ts
717
717
  * import * as hl from "@nktkas/hyperliquid";
@@ -721,23 +721,15 @@ export class WalletClient {
721
721
  * const transport = new hl.HttpTransport(); // or WebSocketTransport
722
722
  * const client = new hl.WalletClient({ wallet, transport });
723
723
  *
724
- * const result = await client.createVault({
725
- * name: "VaultName",
726
- * description: "This is an example of a vault description",
727
- * initialUsd: 100 * 1e6,
728
- * });
724
+ * const result = await client.evmUserModify({ usingBigBlocks: true });
729
725
  * ```
730
726
  */
731
- async createVault(args, signal) {
732
- // Destructure the parameters
733
- const { nonce = this._nonce, ...actionArgs } = args;
727
+ async evmUserModify(args, signal) {
734
728
  // Construct an action
729
+ const nonce = await this.nonceManager();
735
730
  const action = {
736
- type: "createVault",
737
- name: actionArgs.name,
738
- description: actionArgs.description,
739
- initialUsd: actionArgs.initialUsd,
740
- nonce,
731
+ type: "evmUserModify",
732
+ usingBigBlocks: args.usingBigBlocks,
741
733
  };
742
734
  // Sign the action
743
735
  const signature = await signL1Action({
@@ -790,8 +782,9 @@ export class WalletClient {
790
782
  */
791
783
  async modify(args, signal) {
792
784
  // Destructure the parameters
793
- const { vaultAddress = this.defaultVaultAddress, nonce = this._nonce, ...actionArgs } = args;
785
+ const { vaultAddress = this.defaultVaultAddress, ...actionArgs } = args;
794
786
  // Construct an action
787
+ const nonce = await this.nonceManager();
795
788
  const action = {
796
789
  type: "modify",
797
790
  oid: actionArgs.oid,
@@ -871,8 +864,9 @@ export class WalletClient {
871
864
  */
872
865
  async order(args, signal) {
873
866
  // Destructure the parameters
874
- const { vaultAddress = this.defaultVaultAddress, nonce = this._nonce, ...actionArgs } = args;
867
+ const { vaultAddress = this.defaultVaultAddress, ...actionArgs } = args;
875
868
  // Construct an action
869
+ const nonce = await this.nonceManager();
876
870
  const action = {
877
871
  type: "order",
878
872
  orders: actionArgs.orders.map((order) => {
@@ -926,6 +920,47 @@ export class WalletClient {
926
920
  this._validateResponse(response);
927
921
  return response;
928
922
  }
923
+ /**
924
+ * Reserve additional rate-limited actions for a fee.
925
+ * @param args - The parameters for the request.
926
+ * @param signal - An optional abort signal.
927
+ * @returns Successful response indicating the weight reservation.
928
+ * @throws {ApiRequestError} When the API returns an error response.
929
+ *
930
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#reserve-additional-actions
931
+ * @example
932
+ * ```ts
933
+ * import * as hl from "@nktkas/hyperliquid";
934
+ * import { privateKeyToAccount } from "viem/accounts";
935
+ *
936
+ * const wallet = privateKeyToAccount("0x...");
937
+ * const transport = new hl.HttpTransport(); // or WebSocketTransport
938
+ * const client = new hl.WalletClient({ wallet, transport });
939
+ *
940
+ * const result = await client.reserveRequestWeight({ weight: 10 });
941
+ * ```
942
+ */
943
+ async reserveRequestWeight(args, signal) {
944
+ // Construct an action
945
+ const nonce = await this.nonceManager();
946
+ const action = {
947
+ type: "reserveRequestWeight",
948
+ weight: args.weight,
949
+ };
950
+ // Sign the action
951
+ const signature = await signL1Action({
952
+ wallet: this.wallet,
953
+ action,
954
+ nonce,
955
+ isTestnet: this.isTestnet,
956
+ });
957
+ // Send a request
958
+ const request = { action, signature, nonce };
959
+ const response = await this.transport.request("exchange", request, signal);
960
+ // Validate a response
961
+ this._validateResponse(response);
962
+ return response;
963
+ }
929
964
  /**
930
965
  * Schedule a time to cancel all open orders.
931
966
  * @param args - The parameters for the request.
@@ -948,8 +983,9 @@ export class WalletClient {
948
983
  */
949
984
  async scheduleCancel(args = {}, signal) {
950
985
  // Destructure the parameters
951
- const { vaultAddress = this.defaultVaultAddress, nonce = this._nonce, ...actionArgs } = args;
986
+ const { vaultAddress = this.defaultVaultAddress, ...actionArgs } = args;
952
987
  // Construct an action
988
+ const nonce = await this.nonceManager();
953
989
  const action = {
954
990
  type: "scheduleCancel",
955
991
  time: actionArgs.time,
@@ -992,12 +1028,11 @@ export class WalletClient {
992
1028
  * ```
993
1029
  */
994
1030
  async setDisplayName(args, signal) {
995
- // Destructure the parameters
996
- const { nonce = this._nonce, ...actionArgs } = args;
997
1031
  // Construct an action
1032
+ const nonce = await this.nonceManager();
998
1033
  const action = {
999
1034
  type: "setDisplayName",
1000
- displayName: actionArgs.displayName,
1035
+ displayName: args.displayName,
1001
1036
  };
1002
1037
  // Sign the action
1003
1038
  const signature = await signL1Action({
@@ -1034,12 +1069,11 @@ export class WalletClient {
1034
1069
  * ```
1035
1070
  */
1036
1071
  async setReferrer(args, signal) {
1037
- // Destructure the parameters
1038
- const { nonce = this._nonce, ...actionArgs } = args;
1039
1072
  // Construct an action
1073
+ const nonce = await this.nonceManager();
1040
1074
  const action = {
1041
1075
  type: "setReferrer",
1042
- code: actionArgs.code,
1076
+ code: args.code,
1043
1077
  };
1044
1078
  // Sign the action
1045
1079
  const signature = await signL1Action({
@@ -1088,48 +1122,47 @@ export class WalletClient {
1088
1122
  * ```
1089
1123
  */
1090
1124
  async spotDeploy(args, signal) {
1091
- // Destructure the parameters
1092
- const { nonce = this._nonce, ...actionArgs } = args;
1093
1125
  // Construct an action
1126
+ const nonce = await this.nonceManager();
1094
1127
  let action;
1095
- if ("registerToken2" in actionArgs) {
1128
+ if ("registerToken2" in args) {
1096
1129
  action = {
1097
1130
  type: "spotDeploy",
1098
1131
  registerToken2: {
1099
1132
  spec: {
1100
- name: actionArgs.registerToken2.spec.name,
1101
- szDecimals: actionArgs.registerToken2.spec.szDecimals,
1102
- weiDecimals: actionArgs.registerToken2.spec.weiDecimals,
1133
+ name: args.registerToken2.spec.name,
1134
+ szDecimals: args.registerToken2.spec.szDecimals,
1135
+ weiDecimals: args.registerToken2.spec.weiDecimals,
1103
1136
  },
1104
- maxGas: actionArgs.registerToken2.maxGas,
1105
- fullName: actionArgs.registerToken2.fullName,
1137
+ maxGas: args.registerToken2.maxGas,
1138
+ fullName: args.registerToken2.fullName,
1106
1139
  },
1107
1140
  };
1108
1141
  }
1109
- else if ("userGenesis" in actionArgs) {
1142
+ else if ("userGenesis" in args) {
1110
1143
  action = {
1111
1144
  type: "spotDeploy",
1112
1145
  userGenesis: {
1113
- token: actionArgs.userGenesis.token,
1114
- userAndWei: actionArgs.userGenesis.userAndWei,
1115
- existingTokenAndWei: actionArgs.userGenesis.existingTokenAndWei,
1146
+ token: args.userGenesis.token,
1147
+ userAndWei: args.userGenesis.userAndWei,
1148
+ existingTokenAndWei: args.userGenesis.existingTokenAndWei,
1116
1149
  },
1117
1150
  };
1118
1151
  }
1119
- else if ("genesis" in actionArgs) {
1152
+ else if ("genesis" in args) {
1120
1153
  action = {
1121
1154
  type: "spotDeploy",
1122
1155
  genesis: {
1123
- token: actionArgs.genesis.token,
1124
- maxSupply: actionArgs.genesis.maxSupply,
1156
+ token: args.genesis.token,
1157
+ maxSupply: args.genesis.maxSupply,
1125
1158
  },
1126
1159
  };
1127
1160
  }
1128
- else if ("registerSpot" in actionArgs) {
1161
+ else if ("registerSpot" in args) {
1129
1162
  action = {
1130
1163
  type: "spotDeploy",
1131
1164
  registerSpot: {
1132
- tokens: actionArgs.registerSpot.tokens,
1165
+ tokens: args.registerSpot.tokens,
1133
1166
  },
1134
1167
  };
1135
1168
  }
@@ -1137,11 +1170,11 @@ export class WalletClient {
1137
1170
  action = {
1138
1171
  type: "spotDeploy",
1139
1172
  registerHyperliquidity: {
1140
- spot: actionArgs.registerHyperliquidity.spot,
1141
- startPx: actionArgs.registerHyperliquidity.startPx,
1142
- orderSz: actionArgs.registerHyperliquidity.orderSz,
1143
- nOrders: actionArgs.registerHyperliquidity.nOrders,
1144
- nSeededLevels: actionArgs.registerHyperliquidity.nSeededLevels,
1173
+ spot: args.registerHyperliquidity.spot,
1174
+ startPx: args.registerHyperliquidity.startPx,
1175
+ orderSz: args.registerHyperliquidity.orderSz,
1176
+ nOrders: args.registerHyperliquidity.nOrders,
1177
+ nSeededLevels: args.registerHyperliquidity.nSeededLevels,
1145
1178
  },
1146
1179
  };
1147
1180
  }
@@ -1192,7 +1225,7 @@ export class WalletClient {
1192
1225
  signatureChainId: typeof this.signatureChainId === "string"
1193
1226
  ? this.signatureChainId
1194
1227
  : await this.signatureChainId(),
1195
- time: args.time ?? this._nonce,
1228
+ time: await this.nonceManager(),
1196
1229
  };
1197
1230
  // Sign the action
1198
1231
  const signature = await signUserSignedAction({
@@ -1239,13 +1272,12 @@ export class WalletClient {
1239
1272
  * ```
1240
1273
  */
1241
1274
  async spotUser(args, signal) {
1242
- // Destructure the parameters
1243
- const { nonce = this._nonce, ...actionArgs } = args;
1244
1275
  // Construct an action
1276
+ const nonce = await this.nonceManager();
1245
1277
  const action = {
1246
1278
  type: "spotUser",
1247
1279
  toggleSpotDusting: {
1248
- optOut: actionArgs.toggleSpotDusting.optOut,
1280
+ optOut: args.toggleSpotDusting.optOut,
1249
1281
  },
1250
1282
  };
1251
1283
  // Sign the action
@@ -1288,15 +1320,14 @@ export class WalletClient {
1288
1320
  * ```
1289
1321
  */
1290
1322
  async subAccountSpotTransfer(args, signal) {
1291
- // Destructure the parameters
1292
- const { nonce = this._nonce, ...actionArgs } = args;
1293
1323
  // Construct an action
1324
+ const nonce = await this.nonceManager();
1294
1325
  const action = {
1295
1326
  type: "subAccountSpotTransfer",
1296
- subAccountUser: actionArgs.subAccountUser,
1297
- isDeposit: actionArgs.isDeposit,
1298
- token: actionArgs.token,
1299
- amount: actionArgs.amount,
1327
+ subAccountUser: args.subAccountUser,
1328
+ isDeposit: args.isDeposit,
1329
+ token: args.token,
1330
+ amount: args.amount,
1300
1331
  };
1301
1332
  // Sign the action
1302
1333
  const signature = await signL1Action({
@@ -1337,14 +1368,13 @@ export class WalletClient {
1337
1368
  * ```
1338
1369
  */
1339
1370
  async subAccountTransfer(args, signal) {
1340
- // Destructure the parameters
1341
- const { nonce = this._nonce, ...actionArgs } = args;
1342
1371
  // Construct an action
1372
+ const nonce = await this.nonceManager();
1343
1373
  const action = {
1344
1374
  type: "subAccountTransfer",
1345
- subAccountUser: actionArgs.subAccountUser,
1346
- isDeposit: actionArgs.isDeposit,
1347
- usd: actionArgs.usd,
1375
+ subAccountUser: args.subAccountUser,
1376
+ isDeposit: args.isDeposit,
1377
+ usd: args.usd,
1348
1378
  };
1349
1379
  // Sign the action
1350
1380
  const signature = await signL1Action({
@@ -1393,7 +1423,7 @@ export class WalletClient {
1393
1423
  signatureChainId: typeof this.signatureChainId === "string"
1394
1424
  ? this.signatureChainId
1395
1425
  : await this.signatureChainId(),
1396
- nonce: args.nonce ?? this._nonce,
1426
+ nonce: await this.nonceManager(),
1397
1427
  };
1398
1428
  // Sign the action
1399
1429
  const signature = await signUserSignedAction({
@@ -1442,8 +1472,9 @@ export class WalletClient {
1442
1472
  */
1443
1473
  async twapCancel(args, signal) {
1444
1474
  // Destructure the parameters
1445
- const { vaultAddress = this.defaultVaultAddress, nonce = this._nonce, ...actionArgs } = args;
1475
+ const { vaultAddress = this.defaultVaultAddress, ...actionArgs } = args;
1446
1476
  // Construct an action
1477
+ const nonce = await this.nonceManager();
1447
1478
  const action = {
1448
1479
  type: "twapCancel",
1449
1480
  a: actionArgs.a,
@@ -1493,8 +1524,9 @@ export class WalletClient {
1493
1524
  */
1494
1525
  async twapOrder(args, signal) {
1495
1526
  // Destructure the parameters
1496
- const { vaultAddress = this.defaultVaultAddress, nonce = this._nonce, ...actionArgs } = args;
1527
+ const { vaultAddress = this.defaultVaultAddress, ...actionArgs } = args;
1497
1528
  // Construct an action
1529
+ const nonce = await this.nonceManager();
1498
1530
  const action = {
1499
1531
  type: "twapOrder",
1500
1532
  twap: {
@@ -1547,8 +1579,9 @@ export class WalletClient {
1547
1579
  */
1548
1580
  async updateIsolatedMargin(args, signal) {
1549
1581
  // Destructure the parameters
1550
- const { vaultAddress = this.defaultVaultAddress, nonce = this._nonce, ...actionArgs } = args;
1582
+ const { vaultAddress = this.defaultVaultAddress, ...actionArgs } = args;
1551
1583
  // Construct an action
1584
+ const nonce = await this.nonceManager();
1552
1585
  const action = {
1553
1586
  type: "updateIsolatedMargin",
1554
1587
  asset: actionArgs.asset,
@@ -1596,8 +1629,9 @@ export class WalletClient {
1596
1629
  */
1597
1630
  async updateLeverage(args, signal) {
1598
1631
  // Destructure the parameters
1599
- const { vaultAddress = this.defaultVaultAddress, nonce = this._nonce, ...actionArgs } = args;
1632
+ const { vaultAddress = this.defaultVaultAddress, ...actionArgs } = args;
1600
1633
  // Construct an action
1634
+ const nonce = await this.nonceManager();
1601
1635
  const action = {
1602
1636
  type: "updateLeverage",
1603
1637
  asset: actionArgs.asset,
@@ -1651,7 +1685,7 @@ export class WalletClient {
1651
1685
  signatureChainId: typeof this.signatureChainId === "string"
1652
1686
  ? this.signatureChainId
1653
1687
  : await this.signatureChainId(),
1654
- nonce: args.nonce ?? this._nonce,
1688
+ nonce: await this.nonceManager(),
1655
1689
  };
1656
1690
  // Sign the action
1657
1691
  const signature = await signUserSignedAction({
@@ -1706,7 +1740,7 @@ export class WalletClient {
1706
1740
  signatureChainId: typeof this.signatureChainId === "string"
1707
1741
  ? this.signatureChainId
1708
1742
  : await this.signatureChainId(),
1709
- time: args.time ?? this._nonce,
1743
+ time: await this.nonceManager(),
1710
1744
  };
1711
1745
  // Sign the action
1712
1746
  const signature = await signUserSignedAction({
@@ -1753,13 +1787,12 @@ export class WalletClient {
1753
1787
  * ```
1754
1788
  */
1755
1789
  async vaultDistribute(args, signal) {
1756
- // Destructure the parameters
1757
- const { nonce = this._nonce, ...actionArgs } = args;
1758
1790
  // Construct an action
1791
+ const nonce = await this.nonceManager();
1759
1792
  const action = {
1760
1793
  type: "vaultDistribute",
1761
- vaultAddress: actionArgs.vaultAddress,
1762
- usd: actionArgs.usd,
1794
+ vaultAddress: args.vaultAddress,
1795
+ usd: args.usd,
1763
1796
  };
1764
1797
  // Sign the action
1765
1798
  const signature = await signL1Action({
@@ -1800,14 +1833,13 @@ export class WalletClient {
1800
1833
  * ```
1801
1834
  */
1802
1835
  async vaultModify(args, signal) {
1803
- // Destructure the parameters
1804
- const { nonce = this._nonce, ...actionArgs } = args;
1805
1836
  // Construct an action
1837
+ const nonce = await this.nonceManager();
1806
1838
  const action = {
1807
1839
  type: "vaultModify",
1808
- vaultAddress: actionArgs.vaultAddress,
1809
- allowDeposits: actionArgs.allowDeposits,
1810
- alwaysCloseOnWithdraw: actionArgs.alwaysCloseOnWithdraw,
1840
+ vaultAddress: args.vaultAddress,
1841
+ allowDeposits: args.allowDeposits,
1842
+ alwaysCloseOnWithdraw: args.alwaysCloseOnWithdraw,
1811
1843
  };
1812
1844
  // Sign the action
1813
1845
  const signature = await signL1Action({
@@ -1848,14 +1880,13 @@ export class WalletClient {
1848
1880
  * ```
1849
1881
  */
1850
1882
  async vaultTransfer(args, signal) {
1851
- // Destructure the parameters
1852
- const { nonce = this._nonce, ...actionArgs } = args;
1853
1883
  // Construct an action
1884
+ const nonce = await this.nonceManager();
1854
1885
  const action = {
1855
1886
  type: "vaultTransfer",
1856
- vaultAddress: actionArgs.vaultAddress,
1857
- isDeposit: actionArgs.isDeposit,
1858
- usd: actionArgs.usd,
1887
+ vaultAddress: args.vaultAddress,
1888
+ isDeposit: args.isDeposit,
1889
+ usd: args.usd,
1859
1890
  };
1860
1891
  // Sign the action
1861
1892
  const signature = await signL1Action({
@@ -1903,7 +1934,7 @@ export class WalletClient {
1903
1934
  signatureChainId: typeof this.signatureChainId === "string"
1904
1935
  ? this.signatureChainId
1905
1936
  : await this.signatureChainId(),
1906
- time: args.time ?? this._nonce,
1937
+ time: await this.nonceManager(),
1907
1938
  };
1908
1939
  // Sign the action
1909
1940
  const signature = await signUserSignedAction({
@@ -1935,6 +1966,31 @@ export class WalletClient {
1935
1966
  const newFrac = fracPart.replace(/0+$/, "");
1936
1967
  return newFrac ? `${intPart}.${newFrac}` : intPart;
1937
1968
  }
1969
+ /** Guesses the chain ID based on the wallet type or the isTestnet flag. */
1970
+ async _guessSignatureChainId() {
1971
+ // Trying to get chain ID of the wallet
1972
+ if (isAbstractViemWalletClient(this.wallet)) {
1973
+ if ("getChainId" in this.wallet && typeof this.wallet.getChainId === "function") {
1974
+ const chainId = await this.wallet.getChainId();
1975
+ return `0x${chainId.toString(16)}`;
1976
+ }
1977
+ }
1978
+ else if (isAbstractEthersSigner(this.wallet) || isAbstractEthersV5Signer(this.wallet)) {
1979
+ if ("provider" in this.wallet &&
1980
+ typeof this.wallet.provider === "object" && this.wallet.provider !== null &&
1981
+ "getNetwork" in this.wallet.provider &&
1982
+ typeof this.wallet.provider.getNetwork === "function") {
1983
+ const network = await this.wallet.provider.getNetwork();
1984
+ return `0x${network.chainId.toString(16)}`;
1985
+ }
1986
+ }
1987
+ else if (isAbstractWindowEthereum(this.wallet)) {
1988
+ const [chainId] = await this.wallet.request({ method: "eth_chainId", params: [] });
1989
+ return chainId;
1990
+ }
1991
+ // Attempt to guess chain ID based on isTestnet
1992
+ return this.isTestnet ? "0x66eee" : "0xa4b1";
1993
+ }
1938
1994
  /** Validate a response from the API. */
1939
1995
  _validateResponse(response) {
1940
1996
  if (response.status === "err") {