@nktkas/hyperliquid 0.15.2 → 0.15.4

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 (42) hide show
  1. package/README.md +6 -2
  2. package/esm/src/clients/event.d.ts +2 -0
  3. package/esm/src/clients/event.d.ts.map +1 -1
  4. package/esm/src/clients/event.js +2 -0
  5. package/esm/src/clients/wallet.d.ts +81 -3
  6. package/esm/src/clients/wallet.d.ts.map +1 -1
  7. package/esm/src/clients/wallet.js +221 -41
  8. package/esm/src/transports/http/http_transport.d.ts +24 -5
  9. package/esm/src/transports/http/http_transport.d.ts.map +1 -1
  10. package/esm/src/transports/http/http_transport.js +12 -6
  11. package/esm/src/transports/websocket/_hyperliquid_event_target.js +13 -15
  12. package/esm/src/transports/websocket/_websocket_request_dispatcher.d.ts +0 -12
  13. package/esm/src/transports/websocket/_websocket_request_dispatcher.d.ts.map +1 -1
  14. package/esm/src/transports/websocket/_websocket_request_dispatcher.js +7 -23
  15. package/esm/src/transports/websocket/websocket_transport.d.ts +1 -1
  16. package/esm/src/transports/websocket/websocket_transport.d.ts.map +1 -1
  17. package/esm/src/transports/websocket/websocket_transport.js +1 -5
  18. package/esm/src/types/exchange/requests.d.ts +140 -0
  19. package/esm/src/types/exchange/requests.d.ts.map +1 -1
  20. package/esm/src/types/exchange/responses.d.ts +12 -0
  21. package/esm/src/types/exchange/responses.d.ts.map +1 -1
  22. package/package.json +1 -1
  23. package/script/src/clients/event.d.ts +2 -0
  24. package/script/src/clients/event.d.ts.map +1 -1
  25. package/script/src/clients/event.js +2 -0
  26. package/script/src/clients/wallet.d.ts +81 -3
  27. package/script/src/clients/wallet.d.ts.map +1 -1
  28. package/script/src/clients/wallet.js +221 -41
  29. package/script/src/transports/http/http_transport.d.ts +24 -5
  30. package/script/src/transports/http/http_transport.d.ts.map +1 -1
  31. package/script/src/transports/http/http_transport.js +12 -6
  32. package/script/src/transports/websocket/_hyperliquid_event_target.js +13 -15
  33. package/script/src/transports/websocket/_websocket_request_dispatcher.d.ts +0 -12
  34. package/script/src/transports/websocket/_websocket_request_dispatcher.d.ts.map +1 -1
  35. package/script/src/transports/websocket/_websocket_request_dispatcher.js +7 -23
  36. package/script/src/transports/websocket/websocket_transport.d.ts +1 -1
  37. package/script/src/transports/websocket/websocket_transport.d.ts.map +1 -1
  38. package/script/src/transports/websocket/websocket_transport.js +1 -5
  39. package/script/src/types/exchange/requests.d.ts +140 -0
  40. package/script/src/types/exchange/requests.d.ts.map +1 -1
  41. package/script/src/types/exchange/responses.d.ts +12 -0
  42. package/script/src/types/exchange/responses.d.ts.map +1 -1
@@ -46,6 +46,17 @@ export class ApiRequestError extends HyperliquidError {
46
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
47
  */
48
48
  export class WalletClient {
49
+ /** Gets the next nonce for signing transactions. */
50
+ get _nonce() {
51
+ let nonce = Date.now();
52
+ if (nonce <= this._lastNonce) {
53
+ nonce = ++this._lastNonce;
54
+ }
55
+ else {
56
+ this._lastNonce = nonce;
57
+ }
58
+ return nonce;
59
+ }
49
60
  /**
50
61
  * Initialises a new instance.
51
62
  * @param args - The parameters for the client.
@@ -131,13 +142,20 @@ export class WalletClient {
131
142
  writable: true,
132
143
  value: void 0
133
144
  });
145
+ /** The last nonce used for signing transactions. */
146
+ Object.defineProperty(this, "_lastNonce", {
147
+ enumerable: true,
148
+ configurable: true,
149
+ writable: true,
150
+ value: 0
151
+ });
134
152
  this.transport = args.transport;
135
153
  this.wallet = args.wallet;
136
154
  this.isTestnet = args.isTestnet ?? false;
137
155
  this.defaultVaultAddress = args.defaultVaultAddress;
138
156
  this.signatureChainId = args.signatureChainId ?? (this.isTestnet ? "0x66eee" : "0xa4b1");
139
157
  }
140
- // ———————————————Actions———————————————
158
+ // ——————————————— Exchange API ———————————————
141
159
  /**
142
160
  * Approve an agent to sign on behalf of the master or sub-accounts.
143
161
  * @param args - The parameters for the request.
@@ -168,7 +186,7 @@ export class WalletClient {
168
186
  type: "approveAgent",
169
187
  hyperliquidChain: this.isTestnet ? "Testnet" : "Mainnet",
170
188
  signatureChainId: this.signatureChainId,
171
- nonce: args.nonce ?? Date.now(),
189
+ nonce: args.nonce ?? this._nonce,
172
190
  };
173
191
  // Sign the action
174
192
  const signature = await signUserSignedAction({
@@ -221,7 +239,7 @@ export class WalletClient {
221
239
  type: "approveBuilderFee",
222
240
  hyperliquidChain: this.isTestnet ? "Testnet" : "Mainnet",
223
241
  signatureChainId: this.signatureChainId,
224
- nonce: args.nonce ?? Date.now(),
242
+ nonce: args.nonce ?? this._nonce,
225
243
  };
226
244
  // Sign the action
227
245
  const signature = await signUserSignedAction({
@@ -283,7 +301,7 @@ export class WalletClient {
283
301
  */
284
302
  async batchModify(args, signal) {
285
303
  // Destructure the parameters
286
- const { vaultAddress = this.defaultVaultAddress, nonce = Date.now(), ...actionArgs } = args;
304
+ const { vaultAddress = this.defaultVaultAddress, nonce = this._nonce, ...actionArgs } = args;
287
305
  // Construct an action
288
306
  const action = {
289
307
  type: "batchModify",
@@ -293,8 +311,8 @@ export class WalletClient {
293
311
  order: {
294
312
  a: modify.order.a,
295
313
  b: modify.order.b,
296
- p: modify.order.p,
297
- s: modify.order.s,
314
+ p: this._formatDecimal(modify.order.p),
315
+ s: this._formatDecimal(modify.order.s),
298
316
  r: modify.order.r,
299
317
  t: "limit" in modify.order.t
300
318
  ? {
@@ -305,7 +323,7 @@ export class WalletClient {
305
323
  : {
306
324
  trigger: {
307
325
  isMarket: modify.order.t.trigger.isMarket,
308
- triggerPx: modify.order.t.trigger.triggerPx,
326
+ triggerPx: this._formatDecimal(modify.order.t.trigger.triggerPx),
309
327
  tpsl: modify.order.t.trigger.tpsl,
310
328
  },
311
329
  },
@@ -359,7 +377,7 @@ export class WalletClient {
359
377
  */
360
378
  async cancel(args, signal) {
361
379
  // Destructure the parameters
362
- const { vaultAddress = this.defaultVaultAddress, nonce = Date.now(), ...actionArgs } = args;
380
+ const { vaultAddress = this.defaultVaultAddress, nonce = this._nonce, ...actionArgs } = args;
363
381
  // Construct an action
364
382
  const action = {
365
383
  type: "cancel",
@@ -410,7 +428,7 @@ export class WalletClient {
410
428
  type: "cDeposit",
411
429
  hyperliquidChain: this.isTestnet ? "Testnet" : "Mainnet",
412
430
  signatureChainId: this.signatureChainId,
413
- nonce: args.nonce ?? Date.now(),
431
+ nonce: args.nonce ?? this._nonce,
414
432
  };
415
433
  // Sign the action
416
434
  const signature = await signUserSignedAction({
@@ -454,7 +472,7 @@ export class WalletClient {
454
472
  */
455
473
  async claimRewards(args = {}, signal) {
456
474
  // Destructure the parameters
457
- const { nonce = Date.now() } = args;
475
+ const { nonce = this._nonce, } = args;
458
476
  // Construct an action
459
477
  const sortedAction = { type: "claimRewards" };
460
478
  // Sign the action
@@ -498,7 +516,7 @@ export class WalletClient {
498
516
  */
499
517
  async cancelByCloid(args, signal) {
500
518
  // Destructure the parameters
501
- const { vaultAddress = this.defaultVaultAddress, nonce = Date.now(), ...actionArgs } = args;
519
+ const { vaultAddress = this.defaultVaultAddress, nonce = this._nonce, ...actionArgs } = args;
502
520
  // Construct an action
503
521
  const action = {
504
522
  type: "cancelByCloid",
@@ -549,7 +567,7 @@ export class WalletClient {
549
567
  type: "cWithdraw",
550
568
  hyperliquidChain: this.isTestnet ? "Testnet" : "Mainnet",
551
569
  signatureChainId: this.signatureChainId,
552
- nonce: args.nonce ?? Date.now(),
570
+ nonce: args.nonce ?? this._nonce,
553
571
  };
554
572
  // Sign the action
555
573
  const signature = await signUserSignedAction({
@@ -593,7 +611,7 @@ export class WalletClient {
593
611
  */
594
612
  async evmUserModify(args, signal) {
595
613
  // Destructure the parameters
596
- const { nonce = Date.now(), ...actionArgs } = args;
614
+ const { nonce = this._nonce, ...actionArgs } = args;
597
615
  // Construct an action
598
616
  const action = {
599
617
  type: "evmUserModify",
@@ -635,7 +653,7 @@ export class WalletClient {
635
653
  */
636
654
  async createSubAccount(args, signal) {
637
655
  // Destructure the parameters
638
- const { nonce = Date.now(), ...actionArgs } = args;
656
+ const { nonce = this._nonce, ...actionArgs } = args;
639
657
  // Construct an action
640
658
  const action = {
641
659
  type: "createSubAccount",
@@ -655,6 +673,55 @@ export class WalletClient {
655
673
  this._validateResponse(response);
656
674
  return response;
657
675
  }
676
+ /**
677
+ * Create a vault.
678
+ * @param args - The parameters for the request.
679
+ * @param signal - An optional abort signal.
680
+ * @returns Response for creating a vault.
681
+ * @throws {ApiRequestError} When the API returns an error response.
682
+ *
683
+ * @see null - no documentation
684
+ * @example
685
+ * ```ts
686
+ * import * as hl from "@nktkas/hyperliquid";
687
+ * import { privateKeyToAccount } from "viem/accounts";
688
+ *
689
+ * const wallet = privateKeyToAccount("0x...");
690
+ * const transport = new hl.HttpTransport(); // or WebSocketTransport
691
+ * const client = new hl.WalletClient({ wallet, transport });
692
+ *
693
+ * const result = await client.createVault({
694
+ * name: "VaultName",
695
+ * description: "This is an example of a vault description",
696
+ * initialUsd: 100 * 1e6,
697
+ * });
698
+ * ```
699
+ */
700
+ async createVault(args, signal) {
701
+ // Destructure the parameters
702
+ const { nonce = this._nonce, ...actionArgs } = args;
703
+ // Construct an action
704
+ const action = {
705
+ type: "createVault",
706
+ name: actionArgs.name,
707
+ description: actionArgs.description,
708
+ initialUsd: actionArgs.initialUsd,
709
+ nonce,
710
+ };
711
+ // Sign the action
712
+ const signature = await signL1Action({
713
+ wallet: this.wallet,
714
+ action,
715
+ nonce,
716
+ isTestnet: this.isTestnet,
717
+ });
718
+ // Send a request
719
+ const request = { action, signature, nonce };
720
+ const response = await this.transport.request("exchange", request, signal);
721
+ // Validate a response
722
+ this._validateResponse(response);
723
+ return response;
724
+ }
658
725
  /**
659
726
  * Modify an order.
660
727
  * @param args - The parameters for the request.
@@ -692,7 +759,7 @@ export class WalletClient {
692
759
  */
693
760
  async modify(args, signal) {
694
761
  // Destructure the parameters
695
- const { vaultAddress = this.defaultVaultAddress, nonce = Date.now(), ...actionArgs } = args;
762
+ const { vaultAddress = this.defaultVaultAddress, nonce = this._nonce, ...actionArgs } = args;
696
763
  // Construct an action
697
764
  const action = {
698
765
  type: "modify",
@@ -700,8 +767,8 @@ export class WalletClient {
700
767
  order: {
701
768
  a: actionArgs.order.a,
702
769
  b: actionArgs.order.b,
703
- p: actionArgs.order.p,
704
- s: actionArgs.order.s,
770
+ p: this._formatDecimal(actionArgs.order.p),
771
+ s: this._formatDecimal(actionArgs.order.s),
705
772
  r: actionArgs.order.r,
706
773
  t: "limit" in actionArgs.order.t
707
774
  ? {
@@ -712,7 +779,7 @@ export class WalletClient {
712
779
  : {
713
780
  trigger: {
714
781
  isMarket: actionArgs.order.t.trigger.isMarket,
715
- triggerPx: actionArgs.order.t.trigger.triggerPx,
782
+ triggerPx: this._formatDecimal(actionArgs.order.t.trigger.triggerPx),
716
783
  tpsl: actionArgs.order.t.trigger.tpsl,
717
784
  },
718
785
  },
@@ -773,7 +840,7 @@ export class WalletClient {
773
840
  */
774
841
  async order(args, signal) {
775
842
  // Destructure the parameters
776
- const { vaultAddress = this.defaultVaultAddress, nonce = Date.now(), ...actionArgs } = args;
843
+ const { vaultAddress = this.defaultVaultAddress, nonce = this._nonce, ...actionArgs } = args;
777
844
  // Construct an action
778
845
  const action = {
779
846
  type: "order",
@@ -781,8 +848,8 @@ export class WalletClient {
781
848
  const sortedOrder = {
782
849
  a: order.a,
783
850
  b: order.b,
784
- p: order.p,
785
- s: order.s,
851
+ p: this._formatDecimal(order.p),
852
+ s: this._formatDecimal(order.s),
786
853
  r: order.r,
787
854
  t: "limit" in order.t
788
855
  ? {
@@ -793,7 +860,7 @@ export class WalletClient {
793
860
  : {
794
861
  trigger: {
795
862
  isMarket: order.t.trigger.isMarket,
796
- triggerPx: order.t.trigger.triggerPx,
863
+ triggerPx: this._formatDecimal(order.t.trigger.triggerPx),
797
864
  tpsl: order.t.trigger.tpsl,
798
865
  },
799
866
  },
@@ -850,7 +917,7 @@ export class WalletClient {
850
917
  */
851
918
  async scheduleCancel(args = {}, signal) {
852
919
  // Destructure the parameters
853
- const { vaultAddress = this.defaultVaultAddress, nonce = Date.now(), ...actionArgs } = args;
920
+ const { vaultAddress = this.defaultVaultAddress, nonce = this._nonce, ...actionArgs } = args;
854
921
  // Construct an action
855
922
  const action = {
856
923
  type: "scheduleCancel",
@@ -895,7 +962,7 @@ export class WalletClient {
895
962
  */
896
963
  async setDisplayName(args, signal) {
897
964
  // Destructure the parameters
898
- const { nonce = Date.now(), ...actionArgs } = args;
965
+ const { nonce = this._nonce, ...actionArgs } = args;
899
966
  // Construct an action
900
967
  const action = {
901
968
  type: "setDisplayName",
@@ -937,7 +1004,7 @@ export class WalletClient {
937
1004
  */
938
1005
  async setReferrer(args, signal) {
939
1006
  // Destructure the parameters
940
- const { nonce = Date.now(), ...actionArgs } = args;
1007
+ const { nonce = this._nonce, ...actionArgs } = args;
941
1008
  // Construct an action
942
1009
  const action = {
943
1010
  type: "setReferrer",
@@ -957,6 +1024,110 @@ export class WalletClient {
957
1024
  this._validateResponse(response);
958
1025
  return response;
959
1026
  }
1027
+ /**
1028
+ * Deploying HIP-1 and HIP-2 assets.
1029
+ * @param args - The parameters for the request.
1030
+ * @param signal - An optional abort signal.
1031
+ * @returns Successful response without specific data.
1032
+ * @throws {ApiRequestError} When the API returns an error response.
1033
+ * @untested
1034
+ *
1035
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/deploying-hip-1-and-hip-2-assets
1036
+ * @example
1037
+ * ```ts
1038
+ * import * as hl from "@nktkas/hyperliquid";
1039
+ * import { privateKeyToAccount } from "viem/accounts";
1040
+ *
1041
+ * const wallet = privateKeyToAccount("0x...");
1042
+ * const transport = new hl.HttpTransport(); // or WebSocketTransport
1043
+ * const client = new hl.WalletClient({ wallet, transport });
1044
+ *
1045
+ * // Unknown what the successful response will be
1046
+ * const result = await client.spotDeploy({
1047
+ * registerToken2: {
1048
+ * spec: {
1049
+ * name: "TestToken",
1050
+ * szDecimals: 8,
1051
+ * weiDecimals: 8,
1052
+ * },
1053
+ * maxGas: 1000000,
1054
+ * fullName: "TestToken (TT)"
1055
+ * }
1056
+ * });
1057
+ * ```
1058
+ */
1059
+ async spotDeploy(args, signal) {
1060
+ // Destructure the parameters
1061
+ const { nonce = this._nonce, ...actionArgs } = args;
1062
+ // Construct an action
1063
+ let action;
1064
+ if ("registerToken2" in actionArgs) {
1065
+ action = {
1066
+ type: "spotDeploy",
1067
+ registerToken2: {
1068
+ spec: {
1069
+ name: actionArgs.registerToken2.spec.name,
1070
+ szDecimals: actionArgs.registerToken2.spec.szDecimals,
1071
+ weiDecimals: actionArgs.registerToken2.spec.weiDecimals,
1072
+ },
1073
+ maxGas: actionArgs.registerToken2.maxGas,
1074
+ fullName: actionArgs.registerToken2.fullName,
1075
+ },
1076
+ };
1077
+ }
1078
+ else if ("userGenesis" in actionArgs) {
1079
+ action = {
1080
+ type: "spotDeploy",
1081
+ userGenesis: {
1082
+ token: actionArgs.userGenesis.token,
1083
+ userAndWei: actionArgs.userGenesis.userAndWei,
1084
+ existingTokenAndWei: actionArgs.userGenesis.existingTokenAndWei,
1085
+ },
1086
+ };
1087
+ }
1088
+ else if ("genesis" in actionArgs) {
1089
+ action = {
1090
+ type: "spotDeploy",
1091
+ genesis: {
1092
+ token: actionArgs.genesis.token,
1093
+ maxSupply: actionArgs.genesis.maxSupply,
1094
+ },
1095
+ };
1096
+ }
1097
+ else if ("registerSpot" in actionArgs) {
1098
+ action = {
1099
+ type: "spotDeploy",
1100
+ registerSpot: {
1101
+ tokens: actionArgs.registerSpot.tokens,
1102
+ },
1103
+ };
1104
+ }
1105
+ else {
1106
+ action = {
1107
+ type: "spotDeploy",
1108
+ registerHyperliquidity: {
1109
+ spot: actionArgs.registerHyperliquidity.spot,
1110
+ startPx: actionArgs.registerHyperliquidity.startPx,
1111
+ orderSz: actionArgs.registerHyperliquidity.orderSz,
1112
+ nOrders: actionArgs.registerHyperliquidity.nOrders,
1113
+ nSeededLevels: actionArgs.registerHyperliquidity.nSeededLevels,
1114
+ },
1115
+ };
1116
+ }
1117
+ // Sign the action
1118
+ const signature = await signL1Action({
1119
+ wallet: this.wallet,
1120
+ action,
1121
+ nonce,
1122
+ isTestnet: this.isTestnet,
1123
+ });
1124
+ // Send a request
1125
+ const request = { action, signature, nonce };
1126
+ const response = await this.transport.request("exchange", request, signal);
1127
+ // Validate a response
1128
+ this._validateResponse(response);
1129
+ return response;
1130
+ }
960
1131
  /**
961
1132
  * Transfer a spot asset on L1 to another address.
962
1133
  * @param args - The parameters for the request.
@@ -988,7 +1159,7 @@ export class WalletClient {
988
1159
  type: "spotSend",
989
1160
  hyperliquidChain: this.isTestnet ? "Testnet" : "Mainnet",
990
1161
  signatureChainId: this.signatureChainId,
991
- time: args.time ?? Date.now(),
1162
+ time: args.time ?? this._nonce,
992
1163
  };
993
1164
  // Sign the action
994
1165
  const signature = await signUserSignedAction({
@@ -1036,7 +1207,7 @@ export class WalletClient {
1036
1207
  */
1037
1208
  async spotUser(args, signal) {
1038
1209
  // Destructure the parameters
1039
- const { nonce = Date.now(), ...actionArgs } = args;
1210
+ const { nonce = this._nonce, ...actionArgs } = args;
1040
1211
  // Construct an action
1041
1212
  const action = {
1042
1213
  type: "spotUser",
@@ -1085,7 +1256,7 @@ export class WalletClient {
1085
1256
  */
1086
1257
  async subAccountSpotTransfer(args, signal) {
1087
1258
  // Destructure the parameters
1088
- const { nonce = Date.now(), ...actionArgs } = args;
1259
+ const { nonce = this._nonce, ...actionArgs } = args;
1089
1260
  // Construct an action
1090
1261
  const action = {
1091
1262
  type: "subAccountSpotTransfer",
@@ -1134,7 +1305,7 @@ export class WalletClient {
1134
1305
  */
1135
1306
  async subAccountTransfer(args, signal) {
1136
1307
  // Destructure the parameters
1137
- const { nonce = Date.now(), ...actionArgs } = args;
1308
+ const { nonce = this._nonce, ...actionArgs } = args;
1138
1309
  // Construct an action
1139
1310
  const action = {
1140
1311
  type: "subAccountTransfer",
@@ -1187,7 +1358,7 @@ export class WalletClient {
1187
1358
  type: "tokenDelegate",
1188
1359
  hyperliquidChain: this.isTestnet ? "Testnet" : "Mainnet",
1189
1360
  signatureChainId: this.signatureChainId,
1190
- nonce: args.nonce ?? Date.now(),
1361
+ nonce: args.nonce ?? this._nonce,
1191
1362
  };
1192
1363
  // Sign the action
1193
1364
  const signature = await signUserSignedAction({
@@ -1236,7 +1407,7 @@ export class WalletClient {
1236
1407
  */
1237
1408
  async twapCancel(args, signal) {
1238
1409
  // Destructure the parameters
1239
- const { vaultAddress = this.defaultVaultAddress, nonce = Date.now(), ...actionArgs } = args;
1410
+ const { vaultAddress = this.defaultVaultAddress, nonce = this._nonce, ...actionArgs } = args;
1240
1411
  // Construct an action
1241
1412
  const action = {
1242
1413
  type: "twapCancel",
@@ -1287,14 +1458,14 @@ export class WalletClient {
1287
1458
  */
1288
1459
  async twapOrder(args, signal) {
1289
1460
  // Destructure the parameters
1290
- const { vaultAddress = this.defaultVaultAddress, nonce = Date.now(), ...actionArgs } = args;
1461
+ const { vaultAddress = this.defaultVaultAddress, nonce = this._nonce, ...actionArgs } = args;
1291
1462
  // Construct an action
1292
1463
  const action = {
1293
1464
  type: "twapOrder",
1294
1465
  twap: {
1295
1466
  a: actionArgs.a,
1296
1467
  b: actionArgs.b,
1297
- s: actionArgs.s,
1468
+ s: this._formatDecimal(actionArgs.s),
1298
1469
  r: actionArgs.r,
1299
1470
  m: actionArgs.m,
1300
1471
  t: actionArgs.t,
@@ -1341,7 +1512,7 @@ export class WalletClient {
1341
1512
  */
1342
1513
  async updateIsolatedMargin(args, signal) {
1343
1514
  // Destructure the parameters
1344
- const { vaultAddress = this.defaultVaultAddress, nonce = Date.now(), ...actionArgs } = args;
1515
+ const { vaultAddress = this.defaultVaultAddress, nonce = this._nonce, ...actionArgs } = args;
1345
1516
  // Construct an action
1346
1517
  const action = {
1347
1518
  type: "updateIsolatedMargin",
@@ -1390,7 +1561,7 @@ export class WalletClient {
1390
1561
  */
1391
1562
  async updateLeverage(args, signal) {
1392
1563
  // Destructure the parameters
1393
- const { vaultAddress = this.defaultVaultAddress, nonce = Date.now(), ...actionArgs } = args;
1564
+ const { vaultAddress = this.defaultVaultAddress, nonce = this._nonce, ...actionArgs } = args;
1394
1565
  // Construct an action
1395
1566
  const action = {
1396
1567
  type: "updateLeverage",
@@ -1443,7 +1614,7 @@ export class WalletClient {
1443
1614
  type: "usdClassTransfer",
1444
1615
  hyperliquidChain: this.isTestnet ? "Testnet" : "Mainnet",
1445
1616
  signatureChainId: this.signatureChainId,
1446
- nonce: args.nonce ?? Date.now(),
1617
+ nonce: args.nonce ?? this._nonce,
1447
1618
  };
1448
1619
  // Sign the action
1449
1620
  const signature = await signUserSignedAction({
@@ -1496,7 +1667,7 @@ export class WalletClient {
1496
1667
  type: "usdSend",
1497
1668
  hyperliquidChain: this.isTestnet ? "Testnet" : "Mainnet",
1498
1669
  signatureChainId: this.signatureChainId,
1499
- time: args.time ?? Date.now(),
1670
+ time: args.time ?? this._nonce,
1500
1671
  };
1501
1672
  // Sign the action
1502
1673
  const signature = await signUserSignedAction({
@@ -1544,7 +1715,7 @@ export class WalletClient {
1544
1715
  */
1545
1716
  async vaultDistribute(args, signal) {
1546
1717
  // Destructure the parameters
1547
- const { nonce = Date.now(), ...actionArgs } = args;
1718
+ const { nonce = this._nonce, ...actionArgs } = args;
1548
1719
  // Construct an action
1549
1720
  const action = {
1550
1721
  type: "vaultDistribute",
@@ -1591,7 +1762,7 @@ export class WalletClient {
1591
1762
  */
1592
1763
  async vaultModify(args, signal) {
1593
1764
  // Destructure the parameters
1594
- const { nonce = Date.now(), ...actionArgs } = args;
1765
+ const { nonce = this._nonce, ...actionArgs } = args;
1595
1766
  // Construct an action
1596
1767
  const action = {
1597
1768
  type: "vaultModify",
@@ -1639,7 +1810,7 @@ export class WalletClient {
1639
1810
  */
1640
1811
  async vaultTransfer(args, signal) {
1641
1812
  // Destructure the parameters
1642
- const { nonce = Date.now(), ...actionArgs } = args;
1813
+ const { nonce = this._nonce, ...actionArgs } = args;
1643
1814
  // Construct an action
1644
1815
  const action = {
1645
1816
  type: "vaultTransfer",
@@ -1691,7 +1862,7 @@ export class WalletClient {
1691
1862
  type: "withdraw3",
1692
1863
  hyperliquidChain: this.isTestnet ? "Testnet" : "Mainnet",
1693
1864
  signatureChainId: this.signatureChainId,
1694
- time: args.time ?? Date.now(),
1865
+ time: args.time ?? this._nonce,
1695
1866
  };
1696
1867
  // Sign the action
1697
1868
  const signature = await signUserSignedAction({
@@ -1714,6 +1885,15 @@ export class WalletClient {
1714
1885
  this._validateResponse(response);
1715
1886
  return response;
1716
1887
  }
1888
+ // ——————————————— Private methods ———————————————
1889
+ /** Formats a decimal number as a string, removing trailing zeros. */
1890
+ _formatDecimal(numStr) {
1891
+ if (!numStr.includes("."))
1892
+ return numStr;
1893
+ const [intPart, fracPart] = numStr.split(".");
1894
+ const newFrac = fracPart.replace(/0+$/, "");
1895
+ return newFrac ? `${intPart}.${newFrac}` : intPart;
1896
+ }
1717
1897
  /** Validate a response from the API. */
1718
1898
  _validateResponse(response) {
1719
1899
  if (response.status === "err") {
@@ -19,11 +19,27 @@ export declare class HttpRequestError extends TransportError {
19
19
  export interface HttpTransportOptions {
20
20
  /**
21
21
  * Base URL for API endpoints.
22
- * - Mainnet: `https://api.hyperliquid.xyz`
23
- * - Testnet: `https://api.hyperliquid-testnet.xyz`
24
- * @defaultValue `https://api.hyperliquid.xyz`
22
+ *
23
+ * When given as a string or URL, the URL is modified based on the request type:
24
+ * - For `"info"` and `"exchange"`, the hostname is replaced with `api.<baseDomain>`.
25
+ * - For `"explorer"`, the hostname is replaced with `rpc.<baseDomain>`.
26
+ *
27
+ * Alternatively, you can supply an object to specify separate URLs:
28
+ * ```ts
29
+ * {
30
+ * api: "https://api.hyperliquid.xyz",
31
+ * rpc: "https://rpc.hyperliquid.xyz"
32
+ * }
33
+ * ```
34
+ *
35
+ * - Mainnet: `https://hyperliquid.xyz`
36
+ * - Testnet: `https://hyperliquid-testnet.xyz`
37
+ * @defaultValue `https://hyperliquid.xyz`
25
38
  */
26
- url?: string | URL;
39
+ url?: string | URL | {
40
+ api?: string | URL;
41
+ rpc?: string | URL;
42
+ };
27
43
  /**
28
44
  * Request timeout in ms.
29
45
  * Set to `null` to disable.
@@ -47,7 +63,10 @@ export interface HttpTransportOptions {
47
63
  }
48
64
  /** HTTP implementation of the REST transport interface. */
49
65
  export declare class HttpTransport implements IRequestTransport, HttpTransportOptions {
50
- url: string | URL;
66
+ url: string | URL | {
67
+ api?: string | URL;
68
+ rpc?: string | URL;
69
+ };
51
70
  timeout: number | null;
52
71
  fetchOptions: Omit<RequestInit, "body" | "method">;
53
72
  onRequest?: (request: Request) => MaybePromise<Request | void | null | undefined>;
@@ -1 +1 @@
1
- {"version":3,"file":"http_transport.d.ts","sourceRoot":"","sources":["../../../../src/src/transports/http/http_transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEvE,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAEtC;;;;GAIG;AACH,qBAAa,gBAAiB,SAAQ,cAAc;IAM7B,QAAQ,EAAE,QAAQ;IAAS,YAAY,CAAC,EAAE,MAAM;IALnE;;;;OAIG;gBACgB,QAAQ,EAAE,QAAQ,EAAS,YAAY,CAAC,EAAE,MAAM,YAAA;CAOtE;AAED,0DAA0D;AAC1D,MAAM,WAAW,oBAAoB;IACjC;;;;;OAKG;IACH,GAAG,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;IAEnB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAExB,2IAA2I;IAC3I,YAAY,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC;IAEpD;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,YAAY,CAAC,OAAO,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAElF;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,YAAY,CAAC,QAAQ,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;CACzF;AAED,2DAA2D;AAC3D,qBAAa,aAAc,YAAW,iBAAiB,EAAE,oBAAoB;IACzE,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;IAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,YAAY,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC;IACnD,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,YAAY,CAAC,OAAO,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAClF,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,YAAY,CAAC,QAAQ,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAEtF;;;OAGG;gBACS,OAAO,CAAC,EAAE,oBAAoB;IAQ1C;;;;;;;;OAQG;IACG,OAAO,CACT,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,UAAU,EAC1C,OAAO,EAAE,OAAO,EAChB,MAAM,CAAC,EAAE,WAAW,GACrB,OAAO,CAAC,OAAO,CAAC;CAqDtB"}
1
+ {"version":3,"file":"http_transport.d.ts","sourceRoot":"","sources":["../../../../src/src/transports/http/http_transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEvE,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAEtC;;;;GAIG;AACH,qBAAa,gBAAiB,SAAQ,cAAc;IAM7B,QAAQ,EAAE,QAAQ;IAAS,YAAY,CAAC,EAAE,MAAM;IALnE;;;;OAIG;gBACgB,QAAQ,EAAE,QAAQ,EAAS,YAAY,CAAC,EAAE,MAAM,YAAA;CAOtE;AAED,0DAA0D;AAC1D,MAAM,WAAW,oBAAoB;IACjC;;;;;;;;;;;;;;;;;;OAkBG;IACH,GAAG,CAAC,EACE,MAAM,GACN,GAAG,GACH;QACE,GAAG,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;QACnB,GAAG,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;KACtB,CAAC;IAEN;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAExB,2IAA2I;IAC3I,YAAY,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC;IAEpD;;;;OAIG;IACH,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,YAAY,CAAC,OAAO,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAElF;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,YAAY,CAAC,QAAQ,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;CACzF;AAED,2DAA2D;AAC3D,qBAAa,aAAc,YAAW,iBAAiB,EAAE,oBAAoB;IACzE,GAAG,EACG,MAAM,GACN,GAAG,GACH;QACE,GAAG,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;QACnB,GAAG,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;KACtB,CAAC;IACN,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,YAAY,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC;IACnD,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,YAAY,CAAC,OAAO,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAClF,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,YAAY,CAAC,QAAQ,GAAG,IAAI,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAEtF;;;OAGG;gBACS,OAAO,CAAC,EAAE,oBAAoB;IAQ1C;;;;;;;;OAQG;IACG,OAAO,CACT,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,UAAU,EAC1C,OAAO,EAAE,OAAO,EAChB,MAAM,CAAC,EAAE,WAAW,GACrB,OAAO,CAAC,OAAO,CAAC;CAyDtB"}
@@ -84,12 +84,18 @@ export class HttpTransport {
84
84
  */
85
85
  async request(endpoint, payload, signal) {
86
86
  // Construct a Request
87
- const url = new URL(endpoint, this.url);
88
- // FIXME: Temporary hack: replace `api.hyperliquid-testnet.xyz/explorer` with `rpc.hyperliquid-testnet.xyz/explorer`
89
- // until the new rpc url becomes the standard for mainnet.
90
- // TODO: Maybe after that should split the url property into api and rpc variants.
91
- if (url.hostname === "api.hyperliquid-testnet.xyz" && url.pathname === "/explorer") {
92
- url.hostname = "rpc.hyperliquid-testnet.xyz";
87
+ let url;
88
+ if (typeof this.url === "string" || this.url instanceof URL) {
89
+ // If a string is provided, get the base domain and apply the modification to it
90
+ const parsedUrl = new URL(this.url);
91
+ const parts = parsedUrl.hostname.split(".");
92
+ const baseDomain = parts.slice(-2).join(".");
93
+ const baseUrl = `${parsedUrl.protocol}//${endpoint === "explorer" ? "rpc" : "api"}.${baseDomain}`;
94
+ url = new URL(endpoint, baseUrl);
95
+ }
96
+ else {
97
+ // If an object is specified, use the specific url and add a path to it
98
+ url = new URL(endpoint, endpoint === "explorer" ? this.url.rpc : this.url.api);
93
99
  }
94
100
  const init = mergeRequestInit({
95
101
  body: JSON.stringify(payload),
@@ -30,23 +30,21 @@ function isHyperliquidMsg(value) {
30
30
  /** Type guard for explorer block messages. */
31
31
  function isExplorerBlockMsg(value) {
32
32
  return Array.isArray(value) && value.length > 0 &&
33
- value.every((block) => typeof block === "object" && block !== null && !Array.isArray(block) &&
34
- "height" in block && typeof block.height === "number" &&
35
- "blockTime" in block && typeof block.blockTime === "number" &&
36
- "hash" in block && typeof block.hash === "string" &&
37
- "proposer" in block && typeof block.proposer === "string" &&
38
- "numTxs" in block && typeof block.numTxs === "number");
33
+ (typeof value[0] === "object" && value[0] !== null && !Array.isArray(value[0]) &&
34
+ "height" in value[0] && typeof value[0].height === "number" &&
35
+ "blockTime" in value[0] && typeof value[0].blockTime === "number" &&
36
+ "hash" in value[0] && typeof value[0].hash === "string" &&
37
+ "proposer" in value[0] && typeof value[0].proposer === "string" &&
38
+ "numTxs" in value[0] && typeof value[0].numTxs === "number");
39
39
  }
40
40
  /** Type guard for explorer transactions messages. */
41
41
  function isExplorerTxsMsg(value) {
42
42
  return Array.isArray(value) && value.length > 0 &&
43
- value.every((tx) => {
44
- return typeof tx === "object" && tx !== null && !Array.isArray(tx) &&
45
- "action" in tx && typeof tx.action === "object" && tx.action !== null &&
46
- "block" in tx && typeof tx.block === "number" &&
47
- "error" in tx && (typeof tx.error === "string" || tx.error === null) &&
48
- "hash" in tx && typeof tx.hash === "string" &&
49
- "time" in tx && typeof tx.time === "number" &&
50
- "user" in tx && typeof tx.user === "string";
51
- });
43
+ (typeof value[0] === "object" && value[0] !== null && !Array.isArray(value[0]) &&
44
+ "action" in value[0] && typeof value[0].action === "object" && value[0].action !== null &&
45
+ "block" in value[0] && typeof value[0].block === "number" &&
46
+ "error" in value[0] && (typeof value[0].error === "string" || value[0].error === null) &&
47
+ "hash" in value[0] && typeof value[0].hash === "string" &&
48
+ "time" in value[0] && typeof value[0].time === "number" &&
49
+ "user" in value[0] && typeof value[0].user === "string");
52
50
  }