@nktkas/hyperliquid 0.15.3 → 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 (30) hide show
  1. package/README.md +5 -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 +53 -2
  6. package/esm/src/clients/wallet.d.ts.map +1 -1
  7. package/esm/src/clients/wallet.js +173 -42
  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/websocket_transport.d.ts +1 -1
  12. package/esm/src/transports/websocket/websocket_transport.d.ts.map +1 -1
  13. package/esm/src/transports/websocket/websocket_transport.js +1 -5
  14. package/esm/src/types/exchange/requests.d.ts +120 -0
  15. package/esm/src/types/exchange/requests.d.ts.map +1 -1
  16. package/package.json +1 -1
  17. package/script/src/clients/event.d.ts +2 -0
  18. package/script/src/clients/event.d.ts.map +1 -1
  19. package/script/src/clients/event.js +2 -0
  20. package/script/src/clients/wallet.d.ts +53 -2
  21. package/script/src/clients/wallet.d.ts.map +1 -1
  22. package/script/src/clients/wallet.js +173 -42
  23. package/script/src/transports/http/http_transport.d.ts +24 -5
  24. package/script/src/transports/http/http_transport.d.ts.map +1 -1
  25. package/script/src/transports/http/http_transport.js +12 -6
  26. package/script/src/transports/websocket/websocket_transport.d.ts +1 -1
  27. package/script/src/transports/websocket/websocket_transport.d.ts.map +1 -1
  28. package/script/src/transports/websocket/websocket_transport.js +1 -5
  29. package/script/src/types/exchange/requests.d.ts +120 -0
  30. package/script/src/types/exchange/requests.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",
@@ -681,7 +699,7 @@ export class WalletClient {
681
699
  */
682
700
  async createVault(args, signal) {
683
701
  // Destructure the parameters
684
- const { nonce = Date.now(), ...actionArgs } = args;
702
+ const { nonce = this._nonce, ...actionArgs } = args;
685
703
  // Construct an action
686
704
  const action = {
687
705
  type: "createVault",
@@ -741,7 +759,7 @@ export class WalletClient {
741
759
  */
742
760
  async modify(args, signal) {
743
761
  // Destructure the parameters
744
- const { vaultAddress = this.defaultVaultAddress, nonce = Date.now(), ...actionArgs } = args;
762
+ const { vaultAddress = this.defaultVaultAddress, nonce = this._nonce, ...actionArgs } = args;
745
763
  // Construct an action
746
764
  const action = {
747
765
  type: "modify",
@@ -749,8 +767,8 @@ export class WalletClient {
749
767
  order: {
750
768
  a: actionArgs.order.a,
751
769
  b: actionArgs.order.b,
752
- p: actionArgs.order.p,
753
- s: actionArgs.order.s,
770
+ p: this._formatDecimal(actionArgs.order.p),
771
+ s: this._formatDecimal(actionArgs.order.s),
754
772
  r: actionArgs.order.r,
755
773
  t: "limit" in actionArgs.order.t
756
774
  ? {
@@ -761,7 +779,7 @@ export class WalletClient {
761
779
  : {
762
780
  trigger: {
763
781
  isMarket: actionArgs.order.t.trigger.isMarket,
764
- triggerPx: actionArgs.order.t.trigger.triggerPx,
782
+ triggerPx: this._formatDecimal(actionArgs.order.t.trigger.triggerPx),
765
783
  tpsl: actionArgs.order.t.trigger.tpsl,
766
784
  },
767
785
  },
@@ -822,7 +840,7 @@ export class WalletClient {
822
840
  */
823
841
  async order(args, signal) {
824
842
  // Destructure the parameters
825
- const { vaultAddress = this.defaultVaultAddress, nonce = Date.now(), ...actionArgs } = args;
843
+ const { vaultAddress = this.defaultVaultAddress, nonce = this._nonce, ...actionArgs } = args;
826
844
  // Construct an action
827
845
  const action = {
828
846
  type: "order",
@@ -830,8 +848,8 @@ export class WalletClient {
830
848
  const sortedOrder = {
831
849
  a: order.a,
832
850
  b: order.b,
833
- p: order.p,
834
- s: order.s,
851
+ p: this._formatDecimal(order.p),
852
+ s: this._formatDecimal(order.s),
835
853
  r: order.r,
836
854
  t: "limit" in order.t
837
855
  ? {
@@ -842,7 +860,7 @@ export class WalletClient {
842
860
  : {
843
861
  trigger: {
844
862
  isMarket: order.t.trigger.isMarket,
845
- triggerPx: order.t.trigger.triggerPx,
863
+ triggerPx: this._formatDecimal(order.t.trigger.triggerPx),
846
864
  tpsl: order.t.trigger.tpsl,
847
865
  },
848
866
  },
@@ -899,7 +917,7 @@ export class WalletClient {
899
917
  */
900
918
  async scheduleCancel(args = {}, signal) {
901
919
  // Destructure the parameters
902
- const { vaultAddress = this.defaultVaultAddress, nonce = Date.now(), ...actionArgs } = args;
920
+ const { vaultAddress = this.defaultVaultAddress, nonce = this._nonce, ...actionArgs } = args;
903
921
  // Construct an action
904
922
  const action = {
905
923
  type: "scheduleCancel",
@@ -944,7 +962,7 @@ export class WalletClient {
944
962
  */
945
963
  async setDisplayName(args, signal) {
946
964
  // Destructure the parameters
947
- const { nonce = Date.now(), ...actionArgs } = args;
965
+ const { nonce = this._nonce, ...actionArgs } = args;
948
966
  // Construct an action
949
967
  const action = {
950
968
  type: "setDisplayName",
@@ -986,7 +1004,7 @@ export class WalletClient {
986
1004
  */
987
1005
  async setReferrer(args, signal) {
988
1006
  // Destructure the parameters
989
- const { nonce = Date.now(), ...actionArgs } = args;
1007
+ const { nonce = this._nonce, ...actionArgs } = args;
990
1008
  // Construct an action
991
1009
  const action = {
992
1010
  type: "setReferrer",
@@ -1006,6 +1024,110 @@ export class WalletClient {
1006
1024
  this._validateResponse(response);
1007
1025
  return response;
1008
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
+ }
1009
1131
  /**
1010
1132
  * Transfer a spot asset on L1 to another address.
1011
1133
  * @param args - The parameters for the request.
@@ -1037,7 +1159,7 @@ export class WalletClient {
1037
1159
  type: "spotSend",
1038
1160
  hyperliquidChain: this.isTestnet ? "Testnet" : "Mainnet",
1039
1161
  signatureChainId: this.signatureChainId,
1040
- time: args.time ?? Date.now(),
1162
+ time: args.time ?? this._nonce,
1041
1163
  };
1042
1164
  // Sign the action
1043
1165
  const signature = await signUserSignedAction({
@@ -1085,7 +1207,7 @@ export class WalletClient {
1085
1207
  */
1086
1208
  async spotUser(args, signal) {
1087
1209
  // Destructure the parameters
1088
- const { nonce = Date.now(), ...actionArgs } = args;
1210
+ const { nonce = this._nonce, ...actionArgs } = args;
1089
1211
  // Construct an action
1090
1212
  const action = {
1091
1213
  type: "spotUser",
@@ -1134,7 +1256,7 @@ export class WalletClient {
1134
1256
  */
1135
1257
  async subAccountSpotTransfer(args, signal) {
1136
1258
  // Destructure the parameters
1137
- const { nonce = Date.now(), ...actionArgs } = args;
1259
+ const { nonce = this._nonce, ...actionArgs } = args;
1138
1260
  // Construct an action
1139
1261
  const action = {
1140
1262
  type: "subAccountSpotTransfer",
@@ -1183,7 +1305,7 @@ export class WalletClient {
1183
1305
  */
1184
1306
  async subAccountTransfer(args, signal) {
1185
1307
  // Destructure the parameters
1186
- const { nonce = Date.now(), ...actionArgs } = args;
1308
+ const { nonce = this._nonce, ...actionArgs } = args;
1187
1309
  // Construct an action
1188
1310
  const action = {
1189
1311
  type: "subAccountTransfer",
@@ -1236,7 +1358,7 @@ export class WalletClient {
1236
1358
  type: "tokenDelegate",
1237
1359
  hyperliquidChain: this.isTestnet ? "Testnet" : "Mainnet",
1238
1360
  signatureChainId: this.signatureChainId,
1239
- nonce: args.nonce ?? Date.now(),
1361
+ nonce: args.nonce ?? this._nonce,
1240
1362
  };
1241
1363
  // Sign the action
1242
1364
  const signature = await signUserSignedAction({
@@ -1285,7 +1407,7 @@ export class WalletClient {
1285
1407
  */
1286
1408
  async twapCancel(args, signal) {
1287
1409
  // Destructure the parameters
1288
- const { vaultAddress = this.defaultVaultAddress, nonce = Date.now(), ...actionArgs } = args;
1410
+ const { vaultAddress = this.defaultVaultAddress, nonce = this._nonce, ...actionArgs } = args;
1289
1411
  // Construct an action
1290
1412
  const action = {
1291
1413
  type: "twapCancel",
@@ -1336,14 +1458,14 @@ export class WalletClient {
1336
1458
  */
1337
1459
  async twapOrder(args, signal) {
1338
1460
  // Destructure the parameters
1339
- const { vaultAddress = this.defaultVaultAddress, nonce = Date.now(), ...actionArgs } = args;
1461
+ const { vaultAddress = this.defaultVaultAddress, nonce = this._nonce, ...actionArgs } = args;
1340
1462
  // Construct an action
1341
1463
  const action = {
1342
1464
  type: "twapOrder",
1343
1465
  twap: {
1344
1466
  a: actionArgs.a,
1345
1467
  b: actionArgs.b,
1346
- s: actionArgs.s,
1468
+ s: this._formatDecimal(actionArgs.s),
1347
1469
  r: actionArgs.r,
1348
1470
  m: actionArgs.m,
1349
1471
  t: actionArgs.t,
@@ -1390,7 +1512,7 @@ export class WalletClient {
1390
1512
  */
1391
1513
  async updateIsolatedMargin(args, signal) {
1392
1514
  // Destructure the parameters
1393
- const { vaultAddress = this.defaultVaultAddress, nonce = Date.now(), ...actionArgs } = args;
1515
+ const { vaultAddress = this.defaultVaultAddress, nonce = this._nonce, ...actionArgs } = args;
1394
1516
  // Construct an action
1395
1517
  const action = {
1396
1518
  type: "updateIsolatedMargin",
@@ -1439,7 +1561,7 @@ export class WalletClient {
1439
1561
  */
1440
1562
  async updateLeverage(args, signal) {
1441
1563
  // Destructure the parameters
1442
- const { vaultAddress = this.defaultVaultAddress, nonce = Date.now(), ...actionArgs } = args;
1564
+ const { vaultAddress = this.defaultVaultAddress, nonce = this._nonce, ...actionArgs } = args;
1443
1565
  // Construct an action
1444
1566
  const action = {
1445
1567
  type: "updateLeverage",
@@ -1492,7 +1614,7 @@ export class WalletClient {
1492
1614
  type: "usdClassTransfer",
1493
1615
  hyperliquidChain: this.isTestnet ? "Testnet" : "Mainnet",
1494
1616
  signatureChainId: this.signatureChainId,
1495
- nonce: args.nonce ?? Date.now(),
1617
+ nonce: args.nonce ?? this._nonce,
1496
1618
  };
1497
1619
  // Sign the action
1498
1620
  const signature = await signUserSignedAction({
@@ -1545,7 +1667,7 @@ export class WalletClient {
1545
1667
  type: "usdSend",
1546
1668
  hyperliquidChain: this.isTestnet ? "Testnet" : "Mainnet",
1547
1669
  signatureChainId: this.signatureChainId,
1548
- time: args.time ?? Date.now(),
1670
+ time: args.time ?? this._nonce,
1549
1671
  };
1550
1672
  // Sign the action
1551
1673
  const signature = await signUserSignedAction({
@@ -1593,7 +1715,7 @@ export class WalletClient {
1593
1715
  */
1594
1716
  async vaultDistribute(args, signal) {
1595
1717
  // Destructure the parameters
1596
- const { nonce = Date.now(), ...actionArgs } = args;
1718
+ const { nonce = this._nonce, ...actionArgs } = args;
1597
1719
  // Construct an action
1598
1720
  const action = {
1599
1721
  type: "vaultDistribute",
@@ -1640,7 +1762,7 @@ export class WalletClient {
1640
1762
  */
1641
1763
  async vaultModify(args, signal) {
1642
1764
  // Destructure the parameters
1643
- const { nonce = Date.now(), ...actionArgs } = args;
1765
+ const { nonce = this._nonce, ...actionArgs } = args;
1644
1766
  // Construct an action
1645
1767
  const action = {
1646
1768
  type: "vaultModify",
@@ -1688,7 +1810,7 @@ export class WalletClient {
1688
1810
  */
1689
1811
  async vaultTransfer(args, signal) {
1690
1812
  // Destructure the parameters
1691
- const { nonce = Date.now(), ...actionArgs } = args;
1813
+ const { nonce = this._nonce, ...actionArgs } = args;
1692
1814
  // Construct an action
1693
1815
  const action = {
1694
1816
  type: "vaultTransfer",
@@ -1740,7 +1862,7 @@ export class WalletClient {
1740
1862
  type: "withdraw3",
1741
1863
  hyperliquidChain: this.isTestnet ? "Testnet" : "Mainnet",
1742
1864
  signatureChainId: this.signatureChainId,
1743
- time: args.time ?? Date.now(),
1865
+ time: args.time ?? this._nonce,
1744
1866
  };
1745
1867
  // Sign the action
1746
1868
  const signature = await signUserSignedAction({
@@ -1763,6 +1885,15 @@ export class WalletClient {
1763
1885
  this._validateResponse(response);
1764
1886
  return response;
1765
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
+ }
1766
1897
  /** Validate a response from the API. */
1767
1898
  _validateResponse(response) {
1768
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),
@@ -76,7 +76,7 @@ export declare class WebSocketTransport implements IRequestTransport, ISubscript
76
76
  constructor(options?: WebSocketTransportOptions);
77
77
  /**
78
78
  * Sends a request to the Hyperliquid API via WebSocket.
79
- * @param endpoint - The API endpoint to send the request to.
79
+ * @param endpoint - The API endpoint to send the request to (`explorer` requests are not supported).
80
80
  * @param payload - The payload to send with the request.
81
81
  * @param signal - An optional abort signal.
82
82
  * @returns A promise that resolves with parsed JSON response body.
@@ -1 +1 @@
1
- {"version":3,"file":"websocket_transport.d.ts","sourceRoot":"","sources":["../../../../src/src/transports/websocket/websocket_transport.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,KAAK,qBAAqB,EAC1B,qBAAqB,EACrB,0BAA0B,EAC1B,KAAK,4BAA4B,EACpC,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,0BAA0B,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AACvG,OAAO,KAAK,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7F,OAAO,EAAE,qBAAqB,EAAE,CAAC;AACjC,OAAO,EAAE,KAAK,qBAAqB,EAAE,0BAA0B,EAAE,KAAK,4BAA4B,EAAE,CAAC;AAErG,+DAA+D;AAC/D,MAAM,WAAW,yBAAyB;IACtC;;;;;OAKG;IACH,GAAG,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;IAEnB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAExB;;;OAGG;IACH,SAAS,CAAC,EAAE;QACR;;;;WAIG;QACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC5B,CAAC;IAEF;;OAEG;IACH,SAAS,CAAC,EAAE,4BAA4B,CAAC;CAC5C;AAED,kFAAkF;AAClF,qBAAa,kBAAmB,YAAW,iBAAiB,EAAE,sBAAsB;IAChF,qDAAqD;IACrD,SAAS,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEhD,iDAAiD;IACjD,SAAS,CAAC,YAAY,EAAE,0BAA0B,CAAC;IAEnD,6CAA6C;IAC7C,SAAS,CAAC,SAAS,EAAE,sBAAsB,CAAC;IAE5C;;;;;OAKG;IACH,SAAS,CAAC,cAAc,EAAE,GAAG,CACzB,MAAM,EACN;QACI,SAAS,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACrF,cAAc,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;KACpC,CACJ,CAAa;IAEd;;;OAGG;IACH,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAEvB,yCAAyC;IACzC,QAAQ,CAAC,SAAS,EAAE;QAChB;;;WAGG;QACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;KACpC,CAAC;IAEF,oDAAoD;IACpD,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IAEvC;;;OAGG;gBACS,OAAO,CAAC,EAAE,yBAAyB;IAuC/C;;;;;;;;OAQG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAwBzG;;;;;;;OAOG;IACG,SAAS,CACX,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,EACrC,MAAM,CAAC,EAAE,WAAW,GACrB,OAAO,CAAC,YAAY,CAAC;IAwExB;;;;OAIG;IACH,KAAK,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAuB1C;;;;OAIG;IACH,KAAK,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;CAoB7C"}
1
+ {"version":3,"file":"websocket_transport.d.ts","sourceRoot":"","sources":["../../../../src/src/transports/websocket/websocket_transport.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,KAAK,qBAAqB,EAC1B,qBAAqB,EACrB,0BAA0B,EAC1B,KAAK,4BAA4B,EACpC,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,0BAA0B,EAAE,qBAAqB,EAAE,MAAM,oCAAoC,CAAC;AACvG,OAAO,KAAK,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7F,OAAO,EAAE,qBAAqB,EAAE,CAAC;AACjC,OAAO,EAAE,KAAK,qBAAqB,EAAE,0BAA0B,EAAE,KAAK,4BAA4B,EAAE,CAAC;AAErG,+DAA+D;AAC/D,MAAM,WAAW,yBAAyB;IACtC;;;;;OAKG;IACH,GAAG,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;IAEnB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAExB;;;OAGG;IACH,SAAS,CAAC,EAAE;QACR;;;;WAIG;QACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC5B,CAAC;IAEF;;OAEG;IACH,SAAS,CAAC,EAAE,4BAA4B,CAAC;CAC5C;AAED,kFAAkF;AAClF,qBAAa,kBAAmB,YAAW,iBAAiB,EAAE,sBAAsB;IAChF,qDAAqD;IACrD,SAAS,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEhD,iDAAiD;IACjD,SAAS,CAAC,YAAY,EAAE,0BAA0B,CAAC;IAEnD,6CAA6C;IAC7C,SAAS,CAAC,SAAS,EAAE,sBAAsB,CAAC;IAE5C;;;;;OAKG;IACH,SAAS,CAAC,cAAc,EAAE,GAAG,CACzB,MAAM,EACN;QACI,SAAS,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACrF,cAAc,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;KACpC,CACJ,CAAa;IAEd;;;OAGG;IACH,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAEvB,yCAAyC;IACzC,QAAQ,CAAC,SAAS,EAAE;QAChB;;;WAGG;QACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;KACpC,CAAC;IAEF,oDAAoD;IACpD,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IAEvC;;;OAGG;gBACS,OAAO,CAAC,EAAE,yBAAyB;IAuC/C;;;;;;;;OAQG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC;IAiBzG;;;;;;;OAOG;IACG,SAAS,CACX,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,EACrC,MAAM,CAAC,EAAE,WAAW,GACrB,OAAO,CAAC,YAAY,CAAC;IAwExB;;;;OAIG;IACH,KAAK,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAuB1C;;;;OAIG;IACH,KAAK,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;CAoB7C"}
@@ -99,7 +99,7 @@ export class WebSocketTransport {
99
99
  }
100
100
  /**
101
101
  * Sends a request to the Hyperliquid API via WebSocket.
102
- * @param endpoint - The API endpoint to send the request to.
102
+ * @param endpoint - The API endpoint to send the request to (`explorer` requests are not supported).
103
103
  * @param payload - The payload to send with the request.
104
104
  * @param signal - An optional abort signal.
105
105
  * @returns A promise that resolves with parsed JSON response body.
@@ -107,10 +107,6 @@ export class WebSocketTransport {
107
107
  * @note Explorer requests are not supported in the Hyperliquid WebSocket API.
108
108
  */
109
109
  request(type, payload, signal) {
110
- // Reject explorer requests because they are not supported by the Hyperliquid WebSocket API
111
- if (type === "explorer") {
112
- return Promise.reject(new WebSocketRequestError("Explorer requests are not supported in the Hyperliquid WebSocket API."));
113
- }
114
110
  // Send the request and wait for a response
115
111
  const timeoutSignal = this.timeout ? AbortSignal.timeout(this.timeout) : undefined;
116
112
  const combinedSignal = signal && timeoutSignal