@pear-protocol/hyperliquid-sdk 0.0.60-beta-usdh-2 → 0.0.60-beta.10

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.
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 }),
@@ -47,6 +88,7 @@ const useUserData = create((set) => ({
47
88
  accessToken: null,
48
89
  refreshToken: null,
49
90
  isAuthenticated: false,
91
+ isReady: false,
50
92
  address: null,
51
93
  tradeHistories: null,
52
94
  rawOpenPositions: null,
@@ -71,71 +113,18 @@ const useMarketData = create((set) => ({
71
113
  * Convert a full/prefixed symbol (e.g., "xyz:XYZ100") to a display symbol (e.g., "XYZ100").
72
114
  */
73
115
  function toDisplaySymbol(symbol) {
74
- const parts = symbol.split(':');
116
+ const parts = symbol.split(":");
75
117
  return parts.length > 1 ? parts.slice(-1)[0] : symbol;
76
118
  }
77
119
  /**
78
120
  * Convert a display symbol back to backend form using a provided map.
79
121
  * If mapping is missing, returns the original symbol.
80
- * For multi-market assets, returns the first available market.
81
- * @param displaySymbol e.g., "TSLA"
82
- * @param hip3Assets map of display -> all full market names (e.g., "TSLA" -> ["xyz:TSLA", "flx:TSLA"])
122
+ * @param displaySymbol e.g., "XYZ100"
123
+ * @param displayToFull map of display -> full (e.g., "XYZ100" -> "xyz:XYZ100")
83
124
  */
84
- function toBackendSymbol(displaySymbol, hip3Assets) {
85
- const markets = hip3Assets.get(displaySymbol);
86
- // Return first market if available, otherwise return original symbol
87
- return markets && markets.length > 0 ? markets[0] : displaySymbol;
88
- }
89
- /**
90
- * Convert a display symbol to backend form for a specific market prefix.
91
- * This is useful when an asset is available on multiple markets (e.g., xyz:TSLA and flx:TSLA).
92
- * @param displaySymbol e.g., "TSLA"
93
- * @param marketPrefix e.g., "xyz" or "flx"
94
- * @param hip3Assets map of display -> all full market names
95
- * @returns Full market name if found, null if prefix not specified for multi-market asset, otherwise displaySymbol with prefix
96
- */
97
- function toBackendSymbolWithMarket(displaySymbol, marketPrefix, hip3Assets) {
98
- const availableMarkets = hip3Assets.get(displaySymbol);
99
- if (!availableMarkets || availableMarkets.length === 0) {
100
- // Not a HIP-3 asset, return as-is or with prefix if provided
101
- return marketPrefix ? `${marketPrefix}:${displaySymbol}` : displaySymbol;
102
- }
103
- if (marketPrefix) {
104
- // Find the market with the specified prefix
105
- const targetMarket = availableMarkets.find((market) => market.toLowerCase().startsWith(`${marketPrefix.toLowerCase()}:`));
106
- if (targetMarket) {
107
- return targetMarket;
108
- }
109
- }
110
- // No prefix specified or not found, return null to force explicit market selection
111
- return null;
112
- }
113
- /**
114
- * Get all available markets for a display symbol.
115
- * @param displaySymbol e.g., "TSLA"
116
- * @param hip3Assets map of display -> all full market names
117
- * @returns Array of full market names, e.g., ["xyz:TSLA", "flx:TSLA"]
118
- */
119
- function getAvailableMarkets(displaySymbol, hip3Assets) {
125
+ function toBackendSymbol(displaySymbol, displayToFull) {
120
126
  var _a;
121
- return (_a = hip3Assets.get(displaySymbol)) !== null && _a !== void 0 ? _a : [];
122
- }
123
- /**
124
- * Extract the market prefix from a full market name.
125
- * @param fullSymbol e.g., "xyz:TSLA"
126
- * @returns The prefix (e.g., "xyz") or undefined if no prefix
127
- */
128
- function getMarketPrefix(fullSymbol) {
129
- const parts = fullSymbol.split(':');
130
- return parts.length > 1 ? parts[0] : undefined;
131
- }
132
- /**
133
- * Check if a symbol is a HIP-3 market (has a prefix).
134
- * @param symbol e.g., "xyz:TSLA" or "TSLA"
135
- * @returns true if the symbol has a market prefix
136
- */
137
- function isHip3Market(symbol) {
138
- return symbol.includes(':');
127
+ return (_a = displayToFull.get(displaySymbol)) !== null && _a !== void 0 ? _a : displaySymbol;
139
128
  }
140
129
 
141
130
  const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
@@ -371,11 +360,10 @@ const useHyperliquidData = create((set, get) => ({
371
360
  finalAtOICaps: null,
372
361
  aggregatedClearingHouseState: null,
373
362
  perpMetaAssets: null,
374
- hip3Assets: new Map(),
375
- hip3MarketPrefixes: new Map(),
363
+ hip3DisplayToFull: new Map(),
376
364
  setAllMids: (value) => set({ allMids: value }),
377
365
  setActiveAssetData: (value) => set((state) => ({
378
- activeAssetData: typeof value === 'function' ? value(state.activeAssetData) : value,
366
+ activeAssetData: typeof value === 'function' ? value(state.activeAssetData) : value
379
367
  })),
380
368
  deleteActiveAssetData: (key) => {
381
369
  set((state) => {
@@ -410,14 +398,13 @@ const useHyperliquidData = create((set, get) => ({
410
398
  activeAssetData: {
411
399
  ...state.activeAssetData,
412
400
  [key]: value,
413
- },
401
+ }
414
402
  })),
415
403
  setFinalAssetContexts: (value) => set({ finalAssetContexts: value }),
416
404
  setFinalAtOICaps: (value) => set({ finalAtOICaps: value }),
417
405
  setAggregatedClearingHouseState: (value) => set({ aggregatedClearingHouseState: value }),
418
406
  setPerpMetaAssets: (value) => set({ perpMetaAssets: value }),
419
- setHip3Assets: (value) => set({ hip3Assets: value }),
420
- setHip3MarketPrefixes: (value) => set({ hip3MarketPrefixes: value }),
407
+ setHip3DisplayToFull: (value) => set({ hip3DisplayToFull: value })
421
408
  }));
422
409
 
423
410
  const DEFAULT_STATE = {
@@ -558,11 +545,11 @@ const useUserSelection$1 = create((set, get) => ({
558
545
  }));
559
546
 
560
547
  const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
561
- const { setAllMids, setActiveAssetData, upsertActiveAssetData, setCandleData, deleteCandleSymbol, deleteActiveAssetData, addCandleData, setFinalAssetContexts, setFinalAtOICaps, setAggregatedClearingHouseState, } = useHyperliquidData();
548
+ const { setAllMids, setActiveAssetData, upsertActiveAssetData, setCandleData, deleteCandleSymbol, deleteActiveAssetData, addCandleData, setFinalAssetContexts, setFinalAtOICaps, setAggregatedClearingHouseState } = useHyperliquidData();
562
549
  const { candleInterval } = useUserSelection$1();
563
550
  const longTokens = useUserSelection$1((s) => s.longTokens);
564
551
  const shortTokens = useUserSelection$1((s) => s.shortTokens);
565
- const selectedTokenSymbols = useMemo(() => [...longTokens, ...shortTokens].map((t) => t.symbol), [longTokens, shortTokens]);
552
+ const selectedTokenSymbols = useMemo(() => ([...longTokens, ...shortTokens].map((t) => t.symbol)), [longTokens, shortTokens]);
566
553
  const [lastError, setLastError] = useState(null);
567
554
  const [subscribedAddress, setSubscribedAddress] = useState(null);
568
555
  const [subscribedTokens, setSubscribedTokens] = useState([]);
@@ -600,7 +587,7 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
600
587
  .map((dex) => dex.clearinghouseState)
601
588
  .filter(Boolean);
602
589
  const sum = (values) => values.reduce((acc, v) => acc + (parseFloat(v || '0') || 0), 0);
603
- const toStr = (n) => Number.isFinite(n) ? n.toString() : '0';
590
+ const toStr = (n) => (Number.isFinite(n) ? n.toString() : '0');
604
591
  const assetPositions = states.flatMap((s) => s.assetPositions || []);
605
592
  const crossMaintenanceMarginUsed = toStr(sum(states.map((s) => s.crossMaintenanceMarginUsed)));
606
593
  const crossMarginSummary = {
@@ -633,42 +620,17 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
633
620
  case 'allMids':
634
621
  {
635
622
  const data = response.data;
636
- // Keep BOTH normalized prefixed keys AND display symbol keys
637
- // This ensures xyz:TSLA and flx:TSLA are stored separately,
638
- // while also maintaining backward compatibility with non-prefixed lookups
639
- const mids = {};
640
- Object.entries(data.mids || {}).forEach(([k, v]) => {
641
- // Normalize prefixed keys to lowercase prefix (e.g., "XYZ:TSLA" -> "xyz:TSLA")
642
- // This matches how we look up tokens in the SDK
643
- let normalizedKey = k;
644
- if (k.includes(':')) {
645
- const [prefix, ...rest] = k.split(':');
646
- normalizedKey = `${prefix.toLowerCase()}:${rest.join(':')}`;
647
- }
648
- // Store with normalized key
649
- mids[normalizedKey] = v;
650
- // Also store with original key for backward compatibility
651
- if (k !== normalizedKey) {
652
- mids[k] = v;
653
- }
654
- // Also store with display symbol for backward compatibility
655
- const displayKey = toDisplaySymbol(k);
656
- // Only set display key if it doesn't already exist (avoid overwriting market-specific prices)
657
- if (!(displayKey in mids)) {
658
- mids[displayKey] = v;
659
- }
660
- });
661
- setAllMids({ mids });
623
+ const remapped = {
624
+ mids: Object.fromEntries(Object.entries(data.mids || {}).map(([k, v]) => [toDisplaySymbol(k), v]))
625
+ };
626
+ setAllMids(remapped);
662
627
  }
663
628
  break;
664
629
  case 'activeAssetData':
665
630
  {
666
631
  const assetData = response.data;
667
632
  const symbol = toDisplaySymbol(assetData.coin);
668
- const normalized = {
669
- ...assetData,
670
- coin: symbol,
671
- };
633
+ const normalized = { ...assetData, coin: symbol };
672
634
  upsertActiveAssetData(symbol, normalized);
673
635
  }
674
636
  break;
@@ -690,14 +652,7 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
690
652
  console.error('[HyperLiquid WS] Parse error:', errorMessage, 'Raw message:', event.data);
691
653
  setLastError(errorMessage);
692
654
  }
693
- }, [
694
- setAllMids,
695
- upsertActiveAssetData,
696
- addCandleData,
697
- setFinalAssetContexts,
698
- setFinalAtOICaps,
699
- setAggregatedClearingHouseState,
700
- ]);
655
+ }, [setAllMids, upsertActiveAssetData, addCandleData, setFinalAssetContexts, setFinalAtOICaps, setAggregatedClearingHouseState]);
701
656
  const connect = useCallback(() => {
702
657
  if (!enabled)
703
658
  return;
@@ -820,13 +775,7 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
820
775
  // clear aggregatedClearingHouseState
821
776
  setAggregatedClearingHouseState(null);
822
777
  }
823
- }, [
824
- isConnected,
825
- address,
826
- subscribedAddress,
827
- sendJsonMessage,
828
- setAggregatedClearingHouseState,
829
- ]);
778
+ }, [isConnected, address, subscribedAddress, sendJsonMessage, setAggregatedClearingHouseState]);
830
779
  // Handle token subscriptions for activeAssetData
831
780
  useEffect(() => {
832
781
  if (!isConnected || !address)
@@ -835,7 +784,7 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
835
784
  const tokensToSubscribe = effectiveTokens.filter((token) => token && !subscribedTokens.includes(token));
836
785
  const tokensToUnsubscribe = subscribedTokens.filter((token) => !effectiveTokens.includes(token));
837
786
  // Unsubscribe from tokens no longer in the list
838
- tokensToUnsubscribe.forEach((token) => {
787
+ tokensToUnsubscribe.forEach(token => {
839
788
  const unsubscribeMessage = {
840
789
  method: 'unsubscribe',
841
790
  subscription: {
@@ -847,7 +796,7 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
847
796
  sendJsonMessage(unsubscribeMessage);
848
797
  });
849
798
  // Subscribe to new tokens
850
- tokensToSubscribe.forEach((token) => {
799
+ tokensToSubscribe.forEach(token => {
851
800
  const subscribeMessage = {
852
801
  method: 'subscribe',
853
802
  subscription: {
@@ -862,14 +811,7 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
862
811
  setSubscribedTokens(effectiveTokens.filter((token) => token));
863
812
  tokensToSubscribe.forEach((token) => deleteActiveAssetData(token));
864
813
  }
865
- }, [
866
- isConnected,
867
- address,
868
- selectedTokenSymbols,
869
- subscribedTokens,
870
- sendJsonMessage,
871
- setActiveAssetData,
872
- ]);
814
+ }, [isConnected, address, selectedTokenSymbols, subscribedTokens, sendJsonMessage, setActiveAssetData]);
873
815
  // Handle candle subscriptions for tokens and interval changes
874
816
  useEffect(() => {
875
817
  if (!isConnected)
@@ -878,7 +820,7 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
878
820
  // Unsubscribe from previous candle subscriptions if interval changed
879
821
  const prevInterval = prevCandleIntervalRef.current;
880
822
  if (prevInterval && prevInterval !== candleInterval) {
881
- subscribedCandleTokens.forEach((token) => {
823
+ subscribedCandleTokens.forEach(token => {
882
824
  const unsubscribeMessage = {
883
825
  method: 'unsubscribe',
884
826
  subscription: {
@@ -919,21 +861,12 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
919
861
  sendJsonMessage(subscribeMessage);
920
862
  });
921
863
  // Update subscribed state
922
- if (tokensToSubscribe.length > 0 ||
923
- tokensToUnsubscribe.length > 0 ||
924
- prevInterval !== candleInterval) {
864
+ if (tokensToSubscribe.length > 0 || tokensToUnsubscribe.length > 0 || prevInterval !== candleInterval) {
925
865
  setSubscribedCandleTokens(effectiveTokens.filter((token) => token));
926
866
  prevCandleIntervalRef.current = candleInterval;
927
867
  tokensToUnsubscribe.forEach((token) => deleteCandleSymbol(token));
928
868
  }
929
- }, [
930
- isConnected,
931
- selectedTokenSymbols,
932
- candleInterval,
933
- subscribedCandleTokens,
934
- sendJsonMessage,
935
- setCandleData,
936
- ]);
869
+ }, [isConnected, selectedTokenSymbols, candleInterval, subscribedCandleTokens, sendJsonMessage, setCandleData]);
937
870
  return {
938
871
  isConnected,
939
872
  lastError,
@@ -1013,69 +946,16 @@ const useAccountSummary = () => {
1013
946
  return { data: calculated, isLoading };
1014
947
  };
1015
948
 
1016
- // Helper to find asset metadata from perpMetaAssets
1017
- function findAssetMeta$2(coinName, perpMetaAssets) {
1018
- var _a, _b, _c, _d;
1019
- if (!perpMetaAssets) {
1020
- return { collateralToken: 'USDC', marketPrefix: null };
1021
- }
1022
- // Try exact match first (for prefixed assets like "xyz:TSLA")
1023
- const exactMatch = perpMetaAssets.find((a) => a.name === coinName);
1024
- if (exactMatch) {
1025
- return {
1026
- collateralToken: (_a = exactMatch.collateralToken) !== null && _a !== void 0 ? _a : 'USDC',
1027
- marketPrefix: (_b = exactMatch.marketPrefix) !== null && _b !== void 0 ? _b : null,
1028
- };
1029
- }
1030
- // Try matching by base symbol (for non-prefixed names in data)
1031
- const baseMatch = perpMetaAssets.find((a) => {
1032
- const baseName = a.name.includes(':') ? a.name.split(':')[1] : a.name;
1033
- return baseName === coinName;
1034
- });
1035
- if (baseMatch) {
1036
- return {
1037
- collateralToken: (_c = baseMatch.collateralToken) !== null && _c !== void 0 ? _c : 'USDC',
1038
- marketPrefix: (_d = baseMatch.marketPrefix) !== null && _d !== void 0 ? _d : null,
1039
- };
1040
- }
1041
- return { collateralToken: 'USDC', marketPrefix: null };
1042
- }
1043
- // Enrich trade history assets with market prefix and collateral token
1044
- function enrichTradeHistoryAssets(assets, perpMetaAssets) {
1045
- return assets.map((asset) => {
1046
- const meta = findAssetMeta$2(asset.coin, perpMetaAssets);
1047
- return {
1048
- ...asset,
1049
- marketPrefix: meta.marketPrefix,
1050
- collateralToken: meta.collateralToken,
1051
- };
1052
- });
1053
- }
1054
- // Enrich all trade histories with market metadata
1055
- function enrichTradeHistories(histories, perpMetaAssets) {
1056
- return histories.map((history) => ({
1057
- ...history,
1058
- closedLongAssets: enrichTradeHistoryAssets(history.closedLongAssets, perpMetaAssets),
1059
- closedShortAssets: enrichTradeHistoryAssets(history.closedShortAssets, perpMetaAssets),
1060
- }));
1061
- }
1062
949
  const useTradeHistories = () => {
1063
950
  const context = useContext(PearHyperliquidContext);
1064
951
  if (!context) {
1065
952
  throw new Error('useTradeHistories must be used within a PearHyperliquidProvider');
1066
953
  }
1067
954
  const tradeHistories = useUserData((state) => state.tradeHistories);
1068
- const perpMetaAssets = useHyperliquidData((state) => state.perpMetaAssets);
1069
955
  const isLoading = useMemo(() => {
1070
956
  return tradeHistories === null && context.isConnected;
1071
957
  }, [tradeHistories, context.isConnected]);
1072
- // Enrich trade histories with market prefix and collateral token
1073
- const enrichedTradeHistories = useMemo(() => {
1074
- if (!tradeHistories)
1075
- return null;
1076
- return enrichTradeHistories(tradeHistories, perpMetaAssets);
1077
- }, [tradeHistories, perpMetaAssets]);
1078
- return { data: enrichedTradeHistories, isLoading };
958
+ return { data: tradeHistories, isLoading };
1079
959
  };
1080
960
  /**
1081
961
  * Hook to access open orders with loading state
@@ -1108,51 +988,21 @@ const useWebData = () => {
1108
988
  const perpMetaAssets = useHyperliquidData((state) => state.perpMetaAssets);
1109
989
  const aggregatedClearinghouseState = useHyperliquidData((state) => state.aggregatedClearingHouseState);
1110
990
  const finalAtOICaps = useHyperliquidData((state) => state.finalAtOICaps);
1111
- const hip3Assets = useHyperliquidData((state) => state.hip3Assets);
1112
- const hip3MarketPrefixes = useHyperliquidData((state) => state.hip3MarketPrefixes);
991
+ const hip3Assets = useHyperliquidData((state) => state.hip3DisplayToFull);
1113
992
  let marketDataBySymbol = {};
1114
993
  if (finalAssetContexts && perpMetaAssets) {
1115
994
  const result = {};
1116
- // Build a map of display name -> asset context index (for unique display names)
1117
- const displayNameToContextIndex = new Map();
1118
- const seenNames = new Set();
1119
- let contextIndex = 0;
1120
- // First pass: map unique display names to their context index
1121
995
  for (let index = 0; index < perpMetaAssets.length; index++) {
1122
996
  const name = perpMetaAssets[index].name;
1123
- if (!seenNames.has(name)) {
1124
- seenNames.add(name);
1125
- if (contextIndex < finalAssetContexts.length) {
1126
- displayNameToContextIndex.set(name, contextIndex);
1127
- contextIndex++;
1128
- }
1129
- }
1130
- }
1131
- // Second pass: create nested entries for all market variants
1132
- for (let index = 0; index < perpMetaAssets.length; index++) {
1133
- const universeAsset = perpMetaAssets[index];
1134
- const displayName = universeAsset.name;
1135
- const marketPrefix = universeAsset.marketPrefix;
1136
- const ctxIndex = displayNameToContextIndex.get(displayName);
1137
- if (ctxIndex !== undefined) {
1138
- const assetContext = finalAssetContexts[ctxIndex];
1139
- // Initialize the symbol entry if it doesn't exist
1140
- if (!result[displayName]) {
1141
- result[displayName] = {};
1142
- }
1143
- // Use marketPrefix as key for HIP-3 assets, "default" for regular assets
1144
- const variantKey = marketPrefix || 'default';
1145
- result[displayName][variantKey] = {
1146
- asset: assetContext,
1147
- universe: universeAsset,
1148
- };
1149
- }
997
+ result[name] = {
998
+ asset: finalAssetContexts[index],
999
+ universe: perpMetaAssets[index],
1000
+ };
1150
1001
  }
1151
1002
  marketDataBySymbol = result;
1152
1003
  }
1153
1004
  return {
1154
1005
  hip3Assets,
1155
- hip3MarketPrefixes,
1156
1006
  clearinghouseState: aggregatedClearinghouseState,
1157
1007
  perpsAtOpenInterestCap: finalAtOICaps,
1158
1008
  marketDataBySymbol,
@@ -1167,60 +1017,30 @@ const useWebData = () => {
1167
1017
  class TokenMetadataExtractor {
1168
1018
  /**
1169
1019
  * Extracts comprehensive token metadata
1170
- * @param symbol - Token symbol (base symbol without prefix, e.g., "TSLA")
1020
+ * @param symbol - Token symbol
1171
1021
  * @param perpMetaAssets - Aggregated universe assets (flattened across dexes)
1172
1022
  * @param finalAssetContexts - Aggregated asset contexts (flattened across dexes)
1173
1023
  * @param allMids - AllMids data containing current prices
1174
1024
  * @param activeAssetData - Optional active asset data containing leverage information
1175
- * @param marketPrefix - Optional market prefix (e.g., "xyz", "flx") for HIP3 multi-market assets
1176
1025
  * @returns TokenMetadata or null if token not found
1177
1026
  */
1178
- static extractTokenMetadata(symbol, perpMetaAssets, finalAssetContexts, allMids, activeAssetData, marketPrefix) {
1027
+ static extractTokenMetadata(symbol, perpMetaAssets, finalAssetContexts, allMids, activeAssetData) {
1179
1028
  if (!perpMetaAssets || !finalAssetContexts || !allMids) {
1180
1029
  return null;
1181
1030
  }
1182
1031
  // Find token index in aggregated universe
1183
- // For HIP3 assets, match both name AND marketPrefix
1184
- const universeIndex = perpMetaAssets.findIndex((asset) => {
1185
- if (asset.name !== symbol)
1186
- return false;
1187
- // If marketPrefix is specified, match it; otherwise match assets without prefix
1188
- if (marketPrefix) {
1189
- return asset.marketPrefix === marketPrefix;
1190
- }
1191
- // No prefix specified - match non-HIP3 asset (no marketPrefix) or first matching asset
1192
- return !asset.marketPrefix;
1193
- });
1194
- // If no exact match found and prefix was specified, try finding the specific market variant
1195
- const finalIndex = universeIndex === -1 && marketPrefix
1196
- ? perpMetaAssets.findIndex((asset) => asset.name === symbol && asset.marketPrefix === marketPrefix)
1197
- : universeIndex;
1198
- // Fallback: if still not found and no prefix, find first matching by name (for backward compatibility)
1199
- const resolvedIndex = finalIndex === -1
1200
- ? perpMetaAssets.findIndex((asset) => asset.name === symbol)
1201
- : finalIndex;
1202
- if (resolvedIndex === -1) {
1032
+ const universeIndex = perpMetaAssets.findIndex(asset => asset.name === symbol);
1033
+ if (universeIndex === -1) {
1203
1034
  return null;
1204
1035
  }
1205
- const universeAsset = perpMetaAssets[resolvedIndex];
1206
- const assetCtx = finalAssetContexts[resolvedIndex];
1036
+ const universeAsset = perpMetaAssets[universeIndex];
1037
+ const assetCtx = finalAssetContexts[universeIndex];
1207
1038
  if (!assetCtx) {
1208
1039
  return null;
1209
1040
  }
1210
- // Get current price - prefer assetCtx.midPx as it's already index-matched,
1211
- // fall back to allMids lookup if midPx is null
1212
- const prefixedKeyColon = marketPrefix ? `${marketPrefix}:${symbol}` : null;
1213
- let currentPrice = 0;
1214
- // Primary source: assetCtx.midPx (already properly indexed)
1215
- if (assetCtx.midPx) {
1216
- currentPrice = parseFloat(assetCtx.midPx);
1217
- }
1218
- // Fallback: allMids lookup with multiple key formats for HIP3 markets
1219
- if (!currentPrice || isNaN(currentPrice)) {
1220
- const currentPriceStr = (prefixedKeyColon && allMids.mids[prefixedKeyColon]) ||
1221
- allMids.mids[symbol];
1222
- currentPrice = currentPriceStr ? parseFloat(currentPriceStr) : 0;
1223
- }
1041
+ // Get current price from allMids
1042
+ const currentPriceStr = allMids.mids[symbol];
1043
+ const currentPrice = currentPriceStr ? parseFloat(currentPriceStr) : 0;
1224
1044
  // Get previous day price
1225
1045
  const prevDayPrice = parseFloat(assetCtx.prevDayPx);
1226
1046
  // Calculate 24h price change
@@ -1231,11 +1051,7 @@ class TokenMetadataExtractor {
1231
1051
  const markPrice = parseFloat(assetCtx.markPx);
1232
1052
  const oraclePrice = parseFloat(assetCtx.oraclePx);
1233
1053
  // Extract leverage info from activeAssetData if available
1234
- // Try prefixed key first (e.g., "xyz:TSLA"), then fall back to plain symbol
1235
- const activeDataKey = prefixedKeyColon && (activeAssetData === null || activeAssetData === void 0 ? void 0 : activeAssetData[prefixedKeyColon])
1236
- ? prefixedKeyColon
1237
- : symbol;
1238
- const tokenActiveData = activeAssetData === null || activeAssetData === void 0 ? void 0 : activeAssetData[activeDataKey];
1054
+ const tokenActiveData = activeAssetData === null || activeAssetData === void 0 ? void 0 : activeAssetData[symbol];
1239
1055
  const leverage = tokenActiveData === null || tokenActiveData === void 0 ? void 0 : tokenActiveData.leverage;
1240
1056
  const maxTradeSzs = tokenActiveData === null || tokenActiveData === void 0 ? void 0 : tokenActiveData.maxTradeSzs;
1241
1057
  const availableToTrade = tokenActiveData === null || tokenActiveData === void 0 ? void 0 : tokenActiveData.availableToTrade;
@@ -1253,27 +1069,21 @@ class TokenMetadataExtractor {
1253
1069
  leverage,
1254
1070
  maxTradeSzs,
1255
1071
  availableToTrade,
1256
- collateralToken: universeAsset.collateralToken,
1257
1072
  };
1258
1073
  }
1259
1074
  /**
1260
1075
  * Extracts metadata for multiple tokens
1261
- * @param tokens - Array of token objects with symbol and optional marketPrefix
1076
+ * @param symbols - Array of token symbols
1262
1077
  * @param perpMetaAssets - Aggregated universe assets
1263
1078
  * @param finalAssetContexts - Aggregated asset contexts
1264
1079
  * @param allMids - AllMids data
1265
1080
  * @param activeAssetData - Optional active asset data containing leverage information
1266
- * @returns Record of unique key to TokenMetadata. Key is "{prefix}:{symbol}" for HIP3 assets, or just "{symbol}" otherwise
1081
+ * @returns Record of symbol to TokenMetadata
1267
1082
  */
1268
- static extractMultipleTokensMetadata(tokens, perpMetaAssets, finalAssetContexts, allMids, activeAssetData) {
1083
+ static extractMultipleTokensMetadata(symbols, perpMetaAssets, finalAssetContexts, allMids, activeAssetData) {
1269
1084
  const result = {};
1270
- for (const token of tokens) {
1271
- // Use a unique key that includes the prefix for HIP3 assets
1272
- // This ensures xyz:TSLA and flx:TSLA get separate entries
1273
- const resultKey = token.marketPrefix
1274
- ? `${token.marketPrefix}:${token.symbol}`
1275
- : token.symbol;
1276
- result[resultKey] = this.extractTokenMetadata(token.symbol, perpMetaAssets, finalAssetContexts, allMids, activeAssetData, token.marketPrefix);
1085
+ for (const symbol of symbols) {
1086
+ result[symbol] = this.extractTokenMetadata(symbol, perpMetaAssets, finalAssetContexts, allMids, activeAssetData);
1277
1087
  }
1278
1088
  return result;
1279
1089
  }
@@ -1286,30 +1096,10 @@ class TokenMetadataExtractor {
1286
1096
  static isTokenAvailable(symbol, perpMetaAssets) {
1287
1097
  if (!perpMetaAssets)
1288
1098
  return false;
1289
- return perpMetaAssets.some((asset) => asset.name === symbol);
1099
+ return perpMetaAssets.some(asset => asset.name === symbol);
1290
1100
  }
1291
1101
  }
1292
1102
 
1293
- /**
1294
- * Parse a token string that may have a market prefix (e.g., "xyz:GOOGL" -> { prefix: "xyz", symbol: "GOOGL" })
1295
- * This allows us to keep the full name (xyz:GOOGL) for URLs/tags while extracting just the symbol for SDK lookups.
1296
- */
1297
- function parseTokenWithPrefix(token) {
1298
- if (token.includes(':')) {
1299
- const [prefix, ...rest] = token.split(':');
1300
- const symbol = rest.join(':').toUpperCase();
1301
- return {
1302
- prefix: prefix.toLowerCase(),
1303
- symbol,
1304
- fullName: `${prefix.toLowerCase()}:${symbol}`,
1305
- };
1306
- }
1307
- return {
1308
- prefix: null,
1309
- symbol: token.toUpperCase(),
1310
- fullName: token.toUpperCase(),
1311
- };
1312
- }
1313
1103
  const useTokenSelectionMetadataStore = create((set) => ({
1314
1104
  isPriceDataReady: false,
1315
1105
  isLoading: true,
@@ -1319,65 +1109,23 @@ const useTokenSelectionMetadataStore = create((set) => ({
1319
1109
  weightedRatio24h: 1,
1320
1110
  priceRatio: 1,
1321
1111
  priceRatio24h: 1,
1322
- openInterest: '0',
1323
- volume: '0',
1112
+ openInterest: "0",
1113
+ volume: "0",
1324
1114
  sumNetFunding: 0,
1325
1115
  maxLeverage: 0,
1326
1116
  minMargin: 0,
1327
1117
  leverageMatched: true,
1328
- recompute: ({ perpMetaAssets, finalAssetContexts, allMids, activeAssetData, marketData, longTokens, shortTokens, }) => {
1329
- const isPriceDataReady = !!(perpMetaAssets &&
1330
- finalAssetContexts &&
1331
- allMids);
1332
- // Parse tokens - handle prefixed tokens like "xyz:GOOGL" by extracting the symbol and market prefix
1333
- // The full name (xyz:GOOGL) is kept as the metadata key for UI consistency
1334
- const parsedLongTokens = longTokens.map((t) => ({
1335
- ...t,
1336
- parsed: parseTokenWithPrefix(t.symbol),
1337
- }));
1338
- const parsedShortTokens = shortTokens.map((t) => ({
1339
- ...t,
1340
- parsed: parseTokenWithPrefix(t.symbol),
1341
- }));
1342
- // Extract base symbols with their market prefixes for SDK lookups
1343
- // This ensures xyz:TSLA and flx:TSLA get different market data
1344
- const longTokensForLookup = parsedLongTokens.map((t) => ({
1345
- symbol: t.parsed.symbol,
1346
- marketPrefix: t.parsed.prefix,
1347
- }));
1348
- const shortTokensForLookup = parsedShortTokens.map((t) => ({
1349
- symbol: t.parsed.symbol,
1350
- marketPrefix: t.parsed.prefix,
1351
- }));
1352
- // Also extract just the base symbols (without prefix) for lookups that don't support prefixes
1353
- const longBaseSymbols = longTokensForLookup.map((t) => t.symbol);
1354
- const shortBaseSymbols = shortTokensForLookup.map((t) => t.symbol);
1355
- // Get metadata using base symbols with market prefix for proper market differentiation
1356
- const longBaseMetadata = isPriceDataReady
1357
- ? TokenMetadataExtractor.extractMultipleTokensMetadata(longTokensForLookup, perpMetaAssets, finalAssetContexts, allMids, activeAssetData)
1118
+ recompute: ({ perpMetaAssets, finalAssetContexts, allMids, activeAssetData, marketData, longTokens, shortTokens }) => {
1119
+ const isPriceDataReady = !!(perpMetaAssets && finalAssetContexts && allMids);
1120
+ // Compute metadata when ready
1121
+ const longSymbols = longTokens.map((t) => t.symbol);
1122
+ const shortSymbols = shortTokens.map((t) => t.symbol);
1123
+ const longTokensMetadata = isPriceDataReady
1124
+ ? TokenMetadataExtractor.extractMultipleTokensMetadata(longSymbols, perpMetaAssets, finalAssetContexts, allMids, activeAssetData)
1358
1125
  : {};
1359
- const shortBaseMetadata = isPriceDataReady
1360
- ? TokenMetadataExtractor.extractMultipleTokensMetadata(shortTokensForLookup, perpMetaAssets, finalAssetContexts, allMids, activeAssetData)
1126
+ const shortTokensMetadata = isPriceDataReady
1127
+ ? TokenMetadataExtractor.extractMultipleTokensMetadata(shortSymbols, perpMetaAssets, finalAssetContexts, allMids, activeAssetData)
1361
1128
  : {};
1362
- // Re-map metadata using original full names (with prefix) as keys for UI consistency
1363
- // The extractor now keys by "{prefix}:{symbol}" for prefixed tokens, which matches our parsed.fullName
1364
- const longTokensMetadata = {};
1365
- parsedLongTokens.forEach((t) => {
1366
- var _a;
1367
- // Use the full name (e.g., "xyz:TSLA") as the lookup key since extractor uses the same format
1368
- const lookupKey = t.parsed.prefix
1369
- ? `${t.parsed.prefix}:${t.parsed.symbol}`
1370
- : t.parsed.symbol;
1371
- longTokensMetadata[t.symbol] = (_a = longBaseMetadata[lookupKey]) !== null && _a !== void 0 ? _a : null;
1372
- });
1373
- const shortTokensMetadata = {};
1374
- parsedShortTokens.forEach((t) => {
1375
- var _a;
1376
- const lookupKey = t.parsed.prefix
1377
- ? `${t.parsed.prefix}:${t.parsed.symbol}`
1378
- : t.parsed.symbol;
1379
- shortTokensMetadata[t.symbol] = (_a = shortBaseMetadata[lookupKey]) !== null && _a !== void 0 ? _a : null;
1380
- });
1381
1129
  // Determine loading state
1382
1130
  const allTokens = [...longTokens, ...shortTokens];
1383
1131
  const isLoading = (() => {
@@ -1385,33 +1133,26 @@ const useTokenSelectionMetadataStore = create((set) => ({
1385
1133
  return true;
1386
1134
  if (allTokens.length === 0)
1387
1135
  return false;
1388
- const allMetadata = {
1389
- ...longTokensMetadata,
1390
- ...shortTokensMetadata,
1391
- };
1136
+ const allMetadata = { ...longTokensMetadata, ...shortTokensMetadata };
1392
1137
  return allTokens.some((token) => !allMetadata[token.symbol]);
1393
1138
  })();
1394
1139
  // Open interest and volume (from market data for matching asset basket)
1395
- // Use base symbols (without prefix) for matching against market data
1396
1140
  const { openInterest, volume } = (() => {
1397
- const empty = { openInterest: '0', volume: '0' };
1141
+ const empty = { openInterest: "0", volume: "0" };
1398
1142
  if (!(marketData === null || marketData === void 0 ? void 0 : marketData.active) || (!longTokens.length && !shortTokens.length))
1399
1143
  return empty;
1400
- const selectedLong = longBaseSymbols.slice().sort();
1401
- const selectedShort = shortBaseSymbols.slice().sort();
1144
+ const selectedLong = longTokens.map((t) => t.symbol).sort();
1145
+ const selectedShort = shortTokens.map((t) => t.symbol).sort();
1402
1146
  const match = marketData.active.find((item) => {
1403
1147
  const longs = [...item.longAssets].sort();
1404
1148
  const shorts = [...item.shortAssets].sort();
1405
- if (longs.length !== selectedLong.length ||
1406
- shorts.length !== selectedShort.length)
1149
+ if (longs.length !== selectedLong.length || shorts.length !== selectedShort.length)
1407
1150
  return false;
1408
1151
  const longsEqual = longs.every((s, i) => s.asset === selectedLong[i]);
1409
1152
  const shortsEqual = shorts.every((s, i) => s.asset === selectedShort[i]);
1410
1153
  return longsEqual && shortsEqual;
1411
1154
  });
1412
- return match
1413
- ? { openInterest: match.openInterest, volume: match.volume }
1414
- : empty;
1155
+ return match ? { openInterest: match.openInterest, volume: match.volume } : empty;
1415
1156
  })();
1416
1157
  // Price ratio (only when exactly one long and one short)
1417
1158
  const { priceRatio, priceRatio24h } = (() => {
@@ -1491,27 +1232,17 @@ const useTokenSelectionMetadataStore = create((set) => ({
1491
1232
  return totalFunding;
1492
1233
  })();
1493
1234
  // Max leverage (minimum across all tokens)
1494
- // Use tokens with their market prefixes for proper lookup in perpMetaAssets
1495
1235
  const maxLeverage = (() => {
1496
1236
  if (!perpMetaAssets)
1497
1237
  return 0;
1498
- const allTokensForLookup = [
1499
- ...longTokensForLookup,
1500
- ...shortTokensForLookup,
1501
- ];
1502
- if (allTokensForLookup.length === 0)
1238
+ const allTokenSymbols = [...longTokens, ...shortTokens].map((t) => t.symbol);
1239
+ if (allTokenSymbols.length === 0)
1503
1240
  return 0;
1504
1241
  let minLev = Infinity;
1505
- allTokensForLookup.forEach(({ symbol, marketPrefix }) => {
1506
- // Match by both name AND marketPrefix for HIP3 assets
1507
- const tokenUniverse = perpMetaAssets.find((u) => u.name === symbol &&
1508
- (marketPrefix
1509
- ? u.marketPrefix === marketPrefix
1510
- : !u.marketPrefix));
1511
- // Fallback to just matching by name if no exact match
1512
- const fallbackUniverse = tokenUniverse || perpMetaAssets.find((u) => u.name === symbol);
1513
- if (fallbackUniverse === null || fallbackUniverse === void 0 ? void 0 : fallbackUniverse.maxLeverage)
1514
- minLev = Math.min(minLev, fallbackUniverse.maxLeverage);
1242
+ allTokenSymbols.forEach((symbol) => {
1243
+ const tokenUniverse = perpMetaAssets.find((u) => u.name === symbol);
1244
+ if (tokenUniverse === null || tokenUniverse === void 0 ? void 0 : tokenUniverse.maxLeverage)
1245
+ minLev = Math.min(minLev, tokenUniverse.maxLeverage);
1515
1246
  });
1516
1247
  return minLev === Infinity ? 0 : minLev;
1517
1248
  })();
@@ -1523,10 +1254,7 @@ const useTokenSelectionMetadataStore = create((set) => ({
1523
1254
  // Whether all tokens have matching leverage
1524
1255
  const leverageMatched = (() => {
1525
1256
  const allTokensArr = [...longTokens, ...shortTokens];
1526
- const allMetadata = {
1527
- ...longTokensMetadata,
1528
- ...shortTokensMetadata,
1529
- };
1257
+ const allMetadata = { ...longTokensMetadata, ...shortTokensMetadata };
1530
1258
  if (allTokensArr.length === 0)
1531
1259
  return true;
1532
1260
  const tokensWithLev = allTokensArr.filter((token) => { var _a; return (_a = allMetadata[token.symbol]) === null || _a === void 0 ? void 0 : _a.leverage; });
@@ -5711,8 +5439,8 @@ function addAuthInterceptors(params) {
5711
5439
  /**
5712
5440
  * Fetch historical candle data from HyperLiquid API
5713
5441
  */
5714
- const fetchHistoricalCandles = async (coin, startTime, endTime, interval, hip3Assets) => {
5715
- const backendCoin = toBackendSymbol(coin, hip3Assets);
5442
+ const fetchHistoricalCandles = async (coin, startTime, endTime, interval, displayToFull) => {
5443
+ const backendCoin = toBackendSymbol(coin, displayToFull);
5716
5444
  const request = {
5717
5445
  req: { coin: backendCoin, startTime, endTime, interval },
5718
5446
  type: 'candleSnapshot',
@@ -5871,10 +5599,10 @@ const useHistoricalPriceData = () => {
5871
5599
  setTokenLoading(token.symbol, true);
5872
5600
  });
5873
5601
  try {
5874
- const hip3Assets = useHyperliquidData.getState().hip3Assets;
5602
+ const displayToFull = useHyperliquidData.getState().hip3DisplayToFull;
5875
5603
  const fetchPromises = tokensToFetch.map(async (token) => {
5876
5604
  try {
5877
- const response = await fetchHistoricalCandles(token.symbol, startTime, endTime, interval, hip3Assets);
5605
+ const response = await fetchHistoricalCandles(token.symbol, startTime, endTime, interval, displayToFull);
5878
5606
  addHistoricalPriceData(token.symbol, interval, response.data, { start: startTime, end: endTime });
5879
5607
  return { symbol: token.symbol, candles: response.data, success: true };
5880
5608
  }
@@ -6643,12 +6371,12 @@ function validatePositionSize(usdValue, longAssets, shortAssets) {
6643
6371
  * Authorization is derived from headers (Axios defaults or browser localStorage fallback)
6644
6372
  * @throws MinimumPositionSizeError if any asset has less than $11 USD value
6645
6373
  */
6646
- async function createPosition(baseUrl, payload, hip3Assets) {
6374
+ async function createPosition(baseUrl, payload, displayToFull) {
6647
6375
  // Validate minimum asset size before creating position
6648
6376
  validateMinimumAssetSize(payload.usdValue, payload.longAssets, payload.shortAssets);
6649
6377
  const url = joinUrl(baseUrl, "/positions");
6650
6378
  // Translate display symbols to backend format
6651
- const mapAssets = (arr) => arr === null || arr === void 0 ? void 0 : arr.map((a) => ({ ...a, asset: toBackendSymbol(a.asset, hip3Assets) }));
6379
+ const mapAssets = (arr) => arr === null || arr === void 0 ? void 0 : arr.map((a) => ({ ...a, asset: toBackendSymbol(a.asset, displayToFull) }));
6652
6380
  const translatedPayload = {
6653
6381
  ...payload,
6654
6382
  longAssets: mapAssets(payload.longAssets),
@@ -6747,9 +6475,9 @@ async function adjustPosition(baseUrl, positionId, payload) {
6747
6475
  throw toApiError(error);
6748
6476
  }
6749
6477
  }
6750
- async function adjustAdvancePosition(baseUrl, positionId, payload, hip3Assets) {
6478
+ async function adjustAdvancePosition(baseUrl, positionId, payload, displayToFull) {
6751
6479
  const url = joinUrl(baseUrl, `/positions/${positionId}/adjust-advance`);
6752
- const mapAssets = (arr) => arr === null || arr === void 0 ? void 0 : arr.map((a) => ({ ...a, asset: toBackendSymbol(a.asset, hip3Assets) }));
6480
+ const mapAssets = (arr) => arr === null || arr === void 0 ? void 0 : arr.map((a) => ({ ...a, asset: toBackendSymbol(a.asset, displayToFull) }));
6753
6481
  const translatedPayload = (payload || []).map((item) => ({
6754
6482
  longAssets: mapAssets(item.longAssets),
6755
6483
  shortAssets: mapAssets(item.shortAssets),
@@ -6874,62 +6602,16 @@ const buildPositionValue = (rawPositions, clearinghouseState, allMids) => {
6874
6602
  });
6875
6603
  };
6876
6604
 
6877
- // Helper to find asset metadata from perpMetaAssets
6878
- function findAssetMeta$1(coinName, perpMetaAssets) {
6879
- var _a, _b, _c, _d;
6880
- if (!perpMetaAssets) {
6881
- return { collateralToken: 'USDC', marketPrefix: null };
6882
- }
6883
- // Try exact match first (for prefixed assets like "xyz:TSLA")
6884
- const exactMatch = perpMetaAssets.find((a) => a.name === coinName);
6885
- if (exactMatch) {
6886
- return {
6887
- collateralToken: (_a = exactMatch.collateralToken) !== null && _a !== void 0 ? _a : 'USDC',
6888
- marketPrefix: (_b = exactMatch.marketPrefix) !== null && _b !== void 0 ? _b : null,
6889
- };
6890
- }
6891
- // Try matching by base symbol (for non-prefixed names in data)
6892
- const baseMatch = perpMetaAssets.find((a) => {
6893
- const baseName = a.name.includes(':') ? a.name.split(':')[1] : a.name;
6894
- return baseName === coinName;
6895
- });
6896
- if (baseMatch) {
6897
- return {
6898
- collateralToken: (_c = baseMatch.collateralToken) !== null && _c !== void 0 ? _c : 'USDC',
6899
- marketPrefix: (_d = baseMatch.marketPrefix) !== null && _d !== void 0 ? _d : null,
6900
- };
6901
- }
6902
- return { collateralToken: 'USDC', marketPrefix: null };
6903
- }
6904
- // Enrich position assets with market prefix and collateral token
6905
- function enrichPositionAssets(assets, perpMetaAssets) {
6906
- return assets.map((asset) => {
6907
- const meta = findAssetMeta$1(asset.coin, perpMetaAssets);
6908
- return {
6909
- ...asset,
6910
- marketPrefix: meta.marketPrefix,
6911
- collateralToken: meta.collateralToken,
6912
- };
6913
- });
6914
- }
6915
- // Enrich all positions with market metadata
6916
- function enrichPositions(positions, perpMetaAssets) {
6917
- return positions.map((position) => ({
6918
- ...position,
6919
- longAssets: enrichPositionAssets(position.longAssets, perpMetaAssets),
6920
- shortAssets: enrichPositionAssets(position.shortAssets, perpMetaAssets),
6921
- }));
6922
- }
6923
6605
  function usePosition() {
6924
6606
  const context = useContext(PearHyperliquidContext);
6925
6607
  if (!context) {
6926
6608
  throw new Error('usePosition must be used within a PearHyperliquidProvider');
6927
6609
  }
6928
6610
  const { apiBaseUrl, isConnected } = context;
6929
- const hip3Assets = useHyperliquidData((s) => s.hip3Assets);
6611
+ const displayToFull = useHyperliquidData((s) => s.hip3DisplayToFull);
6930
6612
  // Create position API action
6931
6613
  const createPosition$1 = async (payload) => {
6932
- return createPosition(apiBaseUrl, payload, hip3Assets);
6614
+ return createPosition(apiBaseUrl, payload, displayToFull);
6933
6615
  };
6934
6616
  // Update TP/SL risk parameters for a position
6935
6617
  const updateRiskParameters$1 = async (positionId, payload) => {
@@ -6949,47 +6631,28 @@ function usePosition() {
6949
6631
  };
6950
6632
  // Adjust to absolute target sizes per asset, optionally adding new assets
6951
6633
  const adjustAdvancePosition$1 = async (positionId, payload) => {
6952
- return adjustAdvancePosition(apiBaseUrl, positionId, payload, hip3Assets);
6634
+ return adjustAdvancePosition(apiBaseUrl, positionId, payload, displayToFull);
6953
6635
  };
6954
6636
  // Open positions using WS data, with derived values
6955
6637
  const userOpenPositions = useUserData((state) => state.rawOpenPositions);
6956
6638
  const aggregatedClearingHouseState = useHyperliquidData((state) => state.aggregatedClearingHouseState);
6957
6639
  const allMids = useHyperliquidData((state) => state.allMids);
6958
- const perpMetaAssets = useHyperliquidData((state) => state.perpMetaAssets);
6959
6640
  const isLoading = useMemo(() => {
6960
6641
  return userOpenPositions === null && isConnected;
6961
6642
  }, [userOpenPositions, isConnected]);
6962
6643
  const openPositions = useMemo(() => {
6963
6644
  if (!userOpenPositions || !aggregatedClearingHouseState || !allMids)
6964
6645
  return null;
6965
- const positions = buildPositionValue(userOpenPositions, aggregatedClearingHouseState, allMids);
6966
- // Enrich with market prefix and collateral token
6967
- return enrichPositions(positions, perpMetaAssets);
6968
- }, [userOpenPositions, aggregatedClearingHouseState, allMids, perpMetaAssets]);
6969
- return {
6970
- createPosition: createPosition$1,
6971
- updateRiskParameters: updateRiskParameters$1,
6972
- closePosition: closePosition$1,
6973
- closeAllPositions: closeAllPositions$1,
6974
- adjustPosition: adjustPosition$1,
6975
- adjustAdvancePosition: adjustAdvancePosition$1,
6976
- openPositions,
6977
- isLoading,
6978
- };
6646
+ return buildPositionValue(userOpenPositions, aggregatedClearingHouseState, allMids);
6647
+ }, [userOpenPositions, aggregatedClearingHouseState, allMids]);
6648
+ return { createPosition: createPosition$1, updateRiskParameters: updateRiskParameters$1, closePosition: closePosition$1, closeAllPositions: closeAllPositions$1, adjustPosition: adjustPosition$1, adjustAdvancePosition: adjustAdvancePosition$1, openPositions, isLoading };
6979
6649
  }
6980
6650
 
6981
6651
  async function adjustOrder(baseUrl, orderId, payload) {
6982
6652
  const url = joinUrl(baseUrl, `/orders/${orderId}/adjust`);
6983
6653
  try {
6984
- const resp = await apiClient.put(url, payload, {
6985
- headers: { 'Content-Type': 'application/json' },
6986
- timeout: 60000,
6987
- });
6988
- return {
6989
- data: resp.data,
6990
- status: resp.status,
6991
- headers: resp.headers,
6992
- };
6654
+ const resp = await apiClient.put(url, payload, { headers: { 'Content-Type': 'application/json' }, timeout: 60000 });
6655
+ return { data: resp.data, status: resp.status, headers: resp.headers };
6993
6656
  }
6994
6657
  catch (error) {
6995
6658
  throw toApiError(error);
@@ -6998,14 +6661,8 @@ async function adjustOrder(baseUrl, orderId, payload) {
6998
6661
  async function cancelOrder(baseUrl, orderId) {
6999
6662
  const url = joinUrl(baseUrl, `/orders/${orderId}/cancel`);
7000
6663
  try {
7001
- const resp = await apiClient.delete(url, {
7002
- timeout: 60000,
7003
- });
7004
- return {
7005
- data: resp.data,
7006
- status: resp.status,
7007
- headers: resp.headers,
7008
- };
6664
+ const resp = await apiClient.delete(url, { timeout: 60000 });
6665
+ return { data: resp.data, status: resp.status, headers: resp.headers };
7009
6666
  }
7010
6667
  catch (error) {
7011
6668
  throw toApiError(error);
@@ -7015,32 +6672,7 @@ async function cancelTwapOrder(baseUrl, orderId) {
7015
6672
  const url = joinUrl(baseUrl, `/orders/${orderId}/twap/cancel`);
7016
6673
  try {
7017
6674
  const resp = await apiClient.post(url, {}, { headers: { 'Content-Type': 'application/json' }, timeout: 60000 });
7018
- return {
7019
- data: resp.data,
7020
- status: resp.status,
7021
- headers: resp.headers,
7022
- };
7023
- }
7024
- catch (error) {
7025
- throw toApiError(error);
7026
- }
7027
- }
7028
- /**
7029
- * Execute a spot order (swap) using Pear Hyperliquid service
7030
- * POST /orders/spot
7031
- */
7032
- async function executeSpotOrder(baseUrl, payload) {
7033
- const url = joinUrl(baseUrl, '/orders/spot');
7034
- try {
7035
- const resp = await apiClient.post(url, payload, {
7036
- headers: { 'Content-Type': 'application/json' },
7037
- timeout: 60000,
7038
- });
7039
- return {
7040
- data: resp.data,
7041
- status: resp.status,
7042
- headers: resp.headers,
7043
- };
6675
+ return { data: resp.data, status: resp.status, headers: resp.headers };
7044
6676
  }
7045
6677
  catch (error) {
7046
6678
  throw toApiError(error);
@@ -7096,45 +6728,6 @@ function useOrders() {
7096
6728
  return { adjustOrder: adjustOrder$1, cancelOrder: cancelOrder$1, cancelTwapOrder: cancelTwapOrder$1, openOrders: enrichedOpenOrders, isLoading };
7097
6729
  }
7098
6730
 
7099
- /**
7100
- * Hook for executing spot orders (swaps) on Hyperliquid
7101
- * Use this to swap between USDC and USDH or other spot assets
7102
- */
7103
- function useSpotOrder() {
7104
- const context = useContext(PearHyperliquidContext);
7105
- if (!context) {
7106
- throw new Error('useSpotOrder must be used within a PearHyperliquidProvider');
7107
- }
7108
- const { apiBaseUrl } = context;
7109
- const [isLoading, setIsLoading] = useState(false);
7110
- const [error, setError] = useState(null);
7111
- const resetError = useCallback(() => {
7112
- setError(null);
7113
- }, []);
7114
- const executeSpotOrder$1 = useCallback(async (payload) => {
7115
- setIsLoading(true);
7116
- setError(null);
7117
- try {
7118
- const response = await executeSpotOrder(apiBaseUrl, payload);
7119
- return response;
7120
- }
7121
- catch (err) {
7122
- const apiError = err;
7123
- setError(apiError);
7124
- throw apiError;
7125
- }
7126
- finally {
7127
- setIsLoading(false);
7128
- }
7129
- }, [apiBaseUrl]);
7130
- return {
7131
- executeSpotOrder: executeSpotOrder$1,
7132
- isLoading,
7133
- error,
7134
- resetError,
7135
- };
7136
- }
7137
-
7138
6731
  function useTwap() {
7139
6732
  const twapDetails = useUserData(state => state.twapDetails);
7140
6733
  const context = useContext(PearHyperliquidContext);
@@ -7224,170 +6817,59 @@ function useNotifications() {
7224
6817
  };
7225
6818
  }
7226
6819
 
7227
- // Helper to find asset metadata from perpMetaAssets
7228
- function findAssetMeta(assetName, perpMetaAssets) {
7229
- var _a, _b, _c, _d;
7230
- if (!perpMetaAssets) {
7231
- return { collateralToken: 'USDC', marketPrefix: null };
7232
- }
7233
- // Try exact match first (for prefixed assets like "xyz:TSLA")
7234
- const exactMatch = perpMetaAssets.find((a) => a.name === assetName);
7235
- if (exactMatch) {
7236
- return {
7237
- collateralToken: (_a = exactMatch.collateralToken) !== null && _a !== void 0 ? _a : 'USDC',
7238
- marketPrefix: (_b = exactMatch.marketPrefix) !== null && _b !== void 0 ? _b : null,
7239
- };
7240
- }
7241
- // Try matching by base symbol (for non-prefixed names in data)
7242
- const baseMatch = perpMetaAssets.find((a) => {
7243
- const baseName = a.name.includes(':') ? a.name.split(':')[1] : a.name;
7244
- return baseName === assetName;
7245
- });
7246
- if (baseMatch) {
7247
- return {
7248
- collateralToken: (_c = baseMatch.collateralToken) !== null && _c !== void 0 ? _c : 'USDC',
7249
- marketPrefix: (_d = baseMatch.marketPrefix) !== null && _d !== void 0 ? _d : null,
7250
- };
7251
- }
7252
- return { collateralToken: 'USDC', marketPrefix: null };
7253
- }
7254
- // Enrich a single asset with metadata
7255
- function enrichAsset(asset, perpMetaAssets) {
7256
- const meta = findAssetMeta(asset.asset, perpMetaAssets);
7257
- return {
7258
- ...asset,
7259
- collateralToken: meta.collateralToken,
7260
- marketPrefix: meta.marketPrefix,
7261
- };
7262
- }
7263
- // Enrich a basket item with collateral info
7264
- function enrichBasketItem(item, perpMetaAssets) {
7265
- const enrichedLongs = item.longAssets.map((a) => enrichAsset(a, perpMetaAssets));
7266
- const enrichedShorts = item.shortAssets.map((a) => enrichAsset(a, perpMetaAssets));
7267
- // Determine collateral type
7268
- const allAssets = [...enrichedLongs, ...enrichedShorts];
7269
- const hasUsdc = allAssets.some((a) => a.collateralToken === 'USDC');
7270
- const hasUsdh = allAssets.some((a) => a.collateralToken === 'USDH');
7271
- let collateralType = 'USDC';
7272
- if (hasUsdc && hasUsdh) {
7273
- collateralType = 'MIXED';
7274
- }
7275
- else if (hasUsdh) {
7276
- collateralType = 'USDH';
7277
- }
7278
- return {
7279
- ...item,
7280
- longAssets: enrichedLongs,
7281
- shortAssets: enrichedShorts,
7282
- collateralType,
7283
- };
7284
- }
7285
- /**
7286
- * Filter baskets by collateral type
7287
- * - 'USDC': Only baskets where ALL assets use USDC (collateralType === 'USDC')
7288
- * - 'USDH': Only baskets where ALL assets use USDH (collateralType === 'USDH')
7289
- * - 'ALL' or undefined: No filtering, returns all baskets
7290
- */
7291
- function filterByCollateral(baskets, filter) {
7292
- if (!filter || filter === 'ALL') {
7293
- return baskets;
7294
- }
7295
- return baskets.filter((basket) => {
7296
- if (filter === 'USDC') {
7297
- // Include baskets that are purely USDC or have USDC assets
7298
- return (basket.collateralType === 'USDC' || basket.collateralType === 'MIXED');
7299
- }
7300
- if (filter === 'USDH') {
7301
- // Include baskets that are purely USDH or have USDH assets
7302
- return (basket.collateralType === 'USDH' || basket.collateralType === 'MIXED');
7303
- }
7304
- return true;
7305
- });
7306
- }
7307
- // Base selector for the full market-data payload (raw from WS)
6820
+ // Base selector for the full market-data payload
7308
6821
  const useMarketDataPayload = () => {
7309
6822
  return useMarketData((s) => s.marketData);
7310
6823
  };
7311
- // Full payload for 'market-data-all' channel (raw from WS)
6824
+ // Full payload for 'market-data-all' channel
7312
6825
  const useMarketDataAllPayload = () => {
7313
6826
  return useMarketData((s) => s.marketDataAll);
7314
6827
  };
7315
- // Access perpMetaAssets for enrichment
7316
- const usePerpMetaAssets = () => {
7317
- return useHyperliquidData((s) => s.perpMetaAssets);
7318
- };
7319
- // Active baskets (with collateral and market prefix info)
7320
- const useActiveBaskets = (collateralFilter) => {
6828
+ // Active baskets
6829
+ const useActiveBaskets = () => {
6830
+ var _a;
7321
6831
  const data = useMarketDataPayload();
7322
- const perpMetaAssets = usePerpMetaAssets();
7323
- return useMemo(() => {
7324
- if (!(data === null || data === void 0 ? void 0 : data.active))
7325
- return [];
7326
- const enriched = data.active.map((item) => enrichBasketItem(item, perpMetaAssets));
7327
- return filterByCollateral(enriched, collateralFilter);
7328
- }, [data, perpMetaAssets, collateralFilter]);
6832
+ return (_a = data === null || data === void 0 ? void 0 : data.active) !== null && _a !== void 0 ? _a : [];
7329
6833
  };
7330
- // Top gainers (with collateral and market prefix info)
7331
- const useTopGainers = (limit, collateralFilter) => {
6834
+ // Top gainers (optional limit override)
6835
+ const useTopGainers = (limit) => {
7332
6836
  const data = useMarketDataPayload();
7333
- const perpMetaAssets = usePerpMetaAssets();
7334
6837
  return useMemo(() => {
7335
6838
  var _a;
7336
6839
  const list = (_a = data === null || data === void 0 ? void 0 : data.topGainers) !== null && _a !== void 0 ? _a : [];
7337
- const limited = typeof limit === 'number' ? list.slice(0, Math.max(0, limit)) : list;
7338
- const enriched = limited.map((item) => enrichBasketItem(item, perpMetaAssets));
7339
- return filterByCollateral(enriched, collateralFilter);
7340
- }, [data, perpMetaAssets, limit, collateralFilter]);
6840
+ return typeof limit === 'number' ? list.slice(0, Math.max(0, limit)) : list;
6841
+ }, [data, limit]);
7341
6842
  };
7342
- // Top losers (with collateral and market prefix info)
7343
- const useTopLosers = (limit, collateralFilter) => {
6843
+ // Top losers (optional limit override)
6844
+ const useTopLosers = (limit) => {
7344
6845
  const data = useMarketDataPayload();
7345
- const perpMetaAssets = usePerpMetaAssets();
7346
6846
  return useMemo(() => {
7347
6847
  var _a;
7348
6848
  const list = (_a = data === null || data === void 0 ? void 0 : data.topLosers) !== null && _a !== void 0 ? _a : [];
7349
- const limited = typeof limit === 'number' ? list.slice(0, Math.max(0, limit)) : list;
7350
- const enriched = limited.map((item) => enrichBasketItem(item, perpMetaAssets));
7351
- return filterByCollateral(enriched, collateralFilter);
7352
- }, [data, perpMetaAssets, limit, collateralFilter]);
6849
+ return typeof limit === 'number' ? list.slice(0, Math.max(0, limit)) : list;
6850
+ }, [data, limit]);
7353
6851
  };
7354
- // Highlighted baskets (with collateral and market prefix info)
7355
- const useHighlightedBaskets = (collateralFilter) => {
6852
+ // Highlighted baskets
6853
+ const useHighlightedBaskets = () => {
6854
+ var _a;
7356
6855
  const data = useMarketDataPayload();
7357
- const perpMetaAssets = usePerpMetaAssets();
7358
- return useMemo(() => {
7359
- if (!(data === null || data === void 0 ? void 0 : data.highlighted))
7360
- return [];
7361
- const enriched = data.highlighted.map((item) => enrichBasketItem(item, perpMetaAssets));
7362
- return filterByCollateral(enriched, collateralFilter);
7363
- }, [data, perpMetaAssets, collateralFilter]);
6856
+ return (_a = data === null || data === void 0 ? void 0 : data.highlighted) !== null && _a !== void 0 ? _a : [];
7364
6857
  };
7365
- // Watchlist baskets (with collateral and market prefix info)
7366
- const useWatchlistBaskets = (collateralFilter) => {
6858
+ // Watchlist baskets (from market-data payload when subscribed with address)
6859
+ const useWatchlistBaskets = () => {
6860
+ var _a;
7367
6861
  const data = useMarketDataPayload();
7368
- const perpMetaAssets = usePerpMetaAssets();
7369
- return useMemo(() => {
7370
- if (!(data === null || data === void 0 ? void 0 : data.watchlist))
7371
- return [];
7372
- const enriched = data.watchlist.map((item) => enrichBasketItem(item, perpMetaAssets));
7373
- return filterByCollateral(enriched, collateralFilter);
7374
- }, [data, perpMetaAssets, collateralFilter]);
6862
+ return (_a = data === null || data === void 0 ? void 0 : data.watchlist) !== null && _a !== void 0 ? _a : [];
7375
6863
  };
7376
- // All baskets (with collateral and market prefix info)
7377
- const useAllBaskets = (collateralFilter) => {
6864
+ // All baskets (from market-data-all)
6865
+ const useAllBaskets = () => {
6866
+ var _a;
7378
6867
  const dataAll = useMarketDataAllPayload();
7379
- const perpMetaAssets = usePerpMetaAssets();
7380
- return useMemo(() => {
7381
- if (!(dataAll === null || dataAll === void 0 ? void 0 : dataAll.all))
7382
- return [];
7383
- const enriched = dataAll.all.map((item) => enrichBasketItem(item, perpMetaAssets));
7384
- return filterByCollateral(enriched, collateralFilter);
7385
- }, [dataAll, perpMetaAssets, collateralFilter]);
6868
+ return (_a = dataAll === null || dataAll === void 0 ? void 0 : dataAll.all) !== null && _a !== void 0 ? _a : [];
7386
6869
  };
7387
6870
  // Find a basket by its exact asset composition (order-insensitive)
7388
6871
  const useFindBasket = (longs, shorts) => {
7389
6872
  const data = useMarketDataPayload();
7390
- const perpMetaAssets = usePerpMetaAssets();
7391
6873
  return useMemo(() => {
7392
6874
  if (!data)
7393
6875
  return undefined;
@@ -7401,28 +6883,17 @@ const useFindBasket = (longs, shorts) => {
7401
6883
  : '';
7402
6884
  const lKey = normalize(longs);
7403
6885
  const sKey = normalize(shorts);
7404
- const match = (item) => normalize(item.longAssets) === lKey &&
7405
- normalize(item.shortAssets) === sKey;
7406
- const found = data.active.find(match) || data.highlighted.find(match);
7407
- return found
7408
- ? enrichBasketItem(found, perpMetaAssets)
7409
- : undefined;
7410
- }, [data, longs, shorts, perpMetaAssets]);
6886
+ const match = (item) => normalize(item.longAssets) === lKey && normalize(item.shortAssets) === sKey;
6887
+ return data.active.find(match) || data.highlighted.find(match);
6888
+ }, [data, longs, shorts]);
7411
6889
  };
7412
6890
 
7413
- async function toggleWatchlist(baseUrl, longAssets, shortAssets, hip3Assets) {
6891
+ async function toggleWatchlist(baseUrl, longAssets, shortAssets, displayToFull) {
7414
6892
  const url = joinUrl(baseUrl, '/watchlist');
7415
- const mapAssets = (arr) => arr.map((a) => ({ ...a, asset: toBackendSymbol(a.asset, hip3Assets) }));
6893
+ const mapAssets = (arr) => arr.map(a => ({ ...a, asset: toBackendSymbol(a.asset, displayToFull) }));
7416
6894
  try {
7417
- const response = await apiClient.post(url, {
7418
- longAssets: mapAssets(longAssets),
7419
- shortAssets: mapAssets(shortAssets),
7420
- }, { headers: { 'Content-Type': 'application/json' } });
7421
- return {
7422
- data: response.data,
7423
- status: response.status,
7424
- headers: response.headers,
7425
- };
6895
+ const response = await apiClient.post(url, { longAssets: mapAssets(longAssets), shortAssets: mapAssets(shortAssets) }, { headers: { 'Content-Type': 'application/json' } });
6896
+ return { data: response.data, status: response.status, headers: response.headers };
7426
6897
  }
7427
6898
  catch (error) {
7428
6899
  throw toApiError(error);
@@ -7434,11 +6905,11 @@ function useWatchlist() {
7434
6905
  if (!context)
7435
6906
  throw new Error('useWatchlist must be used within a PearHyperliquidProvider');
7436
6907
  const { apiBaseUrl, isConnected } = context;
7437
- const hip3Assets = useHyperliquidData((s) => s.hip3Assets);
6908
+ const displayToFull = useHyperliquidData((s) => s.hip3DisplayToFull);
7438
6909
  const marketData = useMarketDataPayload();
7439
6910
  const isLoading = useMemo(() => !marketData && isConnected, [marketData, isConnected]);
7440
6911
  const toggle = async (longAssets, shortAssets) => {
7441
- const resp = await toggleWatchlist(apiBaseUrl, longAssets, shortAssets, hip3Assets);
6912
+ const resp = await toggleWatchlist(apiBaseUrl, longAssets, shortAssets, displayToFull);
7442
6913
  // Server will push updated market-data over WS; nothing to set here
7443
6914
  return resp;
7444
6915
  };
@@ -7560,36 +7031,47 @@ async function logout(baseUrl, refreshTokenVal) {
7560
7031
  function useAuth() {
7561
7032
  const context = useContext(PearHyperliquidContext);
7562
7033
  if (!context) {
7563
- throw new Error('usePortfolio must be used within a PearHyperliquidProvider');
7034
+ throw new Error("useAuth must be used within a PearHyperliquidProvider");
7564
7035
  }
7565
7036
  const { apiBaseUrl, clientId } = context;
7566
- const [isReady, setIsReady] = useState(false);
7567
7037
  const accessToken = useUserData((s) => s.accessToken);
7568
7038
  const refreshToken$1 = useUserData((s) => s.refreshToken);
7039
+ const isReady = useUserData((s) => s.isReady);
7040
+ const isAuthenticated = useUserData((s) => s.isAuthenticated);
7041
+ const address = useUserData((s) => s.address);
7569
7042
  const setAccessToken = useUserData((s) => s.setAccessToken);
7570
7043
  const setRefreshToken = useUserData((s) => s.setRefreshToken);
7571
- const isAuthenticated = useUserData((s) => s.isAuthenticated);
7044
+ const setIsReady = useUserData((s) => s.setIsReady);
7572
7045
  const setIsAuthenticated = useUserData((s) => s.setIsAuthenticated);
7573
7046
  const setAddress = useUserData((s) => s.setAddress);
7047
+ console.log("sdk", { sdkAddress: address });
7574
7048
  useEffect(() => {
7575
- if (typeof window == 'undefined') {
7049
+ if (typeof window == "undefined") {
7576
7050
  return;
7577
7051
  }
7578
- const access = localStorage.getItem('accessToken');
7579
- const refresh = localStorage.getItem('refreshToken');
7580
- const addr = localStorage.getItem('address');
7581
- setAccessToken(access);
7582
- setRefreshToken(refresh);
7583
- setAddress(addr);
7584
- const authed = Boolean(access && addr);
7585
- setIsAuthenticated(authed);
7052
+ if (address) {
7053
+ // If we already have an address in state, use it to load the session
7054
+ const accessTokenKey = `${address}_accessToken`;
7055
+ const refreshTokenKey = `${address}_refreshToken`;
7056
+ const storedAccessToken = localStorage.getItem(accessTokenKey);
7057
+ const storedRefreshToken = localStorage.getItem(refreshTokenKey);
7058
+ console.log({ storedAccessToken, storedRefreshToken });
7059
+ if (storedAccessToken && storedRefreshToken) {
7060
+ setAccessToken(storedAccessToken);
7061
+ setRefreshToken(storedRefreshToken);
7062
+ setIsAuthenticated(true);
7063
+ }
7064
+ }
7586
7065
  setIsReady(true);
7587
- }, [setAccessToken, setRefreshToken, setIsAuthenticated, setAddress]);
7066
+ }, [address]);
7588
7067
  useEffect(() => {
7589
7068
  const cleanup = addAuthInterceptors({
7590
7069
  apiBaseUrl,
7591
7070
  getAccessToken: () => {
7592
- return typeof window !== 'undefined' ? window.localStorage.getItem('accessToken') : null;
7071
+ if (typeof window === "undefined")
7072
+ return null;
7073
+ // Read from Zustand state as single source of truth
7074
+ return useUserData.getState().accessToken;
7593
7075
  },
7594
7076
  refreshTokens: async () => {
7595
7077
  const data = await refreshTokens();
@@ -7610,17 +7092,18 @@ function useAuth() {
7610
7092
  async function loginWithSignedMessage(address, signature, timestamp) {
7611
7093
  try {
7612
7094
  const { data } = await authenticate(apiBaseUrl, {
7613
- method: 'eip712',
7095
+ method: "eip712",
7614
7096
  address,
7615
7097
  clientId,
7616
7098
  details: { signature, timestamp },
7617
7099
  });
7618
- window.localStorage.setItem('accessToken', data.accessToken);
7619
- window.localStorage.setItem('refreshToken', data.refreshToken);
7620
- window.localStorage.setItem('address', address);
7100
+ const accessTokenKey = `${address}_accessToken`;
7101
+ const refreshTokenKey = `${address}_refreshToken`;
7102
+ window.localStorage.setItem(accessTokenKey, data.accessToken);
7103
+ window.localStorage.setItem(refreshTokenKey, data.refreshToken);
7621
7104
  setAccessToken(data.accessToken);
7622
7105
  setRefreshToken(data.refreshToken);
7623
- setAddress(address);
7106
+ // setAddress(address);
7624
7107
  setIsAuthenticated(true);
7625
7108
  }
7626
7109
  catch (e) {
@@ -7629,13 +7112,19 @@ function useAuth() {
7629
7112
  }
7630
7113
  async function loginWithPrivyToken(address, appId, privyAccessToken) {
7631
7114
  try {
7632
- const { data } = await authenticateWithPrivy(apiBaseUrl, { address, clientId, appId, accessToken: privyAccessToken });
7633
- window.localStorage.setItem('accessToken', data.accessToken);
7634
- window.localStorage.setItem('refreshToken', data.refreshToken);
7635
- window.localStorage.setItem('address', address);
7115
+ const { data } = await authenticateWithPrivy(apiBaseUrl, {
7116
+ address,
7117
+ clientId,
7118
+ appId,
7119
+ accessToken: privyAccessToken,
7120
+ });
7121
+ const accessTokenKey = `${address}_accessToken`;
7122
+ const refreshTokenKey = `${address}_refreshToken`;
7123
+ window.localStorage.setItem(accessTokenKey, data.accessToken);
7124
+ window.localStorage.setItem(refreshTokenKey, data.refreshToken);
7636
7125
  setAccessToken(data.accessToken);
7637
7126
  setRefreshToken(data.refreshToken);
7638
- setAddress(address);
7127
+ // setAddress(address);
7639
7128
  setIsAuthenticated(true);
7640
7129
  }
7641
7130
  catch (e) {
@@ -7643,31 +7132,41 @@ function useAuth() {
7643
7132
  }
7644
7133
  }
7645
7134
  async function refreshTokens() {
7646
- const refresh = window.localStorage.getItem('refreshToken');
7647
- if (!refresh)
7648
- throw new Error('No refresh token');
7649
- const { data } = await refreshToken(apiBaseUrl, refresh);
7650
- window.localStorage.setItem('accessToken', data.accessToken);
7651
- window.localStorage.setItem('refreshToken', data.refreshToken);
7135
+ const currentAddress = address;
7136
+ const currentRefresh = refreshToken$1;
7137
+ if (!currentRefresh || !currentAddress)
7138
+ throw new Error("No refresh token");
7139
+ const { data } = await refreshToken(apiBaseUrl, currentRefresh);
7140
+ // Update tokens in localStorage
7141
+ const accessTokenKey = `${currentAddress}_accessToken`;
7142
+ const refreshTokenKey = `${currentAddress}_refreshToken`;
7143
+ window.localStorage.setItem(accessTokenKey, data.accessToken);
7144
+ window.localStorage.setItem(refreshTokenKey, data.refreshToken);
7652
7145
  setAccessToken(data.accessToken);
7653
7146
  setRefreshToken(data.refreshToken);
7654
7147
  setIsAuthenticated(true);
7655
7148
  return data;
7656
7149
  }
7657
7150
  async function logout$1() {
7658
- const refresh = window.localStorage.getItem('refreshToken');
7659
- if (refresh) {
7151
+ const currentAddress = address;
7152
+ const currentRefresh = refreshToken$1;
7153
+ if (currentRefresh) {
7660
7154
  try {
7661
- await logout(apiBaseUrl, refresh);
7155
+ await logout(apiBaseUrl, currentRefresh);
7662
7156
  }
7663
- catch ( /* ignore */_a) { /* ignore */ }
7157
+ catch (_a) {
7158
+ /* ignore */
7159
+ }
7160
+ }
7161
+ if (currentAddress) {
7162
+ const accessTokenKey = `${currentAddress}_accessToken`;
7163
+ const refreshTokenKey = `${currentAddress}_refreshToken`;
7164
+ window.localStorage.removeItem(accessTokenKey);
7165
+ window.localStorage.removeItem(refreshTokenKey);
7664
7166
  }
7665
- window.localStorage.removeItem('accessToken');
7666
- window.localStorage.removeItem('refreshToken');
7667
- window.localStorage.removeItem('address');
7668
7167
  setAccessToken(null);
7669
7168
  setRefreshToken(null);
7670
- setAddress(null);
7169
+ // setAddress(null);
7671
7170
  setIsAuthenticated(false);
7672
7171
  }
7673
7172
  return {
@@ -7680,6 +7179,8 @@ function useAuth() {
7680
7179
  loginWithPrivyToken,
7681
7180
  refreshTokens,
7682
7181
  logout: logout$1,
7182
+ setAddress,
7183
+ address,
7683
7184
  };
7684
7185
  }
7685
7186
 
@@ -7687,13 +7188,11 @@ const PearHyperliquidContext = createContext(undefined);
7687
7188
  /**
7688
7189
  * React Provider for PearHyperliquidClient
7689
7190
  */
7690
- const PearHyperliquidProvider = ({ children, apiBaseUrl = 'https://hl-v2.pearprotocol.io', clientId = 'PEARPROTOCOLUI', wsUrl = 'wss://hl-v2.pearprotocol.io/ws', }) => {
7191
+ const PearHyperliquidProvider = ({ children, apiBaseUrl = "https://hl-v2.pearprotocol.io", clientId = "PEARPROTOCOLUI", wsUrl = "wss://hl-v2.pearprotocol.io/ws", }) => {
7691
7192
  const address = useUserData((s) => s.address);
7692
- const setAddress = useUserData((s) => s.setAddress);
7693
7193
  const perpsMetaAssets = useHyperliquidData((state) => state.perpMetaAssets);
7694
7194
  const setPerpMetaAssets = useHyperliquidData((state) => state.setPerpMetaAssets);
7695
- const setHip3Assets = useHyperliquidData((state) => state.setHip3Assets);
7696
- const setHip3MarketPrefixes = useHyperliquidData((state) => state.setHip3MarketPrefixes);
7195
+ const setHip3DisplayToFull = useHyperliquidData((state) => state.setHip3DisplayToFull);
7697
7196
  const websocketsEnabled = useMemo(() => Array.isArray(perpsMetaAssets) && perpsMetaAssets.length > 0, [perpsMetaAssets]);
7698
7197
  const { isConnected, lastError } = useHyperliquidWebSocket({
7699
7198
  wsUrl,
@@ -7708,62 +7207,28 @@ const PearHyperliquidProvider = ({ children, apiBaseUrl = 'https://hl-v2.pearpro
7708
7207
  if (perpsMetaAssets === null) {
7709
7208
  fetchAllPerpMetas()
7710
7209
  .then((res) => {
7711
- // Maps for multi-market assets
7712
- const assetToMarkets = new Map(); // TSLA -> ["xyz:TSLA", "flx:TSLA"]
7713
- const marketPrefixes = new Map(); // "xyz:TSLA" -> "xyz"
7714
- const cleanedPerpMetas = [];
7715
- // Process each market group (different collateral tokens)
7716
- res.data.forEach((item) => {
7717
- // Convert numeric collateral token to human-readable name
7718
- const collateralToken = item.collateralToken === 360 ? 'USDH' : 'USDC';
7719
- item.universe.forEach((asset) => {
7720
- var _a;
7721
- const [maybePrefix, maybeMarket] = asset.name.split(':');
7722
- if (maybeMarket) {
7723
- // HIP-3 market with prefix (e.g., "xyz:TSLA")
7724
- const prefix = maybePrefix.toLowerCase();
7725
- const displayName = maybeMarket;
7726
- const fullName = `${prefix}:${displayName}`;
7727
- // Store full market name with prefix
7728
- marketPrefixes.set(fullName, prefix);
7729
- // Track all markets for this asset
7730
- const existingMarkets = (_a = assetToMarkets.get(displayName)) !== null && _a !== void 0 ? _a : [];
7731
- if (!existingMarkets.includes(fullName)) {
7732
- assetToMarkets.set(displayName, [
7733
- ...existingMarkets,
7734
- fullName,
7735
- ]);
7736
- }
7737
- // Add asset with all metadata INCLUDING collateral token for THIS specific market
7738
- // Important: We keep ALL variants so each market+collateral combo is tracked
7739
- cleanedPerpMetas.push({
7740
- ...asset,
7741
- name: displayName, // Use display name for UI
7742
- marketPrefix: prefix, // Which market (xyz, flx, etc)
7743
- collateralToken, // "USDC" or "USDH"
7744
- });
7745
- }
7746
- else {
7747
- // Regular market without prefix
7748
- cleanedPerpMetas.push({
7749
- ...asset,
7750
- collateralToken, // "USDC" or "USDH"
7751
- });
7752
- }
7753
- });
7210
+ const aggregatedPerpMetas = res.data.flatMap((item) => item.universe);
7211
+ const hip3Map = new Map();
7212
+ const displayToFull = new Map();
7213
+ const cleanedPerpMetas = aggregatedPerpMetas.map((asset) => {
7214
+ var _a;
7215
+ const [maybePrefix, maybeMarket] = asset.name.split(":");
7216
+ if (maybeMarket) {
7217
+ const prefix = maybePrefix.toLowerCase();
7218
+ const market = maybeMarket;
7219
+ const existing = (_a = hip3Map.get(prefix)) !== null && _a !== void 0 ? _a : [];
7220
+ hip3Map.set(prefix, [...existing, market]);
7221
+ displayToFull.set(market, `${prefix}:${market}`);
7222
+ return { ...asset, name: market };
7223
+ }
7224
+ return asset;
7754
7225
  });
7755
- setHip3Assets(assetToMarkets);
7756
- setHip3MarketPrefixes(marketPrefixes);
7226
+ setHip3DisplayToFull(displayToFull);
7757
7227
  setPerpMetaAssets(cleanedPerpMetas);
7758
7228
  })
7759
7229
  .catch(() => { });
7760
7230
  }
7761
- }, [
7762
- perpsMetaAssets,
7763
- setPerpMetaAssets,
7764
- setHip3Assets,
7765
- setHip3MarketPrefixes,
7766
- ]);
7231
+ }, [perpsMetaAssets, setPerpMetaAssets, setHip3DisplayToFull]);
7767
7232
  // Auth methods now sourced from useAuth hook
7768
7233
  useAutoSyncFills({
7769
7234
  baseUrl: apiBaseUrl,
@@ -7786,8 +7251,6 @@ const PearHyperliquidProvider = ({ children, apiBaseUrl = 'https://hl-v2.pearpro
7786
7251
  }), [
7787
7252
  apiBaseUrl,
7788
7253
  wsUrl,
7789
- address,
7790
- setAddress,
7791
7254
  isConnected,
7792
7255
  lastError,
7793
7256
  nativeIsConnected,
@@ -7802,7 +7265,7 @@ const PearHyperliquidProvider = ({ children, apiBaseUrl = 'https://hl-v2.pearpro
7802
7265
  function usePearHyperliquid() {
7803
7266
  const ctx = useContext(PearHyperliquidContext);
7804
7267
  if (!ctx)
7805
- throw new Error('usePearHyperliquid must be used within a PearHyperliquidProvider');
7268
+ throw new Error("usePearHyperliquid must be used within a PearHyperliquidProvider");
7806
7269
  return ctx;
7807
7270
  }
7808
7271
 
@@ -7893,4 +7356,4 @@ function mapCandleIntervalToTradingViewInterval(interval) {
7893
7356
  }
7894
7357
  }
7895
7358
 
7896
- export { AccountSummaryCalculator, ConflictDetector, MINIMUM_ASSET_USD_VALUE, MinimumPositionSizeError, PearHyperliquidProvider, TokenMetadataExtractor, adjustAdvancePosition, adjustOrder, adjustPosition, calculateMinimumPositionValue, calculateWeightedRatio, cancelOrder, cancelTwap, cancelTwapOrder, closeAllPositions, closePosition, computeBasketCandles, createCandleLookups, createPosition, executeSpotOrder, getAvailableMarkets, getCompleteTimestamps, getMarketPrefix, getPortfolio, isHip3Market, mapCandleIntervalToTradingViewInterval, mapTradingViewIntervalToCandleInterval, markNotificationReadById, markNotificationsRead, toBackendSymbol, toBackendSymbolWithMarket, toDisplaySymbol, toggleWatchlist, updateRiskParameters, useAccountSummary, useActiveBaskets, useAgentWallet, useAllBaskets, useAuth, useAutoSyncFills, useBasketCandles, useFindBasket, useHighlightedBaskets, useHistoricalPriceData, useHistoricalPriceDataStore, useHyperliquidNativeWebSocket, useHyperliquidWebSocket, useMarketData, useMarketDataAllPayload, useMarketDataPayload, useNotifications, useOpenOrders, useOrders, usePearHyperliquid, usePerformanceOverlays, usePerpMetaAssets, usePortfolio, usePosition, useSpotOrder, useTokenSelectionMetadata, useTopGainers, useTopLosers, useTradeHistories, useTwap, useUserSelection, useWatchlist, useWatchlistBaskets, useWebData, validateMinimumAssetSize, validatePositionSize };
7359
+ export { AccountSummaryCalculator, ConflictDetector, MINIMUM_ASSET_USD_VALUE, 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, validateMinimumAssetSize, validatePositionSize };