@pear-protocol/hyperliquid-sdk 0.0.66-usdh-1 → 0.0.67

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
@@ -23,7 +23,6 @@ const useUserData = create((set) => ({
23
23
  twapDetails: null,
24
24
  notifications: null,
25
25
  userExtraAgents: null,
26
- spotState: null,
27
26
  setAccessToken: (token) => set({ accessToken: token }),
28
27
  setRefreshToken: (token) => set({ refreshToken: token }),
29
28
  setIsAuthenticated: (value) => set({ isAuthenticated: value }),
@@ -44,7 +43,6 @@ const useUserData = create((set) => ({
44
43
  setAccountSummary: (value) => set({ accountSummary: value }),
45
44
  setTwapDetails: (value) => set({ twapDetails: value }),
46
45
  setNotifications: (value) => set({ notifications: value }),
47
- setSpotState: (value) => set({ spotState: value }),
48
46
  clean: () => set({
49
47
  accessToken: null,
50
48
  refreshToken: null,
@@ -56,7 +54,6 @@ const useUserData = create((set) => ({
56
54
  accountSummary: null,
57
55
  twapDetails: null,
58
56
  notifications: null,
59
- spotState: null,
60
57
  }),
61
58
  setUserExtraAgents: (value) => set({ userExtraAgents: value }),
62
59
  }));
@@ -74,71 +71,18 @@ const useMarketData = create((set) => ({
74
71
  * Convert a full/prefixed symbol (e.g., "xyz:XYZ100") to a display symbol (e.g., "XYZ100").
75
72
  */
76
73
  function toDisplaySymbol(symbol) {
77
- const parts = symbol.split(':');
74
+ const parts = symbol.split(":");
78
75
  return parts.length > 1 ? parts.slice(-1)[0] : symbol;
79
76
  }
80
77
  /**
81
78
  * Convert a display symbol back to backend form using a provided map.
82
79
  * If mapping is missing, returns the original symbol.
83
- * For multi-market assets, returns the first available market.
84
- * @param displaySymbol e.g., "TSLA"
85
- * @param hip3Assets map of display -> all full market names (e.g., "TSLA" -> ["xyz:TSLA", "flx:TSLA"])
80
+ * @param displaySymbol e.g., "XYZ100"
81
+ * @param displayToFull map of display -> full (e.g., "XYZ100" -> "xyz:XYZ100")
86
82
  */
87
- function toBackendSymbol(displaySymbol, hip3Assets) {
88
- const markets = hip3Assets.get(displaySymbol);
89
- // Return first market if available, otherwise return original symbol
90
- return markets && markets.length > 0 ? markets[0] : displaySymbol;
91
- }
92
- /**
93
- * Convert a display symbol to backend form for a specific market prefix.
94
- * This is useful when an asset is available on multiple markets (e.g., xyz:TSLA and flx:TSLA).
95
- * @param displaySymbol e.g., "TSLA"
96
- * @param marketPrefix e.g., "xyz" or "flx"
97
- * @param hip3Assets map of display -> all full market names
98
- * @returns Full market name if found, null if prefix not specified for multi-market asset, otherwise displaySymbol with prefix
99
- */
100
- function toBackendSymbolWithMarket(displaySymbol, marketPrefix, hip3Assets) {
101
- const availableMarkets = hip3Assets.get(displaySymbol);
102
- if (!availableMarkets || availableMarkets.length === 0) {
103
- // Not a HIP-3 asset, return as-is or with prefix if provided
104
- return marketPrefix ? `${marketPrefix}:${displaySymbol}` : displaySymbol;
105
- }
106
- if (marketPrefix) {
107
- // Find the market with the specified prefix
108
- const targetMarket = availableMarkets.find((market) => market.toLowerCase().startsWith(`${marketPrefix.toLowerCase()}:`));
109
- if (targetMarket) {
110
- return targetMarket;
111
- }
112
- }
113
- // No prefix specified or not found, return null to force explicit market selection
114
- return null;
115
- }
116
- /**
117
- * Get all available markets for a display symbol.
118
- * @param displaySymbol e.g., "TSLA"
119
- * @param hip3Assets map of display -> all full market names
120
- * @returns Array of full market names, e.g., ["xyz:TSLA", "flx:TSLA"]
121
- */
122
- function getAvailableMarkets(displaySymbol, hip3Assets) {
83
+ function toBackendSymbol(displaySymbol, displayToFull) {
123
84
  var _a;
124
- return (_a = hip3Assets.get(displaySymbol)) !== null && _a !== void 0 ? _a : [];
125
- }
126
- /**
127
- * Extract the market prefix from a full market name.
128
- * @param fullSymbol e.g., "xyz:TSLA"
129
- * @returns The prefix (e.g., "xyz") or undefined if no prefix
130
- */
131
- function getMarketPrefix(fullSymbol) {
132
- const parts = fullSymbol.split(':');
133
- return parts.length > 1 ? parts[0] : undefined;
134
- }
135
- /**
136
- * Check if a symbol is a HIP-3 market (has a prefix).
137
- * @param symbol e.g., "xyz:TSLA" or "TSLA"
138
- * @returns true if the symbol has a market prefix
139
- */
140
- function isHip3Market(symbol) {
141
- return symbol.includes(':');
85
+ return (_a = displayToFull.get(displaySymbol)) !== null && _a !== void 0 ? _a : displaySymbol;
142
86
  }
143
87
 
144
88
  const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
@@ -155,8 +99,7 @@ const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
155
99
  try {
156
100
  const message = JSON.parse(event.data);
157
101
  // Handle subscription responses (only if they don't have channel data)
158
- if (('success' in message || 'error' in message) &&
159
- !('channel' in message)) {
102
+ if (('success' in message || 'error' in message) && !('channel' in message)) {
160
103
  if (message.error) {
161
104
  setLastError(message.error);
162
105
  }
@@ -175,21 +118,12 @@ const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
175
118
  switch (dataMessage.channel) {
176
119
  case 'trade-histories':
177
120
  {
178
- const mapAsset = (a) => {
179
- var _a, _b;
180
- const extractedPrefix = getMarketPrefix(a.coin);
181
- return {
182
- ...a,
183
- coin: toDisplaySymbol(a.coin),
184
- marketPrefix: (_b = (_a = a.marketPrefix) !== null && _a !== void 0 ? _a : extractedPrefix) !== null && _b !== void 0 ? _b : null,
185
- };
186
- };
187
121
  const list = dataMessage.data.map((item) => {
188
122
  var _a, _b;
189
123
  return ({
190
124
  ...item,
191
- closedLongAssets: item.closedLongAssets.map(mapAsset),
192
- closedShortAssets: item.closedShortAssets.map(mapAsset),
125
+ closedLongAssets: item.closedLongAssets.map((a) => ({ ...a, coin: toDisplaySymbol(a.coin) })),
126
+ closedShortAssets: item.closedShortAssets.map((a) => ({ ...a, coin: toDisplaySymbol(a.coin) })),
193
127
  positionLongAssets: (_a = item.positionLongAssets) === null || _a === void 0 ? void 0 : _a.map((a) => toDisplaySymbol(a)),
194
128
  positionShortAssets: (_b = item.positionShortAssets) === null || _b === void 0 ? void 0 : _b.map((a) => toDisplaySymbol(a)),
195
129
  });
@@ -199,19 +133,10 @@ const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
199
133
  break;
200
134
  case 'open-positions':
201
135
  {
202
- const enrichAsset = (a) => {
203
- var _a, _b;
204
- const extractedPrefix = getMarketPrefix(a.coin);
205
- return {
206
- ...a,
207
- coin: toDisplaySymbol(a.coin),
208
- marketPrefix: (_b = (_a = a.marketPrefix) !== null && _a !== void 0 ? _a : extractedPrefix) !== null && _b !== void 0 ? _b : null,
209
- };
210
- };
211
136
  const list = dataMessage.data.map((pos) => ({
212
137
  ...pos,
213
- longAssets: pos.longAssets.map(enrichAsset),
214
- shortAssets: pos.shortAssets.map(enrichAsset),
138
+ longAssets: pos.longAssets.map((a) => ({ ...a, coin: toDisplaySymbol(a.coin) })),
139
+ shortAssets: pos.shortAssets.map((a) => ({ ...a, coin: toDisplaySymbol(a.coin) })),
215
140
  }));
216
141
  setRawOpenPositions(list);
217
142
  }
@@ -220,14 +145,8 @@ const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
220
145
  {
221
146
  const list = dataMessage.data.map((order) => ({
222
147
  ...order,
223
- longAssets: order.longAssets.map((a) => ({
224
- ...a,
225
- asset: toDisplaySymbol(a.asset),
226
- })),
227
- shortAssets: order.shortAssets.map((a) => ({
228
- ...a,
229
- asset: toDisplaySymbol(a.asset),
230
- })),
148
+ longAssets: order.longAssets.map((a) => ({ ...a, asset: toDisplaySymbol(a.asset) })),
149
+ shortAssets: order.shortAssets.map((a) => ({ ...a, asset: toDisplaySymbol(a.asset) })),
231
150
  }));
232
151
  setOpenOrders(list);
233
152
  }
@@ -237,20 +156,10 @@ const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
237
156
  break;
238
157
  case 'twap-details':
239
158
  {
240
- const mapTwapAsset = (a) => {
241
- var _a, _b, _c;
242
- const extractedPrefix = getMarketPrefix(a.asset);
243
- return {
244
- ...a,
245
- asset: toDisplaySymbol(a.asset),
246
- marketPrefix: (_b = (_a = a.marketPrefix) !== null && _a !== void 0 ? _a : extractedPrefix) !== null && _b !== void 0 ? _b : null,
247
- collateralToken: (_c = a.collateralToken) !== null && _c !== void 0 ? _c : undefined,
248
- };
249
- };
250
159
  const list = dataMessage.data.map((twap) => ({
251
160
  ...twap,
252
- longAssets: twap.longAssets.map(mapTwapAsset),
253
- shortAssets: twap.shortAssets.map(mapTwapAsset),
161
+ longAssets: twap.longAssets.map((a) => ({ ...a, asset: toDisplaySymbol(a.asset) })),
162
+ shortAssets: twap.shortAssets.map((a) => ({ ...a, asset: toDisplaySymbol(a.asset) })),
254
163
  }));
255
164
  setTwapDetails(list);
256
165
  }
@@ -263,14 +172,8 @@ const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
263
172
  const md = dataMessage.data;
264
173
  const mapGroup = (g) => ({
265
174
  ...g,
266
- longAssets: g.longAssets.map((a) => ({
267
- ...a,
268
- asset: toDisplaySymbol(a.asset),
269
- })),
270
- shortAssets: g.shortAssets.map((a) => ({
271
- ...a,
272
- asset: toDisplaySymbol(a.asset),
273
- })),
175
+ longAssets: g.longAssets.map((a) => ({ ...a, asset: toDisplaySymbol(a.asset) })),
176
+ shortAssets: g.shortAssets.map((a) => ({ ...a, asset: toDisplaySymbol(a.asset) })),
274
177
  });
275
178
  const mapped = {
276
179
  active: md.active.map(mapGroup),
@@ -288,15 +191,7 @@ const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
288
191
  catch (error) {
289
192
  setLastError(`Failed to parse message: ${error instanceof Error ? error.message : String(error)}`);
290
193
  }
291
- }, [
292
- setTradeHistories,
293
- setRawOpenPositions,
294
- setOpenOrders,
295
- setAccountSummary,
296
- setTwapDetails,
297
- setNotifications,
298
- setMarketData,
299
- ]);
194
+ }, [setTradeHistories, setRawOpenPositions, setOpenOrders, setAccountSummary, setTwapDetails, setNotifications, setMarketData]);
300
195
  const connect = useCallback(() => {
301
196
  if (!enabled || !wsUrl)
302
197
  return;
@@ -365,7 +260,7 @@ const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
365
260
  'open-orders',
366
261
  'twap-details',
367
262
  'fills-checkpoint',
368
- 'notifications',
263
+ 'notifications'
369
264
  ];
370
265
  const globalChannels = ['market-data'];
371
266
  if (address && address !== lastSubscribedAddress) {
@@ -374,14 +269,14 @@ const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
374
269
  sendMessage(JSON.stringify({
375
270
  action: 'unsubscribe',
376
271
  address: lastSubscribedAddress,
377
- channels: addressSpecificChannels,
272
+ channels: addressSpecificChannels
378
273
  }));
379
274
  }
380
275
  // Subscribe to all channels (global + address-specific)
381
276
  sendMessage(JSON.stringify({
382
277
  action: 'subscribe',
383
278
  address: address,
384
- channels: [...globalChannels, ...addressSpecificChannels],
279
+ channels: [...globalChannels, ...addressSpecificChannels]
385
280
  }));
386
281
  setLastSubscribedAddress(address);
387
282
  setLastError(null);
@@ -391,7 +286,7 @@ const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
391
286
  sendMessage(JSON.stringify({
392
287
  action: 'unsubscribe',
393
288
  address: lastSubscribedAddress,
394
- channels: addressSpecificChannels,
289
+ channels: addressSpecificChannels
395
290
  }));
396
291
  setLastSubscribedAddress(null);
397
292
  }
@@ -399,7 +294,7 @@ const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
399
294
  // If no address but connected, subscribe to global channels only
400
295
  sendMessage(JSON.stringify({
401
296
  action: 'subscribe',
402
- channels: globalChannels,
297
+ channels: globalChannels
403
298
  }));
404
299
  }
405
300
  }, [isConnected, address, lastSubscribedAddress, sendMessage]);
@@ -423,12 +318,10 @@ const useHyperliquidData = create((set, get) => ({
423
318
  finalAtOICaps: null,
424
319
  aggregatedClearingHouseState: null,
425
320
  perpMetaAssets: null,
426
- allPerpMetaAssets: null,
427
- hip3Assets: new Map(),
428
- hip3MarketPrefixes: new Map(),
321
+ hip3DisplayToFull: new Map(),
429
322
  setAllMids: (value) => set({ allMids: value }),
430
323
  setActiveAssetData: (value) => set((state) => ({
431
- activeAssetData: typeof value === 'function' ? value(state.activeAssetData) : value,
324
+ activeAssetData: typeof value === 'function' ? value(state.activeAssetData) : value
432
325
  })),
433
326
  deleteActiveAssetData: (key) => {
434
327
  set((state) => {
@@ -463,15 +356,13 @@ const useHyperliquidData = create((set, get) => ({
463
356
  activeAssetData: {
464
357
  ...state.activeAssetData,
465
358
  [key]: value,
466
- },
359
+ }
467
360
  })),
468
361
  setFinalAssetContexts: (value) => set({ finalAssetContexts: value }),
469
362
  setFinalAtOICaps: (value) => set({ finalAtOICaps: value }),
470
363
  setAggregatedClearingHouseState: (value) => set({ aggregatedClearingHouseState: value }),
471
364
  setPerpMetaAssets: (value) => set({ perpMetaAssets: value }),
472
- setAllPerpMetaAssets: (value) => set({ allPerpMetaAssets: value }),
473
- setHip3Assets: (value) => set({ hip3Assets: value }),
474
- setHip3MarketPrefixes: (value) => set({ hip3MarketPrefixes: value }),
365
+ setHip3DisplayToFull: (value) => set({ hip3DisplayToFull: value })
475
366
  }));
476
367
 
477
368
  /**
@@ -734,12 +625,11 @@ const useUserSelection$1 = create((set, get) => ({
734
625
  }));
735
626
 
736
627
  const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
737
- const { setAllMids, setActiveAssetData, upsertActiveAssetData, setCandleData, deleteCandleSymbol, deleteActiveAssetData, addCandleData, setFinalAssetContexts, setFinalAtOICaps, setAggregatedClearingHouseState, } = useHyperliquidData();
738
- const { setSpotState } = useUserData();
628
+ const { setAllMids, setActiveAssetData, upsertActiveAssetData, setCandleData, deleteCandleSymbol, deleteActiveAssetData, addCandleData, setFinalAssetContexts, setFinalAtOICaps, setAggregatedClearingHouseState } = useHyperliquidData();
739
629
  const { candleInterval } = useUserSelection$1();
740
630
  const longTokens = useUserSelection$1((s) => s.longTokens);
741
631
  const shortTokens = useUserSelection$1((s) => s.shortTokens);
742
- const selectedTokenSymbols = useMemo(() => [...longTokens, ...shortTokens].map((t) => t.symbol), [longTokens, shortTokens]);
632
+ const selectedTokenSymbols = useMemo(() => ([...longTokens, ...shortTokens].map((t) => t.symbol)), [longTokens, shortTokens]);
743
633
  const [lastError, setLastError] = useState(null);
744
634
  const [subscribedAddress, setSubscribedAddress] = useState(null);
745
635
  const [subscribedTokens, setSubscribedTokens] = useState([]);
@@ -788,7 +678,7 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
788
678
  .map(([, s]) => s)
789
679
  .filter(Boolean);
790
680
  const sum = (values) => values.reduce((acc, v) => acc + (parseFloat(v || '0') || 0), 0);
791
- const toStr = (n) => Number.isFinite(n) ? n.toString() : '0';
681
+ const toStr = (n) => (Number.isFinite(n) ? n.toString() : '0');
792
682
  const assetPositions = states.flatMap((s) => s.assetPositions || []);
793
683
  const crossMaintenanceMarginUsed = toStr(sum(states.map((s) => s.crossMaintenanceMarginUsed)));
794
684
  const crossMarginSummary = {
@@ -819,42 +709,19 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
819
709
  case 'allMids':
820
710
  {
821
711
  const data = response.data;
822
- // Keep BOTH normalized prefixed keys AND display symbol keys
823
- // This ensures xyz:TSLA and flx:TSLA are stored separately,
824
- // while also maintaining backward compatibility with non-prefixed lookups
825
- const mids = {};
826
- Object.entries(data.mids || {}).forEach(([k, v]) => {
827
- // Normalize prefixed keys to lowercase prefix (e.g., "XYZ:TSLA" -> "xyz:TSLA")
828
- // This matches how we look up tokens in the SDK
829
- let normalizedKey = k;
830
- if (k.includes(':')) {
831
- const [prefix, ...rest] = k.split(':');
832
- normalizedKey = `${prefix.toLowerCase()}:${rest.join(':')}`;
833
- }
834
- // Store with normalized key
835
- mids[normalizedKey] = v;
836
- // Also store with original key for backward compatibility
837
- if (k !== normalizedKey) {
838
- mids[k] = v;
839
- }
840
- // Also store with display symbol for backward compatibility
841
- const displayKey = toDisplaySymbol(k);
842
- // Only set display key if it doesn't already exist (avoid overwriting market-specific prices)
843
- if (!(displayKey in mids)) {
844
- mids[displayKey] = v;
845
- }
846
- });
847
- setAllMids({ mids });
712
+ const remapped = {
713
+ mids: Object.fromEntries(
714
+ // 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]))
716
+ };
717
+ setAllMids(remapped);
848
718
  }
849
719
  break;
850
720
  case 'activeAssetData':
851
721
  {
852
722
  const assetData = response.data;
853
723
  const symbol = toDisplaySymbol(assetData.coin);
854
- const normalized = {
855
- ...assetData,
856
- coin: symbol,
857
- };
724
+ const normalized = { ...assetData, coin: symbol };
858
725
  upsertActiveAssetData(symbol, normalized);
859
726
  }
860
727
  break;
@@ -866,14 +733,6 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
866
733
  addCandleData(symbol, normalized);
867
734
  }
868
735
  break;
869
- case 'spotState':
870
- {
871
- const spotStateData = response.data;
872
- if (spotStateData === null || spotStateData === void 0 ? void 0 : spotStateData.spotState) {
873
- setSpotState(spotStateData.spotState);
874
- }
875
- }
876
- break;
877
736
  default:
878
737
  console.warn(`[HyperLiquid WS] Unknown channel: ${response.channel}`);
879
738
  }
@@ -884,15 +743,7 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
884
743
  console.error('[HyperLiquid WS] Parse error:', errorMessage, 'Raw message:', event.data);
885
744
  setLastError(errorMessage);
886
745
  }
887
- }, [
888
- setAllMids,
889
- upsertActiveAssetData,
890
- addCandleData,
891
- setFinalAssetContexts,
892
- setFinalAtOICaps,
893
- setAggregatedClearingHouseState,
894
- setSpotState,
895
- ]);
746
+ }, [setAllMids, upsertActiveAssetData, addCandleData, setFinalAssetContexts, setFinalAtOICaps, setAggregatedClearingHouseState]);
896
747
  const connect = useCallback(() => {
897
748
  if (!enabled)
898
749
  return;
@@ -990,17 +841,6 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
990
841
  },
991
842
  };
992
843
  sendJsonMessage(unsubscribeMessage);
993
- // Unsubscribe from spotState for previous address
994
- if (subscribedAddress !== DEFAULT_ADDRESS) {
995
- const unsubscribeSpotState = {
996
- method: 'unsubscribe',
997
- subscription: {
998
- type: 'spotState',
999
- user: subscribedAddress,
1000
- },
1001
- };
1002
- sendJsonMessage(unsubscribeSpotState);
1003
- }
1004
844
  const unsubscribeAllDexsClearinghouseState = {
1005
845
  method: 'unsubscribe',
1006
846
  subscription: {
@@ -1044,34 +884,13 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
1044
884
  sendJsonMessage(subscribeAllDexsClearinghouseState);
1045
885
  sendJsonMessage(subscribeAllMids);
1046
886
  sendJsonMessage(subscribeAllDexsAssetCtxs);
1047
- // Subscribe to spotState for real-time spot balances (USDH, USDC, etc.)
1048
- // Only subscribe if we have a real user address (not the default)
1049
- if (userAddress !== DEFAULT_ADDRESS) {
1050
- const subscribeSpotState = {
1051
- method: 'subscribe',
1052
- subscription: {
1053
- type: 'spotState',
1054
- user: userAddress,
1055
- },
1056
- };
1057
- sendJsonMessage(subscribeSpotState);
1058
- }
1059
887
  setSubscribedAddress(userAddress);
1060
888
  // Clear previous data when address changes
1061
889
  if (subscribedAddress && subscribedAddress !== userAddress) {
1062
890
  // clear aggregatedClearingHouseState
1063
891
  setAggregatedClearingHouseState(null);
1064
- // clear spotState
1065
- setSpotState(null);
1066
892
  }
1067
- }, [
1068
- isConnected,
1069
- address,
1070
- subscribedAddress,
1071
- sendJsonMessage,
1072
- setAggregatedClearingHouseState,
1073
- setSpotState,
1074
- ]);
893
+ }, [isConnected, address, subscribedAddress, sendJsonMessage, setAggregatedClearingHouseState]);
1075
894
  // Handle token subscriptions for activeAssetData
1076
895
  useEffect(() => {
1077
896
  if (!isConnected || !address)
@@ -1080,7 +899,7 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
1080
899
  const tokensToSubscribe = effectiveTokens.filter((token) => token && !subscribedTokens.includes(token));
1081
900
  const tokensToUnsubscribe = subscribedTokens.filter((token) => !effectiveTokens.includes(token));
1082
901
  // Unsubscribe from tokens no longer in the list
1083
- tokensToUnsubscribe.forEach((token) => {
902
+ tokensToUnsubscribe.forEach(token => {
1084
903
  const unsubscribeMessage = {
1085
904
  method: 'unsubscribe',
1086
905
  subscription: {
@@ -1092,7 +911,7 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
1092
911
  sendJsonMessage(unsubscribeMessage);
1093
912
  });
1094
913
  // Subscribe to new tokens
1095
- tokensToSubscribe.forEach((token) => {
914
+ tokensToSubscribe.forEach(token => {
1096
915
  const subscribeMessage = {
1097
916
  method: 'subscribe',
1098
917
  subscription: {
@@ -1107,14 +926,7 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
1107
926
  setSubscribedTokens(effectiveTokens.filter((token) => token));
1108
927
  tokensToSubscribe.forEach((token) => deleteActiveAssetData(token));
1109
928
  }
1110
- }, [
1111
- isConnected,
1112
- address,
1113
- selectedTokenSymbols,
1114
- subscribedTokens,
1115
- sendJsonMessage,
1116
- setActiveAssetData,
1117
- ]);
929
+ }, [isConnected, address, selectedTokenSymbols, subscribedTokens, sendJsonMessage, setActiveAssetData]);
1118
930
  // Handle candle subscriptions for tokens and interval changes
1119
931
  useEffect(() => {
1120
932
  if (!isConnected)
@@ -1123,7 +935,7 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
1123
935
  // Unsubscribe from previous candle subscriptions if interval changed
1124
936
  const prevInterval = prevCandleIntervalRef.current;
1125
937
  if (prevInterval && prevInterval !== candleInterval) {
1126
- subscribedCandleTokens.forEach((token) => {
938
+ subscribedCandleTokens.forEach(token => {
1127
939
  const unsubscribeMessage = {
1128
940
  method: 'unsubscribe',
1129
941
  subscription: {
@@ -1164,21 +976,12 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, }) => {
1164
976
  sendJsonMessage(subscribeMessage);
1165
977
  });
1166
978
  // Update subscribed state
1167
- if (tokensToSubscribe.length > 0 ||
1168
- tokensToUnsubscribe.length > 0 ||
1169
- prevInterval !== candleInterval) {
979
+ if (tokensToSubscribe.length > 0 || tokensToUnsubscribe.length > 0 || prevInterval !== candleInterval) {
1170
980
  setSubscribedCandleTokens(effectiveTokens.filter((token) => token));
1171
981
  prevCandleIntervalRef.current = candleInterval;
1172
982
  tokensToUnsubscribe.forEach((token) => deleteCandleSymbol(token));
1173
983
  }
1174
- }, [
1175
- isConnected,
1176
- selectedTokenSymbols,
1177
- candleInterval,
1178
- subscribedCandleTokens,
1179
- sendJsonMessage,
1180
- setCandleData,
1181
- ]);
984
+ }, [isConnected, selectedTokenSymbols, candleInterval, subscribedCandleTokens, sendJsonMessage, setCandleData]);
1182
985
  return {
1183
986
  isConnected,
1184
987
  lastError,
@@ -1267,112 +1070,20 @@ const useAccountSummary = () => {
1267
1070
  return { data: calculated, isLoading };
1268
1071
  };
1269
1072
 
1270
- function findAssetMeta$4(coinName, perpMetaAssets, knownPrefix, desiredCollateral) {
1271
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
1272
- if (!perpMetaAssets) {
1273
- return { collateralToken: 'USDC', marketPrefix: null };
1274
- }
1275
- if (desiredCollateral) {
1276
- const collateralMatch = perpMetaAssets.find((a) => a.name === coinName && a.collateralToken === desiredCollateral);
1277
- if (collateralMatch) {
1278
- return {
1279
- collateralToken: (_a = collateralMatch.collateralToken) !== null && _a !== void 0 ? _a : 'USDC',
1280
- marketPrefix: (_b = collateralMatch.marketPrefix) !== null && _b !== void 0 ? _b : null,
1281
- };
1282
- }
1283
- }
1284
- if (coinName.includes(':')) {
1285
- const [prefix, symbol] = coinName.split(':');
1286
- const exactMatch = perpMetaAssets.find((a) => {
1287
- var _a;
1288
- return a.name === symbol &&
1289
- ((_a = a.marketPrefix) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === prefix.toLowerCase();
1290
- });
1291
- if (exactMatch) {
1292
- return {
1293
- collateralToken: (_c = exactMatch.collateralToken) !== null && _c !== void 0 ? _c : 'USDC',
1294
- marketPrefix: (_d = exactMatch.marketPrefix) !== null && _d !== void 0 ? _d : null,
1295
- };
1296
- }
1297
- }
1298
- if (knownPrefix) {
1299
- const exactMatch = perpMetaAssets.find((a) => {
1300
- var _a;
1301
- return a.name === coinName &&
1302
- ((_a = a.marketPrefix) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === knownPrefix.toLowerCase();
1303
- });
1304
- if (exactMatch) {
1305
- return {
1306
- collateralToken: (_e = exactMatch.collateralToken) !== null && _e !== void 0 ? _e : 'USDC',
1307
- marketPrefix: (_f = exactMatch.marketPrefix) !== null && _f !== void 0 ? _f : null,
1308
- };
1309
- }
1310
- }
1311
- const exactMatch = perpMetaAssets.find((a) => a.name === coinName && !a.marketPrefix);
1312
- if (exactMatch) {
1313
- return {
1314
- collateralToken: (_g = exactMatch.collateralToken) !== null && _g !== void 0 ? _g : 'USDC',
1315
- marketPrefix: (_h = exactMatch.marketPrefix) !== null && _h !== void 0 ? _h : null,
1316
- };
1317
- }
1318
- const hip3Matches = perpMetaAssets.filter((a) => a.name === coinName && a.marketPrefix);
1319
- if (hip3Matches.length > 0) {
1320
- if (desiredCollateral) {
1321
- const collateralMatch = hip3Matches.find((a) => a.collateralToken === desiredCollateral);
1322
- if (collateralMatch) {
1323
- return {
1324
- collateralToken: (_j = collateralMatch.collateralToken) !== null && _j !== void 0 ? _j : 'USDC',
1325
- marketPrefix: (_k = collateralMatch.marketPrefix) !== null && _k !== void 0 ? _k : null,
1326
- };
1327
- }
1328
- }
1329
- const usdHMatch = hip3Matches.find((a) => a.collateralToken === 'USDH');
1330
- const chosen = usdHMatch !== null && usdHMatch !== void 0 ? usdHMatch : hip3Matches[0];
1331
- return {
1332
- collateralToken: (_l = chosen.collateralToken) !== null && _l !== void 0 ? _l : 'USDC',
1333
- marketPrefix: (_m = chosen.marketPrefix) !== null && _m !== void 0 ? _m : null,
1334
- };
1335
- }
1336
- return { collateralToken: 'USDC', marketPrefix: null };
1337
- }
1338
- function enrichTradeHistoryAssets(assets, perpMetaAssets) {
1339
- return assets.map((asset) => {
1340
- var _a;
1341
- if (asset.marketPrefix && asset.collateralToken) {
1342
- return asset;
1343
- }
1344
- const meta = findAssetMeta$4(asset.coin, perpMetaAssets, asset.marketPrefix, asset.collateralToken);
1345
- return {
1346
- ...asset,
1347
- marketPrefix: asset.marketPrefix || meta.marketPrefix,
1348
- collateralToken: (_a = asset.collateralToken) !== null && _a !== void 0 ? _a : meta.collateralToken,
1349
- };
1350
- });
1351
- }
1352
- function enrichTradeHistories(histories, perpMetaAssets) {
1353
- return histories.map((history) => ({
1354
- ...history,
1355
- closedLongAssets: enrichTradeHistoryAssets(history.closedLongAssets, perpMetaAssets),
1356
- closedShortAssets: enrichTradeHistoryAssets(history.closedShortAssets, perpMetaAssets),
1357
- }));
1358
- }
1359
1073
  const useTradeHistories = () => {
1360
1074
  const context = useContext(PearHyperliquidContext);
1361
1075
  if (!context) {
1362
1076
  throw new Error('useTradeHistories must be used within a PearHyperliquidProvider');
1363
1077
  }
1364
1078
  const tradeHistories = useUserData((state) => state.tradeHistories);
1365
- const allPerpMetaAssets = useHyperliquidData((state) => state.allPerpMetaAssets);
1366
1079
  const isLoading = useMemo(() => {
1367
1080
  return tradeHistories === null && context.isConnected;
1368
1081
  }, [tradeHistories, context.isConnected]);
1369
- const enrichedTradeHistories = useMemo(() => {
1370
- if (!tradeHistories)
1371
- return null;
1372
- return enrichTradeHistories(tradeHistories, allPerpMetaAssets);
1373
- }, [tradeHistories, allPerpMetaAssets]);
1374
- return { data: enrichedTradeHistories, isLoading };
1082
+ return { data: tradeHistories, isLoading };
1375
1083
  };
1084
+ /**
1085
+ * Hook to access open orders with loading state
1086
+ */
1376
1087
  const useOpenOrders = () => {
1377
1088
  const context = useContext(PearHyperliquidContext);
1378
1089
  if (!context) {
@@ -1401,51 +1112,21 @@ const useWebData = () => {
1401
1112
  const perpMetaAssets = useHyperliquidData((state) => state.perpMetaAssets);
1402
1113
  const aggregatedClearinghouseState = useHyperliquidData((state) => state.aggregatedClearingHouseState);
1403
1114
  const finalAtOICaps = useHyperliquidData((state) => state.finalAtOICaps);
1404
- const hip3Assets = useHyperliquidData((state) => state.hip3Assets);
1405
- const hip3MarketPrefixes = useHyperliquidData((state) => state.hip3MarketPrefixes);
1115
+ const hip3Assets = useHyperliquidData((state) => state.hip3DisplayToFull);
1406
1116
  let marketDataBySymbol = {};
1407
1117
  if (finalAssetContexts && perpMetaAssets) {
1408
1118
  const result = {};
1409
- // Build a map of display name -> asset context index (for unique display names)
1410
- const displayNameToContextIndex = new Map();
1411
- const seenNames = new Set();
1412
- let contextIndex = 0;
1413
- // First pass: map unique display names to their context index
1414
1119
  for (let index = 0; index < perpMetaAssets.length; index++) {
1415
1120
  const name = perpMetaAssets[index].name;
1416
- if (!seenNames.has(name)) {
1417
- seenNames.add(name);
1418
- if (contextIndex < finalAssetContexts.length) {
1419
- displayNameToContextIndex.set(name, contextIndex);
1420
- contextIndex++;
1421
- }
1422
- }
1423
- }
1424
- // Second pass: create nested entries for all market variants
1425
- for (let index = 0; index < perpMetaAssets.length; index++) {
1426
- const universeAsset = perpMetaAssets[index];
1427
- const displayName = universeAsset.name;
1428
- const marketPrefix = universeAsset.marketPrefix;
1429
- const ctxIndex = displayNameToContextIndex.get(displayName);
1430
- if (ctxIndex !== undefined) {
1431
- const assetContext = finalAssetContexts[ctxIndex];
1432
- // Initialize the symbol entry if it doesn't exist
1433
- if (!result[displayName]) {
1434
- result[displayName] = {};
1435
- }
1436
- // Use marketPrefix as key for HIP-3 assets, "default" for regular assets
1437
- const variantKey = marketPrefix || 'default';
1438
- result[displayName][variantKey] = {
1439
- asset: assetContext,
1440
- universe: universeAsset,
1441
- };
1442
- }
1121
+ result[name] = {
1122
+ asset: finalAssetContexts[index],
1123
+ universe: perpMetaAssets[index],
1124
+ };
1443
1125
  }
1444
1126
  marketDataBySymbol = result;
1445
1127
  }
1446
1128
  return {
1447
1129
  hip3Assets,
1448
- hip3MarketPrefixes,
1449
1130
  clearinghouseState: aggregatedClearinghouseState,
1450
1131
  perpsAtOpenInterestCap: finalAtOICaps,
1451
1132
  marketDataBySymbol,
@@ -1460,60 +1141,30 @@ const useWebData = () => {
1460
1141
  class TokenMetadataExtractor {
1461
1142
  /**
1462
1143
  * Extracts comprehensive token metadata
1463
- * @param symbol - Token symbol (base symbol without prefix, e.g., "TSLA")
1144
+ * @param symbol - Token symbol
1464
1145
  * @param perpMetaAssets - Aggregated universe assets (flattened across dexes)
1465
1146
  * @param finalAssetContexts - Aggregated asset contexts (flattened across dexes)
1466
1147
  * @param allMids - AllMids data containing current prices
1467
1148
  * @param activeAssetData - Optional active asset data containing leverage information
1468
- * @param marketPrefix - Optional market prefix (e.g., "xyz", "flx") for HIP3 multi-market assets
1469
1149
  * @returns TokenMetadata or null if token not found
1470
1150
  */
1471
- static extractTokenMetadata(symbol, perpMetaAssets, finalAssetContexts, allMids, activeAssetData, marketPrefix) {
1151
+ static extractTokenMetadata(symbol, perpMetaAssets, finalAssetContexts, allMids, activeAssetData) {
1472
1152
  if (!perpMetaAssets || !finalAssetContexts || !allMids) {
1473
1153
  return null;
1474
1154
  }
1475
1155
  // Find token index in aggregated universe
1476
- // For HIP3 assets, match both name AND marketPrefix
1477
- const universeIndex = perpMetaAssets.findIndex((asset) => {
1478
- if (asset.name !== symbol)
1479
- return false;
1480
- // If marketPrefix is specified, match it; otherwise match assets without prefix
1481
- if (marketPrefix) {
1482
- return asset.marketPrefix === marketPrefix;
1483
- }
1484
- // No prefix specified - match non-HIP3 asset (no marketPrefix) or first matching asset
1485
- return !asset.marketPrefix;
1486
- });
1487
- // If no exact match found and prefix was specified, try finding the specific market variant
1488
- const finalIndex = universeIndex === -1 && marketPrefix
1489
- ? perpMetaAssets.findIndex((asset) => asset.name === symbol && asset.marketPrefix === marketPrefix)
1490
- : universeIndex;
1491
- // Fallback: if still not found and no prefix, find first matching by name (for backward compatibility)
1492
- const resolvedIndex = finalIndex === -1
1493
- ? perpMetaAssets.findIndex((asset) => asset.name === symbol)
1494
- : finalIndex;
1495
- if (resolvedIndex === -1) {
1156
+ const universeIndex = perpMetaAssets.findIndex(asset => asset.name === symbol);
1157
+ if (universeIndex === -1) {
1496
1158
  return null;
1497
1159
  }
1498
- const universeAsset = perpMetaAssets[resolvedIndex];
1499
- const assetCtx = finalAssetContexts[resolvedIndex];
1160
+ const universeAsset = perpMetaAssets[universeIndex];
1161
+ const assetCtx = finalAssetContexts[universeIndex];
1500
1162
  if (!assetCtx) {
1501
1163
  return null;
1502
1164
  }
1503
- // Get current price - prefer assetCtx.midPx as it's already index-matched,
1504
- // fall back to allMids lookup if midPx is null
1505
- const prefixedKeyColon = marketPrefix ? `${marketPrefix}:${symbol}` : null;
1506
- let currentPrice = 0;
1507
- // Primary source: assetCtx.midPx (already properly indexed)
1508
- if (assetCtx.midPx) {
1509
- currentPrice = parseFloat(assetCtx.midPx);
1510
- }
1511
- // Fallback: allMids lookup with multiple key formats for HIP3 markets
1512
- if (!currentPrice || isNaN(currentPrice)) {
1513
- const currentPriceStr = (prefixedKeyColon && allMids.mids[prefixedKeyColon]) ||
1514
- allMids.mids[symbol];
1515
- currentPrice = currentPriceStr ? parseFloat(currentPriceStr) : 0;
1516
- }
1165
+ // Get current price from allMids
1166
+ const currentPriceStr = allMids.mids[symbol];
1167
+ const currentPrice = currentPriceStr ? parseFloat(currentPriceStr) : 0;
1517
1168
  // Get previous day price
1518
1169
  const prevDayPrice = parseFloat(assetCtx.prevDayPx);
1519
1170
  // Calculate 24h price change
@@ -1524,11 +1175,7 @@ class TokenMetadataExtractor {
1524
1175
  const markPrice = parseFloat(assetCtx.markPx);
1525
1176
  const oraclePrice = parseFloat(assetCtx.oraclePx);
1526
1177
  // Extract leverage info from activeAssetData if available
1527
- // Try prefixed key first (e.g., "xyz:TSLA"), then fall back to plain symbol
1528
- const activeDataKey = prefixedKeyColon && (activeAssetData === null || activeAssetData === void 0 ? void 0 : activeAssetData[prefixedKeyColon])
1529
- ? prefixedKeyColon
1530
- : symbol;
1531
- const tokenActiveData = activeAssetData === null || activeAssetData === void 0 ? void 0 : activeAssetData[activeDataKey];
1178
+ const tokenActiveData = activeAssetData === null || activeAssetData === void 0 ? void 0 : activeAssetData[symbol];
1532
1179
  const leverage = tokenActiveData === null || tokenActiveData === void 0 ? void 0 : tokenActiveData.leverage;
1533
1180
  const maxTradeSzs = tokenActiveData === null || tokenActiveData === void 0 ? void 0 : tokenActiveData.maxTradeSzs;
1534
1181
  const availableToTrade = tokenActiveData === null || tokenActiveData === void 0 ? void 0 : tokenActiveData.availableToTrade;
@@ -1546,27 +1193,21 @@ class TokenMetadataExtractor {
1546
1193
  leverage,
1547
1194
  maxTradeSzs,
1548
1195
  availableToTrade,
1549
- collateralToken: universeAsset.collateralToken,
1550
1196
  };
1551
1197
  }
1552
1198
  /**
1553
1199
  * Extracts metadata for multiple tokens
1554
- * @param tokens - Array of token objects with symbol and optional marketPrefix
1200
+ * @param symbols - Array of token symbols
1555
1201
  * @param perpMetaAssets - Aggregated universe assets
1556
1202
  * @param finalAssetContexts - Aggregated asset contexts
1557
1203
  * @param allMids - AllMids data
1558
1204
  * @param activeAssetData - Optional active asset data containing leverage information
1559
- * @returns Record of unique key to TokenMetadata. Key is "{prefix}:{symbol}" for HIP3 assets, or just "{symbol}" otherwise
1205
+ * @returns Record of symbol to TokenMetadata
1560
1206
  */
1561
- static extractMultipleTokensMetadata(tokens, perpMetaAssets, finalAssetContexts, allMids, activeAssetData) {
1207
+ static extractMultipleTokensMetadata(symbols, perpMetaAssets, finalAssetContexts, allMids, activeAssetData) {
1562
1208
  const result = {};
1563
- for (const token of tokens) {
1564
- // Use a unique key that includes the prefix for HIP3 assets
1565
- // This ensures xyz:TSLA and flx:TSLA get separate entries
1566
- const resultKey = token.marketPrefix
1567
- ? `${token.marketPrefix}:${token.symbol}`
1568
- : token.symbol;
1569
- result[resultKey] = this.extractTokenMetadata(token.symbol, perpMetaAssets, finalAssetContexts, allMids, activeAssetData, token.marketPrefix);
1209
+ for (const symbol of symbols) {
1210
+ result[symbol] = this.extractTokenMetadata(symbol, perpMetaAssets, finalAssetContexts, allMids, activeAssetData);
1570
1211
  }
1571
1212
  return result;
1572
1213
  }
@@ -1579,30 +1220,10 @@ class TokenMetadataExtractor {
1579
1220
  static isTokenAvailable(symbol, perpMetaAssets) {
1580
1221
  if (!perpMetaAssets)
1581
1222
  return false;
1582
- return perpMetaAssets.some((asset) => asset.name === symbol);
1223
+ return perpMetaAssets.some(asset => asset.name === symbol);
1583
1224
  }
1584
1225
  }
1585
1226
 
1586
- /**
1587
- * Parse a token string that may have a market prefix (e.g., "xyz:GOOGL" -> { prefix: "xyz", symbol: "GOOGL" })
1588
- * This allows us to keep the full name (xyz:GOOGL) for URLs/tags while extracting just the symbol for SDK lookups.
1589
- */
1590
- function parseTokenWithPrefix(token) {
1591
- if (token.includes(':')) {
1592
- const [prefix, ...rest] = token.split(':');
1593
- const symbol = rest.join(':').toUpperCase();
1594
- return {
1595
- prefix: prefix.toLowerCase(),
1596
- symbol,
1597
- fullName: `${prefix.toLowerCase()}:${symbol}`,
1598
- };
1599
- }
1600
- return {
1601
- prefix: null,
1602
- symbol: token.toUpperCase(),
1603
- fullName: token.toUpperCase(),
1604
- };
1605
- }
1606
1227
  const useTokenSelectionMetadataStore = create((set) => ({
1607
1228
  isPriceDataReady: false,
1608
1229
  isLoading: true,
@@ -1612,65 +1233,23 @@ const useTokenSelectionMetadataStore = create((set) => ({
1612
1233
  weightedRatio24h: 1,
1613
1234
  priceRatio: 1,
1614
1235
  priceRatio24h: 1,
1615
- openInterest: '0',
1616
- volume: '0',
1236
+ openInterest: "0",
1237
+ volume: "0",
1617
1238
  sumNetFunding: 0,
1618
1239
  maxLeverage: 0,
1619
1240
  minMargin: 0,
1620
1241
  leverageMatched: true,
1621
- recompute: ({ perpMetaAssets, finalAssetContexts, allMids, activeAssetData, marketData, longTokens, shortTokens, }) => {
1622
- const isPriceDataReady = !!(perpMetaAssets &&
1623
- finalAssetContexts &&
1624
- allMids);
1625
- // Parse tokens - handle prefixed tokens like "xyz:GOOGL" by extracting the symbol and market prefix
1626
- // The full name (xyz:GOOGL) is kept as the metadata key for UI consistency
1627
- const parsedLongTokens = longTokens.map((t) => ({
1628
- ...t,
1629
- parsed: parseTokenWithPrefix(t.symbol),
1630
- }));
1631
- const parsedShortTokens = shortTokens.map((t) => ({
1632
- ...t,
1633
- parsed: parseTokenWithPrefix(t.symbol),
1634
- }));
1635
- // Extract base symbols with their market prefixes for SDK lookups
1636
- // This ensures xyz:TSLA and flx:TSLA get different market data
1637
- const longTokensForLookup = parsedLongTokens.map((t) => ({
1638
- symbol: t.parsed.symbol,
1639
- marketPrefix: t.parsed.prefix,
1640
- }));
1641
- const shortTokensForLookup = parsedShortTokens.map((t) => ({
1642
- symbol: t.parsed.symbol,
1643
- marketPrefix: t.parsed.prefix,
1644
- }));
1645
- // Also extract just the base symbols (without prefix) for lookups that don't support prefixes
1646
- const longBaseSymbols = longTokensForLookup.map((t) => t.symbol);
1647
- const shortBaseSymbols = shortTokensForLookup.map((t) => t.symbol);
1648
- // Get metadata using base symbols with market prefix for proper market differentiation
1649
- const longBaseMetadata = isPriceDataReady
1650
- ? TokenMetadataExtractor.extractMultipleTokensMetadata(longTokensForLookup, perpMetaAssets, finalAssetContexts, allMids, activeAssetData)
1242
+ recompute: ({ perpMetaAssets, finalAssetContexts, allMids, activeAssetData, marketData, longTokens, shortTokens }) => {
1243
+ const isPriceDataReady = !!(perpMetaAssets && finalAssetContexts && allMids);
1244
+ // Compute metadata when ready
1245
+ const longSymbols = longTokens.map((t) => t.symbol);
1246
+ const shortSymbols = shortTokens.map((t) => t.symbol);
1247
+ const longTokensMetadata = isPriceDataReady
1248
+ ? TokenMetadataExtractor.extractMultipleTokensMetadata(longSymbols, perpMetaAssets, finalAssetContexts, allMids, activeAssetData)
1651
1249
  : {};
1652
- const shortBaseMetadata = isPriceDataReady
1653
- ? TokenMetadataExtractor.extractMultipleTokensMetadata(shortTokensForLookup, perpMetaAssets, finalAssetContexts, allMids, activeAssetData)
1250
+ const shortTokensMetadata = isPriceDataReady
1251
+ ? TokenMetadataExtractor.extractMultipleTokensMetadata(shortSymbols, perpMetaAssets, finalAssetContexts, allMids, activeAssetData)
1654
1252
  : {};
1655
- // Re-map metadata using original full names (with prefix) as keys for UI consistency
1656
- // The extractor now keys by "{prefix}:{symbol}" for prefixed tokens, which matches our parsed.fullName
1657
- const longTokensMetadata = {};
1658
- parsedLongTokens.forEach((t) => {
1659
- var _a;
1660
- // Use the full name (e.g., "xyz:TSLA") as the lookup key since extractor uses the same format
1661
- const lookupKey = t.parsed.prefix
1662
- ? `${t.parsed.prefix}:${t.parsed.symbol}`
1663
- : t.parsed.symbol;
1664
- longTokensMetadata[t.symbol] = (_a = longBaseMetadata[lookupKey]) !== null && _a !== void 0 ? _a : null;
1665
- });
1666
- const shortTokensMetadata = {};
1667
- parsedShortTokens.forEach((t) => {
1668
- var _a;
1669
- const lookupKey = t.parsed.prefix
1670
- ? `${t.parsed.prefix}:${t.parsed.symbol}`
1671
- : t.parsed.symbol;
1672
- shortTokensMetadata[t.symbol] = (_a = shortBaseMetadata[lookupKey]) !== null && _a !== void 0 ? _a : null;
1673
- });
1674
1253
  // Determine loading state
1675
1254
  const allTokens = [...longTokens, ...shortTokens];
1676
1255
  const isLoading = (() => {
@@ -1678,33 +1257,26 @@ const useTokenSelectionMetadataStore = create((set) => ({
1678
1257
  return true;
1679
1258
  if (allTokens.length === 0)
1680
1259
  return false;
1681
- const allMetadata = {
1682
- ...longTokensMetadata,
1683
- ...shortTokensMetadata,
1684
- };
1260
+ const allMetadata = { ...longTokensMetadata, ...shortTokensMetadata };
1685
1261
  return allTokens.some((token) => !allMetadata[token.symbol]);
1686
1262
  })();
1687
1263
  // Open interest and volume (from market data for matching asset basket)
1688
- // Use base symbols (without prefix) for matching against market data
1689
1264
  const { openInterest, volume } = (() => {
1690
- const empty = { openInterest: '0', volume: '0' };
1265
+ const empty = { openInterest: "0", volume: "0" };
1691
1266
  if (!(marketData === null || marketData === void 0 ? void 0 : marketData.active) || (!longTokens.length && !shortTokens.length))
1692
1267
  return empty;
1693
- const selectedLong = longBaseSymbols.slice().sort();
1694
- const selectedShort = shortBaseSymbols.slice().sort();
1268
+ const selectedLong = longTokens.map((t) => t.symbol).sort();
1269
+ const selectedShort = shortTokens.map((t) => t.symbol).sort();
1695
1270
  const match = marketData.active.find((item) => {
1696
1271
  const longs = [...item.longAssets].sort();
1697
1272
  const shorts = [...item.shortAssets].sort();
1698
- if (longs.length !== selectedLong.length ||
1699
- shorts.length !== selectedShort.length)
1273
+ if (longs.length !== selectedLong.length || shorts.length !== selectedShort.length)
1700
1274
  return false;
1701
1275
  const longsEqual = longs.every((s, i) => s.asset === selectedLong[i]);
1702
1276
  const shortsEqual = shorts.every((s, i) => s.asset === selectedShort[i]);
1703
1277
  return longsEqual && shortsEqual;
1704
1278
  });
1705
- return match
1706
- ? { openInterest: match.openInterest, volume: match.volume }
1707
- : empty;
1279
+ return match ? { openInterest: match.openInterest, volume: match.volume } : empty;
1708
1280
  })();
1709
1281
  // Price ratio (only when exactly one long and one short)
1710
1282
  const { priceRatio, priceRatio24h } = (() => {
@@ -1784,27 +1356,17 @@ const useTokenSelectionMetadataStore = create((set) => ({
1784
1356
  return totalFunding;
1785
1357
  })();
1786
1358
  // Max leverage (minimum across all tokens)
1787
- // Use tokens with their market prefixes for proper lookup in perpMetaAssets
1788
1359
  const maxLeverage = (() => {
1789
1360
  if (!perpMetaAssets)
1790
1361
  return 0;
1791
- const allTokensForLookup = [
1792
- ...longTokensForLookup,
1793
- ...shortTokensForLookup,
1794
- ];
1795
- if (allTokensForLookup.length === 0)
1362
+ const allTokenSymbols = [...longTokens, ...shortTokens].map((t) => t.symbol);
1363
+ if (allTokenSymbols.length === 0)
1796
1364
  return 0;
1797
1365
  let minLev = Infinity;
1798
- allTokensForLookup.forEach(({ symbol, marketPrefix }) => {
1799
- // Match by both name AND marketPrefix for HIP3 assets
1800
- const tokenUniverse = perpMetaAssets.find((u) => u.name === symbol &&
1801
- (marketPrefix
1802
- ? u.marketPrefix === marketPrefix
1803
- : !u.marketPrefix));
1804
- // Fallback to just matching by name if no exact match
1805
- const fallbackUniverse = tokenUniverse || perpMetaAssets.find((u) => u.name === symbol);
1806
- if (fallbackUniverse === null || fallbackUniverse === void 0 ? void 0 : fallbackUniverse.maxLeverage)
1807
- minLev = Math.min(minLev, fallbackUniverse.maxLeverage);
1366
+ allTokenSymbols.forEach((symbol) => {
1367
+ const tokenUniverse = perpMetaAssets.find((u) => u.name === symbol);
1368
+ if (tokenUniverse === null || tokenUniverse === void 0 ? void 0 : tokenUniverse.maxLeverage)
1369
+ minLev = Math.min(minLev, tokenUniverse.maxLeverage);
1808
1370
  });
1809
1371
  return minLev === Infinity ? 0 : minLev;
1810
1372
  })();
@@ -1816,10 +1378,7 @@ const useTokenSelectionMetadataStore = create((set) => ({
1816
1378
  // Whether all tokens have matching leverage
1817
1379
  const leverageMatched = (() => {
1818
1380
  const allTokensArr = [...longTokens, ...shortTokens];
1819
- const allMetadata = {
1820
- ...longTokensMetadata,
1821
- ...shortTokensMetadata,
1822
- };
1381
+ const allMetadata = { ...longTokensMetadata, ...shortTokensMetadata };
1823
1382
  if (allTokensArr.length === 0)
1824
1383
  return true;
1825
1384
  const tokensWithLev = allTokensArr.filter((token) => { var _a; return (_a = allMetadata[token.symbol]) === null || _a === void 0 ? void 0 : _a.leverage; });
@@ -6004,8 +5563,8 @@ function addAuthInterceptors(params) {
6004
5563
  /**
6005
5564
  * Fetch historical candle data from HyperLiquid API
6006
5565
  */
6007
- const fetchHistoricalCandles = async (coin, startTime, endTime, interval, hip3Assets) => {
6008
- const backendCoin = toBackendSymbol(coin, hip3Assets);
5566
+ const fetchHistoricalCandles = async (coin, startTime, endTime, interval, displayToFull) => {
5567
+ const backendCoin = toBackendSymbol(coin, displayToFull);
6009
5568
  const request = {
6010
5569
  req: { coin: backendCoin, startTime, endTime, interval },
6011
5570
  type: 'candleSnapshot',
@@ -6164,10 +5723,10 @@ const useHistoricalPriceData = () => {
6164
5723
  setTokenLoading(token.symbol, true);
6165
5724
  });
6166
5725
  try {
6167
- const hip3Assets = useHyperliquidData.getState().hip3Assets;
5726
+ const displayToFull = useHyperliquidData.getState().hip3DisplayToFull;
6168
5727
  const fetchPromises = tokensToFetch.map(async (token) => {
6169
5728
  try {
6170
- const response = await fetchHistoricalCandles(token.symbol, startTime, endTime, interval, hip3Assets);
5729
+ const response = await fetchHistoricalCandles(token.symbol, startTime, endTime, interval, displayToFull);
6171
5730
  addHistoricalPriceData(token.symbol, interval, response.data, { start: startTime, end: endTime });
6172
5731
  return { symbol: token.symbol, candles: response.data, success: true };
6173
5732
  }
@@ -6856,14 +6415,14 @@ function useAutoSyncFills(options) {
6856
6415
  * @throws MinimumPositionSizeError if any asset has less than $11 USD value
6857
6416
  * @throws MaxAssetsPerLegError if any leg exceeds the maximum allowed assets (15)
6858
6417
  */
6859
- async function createPosition(baseUrl, payload, hip3Assets) {
6418
+ async function createPosition(baseUrl, payload, displayToFull) {
6860
6419
  // Validate maximum assets per leg before creating position
6861
6420
  validateMaxAssetsPerLeg(payload.longAssets, payload.shortAssets);
6862
6421
  // Validate minimum asset size before creating position
6863
6422
  validateMinimumAssetSize(payload.usdValue, payload.longAssets, payload.shortAssets);
6864
6423
  const url = joinUrl(baseUrl, "/positions");
6865
6424
  // Translate display symbols to backend format
6866
- const mapAssets = (arr) => arr === null || arr === void 0 ? void 0 : arr.map((a) => ({ ...a, asset: toBackendSymbol(a.asset, hip3Assets) }));
6425
+ const mapAssets = (arr) => arr === null || arr === void 0 ? void 0 : arr.map((a) => ({ ...a, asset: toBackendSymbol(a.asset, displayToFull) }));
6867
6426
  const translatedPayload = {
6868
6427
  ...payload,
6869
6428
  longAssets: mapAssets(payload.longAssets),
@@ -6962,9 +6521,9 @@ async function adjustPosition(baseUrl, positionId, payload) {
6962
6521
  throw toApiError(error);
6963
6522
  }
6964
6523
  }
6965
- async function adjustAdvancePosition(baseUrl, positionId, payload, hip3Assets) {
6524
+ async function adjustAdvancePosition(baseUrl, positionId, payload, displayToFull) {
6966
6525
  const url = joinUrl(baseUrl, `/positions/${positionId}/adjust-advance`);
6967
- const mapAssets = (arr) => arr === null || arr === void 0 ? void 0 : arr.map((a) => ({ ...a, asset: toBackendSymbol(a.asset, hip3Assets) }));
6526
+ const mapAssets = (arr) => arr === null || arr === void 0 ? void 0 : arr.map((a) => ({ ...a, asset: toBackendSymbol(a.asset, displayToFull) }));
6968
6527
  const translatedPayload = (payload || []).map((item) => ({
6969
6528
  longAssets: mapAssets(item.longAssets),
6970
6529
  shortAssets: mapAssets(item.shortAssets),
@@ -7027,9 +6586,6 @@ const calculatePositionAsset = (asset, currentPrice, totalInitialPositionSize, l
7027
6586
  entryPositionValue: entryNotional,
7028
6587
  initialWeight: totalInitialPositionSize > 0 ? entryNotional / totalInitialPositionSize : 0,
7029
6588
  fundingPaid: (_a = asset.fundingPaid) !== null && _a !== void 0 ? _a : 0,
7030
- // Preserve market metadata from raw asset (if provided by backend)
7031
- marketPrefix: asset.marketPrefix,
7032
- collateralToken: asset.collateralToken,
7033
6589
  };
7034
6590
  };
7035
6591
  const buildPositionValue = (rawPositions, clearinghouseState, allMids) => {
@@ -7054,7 +6610,7 @@ const buildPositionValue = (rawPositions, clearinghouseState, allMids) => {
7054
6610
  var _a, _b, _c;
7055
6611
  const currentPrice = parseFloat(allMids.mids[longAsset.coin]);
7056
6612
  const assetState = (_a = clearinghouseState.assetPositions.find(ap => toDisplaySymbol(ap.position.coin) === longAsset.coin)) === null || _a === void 0 ? void 0 : _a.position;
7057
- const leverage = (_c = (_b = assetState === null || assetState === void 0 ? void 0 : assetState.leverage) === null || _b === void 0 ? void 0 : _b.value) !== null && _c !== void 0 ? _c : 0;
6613
+ const leverage = (_c = (_b = assetState === null || assetState === void 0 ? void 0 : assetState.leverage) === null || _b === void 0 ? void 0 : _b.value) !== null && _c !== void 0 ? _c : longAsset.leverage;
7058
6614
  const mappedPositionAssets = calculatePositionAsset(longAsset, currentPrice, totalInitialPositionSize, leverage, true);
7059
6615
  mappedPosition.entryPositionValue += mappedPositionAssets.entryPositionValue;
7060
6616
  mappedPosition.unrealizedPnl += mappedPositionAssets.unrealizedPnl;
@@ -7068,7 +6624,7 @@ const buildPositionValue = (rawPositions, clearinghouseState, allMids) => {
7068
6624
  var _a, _b, _c;
7069
6625
  const currentPrice = parseFloat(allMids.mids[shortAsset.coin]);
7070
6626
  const assetState = (_a = clearinghouseState.assetPositions.find(ap => toDisplaySymbol(ap.position.coin) === shortAsset.coin)) === null || _a === void 0 ? void 0 : _a.position;
7071
- const leverage = (_c = (_b = assetState === null || assetState === void 0 ? void 0 : assetState.leverage) === null || _b === void 0 ? void 0 : _b.value) !== null && _c !== void 0 ? _c : 0;
6627
+ const leverage = (_c = (_b = assetState === null || assetState === void 0 ? void 0 : assetState.leverage) === null || _b === void 0 ? void 0 : _b.value) !== null && _c !== void 0 ? _c : shortAsset.leverage;
7072
6628
  const mappedPositionAssets = calculatePositionAsset(shortAsset, currentPrice, totalInitialPositionSize, leverage, false);
7073
6629
  mappedPosition.entryPositionValue += mappedPositionAssets.entryPositionValue;
7074
6630
  mappedPosition.unrealizedPnl += mappedPositionAssets.unrealizedPnl;
@@ -7092,151 +6648,57 @@ const buildPositionValue = (rawPositions, clearinghouseState, allMids) => {
7092
6648
  });
7093
6649
  };
7094
6650
 
7095
- function findAssetMeta$3(coinName, perpMetaAssets, knownPrefix, desiredCollateral) {
7096
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
7097
- if (!perpMetaAssets) {
7098
- return { collateralToken: 'USDC', marketPrefix: null };
7099
- }
7100
- if (desiredCollateral) {
7101
- const collateralMatch = perpMetaAssets.find((a) => a.name === coinName && a.collateralToken === desiredCollateral);
7102
- if (collateralMatch) {
7103
- return {
7104
- collateralToken: (_a = collateralMatch.collateralToken) !== null && _a !== void 0 ? _a : 'USDC',
7105
- marketPrefix: (_b = collateralMatch.marketPrefix) !== null && _b !== void 0 ? _b : null,
7106
- };
7107
- }
7108
- }
7109
- if (coinName.includes(':')) {
7110
- const [prefix, symbol] = coinName.split(':');
7111
- const exactMatch = perpMetaAssets.find((a) => {
7112
- var _a;
7113
- return a.name === symbol &&
7114
- ((_a = a.marketPrefix) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === prefix.toLowerCase();
7115
- });
7116
- if (exactMatch) {
7117
- return {
7118
- collateralToken: (_c = exactMatch.collateralToken) !== null && _c !== void 0 ? _c : 'USDC',
7119
- marketPrefix: (_d = exactMatch.marketPrefix) !== null && _d !== void 0 ? _d : null,
7120
- };
7121
- }
7122
- }
7123
- if (knownPrefix) {
7124
- const exactMatch = perpMetaAssets.find((a) => {
7125
- var _a;
7126
- return a.name === coinName &&
7127
- ((_a = a.marketPrefix) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === knownPrefix.toLowerCase();
7128
- });
7129
- if (exactMatch) {
7130
- return {
7131
- collateralToken: (_e = exactMatch.collateralToken) !== null && _e !== void 0 ? _e : 'USDC',
7132
- marketPrefix: (_f = exactMatch.marketPrefix) !== null && _f !== void 0 ? _f : null,
7133
- };
7134
- }
7135
- }
7136
- const regularAsset = perpMetaAssets.find((a) => a.name === coinName && !a.marketPrefix);
7137
- if (regularAsset) {
7138
- return {
7139
- collateralToken: (_g = regularAsset.collateralToken) !== null && _g !== void 0 ? _g : 'USDC',
7140
- marketPrefix: null,
7141
- };
7142
- }
7143
- const hip3Asset = perpMetaAssets.find((a) => a.name === coinName && a.marketPrefix);
7144
- if (hip3Asset) {
7145
- return {
7146
- collateralToken: (_h = hip3Asset.collateralToken) !== null && _h !== void 0 ? _h : 'USDC',
7147
- marketPrefix: (_j = hip3Asset.marketPrefix) !== null && _j !== void 0 ? _j : null,
7148
- };
7149
- }
7150
- return { collateralToken: 'USDC', marketPrefix: null };
7151
- }
7152
- function enrichPositionAssets(assets, perpMetaAssets) {
7153
- return assets.map((asset) => {
7154
- var _a;
7155
- if (asset.marketPrefix && asset.collateralToken) {
7156
- return asset;
7157
- }
7158
- const meta = findAssetMeta$3(asset.coin, perpMetaAssets, asset.marketPrefix, asset.collateralToken);
7159
- return {
7160
- ...asset,
7161
- marketPrefix: asset.marketPrefix || meta.marketPrefix,
7162
- collateralToken: (_a = asset.collateralToken) !== null && _a !== void 0 ? _a : meta.collateralToken,
7163
- };
7164
- });
7165
- }
7166
- function enrichPositions(positions, perpMetaAssets) {
7167
- return positions.map((position) => ({
7168
- ...position,
7169
- longAssets: enrichPositionAssets(position.longAssets, perpMetaAssets),
7170
- shortAssets: enrichPositionAssets(position.shortAssets, perpMetaAssets),
7171
- }));
7172
- }
7173
6651
  function usePosition() {
7174
6652
  const context = useContext(PearHyperliquidContext);
7175
6653
  if (!context) {
7176
6654
  throw new Error('usePosition must be used within a PearHyperliquidProvider');
7177
6655
  }
7178
6656
  const { apiBaseUrl, isConnected } = context;
7179
- const hip3Assets = useHyperliquidData((s) => s.hip3Assets);
6657
+ const displayToFull = useHyperliquidData((s) => s.hip3DisplayToFull);
6658
+ // Create position API action
7180
6659
  const createPosition$1 = async (payload) => {
7181
- return createPosition(apiBaseUrl, payload, hip3Assets);
6660
+ return createPosition(apiBaseUrl, payload, displayToFull);
7182
6661
  };
6662
+ // Update TP/SL risk parameters for a position
7183
6663
  const updateRiskParameters$1 = async (positionId, payload) => {
7184
6664
  return updateRiskParameters(apiBaseUrl, positionId, payload);
7185
6665
  };
6666
+ // Close a position (MARKET or TWAP)
7186
6667
  const closePosition$1 = async (positionId, payload) => {
7187
6668
  return closePosition(apiBaseUrl, positionId, payload);
7188
6669
  };
6670
+ // Close all positions (MARKET or TWAP)
7189
6671
  const closeAllPositions$1 = async (payload) => {
7190
6672
  return closeAllPositions(apiBaseUrl, payload);
7191
6673
  };
6674
+ // Adjust a position (REDUCE/INCREASE by %; MARKET or LIMIT)
7192
6675
  const adjustPosition$1 = async (positionId, payload) => {
7193
6676
  return adjustPosition(apiBaseUrl, positionId, payload);
7194
6677
  };
6678
+ // Adjust to absolute target sizes per asset, optionally adding new assets
7195
6679
  const adjustAdvancePosition$1 = async (positionId, payload) => {
7196
- return adjustAdvancePosition(apiBaseUrl, positionId, payload, hip3Assets);
6680
+ return adjustAdvancePosition(apiBaseUrl, positionId, payload, displayToFull);
7197
6681
  };
6682
+ // Open positions using WS data, with derived values
7198
6683
  const userOpenPositions = useUserData((state) => state.rawOpenPositions);
7199
6684
  const aggregatedClearingHouseState = useHyperliquidData((state) => state.aggregatedClearingHouseState);
7200
6685
  const allMids = useHyperliquidData((state) => state.allMids);
7201
- const allPerpMetaAssets = useHyperliquidData((state) => state.allPerpMetaAssets);
7202
6686
  const isLoading = useMemo(() => {
7203
6687
  return userOpenPositions === null && isConnected;
7204
6688
  }, [userOpenPositions, isConnected]);
7205
6689
  const openPositions = useMemo(() => {
7206
6690
  if (!userOpenPositions || !aggregatedClearingHouseState || !allMids)
7207
6691
  return null;
7208
- const positions = buildPositionValue(userOpenPositions, aggregatedClearingHouseState, allMids);
7209
- return enrichPositions(positions, allPerpMetaAssets);
7210
- }, [
7211
- userOpenPositions,
7212
- aggregatedClearingHouseState,
7213
- allMids,
7214
- allPerpMetaAssets,
7215
- ]);
7216
- return {
7217
- createPosition: createPosition$1,
7218
- updateRiskParameters: updateRiskParameters$1,
7219
- closePosition: closePosition$1,
7220
- closeAllPositions: closeAllPositions$1,
7221
- adjustPosition: adjustPosition$1,
7222
- adjustAdvancePosition: adjustAdvancePosition$1,
7223
- openPositions,
7224
- isLoading,
7225
- };
6692
+ return buildPositionValue(userOpenPositions, aggregatedClearingHouseState, allMids);
6693
+ }, [userOpenPositions, aggregatedClearingHouseState, allMids]);
6694
+ return { createPosition: createPosition$1, updateRiskParameters: updateRiskParameters$1, closePosition: closePosition$1, closeAllPositions: closeAllPositions$1, adjustPosition: adjustPosition$1, adjustAdvancePosition: adjustAdvancePosition$1, openPositions, isLoading };
7226
6695
  }
7227
6696
 
7228
6697
  async function adjustOrder(baseUrl, orderId, payload) {
7229
6698
  const url = joinUrl(baseUrl, `/orders/${orderId}/adjust`);
7230
6699
  try {
7231
- const resp = await apiClient.put(url, payload, {
7232
- headers: { 'Content-Type': 'application/json' },
7233
- timeout: 60000,
7234
- });
7235
- return {
7236
- data: resp.data,
7237
- status: resp.status,
7238
- headers: resp.headers,
7239
- };
6700
+ const resp = await apiClient.put(url, payload, { headers: { 'Content-Type': 'application/json' }, timeout: 60000 });
6701
+ return { data: resp.data, status: resp.status, headers: resp.headers };
7240
6702
  }
7241
6703
  catch (error) {
7242
6704
  throw toApiError(error);
@@ -7245,14 +6707,8 @@ async function adjustOrder(baseUrl, orderId, payload) {
7245
6707
  async function cancelOrder(baseUrl, orderId) {
7246
6708
  const url = joinUrl(baseUrl, `/orders/${orderId}/cancel`);
7247
6709
  try {
7248
- const resp = await apiClient.delete(url, {
7249
- timeout: 60000,
7250
- });
7251
- return {
7252
- data: resp.data,
7253
- status: resp.status,
7254
- headers: resp.headers,
7255
- };
6710
+ const resp = await apiClient.delete(url, { timeout: 60000 });
6711
+ return { data: resp.data, status: resp.status, headers: resp.headers };
7256
6712
  }
7257
6713
  catch (error) {
7258
6714
  throw toApiError(error);
@@ -7262,129 +6718,19 @@ async function cancelTwapOrder(baseUrl, orderId) {
7262
6718
  const url = joinUrl(baseUrl, `/orders/${orderId}/twap/cancel`);
7263
6719
  try {
7264
6720
  const resp = await apiClient.post(url, {}, { headers: { 'Content-Type': 'application/json' }, timeout: 60000 });
7265
- return {
7266
- data: resp.data,
7267
- status: resp.status,
7268
- headers: resp.headers,
7269
- };
7270
- }
7271
- catch (error) {
7272
- throw toApiError(error);
7273
- }
7274
- }
7275
- /**
7276
- * Execute a spot order (swap) using Pear Hyperliquid service
7277
- * POST /orders/spot
7278
- */
7279
- async function executeSpotOrder(baseUrl, payload) {
7280
- const url = joinUrl(baseUrl, '/orders/spot');
7281
- try {
7282
- const resp = await apiClient.post(url, payload, {
7283
- headers: { 'Content-Type': 'application/json' },
7284
- timeout: 60000,
7285
- });
7286
- return {
7287
- data: resp.data,
7288
- status: resp.status,
7289
- headers: resp.headers,
7290
- };
6721
+ return { data: resp.data, status: resp.status, headers: resp.headers };
7291
6722
  }
7292
6723
  catch (error) {
7293
6724
  throw toApiError(error);
7294
6725
  }
7295
6726
  }
7296
6727
 
7297
- function findAssetMeta$2(assetName, perpMetaAssets, knownPrefix, desiredCollateral) {
7298
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
7299
- if (!perpMetaAssets) {
7300
- return { collateralToken: 'USDC', marketPrefix: null };
7301
- }
7302
- if (desiredCollateral) {
7303
- const collateralMatch = perpMetaAssets.find((a) => a.name === assetName && a.collateralToken === desiredCollateral);
7304
- if (collateralMatch) {
7305
- return {
7306
- collateralToken: (_a = collateralMatch.collateralToken) !== null && _a !== void 0 ? _a : 'USDC',
7307
- marketPrefix: (_b = collateralMatch.marketPrefix) !== null && _b !== void 0 ? _b : null,
7308
- };
7309
- }
7310
- }
7311
- if (assetName.includes(':')) {
7312
- const [prefix, symbol] = assetName.split(':');
7313
- const exactMatch = perpMetaAssets.find((a) => {
7314
- var _a;
7315
- return a.name === symbol &&
7316
- ((_a = a.marketPrefix) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === prefix.toLowerCase();
7317
- });
7318
- if (exactMatch) {
7319
- return {
7320
- collateralToken: (_c = exactMatch.collateralToken) !== null && _c !== void 0 ? _c : 'USDC',
7321
- marketPrefix: (_d = exactMatch.marketPrefix) !== null && _d !== void 0 ? _d : null,
7322
- };
7323
- }
7324
- }
7325
- if (knownPrefix) {
7326
- const exactMatch = perpMetaAssets.find((a) => {
7327
- var _a;
7328
- return a.name === assetName &&
7329
- ((_a = a.marketPrefix) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === knownPrefix.toLowerCase();
7330
- });
7331
- if (exactMatch) {
7332
- return {
7333
- collateralToken: (_e = exactMatch.collateralToken) !== null && _e !== void 0 ? _e : 'USDC',
7334
- marketPrefix: (_f = exactMatch.marketPrefix) !== null && _f !== void 0 ? _f : null,
7335
- };
7336
- }
7337
- }
7338
- const regularAsset = perpMetaAssets.find((a) => a.name === assetName && !a.marketPrefix);
7339
- if (regularAsset) {
7340
- return {
7341
- collateralToken: (_g = regularAsset.collateralToken) !== null && _g !== void 0 ? _g : 'USDC',
7342
- marketPrefix: null,
7343
- };
7344
- }
7345
- const hip3Assets = perpMetaAssets.filter((a) => a.name === assetName && a.marketPrefix);
7346
- if (hip3Assets.length > 0) {
7347
- if (desiredCollateral) {
7348
- const collateralMatch = hip3Assets.find((a) => a.collateralToken === desiredCollateral);
7349
- if (collateralMatch) {
7350
- return {
7351
- collateralToken: (_h = collateralMatch.collateralToken) !== null && _h !== void 0 ? _h : 'USDC',
7352
- marketPrefix: (_j = collateralMatch.marketPrefix) !== null && _j !== void 0 ? _j : null,
7353
- };
7354
- }
7355
- }
7356
- const usdHMatch = hip3Assets.find((a) => a.collateralToken === 'USDH');
7357
- const chosen = usdHMatch !== null && usdHMatch !== void 0 ? usdHMatch : hip3Assets[0];
7358
- return {
7359
- collateralToken: (_k = chosen.collateralToken) !== null && _k !== void 0 ? _k : 'USDC',
7360
- marketPrefix: (_l = chosen.marketPrefix) !== null && _l !== void 0 ? _l : null,
7361
- };
7362
- }
7363
- return { collateralToken: 'USDC', marketPrefix: null };
7364
- }
7365
- function enrichOrderAssets$1(assets, perpMetaAssets) {
7366
- if (!assets)
7367
- return [];
7368
- return assets.map((asset) => {
7369
- var _a;
7370
- if (asset.marketPrefix && asset.collateralToken) {
7371
- return asset;
7372
- }
7373
- const meta = findAssetMeta$2(asset.asset, perpMetaAssets, asset.marketPrefix, asset.collateralToken);
7374
- return {
7375
- ...asset,
7376
- marketPrefix: asset.marketPrefix || meta.marketPrefix,
7377
- collateralToken: (_a = asset.collateralToken) !== null && _a !== void 0 ? _a : meta.collateralToken,
7378
- };
7379
- });
7380
- }
7381
6728
  function useOrders() {
7382
6729
  const context = useContext(PearHyperliquidContext);
7383
6730
  if (!context)
7384
6731
  throw new Error('useOrders must be used within a PearHyperliquidProvider');
7385
6732
  const { apiBaseUrl } = context;
7386
6733
  const openOrders = useUserData((state) => state.openOrders);
7387
- const allPerpMetaAssets = useHyperliquidData((state) => state.allPerpMetaAssets);
7388
6734
  const isLoading = useMemo(() => openOrders === null && context.isConnected, [openOrders, context.isConnected]);
7389
6735
  const { openPositions } = usePosition();
7390
6736
  const positionsById = useMemo(() => {
@@ -7403,27 +6749,19 @@ function useOrders() {
7403
6749
  const isTpSl = ord.orderType === 'TP' || ord.orderType === 'SL';
7404
6750
  const hasAssets = ((_b = (_a = ord.longAssets) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0 || ((_d = (_c = ord.shortAssets) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0) > 0;
7405
6751
  const pos = positionsById.get((_e = ord.positionId) !== null && _e !== void 0 ? _e : '');
7406
- let enrichedOrd = {
7407
- ...ord,
7408
- longAssets: enrichOrderAssets$1(ord.longAssets, allPerpMetaAssets),
7409
- shortAssets: enrichOrderAssets$1(ord.shortAssets, allPerpMetaAssets),
7410
- };
7411
- if (isTpSl && !hasAssets && pos) {
7412
- const mapAssets = (arr) => arr.map((a) => ({
7413
- asset: a.coin,
7414
- weight: a.initialWeight,
7415
- marketPrefix: a.marketPrefix,
7416
- collateralToken: a.collateralToken,
7417
- }));
7418
- enrichedOrd = {
7419
- ...enrichedOrd,
6752
+ if (!isTpSl || !pos)
6753
+ return ord;
6754
+ const mapAssets = (arr) => arr.map((a) => ({ asset: a.coin, weight: a.initialWeight }));
6755
+ if (!hasAssets) {
6756
+ return {
6757
+ ...ord,
7420
6758
  longAssets: mapAssets(pos.longAssets),
7421
6759
  shortAssets: mapAssets(pos.shortAssets),
7422
6760
  };
7423
6761
  }
7424
- return enrichedOrd;
6762
+ return ord;
7425
6763
  });
7426
- }, [openOrders, positionsById, allPerpMetaAssets]);
6764
+ }, [openOrders, positionsById]);
7427
6765
  const adjustOrder$1 = async (orderId, payload) => {
7428
6766
  return adjustOrder(apiBaseUrl, orderId, payload);
7429
6767
  };
@@ -7433,156 +6771,16 @@ function useOrders() {
7433
6771
  const cancelTwapOrder$1 = async (orderId) => {
7434
6772
  return cancelTwapOrder(apiBaseUrl, orderId);
7435
6773
  };
7436
- return {
7437
- adjustOrder: adjustOrder$1,
7438
- cancelOrder: cancelOrder$1,
7439
- cancelTwapOrder: cancelTwapOrder$1,
7440
- openOrders: enrichedOpenOrders,
7441
- isLoading,
7442
- };
6774
+ return { adjustOrder: adjustOrder$1, cancelOrder: cancelOrder$1, cancelTwapOrder: cancelTwapOrder$1, openOrders: enrichedOpenOrders, isLoading };
7443
6775
  }
7444
6776
 
7445
- /**
7446
- * Hook for executing spot orders (swaps) on Hyperliquid
7447
- * Use this to swap between USDC and USDH or other spot assets
7448
- */
7449
- function useSpotOrder() {
7450
- const context = useContext(PearHyperliquidContext);
7451
- if (!context) {
7452
- throw new Error('useSpotOrder must be used within a PearHyperliquidProvider');
7453
- }
7454
- const { apiBaseUrl } = context;
7455
- const [isLoading, setIsLoading] = useState(false);
7456
- const [error, setError] = useState(null);
7457
- const resetError = useCallback(() => {
7458
- setError(null);
7459
- }, []);
7460
- const executeSpotOrder$1 = useCallback(async (payload) => {
7461
- setIsLoading(true);
7462
- setError(null);
7463
- try {
7464
- const response = await executeSpotOrder(apiBaseUrl, payload);
7465
- return response;
7466
- }
7467
- catch (err) {
7468
- const apiError = err;
7469
- setError(apiError);
7470
- throw apiError;
7471
- }
7472
- finally {
7473
- setIsLoading(false);
7474
- }
7475
- }, [apiBaseUrl]);
7476
- return {
7477
- executeSpotOrder: executeSpotOrder$1,
7478
- isLoading,
7479
- error,
7480
- resetError,
7481
- };
7482
- }
7483
-
7484
- function findAssetMeta$1(assetName, perpMetaAssets, knownPrefix, desiredCollateral) {
7485
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
7486
- if (!perpMetaAssets) {
7487
- return { collateralToken: 'USDC', marketPrefix: null };
7488
- }
7489
- if (desiredCollateral) {
7490
- const collateralMatch = perpMetaAssets.find((a) => a.name === assetName && a.collateralToken === desiredCollateral);
7491
- if (collateralMatch) {
7492
- return {
7493
- collateralToken: (_a = collateralMatch.collateralToken) !== null && _a !== void 0 ? _a : 'USDC',
7494
- marketPrefix: (_b = collateralMatch.marketPrefix) !== null && _b !== void 0 ? _b : null,
7495
- };
7496
- }
7497
- }
7498
- if (assetName.includes(':')) {
7499
- const [prefix, symbol] = assetName.split(':');
7500
- const exactMatch = perpMetaAssets.find((a) => {
7501
- var _a;
7502
- return a.name === symbol &&
7503
- ((_a = a.marketPrefix) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === prefix.toLowerCase();
7504
- });
7505
- if (exactMatch) {
7506
- return {
7507
- collateralToken: (_c = exactMatch.collateralToken) !== null && _c !== void 0 ? _c : 'USDC',
7508
- marketPrefix: (_d = exactMatch.marketPrefix) !== null && _d !== void 0 ? _d : null,
7509
- };
7510
- }
7511
- }
7512
- if (knownPrefix) {
7513
- const exactMatch = perpMetaAssets.find((a) => {
7514
- var _a;
7515
- return a.name === assetName &&
7516
- ((_a = a.marketPrefix) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === knownPrefix.toLowerCase();
7517
- });
7518
- if (exactMatch) {
7519
- return {
7520
- collateralToken: (_e = exactMatch.collateralToken) !== null && _e !== void 0 ? _e : 'USDC',
7521
- marketPrefix: (_f = exactMatch.marketPrefix) !== null && _f !== void 0 ? _f : null,
7522
- };
7523
- }
7524
- }
7525
- const regularAsset = perpMetaAssets.find((a) => a.name === assetName && !a.marketPrefix);
7526
- if (regularAsset) {
7527
- return {
7528
- collateralToken: (_g = regularAsset.collateralToken) !== null && _g !== void 0 ? _g : 'USDC',
7529
- marketPrefix: null,
7530
- };
7531
- }
7532
- const hip3Assets = perpMetaAssets.filter((a) => a.name === assetName && a.marketPrefix);
7533
- if (hip3Assets.length > 0) {
7534
- if (desiredCollateral) {
7535
- const collateralMatch = hip3Assets.find((a) => a.collateralToken === desiredCollateral);
7536
- if (collateralMatch) {
7537
- return {
7538
- collateralToken: (_h = collateralMatch.collateralToken) !== null && _h !== void 0 ? _h : 'USDC',
7539
- marketPrefix: (_j = collateralMatch.marketPrefix) !== null && _j !== void 0 ? _j : null,
7540
- };
7541
- }
7542
- }
7543
- const usdHMatch = hip3Assets.find((a) => a.collateralToken === 'USDH');
7544
- const chosen = usdHMatch !== null && usdHMatch !== void 0 ? usdHMatch : hip3Assets[0];
7545
- return {
7546
- collateralToken: (_k = chosen.collateralToken) !== null && _k !== void 0 ? _k : 'USDC',
7547
- marketPrefix: (_l = chosen.marketPrefix) !== null && _l !== void 0 ? _l : null,
7548
- };
7549
- }
7550
- return { collateralToken: 'USDC', marketPrefix: null };
7551
- }
7552
- function enrichOrderAssets(assets, perpMetaAssets) {
7553
- if (!assets)
7554
- return [];
7555
- return assets.map((asset) => {
7556
- var _a;
7557
- if (asset.marketPrefix && asset.collateralToken) {
7558
- return asset;
7559
- }
7560
- const meta = findAssetMeta$1(asset.asset, perpMetaAssets, asset.marketPrefix, asset.collateralToken);
7561
- return {
7562
- ...asset,
7563
- marketPrefix: asset.marketPrefix || meta.marketPrefix,
7564
- collateralToken: (_a = asset.collateralToken) !== null && _a !== void 0 ? _a : meta.collateralToken,
7565
- };
7566
- });
7567
- }
7568
- function enrichTwapOrders(orders, perpMetaAssets) {
7569
- return orders.map((order) => ({
7570
- ...order,
7571
- longAssets: enrichOrderAssets(order.longAssets, perpMetaAssets),
7572
- shortAssets: enrichOrderAssets(order.shortAssets, perpMetaAssets),
7573
- }));
7574
- }
7575
6777
  function useTwap() {
7576
- const twapDetails = useUserData((state) => state.twapDetails);
7577
- const allPerpMetaAssets = useHyperliquidData((state) => state.allPerpMetaAssets);
6778
+ const twapDetails = useUserData(state => state.twapDetails);
7578
6779
  const context = useContext(PearHyperliquidContext);
7579
6780
  if (!context)
7580
6781
  throw new Error('useTwap must be used within a PearHyperliquidProvider');
7581
6782
  const { apiBaseUrl } = context;
7582
- const orders = useMemo(() => {
7583
- const rawOrders = twapDetails !== null && twapDetails !== void 0 ? twapDetails : [];
7584
- return enrichTwapOrders(rawOrders, allPerpMetaAssets);
7585
- }, [twapDetails, allPerpMetaAssets]);
6783
+ const orders = useMemo(() => twapDetails !== null && twapDetails !== void 0 ? twapDetails : [], [twapDetails]);
7586
6784
  const cancelTwap$1 = async (orderId) => {
7587
6785
  return cancelTwap(apiBaseUrl, orderId);
7588
6786
  };
@@ -7665,170 +6863,59 @@ function useNotifications() {
7665
6863
  };
7666
6864
  }
7667
6865
 
7668
- // Helper to find asset metadata from perpMetaAssets
7669
- function findAssetMeta(assetName, perpMetaAssets) {
7670
- var _a, _b, _c, _d;
7671
- if (!perpMetaAssets) {
7672
- return { collateralToken: 'USDC', marketPrefix: null };
7673
- }
7674
- // Try exact match first (for prefixed assets like "xyz:TSLA")
7675
- const exactMatch = perpMetaAssets.find((a) => a.name === assetName);
7676
- if (exactMatch) {
7677
- return {
7678
- collateralToken: (_a = exactMatch.collateralToken) !== null && _a !== void 0 ? _a : 'USDC',
7679
- marketPrefix: (_b = exactMatch.marketPrefix) !== null && _b !== void 0 ? _b : null,
7680
- };
7681
- }
7682
- // Try matching by base symbol (for non-prefixed names in data)
7683
- const baseMatch = perpMetaAssets.find((a) => {
7684
- const baseName = a.name.includes(':') ? a.name.split(':')[1] : a.name;
7685
- return baseName === assetName;
7686
- });
7687
- if (baseMatch) {
7688
- return {
7689
- collateralToken: (_c = baseMatch.collateralToken) !== null && _c !== void 0 ? _c : 'USDC',
7690
- marketPrefix: (_d = baseMatch.marketPrefix) !== null && _d !== void 0 ? _d : null,
7691
- };
7692
- }
7693
- return { collateralToken: 'USDC', marketPrefix: null };
7694
- }
7695
- // Enrich a single asset with metadata
7696
- function enrichAsset(asset, perpMetaAssets) {
7697
- const meta = findAssetMeta(asset.asset, perpMetaAssets);
7698
- return {
7699
- ...asset,
7700
- collateralToken: meta.collateralToken,
7701
- marketPrefix: meta.marketPrefix,
7702
- };
7703
- }
7704
- // Enrich a basket item with collateral info
7705
- function enrichBasketItem(item, perpMetaAssets) {
7706
- const enrichedLongs = item.longAssets.map((a) => enrichAsset(a, perpMetaAssets));
7707
- const enrichedShorts = item.shortAssets.map((a) => enrichAsset(a, perpMetaAssets));
7708
- // Determine collateral type
7709
- const allAssets = [...enrichedLongs, ...enrichedShorts];
7710
- const hasUsdc = allAssets.some((a) => a.collateralToken === 'USDC');
7711
- const hasUsdh = allAssets.some((a) => a.collateralToken === 'USDH');
7712
- let collateralType = 'USDC';
7713
- if (hasUsdc && hasUsdh) {
7714
- collateralType = 'MIXED';
7715
- }
7716
- else if (hasUsdh) {
7717
- collateralType = 'USDH';
7718
- }
7719
- return {
7720
- ...item,
7721
- longAssets: enrichedLongs,
7722
- shortAssets: enrichedShorts,
7723
- collateralType,
7724
- };
7725
- }
7726
- /**
7727
- * Filter baskets by collateral type
7728
- * - 'USDC': Only baskets where ALL assets use USDC (collateralType === 'USDC')
7729
- * - 'USDH': Only baskets where ALL assets use USDH (collateralType === 'USDH')
7730
- * - 'ALL' or undefined: No filtering, returns all baskets
7731
- */
7732
- function filterByCollateral(baskets, filter) {
7733
- if (!filter || filter === 'ALL') {
7734
- return baskets;
7735
- }
7736
- return baskets.filter((basket) => {
7737
- if (filter === 'USDC') {
7738
- // Include baskets that are purely USDC or have USDC assets
7739
- return (basket.collateralType === 'USDC' || basket.collateralType === 'MIXED');
7740
- }
7741
- if (filter === 'USDH') {
7742
- // Include baskets that are purely USDH or have USDH assets
7743
- return (basket.collateralType === 'USDH' || basket.collateralType === 'MIXED');
7744
- }
7745
- return true;
7746
- });
7747
- }
7748
- // Base selector for the full market-data payload (raw from WS)
6866
+ // Base selector for the full market-data payload
7749
6867
  const useMarketDataPayload = () => {
7750
6868
  return useMarketData((s) => s.marketData);
7751
6869
  };
7752
- // Full payload for 'market-data-all' channel (raw from WS)
6870
+ // Full payload for 'market-data-all' channel
7753
6871
  const useMarketDataAllPayload = () => {
7754
6872
  return useMarketData((s) => s.marketDataAll);
7755
6873
  };
7756
- // Access perpMetaAssets for enrichment
7757
- const usePerpMetaAssets = () => {
7758
- return useHyperliquidData((s) => s.perpMetaAssets);
7759
- };
7760
- // Active baskets (with collateral and market prefix info)
7761
- const useActiveBaskets = (collateralFilter) => {
6874
+ // Active baskets
6875
+ const useActiveBaskets = () => {
6876
+ var _a;
7762
6877
  const data = useMarketDataPayload();
7763
- const perpMetaAssets = usePerpMetaAssets();
7764
- return useMemo(() => {
7765
- if (!(data === null || data === void 0 ? void 0 : data.active))
7766
- return [];
7767
- const enriched = data.active.map((item) => enrichBasketItem(item, perpMetaAssets));
7768
- return filterByCollateral(enriched, collateralFilter);
7769
- }, [data, perpMetaAssets, collateralFilter]);
6878
+ return (_a = data === null || data === void 0 ? void 0 : data.active) !== null && _a !== void 0 ? _a : [];
7770
6879
  };
7771
- // Top gainers (with collateral and market prefix info)
7772
- const useTopGainers = (limit, collateralFilter) => {
6880
+ // Top gainers (optional limit override)
6881
+ const useTopGainers = (limit) => {
7773
6882
  const data = useMarketDataPayload();
7774
- const perpMetaAssets = usePerpMetaAssets();
7775
6883
  return useMemo(() => {
7776
6884
  var _a;
7777
6885
  const list = (_a = data === null || data === void 0 ? void 0 : data.topGainers) !== null && _a !== void 0 ? _a : [];
7778
- const limited = typeof limit === 'number' ? list.slice(0, Math.max(0, limit)) : list;
7779
- const enriched = limited.map((item) => enrichBasketItem(item, perpMetaAssets));
7780
- return filterByCollateral(enriched, collateralFilter);
7781
- }, [data, perpMetaAssets, limit, collateralFilter]);
6886
+ return typeof limit === 'number' ? list.slice(0, Math.max(0, limit)) : list;
6887
+ }, [data, limit]);
7782
6888
  };
7783
- // Top losers (with collateral and market prefix info)
7784
- const useTopLosers = (limit, collateralFilter) => {
6889
+ // Top losers (optional limit override)
6890
+ const useTopLosers = (limit) => {
7785
6891
  const data = useMarketDataPayload();
7786
- const perpMetaAssets = usePerpMetaAssets();
7787
6892
  return useMemo(() => {
7788
6893
  var _a;
7789
6894
  const list = (_a = data === null || data === void 0 ? void 0 : data.topLosers) !== null && _a !== void 0 ? _a : [];
7790
- const limited = typeof limit === 'number' ? list.slice(0, Math.max(0, limit)) : list;
7791
- const enriched = limited.map((item) => enrichBasketItem(item, perpMetaAssets));
7792
- return filterByCollateral(enriched, collateralFilter);
7793
- }, [data, perpMetaAssets, limit, collateralFilter]);
6895
+ return typeof limit === 'number' ? list.slice(0, Math.max(0, limit)) : list;
6896
+ }, [data, limit]);
7794
6897
  };
7795
- // Highlighted baskets (with collateral and market prefix info)
7796
- const useHighlightedBaskets = (collateralFilter) => {
6898
+ // Highlighted baskets
6899
+ const useHighlightedBaskets = () => {
6900
+ var _a;
7797
6901
  const data = useMarketDataPayload();
7798
- const perpMetaAssets = usePerpMetaAssets();
7799
- return useMemo(() => {
7800
- if (!(data === null || data === void 0 ? void 0 : data.highlighted))
7801
- return [];
7802
- const enriched = data.highlighted.map((item) => enrichBasketItem(item, perpMetaAssets));
7803
- return filterByCollateral(enriched, collateralFilter);
7804
- }, [data, perpMetaAssets, collateralFilter]);
6902
+ return (_a = data === null || data === void 0 ? void 0 : data.highlighted) !== null && _a !== void 0 ? _a : [];
7805
6903
  };
7806
- // Watchlist baskets (with collateral and market prefix info)
7807
- const useWatchlistBaskets = (collateralFilter) => {
6904
+ // Watchlist baskets (from market-data payload when subscribed with address)
6905
+ const useWatchlistBaskets = () => {
6906
+ var _a;
7808
6907
  const data = useMarketDataPayload();
7809
- const perpMetaAssets = usePerpMetaAssets();
7810
- return useMemo(() => {
7811
- if (!(data === null || data === void 0 ? void 0 : data.watchlist))
7812
- return [];
7813
- const enriched = data.watchlist.map((item) => enrichBasketItem(item, perpMetaAssets));
7814
- return filterByCollateral(enriched, collateralFilter);
7815
- }, [data, perpMetaAssets, collateralFilter]);
6908
+ return (_a = data === null || data === void 0 ? void 0 : data.watchlist) !== null && _a !== void 0 ? _a : [];
7816
6909
  };
7817
- // All baskets (with collateral and market prefix info)
7818
- const useAllBaskets = (collateralFilter) => {
6910
+ // All baskets (from market-data-all)
6911
+ const useAllBaskets = () => {
6912
+ var _a;
7819
6913
  const dataAll = useMarketDataAllPayload();
7820
- const perpMetaAssets = usePerpMetaAssets();
7821
- return useMemo(() => {
7822
- if (!(dataAll === null || dataAll === void 0 ? void 0 : dataAll.all))
7823
- return [];
7824
- const enriched = dataAll.all.map((item) => enrichBasketItem(item, perpMetaAssets));
7825
- return filterByCollateral(enriched, collateralFilter);
7826
- }, [dataAll, perpMetaAssets, collateralFilter]);
6914
+ return (_a = dataAll === null || dataAll === void 0 ? void 0 : dataAll.all) !== null && _a !== void 0 ? _a : [];
7827
6915
  };
7828
6916
  // Find a basket by its exact asset composition (order-insensitive)
7829
6917
  const useFindBasket = (longs, shorts) => {
7830
6918
  const data = useMarketDataPayload();
7831
- const perpMetaAssets = usePerpMetaAssets();
7832
6919
  return useMemo(() => {
7833
6920
  if (!data)
7834
6921
  return undefined;
@@ -7842,28 +6929,17 @@ const useFindBasket = (longs, shorts) => {
7842
6929
  : '';
7843
6930
  const lKey = normalize(longs);
7844
6931
  const sKey = normalize(shorts);
7845
- const match = (item) => normalize(item.longAssets) === lKey &&
7846
- normalize(item.shortAssets) === sKey;
7847
- const found = data.active.find(match) || data.highlighted.find(match);
7848
- return found
7849
- ? enrichBasketItem(found, perpMetaAssets)
7850
- : undefined;
7851
- }, [data, longs, shorts, perpMetaAssets]);
6932
+ const match = (item) => normalize(item.longAssets) === lKey && normalize(item.shortAssets) === sKey;
6933
+ return data.active.find(match) || data.highlighted.find(match);
6934
+ }, [data, longs, shorts]);
7852
6935
  };
7853
6936
 
7854
- async function toggleWatchlist(baseUrl, longAssets, shortAssets, hip3Assets) {
6937
+ async function toggleWatchlist(baseUrl, longAssets, shortAssets, displayToFull) {
7855
6938
  const url = joinUrl(baseUrl, '/watchlist');
7856
- const mapAssets = (arr) => arr.map((a) => ({ ...a, asset: toBackendSymbol(a.asset, hip3Assets) }));
6939
+ const mapAssets = (arr) => arr.map(a => ({ ...a, asset: toBackendSymbol(a.asset, displayToFull) }));
7857
6940
  try {
7858
- const response = await apiClient.post(url, {
7859
- longAssets: mapAssets(longAssets),
7860
- shortAssets: mapAssets(shortAssets),
7861
- }, { headers: { 'Content-Type': 'application/json' } });
7862
- return {
7863
- data: response.data,
7864
- status: response.status,
7865
- headers: response.headers,
7866
- };
6941
+ const response = await apiClient.post(url, { longAssets: mapAssets(longAssets), shortAssets: mapAssets(shortAssets) }, { headers: { 'Content-Type': 'application/json' } });
6942
+ return { data: response.data, status: response.status, headers: response.headers };
7867
6943
  }
7868
6944
  catch (error) {
7869
6945
  throw toApiError(error);
@@ -7875,11 +6951,11 @@ function useWatchlist() {
7875
6951
  if (!context)
7876
6952
  throw new Error('useWatchlist must be used within a PearHyperliquidProvider');
7877
6953
  const { apiBaseUrl, isConnected } = context;
7878
- const hip3Assets = useHyperliquidData((s) => s.hip3Assets);
6954
+ const displayToFull = useHyperliquidData((s) => s.hip3DisplayToFull);
7879
6955
  const marketData = useMarketDataPayload();
7880
6956
  const isLoading = useMemo(() => !marketData && isConnected, [marketData, isConnected]);
7881
6957
  const toggle = async (longAssets, shortAssets) => {
7882
- const resp = await toggleWatchlist(apiBaseUrl, longAssets, shortAssets, hip3Assets);
6958
+ const resp = await toggleWatchlist(apiBaseUrl, longAssets, shortAssets, displayToFull);
7883
6959
  // Server will push updated market-data over WS; nothing to set here
7884
6960
  return resp;
7885
6961
  };
@@ -8133,48 +7209,16 @@ function useAuth() {
8133
7209
  };
8134
7210
  }
8135
7211
 
8136
- const useSpotBalances = () => {
8137
- const spotState = useUserData((state) => state.spotState);
8138
- return useMemo(() => {
8139
- if (!spotState) {
8140
- return {
8141
- usdhBalance: undefined,
8142
- spotUsdcBalance: undefined,
8143
- isLoading: true,
8144
- };
8145
- }
8146
- const balances = spotState.balances || [];
8147
- let usdhBal = 0;
8148
- let spotUsdcBal = 0;
8149
- for (const balance of balances) {
8150
- const total = parseFloat(balance.total || '0');
8151
- if (balance.coin === 'USDH') {
8152
- usdhBal = total;
8153
- }
8154
- if (balance.coin === 'USDC') {
8155
- spotUsdcBal = total;
8156
- }
8157
- }
8158
- return {
8159
- usdhBalance: usdhBal,
8160
- spotUsdcBalance: spotUsdcBal,
8161
- isLoading: false,
8162
- };
8163
- }, [spotState]);
8164
- };
8165
-
8166
7212
  const PearHyperliquidContext = createContext(undefined);
8167
7213
  /**
8168
7214
  * React Provider for PearHyperliquidClient
8169
7215
  */
8170
- const PearHyperliquidProvider = ({ children, apiBaseUrl = 'https://hl-ui.pearprotocol.io', clientId = 'PEARPROTOCOLUI', wsUrl = 'wss://hl-ui.pearprotocol.io/ws', }) => {
7216
+ const PearHyperliquidProvider = ({ children, apiBaseUrl = "https://hl-ui.pearprotocol.io", clientId = "PEARPROTOCOLUI", wsUrl = "wss://hl-ui.pearprotocol.io/ws", }) => {
8171
7217
  const address = useUserData((s) => s.address);
8172
7218
  const setAddress = useUserData((s) => s.setAddress);
8173
7219
  const perpsMetaAssets = useHyperliquidData((state) => state.perpMetaAssets);
8174
7220
  const setPerpMetaAssets = useHyperliquidData((state) => state.setPerpMetaAssets);
8175
- const setAllPerpMetaAssets = useHyperliquidData((state) => state.setAllPerpMetaAssets);
8176
- const setHip3Assets = useHyperliquidData((state) => state.setHip3Assets);
8177
- const setHip3MarketPrefixes = useHyperliquidData((state) => state.setHip3MarketPrefixes);
7221
+ const setHip3DisplayToFull = useHyperliquidData((state) => state.setHip3DisplayToFull);
8178
7222
  const websocketsEnabled = useMemo(() => Array.isArray(perpsMetaAssets) && perpsMetaAssets.length > 0, [perpsMetaAssets]);
8179
7223
  const { isConnected, lastError } = useHyperliquidWebSocket({
8180
7224
  wsUrl,
@@ -8189,65 +7233,32 @@ const PearHyperliquidProvider = ({ children, apiBaseUrl = 'https://hl-ui.pearpro
8189
7233
  if (perpsMetaAssets === null) {
8190
7234
  fetchAllPerpMetas()
8191
7235
  .then((res) => {
8192
- const assetToMarkets = new Map();
8193
- const marketPrefixes = new Map();
8194
- const cleanedPerpMetas = [];
8195
- const allPerpMetas = [];
8196
- const FILTERED_PREFIXES = ['vntl', 'hyna'];
8197
- res.data.forEach((item) => {
8198
- const collateralToken = item.collateralToken === 360 ? 'USDH' : 'USDC';
8199
- item.universe.forEach((asset) => {
8200
- var _a;
8201
- const [maybePrefix, maybeMarket] = asset.name.split(':');
8202
- if (maybeMarket) {
8203
- const prefix = maybePrefix.toLowerCase();
8204
- const displayName = maybeMarket;
8205
- const fullName = `${prefix}:${displayName}`;
8206
- marketPrefixes.set(fullName, prefix);
8207
- if (!FILTERED_PREFIXES.includes(prefix)) {
8208
- const existingMarkets = (_a = assetToMarkets.get(displayName)) !== null && _a !== void 0 ? _a : [];
8209
- if (!existingMarkets.includes(fullName)) {
8210
- assetToMarkets.set(displayName, [
8211
- ...existingMarkets,
8212
- fullName,
8213
- ]);
8214
- }
8215
- }
8216
- const assetWithMeta = {
8217
- ...asset,
8218
- name: displayName,
8219
- marketPrefix: prefix,
8220
- collateralToken,
8221
- };
8222
- allPerpMetas.push(assetWithMeta);
8223
- if (!FILTERED_PREFIXES.includes(prefix)) {
8224
- cleanedPerpMetas.push(assetWithMeta);
8225
- }
8226
- }
8227
- else {
8228
- const assetWithMeta = {
8229
- ...asset,
8230
- collateralToken,
8231
- };
8232
- cleanedPerpMetas.push(assetWithMeta);
8233
- allPerpMetas.push(assetWithMeta);
8234
- }
8235
- });
7236
+ // Only show HL and XYZ for now as other are using USDH collateral and need more work
7237
+ const aggregatedPerpMetas = res.data
7238
+ .slice(0, 2)
7239
+ .flatMap((item) => item.universe);
7240
+ const hip3Map = new Map();
7241
+ const displayToFull = new Map();
7242
+ const cleanedPerpMetas = aggregatedPerpMetas.map((asset) => {
7243
+ var _a;
7244
+ const [maybePrefix, maybeMarket] = asset.name.split(":");
7245
+ if (maybeMarket) {
7246
+ const prefix = maybePrefix.toLowerCase();
7247
+ const market = maybeMarket;
7248
+ const existing = (_a = hip3Map.get(prefix)) !== null && _a !== void 0 ? _a : [];
7249
+ hip3Map.set(prefix, [...existing, market]);
7250
+ displayToFull.set(market, `${prefix}:${market}`);
7251
+ return { ...asset, name: market };
7252
+ }
7253
+ return asset;
8236
7254
  });
8237
- setHip3Assets(assetToMarkets);
8238
- setHip3MarketPrefixes(marketPrefixes);
7255
+ setHip3DisplayToFull(displayToFull);
8239
7256
  setPerpMetaAssets(cleanedPerpMetas);
8240
- setAllPerpMetaAssets(allPerpMetas);
8241
7257
  })
8242
7258
  .catch(() => { });
8243
7259
  }
8244
- }, [
8245
- perpsMetaAssets,
8246
- setPerpMetaAssets,
8247
- setAllPerpMetaAssets,
8248
- setHip3Assets,
8249
- setHip3MarketPrefixes,
8250
- ]);
7260
+ }, [perpsMetaAssets, setPerpMetaAssets, setHip3DisplayToFull]);
7261
+ // Auth methods now sourced from useAuth hook
8251
7262
  useAutoSyncFills({
8252
7263
  baseUrl: apiBaseUrl,
8253
7264
  address,
@@ -8285,7 +7296,7 @@ const PearHyperliquidProvider = ({ children, apiBaseUrl = 'https://hl-ui.pearpro
8285
7296
  function usePearHyperliquid() {
8286
7297
  const ctx = useContext(PearHyperliquidContext);
8287
7298
  if (!ctx)
8288
- throw new Error('usePearHyperliquid must be used within a PearHyperliquidProvider');
7299
+ throw new Error("usePearHyperliquid must be used within a PearHyperliquidProvider");
8289
7300
  return ctx;
8290
7301
  }
8291
7302
 
@@ -8376,4 +7387,4 @@ function mapCandleIntervalToTradingViewInterval(interval) {
8376
7387
  }
8377
7388
  }
8378
7389
 
8379
- 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, 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, useSpotBalances, useSpotOrder, useTokenSelectionMetadata, useTopGainers, useTopLosers, useTradeHistories, useTwap, useUserSelection, useWatchlist, useWatchlistBaskets, useWebData, validateMaxAssetsPerLeg, validateMinimumAssetSize, validatePositionSize };
7390
+ 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 };