@tria-sdk/hyperliquid-core 6.50.0-beta → 6.52.0-beta

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 (40) hide show
  1. package/dist/api.d.ts +59 -16
  2. package/dist/api.d.ts.map +1 -1
  3. package/dist/api.js +179 -105
  4. package/dist/api.js.map +1 -1
  5. package/dist/client.d.ts +20 -1
  6. package/dist/client.d.ts.map +1 -1
  7. package/dist/client.js +41 -1
  8. package/dist/client.js.map +1 -1
  9. package/dist/exchange.d.ts +0 -2
  10. package/dist/exchange.d.ts.map +1 -1
  11. package/dist/exchange.js.map +1 -1
  12. package/dist/index.d.ts +2 -0
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +2 -0
  15. package/dist/index.js.map +1 -1
  16. package/dist/utils/errorMapper.d.ts +14 -0
  17. package/dist/utils/errorMapper.d.ts.map +1 -0
  18. package/dist/utils/errorMapper.js +357 -0
  19. package/dist/utils/errorMapper.js.map +1 -0
  20. package/dist/utils/format.d.ts +1 -0
  21. package/dist/utils/format.d.ts.map +1 -1
  22. package/dist/utils/format.js +9 -4
  23. package/dist/utils/format.js.map +1 -1
  24. package/dist/utils/localization.d.ts +2 -1
  25. package/dist/utils/localization.d.ts.map +1 -1
  26. package/dist/utils/localization.js +2 -0
  27. package/dist/utils/localization.js.map +1 -1
  28. package/dist/utils/orderErrorParser.d.ts +29 -0
  29. package/dist/utils/orderErrorParser.d.ts.map +1 -0
  30. package/dist/utils/orderErrorParser.js +82 -0
  31. package/dist/utils/orderErrorParser.js.map +1 -0
  32. package/dist/websocket/WebSocketManager.d.ts +7 -0
  33. package/dist/websocket/WebSocketManager.d.ts.map +1 -1
  34. package/dist/websocket/WebSocketManager.js +84 -2
  35. package/dist/websocket/WebSocketManager.js.map +1 -1
  36. package/dist/websocket/types.d.ts +120 -3
  37. package/dist/websocket/types.d.ts.map +1 -1
  38. package/dist/websocket/types.js +7 -0
  39. package/dist/websocket/types.js.map +1 -1
  40. package/package.json +1 -1
package/dist/api.js CHANGED
@@ -3,7 +3,7 @@
3
3
  * Platform-agnostic data fetching - no web or React Native specific code
4
4
  */
5
5
  import { SymbolConverter } from "@nktkas/hyperliquid/utils";
6
- import { getHyperliquidInfoClient, getHyperliquidTransport } from "./client";
6
+ import { getHyperliquidInfoClient, getHyperliquidTransport, getHyperliquidWsInfoClient, getHyperliquidWsTransport, } from "./client";
7
7
  // ============================================================================
8
8
  // Constants
9
9
  // ============================================================================
@@ -40,6 +40,7 @@ const mapRawAssetPositionToPosition = (entry) => {
40
40
  /**
41
41
  * Maps a raw user fill entry to a typed HyperliquidUserFill.
42
42
  * Shared between fetchUserFills and fetchUserFillsByTime to avoid duplication.
43
+ * Accepts both our internal RawUserFill type and SDK response types.
43
44
  */
44
45
  const mapRawUserFill = (fill) => ({
45
46
  coin: String(fill.coin ?? ""),
@@ -57,7 +58,7 @@ const mapRawUserFill = (fill) => ({
57
58
  dir: fill.dir ? String(fill.dir) : undefined,
58
59
  closedPnl: fill.closedPnl ? String(fill.closedPnl) : undefined,
59
60
  crossed: typeof fill.crossed === "boolean" ? fill.crossed : undefined,
60
- liquidation: fill.liquidation ?? undefined,
61
+ liquidation: fill.liquidation,
61
62
  twapId: typeof fill.twapId === "number" ? fill.twapId : undefined,
62
63
  });
63
64
  /**
@@ -187,16 +188,22 @@ const pickValidPrice = (...values) => {
187
188
  // ============================================================================
188
189
  /**
189
190
  * Retrieves raw spot metadata from Hyperliquid public API
191
+ * Uses WebSocket POST by default to reduce HTTP rate limiting
190
192
  */
191
- export async function fetchSpotMeta(network = "testnet") {
192
- const client = getHyperliquidInfoClient(network);
193
+ export async function fetchSpotMeta(network = "testnet", useWsPost = true) {
194
+ const client = useWsPost
195
+ ? getHyperliquidWsInfoClient(network)
196
+ : getHyperliquidInfoClient(network);
193
197
  return client.spotMeta();
194
198
  }
195
199
  /**
196
200
  * Fetches token details for a specific token
201
+ * Uses WebSocket POST by default to reduce HTTP rate limiting
197
202
  */
198
- export async function fetchTokenDetails(tokenId, network = "testnet") {
199
- const client = getHyperliquidInfoClient(network);
203
+ export async function fetchTokenDetails(tokenId, network = "testnet", useWsPost = true) {
204
+ const client = useWsPost
205
+ ? getHyperliquidWsInfoClient(network)
206
+ : getHyperliquidInfoClient(network);
200
207
  const details = await client.tokenDetails({ tokenId });
201
208
  return {
202
209
  name: details.name,
@@ -215,16 +222,22 @@ export async function fetchTokenDetails(tokenId, network = "testnet") {
215
222
  }
216
223
  /**
217
224
  * Fetches all mid prices
225
+ * Uses WebSocket POST by default to reduce HTTP rate limiting
218
226
  */
219
- export async function fetchAllMids(network = "testnet") {
220
- const client = getHyperliquidInfoClient(network);
227
+ export async function fetchAllMids(network = "testnet", useWsPost = true) {
228
+ const client = useWsPost
229
+ ? getHyperliquidWsInfoClient(network)
230
+ : getHyperliquidInfoClient(network);
221
231
  return client.allMids();
222
232
  }
223
233
  /**
224
234
  * Fetches spot metadata and asset contexts
235
+ * Uses WebSocket POST by default to reduce HTTP rate limiting
225
236
  */
226
- export async function fetchSpotMetaAndAssetCtxs(network = "testnet") {
227
- const client = getHyperliquidInfoClient(network);
237
+ export async function fetchSpotMetaAndAssetCtxs(network = "testnet", useWsPost = true) {
238
+ const client = useWsPost
239
+ ? getHyperliquidWsInfoClient(network)
240
+ : getHyperliquidInfoClient(network);
228
241
  return client.spotMetaAndAssetCtxs();
229
242
  }
230
243
  /**
@@ -396,18 +409,24 @@ export async function fetchSpotPairsWithMarketData(network = "testnet") {
396
409
  }
397
410
  /**
398
411
  * Fetches spot order book for a token
412
+ * Uses WebSocket POST by default to reduce HTTP rate limiting
399
413
  */
400
- export async function fetchSpotOrderBook(tokenName, network = "testnet") {
401
- const client = getHyperliquidInfoClient(network);
414
+ export async function fetchSpotOrderBook(tokenName, network = "testnet", useWsPost = true) {
415
+ const client = useWsPost
416
+ ? getHyperliquidWsInfoClient(network)
417
+ : getHyperliquidInfoClient(network);
402
418
  const coin = ensureSpotSymbol(tokenName);
403
419
  return client.l2Book({ coin });
404
420
  }
405
421
  /**
406
422
  * Fetches order book snapshot with normalized levels
423
+ * Uses WebSocket POST by default to reduce HTTP rate limiting
407
424
  */
408
- export async function fetchOrderBook(symbol, depth = 25, network = "testnet") {
425
+ export async function fetchOrderBook(symbol, depth = 25, network = "testnet", useWsPost = true) {
409
426
  const { coin, market } = parseSymbolForBook(symbol);
410
- const client = getHyperliquidInfoClient(network);
427
+ const client = useWsPost
428
+ ? getHyperliquidWsInfoClient(network)
429
+ : getHyperliquidInfoClient(network);
411
430
  const response = (await client.l2Book({ coin }));
412
431
  const levels = Array.isArray(response?.levels)
413
432
  ? response.levels
@@ -438,18 +457,21 @@ export async function fetchOrderBook(symbol, depth = 25, network = "testnet") {
438
457
  }
439
458
  /**
440
459
  * Fetches recent trades for a coin
460
+ * Uses WebSocket POST by default to reduce HTTP rate limiting
441
461
  */
442
- export async function fetchRecentTrades(coin, limit = 20, network = "testnet") {
443
- const transport = getHyperliquidTransport(network);
444
- const trades = await transport.request("info", {
445
- type: "recentTrades",
462
+ export async function fetchRecentTrades(coin, limit = 20, network = "testnet",
463
+ /** Use WebSocket POST to reduce HTTP rate limiting (default: true) */
464
+ useWsPost = true) {
465
+ const client = useWsPost
466
+ ? getHyperliquidWsInfoClient(network)
467
+ : getHyperliquidInfoClient(network);
468
+ const trades = await client.recentTrades({
446
469
  coin,
447
- limit,
448
470
  });
449
471
  if (!Array.isArray(trades)) {
450
472
  throw new Error(`Unexpected API response for recentTrades: expected array, got ${typeof trades}`);
451
473
  }
452
- return trades.map((trade) => {
474
+ return trades.slice(0, limit).map((trade) => {
453
475
  const price = trade.px ?? trade.p ?? "0";
454
476
  const size = trade.sz ?? trade.s ?? "0";
455
477
  const timestamp = trade.time ?? Date.now();
@@ -465,35 +487,45 @@ export async function fetchRecentTrades(coin, limit = 20, network = "testnet") {
465
487
  }
466
488
  /**
467
489
  * Fetches perp metadata
490
+ * Uses WebSocket POST by default to reduce HTTP rate limiting
468
491
  */
469
- export async function fetchPerpMeta(network = "testnet") {
470
- const client = getHyperliquidInfoClient(network);
492
+ export async function fetchPerpMeta(network = "testnet", useWsPost = true) {
493
+ const client = useWsPost
494
+ ? getHyperliquidWsInfoClient(network)
495
+ : getHyperliquidInfoClient(network);
471
496
  return client.meta();
472
497
  }
473
498
  /**
474
499
  * Fetches perp metadata and asset contexts
500
+ * Uses WebSocket POST by default to reduce HTTP rate limiting
475
501
  */
476
- export async function fetchPerpMetaAndAssetCtxs(network = "testnet") {
477
- const client = getHyperliquidInfoClient(network);
502
+ export async function fetchPerpMetaAndAssetCtxs(network = "testnet", useWsPost = true) {
503
+ const client = useWsPost
504
+ ? getHyperliquidWsInfoClient(network)
505
+ : getHyperliquidInfoClient(network);
478
506
  return client.metaAndAssetCtxs();
479
507
  }
480
508
  /**
481
509
  * Fetches funding history for a coin
510
+ * Uses WebSocket POST by default to reduce HTTP rate limiting
482
511
  */
483
- export async function fetchFundingHistory(coin, startTime, network = "testnet") {
484
- const client = getHyperliquidInfoClient(network);
512
+ export async function fetchFundingHistory(coin, startTime, network = "testnet", useWsPost = true) {
513
+ const client = useWsPost
514
+ ? getHyperliquidWsInfoClient(network)
515
+ : getHyperliquidInfoClient(network);
485
516
  return client.fundingHistory({ coin, startTime });
486
517
  }
487
518
  /**
488
519
  * Fetches user fills (trade history)
489
520
  */
490
521
  export async function fetchUserFills(params) {
491
- const { user, aggregateByTime = false, limit = 100, network = "testnet", } = params;
492
- const transport = getHyperliquidTransport(network);
522
+ const { user, aggregateByTime = false, limit = 100, network = "testnet", useWsPost = true, } = params;
523
+ const client = useWsPost
524
+ ? getHyperliquidWsInfoClient(network)
525
+ : getHyperliquidInfoClient(network);
493
526
  const now = Date.now();
494
- const fills = await transport.request("info", {
495
- type: "userFillsByTime",
496
- user,
527
+ const fills = await client.userFillsByTime({
528
+ user: user,
497
529
  aggregateByTime,
498
530
  startTime: now - 30 * 24 * 60 * 60 * 1000,
499
531
  endTime: now,
@@ -505,13 +537,15 @@ export async function fetchUserFills(params) {
505
537
  }
506
538
  /**
507
539
  * Fetches user fills within a time window (order history)
540
+ * Uses WebSocket POST by default to reduce HTTP rate limiting
508
541
  */
509
542
  export async function fetchUserFillsByTime(params) {
510
- const { user, startTime, endTime = Date.now(), aggregateByTime = true, limit = 200, network = "testnet", } = params;
511
- const transport = getHyperliquidTransport(network);
512
- const fills = await transport.request("info", {
513
- type: "userFillsByTime",
514
- user,
543
+ const { user, startTime, endTime = Date.now(), aggregateByTime = true, limit = 200, network = "testnet", useWsPost = true, } = params;
544
+ const client = useWsPost
545
+ ? getHyperliquidWsInfoClient(network)
546
+ : getHyperliquidInfoClient(network);
547
+ const fills = await client.userFillsByTime({
548
+ user: user,
515
549
  startTime,
516
550
  endTime,
517
551
  aggregateByTime,
@@ -529,15 +563,17 @@ export async function fetchUserFillsByTime(params) {
529
563
  }
530
564
  /**
531
565
  * Fetches user funding ledger updates
566
+ * Uses WebSocket POST by default to reduce HTTP rate limiting
532
567
  */
533
568
  export async function fetchUserFunding(params) {
534
- const { user, startTime, endTime = null, limit = 200, network = "testnet", } = params;
535
- const transport = getHyperliquidTransport(network);
536
- const updates = await transport.request("info", {
537
- type: "userFunding",
538
- user,
569
+ const { user, startTime, endTime = null, limit = 200, network = "testnet", useWsPost = true, } = params;
570
+ const client = useWsPost
571
+ ? getHyperliquidWsInfoClient(network)
572
+ : getHyperliquidInfoClient(network);
573
+ const updates = await client.userFunding({
574
+ user: user,
539
575
  startTime,
540
- endTime,
576
+ endTime: endTime ?? undefined,
541
577
  });
542
578
  if (!Array.isArray(updates)) {
543
579
  throw new Error(`Unexpected API response for userFunding: expected array, got ${typeof updates}`);
@@ -551,21 +587,23 @@ export async function fetchUserFunding(params) {
551
587
  usdc: update.delta?.usdc ?? "0",
552
588
  szi: update.delta?.szi ?? "0",
553
589
  fundingRate: update.delta?.fundingRate ?? "0",
554
- nSamples: update.delta?.nSamples ?? 0,
590
+ nSamples: Number(update.delta?.nSamples ?? 0),
555
591
  },
556
592
  }));
557
593
  }
558
594
  /**
559
595
  * Fetches user non-funding ledger updates (deposits, withdrawals, transfers)
596
+ * Uses WebSocket POST by default to reduce HTTP rate limiting
560
597
  */
561
598
  export async function fetchUserNonFundingLedgerUpdates(params) {
562
- const { user, startTime, endTime = null, limit = 200, network = "testnet", } = params;
563
- const transport = getHyperliquidTransport(network);
564
- const updates = await transport.request("info", {
565
- type: "userNonFundingLedgerUpdates",
566
- user,
599
+ const { user, startTime, endTime = null, limit = 200, network = "testnet", useWsPost = true, } = params;
600
+ const client = useWsPost
601
+ ? getHyperliquidWsInfoClient(network)
602
+ : getHyperliquidInfoClient(network);
603
+ const updates = await client.userNonFundingLedgerUpdates({
604
+ user: user,
567
605
  startTime,
568
- endTime,
606
+ endTime: endTime ?? undefined,
569
607
  });
570
608
  if (!Array.isArray(updates)) {
571
609
  throw new Error(`Unexpected API response for userNonFundingLedgerUpdates: expected array, got ${typeof updates}`);
@@ -635,10 +673,13 @@ export async function fetchPerpsWithMarketData(network = "testnet") {
635
673
  }
636
674
  /**
637
675
  * Fetches candlestick data
676
+ * Uses WebSocket POST by default to reduce HTTP rate limiting
638
677
  */
639
678
  export async function fetchCandlesticks(params) {
640
- const { coin, interval, startTime, endTime, network = "testnet" } = params;
641
- const client = getHyperliquidInfoClient(network);
679
+ const { coin, interval, startTime, endTime, network = "testnet", useWsPost = true, } = params;
680
+ const client = useWsPost
681
+ ? getHyperliquidWsInfoClient(network)
682
+ : getHyperliquidInfoClient(network);
642
683
  const now = Date.now();
643
684
  const fromTime = startTime ?? now - CANDLE_LOOKBACK * intervalToMs(interval);
644
685
  const toTime = endTime ?? now;
@@ -743,12 +784,15 @@ export async function fetchLatestPrice(coin, network = "testnet") {
743
784
  }
744
785
  /**
745
786
  * Fetches user leverage mode for a specific coin.
787
+ * Uses WebSocket POST by default to reduce HTTP rate limiting
746
788
  * @throws Error if the API call fails - callers should implement retry logic.
747
789
  * @returns The leverage mode, or null if the user has no position for this coin.
748
790
  */
749
- export async function fetchUserLeverageMode(userAddress, coin, network = "testnet") {
791
+ export async function fetchUserLeverageMode(userAddress, coin, network = "testnet", useWsPost = true) {
750
792
  try {
751
- const client = getHyperliquidInfoClient(network);
793
+ const client = useWsPost
794
+ ? getHyperliquidWsInfoClient(network)
795
+ : getHyperliquidInfoClient(network);
752
796
  const state = await client.clearinghouseState({
753
797
  user: userAddress,
754
798
  });
@@ -793,9 +837,15 @@ export async function fetchUserLeverageMode(userAddress, coin, network = "testne
793
837
  /**
794
838
  * Fetches top of book (best bid/ask) for a symbol
795
839
  */
796
- export async function fetchTopOfBook(symbol, network = "testnet") {
840
+ /**
841
+ * Fetches top of book (best bid/ask) for a symbol
842
+ * Uses WebSocket POST by default to reduce HTTP rate limiting
843
+ */
844
+ export async function fetchTopOfBook(symbol, network = "testnet", useWsPost = true) {
797
845
  const { coin } = parseSymbolForBook(symbol);
798
- const client = getHyperliquidInfoClient(network);
846
+ const client = useWsPost
847
+ ? getHyperliquidWsInfoClient(network)
848
+ : getHyperliquidInfoClient(network);
799
849
  const book = (await client.l2Book({ coin }));
800
850
  const levels = Array.isArray(book?.levels)
801
851
  ? book.levels
@@ -818,9 +868,12 @@ export async function fetchTopOfBook(symbol, network = "testnet") {
818
868
  // ============================================================================
819
869
  /**
820
870
  * Fetches user positions from clearinghouse state
871
+ * Uses WebSocket POST by default to reduce HTTP rate limiting
821
872
  */
822
- export async function fetchUserPositions(userAddress, network = "testnet") {
823
- const client = getHyperliquidInfoClient(network);
873
+ export async function fetchUserPositions(userAddress, network = "testnet", useWsPost = true) {
874
+ const client = useWsPost
875
+ ? getHyperliquidWsInfoClient(network)
876
+ : getHyperliquidInfoClient(network);
824
877
  const state = await client.clearinghouseState({
825
878
  user: userAddress,
826
879
  });
@@ -833,9 +886,13 @@ export async function fetchUserPositions(userAddress, network = "testnet") {
833
886
  }
834
887
  /**
835
888
  * Fetches user's clearinghouse state (positions + margin summary)
889
+ * Uses WebSocket POST by default to reduce HTTP rate limiting
836
890
  */
837
- export async function fetchUserState(userAddress, network = "testnet", dex) {
838
- const client = getHyperliquidInfoClient(network);
891
+ export async function fetchUserState(userAddress, network = "testnet", dex, useWsPost = true) {
892
+ // Use WebSocket client by default to avoid HTTP rate limiting
893
+ const client = useWsPost
894
+ ? getHyperliquidWsInfoClient(network)
895
+ : getHyperliquidInfoClient(network);
839
896
  const state = await client.clearinghouseState({
840
897
  user: userAddress,
841
898
  ...(dex ? { dex } : {}),
@@ -872,9 +929,13 @@ export async function fetchUserState(userAddress, network = "testnet", dex) {
872
929
  }
873
930
  /**
874
931
  * Fetches user's open orders with frontend info (includes trigger prices for TP/SL)
932
+ * Uses WebSocket POST by default to reduce HTTP rate limiting
875
933
  */
876
- export async function fetchOpenOrders(userAddress, network = "testnet", dex) {
877
- const client = getHyperliquidInfoClient(network);
934
+ export async function fetchOpenOrders(userAddress, network = "testnet", dex, useWsPost = true) {
935
+ // Use WebSocket client by default to avoid HTTP rate limiting
936
+ const client = useWsPost
937
+ ? getHyperliquidWsInfoClient(network)
938
+ : getHyperliquidInfoClient(network);
878
939
  // Use frontendOpenOrders to get complete order info including triggerPx for TP/SL orders
879
940
  const orders = await client.frontendOpenOrders({
880
941
  user: userAddress,
@@ -905,6 +966,7 @@ export async function fetchOpenOrders(userAddress, network = "testnet", dex) {
905
966
  // ============================================================================
906
967
  /**
907
968
  * Resolves asset index for a coin
969
+ * Uses WebSocket transport for consistency with other requests
908
970
  */
909
971
  export async function resolveAssetIndex(coin, network = "testnet") {
910
972
  const normalizedCoin = (coin || "")
@@ -915,7 +977,7 @@ export async function resolveAssetIndex(coin, network = "testnet") {
915
977
  throw new Error("Coin is required to resolve asset index");
916
978
  }
917
979
  const converter = await SymbolConverter.create({
918
- transport: getHyperliquidTransport(network),
980
+ transport: getHyperliquidWsTransport(network),
919
981
  });
920
982
  const assetId = converter.getAssetId(normalizedCoin);
921
983
  if (assetId === undefined) {
@@ -926,13 +988,16 @@ export async function resolveAssetIndex(coin, network = "testnet") {
926
988
  /**
927
989
  * Fetches user fee rates from Hyperliquid
928
990
  * Returns taker/maker rates for perps and spot
991
+ * Uses WebSocket POST by default to reduce HTTP rate limiting
929
992
  */
930
993
  export async function fetchUserFees(params) {
931
- const { userAddress, network = "testnet" } = params;
994
+ const { userAddress, network = "testnet", useWsPost = true } = params;
932
995
  if (!userAddress) {
933
996
  throw new Error("User address is required to fetch fees");
934
997
  }
935
- const client = getHyperliquidInfoClient(network);
998
+ const client = useWsPost
999
+ ? getHyperliquidWsInfoClient(network)
1000
+ : getHyperliquidInfoClient(network);
936
1001
  const response = await client.userFees({
937
1002
  user: userAddress,
938
1003
  });
@@ -947,46 +1012,54 @@ export async function fetchUserFees(params) {
947
1012
  /**
948
1013
  * Fetches user historical orders from Hyperliquid
949
1014
  * Returns orders with their current status (open, filled, canceled, etc.)
1015
+ * Uses WebSocket POST by default to reduce HTTP rate limiting
950
1016
  */
951
1017
  export async function fetchHistoricalOrders(params) {
952
- const { user, limit = 200, network = "testnet" } = params;
1018
+ const { user, limit = 200, network = "testnet", useWsPost = true } = params;
953
1019
  if (!user) {
954
1020
  throw new Error("User address is required to fetch historical orders");
955
1021
  }
956
- const transport = getHyperliquidTransport(network);
957
- const response = await transport.request("info", {
958
- type: "historicalOrders",
959
- user,
1022
+ const client = useWsPost
1023
+ ? getHyperliquidWsInfoClient(network)
1024
+ : getHyperliquidInfoClient(network);
1025
+ const response = await client.historicalOrders({
1026
+ user: user,
960
1027
  });
961
1028
  if (!Array.isArray(response)) {
962
1029
  return [];
963
1030
  }
964
1031
  return response.slice(0, limit).map((item) => {
965
1032
  const order = item.order ?? {};
1033
+ const orderObj = order;
966
1034
  return {
967
1035
  order: {
968
- coin: String(order.coin ?? ""),
969
- side: order.side === "B" || order.side === "A" ? order.side : "B",
970
- limitPx: String(order.limitPx ?? "0"),
971
- sz: String(order.sz ?? "0"),
972
- oid: typeof order.oid === "number" ? order.oid : 0,
973
- timestamp: typeof order.timestamp === "number" ? order.timestamp : Date.now(),
974
- origSz: String(order.origSz ?? order.sz ?? "0"),
975
- triggerCondition: order.triggerCondition
976
- ? String(order.triggerCondition)
1036
+ coin: String(orderObj.coin ?? ""),
1037
+ side: orderObj.side === "B" || orderObj.side === "A" ? orderObj.side : "B",
1038
+ limitPx: String(orderObj.limitPx ?? "0"),
1039
+ sz: String(orderObj.sz ?? "0"),
1040
+ oid: typeof orderObj.oid === "number" ? orderObj.oid : 0,
1041
+ timestamp: typeof orderObj.timestamp === "number"
1042
+ ? orderObj.timestamp
1043
+ : Date.now(),
1044
+ origSz: String(orderObj.origSz ?? orderObj.sz ?? "0"),
1045
+ triggerCondition: orderObj.triggerCondition
1046
+ ? String(orderObj.triggerCondition)
977
1047
  : undefined,
978
- isTrigger: typeof order.isTrigger === "boolean" ? order.isTrigger : false,
979
- triggerPx: order.triggerPx ? String(order.triggerPx) : undefined,
980
- children: Array.isArray(order.children) ? order.children : [],
981
- isPositionTpsl: typeof order.isPositionTpsl === "boolean"
982
- ? order.isPositionTpsl
1048
+ isTrigger: typeof orderObj.isTrigger === "boolean" ? orderObj.isTrigger : false,
1049
+ triggerPx: orderObj.triggerPx ? String(orderObj.triggerPx) : undefined,
1050
+ children: Array.isArray(orderObj.children) ? orderObj.children : [],
1051
+ isPositionTpsl: typeof orderObj.isPositionTpsl === "boolean"
1052
+ ? orderObj.isPositionTpsl
983
1053
  : false,
984
- reduceOnly: typeof order.reduceOnly === "boolean" ? order.reduceOnly : false,
985
- orderType: String(order.orderType ?? "Limit"),
986
- tif: String(order.tif ?? "Gtc"),
987
- cloid: order.cloid ? String(order.cloid) : undefined,
1054
+ reduceOnly: typeof orderObj.reduceOnly === "boolean"
1055
+ ? orderObj.reduceOnly
1056
+ : false,
1057
+ orderType: String(orderObj.orderType ?? "Limit"),
1058
+ tif: String(orderObj.tif ?? "Gtc"),
1059
+ cloid: orderObj.cloid ? String(orderObj.cloid) : undefined,
988
1060
  },
989
- status: (item.status ?? "filled"),
1061
+ status: (item.status ??
1062
+ "filled"),
990
1063
  statusTimestamp: typeof item.statusTimestamp === "number"
991
1064
  ? item.statusTimestamp
992
1065
  : Date.now(),
@@ -996,16 +1069,20 @@ export async function fetchHistoricalOrders(params) {
996
1069
  /**
997
1070
  * Fetches user frontend open orders from Hyperliquid
998
1071
  * Returns open orders with additional display information (trigger conditions, TP/SL, etc.)
1072
+ * Uses WebSocket POST for dex-specific queries to reduce HTTP rate limiting
999
1073
  */
1000
1074
  export async function fetchFrontendOpenOrders(params) {
1001
- const { user, network = "testnet" } = params;
1075
+ const { user, dex, network = "testnet" } = params;
1002
1076
  if (!user) {
1003
1077
  throw new Error("User address is required to fetch open orders");
1004
1078
  }
1005
- const transport = getHyperliquidTransport(network);
1006
- const response = await transport.request("info", {
1007
- type: "frontendOpenOrders",
1008
- user,
1079
+ // Use WebSocket client for dex-specific queries to avoid HTTP rate limiting
1080
+ const client = dex
1081
+ ? getHyperliquidWsInfoClient(network)
1082
+ : getHyperliquidInfoClient(network);
1083
+ const response = await client.frontendOpenOrders({
1084
+ user: user,
1085
+ ...(dex ? { dex } : {}),
1009
1086
  });
1010
1087
  if (!Array.isArray(response)) {
1011
1088
  return [];
@@ -1043,6 +1120,7 @@ let inflightHip3DexsRequest = null;
1043
1120
  const HIP3_DEXS_CACHE_TTL = 60000; // 60 seconds
1044
1121
  /**
1045
1122
  * Fetches all HIP-3 perp DEXs with caching and deduplication
1123
+ * Uses WebSocket POST to reduce HTTP rate limiting
1046
1124
  */
1047
1125
  export async function fetchHip3Dexs(network = "mainnet") {
1048
1126
  const now = Date.now();
@@ -1056,7 +1134,8 @@ export async function fetchHip3Dexs(network = "mainnet") {
1056
1134
  }
1057
1135
  inflightHip3DexsRequest = (async () => {
1058
1136
  try {
1059
- const transport = getHyperliquidTransport(network);
1137
+ // Use WebSocket transport for consistency with other requests
1138
+ const transport = getHyperliquidWsTransport(network);
1060
1139
  const data = await transport.request("info", {
1061
1140
  type: "perpDexs",
1062
1141
  });
@@ -1115,17 +1194,12 @@ export async function fetchHip3Markets(dexName, network = "mainnet") {
1115
1194
  if (dexIndex === -1) {
1116
1195
  return [];
1117
1196
  }
1118
- const transport = getHyperliquidTransport(network);
1119
- // Fetch metadata and mids in parallel
1197
+ // Use WebSocket InfoClient for dex-specific queries to reduce HTTP rate limiting
1198
+ const wsClient = getHyperliquidWsInfoClient(network);
1199
+ // Fetch metadata and mids in parallel using WebSocket POST requests
1120
1200
  const [metaResult, midsResult] = await Promise.allSettled([
1121
- transport.request("info", {
1122
- type: "metaAndAssetCtxs",
1123
- dex: dexName,
1124
- }),
1125
- transport.request("info", {
1126
- type: "allMids",
1127
- dex: dexName,
1128
- }),
1201
+ wsClient.metaAndAssetCtxs({ dex: dexName }),
1202
+ wsClient.allMids({ dex: dexName }),
1129
1203
  ]);
1130
1204
  if (metaResult.status === "rejected") {
1131
1205
  console.error("[fetchHip3Markets] Meta fetch failed:", metaResult.reason);
@@ -1179,7 +1253,7 @@ export async function fetchHip3Markets(dexName, network = "mainnet") {
1179
1253
  priceChangePercent24h,
1180
1254
  volume24h: parseFloat(ctx.dayNtlVlm),
1181
1255
  openInterest: parseFloat(ctx.openInterest),
1182
- fundingRate: parseFloat(ctx.funding),
1256
+ fundingRate: parseFloat(ctx.funding) * 100, // Convert to percentage (same as perp markets)
1183
1257
  markPrice,
1184
1258
  sizeDecimals: asset.szDecimals,
1185
1259
  maxLeverage: asset.maxLeverage,