@nktkas/hyperliquid 0.19.1 → 0.20.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 (136) hide show
  1. package/CONTRIBUTING.md +4 -2
  2. package/README.md +36 -35
  3. package/esm/_dnt.polyfills.d.ts +20 -0
  4. package/esm/_dnt.polyfills.d.ts.map +1 -0
  5. package/esm/_dnt.polyfills.js +12 -0
  6. package/esm/mod.d.ts +3 -0
  7. package/esm/mod.d.ts.map +1 -1
  8. package/esm/mod.js +2 -0
  9. package/esm/src/base.d.ts +1 -47
  10. package/esm/src/base.d.ts.map +1 -1
  11. package/esm/src/base.js +1 -8
  12. package/esm/src/clients/event.d.ts +6 -4
  13. package/esm/src/clients/event.d.ts.map +1 -1
  14. package/esm/src/clients/event.js +58 -77
  15. package/esm/src/clients/public.d.ts +26 -5
  16. package/esm/src/clients/public.d.ts.map +1 -1
  17. package/esm/src/clients/public.js +29 -41
  18. package/esm/src/clients/wallet.d.ts +200 -26
  19. package/esm/src/clients/wallet.d.ts.map +1 -1
  20. package/esm/src/clients/wallet.js +306 -284
  21. package/esm/src/signing.d.ts +80 -5
  22. package/esm/src/signing.d.ts.map +1 -1
  23. package/esm/src/signing.js +96 -7
  24. package/esm/src/transports/base.d.ts +49 -0
  25. package/esm/src/transports/base.d.ts.map +1 -0
  26. package/esm/src/transports/base.js +8 -0
  27. package/esm/src/transports/http/http_transport.d.ts +8 -5
  28. package/esm/src/transports/http/http_transport.d.ts.map +1 -1
  29. package/esm/src/transports/http/http_transport.js +15 -62
  30. package/esm/src/transports/websocket/_hyperliquid_event_target.d.ts +36 -39
  31. package/esm/src/transports/websocket/_hyperliquid_event_target.d.ts.map +1 -1
  32. package/esm/src/transports/websocket/_reconnecting_websocket.d.ts +18 -25
  33. package/esm/src/transports/websocket/_reconnecting_websocket.d.ts.map +1 -1
  34. package/esm/src/transports/websocket/_reconnecting_websocket.js +80 -179
  35. package/{script/src/transports/websocket/_websocket_request_dispatcher.d.ts → esm/src/transports/websocket/_websocket_async_request.d.ts} +14 -18
  36. package/esm/src/transports/websocket/_websocket_async_request.d.ts.map +1 -0
  37. package/esm/src/transports/websocket/{_websocket_request_dispatcher.js → _websocket_async_request.js} +42 -75
  38. package/esm/src/transports/websocket/websocket_transport.d.ts +38 -28
  39. package/esm/src/transports/websocket/websocket_transport.d.ts.map +1 -1
  40. package/esm/src/transports/websocket/websocket_transport.js +61 -76
  41. package/esm/src/types/exchange/requests.d.ts +278 -66
  42. package/esm/src/types/exchange/requests.d.ts.map +1 -1
  43. package/esm/src/types/info/assets.d.ts +0 -48
  44. package/esm/src/types/info/assets.d.ts.map +1 -1
  45. package/esm/src/types/info/markets.d.ts +52 -0
  46. package/esm/src/types/info/markets.d.ts.map +1 -0
  47. package/esm/src/types/info/markets.js +1 -0
  48. package/esm/src/types/info/orders.d.ts +1 -1
  49. package/esm/src/types/info/orders.d.ts.map +1 -1
  50. package/esm/src/types/info/requests.d.ts +14 -5
  51. package/esm/src/types/info/requests.d.ts.map +1 -1
  52. package/esm/src/types/mod.d.ts +4 -0
  53. package/esm/src/types/mod.d.ts.map +1 -1
  54. package/esm/src/types/mod.js +3 -1
  55. package/esm/src/types/subscriptions/requests.d.ts +2 -0
  56. package/esm/src/types/subscriptions/requests.d.ts.map +1 -1
  57. package/package.json +12 -9
  58. package/script/_dnt.polyfills.d.ts +20 -0
  59. package/script/_dnt.polyfills.d.ts.map +1 -0
  60. package/script/_dnt.polyfills.js +23 -0
  61. package/script/mod.d.ts +3 -0
  62. package/script/mod.d.ts.map +1 -1
  63. package/script/mod.js +3 -1
  64. package/script/src/base.d.ts +1 -47
  65. package/script/src/base.d.ts.map +1 -1
  66. package/script/src/base.js +2 -10
  67. package/script/src/clients/event.d.ts +6 -4
  68. package/script/src/clients/event.d.ts.map +1 -1
  69. package/script/src/clients/event.js +58 -77
  70. package/script/src/clients/public.d.ts +26 -5
  71. package/script/src/clients/public.d.ts.map +1 -1
  72. package/script/src/clients/public.js +29 -41
  73. package/script/src/clients/wallet.d.ts +200 -26
  74. package/script/src/clients/wallet.d.ts.map +1 -1
  75. package/script/src/clients/wallet.js +305 -283
  76. package/script/src/signing.d.ts +80 -5
  77. package/script/src/signing.d.ts.map +1 -1
  78. package/script/src/signing.js +148 -58
  79. package/script/src/transports/base.d.ts +49 -0
  80. package/script/src/transports/base.d.ts.map +1 -0
  81. package/script/src/transports/base.js +22 -0
  82. package/script/src/transports/http/http_transport.d.ts +8 -5
  83. package/script/src/transports/http/http_transport.d.ts.map +1 -1
  84. package/script/src/transports/http/http_transport.js +16 -63
  85. package/script/src/transports/websocket/_hyperliquid_event_target.d.ts +36 -39
  86. package/script/src/transports/websocket/_hyperliquid_event_target.d.ts.map +1 -1
  87. package/script/src/transports/websocket/_reconnecting_websocket.d.ts +18 -25
  88. package/script/src/transports/websocket/_reconnecting_websocket.d.ts.map +1 -1
  89. package/script/src/transports/websocket/_reconnecting_websocket.js +81 -180
  90. package/{esm/src/transports/websocket/_websocket_request_dispatcher.d.ts → script/src/transports/websocket/_websocket_async_request.d.ts} +14 -18
  91. package/script/src/transports/websocket/_websocket_async_request.d.ts.map +1 -0
  92. package/script/src/transports/websocket/{_websocket_request_dispatcher.js → _websocket_async_request.js} +45 -78
  93. package/script/src/transports/websocket/websocket_transport.d.ts +38 -28
  94. package/script/src/transports/websocket/websocket_transport.d.ts.map +1 -1
  95. package/script/src/transports/websocket/websocket_transport.js +63 -78
  96. package/script/src/types/exchange/requests.d.ts +278 -66
  97. package/script/src/types/exchange/requests.d.ts.map +1 -1
  98. package/script/src/types/info/assets.d.ts +0 -48
  99. package/script/src/types/info/assets.d.ts.map +1 -1
  100. package/script/src/types/info/markets.d.ts +52 -0
  101. package/script/src/types/info/markets.d.ts.map +1 -0
  102. package/script/{deps/jsr.io/@noble/hashes/1.8.0/src/crypto.js → src/types/info/markets.js} +0 -2
  103. package/script/src/types/info/orders.d.ts +1 -1
  104. package/script/src/types/info/orders.d.ts.map +1 -1
  105. package/script/src/types/info/requests.d.ts +14 -5
  106. package/script/src/types/info/requests.d.ts.map +1 -1
  107. package/script/src/types/mod.d.ts +4 -0
  108. package/script/src/types/mod.d.ts.map +1 -1
  109. package/script/src/types/mod.js +25 -22
  110. package/script/src/types/subscriptions/requests.d.ts +2 -0
  111. package/script/src/types/subscriptions/requests.d.ts.map +1 -1
  112. package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/_u64.d.ts +0 -55
  113. package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/_u64.d.ts.map +0 -1
  114. package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/_u64.js +0 -66
  115. package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/crypto.d.ts +0 -2
  116. package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/crypto.d.ts.map +0 -1
  117. package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/crypto.js +0 -1
  118. package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/sha3.d.ts +0 -53
  119. package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/sha3.d.ts.map +0 -1
  120. package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/sha3.js +0 -294
  121. package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/utils.d.ts +0 -161
  122. package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/utils.d.ts.map +0 -1
  123. package/esm/deps/jsr.io/@noble/hashes/1.8.0/src/utils.js +0 -280
  124. package/esm/src/transports/websocket/_websocket_request_dispatcher.d.ts.map +0 -1
  125. package/script/deps/jsr.io/@noble/hashes/1.8.0/src/_u64.d.ts +0 -55
  126. package/script/deps/jsr.io/@noble/hashes/1.8.0/src/_u64.d.ts.map +0 -1
  127. package/script/deps/jsr.io/@noble/hashes/1.8.0/src/_u64.js +0 -99
  128. package/script/deps/jsr.io/@noble/hashes/1.8.0/src/crypto.d.ts +0 -2
  129. package/script/deps/jsr.io/@noble/hashes/1.8.0/src/crypto.d.ts.map +0 -1
  130. package/script/deps/jsr.io/@noble/hashes/1.8.0/src/sha3.d.ts +0 -53
  131. package/script/deps/jsr.io/@noble/hashes/1.8.0/src/sha3.d.ts.map +0 -1
  132. package/script/deps/jsr.io/@noble/hashes/1.8.0/src/sha3.js +0 -309
  133. package/script/deps/jsr.io/@noble/hashes/1.8.0/src/utils.d.ts +0 -161
  134. package/script/deps/jsr.io/@noble/hashes/1.8.0/src/utils.d.ts.map +0 -1
  135. package/script/deps/jsr.io/@noble/hashes/1.8.0/src/utils.js +0 -322
  136. package/script/src/transports/websocket/_websocket_request_dispatcher.d.ts.map +0 -1
@@ -14,6 +14,7 @@
14
14
  const signing_js_1 = require("../signing.js");
15
15
  /** Error thrown when the API returns an error response. */
16
16
  class ApiRequestError extends base_js_1.HyperliquidError {
17
+ response;
17
18
  constructor(response) {
18
19
  let message = "Cannot process API request";
19
20
  if (response.status === "err") {
@@ -41,27 +42,15 @@
41
42
  }
42
43
  }
43
44
  super(message);
44
- Object.defineProperty(this, "response", {
45
- enumerable: true,
46
- configurable: true,
47
- writable: true,
48
- value: response
49
- });
45
+ this.response = response;
50
46
  this.name = "ApiRequestError";
51
47
  }
52
48
  }
53
49
  exports.ApiRequestError = ApiRequestError;
54
50
  /** Nonce manager for generating unique nonces for signing transactions. */
55
51
  class NonceManager {
56
- constructor() {
57
- /** The last nonce used for signing transactions. */
58
- Object.defineProperty(this, "lastNonce", {
59
- enumerable: true,
60
- configurable: true,
61
- writable: true,
62
- value: 0
63
- });
64
- }
52
+ /** The last nonce used for signing transactions. */
53
+ lastNonce = 0;
65
54
  /**
66
55
  * Gets the next nonce for signing transactions.
67
56
  * @returns The next nonce.
@@ -83,6 +72,13 @@
83
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.
84
73
  */
85
74
  class WalletClient {
75
+ transport;
76
+ wallet;
77
+ isTestnet;
78
+ defaultVaultAddress;
79
+ defaultExpiresAfter;
80
+ signatureChainId;
81
+ nonceManager;
86
82
  /**
87
83
  * Initialises a new instance.
88
84
  * @param args - The parameters for the client.
@@ -130,58 +126,6 @@
130
126
  * ```
131
127
  */
132
128
  constructor(args) {
133
- /** The transport used to connect to the Hyperliquid API. */
134
- Object.defineProperty(this, "transport", {
135
- enumerable: true,
136
- configurable: true,
137
- writable: true,
138
- value: void 0
139
- });
140
- /** The `viem`, `ethers.js`, or `window.ethereum` wallet used for signing transactions. */
141
- Object.defineProperty(this, "wallet", {
142
- enumerable: true,
143
- configurable: true,
144
- writable: true,
145
- value: void 0
146
- });
147
- /** Specifies whether the client uses testnet. */
148
- Object.defineProperty(this, "isTestnet", {
149
- enumerable: true,
150
- configurable: true,
151
- writable: true,
152
- value: void 0
153
- });
154
- /** Sets a default vaultAddress to be used if no vaultAddress is explicitly passed to a method. */
155
- Object.defineProperty(this, "defaultVaultAddress", {
156
- enumerable: true,
157
- configurable: true,
158
- writable: true,
159
- value: void 0
160
- });
161
- /** Sets a default expiresAfter to be used if no expiresAfter is explicitly passed to a method. */
162
- Object.defineProperty(this, "defaultExpiresAfter", {
163
- enumerable: true,
164
- configurable: true,
165
- writable: true,
166
- value: void 0
167
- });
168
- /**
169
- * The network that will be used to sign transactions.
170
- * Must match the network of the {@link wallet}.
171
- */
172
- Object.defineProperty(this, "signatureChainId", {
173
- enumerable: true,
174
- configurable: true,
175
- writable: true,
176
- value: void 0
177
- });
178
- /** Function to get the next nonce for signing transactions. */
179
- Object.defineProperty(this, "nonceManager", {
180
- enumerable: true,
181
- configurable: true,
182
- writable: true,
183
- value: void 0
184
- });
185
129
  this.transport = args.transport;
186
130
  this.wallet = args.wallet;
187
131
  this.isTestnet = args.isTestnet ?? false;
@@ -237,11 +181,7 @@
237
181
  if (action.agentName === "")
238
182
  delete action.agentName;
239
183
  // Send a request
240
- const request = { action, signature, nonce: action.nonce };
241
- const response = await this.transport.request("exchange", request, signal);
242
- // Validate a response
243
- this._validateResponse(response);
244
- return response;
184
+ return await this._request({ action, signature, nonce: action.nonce }, signal);
245
185
  }
246
186
  /**
247
187
  * Approve a maximum fee rate for a builder.
@@ -287,11 +227,7 @@
287
227
  chainId: parseInt(action.signatureChainId, 16),
288
228
  });
289
229
  // Send a request
290
- const request = { action, signature, nonce: action.nonce };
291
- const response = await this.transport.request("exchange", request, signal);
292
- // Validate a response
293
- this._validateResponse(response);
294
- return response;
230
+ return await this._request({ action, signature, nonce: action.nonce }, signal);
295
231
  }
296
232
  /**
297
233
  * Modify multiple orders.
@@ -377,11 +313,7 @@
377
313
  expiresAfter,
378
314
  });
379
315
  // Send a request
380
- const request = { action, signature, nonce, vaultAddress, expiresAfter };
381
- const response = await this.transport.request("exchange", request, signal);
382
- // Validate a response
383
- this._validateResponse(response);
384
- return response;
316
+ return await this._request({ action, signature, nonce, vaultAddress, expiresAfter }, signal);
385
317
  }
386
318
  /**
387
319
  * Cancel order(s).
@@ -430,11 +362,7 @@
430
362
  expiresAfter,
431
363
  });
432
364
  // Send a request
433
- const request = { action, signature, nonce, vaultAddress, expiresAfter };
434
- const response = await this.transport.request("exchange", request, signal);
435
- // Validate a response
436
- this._validateResponse(response);
437
- return response;
365
+ return await this._request({ action, signature, nonce, vaultAddress, expiresAfter }, signal);
438
366
  }
439
367
  /**
440
368
  * Cancel order(s) by cloid.
@@ -482,11 +410,7 @@
482
410
  expiresAfter,
483
411
  });
484
412
  // Send a request
485
- const request = { action, signature, nonce, vaultAddress, expiresAfter };
486
- const response = await this.transport.request("exchange", request, signal);
487
- // Validate a response
488
- this._validateResponse(response);
489
- return response;
413
+ return await this._request({ action, signature, nonce, vaultAddress, expiresAfter }, signal);
490
414
  }
491
415
  /**
492
416
  * Transfer native token from the user's spot account into staking for delegating to validators.
@@ -531,11 +455,7 @@
531
455
  chainId: parseInt(action.signatureChainId, 16),
532
456
  });
533
457
  // Send a request
534
- const request = { action, signature, nonce: action.nonce };
535
- const response = await this.transport.request("exchange", request, signal);
536
- // Validate a response
537
- this._validateResponse(response);
538
- return response;
458
+ return await this._request({ action, signature, nonce: action.nonce }, signal);
539
459
  }
540
460
  /**
541
461
  * Claim rewards from referral program.
@@ -569,11 +489,55 @@
569
489
  isTestnet: this.isTestnet,
570
490
  });
571
491
  // Send a request
572
- const request = { action, signature, nonce };
573
- const response = await this.transport.request("exchange", request, signal);
574
- // Validate a response
575
- this._validateResponse(response);
576
- return response;
492
+ return await this._request({ action, signature, nonce }, signal);
493
+ }
494
+ /**
495
+ * Convert a single-signature account to a multi-signature account.
496
+ * @param args - The parameters for the request.
497
+ * @param signal - An optional abort signal.
498
+ * @returns Successful response without specific data.
499
+ * @throws {ApiRequestError} When the API returns an error response.
500
+ *
501
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/hypercore/multi-sig
502
+ * @example
503
+ * ```ts
504
+ * import * as hl from "@nktkas/hyperliquid";
505
+ * import { privateKeyToAccount } from "viem/accounts";
506
+ *
507
+ * const wallet = privateKeyToAccount("0x...");
508
+ * const transport = new hl.HttpTransport(); // or WebSocketTransport
509
+ * const client = new hl.WalletClient({ wallet, transport });
510
+ *
511
+ * const result = await client.convertToMultiSigUser({
512
+ * authorizedUsers: ["0x...", "0x..."],
513
+ * threshold: 2,
514
+ * });
515
+ * ```
516
+ */
517
+ async convertToMultiSigUser(args, signal) {
518
+ // Construct an action
519
+ const action = {
520
+ type: "convertToMultiSigUser",
521
+ hyperliquidChain: this._getHyperliquidChain(),
522
+ signatureChainId: await this._getSignatureChainId(),
523
+ signers: JSON.stringify(args),
524
+ nonce: await this.nonceManager(),
525
+ };
526
+ // Sign the action
527
+ const signature = await (0, signing_js_1.signUserSignedAction)({
528
+ wallet: this.wallet,
529
+ action,
530
+ types: {
531
+ "HyperliquidTransaction:ConvertToMultiSigUser": [
532
+ { name: "hyperliquidChain", type: "string" },
533
+ { name: "signers", type: "string" },
534
+ { name: "nonce", type: "uint64" },
535
+ ],
536
+ },
537
+ chainId: parseInt(action.signatureChainId, 16),
538
+ });
539
+ // Send a request
540
+ return await this._request({ action, signature, nonce: action.nonce }, signal);
577
541
  }
578
542
  /**
579
543
  * Create a sub-account.
@@ -610,11 +574,7 @@
610
574
  isTestnet: this.isTestnet,
611
575
  });
612
576
  // Send a request
613
- const request = { action, signature, nonce };
614
- const response = await this.transport.request("exchange", request, signal);
615
- // Validate a response
616
- this._validateResponse(response);
617
- return response;
577
+ return await this._request({ action, signature, nonce }, signal);
618
578
  }
619
579
  /**
620
580
  * Create a vault.
@@ -658,11 +618,81 @@
658
618
  isTestnet: this.isTestnet,
659
619
  });
660
620
  // Send a request
661
- const request = { action, signature, nonce };
662
- const response = await this.transport.request("exchange", request, signal);
663
- // Validate a response
664
- this._validateResponse(response);
665
- return response;
621
+ return await this._request({ action, signature, nonce }, signal);
622
+ }
623
+ async cSignerAction(args, signal) {
624
+ // Destructure the parameters
625
+ const { expiresAfter = await this._getDefaultExpiresAfter(), ...actionArgs } = args;
626
+ // Construct an action
627
+ const nonce = await this.nonceManager();
628
+ const action = {
629
+ type: "CSignerAction",
630
+ ...actionArgs,
631
+ };
632
+ // Sign the action
633
+ const signature = await (0, signing_js_1.signL1Action)({
634
+ wallet: this.wallet,
635
+ action,
636
+ nonce,
637
+ isTestnet: this.isTestnet,
638
+ expiresAfter,
639
+ });
640
+ // Send a request
641
+ return await this._request({ action, signature, nonce, expiresAfter }, signal);
642
+ }
643
+ async cValidatorAction(args, signal) {
644
+ // Destructure the parameters
645
+ const { expiresAfter = await this._getDefaultExpiresAfter(), ...actionArgs } = args;
646
+ // Construct an action
647
+ const nonce = await this.nonceManager();
648
+ let action;
649
+ if ("changeProfile" in actionArgs) {
650
+ action = {
651
+ type: "CValidatorAction",
652
+ changeProfile: {
653
+ node_ip: actionArgs.changeProfile.node_ip ?? null,
654
+ name: actionArgs.changeProfile.name ?? null,
655
+ description: actionArgs.changeProfile.description ?? null,
656
+ unjailed: actionArgs.changeProfile.unjailed,
657
+ disable_delegations: actionArgs.changeProfile.disable_delegations ?? null,
658
+ commission_bps: actionArgs.changeProfile.commission_bps ?? null,
659
+ signer: actionArgs.changeProfile.signer?.toLowerCase() ?? null,
660
+ },
661
+ };
662
+ }
663
+ else if ("register" in actionArgs) {
664
+ action = {
665
+ type: "CValidatorAction",
666
+ register: {
667
+ profile: {
668
+ node_ip: { Ip: actionArgs.register.profile.node_ip.Ip },
669
+ name: actionArgs.register.profile.name,
670
+ description: actionArgs.register.profile.description,
671
+ delegations_disabled: actionArgs.register.profile.delegations_disabled,
672
+ commission_bps: actionArgs.register.profile.commission_bps,
673
+ signer: actionArgs.register.profile.signer?.toLowerCase(),
674
+ },
675
+ unjailed: actionArgs.register.unjailed,
676
+ initial_wei: actionArgs.register.initial_wei,
677
+ },
678
+ };
679
+ }
680
+ else {
681
+ action = {
682
+ type: "CValidatorAction",
683
+ unregister: actionArgs.unregister,
684
+ };
685
+ }
686
+ // Sign the action
687
+ const signature = await (0, signing_js_1.signL1Action)({
688
+ wallet: this.wallet,
689
+ action,
690
+ nonce,
691
+ isTestnet: this.isTestnet,
692
+ expiresAfter,
693
+ });
694
+ // Send a request
695
+ return await this._request({ action, signature, nonce, expiresAfter }, signal);
666
696
  }
667
697
  /**
668
698
  * Transfer native token from staking into the user's spot account.
@@ -707,11 +737,7 @@
707
737
  chainId: parseInt(action.signatureChainId, 16),
708
738
  });
709
739
  // Send a request
710
- const request = { action, signature, nonce: action.nonce };
711
- const response = await this.transport.request("exchange", request, signal);
712
- // Validate a response
713
- this._validateResponse(response);
714
- return response;
740
+ return await this._request({ action, signature, nonce: action.nonce }, signal);
715
741
  }
716
742
  /**
717
743
  * Configure block type for EVM transactions.
@@ -748,11 +774,7 @@
748
774
  isTestnet: this.isTestnet,
749
775
  });
750
776
  // Send a request
751
- const request = { action, signature, nonce };
752
- const response = await this.transport.request("exchange", request, signal);
753
- // Validate a response
754
- this._validateResponse(response);
755
- return response;
777
+ return await this._request({ action, signature, nonce }, signal);
756
778
  }
757
779
  /**
758
780
  * Modify an order.
@@ -831,11 +853,82 @@
831
853
  expiresAfter,
832
854
  });
833
855
  // Send a request
834
- const request = { action, signature, nonce, vaultAddress, expiresAfter };
835
- const response = await this.transport.request("exchange", request, signal);
836
- // Validate a response
837
- this._validateResponse(response);
838
- return response;
856
+ return await this._request({ action, signature, nonce, vaultAddress, expiresAfter }, signal);
857
+ }
858
+ /**
859
+ * A multi-signature request.
860
+ * @param args - The parameters for the request.
861
+ * @param signal - An optional abort signal.
862
+ * @returns Successful response without specific data.
863
+ * @throws {ApiRequestError} When the API returns an error response.
864
+ *
865
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/hypercore/multi-sig
866
+ * @example
867
+ * ```ts
868
+ * import * as hl from "@nktkas/hyperliquid";
869
+ * import { privateKeyToAccount } from "viem/accounts";
870
+ *
871
+ * const wallet = privateKeyToAccount("0x...");
872
+ * const transport = new hl.HttpTransport(); // or WebSocketTransport
873
+ * const client = new hl.WalletClient({ wallet, transport });
874
+ *
875
+ * const multiSigUser = "0x..."; // Multi-sig user address
876
+ *
877
+ * const nonce = Date.now();
878
+ * const action = { type: "scheduleCancel", time: Date.now() + 10000 };
879
+ *
880
+ * const signature = await hl.signL1Action({
881
+ * wallet,
882
+ * action: [multiSigUser.toLowerCase(), signer1.address.toLowerCase(), action],
883
+ * nonce,
884
+ * isTestnet: true,
885
+ * });
886
+ *
887
+ * const result = await client.multiSig({
888
+ * signatures: [signature],
889
+ * payload: {
890
+ * multiSigUser,
891
+ * outerSigner: wallet.address,
892
+ * action,
893
+ * },
894
+ * nonce,
895
+ * });
896
+ * ```
897
+ * @unstable May not behave as expected and the interface may change in the future.
898
+ */
899
+ async multiSig(args, signal) {
900
+ // Destructure the parameters
901
+ const { vaultAddress = this.defaultVaultAddress, expiresAfter = await this._getDefaultExpiresAfter(), nonce, ...actionArgs } = args;
902
+ // Construct an action
903
+ const hyperliquidChain = this._getHyperliquidChain();
904
+ const action = {
905
+ type: "multiSig",
906
+ signatureChainId: await this._getSignatureChainId(),
907
+ signatures: actionArgs.signatures.map((signature) => ({
908
+ r: signature.r.replace(/^0x0+/, "0x").toLowerCase(),
909
+ s: signature.s.replace(/^0x0+/, "0x").toLowerCase(),
910
+ v: signature.v,
911
+ })),
912
+ payload: {
913
+ multiSigUser: actionArgs.payload.multiSigUser.toLowerCase(),
914
+ outerSigner: actionArgs.payload.outerSigner.toLowerCase(),
915
+ action: actionArgs.payload.action,
916
+ },
917
+ };
918
+ // Sign the action
919
+ const actionForMultiSig = structuredClone(action);
920
+ delete actionForMultiSig.type;
921
+ const signature = await (0, signing_js_1.signMultiSigAction)({
922
+ wallet: this.wallet,
923
+ action: actionForMultiSig,
924
+ nonce,
925
+ vaultAddress,
926
+ expiresAfter,
927
+ hyperliquidChain,
928
+ signatureChainId: action.signatureChainId,
929
+ });
930
+ // Send a request
931
+ return await this._request({ action, signature, nonce, vaultAddress, expiresAfter }, signal);
839
932
  }
840
933
  /**
841
934
  * Place an order(s).
@@ -925,22 +1018,8 @@
925
1018
  expiresAfter,
926
1019
  });
927
1020
  // Send a request
928
- const request = { action, signature, nonce, vaultAddress, expiresAfter };
929
- const response = await this.transport.request("exchange", request, signal);
930
- // Validate a response
931
- this._validateResponse(response);
932
- return response;
1021
+ return await this._request({ action, signature, nonce, vaultAddress, expiresAfter }, signal);
933
1022
  }
934
- /**
935
- * Deploying HIP-3 assets.
936
- * @param args - The parameters for the request.
937
- * @param signal - An optional abort signal.
938
- * @returns Successful response without specific data.
939
- * @throws {ApiRequestError} When the API returns an error response.
940
- *
941
- * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/deploying-hip-3-assets
942
- * @untested
943
- */
944
1023
  async perpDeploy(args, signal) {
945
1024
  // Construct an action
946
1025
  const nonce = await this.nonceManager();
@@ -987,11 +1066,60 @@
987
1066
  isTestnet: this.isTestnet,
988
1067
  });
989
1068
  // Send a request
990
- const request = { action, signature, nonce };
991
- const response = await this.transport.request("exchange", request, signal);
992
- // Validate a response
993
- this._validateResponse(response);
994
- return response;
1069
+ return await this._request({ action, signature, nonce }, signal);
1070
+ }
1071
+ /**
1072
+ * Transfer funds between Spot account and Perp dex account.
1073
+ * @param args - The parameters for the request.
1074
+ * @param signal - An optional abort signal.
1075
+ * @returns Successful response without specific data.
1076
+ * @throws {ApiRequestError} When the API returns an error response.
1077
+ *
1078
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#transfer-from-spot-account-to-perp-account-and-vice-versa
1079
+ * @example
1080
+ * ```ts
1081
+ * import * as hl from "@nktkas/hyperliquid";
1082
+ * import { privateKeyToAccount } from "viem/accounts";
1083
+ *
1084
+ * const wallet = privateKeyToAccount("0x...");
1085
+ * const transport = new hl.HttpTransport(); // or WebSocketTransport
1086
+ * const client = new hl.WalletClient({ wallet, transport });
1087
+ *
1088
+ * const result = await client.perpDexClassTransfer({
1089
+ * dex: "test",
1090
+ * token: "USDC",
1091
+ * amount: "1",
1092
+ * toPerp: true,
1093
+ * });
1094
+ * ```
1095
+ */
1096
+ async perpDexClassTransfer(args, signal) {
1097
+ // Construct an action
1098
+ const action = {
1099
+ ...args,
1100
+ type: "PerpDexClassTransfer",
1101
+ hyperliquidChain: this._getHyperliquidChain(),
1102
+ signatureChainId: await this._getSignatureChainId(),
1103
+ nonce: await this.nonceManager(),
1104
+ };
1105
+ // Sign the action
1106
+ const signature = await (0, signing_js_1.signUserSignedAction)({
1107
+ wallet: this.wallet,
1108
+ action,
1109
+ types: {
1110
+ "HyperliquidTransaction:PerpDexClassTransfer": [
1111
+ { name: "hyperliquidChain", type: "string" },
1112
+ { name: "dex", type: "string" },
1113
+ { name: "token", type: "string" },
1114
+ { name: "amount", type: "string" },
1115
+ { name: "toPerp", type: "bool" },
1116
+ { name: "nonce", type: "uint64" },
1117
+ ],
1118
+ },
1119
+ chainId: parseInt(action.signatureChainId, 16),
1120
+ });
1121
+ // Send a request
1122
+ return await this._request({ action, signature, nonce: action.nonce }, signal);
995
1123
  }
996
1124
  /**
997
1125
  * Create a referral code.
@@ -1028,11 +1156,7 @@
1028
1156
  isTestnet: this.isTestnet,
1029
1157
  });
1030
1158
  // Send a request
1031
- const request = { action, signature, nonce };
1032
- const response = await this.transport.request("exchange", request, signal);
1033
- // Validate a response
1034
- this._validateResponse(response);
1035
- return response;
1159
+ return await this._request({ action, signature, nonce }, signal);
1036
1160
  }
1037
1161
  /**
1038
1162
  * Reserve additional rate-limited actions for a fee.
@@ -1072,33 +1196,11 @@
1072
1196
  expiresAfter,
1073
1197
  });
1074
1198
  // Send a request
1075
- const request = { action, signature, nonce, expiresAfter };
1076
- const response = await this.transport.request("exchange", request, signal);
1077
- // Validate a response
1078
- this._validateResponse(response);
1079
- return response;
1199
+ return await this._request({ action, signature, nonce, expiresAfter }, signal);
1080
1200
  }
1081
- /**
1082
- * Schedule a cancel-all operation at a future time.
1083
- * @param args - The parameters for the request.
1084
- * @param signal - An optional abort signal.
1085
- * @returns Successful response without specific data.
1086
- * @throws {ApiRequestError} When the API returns an error response.
1087
- *
1088
- * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#schedule-cancel-dead-mans-switch
1089
- * @example
1090
- * ```ts
1091
- * import * as hl from "@nktkas/hyperliquid";
1092
- * import { privateKeyToAccount } from "viem/accounts";
1093
- *
1094
- * const wallet = privateKeyToAccount("0x...");
1095
- * const transport = new hl.HttpTransport(); // or WebSocketTransport
1096
- * const client = new hl.WalletClient({ wallet, transport });
1097
- *
1098
- * const result = await client.scheduleCancel({ time: Date.now() + 3600000 });
1099
- * ```
1100
- */
1101
- async scheduleCancel(args = {}, signal) {
1201
+ async scheduleCancel(args_or_signal, maybeSignal) {
1202
+ const args = args_or_signal instanceof AbortSignal ? {} : args_or_signal ?? {};
1203
+ const signal = args_or_signal instanceof AbortSignal ? args_or_signal : maybeSignal;
1102
1204
  // Destructure the parameters
1103
1205
  const { vaultAddress = this.defaultVaultAddress, expiresAfter = await this._getDefaultExpiresAfter(), ...actionArgs } = args;
1104
1206
  // Construct an action
@@ -1119,11 +1221,7 @@
1119
1221
  expiresAfter,
1120
1222
  });
1121
1223
  // Send a request
1122
- const request = { action, signature, nonce, vaultAddress, expiresAfter };
1123
- const response = await this.transport.request("exchange", request, signal);
1124
- // Validate a response
1125
- this._validateResponse(response);
1126
- return response;
1224
+ return await this._request({ action, signature, nonce, vaultAddress, expiresAfter }, signal);
1127
1225
  }
1128
1226
  /**
1129
1227
  * Set the display name in the leaderboard.
@@ -1160,11 +1258,7 @@
1160
1258
  isTestnet: this.isTestnet,
1161
1259
  });
1162
1260
  // Send a request
1163
- const request = { action, signature, nonce };
1164
- const response = await this.transport.request("exchange", request, signal);
1165
- // Validate a response
1166
- this._validateResponse(response);
1167
- return response;
1261
+ return await this._request({ action, signature, nonce }, signal);
1168
1262
  }
1169
1263
  /**
1170
1264
  * Set a referral code.
@@ -1201,22 +1295,8 @@
1201
1295
  isTestnet: this.isTestnet,
1202
1296
  });
1203
1297
  // Send a request
1204
- const request = { action, signature, nonce };
1205
- const response = await this.transport.request("exchange", request, signal);
1206
- // Validate a response
1207
- this._validateResponse(response);
1208
- return response;
1298
+ return await this._request({ action, signature, nonce }, signal);
1209
1299
  }
1210
- /**
1211
- * Deploying HIP-1 and HIP-2 assets.
1212
- * @param args - The parameters for the request.
1213
- * @param signal - An optional abort signal.
1214
- * @returns Successful response without specific data.
1215
- * @throws {ApiRequestError} When the API returns an error response.
1216
- *
1217
- * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/deploying-hip-1-and-hip-2-assets
1218
- * @untested
1219
- */
1220
1300
  async spotDeploy(args, signal) {
1221
1301
  // Construct an action
1222
1302
  const nonce = await this.nonceManager();
@@ -1305,11 +1385,7 @@
1305
1385
  isTestnet: this.isTestnet,
1306
1386
  });
1307
1387
  // Send a request
1308
- const request = { action, signature, nonce };
1309
- const response = await this.transport.request("exchange", request, signal);
1310
- // Validate a response
1311
- this._validateResponse(response);
1312
- return response;
1388
+ return await this._request({ action, signature, nonce }, signal);
1313
1389
  }
1314
1390
  /**
1315
1391
  * Send spot assets to another address.
@@ -1360,11 +1436,7 @@
1360
1436
  chainId: parseInt(action.signatureChainId, 16),
1361
1437
  });
1362
1438
  // Send a request
1363
- const request = { action, signature, nonce: action.time };
1364
- const response = await this.transport.request("exchange", request, signal);
1365
- // Validate a response
1366
- this._validateResponse(response);
1367
- return response;
1439
+ return await this._request({ action, signature, nonce: action.time }, signal);
1368
1440
  }
1369
1441
  /**
1370
1442
  * Opt Out of Spot Dusting.
@@ -1403,11 +1475,7 @@
1403
1475
  isTestnet: this.isTestnet,
1404
1476
  });
1405
1477
  // Send a request
1406
- const request = { action, signature, nonce };
1407
- const response = await this.transport.request("exchange", request, signal);
1408
- // Validate a response
1409
- this._validateResponse(response);
1410
- return response;
1478
+ return await this._request({ action, signature, nonce }, signal);
1411
1479
  }
1412
1480
  /**
1413
1481
  * Transfer between sub-accounts (spot).
@@ -1452,11 +1520,7 @@
1452
1520
  isTestnet: this.isTestnet,
1453
1521
  });
1454
1522
  // Send a request
1455
- const request = { action, signature, nonce };
1456
- const response = await this.transport.request("exchange", request, signal);
1457
- // Validate a response
1458
- this._validateResponse(response);
1459
- return response;
1523
+ return await this._request({ action, signature, nonce }, signal);
1460
1524
  }
1461
1525
  /**
1462
1526
  * Transfer between sub-accounts (perpetual).
@@ -1499,11 +1563,7 @@
1499
1563
  isTestnet: this.isTestnet,
1500
1564
  });
1501
1565
  // Send a request
1502
- const request = { action, signature, nonce };
1503
- const response = await this.transport.request("exchange", request, signal);
1504
- // Validate a response
1505
- this._validateResponse(response);
1506
- return response;
1566
+ return await this._request({ action, signature, nonce }, signal);
1507
1567
  }
1508
1568
  /**
1509
1569
  * Delegate or undelegate native tokens to or from a validator.
@@ -1554,11 +1614,7 @@
1554
1614
  chainId: parseInt(action.signatureChainId, 16),
1555
1615
  });
1556
1616
  // Send a request
1557
- const request = { action, signature, nonce: action.nonce };
1558
- const response = await this.transport.request("exchange", request, signal);
1559
- // Validate a response
1560
- this._validateResponse(response);
1561
- return response;
1617
+ return await this._request({ action, signature, nonce: action.nonce }, signal);
1562
1618
  }
1563
1619
  /**
1564
1620
  * Cancel a TWAP order.
@@ -1603,11 +1659,7 @@
1603
1659
  expiresAfter,
1604
1660
  });
1605
1661
  // Send a request
1606
- const request = { action, signature, nonce, vaultAddress, expiresAfter };
1607
- const response = await this.transport.request("exchange", request, signal);
1608
- // Validate a response
1609
- this._validateResponse(response);
1610
- return response;
1662
+ return await this._request({ action, signature, nonce, vaultAddress, expiresAfter }, signal);
1611
1663
  }
1612
1664
  /**
1613
1665
  * Place a TWAP order.
@@ -1662,11 +1714,7 @@
1662
1714
  expiresAfter,
1663
1715
  });
1664
1716
  // Send a request
1665
- const request = { action, signature, nonce, vaultAddress, expiresAfter };
1666
- const response = await this.transport.request("exchange", request, signal);
1667
- // Validate a response
1668
- this._validateResponse(response);
1669
- return response;
1717
+ return await this._request({ action, signature, nonce, vaultAddress, expiresAfter }, signal);
1670
1718
  }
1671
1719
  /**
1672
1720
  * Add or remove margin from isolated position.
@@ -1709,11 +1757,7 @@
1709
1757
  expiresAfter,
1710
1758
  });
1711
1759
  // Send a request
1712
- const request = { action, signature, nonce, vaultAddress, expiresAfter };
1713
- const response = await this.transport.request("exchange", request, signal);
1714
- // Validate a response
1715
- this._validateResponse(response);
1716
- return response;
1760
+ return await this._request({ action, signature, nonce, vaultAddress, expiresAfter }, signal);
1717
1761
  }
1718
1762
  /**
1719
1763
  * Update cross or isolated leverage on a coin.
@@ -1756,14 +1800,10 @@
1756
1800
  expiresAfter,
1757
1801
  });
1758
1802
  // Send a request
1759
- const request = { action, signature, nonce, vaultAddress, expiresAfter };
1760
- const response = await this.transport.request("exchange", request, signal);
1761
- // Validate a response
1762
- this._validateResponse(response);
1763
- return response;
1803
+ return await this._request({ action, signature, nonce, vaultAddress, expiresAfter }, signal);
1764
1804
  }
1765
1805
  /**
1766
- * Transfer funds between Spot and Perp accounts.
1806
+ * Transfer funds between Spot account and Perp account.
1767
1807
  * @param args - The parameters for the request.
1768
1808
  * @param signal - An optional abort signal.
1769
1809
  * @returns Successful response without specific data.
@@ -1806,11 +1846,7 @@
1806
1846
  chainId: parseInt(action.signatureChainId, 16),
1807
1847
  });
1808
1848
  // Send a request
1809
- const request = { action, signature, nonce: action.nonce };
1810
- const response = await this.transport.request("exchange", request, signal);
1811
- // Validate a response
1812
- this._validateResponse(response);
1813
- return response;
1849
+ return await this._request({ action, signature, nonce: action.nonce }, signal);
1814
1850
  }
1815
1851
  /**
1816
1852
  * Send usd to another address.
@@ -1856,11 +1892,7 @@
1856
1892
  chainId: parseInt(action.signatureChainId, 16),
1857
1893
  });
1858
1894
  // Send a request
1859
- const request = { action, signature, nonce: action.time };
1860
- const response = await this.transport.request("exchange", request, signal);
1861
- // Validate a response
1862
- this._validateResponse(response);
1863
- return response;
1895
+ return await this._request({ action, signature, nonce: action.time }, signal);
1864
1896
  }
1865
1897
  /**
1866
1898
  * Distribute funds from a vault between followers.
@@ -1898,11 +1930,7 @@
1898
1930
  isTestnet: this.isTestnet,
1899
1931
  });
1900
1932
  // Send a request
1901
- const request = { action, signature, nonce };
1902
- const response = await this.transport.request("exchange", request, signal);
1903
- // Validate a response
1904
- this._validateResponse(response);
1905
- return response;
1933
+ return await this._request({ action, signature, nonce }, signal);
1906
1934
  }
1907
1935
  /**
1908
1936
  * Modify a vault's configuration.
@@ -1945,11 +1973,7 @@
1945
1973
  isTestnet: this.isTestnet,
1946
1974
  });
1947
1975
  // Send a request
1948
- const request = { action, signature, nonce };
1949
- const response = await this.transport.request("exchange", request, signal);
1950
- // Validate a response
1951
- this._validateResponse(response);
1952
- return response;
1976
+ return await this._request({ action, signature, nonce }, signal);
1953
1977
  }
1954
1978
  /**
1955
1979
  * Deposit or withdraw from a vault.
@@ -1995,11 +2019,7 @@
1995
2019
  expiresAfter,
1996
2020
  });
1997
2021
  // Send a request
1998
- const request = { action, signature, nonce, expiresAfter };
1999
- const response = await this.transport.request("exchange", request, signal);
2000
- // Validate a response
2001
- this._validateResponse(response);
2002
- return response;
2022
+ return await this._request({ action, signature, nonce, expiresAfter }, signal);
2003
2023
  }
2004
2024
  /**
2005
2025
  * Initiate a withdrawal request.
@@ -2045,9 +2065,11 @@
2045
2065
  chainId: parseInt(action.signatureChainId, 16),
2046
2066
  });
2047
2067
  // Send a request
2048
- const request = { action, signature, nonce: action.time };
2049
- const response = await this.transport.request("exchange", request, signal);
2050
- // Validate a response
2068
+ return await this._request({ action, signature, nonce: action.time }, signal);
2069
+ }
2070
+ /** Send an API request and validate the response. */
2071
+ async _request(payload, signal) {
2072
+ const response = await this.transport.request("exchange", payload, signal);
2051
2073
  this._validateResponse(response);
2052
2074
  return response;
2053
2075
  }
@@ -2062,7 +2084,7 @@
2062
2084
  /** Guesses the chain ID based on the wallet type or the isTestnet flag. */
2063
2085
  async _guessSignatureChainId() {
2064
2086
  // Trying to get chain ID of the wallet
2065
- if ((0, signing_js_1.isAbstractViemWalletClient)(this.wallet)) {
2087
+ if ((0, signing_js_1.isAbstractViemWalletClient)(this.wallet) || (0, signing_js_1.isAbstractExtendedViemWalletClient)(this.wallet)) {
2066
2088
  if ("getChainId" in this.wallet && typeof this.wallet.getChainId === "function") {
2067
2089
  const chainId = await this.wallet.getChainId();
2068
2090
  return `0x${chainId.toString(16)}`;