@pear-protocol/hyperliquid-sdk 0.0.67 → 0.0.68-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.
@@ -1,12 +1,14 @@
1
1
  import type { GetEIP712MessageResponse } from "../types";
2
2
  export declare function useAuth(): {
3
3
  readonly isReady: boolean;
4
- readonly isAuthenticated: any;
5
- readonly accessToken: any;
6
- readonly refreshToken: any;
4
+ readonly isAuthenticated: boolean;
5
+ readonly accessToken: string | null;
6
+ readonly refreshToken: string | null;
7
7
  readonly getEip712: (address: string) => Promise<GetEIP712MessageResponse>;
8
8
  readonly loginWithSignedMessage: (address: string, signature: string, timestamp: number) => Promise<void>;
9
9
  readonly loginWithPrivyToken: (address: string, appId: string, privyAccessToken: string) => Promise<void>;
10
10
  readonly refreshTokens: () => Promise<import("../types").RefreshTokenResponse>;
11
11
  readonly logout: () => Promise<void>;
12
+ readonly setAddress: (address: string | null) => void;
13
+ readonly address: string | null;
12
14
  };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import React, { ReactNode } from 'react';
2
+ import * as zustand from 'zustand';
2
3
 
3
4
  interface PearHyperliquidContextType {
4
5
  clientId: string;
@@ -781,7 +782,18 @@ interface TokenHistoricalPriceData {
781
782
  oldestTime: number | null;
782
783
  latestTime: number | null;
783
784
  }
784
- declare const useHistoricalPriceDataStore: any;
785
+ interface HistoricalPriceDataState {
786
+ historicalPriceData: Record<string, TokenHistoricalPriceData>;
787
+ loadingTokens: Set<string>;
788
+ addHistoricalPriceData: (symbol: string, interval: CandleInterval, candles: CandleData[], range: HistoricalRange) => void;
789
+ hasHistoricalPriceData: (symbol: string, interval: CandleInterval, startTime: number, endTime: number) => boolean;
790
+ getHistoricalPriceData: (symbol: string, interval: CandleInterval, startTime: number, endTime: number) => CandleData[];
791
+ setTokenLoading: (symbol: string, loading: boolean) => void;
792
+ isTokenLoading: (symbol: string) => boolean;
793
+ removeTokenPriceData: (symbol: string, interval: CandleInterval) => void;
794
+ clearData: () => void;
795
+ }
796
+ declare const useHistoricalPriceDataStore: zustand.UseBoundStore<zustand.StoreApi<HistoricalPriceDataState>>;
785
797
 
786
798
  interface UseHistoricalPriceDataReturn {
787
799
  fetchHistoricalPriceData: (startTime: number, endTime: number, interval: CandleInterval, callback?: (data: Record<string, CandleData[]>) => void) => Promise<Record<string, CandleData[]>>;
@@ -1119,14 +1131,16 @@ declare function usePortfolio(): UsePortfolioResult;
1119
1131
 
1120
1132
  declare function useAuth(): {
1121
1133
  readonly isReady: boolean;
1122
- readonly isAuthenticated: any;
1123
- readonly accessToken: any;
1124
- readonly refreshToken: any;
1134
+ readonly isAuthenticated: boolean;
1135
+ readonly accessToken: string | null;
1136
+ readonly refreshToken: string | null;
1125
1137
  readonly getEip712: (address: string) => Promise<GetEIP712MessageResponse>;
1126
1138
  readonly loginWithSignedMessage: (address: string, signature: string, timestamp: number) => Promise<void>;
1127
1139
  readonly loginWithPrivyToken: (address: string, appId: string, privyAccessToken: string) => Promise<void>;
1128
1140
  readonly refreshTokens: () => Promise<RefreshTokenResponse>;
1129
1141
  readonly logout: () => Promise<void>;
1142
+ readonly setAddress: (address: string | null) => void;
1143
+ readonly address: string | null;
1130
1144
  };
1131
1145
 
1132
1146
  interface UseHyperliquidWebSocketProps {
@@ -1323,7 +1337,14 @@ declare function validatePositionSize(usdValue: number, longAssets?: PairAssetIn
1323
1337
  minimumRequired?: number;
1324
1338
  };
1325
1339
 
1326
- declare const useMarketData: any;
1340
+ interface MarketDataState {
1341
+ marketData: ActiveAssetsResponse | null;
1342
+ marketDataAll: ActiveAssetsAllResponse | null;
1343
+ setMarketData: (value: ActiveAssetsResponse | null) => void;
1344
+ setMarketDataAll: (value: ActiveAssetsAllResponse | null) => void;
1345
+ clean: () => void;
1346
+ }
1347
+ declare const useMarketData: zustand.UseBoundStore<zustand.StoreApi<MarketDataState>>;
1327
1348
 
1328
1349
  export { AccountSummaryCalculator, ConflictDetector, MAX_ASSETS_PER_LEG, MINIMUM_ASSET_USD_VALUE, MaxAssetsPerLegError, MinimumPositionSizeError, PearHyperliquidProvider, TokenMetadataExtractor, adjustAdvancePosition, adjustOrder, adjustPosition, calculateMinimumPositionValue, calculateWeightedRatio, cancelOrder, cancelTwap, cancelTwapOrder, closeAllPositions, closePosition, computeBasketCandles, createCandleLookups, createPosition, getCompleteTimestamps, getPortfolio, mapCandleIntervalToTradingViewInterval, mapTradingViewIntervalToCandleInterval, markNotificationReadById, markNotificationsRead, toggleWatchlist, updateRiskParameters, useAccountSummary, useActiveBaskets, useAgentWallet, useAllBaskets, useAuth, useAutoSyncFills, useBasketCandles, useFindBasket, useHighlightedBaskets, useHistoricalPriceData, useHistoricalPriceDataStore, useHyperliquidNativeWebSocket, useHyperliquidWebSocket, useMarketData, useMarketDataAllPayload, useMarketDataPayload, useNotifications, useOpenOrders, useOrders, usePearHyperliquid, usePerformanceOverlays, usePortfolio, usePosition, useTokenSelectionMetadata, useTopGainers, useTopLosers, useTradeHistories, useTwap, useUserSelection, useWatchlist, useWatchlistBaskets, useWebData, validateMaxAssetsPerLeg, validateMinimumAssetSize, validatePositionSize };
1329
1350
  export type { AccountSummaryResponseDto, ActiveAssetGroupItem, ActiveAssetsResponse, AdjustAdvanceAssetInput, AdjustAdvanceItemInput, AdjustAdvanceResponseDto, AdjustExecutionType, AdjustOrderRequestInput, AdjustOrderResponseDto, AdjustPositionRequestInput, AdjustPositionResponseDto, AgentWalletDto, AgentWalletState, ApiErrorResponse, ApiResponse, AssetCtx, AssetInformationDetail, AssetMarketData, AssetPosition, AutoSyncFillsOptions, AutoSyncFillsState, BalanceSummaryDto, CancelOrderResponseDto, CancelTwapResponseDto, CandleChartData, CandleData, CandleInterval, CandleSnapshotRequest, ClearinghouseState, CloseAllPositionsResponseDto, CloseAllPositionsResultDto, CloseExecutionType, ClosePositionRequestInput, ClosePositionResponseDto, CreatePositionRequestInput, CreatePositionResponseDto, CrossMarginSummaryDto, CumFundingDto, ExecutionType, ExtraAgent, HLWebSocketResponse, HistoricalRange, LadderConfigInput, MarginSummaryDto, NotificationCategory, NotificationDto, OpenLimitOrderDto, OpenPositionDto, OrderAssetDto, OrderStatus, PairAssetDto, PairAssetInput, PerformanceOverlay, PlatformAccountSummaryResponseDto, PortfolioBucketDto, PortfolioInterval, PortfolioIntervalsDto, PortfolioOverallDto, PortfolioResponseDto, PositionAdjustmentType, PositionAssetDetailDto, PositionAssetSummaryDto, PositionResponseStatus, RealtimeBar, RealtimeBarsCallback, ToggleWatchlistResponseDto, TokenConflict, TokenHistoricalPriceData, TokenMetadata, TokenSelection, TpSlThresholdInput, TpSlThresholdType, TradeHistoryAssetDataDto, TradeHistoryDataDto, TwapChunkStatusDto, TwapMonitoringDto, TwapSliceFillResponseItem, UniverseAsset, UpdateRiskParametersRequestInput, UpdateRiskParametersResponseDto, UseAuthOptions, UseBasketCandlesReturn, UseHistoricalPriceDataReturn, UseNotificationsResult, UsePerformanceOverlaysReturn, UsePortfolioResult, UseTokenSelectionMetadataReturn, UserProfile, UserSelectionState, WatchlistItemDto, WebSocketAckResponse, WebSocketChannel, WebSocketConnectionState, WebSocketDataMessage, WebSocketMessage, WebSocketSubscribeMessage, WsAllMidsData };
package/dist/index.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
- import { useState, useRef, useCallback, useEffect, useMemo, useContext, createContext } from 'react';
3
- import { create } from 'zustand';
2
+ import React, { useState, useRef, useCallback, useEffect, useMemo, useContext, createContext } from 'react';
4
3
 
5
4
  // Browser-compatible WebSocket ready state enum (mirrors native values)
6
5
  var ReadyState;
@@ -11,10 +10,52 @@ var ReadyState;
11
10
  ReadyState[ReadyState["CLOSED"] = 3] = "CLOSED";
12
11
  })(ReadyState || (ReadyState = {}));
13
12
 
13
+ const createStoreImpl = (createState) => {
14
+ let state;
15
+ const listeners = /* @__PURE__ */ new Set();
16
+ const setState = (partial, replace) => {
17
+ const nextState = typeof partial === "function" ? partial(state) : partial;
18
+ if (!Object.is(nextState, state)) {
19
+ const previousState = state;
20
+ state = (replace != null ? replace : typeof nextState !== "object" || nextState === null) ? nextState : Object.assign({}, state, nextState);
21
+ listeners.forEach((listener) => listener(state, previousState));
22
+ }
23
+ };
24
+ const getState = () => state;
25
+ const getInitialState = () => initialState;
26
+ const subscribe = (listener) => {
27
+ listeners.add(listener);
28
+ return () => listeners.delete(listener);
29
+ };
30
+ const api = { setState, getState, getInitialState, subscribe };
31
+ const initialState = state = createState(setState, getState, api);
32
+ return api;
33
+ };
34
+ const createStore = ((createState) => createState ? createStoreImpl(createState) : createStoreImpl);
35
+
36
+ const identity = (arg) => arg;
37
+ function useStore(api, selector = identity) {
38
+ const slice = React.useSyncExternalStore(
39
+ api.subscribe,
40
+ React.useCallback(() => selector(api.getState()), [api, selector]),
41
+ React.useCallback(() => selector(api.getInitialState()), [api, selector])
42
+ );
43
+ React.useDebugValue(slice);
44
+ return slice;
45
+ }
46
+ const createImpl = (createState) => {
47
+ const api = createStore(createState);
48
+ const useBoundStore = (selector) => useStore(api, selector);
49
+ Object.assign(useBoundStore, api);
50
+ return useBoundStore;
51
+ };
52
+ const create = ((createState) => createState ? createImpl(createState) : createImpl);
53
+
14
54
  const useUserData = create((set) => ({
15
55
  accessToken: null,
16
56
  refreshToken: null,
17
57
  isAuthenticated: false,
58
+ isReady: false,
18
59
  address: null,
19
60
  tradeHistories: null,
20
61
  rawOpenPositions: null,
@@ -26,17 +67,17 @@ const useUserData = create((set) => ({
26
67
  setAccessToken: (token) => set({ accessToken: token }),
27
68
  setRefreshToken: (token) => set({ refreshToken: token }),
28
69
  setIsAuthenticated: (value) => set({ isAuthenticated: value }),
29
- setAddress: (address) => set(() => {
30
- if (typeof window !== 'undefined') {
31
- if (address) {
32
- window.localStorage.setItem('address', address);
33
- }
34
- else {
35
- window.localStorage.removeItem('address');
36
- }
37
- }
38
- return { address };
39
- }),
70
+ setIsReady: (value) => set({ isReady: value }),
71
+ setAddress: (address) => {
72
+ // if (typeof window !== "undefined") {
73
+ // if (address) {
74
+ // window.localStorage.setItem("address", address);
75
+ // } else {
76
+ // window.localStorage.removeItem("address");
77
+ // }
78
+ // }
79
+ set({ address });
80
+ },
40
81
  setTradeHistories: (value) => set({ tradeHistories: value }),
41
82
  setRawOpenPositions: (value) => set({ rawOpenPositions: value }),
42
83
  setOpenOrders: (value) => set({ openOrders: value }),
@@ -44,10 +85,11 @@ const useUserData = create((set) => ({
44
85
  setTwapDetails: (value) => set({ twapDetails: value }),
45
86
  setNotifications: (value) => set({ notifications: value }),
46
87
  clean: () => set({
47
- accessToken: null,
48
- refreshToken: null,
49
- isAuthenticated: false,
50
- address: null,
88
+ // accessToken: null,
89
+ // refreshToken: null,
90
+ // isAuthenticated: false,
91
+ // isReady: false,
92
+ // address: null,
51
93
  tradeHistories: null,
52
94
  rawOpenPositions: null,
53
95
  openOrders: null,
@@ -625,11 +667,11 @@ const useUserSelection$1 = create((set, get) => ({
625
667
  }));
626
668
 
627
669
  const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
628
- const { setAllMids, setActiveAssetData, upsertActiveAssetData, setCandleData, deleteCandleSymbol, deleteActiveAssetData, addCandleData, setFinalAssetContexts, setFinalAtOICaps, setAggregatedClearingHouseState } = useHyperliquidData();
670
+ const { setAllMids, setActiveAssetData, upsertActiveAssetData, setCandleData, deleteCandleSymbol, deleteActiveAssetData, addCandleData, setFinalAssetContexts, setFinalAtOICaps, setAggregatedClearingHouseState, } = useHyperliquidData();
629
671
  const { candleInterval } = useUserSelection$1();
630
672
  const longTokens = useUserSelection$1((s) => s.longTokens);
631
673
  const shortTokens = useUserSelection$1((s) => s.shortTokens);
632
- const selectedTokenSymbols = useMemo(() => ([...longTokens, ...shortTokens].map((t) => t.symbol)), [longTokens, shortTokens]);
674
+ const selectedTokenSymbols = useMemo(() => [...longTokens, ...shortTokens].map((t) => t.symbol), [longTokens, shortTokens]);
633
675
  const [lastError, setLastError] = useState(null);
634
676
  const [subscribedAddress, setSubscribedAddress] = useState(null);
635
677
  const [subscribedTokens, setSubscribedTokens] = useState([]);
@@ -644,9 +686,9 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
644
686
  try {
645
687
  const message = JSON.parse(event.data);
646
688
  // Handle subscription responses
647
- if ('success' in message || 'error' in message) {
689
+ if ("success" in message || "error" in message) {
648
690
  if (message.error) {
649
- console.error('[HyperLiquid WS] Subscription error:', message.error);
691
+ console.error("[HyperLiquid WS] Subscription error:", message.error);
650
692
  setLastError(message.error);
651
693
  }
652
694
  else {
@@ -655,30 +697,30 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
655
697
  return;
656
698
  }
657
699
  // Handle channel data messages
658
- if ('channel' in message && 'data' in message) {
700
+ if ("channel" in message && "data" in message) {
659
701
  const response = message;
660
702
  switch (response.channel) {
661
- case 'webData3':
703
+ case "webData3":
662
704
  const webData3 = response.data;
663
705
  // finalAssetContexts now sourced from allDexsAssetCtxs channel
664
706
  const finalAtOICaps = webData3.perpDexStates.flatMap((dex) => dex.perpsAtOpenInterestCap);
665
707
  setFinalAtOICaps(finalAtOICaps);
666
708
  break;
667
- case 'allDexsAssetCtxs':
709
+ case "allDexsAssetCtxs":
668
710
  {
669
711
  const data = response.data;
670
712
  const finalAssetContexts = (data.ctxs || []).flatMap(([, ctxs]) => ctxs || []);
671
713
  setFinalAssetContexts(finalAssetContexts);
672
714
  }
673
715
  break;
674
- case 'allDexsClearinghouseState':
716
+ case "allDexsClearinghouseState":
675
717
  {
676
718
  const data = response.data;
677
719
  const states = (data.clearinghouseStates || [])
678
720
  .map(([, s]) => s)
679
721
  .filter(Boolean);
680
- const sum = (values) => values.reduce((acc, v) => acc + (parseFloat(v || '0') || 0), 0);
681
- const toStr = (n) => (Number.isFinite(n) ? n.toString() : '0');
722
+ const sum = (values) => values.reduce((acc, v) => acc + (parseFloat(v || "0") || 0), 0);
723
+ const toStr = (n) => Number.isFinite(n) ? n.toString() : "0";
682
724
  const assetPositions = states.flatMap((s) => s.assetPositions || []);
683
725
  const crossMaintenanceMarginUsed = toStr(sum(states.map((s) => s.crossMaintenanceMarginUsed)));
684
726
  const crossMarginSummary = {
@@ -706,29 +748,34 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
706
748
  setAggregatedClearingHouseState(aggregatedClearingHouseState);
707
749
  }
708
750
  break;
709
- case 'allMids':
751
+ case "allMids":
710
752
  {
711
753
  const data = response.data;
712
754
  const remapped = {
713
755
  mids: Object.fromEntries(
714
756
  // only support non hip-3 and xyz market
715
- Object.entries(data.mids || {}).filter(([k, v]) => !k.includes(':') || k.includes('xyz:')).map(([k, v]) => [toDisplaySymbol(k), v]))
757
+ Object.entries(data.mids || {})
758
+ .filter(([k, v]) => !k.includes(":") || k.includes("xyz:"))
759
+ .map(([k, v]) => [toDisplaySymbol(k), v])),
716
760
  };
717
761
  setAllMids(remapped);
718
762
  }
719
763
  break;
720
- case 'activeAssetData':
764
+ case "activeAssetData":
721
765
  {
722
766
  const assetData = response.data;
723
767
  const symbol = toDisplaySymbol(assetData.coin);
724
- const normalized = { ...assetData, coin: symbol };
768
+ const normalized = {
769
+ ...assetData,
770
+ coin: symbol,
771
+ };
725
772
  upsertActiveAssetData(symbol, normalized);
726
773
  }
727
774
  break;
728
- case 'candle':
775
+ case "candle":
729
776
  {
730
777
  const candleDataItem = response.data;
731
- const symbol = toDisplaySymbol(candleDataItem.s || '');
778
+ const symbol = toDisplaySymbol(candleDataItem.s || "");
732
779
  const normalized = { ...candleDataItem, s: symbol };
733
780
  addCandleData(symbol, normalized);
734
781
  }
@@ -740,10 +787,17 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
740
787
  }
741
788
  catch (error) {
742
789
  const errorMessage = `Failed to parse message: ${error instanceof Error ? error.message : String(error)}`;
743
- console.error('[HyperLiquid WS] Parse error:', errorMessage, 'Raw message:', event.data);
790
+ console.error("[HyperLiquid WS] Parse error:", errorMessage, "Raw message:", event.data);
744
791
  setLastError(errorMessage);
745
792
  }
746
- }, [setAllMids, upsertActiveAssetData, addCandleData, setFinalAssetContexts, setFinalAtOICaps, setAggregatedClearingHouseState]);
793
+ }, [
794
+ setAllMids,
795
+ upsertActiveAssetData,
796
+ addCandleData,
797
+ setFinalAssetContexts,
798
+ setFinalAtOICaps,
799
+ setAggregatedClearingHouseState,
800
+ ]);
747
801
  const connect = useCallback(() => {
748
802
  if (!enabled)
749
803
  return;
@@ -756,7 +810,7 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
756
810
  }
757
811
  manualCloseRef.current = false;
758
812
  setReadyState(ReadyState.CONNECTING);
759
- const ws = new WebSocket('wss://api.hyperliquid.xyz/ws');
813
+ const ws = new WebSocket("wss://api.hyperliquid.xyz/ws");
760
814
  wsRef.current = ws;
761
815
  ws.onopen = () => {
762
816
  reconnectAttemptsRef.current = 0;
@@ -765,15 +819,15 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
765
819
  };
766
820
  ws.onmessage = handleMessage;
767
821
  ws.onerror = (event) => {
768
- console.error('[HyperLiquid WS] Connection error:', event);
769
- setLastError('WebSocket error');
822
+ console.error("[HyperLiquid WS] Connection error:", event);
823
+ setLastError("WebSocket error");
770
824
  };
771
825
  ws.onclose = () => {
772
826
  setReadyState(ReadyState.CLOSED);
773
827
  if (!manualCloseRef.current && reconnectAttemptsRef.current < 5) {
774
828
  reconnectAttemptsRef.current += 1;
775
829
  if (reconnectAttemptsRef.current === 5) {
776
- console.error('[HyperLiquid WS] Reconnection stopped after 5 attempts');
830
+ console.error("[HyperLiquid WS] Reconnection stopped after 5 attempts");
777
831
  }
778
832
  setTimeout(() => connect(), 3000);
779
833
  }
@@ -807,7 +861,7 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
807
861
  if (isConnected) {
808
862
  // Send ping every 30 seconds
809
863
  pingIntervalRef.current = setInterval(() => {
810
- sendJsonMessage({ method: 'ping' });
864
+ sendJsonMessage({ method: "ping" });
811
865
  }, 30000);
812
866
  }
813
867
  else {
@@ -827,57 +881,57 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
827
881
  useEffect(() => {
828
882
  if (!isConnected)
829
883
  return;
830
- const DEFAULT_ADDRESS = '0x0000000000000000000000000000000000000000';
884
+ const DEFAULT_ADDRESS = "0x0000000000000000000000000000000000000000";
831
885
  const userAddress = address || DEFAULT_ADDRESS;
832
886
  if (subscribedAddress === userAddress)
833
887
  return;
834
888
  // Unsubscribe from previous address if exists
835
889
  if (subscribedAddress) {
836
890
  const unsubscribeMessage = {
837
- method: 'unsubscribe',
891
+ method: "unsubscribe",
838
892
  subscription: {
839
- type: 'webData3',
893
+ type: "webData3",
840
894
  user: subscribedAddress,
841
895
  },
842
896
  };
843
897
  sendJsonMessage(unsubscribeMessage);
844
898
  const unsubscribeAllDexsClearinghouseState = {
845
- method: 'unsubscribe',
899
+ method: "unsubscribe",
846
900
  subscription: {
847
- type: 'allDexsClearinghouseState',
901
+ type: "allDexsClearinghouseState",
848
902
  user: subscribedAddress,
849
903
  },
850
904
  };
851
905
  sendJsonMessage(unsubscribeAllDexsClearinghouseState);
852
906
  }
853
907
  const subscribeWebData3 = {
854
- method: 'subscribe',
908
+ method: "subscribe",
855
909
  subscription: {
856
- type: 'webData3',
910
+ type: "webData3",
857
911
  user: userAddress,
858
912
  },
859
913
  };
860
914
  // Subscribe to allDexsClearinghouseState with the same payload as webData3
861
915
  const subscribeAllDexsClearinghouseState = {
862
- method: 'subscribe',
916
+ method: "subscribe",
863
917
  subscription: {
864
- type: 'allDexsClearinghouseState',
918
+ type: "allDexsClearinghouseState",
865
919
  user: userAddress,
866
920
  },
867
921
  };
868
922
  // Subscribe to allMids
869
923
  const subscribeAllMids = {
870
- method: 'subscribe',
924
+ method: "subscribe",
871
925
  subscription: {
872
- type: 'allMids',
873
- dex: 'ALL_DEXS',
926
+ type: "allMids",
927
+ dex: "ALL_DEXS",
874
928
  },
875
929
  };
876
930
  // Subscribe to allDexsAssetCtxs (no payload params, global feed)
877
931
  const subscribeAllDexsAssetCtxs = {
878
- method: 'subscribe',
932
+ method: "subscribe",
879
933
  subscription: {
880
- type: 'allDexsAssetCtxs',
934
+ type: "allDexsAssetCtxs",
881
935
  },
882
936
  };
883
937
  sendJsonMessage(subscribeWebData3);
@@ -890,7 +944,13 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
890
944
  // clear aggregatedClearingHouseState
891
945
  setAggregatedClearingHouseState(null);
892
946
  }
893
- }, [isConnected, address, subscribedAddress, sendJsonMessage, setAggregatedClearingHouseState]);
947
+ }, [
948
+ isConnected,
949
+ address,
950
+ subscribedAddress,
951
+ sendJsonMessage,
952
+ setAggregatedClearingHouseState,
953
+ ]);
894
954
  // Handle token subscriptions for activeAssetData
895
955
  useEffect(() => {
896
956
  if (!isConnected || !address)
@@ -899,11 +959,11 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
899
959
  const tokensToSubscribe = effectiveTokens.filter((token) => token && !subscribedTokens.includes(token));
900
960
  const tokensToUnsubscribe = subscribedTokens.filter((token) => !effectiveTokens.includes(token));
901
961
  // Unsubscribe from tokens no longer in the list
902
- tokensToUnsubscribe.forEach(token => {
962
+ tokensToUnsubscribe.forEach((token) => {
903
963
  const unsubscribeMessage = {
904
- method: 'unsubscribe',
964
+ method: "unsubscribe",
905
965
  subscription: {
906
- type: 'activeAssetData',
966
+ type: "activeAssetData",
907
967
  user: address,
908
968
  coin: token,
909
969
  },
@@ -911,11 +971,11 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
911
971
  sendJsonMessage(unsubscribeMessage);
912
972
  });
913
973
  // Subscribe to new tokens
914
- tokensToSubscribe.forEach(token => {
974
+ tokensToSubscribe.forEach((token) => {
915
975
  const subscribeMessage = {
916
- method: 'subscribe',
976
+ method: "subscribe",
917
977
  subscription: {
918
- type: 'activeAssetData',
978
+ type: "activeAssetData",
919
979
  user: address,
920
980
  coin: token,
921
981
  },
@@ -926,7 +986,14 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
926
986
  setSubscribedTokens(effectiveTokens.filter((token) => token));
927
987
  tokensToSubscribe.forEach((token) => deleteActiveAssetData(token));
928
988
  }
929
- }, [isConnected, address, selectedTokenSymbols, subscribedTokens, sendJsonMessage, setActiveAssetData]);
989
+ }, [
990
+ isConnected,
991
+ address,
992
+ selectedTokenSymbols,
993
+ subscribedTokens,
994
+ sendJsonMessage,
995
+ setActiveAssetData,
996
+ ]);
930
997
  // Handle candle subscriptions for tokens and interval changes
931
998
  useEffect(() => {
932
999
  if (!isConnected)
@@ -935,11 +1002,11 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
935
1002
  // Unsubscribe from previous candle subscriptions if interval changed
936
1003
  const prevInterval = prevCandleIntervalRef.current;
937
1004
  if (prevInterval && prevInterval !== candleInterval) {
938
- subscribedCandleTokens.forEach(token => {
1005
+ subscribedCandleTokens.forEach((token) => {
939
1006
  const unsubscribeMessage = {
940
- method: 'unsubscribe',
1007
+ method: "unsubscribe",
941
1008
  subscription: {
942
- type: 'candle',
1009
+ type: "candle",
943
1010
  coin: token,
944
1011
  interval: prevInterval,
945
1012
  },
@@ -954,9 +1021,9 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
954
1021
  // Unsubscribe from tokens no longer in the list
955
1022
  tokensToUnsubscribe.forEach((token) => {
956
1023
  const unsubscribeMessage = {
957
- method: 'unsubscribe',
1024
+ method: "unsubscribe",
958
1025
  subscription: {
959
- type: 'candle',
1026
+ type: "candle",
960
1027
  coin: token,
961
1028
  interval: candleInterval,
962
1029
  },
@@ -966,9 +1033,9 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
966
1033
  // Subscribe to new tokens
967
1034
  tokensToSubscribe.forEach((token) => {
968
1035
  const subscribeMessage = {
969
- method: 'subscribe',
1036
+ method: "subscribe",
970
1037
  subscription: {
971
- type: 'candle',
1038
+ type: "candle",
972
1039
  coin: token,
973
1040
  interval: candleInterval,
974
1041
  },
@@ -976,12 +1043,21 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
976
1043
  sendJsonMessage(subscribeMessage);
977
1044
  });
978
1045
  // Update subscribed state
979
- if (tokensToSubscribe.length > 0 || tokensToUnsubscribe.length > 0 || prevInterval !== candleInterval) {
1046
+ if (tokensToSubscribe.length > 0 ||
1047
+ tokensToUnsubscribe.length > 0 ||
1048
+ prevInterval !== candleInterval) {
980
1049
  setSubscribedCandleTokens(effectiveTokens.filter((token) => token));
981
1050
  prevCandleIntervalRef.current = candleInterval;
982
1051
  tokensToUnsubscribe.forEach((token) => deleteCandleSymbol(token));
983
1052
  }
984
- }, [isConnected, selectedTokenSymbols, candleInterval, subscribedCandleTokens, sendJsonMessage, setCandleData]);
1053
+ }, [
1054
+ isConnected,
1055
+ selectedTokenSymbols,
1056
+ candleInterval,
1057
+ subscribedCandleTokens,
1058
+ sendJsonMessage,
1059
+ setCandleData,
1060
+ ]);
985
1061
  return {
986
1062
  isConnected,
987
1063
  lastError,
@@ -7077,38 +7153,47 @@ async function logout(baseUrl, refreshTokenVal) {
7077
7153
  function useAuth() {
7078
7154
  const context = useContext(PearHyperliquidContext);
7079
7155
  if (!context) {
7080
- throw new Error("usePortfolio must be used within a PearHyperliquidProvider");
7156
+ throw new Error("useAuth must be used within a PearHyperliquidProvider");
7081
7157
  }
7082
7158
  const { apiBaseUrl, clientId } = context;
7083
- const [isReady, setIsReady] = useState(false);
7084
7159
  const accessToken = useUserData((s) => s.accessToken);
7085
7160
  const refreshToken$1 = useUserData((s) => s.refreshToken);
7161
+ const isReady = useUserData((s) => s.isReady);
7162
+ const isAuthenticated = useUserData((s) => s.isAuthenticated);
7163
+ const address = useUserData((s) => s.address);
7086
7164
  const setAccessToken = useUserData((s) => s.setAccessToken);
7087
7165
  const setRefreshToken = useUserData((s) => s.setRefreshToken);
7088
- const isAuthenticated = useUserData((s) => s.isAuthenticated);
7166
+ const setIsReady = useUserData((s) => s.setIsReady);
7089
7167
  const setIsAuthenticated = useUserData((s) => s.setIsAuthenticated);
7090
7168
  const setAddress = useUserData((s) => s.setAddress);
7169
+ console.log("sdk", { sdkAddress: address });
7091
7170
  useEffect(() => {
7092
7171
  if (typeof window == "undefined") {
7093
7172
  return;
7094
7173
  }
7095
- const access = localStorage.getItem("accessToken");
7096
- const refresh = localStorage.getItem("refreshToken");
7097
- const addr = localStorage.getItem("address");
7098
- setAccessToken(access);
7099
- setRefreshToken(refresh);
7100
- setAddress(addr);
7101
- const authed = Boolean(access && addr);
7102
- setIsAuthenticated(authed);
7174
+ if (address) {
7175
+ // If we already have an address in state, use it to load the session
7176
+ const accessTokenKey = `${address}_accessToken`;
7177
+ const refreshTokenKey = `${address}_refreshToken`;
7178
+ const storedAccessToken = localStorage.getItem(accessTokenKey);
7179
+ const storedRefreshToken = localStorage.getItem(refreshTokenKey);
7180
+ console.log({ storedAccessToken, storedRefreshToken });
7181
+ if (storedAccessToken && storedRefreshToken) {
7182
+ setAccessToken(storedAccessToken);
7183
+ setRefreshToken(storedRefreshToken);
7184
+ setIsAuthenticated(true);
7185
+ }
7186
+ }
7103
7187
  setIsReady(true);
7104
- }, [setAccessToken, setRefreshToken, setIsAuthenticated, setAddress]);
7188
+ }, [address]);
7105
7189
  useEffect(() => {
7106
7190
  const cleanup = addAuthInterceptors({
7107
7191
  apiBaseUrl,
7108
7192
  getAccessToken: () => {
7109
- return typeof window !== "undefined"
7110
- ? window.localStorage.getItem("accessToken")
7111
- : null;
7193
+ if (typeof window === "undefined")
7194
+ return null;
7195
+ // Read from Zustand state as single source of truth
7196
+ return useUserData.getState().accessToken;
7112
7197
  },
7113
7198
  refreshTokens: async () => {
7114
7199
  const data = await refreshTokens();
@@ -7134,12 +7219,13 @@ function useAuth() {
7134
7219
  clientId,
7135
7220
  details: { signature, timestamp },
7136
7221
  });
7137
- window.localStorage.setItem("accessToken", data.accessToken);
7138
- window.localStorage.setItem("refreshToken", data.refreshToken);
7139
- window.localStorage.setItem("address", address);
7222
+ const accessTokenKey = `${address}_accessToken`;
7223
+ const refreshTokenKey = `${address}_refreshToken`;
7224
+ window.localStorage.setItem(accessTokenKey, data.accessToken);
7225
+ window.localStorage.setItem(refreshTokenKey, data.refreshToken);
7140
7226
  setAccessToken(data.accessToken);
7141
7227
  setRefreshToken(data.refreshToken);
7142
- setAddress(address);
7228
+ // setAddress(address);
7143
7229
  setIsAuthenticated(true);
7144
7230
  }
7145
7231
  catch (e) {
@@ -7154,12 +7240,13 @@ function useAuth() {
7154
7240
  appId,
7155
7241
  accessToken: privyAccessToken,
7156
7242
  });
7157
- window.localStorage.setItem("accessToken", data.accessToken);
7158
- window.localStorage.setItem("refreshToken", data.refreshToken);
7159
- window.localStorage.setItem("address", address);
7243
+ const accessTokenKey = `${address}_accessToken`;
7244
+ const refreshTokenKey = `${address}_refreshToken`;
7245
+ window.localStorage.setItem(accessTokenKey, data.accessToken);
7246
+ window.localStorage.setItem(refreshTokenKey, data.refreshToken);
7160
7247
  setAccessToken(data.accessToken);
7161
7248
  setRefreshToken(data.refreshToken);
7162
- setAddress(address);
7249
+ // setAddress(address);
7163
7250
  setIsAuthenticated(true);
7164
7251
  }
7165
7252
  catch (e) {
@@ -7167,33 +7254,41 @@ function useAuth() {
7167
7254
  }
7168
7255
  }
7169
7256
  async function refreshTokens() {
7170
- const refresh = window.localStorage.getItem("refreshToken");
7171
- if (!refresh)
7257
+ const currentAddress = address;
7258
+ const currentRefresh = refreshToken$1;
7259
+ if (!currentRefresh || !currentAddress)
7172
7260
  throw new Error("No refresh token");
7173
- const { data } = await refreshToken(apiBaseUrl, refresh);
7174
- window.localStorage.setItem("accessToken", data.accessToken);
7175
- window.localStorage.setItem("refreshToken", data.refreshToken);
7261
+ const { data } = await refreshToken(apiBaseUrl, currentRefresh);
7262
+ // Update tokens in localStorage
7263
+ const accessTokenKey = `${currentAddress}_accessToken`;
7264
+ const refreshTokenKey = `${currentAddress}_refreshToken`;
7265
+ window.localStorage.setItem(accessTokenKey, data.accessToken);
7266
+ window.localStorage.setItem(refreshTokenKey, data.refreshToken);
7176
7267
  setAccessToken(data.accessToken);
7177
7268
  setRefreshToken(data.refreshToken);
7178
7269
  setIsAuthenticated(true);
7179
7270
  return data;
7180
7271
  }
7181
7272
  async function logout$1() {
7182
- const refresh = window.localStorage.getItem("refreshToken");
7183
- if (refresh) {
7273
+ const currentAddress = address;
7274
+ const currentRefresh = refreshToken$1;
7275
+ if (currentRefresh) {
7184
7276
  try {
7185
- await logout(apiBaseUrl, refresh);
7277
+ await logout(apiBaseUrl, currentRefresh);
7186
7278
  }
7187
7279
  catch (_a) {
7188
7280
  /* ignore */
7189
7281
  }
7190
7282
  }
7191
- window.localStorage.removeItem("accessToken");
7192
- window.localStorage.removeItem("refreshToken");
7193
- window.localStorage.removeItem("address");
7283
+ if (currentAddress) {
7284
+ const accessTokenKey = `${currentAddress}_accessToken`;
7285
+ const refreshTokenKey = `${currentAddress}_refreshToken`;
7286
+ window.localStorage.removeItem(accessTokenKey);
7287
+ window.localStorage.removeItem(refreshTokenKey);
7288
+ }
7194
7289
  setAccessToken(null);
7195
7290
  setRefreshToken(null);
7196
- setAddress(null);
7291
+ // setAddress(null);
7197
7292
  setIsAuthenticated(false);
7198
7293
  }
7199
7294
  return {
@@ -7206,6 +7301,8 @@ function useAuth() {
7206
7301
  loginWithPrivyToken,
7207
7302
  refreshTokens,
7208
7303
  logout: logout$1,
7304
+ setAddress,
7305
+ address,
7209
7306
  };
7210
7307
  }
7211
7308
 
@@ -7215,7 +7312,6 @@ const PearHyperliquidContext = createContext(undefined);
7215
7312
  */
7216
7313
  const PearHyperliquidProvider = ({ children, apiBaseUrl = "https://hl-ui.pearprotocol.io", clientId = "PEARPROTOCOLUI", wsUrl = "wss://hl-ui.pearprotocol.io/ws", }) => {
7217
7314
  const address = useUserData((s) => s.address);
7218
- const setAddress = useUserData((s) => s.setAddress);
7219
7315
  const perpsMetaAssets = useHyperliquidData((state) => state.perpMetaAssets);
7220
7316
  const setPerpMetaAssets = useHyperliquidData((state) => state.setPerpMetaAssets);
7221
7317
  const setHip3DisplayToFull = useHyperliquidData((state) => state.setHip3DisplayToFull);
@@ -7280,8 +7376,6 @@ const PearHyperliquidProvider = ({ children, apiBaseUrl = "https://hl-ui.pearpro
7280
7376
  }), [
7281
7377
  apiBaseUrl,
7282
7378
  wsUrl,
7283
- address,
7284
- setAddress,
7285
7379
  isConnected,
7286
7380
  lastError,
7287
7381
  nativeIsConnected,
@@ -10,5 +10,16 @@ interface TokenHistoricalPriceData {
10
10
  oldestTime: number | null;
11
11
  latestTime: number | null;
12
12
  }
13
- export declare const useHistoricalPriceDataStore: any;
13
+ interface HistoricalPriceDataState {
14
+ historicalPriceData: Record<string, TokenHistoricalPriceData>;
15
+ loadingTokens: Set<string>;
16
+ addHistoricalPriceData: (symbol: string, interval: CandleInterval, candles: CandleData[], range: HistoricalRange) => void;
17
+ hasHistoricalPriceData: (symbol: string, interval: CandleInterval, startTime: number, endTime: number) => boolean;
18
+ getHistoricalPriceData: (symbol: string, interval: CandleInterval, startTime: number, endTime: number) => CandleData[];
19
+ setTokenLoading: (symbol: string, loading: boolean) => void;
20
+ isTokenLoading: (symbol: string) => boolean;
21
+ removeTokenPriceData: (symbol: string, interval: CandleInterval) => void;
22
+ clearData: () => void;
23
+ }
24
+ export declare const useHistoricalPriceDataStore: import("zustand").UseBoundStore<import("zustand").StoreApi<HistoricalPriceDataState>>;
14
25
  export type { HistoricalRange, TokenHistoricalPriceData };
@@ -1 +1,25 @@
1
- export declare const useHyperliquidData: any;
1
+ import { ActiveAssetData, CandleChartData, CandleData, ClearinghouseState, UniverseAsset, WebData3AssetCtx, WsAllMidsData } from "../types";
2
+ interface HyperliquidDataState {
3
+ allMids: WsAllMidsData | null;
4
+ activeAssetData: Record<string, ActiveAssetData> | null;
5
+ candleData: CandleChartData | null;
6
+ finalAssetContexts: WebData3AssetCtx[] | null;
7
+ finalAtOICaps: string[] | null;
8
+ aggregatedClearingHouseState: ClearinghouseState | null;
9
+ perpMetaAssets: UniverseAsset[] | null;
10
+ hip3DisplayToFull: Map<string, string>;
11
+ setAllMids: (value: WsAllMidsData | null) => void;
12
+ setActiveAssetData: (value: Record<string, ActiveAssetData> | null | ((prev: Record<string, ActiveAssetData> | null) => Record<string, ActiveAssetData> | null)) => void;
13
+ deleteActiveAssetData: (key: string) => void;
14
+ addCandleData: (symbol: string, candle: CandleData) => void;
15
+ deleteCandleSymbol: (symbol: string) => void;
16
+ setCandleData: (value: CandleChartData | null) => void;
17
+ upsertActiveAssetData: (key: string, value: ActiveAssetData) => void;
18
+ setFinalAssetContexts: (value: WebData3AssetCtx[] | null) => void;
19
+ setFinalAtOICaps: (value: string[] | null) => void;
20
+ setAggregatedClearingHouseState: (value: ClearinghouseState | null) => void;
21
+ setPerpMetaAssets: (value: UniverseAsset[] | null) => void;
22
+ setHip3DisplayToFull: (value: Map<string, string>) => void;
23
+ }
24
+ export declare const useHyperliquidData: import("zustand").UseBoundStore<import("zustand").StoreApi<HyperliquidDataState>>;
25
+ export {};
@@ -1 +1,10 @@
1
- export declare const useMarketData: any;
1
+ import type { ActiveAssetsAllResponse, ActiveAssetsResponse } from '../types';
2
+ interface MarketDataState {
3
+ marketData: ActiveAssetsResponse | null;
4
+ marketDataAll: ActiveAssetsAllResponse | null;
5
+ setMarketData: (value: ActiveAssetsResponse | null) => void;
6
+ setMarketDataAll: (value: ActiveAssetsAllResponse | null) => void;
7
+ clean: () => void;
8
+ }
9
+ export declare const useMarketData: import("zustand").UseBoundStore<import("zustand").StoreApi<MarketDataState>>;
10
+ export {};
@@ -24,4 +24,4 @@ export interface TokenSelectionMetadataState {
24
24
  shortTokens: TokenSelection[];
25
25
  }) => void;
26
26
  }
27
- export declare const useTokenSelectionMetadataStore: any;
27
+ export declare const useTokenSelectionMetadataStore: import("zustand").UseBoundStore<import("zustand").StoreApi<TokenSelectionMetadataState>>;
@@ -1 +1,30 @@
1
- export declare const useUserData: any;
1
+ import { PlatformAccountSummaryResponseDto, OpenLimitOrderDto, RawPositionDto, TradeHistoryDataDto, TwapMonitoringDto, NotificationDto, ExtraAgent } from "../types";
2
+ interface UserDataState {
3
+ accessToken: string | null;
4
+ refreshToken: string | null;
5
+ isAuthenticated: boolean;
6
+ isReady: boolean;
7
+ address: string | null;
8
+ tradeHistories: TradeHistoryDataDto[] | null;
9
+ rawOpenPositions: RawPositionDto[] | null;
10
+ openOrders: OpenLimitOrderDto[] | null;
11
+ accountSummary: PlatformAccountSummaryResponseDto | null;
12
+ twapDetails: TwapMonitoringDto[] | null;
13
+ notifications: NotificationDto[] | null;
14
+ userExtraAgents: ExtraAgent[] | null;
15
+ setAccessToken: (token: string | null) => void;
16
+ setRefreshToken: (token: string | null) => void;
17
+ setIsAuthenticated: (value: boolean) => void;
18
+ setIsReady: (value: boolean) => void;
19
+ setAddress: (address: string | null) => void;
20
+ setTradeHistories: (value: TradeHistoryDataDto[] | null) => void;
21
+ setRawOpenPositions: (value: RawPositionDto[] | null) => void;
22
+ setOpenOrders: (value: OpenLimitOrderDto[] | null) => void;
23
+ setAccountSummary: (value: PlatformAccountSummaryResponseDto | null) => void;
24
+ setUserExtraAgents: (value: ExtraAgent[] | null) => void;
25
+ setTwapDetails: (value: TwapMonitoringDto[] | null) => void;
26
+ setNotifications: (value: NotificationDto[] | null) => void;
27
+ clean: () => void;
28
+ }
29
+ export declare const useUserData: import("zustand").UseBoundStore<import("zustand").StoreApi<UserDataState>>;
30
+ export {};
@@ -23,5 +23,5 @@ interface UserSelectionState {
23
23
  setTokenSelections: (longTokens: TokenSelection[], shortTokens: TokenSelection[]) => void;
24
24
  resetToDefaults: () => void;
25
25
  }
26
- export declare const useUserSelection: any;
26
+ export declare const useUserSelection: import("zustand").UseBoundStore<import("zustand").StoreApi<UserSelectionState>>;
27
27
  export type { UserSelectionState };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pear-protocol/hyperliquid-sdk",
3
- "version": "0.0.67",
3
+ "version": "0.0.68-beta",
4
4
  "description": "React SDK for Pear Protocol Hyperliquid API integration",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -24,7 +24,8 @@
24
24
  "clean": "rimraf dist"
25
25
  },
26
26
  "dependencies": {
27
- "axios": "^1.6.0"
27
+ "axios": "^1.6.0",
28
+ "zustand": "^5.0.8"
28
29
  },
29
30
  "peerDependencies": {
30
31
  "react": "^18.0.0",