@pear-protocol/hyperliquid-sdk 0.0.79 → 0.1.2

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
@@ -105,84 +105,9 @@ const useMarketData = create((set) => ({
105
105
  marketData: null,
106
106
  marketDataAll: null,
107
107
  setMarketData: (value) => set({ marketData: value }),
108
- setMarketDataAll: (value) => set({ marketDataAll: value }),
109
- clean: () => set({ marketData: null, marketDataAll: null }),
108
+ clean: () => set({ marketData: null }),
110
109
  }));
111
110
 
112
- // Utilities for translating between display symbols and backend (prefixed) symbols
113
- /**
114
- * Convert a full/prefixed symbol (e.g., "xyz:XYZ100") to a display symbol (e.g., "XYZ100").
115
- */
116
- function toDisplaySymbol(symbol) {
117
- const parts = symbol.split(":");
118
- return parts.length > 1 ? parts.slice(-1)[0] : symbol;
119
- }
120
- /**
121
- * Convert a display symbol back to backend form using a provided map.
122
- * If mapping is missing, returns the original symbol.
123
- * For multi-market assets, returns the first available market.
124
- * @param displaySymbol e.g., "TSLA"
125
- * @param hip3Assets map of display -> all full market names (e.g., "TSLA" -> ["xyz:TSLA", "flx:TSLA"])
126
- */
127
- function toBackendSymbol(displaySymbol, hip3Assets) {
128
- if (displaySymbol === "BTC")
129
- return "BTC";
130
- const markets = hip3Assets.get(displaySymbol);
131
- // Return first market if available, otherwise return original symbol
132
- return markets && markets.length > 0 ? markets[0] : displaySymbol;
133
- }
134
- /**
135
- * Convert a display symbol to backend form for a specific market prefix.
136
- * This is useful when an asset is available on multiple markets (e.g., xyz:TSLA and flx:TSLA).
137
- * @param displaySymbol e.g., "TSLA"
138
- * @param marketPrefix e.g., "xyz" or "flx"
139
- * @param hip3Assets map of display -> all full market names
140
- * @returns Full market name if found, null if prefix not specified for multi-market asset, otherwise displaySymbol with prefix
141
- */
142
- function toBackendSymbolWithMarket(displaySymbol, marketPrefix, hip3Assets) {
143
- const availableMarkets = hip3Assets.get(displaySymbol);
144
- if (!availableMarkets || availableMarkets.length === 0) {
145
- // Not a HIP-3 asset, return as-is or with prefix if provided
146
- return marketPrefix ? `${marketPrefix}:${displaySymbol}` : displaySymbol;
147
- }
148
- if (marketPrefix) {
149
- // Find the market with the specified prefix
150
- const targetMarket = availableMarkets.find((market) => market.toLowerCase().startsWith(`${marketPrefix.toLowerCase()}:`));
151
- if (targetMarket) {
152
- return targetMarket;
153
- }
154
- }
155
- // No prefix specified or not found, return null to force explicit market selection
156
- return null;
157
- }
158
- /**
159
- * Get all available markets for a display symbol.
160
- * @param displaySymbol e.g., "TSLA"
161
- * @param hip3Assets map of display -> all full market names
162
- * @returns Array of full market names, e.g., ["xyz:TSLA", "flx:TSLA"]
163
- */
164
- function getAvailableMarkets(displaySymbol, hip3Assets) {
165
- var _a;
166
- return (_a = hip3Assets.get(displaySymbol)) !== null && _a !== void 0 ? _a : [];
167
- }
168
- /**
169
- * Extract the market prefix from a full market name.
170
- * @param fullSymbol e.g., "xyz:TSLA"
171
- * @returns The prefix (e.g., "xyz") or undefined if no prefix
172
- */
173
- function getMarketPrefix(fullSymbol) {
174
- const parts = fullSymbol.split(":");
175
- return parts.length > 1 ? parts[0] : undefined;
176
- }
177
- /**
178
- * Check if a symbol is a HIP-3 market (has a prefix).
179
- * @param symbol e.g., "xyz:TSLA" or "TSLA"
180
- * @returns true if the symbol has a market prefix
181
- */
182
- function isHip3Market(symbol) {
183
- return symbol.includes(":");
184
- }
185
-
186
111
  const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
187
112
  const { setTradeHistories, setRawOpenPositions, setOpenOrders, setAccountSummary, setTwapDetails, setNotifications, clean, } = useUserData();
188
113
  const { setMarketData } = useMarketData();
@@ -217,60 +142,19 @@ const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
217
142
  switch (dataMessage.channel) {
218
143
  case 'trade-histories':
219
144
  {
220
- const mapAsset = (a) => {
221
- var _a, _b;
222
- const extractedPrefix = getMarketPrefix(a.coin);
223
- return {
224
- ...a,
225
- coin: toDisplaySymbol(a.coin),
226
- marketPrefix: (_b = (_a = a.marketPrefix) !== null && _a !== void 0 ? _a : extractedPrefix) !== null && _b !== void 0 ? _b : null,
227
- };
228
- };
229
- const list = dataMessage.data.map((item) => {
230
- var _a, _b;
231
- return ({
232
- ...item,
233
- closedLongAssets: item.closedLongAssets.map(mapAsset),
234
- closedShortAssets: item.closedShortAssets.map(mapAsset),
235
- positionLongAssets: (_a = item.positionLongAssets) === null || _a === void 0 ? void 0 : _a.map((a) => toDisplaySymbol(a)),
236
- positionShortAssets: (_b = item.positionShortAssets) === null || _b === void 0 ? void 0 : _b.map((a) => toDisplaySymbol(a)),
237
- });
238
- });
145
+ const list = dataMessage.data;
239
146
  setTradeHistories(list);
240
147
  }
241
148
  break;
242
149
  case 'open-positions':
243
150
  {
244
- const enrichAsset = (a) => {
245
- var _a, _b;
246
- const extractedPrefix = getMarketPrefix(a.coin);
247
- return {
248
- ...a,
249
- coin: toDisplaySymbol(a.coin),
250
- marketPrefix: (_b = (_a = a.marketPrefix) !== null && _a !== void 0 ? _a : extractedPrefix) !== null && _b !== void 0 ? _b : null,
251
- };
252
- };
253
- const list = dataMessage.data.map((pos) => ({
254
- ...pos,
255
- longAssets: pos.longAssets.map(enrichAsset),
256
- shortAssets: pos.shortAssets.map(enrichAsset),
257
- }));
151
+ const list = dataMessage.data;
258
152
  setRawOpenPositions(list);
259
153
  }
260
154
  break;
261
155
  case 'open-orders':
262
156
  {
263
- const list = dataMessage.data.map((order) => ({
264
- ...order,
265
- longAssets: order.longAssets.map((a) => ({
266
- ...a,
267
- asset: toDisplaySymbol(a.asset),
268
- })),
269
- shortAssets: order.shortAssets.map((a) => ({
270
- ...a,
271
- asset: toDisplaySymbol(a.asset),
272
- })),
273
- }));
157
+ const list = dataMessage.data;
274
158
  setOpenOrders(list);
275
159
  }
276
160
  break;
@@ -279,21 +163,7 @@ const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
279
163
  break;
280
164
  case 'twap-details':
281
165
  {
282
- const mapTwapAsset = (a) => {
283
- var _a, _b, _c;
284
- const extractedPrefix = getMarketPrefix(a.asset);
285
- return {
286
- ...a,
287
- asset: toDisplaySymbol(a.asset),
288
- marketPrefix: (_b = (_a = a.marketPrefix) !== null && _a !== void 0 ? _a : extractedPrefix) !== null && _b !== void 0 ? _b : null,
289
- collateralToken: (_c = a.collateralToken) !== null && _c !== void 0 ? _c : undefined,
290
- };
291
- };
292
- const list = dataMessage.data.map((twap) => ({
293
- ...twap,
294
- longAssets: twap.longAssets.map(mapTwapAsset),
295
- shortAssets: twap.shortAssets.map(mapTwapAsset),
296
- }));
166
+ const list = dataMessage.data;
297
167
  setTwapDetails(list);
298
168
  }
299
169
  break;
@@ -303,25 +173,7 @@ const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
303
173
  case 'market-data':
304
174
  {
305
175
  const md = dataMessage.data;
306
- const mapGroup = (g) => ({
307
- ...g,
308
- longAssets: g.longAssets.map((a) => ({
309
- ...a,
310
- asset: toDisplaySymbol(a.asset),
311
- })),
312
- shortAssets: g.shortAssets.map((a) => ({
313
- ...a,
314
- asset: toDisplaySymbol(a.asset),
315
- })),
316
- });
317
- const mapped = {
318
- active: md.active.map(mapGroup),
319
- topGainers: md.topGainers.map(mapGroup),
320
- topLosers: md.topLosers.map(mapGroup),
321
- highlighted: md.highlighted.map(mapGroup),
322
- watchlist: md.watchlist.map(mapGroup),
323
- };
324
- setMarketData(mapped);
176
+ setMarketData(md);
325
177
  }
326
178
  break;
327
179
  }
@@ -457,7 +309,229 @@ const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
457
309
  };
458
310
  };
459
311
 
460
- const useHyperliquidData = create((set, get) => ({
312
+ const getMarketInfoFromSymbol = (symbol) => {
313
+ const separatorIndex = symbol.indexOf(':');
314
+ if (separatorIndex > -1) {
315
+ const prefix = symbol.slice(0, separatorIndex);
316
+ const name = symbol.slice(separatorIndex + 1);
317
+ return {
318
+ symbolName: name || symbol,
319
+ marketName: prefix || '',
320
+ };
321
+ }
322
+ return { symbolName: symbol, marketName: '' };
323
+ };
324
+
325
+ /**
326
+ * Check if two symbols match, handling kPEPE/KPEPE variations
327
+ * Returns true if symbols match (case-insensitive for k-prefix tokens)
328
+ */
329
+ function symbolsMatch(assetName, searchSymbol) {
330
+ // Exact match
331
+ if (assetName === searchSymbol)
332
+ return true;
333
+ // Try case-insensitive match for k-prefix tokens (kPEPE vs KPEPE)
334
+ if (assetName.toUpperCase() === searchSymbol.toUpperCase()) {
335
+ return true;
336
+ }
337
+ return false;
338
+ }
339
+ /**
340
+ * Extracts token metadata from aggregated WebData3 contexts and AllMids data
341
+ */
342
+ class TokenMetadataExtractor {
343
+ /**
344
+ * Checks if token data is available in aggregated universe assets
345
+ * @param symbol - Token symbol
346
+ * @param perpMetaAssets - Aggregated universe assets
347
+ * @returns boolean indicating if token exists in universe
348
+ */
349
+ static isTokenAvailable(symbol, perpMetaAssets) {
350
+ if (!perpMetaAssets)
351
+ return false;
352
+ return perpMetaAssets.some((asset) => symbolsMatch(asset.name, symbol));
353
+ }
354
+ /**
355
+ * Extracts token metadata using DEX-aware lookup (correctly matches perpMetas to assetContexts)
356
+ * @param symbol - Token symbol (e.g., "BTC", "TSLA")
357
+ * @param perpMetasByDex - Map of DEX name to UniverseAsset[]
358
+ * @param assetContextsByDex - Map of DEX name to WebData3AssetCtx[]
359
+ * @param allMids - AllMids data containing current prices
360
+ * @param activeAssetData - Optional active asset data containing leverage information
361
+ * @param finalAtOICaps - Optional array of symbols at OI caps
362
+ * @returns TokenMetadata or null if token not found
363
+ */
364
+ static extractTokenMetadataByDex(symbol, perpMetasByDex, assetContextsByDex, allMids, activeAssetData, finalAtOICaps) {
365
+ let foundDexName = null;
366
+ let foundAssetIndex = -1;
367
+ let foundAsset = null;
368
+ for (const [dexName, assets] of perpMetasByDex) {
369
+ const assetIndex = assets.findIndex((asset) => symbolsMatch(asset.name, symbol));
370
+ if (assetIndex !== -1) {
371
+ foundDexName = dexName;
372
+ foundAssetIndex = assetIndex;
373
+ foundAsset = assets[assetIndex];
374
+ break;
375
+ }
376
+ }
377
+ if (!foundDexName || foundAssetIndex === -1 || !foundAsset) {
378
+ return null;
379
+ }
380
+ const dexContexts = assetContextsByDex.get(foundDexName);
381
+ const assetCtx = dexContexts === null || dexContexts === void 0 ? void 0 : dexContexts[foundAssetIndex];
382
+ if (!assetCtx) {
383
+ return null;
384
+ }
385
+ // Get current price - prefer assetCtx.midPx as it's already index-matched,
386
+ // fall back to allMids lookup if midPx is null
387
+ const actualSymbol = foundAsset.name;
388
+ let currentPrice = 0;
389
+ // Fallback: assetCtx.midPx (already properly indexed)
390
+ if (!currentPrice || isNaN(currentPrice)) {
391
+ const currentPriceStr = allMids.mids[actualSymbol] || allMids.mids[symbol];
392
+ currentPrice = currentPriceStr ? parseFloat(currentPriceStr) : 0;
393
+ }
394
+ // Primary source: allMids lookup
395
+ if (assetCtx.midPx) {
396
+ currentPrice = parseFloat(assetCtx.midPx);
397
+ }
398
+ // Get previous day price
399
+ const prevDayPrice = parseFloat(assetCtx.prevDayPx);
400
+ // Calculate 24h price change
401
+ const priceChange24h = currentPrice - prevDayPrice;
402
+ const priceChange24hPercent = prevDayPrice !== 0 ? (priceChange24h / prevDayPrice) * 100 : 0;
403
+ // Parse other metadata
404
+ const netFunding = parseFloat(assetCtx.funding) * 100;
405
+ const markPrice = parseFloat(assetCtx.markPx);
406
+ const oraclePrice = parseFloat(assetCtx.oraclePx);
407
+ // Extract leverage info from activeAssetData if available
408
+ const tokenActiveData = (activeAssetData === null || activeAssetData === void 0 ? void 0 : activeAssetData[actualSymbol]) || (activeAssetData === null || activeAssetData === void 0 ? void 0 : activeAssetData[symbol]);
409
+ const leverage = tokenActiveData === null || tokenActiveData === void 0 ? void 0 : tokenActiveData.leverage;
410
+ const maxTradeSzs = tokenActiveData === null || tokenActiveData === void 0 ? void 0 : tokenActiveData.maxTradeSzs;
411
+ const availableToTrade = tokenActiveData === null || tokenActiveData === void 0 ? void 0 : tokenActiveData.availableToTrade;
412
+ const { symbolName, marketName } = getMarketInfoFromSymbol(actualSymbol);
413
+ return {
414
+ assetName: foundAsset.name,
415
+ symbolName,
416
+ marketName,
417
+ isAtOiCaps: finalAtOICaps ? finalAtOICaps.includes(symbol) : false,
418
+ currentPrice,
419
+ prevDayPrice,
420
+ priceChange24h,
421
+ priceChange24hPercent,
422
+ netFunding,
423
+ maxLeverage: foundAsset.maxLeverage,
424
+ markPrice,
425
+ oraclePrice,
426
+ openInterest: assetCtx.openInterest,
427
+ dayVolume: assetCtx.dayNtlVlm,
428
+ leverage,
429
+ maxTradeSzs,
430
+ availableToTrade,
431
+ collateralToken: foundAsset.collateralToken,
432
+ };
433
+ }
434
+ }
435
+ // Helper functions for token metadata
436
+ const buildOiCapSet = (finalAtOICaps) => new Set((finalAtOICaps !== null && finalAtOICaps !== void 0 ? finalAtOICaps : [])
437
+ .filter(Boolean)
438
+ .map((value) => value.toUpperCase()));
439
+ const isAtOiCaps = (assetName, oiCapSet) => oiCapSet.has(assetName.toUpperCase());
440
+ const applyMetadataContext = (symbol, metadata, oiCapSet) => {
441
+ if (!metadata)
442
+ return null;
443
+ const { symbolName, marketName } = getMarketInfoFromSymbol(symbol);
444
+ return {
445
+ ...metadata,
446
+ symbolName,
447
+ marketName,
448
+ isAtOiCaps: isAtOiCaps(symbol, oiCapSet),
449
+ };
450
+ };
451
+ const applyOiCapsToMetadataMap = (tokenMetadata, finalAtOICaps) => {
452
+ if (!tokenMetadata || Object.keys(tokenMetadata).length === 0) {
453
+ return tokenMetadata;
454
+ }
455
+ const oiCapSet = buildOiCapSet(finalAtOICaps);
456
+ const next = {};
457
+ Object.entries(tokenMetadata).forEach(([symbol, metadata]) => {
458
+ next[symbol] = applyMetadataContext(symbol, metadata, oiCapSet);
459
+ });
460
+ return next;
461
+ };
462
+ const shouldSkipToken = (asset, oiCapSet) => {
463
+ if (asset.isDelisted)
464
+ return true;
465
+ if (isAtOiCaps(asset.name, oiCapSet))
466
+ return true;
467
+ return false;
468
+ };
469
+ const buildTokenMetadataMap = ({ perpMetasByDex, assetContextsByDex, allMids, activeAssetData, finalAtOICaps, }) => {
470
+ if (!perpMetasByDex || !assetContextsByDex || !allMids) {
471
+ return {};
472
+ }
473
+ const oiCapSet = buildOiCapSet(finalAtOICaps);
474
+ const metadataMap = {};
475
+ // Iterate through all DEXes and their assets
476
+ for (const [, assets] of perpMetasByDex) {
477
+ for (const asset of assets) {
478
+ if (shouldSkipToken(asset, oiCapSet)) {
479
+ continue;
480
+ }
481
+ const symbol = asset.name;
482
+ const metadata = TokenMetadataExtractor.extractTokenMetadataByDex(symbol, perpMetasByDex, assetContextsByDex, allMids, activeAssetData, finalAtOICaps);
483
+ metadataMap[symbol] = applyMetadataContext(symbol, metadata, oiCapSet);
484
+ }
485
+ }
486
+ return metadataMap;
487
+ };
488
+ const updateTokenMetadataForSymbols = (prev, symbols, { perpMetasByDex, assetContextsByDex, allMids, activeAssetData, finalAtOICaps, }) => {
489
+ if (!perpMetasByDex || !assetContextsByDex || !allMids) {
490
+ return prev;
491
+ }
492
+ const oiCapSet = buildOiCapSet(finalAtOICaps);
493
+ const next = { ...prev };
494
+ symbols.forEach((symbol) => {
495
+ // Find asset in any DEX
496
+ let foundAsset;
497
+ for (const [, assets] of perpMetasByDex) {
498
+ foundAsset = assets.find((a) => a.name === symbol);
499
+ if (foundAsset)
500
+ break;
501
+ }
502
+ if (foundAsset && shouldSkipToken(foundAsset, oiCapSet)) {
503
+ delete next[symbol];
504
+ return;
505
+ }
506
+ next[symbol] = applyMetadataContext(symbol, TokenMetadataExtractor.extractTokenMetadataByDex(symbol, perpMetasByDex, assetContextsByDex, allMids, activeAssetData, finalAtOICaps), oiCapSet);
507
+ });
508
+ return next;
509
+ };
510
+ const refreshTokenMetadata = (state, overrides, options) => {
511
+ var _a, _b, _c, _d, _e, _f, _g, _h;
512
+ const inputs = {
513
+ perpMetaAssets: (_a = overrides.perpMetaAssets) !== null && _a !== void 0 ? _a : state.perpMetaAssets,
514
+ finalAssetContexts: (_b = overrides.finalAssetContexts) !== null && _b !== void 0 ? _b : state.finalAssetContexts,
515
+ allMids: (_c = overrides.allMids) !== null && _c !== void 0 ? _c : state.allMids,
516
+ activeAssetData: (_d = overrides.activeAssetData) !== null && _d !== void 0 ? _d : state.activeAssetData,
517
+ finalAtOICaps: (_e = overrides.finalAtOICaps) !== null && _e !== void 0 ? _e : state.finalAtOICaps,
518
+ // DEX-aware inputs
519
+ perpMetasByDex: (_f = overrides.perpMetasByDex) !== null && _f !== void 0 ? _f : state.perpMetasByDex,
520
+ assetContextsByDex: (_g = overrides.assetContextsByDex) !== null && _g !== void 0 ? _g : state.assetContextsByDex,
521
+ };
522
+ if (!inputs.perpMetasByDex || !inputs.assetContextsByDex || !inputs.allMids) {
523
+ return state.tokenMetadata;
524
+ }
525
+ if (options === null || options === void 0 ? void 0 : options.oiCapsOnly) {
526
+ return applyOiCapsToMetadataMap(state.tokenMetadata, inputs.finalAtOICaps);
527
+ }
528
+ if ((_h = options === null || options === void 0 ? void 0 : options.symbols) === null || _h === void 0 ? void 0 : _h.length) {
529
+ return updateTokenMetadataForSymbols(state.tokenMetadata, options.symbols, inputs);
530
+ }
531
+ return buildTokenMetadataMap(inputs);
532
+ };
533
+
534
+ const useHyperliquidData = create((set) => ({
461
535
  allMids: null,
462
536
  activeAssetData: null,
463
537
  candleData: null,
@@ -466,21 +540,32 @@ const useHyperliquidData = create((set, get) => ({
466
540
  aggregatedClearingHouseState: null,
467
541
  rawClearinghouseStates: null,
468
542
  perpMetaAssets: null,
469
- allPerpMetaAssets: null,
470
- hip3Assets: new Map(),
471
- hip3MarketPrefixes: new Map(),
472
- setAllMids: (value) => set({ allMids: value }),
473
- setActiveAssetData: (value) => set((state) => ({
474
- activeAssetData: typeof value === 'function' ? value(state.activeAssetData) : value,
543
+ tokenMetadata: {},
544
+ perpDexs: null,
545
+ perpMetasByDex: null,
546
+ assetContextsByDex: null,
547
+ setAllMids: (value) => set((state) => ({
548
+ allMids: value,
549
+ tokenMetadata: refreshTokenMetadata(state, { allMids: value }),
475
550
  })),
551
+ setActiveAssetData: (value) => set((state) => {
552
+ const activeAssetData = typeof value === 'function' ? value(state.activeAssetData) : value;
553
+ return {
554
+ activeAssetData,
555
+ tokenMetadata: refreshTokenMetadata(state, { activeAssetData }),
556
+ };
557
+ }),
476
558
  deleteActiveAssetData: (key) => {
477
559
  set((state) => {
478
560
  if (!state.activeAssetData || !(key in state.activeAssetData)) {
479
- return state; // No change if key doesn't exist
561
+ return state;
480
562
  }
481
- const updated = { ...state.activeAssetData };
482
- delete updated[key];
483
- return { activeAssetData: updated };
563
+ const activeAssetData = { ...state.activeAssetData };
564
+ delete activeAssetData[key];
565
+ return {
566
+ activeAssetData,
567
+ tokenMetadata: refreshTokenMetadata(state, { activeAssetData }, { symbols: [key] }),
568
+ };
484
569
  });
485
570
  },
486
571
  addCandleData(symbol, candle) {
@@ -502,20 +587,43 @@ const useHyperliquidData = create((set, get) => ({
502
587
  });
503
588
  },
504
589
  setCandleData: (value) => set({ candleData: value }),
505
- upsertActiveAssetData: (key, value) => set((state) => ({
506
- activeAssetData: {
507
- ...state.activeAssetData,
508
- [key]: value,
509
- },
590
+ upsertActiveAssetData: (key, value) => set((state) => {
591
+ var _a;
592
+ const activeAssetData = { ...((_a = state.activeAssetData) !== null && _a !== void 0 ? _a : {}), [key]: value };
593
+ return {
594
+ activeAssetData,
595
+ tokenMetadata: refreshTokenMetadata(state, { activeAssetData }, { symbols: [key] }),
596
+ };
597
+ }),
598
+ setFinalAssetContexts: (value) => set((state) => ({
599
+ finalAssetContexts: value,
600
+ tokenMetadata: refreshTokenMetadata(state, { finalAssetContexts: value }),
601
+ })),
602
+ setFinalAtOICaps: (value) => set((state) => ({
603
+ finalAtOICaps: value,
604
+ tokenMetadata: refreshTokenMetadata(state, { finalAtOICaps: value }, { oiCapsOnly: true }),
510
605
  })),
511
- setFinalAssetContexts: (value) => set({ finalAssetContexts: value }),
512
- setFinalAtOICaps: (value) => set({ finalAtOICaps: value }),
513
606
  setAggregatedClearingHouseState: (value) => set({ aggregatedClearingHouseState: value }),
514
607
  setRawClearinghouseStates: (value) => set({ rawClearinghouseStates: value }),
515
- setPerpMetaAssets: (value) => set({ perpMetaAssets: value }),
516
- setAllPerpMetaAssets: (value) => set({ allPerpMetaAssets: value }),
517
- setHip3Assets: (value) => set({ hip3Assets: value }),
518
- setHip3MarketPrefixes: (value) => set({ hip3MarketPrefixes: value }),
608
+ setPerpMetaAssets: (value) => set((state) => ({
609
+ perpMetaAssets: value,
610
+ tokenMetadata: refreshTokenMetadata(state, { perpMetaAssets: value }),
611
+ })),
612
+ setPerpDexs: (value) => set({ perpDexs: value }),
613
+ setPerpMetasByDex: (value) => set((state) => ({
614
+ perpMetasByDex: value,
615
+ tokenMetadata: refreshTokenMetadata(state, {
616
+ perpMetasByDex: value,
617
+ assetContextsByDex: state.assetContextsByDex,
618
+ }),
619
+ })),
620
+ setAssetContextsByDex: (value) => set((state) => ({
621
+ assetContextsByDex: value,
622
+ tokenMetadata: refreshTokenMetadata(state, {
623
+ assetContextsByDex: value,
624
+ perpMetasByDex: state.perpMetasByDex,
625
+ }),
626
+ })),
519
627
  }));
520
628
 
521
629
  /**
@@ -778,7 +886,7 @@ const useUserSelection$1 = create((set, get) => ({
778
886
  }));
779
887
 
780
888
  const useHyperliquidNativeWebSocket = ({ address, enabled = true, onUserFills, }) => {
781
- const { setAllMids, setActiveAssetData, upsertActiveAssetData, setCandleData, deleteCandleSymbol, deleteActiveAssetData, addCandleData, setFinalAssetContexts, setFinalAtOICaps, setAggregatedClearingHouseState, setRawClearinghouseStates, } = useHyperliquidData();
889
+ const { setAllMids, setActiveAssetData, upsertActiveAssetData, setCandleData, deleteCandleSymbol, deleteActiveAssetData, addCandleData, setFinalAtOICaps, setAggregatedClearingHouseState, setRawClearinghouseStates, setAssetContextsByDex, } = useHyperliquidData();
782
890
  const { setSpotState } = useUserData();
783
891
  const { candleInterval } = useUserSelection$1();
784
892
  const userSummary = useUserData((state) => state.accountSummary);
@@ -831,22 +939,13 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, onUserFills, }
831
939
  case 'allDexsAssetCtxs':
832
940
  {
833
941
  const data = response.data;
834
- // Filter out hyna to match perpMetaAssets filtering
835
- const FILTERED_DEX_PREFIXES = ['hyna'];
836
- const filtered = (data.ctxs || [])
837
- .filter(([prefix]) => !FILTERED_DEX_PREFIXES.includes((prefix || '').toLowerCase()))
838
- .sort((a, b) => {
839
- // Sort to match perpMetaAssets order: default market first, then alphabetically
840
- const prefixA = a[0] || '';
841
- const prefixB = b[0] || '';
842
- if (prefixA === '' && prefixB !== '')
843
- return -1;
844
- if (prefixA !== '' && prefixB === '')
845
- return 1;
846
- return prefixA.localeCompare(prefixB);
942
+ // Store by DEX name, mapping '' to 'HYPERLIQUID'
943
+ const assetContextsByDex = new Map();
944
+ data.ctxs.forEach(([dexKey, ctxs]) => {
945
+ const dexName = dexKey === '' ? 'HYPERLIQUID' : dexKey;
946
+ assetContextsByDex.set(dexName, ctxs || []);
847
947
  });
848
- const finalAssetContexts = filtered.flatMap(([, ctxs]) => ctxs || []);
849
- setFinalAssetContexts(finalAssetContexts);
948
+ setAssetContextsByDex(assetContextsByDex);
850
949
  }
851
950
  break;
852
951
  case 'allDexsClearinghouseState':
@@ -889,51 +988,20 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, onUserFills, }
889
988
  case 'allMids':
890
989
  {
891
990
  const data = response.data;
892
- // Keep BOTH normalized prefixed keys AND display symbol keys
893
- // This ensures xyz:TSLA and flx:TSLA are stored separately,
894
- // while also maintaining backward compatibility with non-prefixed lookups
895
- const mids = {};
896
- Object.entries(data.mids || {}).forEach(([k, v]) => {
897
- // Normalize prefixed keys to lowercase prefix (e.g., "XYZ:TSLA" -> "xyz:TSLA")
898
- // This matches how we look up tokens in the SDK
899
- let normalizedKey = k;
900
- if (k.includes(':')) {
901
- const [prefix, ...rest] = k.split(':');
902
- normalizedKey = `${prefix.toLowerCase()}:${rest.join(':')}`;
903
- }
904
- // Store with normalized key
905
- mids[normalizedKey] = v;
906
- // Also store with original key for backward compatibility
907
- if (k !== normalizedKey) {
908
- mids[k] = v;
909
- }
910
- // Also store with display symbol for backward compatibility
911
- const displayKey = toDisplaySymbol(k);
912
- // Only set display key if it doesn't already exist (avoid overwriting market-specific prices)
913
- if (!(displayKey in mids)) {
914
- mids[displayKey] = v;
915
- }
916
- });
917
- setAllMids({ mids });
991
+ setAllMids(data);
918
992
  }
919
993
  break;
920
994
  case 'activeAssetData':
921
995
  {
922
996
  const assetData = response.data;
923
- const symbol = toDisplaySymbol(assetData.coin);
924
- const normalized = {
925
- ...assetData,
926
- coin: symbol,
927
- };
928
- upsertActiveAssetData(symbol, normalized);
997
+ upsertActiveAssetData(assetData.coin, assetData);
929
998
  }
930
999
  break;
931
1000
  case 'candle':
932
1001
  {
933
1002
  const candleDataItem = response.data;
934
- const symbol = toDisplaySymbol(candleDataItem.s || '');
935
- const normalized = { ...candleDataItem, s: symbol };
936
- addCandleData(symbol, normalized);
1003
+ const symbol = candleDataItem.s || '';
1004
+ addCandleData(symbol, candleDataItem);
937
1005
  }
938
1006
  break;
939
1007
  case 'spotState':
@@ -958,10 +1026,10 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, onUserFills, }
958
1026
  setAllMids,
959
1027
  upsertActiveAssetData,
960
1028
  addCandleData,
961
- setFinalAssetContexts,
962
1029
  setFinalAtOICaps,
963
1030
  setAggregatedClearingHouseState,
964
1031
  setRawClearinghouseStates,
1032
+ setAssetContextsByDex,
965
1033
  setSpotState,
966
1034
  onUserFills,
967
1035
  ]);
@@ -1352,367 +1420,102 @@ const useAccountSummary = () => {
1352
1420
  throw new Error('useAccountSummary must be used within a PearHyperliquidProvider');
1353
1421
  }
1354
1422
  const platformAccountSummary = useUserData((state) => state.accountSummary);
1355
- const aggregatedClearingHouseState = useHyperliquidData((state) => state.aggregatedClearingHouseState);
1356
- const registeredAgentWallets = useUserData((state) => state.userExtraAgents);
1357
- const isLoading = useMemo(() => {
1358
- return !platformAccountSummary || !registeredAgentWallets || !aggregatedClearingHouseState;
1359
- }, [platformAccountSummary, registeredAgentWallets, aggregatedClearingHouseState]);
1360
- // Create calculator and compute account summary
1361
- const calculator = new AccountSummaryCalculator(aggregatedClearingHouseState);
1362
- const calculated = calculator.calculateAccountSummary(platformAccountSummary, registeredAgentWallets || []);
1363
- return { data: calculated, isLoading };
1364
- };
1365
-
1366
- function findAssetMeta$4(coinName, perpMetaAssets, knownPrefix, desiredCollateral) {
1367
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
1368
- if (!perpMetaAssets) {
1369
- return { collateralToken: 'USDC', marketPrefix: null };
1370
- }
1371
- if (desiredCollateral) {
1372
- const collateralMatch = perpMetaAssets.find((a) => a.name === coinName && a.collateralToken === desiredCollateral);
1373
- if (collateralMatch) {
1374
- return {
1375
- collateralToken: (_a = collateralMatch.collateralToken) !== null && _a !== void 0 ? _a : 'USDC',
1376
- marketPrefix: (_b = collateralMatch.marketPrefix) !== null && _b !== void 0 ? _b : null,
1377
- };
1378
- }
1379
- }
1380
- if (coinName.includes(':')) {
1381
- const [prefix, symbol] = coinName.split(':');
1382
- const exactMatch = perpMetaAssets.find((a) => {
1383
- var _a;
1384
- return a.name === symbol &&
1385
- ((_a = a.marketPrefix) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === prefix.toLowerCase();
1386
- });
1387
- if (exactMatch) {
1388
- return {
1389
- collateralToken: (_c = exactMatch.collateralToken) !== null && _c !== void 0 ? _c : 'USDC',
1390
- marketPrefix: (_d = exactMatch.marketPrefix) !== null && _d !== void 0 ? _d : null,
1391
- };
1392
- }
1393
- }
1394
- if (knownPrefix) {
1395
- const exactMatch = perpMetaAssets.find((a) => {
1396
- var _a;
1397
- return a.name === coinName &&
1398
- ((_a = a.marketPrefix) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === knownPrefix.toLowerCase();
1399
- });
1400
- if (exactMatch) {
1401
- return {
1402
- collateralToken: (_e = exactMatch.collateralToken) !== null && _e !== void 0 ? _e : 'USDC',
1403
- marketPrefix: (_f = exactMatch.marketPrefix) !== null && _f !== void 0 ? _f : null,
1404
- };
1405
- }
1406
- }
1407
- const exactMatch = perpMetaAssets.find((a) => a.name === coinName && !a.marketPrefix);
1408
- if (exactMatch) {
1409
- return {
1410
- collateralToken: (_g = exactMatch.collateralToken) !== null && _g !== void 0 ? _g : 'USDC',
1411
- marketPrefix: (_h = exactMatch.marketPrefix) !== null && _h !== void 0 ? _h : null,
1412
- };
1413
- }
1414
- const hip3Matches = perpMetaAssets.filter((a) => a.name === coinName && a.marketPrefix);
1415
- if (hip3Matches.length > 0) {
1416
- if (desiredCollateral) {
1417
- const collateralMatch = hip3Matches.find((a) => a.collateralToken === desiredCollateral);
1418
- if (collateralMatch) {
1419
- return {
1420
- collateralToken: (_j = collateralMatch.collateralToken) !== null && _j !== void 0 ? _j : 'USDC',
1421
- marketPrefix: (_k = collateralMatch.marketPrefix) !== null && _k !== void 0 ? _k : null,
1422
- };
1423
- }
1424
- }
1425
- const usdHMatch = hip3Matches.find((a) => a.collateralToken === 'USDH');
1426
- const chosen = usdHMatch !== null && usdHMatch !== void 0 ? usdHMatch : hip3Matches[0];
1427
- return {
1428
- collateralToken: (_l = chosen.collateralToken) !== null && _l !== void 0 ? _l : 'USDC',
1429
- marketPrefix: (_m = chosen.marketPrefix) !== null && _m !== void 0 ? _m : null,
1430
- };
1431
- }
1432
- return { collateralToken: 'USDC', marketPrefix: null };
1433
- }
1434
- function enrichTradeHistoryAssets(assets, perpMetaAssets) {
1435
- return assets.map((asset) => {
1436
- var _a;
1437
- if (asset.marketPrefix && asset.collateralToken) {
1438
- return asset;
1439
- }
1440
- const meta = findAssetMeta$4(asset.coin, perpMetaAssets, asset.marketPrefix, asset.collateralToken);
1441
- return {
1442
- ...asset,
1443
- marketPrefix: asset.marketPrefix || meta.marketPrefix,
1444
- collateralToken: (_a = asset.collateralToken) !== null && _a !== void 0 ? _a : meta.collateralToken,
1445
- };
1446
- });
1447
- }
1448
- function enrichTradeHistories(histories, perpMetaAssets) {
1449
- return histories.map((history) => ({
1450
- ...history,
1451
- closedLongAssets: enrichTradeHistoryAssets(history.closedLongAssets, perpMetaAssets),
1452
- closedShortAssets: enrichTradeHistoryAssets(history.closedShortAssets, perpMetaAssets),
1453
- }));
1454
- }
1455
- const useTradeHistories = () => {
1456
- const context = useContext(PearHyperliquidContext);
1457
- if (!context) {
1458
- throw new Error('useTradeHistories must be used within a PearHyperliquidProvider');
1459
- }
1460
- const tradeHistories = useUserData((state) => state.tradeHistories);
1461
- const allPerpMetaAssets = useHyperliquidData((state) => state.allPerpMetaAssets);
1462
- const isLoading = useMemo(() => {
1463
- return tradeHistories === null && context.isConnected;
1464
- }, [tradeHistories, context.isConnected]);
1465
- const enrichedTradeHistories = useMemo(() => {
1466
- if (!tradeHistories)
1467
- return null;
1468
- return enrichTradeHistories(tradeHistories, allPerpMetaAssets);
1469
- }, [tradeHistories, allPerpMetaAssets]);
1470
- return { data: enrichedTradeHistories, isLoading };
1471
- };
1472
- const useOpenOrders = () => {
1473
- const context = useContext(PearHyperliquidContext);
1474
- if (!context) {
1475
- throw new Error('useOpenOrders must be used within a PearHyperliquidProvider');
1476
- }
1477
- const openOrders = useUserData((state) => state.openOrders);
1478
- const isLoading = useMemo(() => {
1479
- return openOrders === null && context.isConnected;
1480
- }, [openOrders, context.isConnected]);
1481
- return { data: openOrders, isLoading };
1482
- };
1483
-
1484
- const useUserSelection = () => {
1485
- return useUserSelection$1();
1486
- };
1487
-
1488
- /**
1489
- * Hook to access webData and native WebSocket state
1490
- */
1491
- const useWebData = () => {
1492
- const context = useContext(PearHyperliquidContext);
1493
- if (!context) {
1494
- throw new Error('useWebData must be used within a PearHyperliquidProvider');
1495
- }
1496
- const finalAssetContexts = useHyperliquidData((state) => state.finalAssetContexts);
1497
- const perpMetaAssets = useHyperliquidData((state) => state.perpMetaAssets);
1498
- const aggregatedClearinghouseState = useHyperliquidData((state) => state.aggregatedClearingHouseState);
1499
- const finalAtOICaps = useHyperliquidData((state) => state.finalAtOICaps);
1500
- const hip3Assets = useHyperliquidData((state) => state.hip3Assets);
1501
- const hip3MarketPrefixes = useHyperliquidData((state) => state.hip3MarketPrefixes);
1502
- let marketDataBySymbol = {};
1503
- if (finalAssetContexts && perpMetaAssets) {
1504
- const result = {};
1505
- // Build a map of display name -> asset context index (for unique display names)
1506
- const displayNameToContextIndex = new Map();
1507
- const seenNames = new Set();
1508
- let contextIndex = 0;
1509
- // First pass: map unique display names to their context index
1510
- for (let index = 0; index < perpMetaAssets.length; index++) {
1511
- const name = perpMetaAssets[index].name;
1512
- if (!seenNames.has(name)) {
1513
- seenNames.add(name);
1514
- if (contextIndex < finalAssetContexts.length) {
1515
- displayNameToContextIndex.set(name, contextIndex);
1516
- contextIndex++;
1517
- }
1518
- }
1519
- }
1520
- // Second pass: create nested entries for all market variants
1521
- for (let index = 0; index < perpMetaAssets.length; index++) {
1522
- const universeAsset = perpMetaAssets[index];
1523
- const displayName = universeAsset.name;
1524
- const marketPrefix = universeAsset.marketPrefix;
1525
- const ctxIndex = displayNameToContextIndex.get(displayName);
1526
- if (ctxIndex !== undefined) {
1527
- const assetContext = finalAssetContexts[ctxIndex];
1528
- // Initialize the symbol entry if it doesn't exist
1529
- if (!result[displayName]) {
1530
- result[displayName] = {};
1531
- }
1532
- // Use marketPrefix as key for HIP-3 assets, "default" for regular assets
1533
- const variantKey = marketPrefix || 'default';
1534
- result[displayName][variantKey] = {
1535
- asset: assetContext,
1536
- universe: universeAsset,
1537
- };
1538
- }
1539
- }
1540
- marketDataBySymbol = result;
1541
- }
1542
- return {
1543
- hip3Assets,
1544
- hip3MarketPrefixes,
1545
- clearinghouseState: aggregatedClearinghouseState,
1546
- perpsAtOpenInterestCap: finalAtOICaps,
1547
- marketDataBySymbol,
1548
- isConnected: context.nativeIsConnected,
1549
- error: context.nativeLastError,
1550
- };
1551
- };
1552
-
1553
- /**
1554
- * Check if two symbols match, handling kPEPE/KPEPE variations
1555
- * Returns true if symbols match (case-insensitive for k-prefix tokens)
1556
- */
1557
- function symbolsMatch(assetName, searchSymbol) {
1558
- // Exact match
1559
- if (assetName === searchSymbol)
1560
- return true;
1561
- // Try case-insensitive match for k-prefix tokens (kPEPE vs KPEPE)
1562
- if (assetName.toUpperCase() === searchSymbol.toUpperCase()) {
1563
- return true;
1564
- }
1565
- return false;
1566
- }
1567
- /**
1568
- * Extracts token metadata from aggregated WebData3 contexts and AllMids data
1569
- */
1570
- class TokenMetadataExtractor {
1571
- /**
1572
- * Extracts comprehensive token metadata
1573
- * @param symbol - Token symbol (base symbol without prefix, e.g., "TSLA")
1574
- * @param perpMetaAssets - Aggregated universe assets (flattened across dexes)
1575
- * @param finalAssetContexts - Aggregated asset contexts (flattened across dexes)
1576
- * @param allMids - AllMids data containing current prices
1577
- * @param activeAssetData - Optional active asset data containing leverage information
1578
- * @param marketPrefix - Optional market prefix (e.g., "xyz", "flx") for HIP3 multi-market assets
1579
- * @returns TokenMetadata or null if token not found
1580
- */
1581
- static extractTokenMetadata(symbol, perpMetaAssets, finalAssetContexts, allMids, activeAssetData, marketPrefix) {
1582
- if (!perpMetaAssets || !finalAssetContexts || !allMids) {
1583
- return null;
1584
- }
1585
- // Find token index in aggregated universe
1586
- // For HIP3 assets, match both name AND marketPrefix
1587
- // Uses symbolsMatch to handle kPEPE/KPEPE case variations
1588
- const universeIndex = perpMetaAssets.findIndex((asset) => {
1589
- if (!symbolsMatch(asset.name, symbol))
1590
- return false;
1591
- // If marketPrefix is specified, match it; otherwise match assets without prefix
1592
- if (marketPrefix) {
1593
- return asset.marketPrefix === marketPrefix;
1594
- }
1595
- // No prefix specified - match non-HIP3 asset (no marketPrefix) or first matching asset
1596
- return !asset.marketPrefix;
1597
- });
1598
- if (universeIndex === -1) {
1599
- return null;
1600
- }
1601
- const universeAsset = perpMetaAssets[universeIndex];
1602
- const assetCtx = finalAssetContexts[universeIndex];
1603
- if (!assetCtx) {
1604
- return null;
1605
- }
1606
- // Get current price - prefer assetCtx.midPx as it's already index-matched,
1607
- // fall back to allMids lookup if midPx is null
1608
- const actualSymbol = universeAsset.name; // Use actual symbol from universe (handles kPEPE vs KPEPE)
1609
- const prefixedKeyColon = marketPrefix
1610
- ? `${marketPrefix}:${actualSymbol}`
1611
- : null;
1612
- let currentPrice = 0;
1613
- // Primary source: assetCtx.midPx (already properly indexed)
1614
- if (assetCtx.midPx) {
1615
- currentPrice = parseFloat(assetCtx.midPx);
1616
- }
1617
- // Fallback: allMids lookup with multiple key formats for HIP3 markets
1618
- // Try actual symbol from universe first, then input symbol
1619
- if (!currentPrice || isNaN(currentPrice)) {
1620
- const currentPriceStr = (prefixedKeyColon && allMids.mids[prefixedKeyColon]) ||
1621
- allMids.mids[actualSymbol] ||
1622
- allMids.mids[symbol];
1623
- currentPrice = currentPriceStr ? parseFloat(currentPriceStr) : 0;
1624
- }
1625
- // Get previous day price
1626
- const prevDayPrice = parseFloat(assetCtx.prevDayPx);
1627
- // Calculate 24h price change
1628
- const priceChange24h = currentPrice - prevDayPrice;
1629
- const priceChange24hPercent = prevDayPrice !== 0 ? (priceChange24h / prevDayPrice) * 100 : 0;
1630
- // Parse other metadata
1631
- const netFunding = parseFloat(assetCtx.funding) * 100;
1632
- const markPrice = parseFloat(assetCtx.markPx);
1633
- const oraclePrice = parseFloat(assetCtx.oraclePx);
1634
- // Extract leverage info from activeAssetData if available
1635
- // Try prefixed key first (e.g., "xyz:TSLA"), then actual symbol, then input symbol
1636
- const activeDataKey = prefixedKeyColon && (activeAssetData === null || activeAssetData === void 0 ? void 0 : activeAssetData[prefixedKeyColon])
1637
- ? prefixedKeyColon
1638
- : (activeAssetData === null || activeAssetData === void 0 ? void 0 : activeAssetData[actualSymbol])
1639
- ? actualSymbol
1640
- : symbol;
1641
- const tokenActiveData = activeAssetData === null || activeAssetData === void 0 ? void 0 : activeAssetData[activeDataKey];
1642
- const leverage = tokenActiveData === null || tokenActiveData === void 0 ? void 0 : tokenActiveData.leverage;
1643
- const maxTradeSzs = tokenActiveData === null || tokenActiveData === void 0 ? void 0 : tokenActiveData.maxTradeSzs;
1644
- const availableToTrade = tokenActiveData === null || tokenActiveData === void 0 ? void 0 : tokenActiveData.availableToTrade;
1645
- return {
1646
- currentPrice,
1647
- prevDayPrice,
1648
- priceChange24h,
1649
- priceChange24hPercent,
1650
- netFunding,
1651
- maxLeverage: universeAsset.maxLeverage,
1652
- markPrice,
1653
- oraclePrice,
1654
- openInterest: assetCtx.openInterest,
1655
- dayVolume: assetCtx.dayNtlVlm,
1656
- leverage,
1657
- maxTradeSzs,
1658
- availableToTrade,
1659
- collateralToken: universeAsset.collateralToken,
1660
- };
1661
- }
1662
- /**
1663
- * Extracts metadata for multiple tokens
1664
- * @param tokens - Array of token objects with symbol and optional marketPrefix
1665
- * @param perpMetaAssets - Aggregated universe assets
1666
- * @param finalAssetContexts - Aggregated asset contexts
1667
- * @param allMids - AllMids data
1668
- * @param activeAssetData - Optional active asset data containing leverage information
1669
- * @returns Record of unique key to TokenMetadata. Key is "{prefix}:{symbol}" for HIP3 assets, or just "{symbol}" otherwise
1670
- */
1671
- static extractMultipleTokensMetadata(tokens, perpMetaAssets, finalAssetContexts, allMids, activeAssetData) {
1672
- const result = {};
1673
- for (const token of tokens) {
1674
- // Use a unique key that includes the prefix for HIP3 assets
1675
- // This ensures xyz:TSLA and flx:TSLA get separate entries
1676
- const resultKey = token.marketPrefix
1677
- ? `${token.marketPrefix}:${token.symbol}`
1678
- : token.symbol;
1679
- result[resultKey] = this.extractTokenMetadata(token.symbol, perpMetaAssets, finalAssetContexts, allMids, activeAssetData, token.marketPrefix);
1680
- }
1681
- return result;
1682
- }
1683
- /**
1684
- * Checks if token data is available in aggregated universe assets
1685
- * @param symbol - Token symbol
1686
- * @param perpMetaAssets - Aggregated universe assets
1687
- * @returns boolean indicating if token exists in universe
1688
- */
1689
- static isTokenAvailable(symbol, perpMetaAssets) {
1690
- if (!perpMetaAssets)
1691
- return false;
1692
- return perpMetaAssets.some((asset) => symbolsMatch(asset.name, symbol));
1423
+ const aggregatedClearingHouseState = useHyperliquidData((state) => state.aggregatedClearingHouseState);
1424
+ const registeredAgentWallets = useUserData((state) => state.userExtraAgents);
1425
+ const isLoading = useMemo(() => {
1426
+ return !platformAccountSummary || !registeredAgentWallets || !aggregatedClearingHouseState;
1427
+ }, [platformAccountSummary, registeredAgentWallets, aggregatedClearingHouseState]);
1428
+ // Create calculator and compute account summary
1429
+ const calculator = new AccountSummaryCalculator(aggregatedClearingHouseState);
1430
+ const calculated = calculator.calculateAccountSummary(platformAccountSummary, registeredAgentWallets || []);
1431
+ return { data: calculated, isLoading };
1432
+ };
1433
+
1434
+ const selectTokenMetadataBySymbols = (tokenMetadata, symbols) => {
1435
+ const result = {};
1436
+ symbols.forEach((symbol) => {
1437
+ var _a;
1438
+ result[symbol] = (_a = tokenMetadata[symbol]) !== null && _a !== void 0 ? _a : null;
1439
+ });
1440
+ return result;
1441
+ };
1442
+ const getAssetByName = (tokenMetadata, symbol) => {
1443
+ var _a, _b;
1444
+ if (symbol in tokenMetadata) {
1445
+ return (_a = tokenMetadata[symbol]) !== null && _a !== void 0 ? _a : null;
1693
1446
  }
1694
- }
1447
+ const normalizedSymbol = symbol.toUpperCase();
1448
+ const matchKey = Object.keys(tokenMetadata).find((key) => key.toUpperCase() === normalizedSymbol);
1449
+ return matchKey ? (_b = tokenMetadata[matchKey]) !== null && _b !== void 0 ? _b : null : null;
1450
+ };
1695
1451
 
1696
1452
  /**
1697
- * Parse a token string that may have a market prefix (e.g., "xyz:GOOGL" -> { prefix: "xyz", symbol: "GOOGL" })
1698
- * This allows us to keep the full name (xyz:GOOGL) for URLs/tags while extracting just the symbol for SDK lookups.
1453
+ * Hook to access webData
1699
1454
  */
1700
- function parseTokenWithPrefix(token) {
1701
- if (token.includes(":")) {
1702
- const [prefix, ...rest] = token.split(":");
1703
- const symbol = rest.join(":").toUpperCase();
1704
- return {
1705
- prefix: prefix.toLowerCase(),
1706
- symbol,
1707
- fullName: `${prefix.toLowerCase()}:${symbol}`,
1708
- };
1455
+ const useMarket = () => {
1456
+ const tokenMetadata = useHyperliquidData((state) => state.tokenMetadata);
1457
+ const allTokenMetadata = useMemo(() => Object.values(tokenMetadata).filter((metadata) => Boolean(metadata)), [tokenMetadata]);
1458
+ const getAssetByName$1 = useCallback((symbol) => getAssetByName(tokenMetadata, symbol), [tokenMetadata]);
1459
+ return { allTokenMetadata, getAssetByName: getAssetByName$1 };
1460
+ };
1461
+
1462
+ const useTradeHistories = () => {
1463
+ const context = useContext(PearHyperliquidContext);
1464
+ if (!context) {
1465
+ throw new Error('useTradeHistories must be used within a PearHyperliquidProvider');
1709
1466
  }
1710
- return {
1711
- prefix: null,
1712
- symbol: token.toUpperCase(),
1713
- fullName: token.toUpperCase(),
1714
- };
1715
- }
1467
+ const tradeHistories = useUserData((state) => state.tradeHistories);
1468
+ const { getAssetByName } = useMarket();
1469
+ const enrichedTradeHistories = useMemo(() => {
1470
+ if (!tradeHistories)
1471
+ return null;
1472
+ return tradeHistories.map((history) => ({
1473
+ ...history,
1474
+ closedLongAssets: history.closedLongAssets.map((asset) => ({
1475
+ ...asset,
1476
+ metadata: getAssetByName(asset.coin),
1477
+ })),
1478
+ closedShortAssets: history.closedShortAssets.map((asset) => ({
1479
+ ...asset,
1480
+ metadata: getAssetByName(asset.coin),
1481
+ })),
1482
+ }));
1483
+ }, [tradeHistories, getAssetByName]);
1484
+ const isLoading = useMemo(() => {
1485
+ return tradeHistories === null && context.isConnected;
1486
+ }, [tradeHistories, context.isConnected]);
1487
+ return { data: enrichedTradeHistories, isLoading };
1488
+ };
1489
+ const useOpenOrders = () => {
1490
+ const context = useContext(PearHyperliquidContext);
1491
+ if (!context) {
1492
+ throw new Error('useOpenOrders must be used within a PearHyperliquidProvider');
1493
+ }
1494
+ const openOrders = useUserData((state) => state.openOrders);
1495
+ const { getAssetByName } = useMarket();
1496
+ const enrichedOpenOrders = useMemo(() => {
1497
+ if (!openOrders)
1498
+ return null;
1499
+ const mapAssets = (assets) => (assets !== null && assets !== void 0 ? assets : []).map((asset) => ({
1500
+ ...asset,
1501
+ metadata: getAssetByName(asset.asset),
1502
+ }));
1503
+ return openOrders.map((order) => ({
1504
+ ...order,
1505
+ longAssets: mapAssets(order.longAssets),
1506
+ shortAssets: mapAssets(order.shortAssets),
1507
+ }));
1508
+ }, [openOrders, getAssetByName]);
1509
+ const isLoading = useMemo(() => {
1510
+ return openOrders === null && context.isConnected;
1511
+ }, [openOrders, context.isConnected]);
1512
+ return { data: enrichedOpenOrders, isLoading };
1513
+ };
1514
+
1515
+ const useUserSelection = () => {
1516
+ return useUserSelection$1();
1517
+ };
1518
+
1716
1519
  const useTokenSelectionMetadataStore = create((set) => ({
1717
1520
  isPriceDataReady: false,
1718
1521
  isLoading: true,
@@ -1728,59 +1531,18 @@ const useTokenSelectionMetadataStore = create((set) => ({
1728
1531
  maxLeverage: 0,
1729
1532
  minMargin: 0,
1730
1533
  leverageMatched: true,
1731
- recompute: ({ perpMetaAssets, finalAssetContexts, allMids, activeAssetData, marketData, longTokens, shortTokens, }) => {
1732
- const isPriceDataReady = !!(perpMetaAssets &&
1733
- finalAssetContexts &&
1734
- allMids);
1735
- // Parse tokens - handle prefixed tokens like "xyz:GOOGL" by extracting the symbol and market prefix
1736
- // The full name (xyz:GOOGL) is kept as the metadata key for UI consistency
1737
- const parsedLongTokens = longTokens.map((t) => ({
1738
- ...t,
1739
- parsed: parseTokenWithPrefix(t.symbol),
1740
- }));
1741
- const parsedShortTokens = shortTokens.map((t) => ({
1742
- ...t,
1743
- parsed: parseTokenWithPrefix(t.symbol),
1744
- }));
1745
- // Extract base symbols with their market prefixes for SDK lookups
1746
- // This ensures xyz:TSLA and flx:TSLA get different market data
1747
- const longTokensForLookup = parsedLongTokens.map((t) => ({
1748
- symbol: t.parsed.symbol,
1749
- marketPrefix: t.parsed.prefix,
1750
- }));
1751
- const shortTokensForLookup = parsedShortTokens.map((t) => ({
1752
- symbol: t.parsed.symbol,
1753
- marketPrefix: t.parsed.prefix,
1754
- }));
1755
- // Also extract just the base symbols (without prefix) for lookups that don't support prefixes
1756
- const longBaseSymbols = longTokensForLookup.map((t) => t.symbol);
1757
- const shortBaseSymbols = shortTokensForLookup.map((t) => t.symbol);
1758
- // Get metadata using base symbols with market prefix for proper market differentiation
1759
- const longBaseMetadata = isPriceDataReady
1760
- ? TokenMetadataExtractor.extractMultipleTokensMetadata(longTokensForLookup, perpMetaAssets, finalAssetContexts, allMids, activeAssetData)
1534
+ recompute: ({ perpMetaAssets, tokenMetadata, marketData, longTokens, shortTokens, }) => {
1535
+ const isPriceDataReady = Object.keys(tokenMetadata).length > 0;
1536
+ // Get token symbols for lookups
1537
+ const longSymbols = longTokens.map((t) => t.symbol);
1538
+ const shortSymbols = shortTokens.map((t) => t.symbol);
1539
+ // Get metadata
1540
+ const longTokensMetadata = isPriceDataReady
1541
+ ? selectTokenMetadataBySymbols(tokenMetadata, longSymbols)
1761
1542
  : {};
1762
- const shortBaseMetadata = isPriceDataReady
1763
- ? TokenMetadataExtractor.extractMultipleTokensMetadata(shortTokensForLookup, perpMetaAssets, finalAssetContexts, allMids, activeAssetData)
1543
+ const shortTokensMetadata = isPriceDataReady
1544
+ ? selectTokenMetadataBySymbols(tokenMetadata, shortSymbols)
1764
1545
  : {};
1765
- // Re-map metadata using original full names (with prefix) as keys for UI consistency
1766
- // The extractor now keys by "{prefix}:{symbol}" for prefixed tokens, which matches our parsed.fullName
1767
- const longTokensMetadata = {};
1768
- parsedLongTokens.forEach((t) => {
1769
- var _a;
1770
- // Use the full name (e.g., "xyz:TSLA") as the lookup key since extractor uses the same format
1771
- const lookupKey = t.parsed.prefix
1772
- ? `${t.parsed.prefix}:${t.parsed.symbol}`
1773
- : t.parsed.symbol;
1774
- longTokensMetadata[t.symbol] = (_a = longBaseMetadata[lookupKey]) !== null && _a !== void 0 ? _a : null;
1775
- });
1776
- const shortTokensMetadata = {};
1777
- parsedShortTokens.forEach((t) => {
1778
- var _a;
1779
- const lookupKey = t.parsed.prefix
1780
- ? `${t.parsed.prefix}:${t.parsed.symbol}`
1781
- : t.parsed.symbol;
1782
- shortTokensMetadata[t.symbol] = (_a = shortBaseMetadata[lookupKey]) !== null && _a !== void 0 ? _a : null;
1783
- });
1784
1546
  // Determine loading state
1785
1547
  const allTokens = [...longTokens, ...shortTokens];
1786
1548
  const isLoading = (() => {
@@ -1795,13 +1557,12 @@ const useTokenSelectionMetadataStore = create((set) => ({
1795
1557
  return allTokens.some((token) => !allMetadata[token.symbol]);
1796
1558
  })();
1797
1559
  // Open interest and volume (from market data for matching asset basket)
1798
- // Use base symbols (without prefix) for matching against market data
1799
1560
  const { openInterest, volume } = (() => {
1800
1561
  const empty = { openInterest: "0", volume: "0" };
1801
1562
  if (!(marketData === null || marketData === void 0 ? void 0 : marketData.active) || (!longTokens.length && !shortTokens.length))
1802
1563
  return empty;
1803
- const selectedLong = longBaseSymbols.slice().sort();
1804
- const selectedShort = shortBaseSymbols.slice().sort();
1564
+ const selectedLong = longSymbols.slice().sort();
1565
+ const selectedShort = shortSymbols.slice().sort();
1805
1566
  const match = marketData.active.find((item) => {
1806
1567
  const longs = [...item.longAssets].sort();
1807
1568
  const shorts = [...item.shortAssets].sort();
@@ -1894,27 +1655,18 @@ const useTokenSelectionMetadataStore = create((set) => ({
1894
1655
  return totalFunding;
1895
1656
  })();
1896
1657
  // Max leverage (maximum across all tokens)
1897
- // Use tokens with their market prefixes for proper lookup in perpMetaAssets
1898
1658
  const maxLeverage = (() => {
1899
1659
  if (!perpMetaAssets)
1900
1660
  return 0;
1901
- const allTokensForLookup = [
1902
- ...longTokensForLookup,
1903
- ...shortTokensForLookup,
1904
- ];
1905
- if (allTokensForLookup.length === 0)
1661
+ const allSymbols = [...longSymbols, ...shortSymbols];
1662
+ if (allSymbols.length === 0)
1906
1663
  return 0;
1907
1664
  let maxLev = 0;
1908
- allTokensForLookup.forEach(({ symbol, marketPrefix }) => {
1909
- // Match by both name AND marketPrefix for HIP3 assets
1910
- const tokenUniverse = perpMetaAssets.find((u) => u.name === symbol &&
1911
- (marketPrefix
1912
- ? u.marketPrefix === marketPrefix
1913
- : !u.marketPrefix));
1914
- // Fallback to just matching by name if no exact match
1915
- const fallbackUniverse = tokenUniverse || perpMetaAssets.find((u) => u.name === symbol);
1916
- if (fallbackUniverse === null || fallbackUniverse === void 0 ? void 0 : fallbackUniverse.maxLeverage)
1917
- maxLev = Math.max(maxLev, fallbackUniverse.maxLeverage);
1665
+ allSymbols.forEach((symbol) => {
1666
+ const tokenUniverse = perpMetaAssets.find((u) => u.name === symbol);
1667
+ if (tokenUniverse === null || tokenUniverse === void 0 ? void 0 : tokenUniverse.maxLeverage) {
1668
+ maxLev = Math.max(maxLev, tokenUniverse.maxLeverage);
1669
+ }
1918
1670
  });
1919
1671
  return maxLev;
1920
1672
  })();
@@ -1968,9 +1720,7 @@ const useTokenSelectionMetadata = () => {
1968
1720
  throw new Error('useTokenSelection must be used within PearHyperliquidProvider');
1969
1721
  }
1970
1722
  const perpMetaAssets = useHyperliquidData((state) => state.perpMetaAssets);
1971
- const finalAssetContexts = useHyperliquidData((state) => state.finalAssetContexts);
1972
- const allMids = useHyperliquidData((state) => state.allMids);
1973
- const activeAssetData = useHyperliquidData((state) => state.activeAssetData);
1723
+ const tokenMetadata = useHyperliquidData((state) => state.tokenMetadata);
1974
1724
  const marketData = useMarketData((state) => state.marketData);
1975
1725
  const { longTokens, shortTokens } = useUserSelection$1();
1976
1726
  const { isLoading, isPriceDataReady, longTokensMetadata, shortTokensMetadata, weightedRatio, weightedRatio24h, priceRatio, priceRatio24h, openInterest, volume, sumNetFunding, maxLeverage, minMargin, leverageMatched, recompute, } = useTokenSelectionMetadataStore();
@@ -1978,16 +1728,14 @@ const useTokenSelectionMetadata = () => {
1978
1728
  useEffect(() => {
1979
1729
  recompute({
1980
1730
  perpMetaAssets,
1981
- finalAssetContexts,
1982
- allMids,
1983
- activeAssetData: activeAssetData || null,
1731
+ tokenMetadata,
1984
1732
  marketData: marketData || null,
1985
1733
  longTokens,
1986
1734
  shortTokens,
1987
1735
  });
1988
1736
  // We want to recompute when token lists or upstream data change
1989
1737
  // eslint-disable-next-line react-hooks/exhaustive-deps
1990
- }, [perpMetaAssets, finalAssetContexts, allMids, activeAssetData, JSON.stringify(longTokens), JSON.stringify(shortTokens)]);
1738
+ }, [perpMetaAssets, tokenMetadata, JSON.stringify(longTokens), JSON.stringify(shortTokens)]);
1991
1739
  return {
1992
1740
  // Loading states
1993
1741
  isLoading,
@@ -6114,10 +5862,9 @@ function addAuthInterceptors(params) {
6114
5862
  /**
6115
5863
  * Fetch historical candle data from HyperLiquid API
6116
5864
  */
6117
- const fetchHistoricalCandles = async (coin, startTime, endTime, interval, hip3Assets) => {
6118
- const backendCoin = toBackendSymbol(coin, hip3Assets);
5865
+ const fetchHistoricalCandles = async (coin, startTime, endTime, interval) => {
6119
5866
  const request = {
6120
- req: { coin: backendCoin, startTime, endTime, interval },
5867
+ req: { coin, startTime, endTime, interval },
6121
5868
  type: 'candleSnapshot',
6122
5869
  };
6123
5870
  try {
@@ -6194,6 +5941,26 @@ const fetchExtraAgents = async (user) => {
6194
5941
  throw toApiError(error);
6195
5942
  }
6196
5943
  };
5944
+ /**
5945
+ * Fetch perp dexes from HyperLiquid API
5946
+ * Endpoint: https://api.hyperliquid.xyz/info
5947
+ * Payload: { "type": "perpDexs" }
5948
+ * Returns array where index 0 is null (HYPERLIQUID), index 1+ are named DEXes
5949
+ */
5950
+ const fetchPerpDexs = async () => {
5951
+ const request = { type: 'perpDexs' };
5952
+ try {
5953
+ const response = await axios$1.post('https://api.hyperliquid.xyz/info', request, { headers: { 'Content-Type': 'application/json' } });
5954
+ return {
5955
+ data: response.data,
5956
+ status: response.status,
5957
+ headers: response.headers,
5958
+ };
5959
+ }
5960
+ catch (error) {
5961
+ throw toApiError(error);
5962
+ }
5963
+ };
6197
5964
 
6198
5965
  const useHistoricalPriceData = () => {
6199
5966
  const context = useContext(PearHyperliquidContext);
@@ -6274,10 +6041,9 @@ const useHistoricalPriceData = () => {
6274
6041
  setTokenLoading(token.symbol, true);
6275
6042
  });
6276
6043
  try {
6277
- const hip3Assets = useHyperliquidData.getState().hip3Assets;
6278
6044
  const fetchPromises = tokensToFetch.map(async (token) => {
6279
6045
  try {
6280
- const response = await fetchHistoricalCandles(token.symbol, startTime, endTime, interval, hip3Assets);
6046
+ const response = await fetchHistoricalCandles(token.symbol, startTime, endTime, interval);
6281
6047
  addHistoricalPriceData(token.symbol, interval, response.data, { start: startTime, end: endTime });
6282
6048
  return { symbol: token.symbol, candles: response.data, success: true };
6283
6049
  }
@@ -6756,7 +6522,6 @@ const usePerformanceOverlays = () => {
6756
6522
  overlays.forEach(overlay => {
6757
6523
  symbols.push(overlay.symbol);
6758
6524
  });
6759
- console.log("final symbols", symbols);
6760
6525
  return symbols;
6761
6526
  }, [overlays]);
6762
6527
  return {
@@ -6825,24 +6590,14 @@ function useAgentWallet() {
6825
6590
  * @throws MinimumPositionSizeError if any asset has less than $11 USD value
6826
6591
  * @throws MaxAssetsPerLegError if any leg exceeds the maximum allowed assets (15)
6827
6592
  */
6828
- async function createPosition(baseUrl, payload, hip3Assets) {
6593
+ async function createPosition(baseUrl, payload) {
6829
6594
  // Validate maximum assets per leg before creating position
6830
6595
  validateMaxAssetsPerLeg(payload.longAssets, payload.shortAssets);
6831
6596
  // Validate minimum asset size before creating position
6832
6597
  validateMinimumAssetSize(payload.usdValue, payload.longAssets, payload.shortAssets);
6833
6598
  const url = joinUrl(baseUrl, "/positions");
6834
- // Translate display symbols to backend format
6835
- const mapAssets = (arr) => arr === null || arr === void 0 ? void 0 : arr.map((a) => ({ ...a, asset: toBackendSymbol(a.asset, hip3Assets) }));
6836
- const translatedPayload = {
6837
- ...payload,
6838
- longAssets: mapAssets(payload.longAssets),
6839
- shortAssets: mapAssets(payload.shortAssets),
6840
- assetName: payload.assetName
6841
- ? toBackendSymbol(payload.assetName, hip3Assets)
6842
- : undefined,
6843
- };
6844
6599
  try {
6845
- const resp = await apiClient.post(url, translatedPayload, {
6600
+ const resp = await apiClient.post(url, payload, {
6846
6601
  headers: {
6847
6602
  "Content-Type": "application/json",
6848
6603
  },
@@ -6934,15 +6689,10 @@ async function adjustPosition(baseUrl, positionId, payload) {
6934
6689
  throw toApiError(error);
6935
6690
  }
6936
6691
  }
6937
- async function adjustAdvancePosition(baseUrl, positionId, payload, hip3Assets) {
6692
+ async function adjustAdvancePosition(baseUrl, positionId, payload) {
6938
6693
  const url = joinUrl(baseUrl, `/positions/${positionId}/adjust-advance`);
6939
- const mapAssets = (arr) => arr === null || arr === void 0 ? void 0 : arr.map((a) => ({ ...a, asset: toBackendSymbol(a.asset, hip3Assets) }));
6940
- const translatedPayload = (payload || []).map((item) => ({
6941
- longAssets: mapAssets(item.longAssets),
6942
- shortAssets: mapAssets(item.shortAssets),
6943
- }));
6944
6694
  try {
6945
- const resp = await apiClient.post(url, translatedPayload, {
6695
+ const resp = await apiClient.post(url, payload, {
6946
6696
  headers: {
6947
6697
  "Content-Type": "application/json",
6948
6698
  },
@@ -7002,7 +6752,7 @@ async function updateLeverage(baseUrl, positionId, payload) {
7002
6752
  }
7003
6753
  }
7004
6754
 
7005
- const calculatePositionAsset = (asset, currentPrice, totalInitialPositionSize, leverage, isLong = true) => {
6755
+ const calculatePositionAsset = (asset, currentPrice, totalInitialPositionSize, leverage, metadata, isLong = true) => {
7006
6756
  var _a;
7007
6757
  const entryNotional = asset.entryPrice * asset.size;
7008
6758
  const currentNotional = currentPrice * asset.size;
@@ -7021,13 +6771,12 @@ const calculatePositionAsset = (asset, currentPrice, totalInitialPositionSize, l
7021
6771
  entryPositionValue: entryNotional,
7022
6772
  initialWeight: totalInitialPositionSize > 0 ? entryNotional / totalInitialPositionSize : 0,
7023
6773
  fundingPaid: (_a = asset.fundingPaid) !== null && _a !== void 0 ? _a : 0,
7024
- // Preserve market metadata from raw asset (if provided by backend)
7025
- marketPrefix: asset.marketPrefix,
7026
- collateralToken: asset.collateralToken,
6774
+ metadata,
7027
6775
  };
7028
6776
  };
7029
- const buildPositionValue = (rawPositions, clearinghouseState, allMids) => {
6777
+ const buildPositionValue = (rawPositions, clearinghouseState, getAssetByName) => {
7030
6778
  return rawPositions.map((position) => {
6779
+ var _a, _b, _c, _d, _e, _f, _g, _h;
7031
6780
  let mappedPosition = {
7032
6781
  positionId: position.positionId,
7033
6782
  address: position.address,
@@ -7045,11 +6794,12 @@ const buildPositionValue = (rawPositions, clearinghouseState, allMids) => {
7045
6794
  const totalInitialPositionSize = position.longAssets.reduce((acc, asset) => acc + asset.entryPrice * asset.size, 0) +
7046
6795
  position.shortAssets.reduce((acc, asset) => acc + asset.entryPrice * asset.size, 0);
7047
6796
  mappedPosition.longAssets = position.longAssets.map((longAsset) => {
7048
- var _a, _b, _c;
7049
- const currentPrice = parseFloat(allMids.mids[longAsset.coin]);
7050
- const assetState = (_a = clearinghouseState.assetPositions.find((ap) => toDisplaySymbol(ap.position.coin) === longAsset.coin)) === null || _a === void 0 ? void 0 : _a.position;
7051
- 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;
7052
- const mappedPositionAssets = calculatePositionAsset(longAsset, currentPrice, totalInitialPositionSize, leverage, true);
6797
+ var _a, _b, _c, _d;
6798
+ const metadata = getAssetByName(longAsset.coin);
6799
+ const currentPrice = (_a = metadata === null || metadata === void 0 ? void 0 : metadata.currentPrice) !== null && _a !== void 0 ? _a : 0;
6800
+ const assetState = (_b = clearinghouseState.assetPositions.find((ap) => ap.position.coin === longAsset.coin)) === null || _b === void 0 ? void 0 : _b.position;
6801
+ const leverage = (_d = (_c = assetState === null || assetState === void 0 ? void 0 : assetState.leverage) === null || _c === void 0 ? void 0 : _c.value) !== null && _d !== void 0 ? _d : longAsset.leverage;
6802
+ const mappedPositionAssets = calculatePositionAsset(longAsset, currentPrice, totalInitialPositionSize, leverage, metadata, true);
7053
6803
  mappedPosition.entryPositionValue +=
7054
6804
  mappedPositionAssets.entryPositionValue;
7055
6805
  mappedPosition.unrealizedPnl += mappedPositionAssets.unrealizedPnl;
@@ -7060,11 +6810,12 @@ const buildPositionValue = (rawPositions, clearinghouseState, allMids) => {
7060
6810
  return mappedPositionAssets;
7061
6811
  });
7062
6812
  mappedPosition.shortAssets = position.shortAssets.map((shortAsset) => {
7063
- var _a, _b, _c;
7064
- const currentPrice = parseFloat(allMids.mids[shortAsset.coin]);
7065
- const assetState = (_a = clearinghouseState.assetPositions.find((ap) => toDisplaySymbol(ap.position.coin) === shortAsset.coin)) === null || _a === void 0 ? void 0 : _a.position;
7066
- 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;
7067
- const mappedPositionAssets = calculatePositionAsset(shortAsset, currentPrice, totalInitialPositionSize, leverage, false);
6813
+ var _a, _b, _c, _d;
6814
+ const metadata = getAssetByName(shortAsset.coin);
6815
+ const currentPrice = (_a = metadata === null || metadata === void 0 ? void 0 : metadata.currentPrice) !== null && _a !== void 0 ? _a : 0;
6816
+ const assetState = (_b = clearinghouseState.assetPositions.find((ap) => ap.position.coin === shortAsset.coin)) === null || _b === void 0 ? void 0 : _b.position;
6817
+ const leverage = (_d = (_c = assetState === null || assetState === void 0 ? void 0 : assetState.leverage) === null || _c === void 0 ? void 0 : _c.value) !== null && _d !== void 0 ? _d : shortAsset.leverage;
6818
+ const mappedPositionAssets = calculatePositionAsset(shortAsset, currentPrice, totalInitialPositionSize, leverage, metadata, false);
7068
6819
  mappedPosition.entryPositionValue +=
7069
6820
  mappedPositionAssets.entryPositionValue;
7070
6821
  mappedPosition.unrealizedPnl += mappedPositionAssets.unrealizedPnl;
@@ -7079,8 +6830,8 @@ const buildPositionValue = (rawPositions, clearinghouseState, allMids) => {
7079
6830
  if (position.longAssets.length === 1 && position.shortAssets.length === 1) {
7080
6831
  const long = position.longAssets[0];
7081
6832
  const short = position.shortAssets[0];
7082
- const longMark = parseFloat(allMids.mids[long.coin]);
7083
- const shortMark = parseFloat(allMids.mids[short.coin]);
6833
+ const longMark = (_b = (_a = getAssetByName(long.coin)) === null || _a === void 0 ? void 0 : _a.currentPrice) !== null && _b !== void 0 ? _b : 0;
6834
+ const shortMark = (_d = (_c = getAssetByName(short.coin)) === null || _c === void 0 ? void 0 : _c.currentPrice) !== null && _d !== void 0 ? _d : 0;
7084
6835
  if (long.size > 0 && short.size > 0) {
7085
6836
  mappedPosition.entryPriceRatio = long.entryPrice / short.entryPrice;
7086
6837
  mappedPosition.markPriceRatio = longMark / shortMark;
@@ -7096,13 +6847,13 @@ const buildPositionValue = (rawPositions, clearinghouseState, allMids) => {
7096
6847
  }
7097
6848
  if (position.longAssets.length === 1 && position.shortAssets.length === 0) {
7098
6849
  const long = position.longAssets[0];
7099
- const longMark = parseFloat(allMids.mids[long.coin]);
6850
+ const longMark = (_f = (_e = getAssetByName(long.coin)) === null || _e === void 0 ? void 0 : _e.currentPrice) !== null && _f !== void 0 ? _f : 0;
7100
6851
  mappedPosition.entryPriceRatio = long.entryPrice;
7101
6852
  mappedPosition.markPriceRatio = longMark;
7102
6853
  }
7103
6854
  if (position.longAssets.length === 0 && position.shortAssets.length === 1) {
7104
6855
  const short = position.shortAssets[0];
7105
- const shortMark = parseFloat(allMids.mids[short.coin]);
6856
+ const shortMark = (_h = (_g = getAssetByName(short.coin)) === null || _g === void 0 ? void 0 : _g.currentPrice) !== null && _h !== void 0 ? _h : 0;
7106
6857
  mappedPosition.entryPriceRatio = short.entryPrice;
7107
6858
  mappedPosition.markPriceRatio = shortMark;
7108
6859
  }
@@ -7112,93 +6863,14 @@ const buildPositionValue = (rawPositions, clearinghouseState, allMids) => {
7112
6863
  });
7113
6864
  };
7114
6865
 
7115
- function findAssetMeta$3(coinName, perpMetaAssets, knownPrefix, desiredCollateral) {
7116
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
7117
- if (!perpMetaAssets) {
7118
- return { collateralToken: 'USDC', marketPrefix: null };
7119
- }
7120
- if (desiredCollateral) {
7121
- const collateralMatch = perpMetaAssets.find((a) => a.name === coinName && a.collateralToken === desiredCollateral);
7122
- if (collateralMatch) {
7123
- return {
7124
- collateralToken: (_a = collateralMatch.collateralToken) !== null && _a !== void 0 ? _a : 'USDC',
7125
- marketPrefix: (_b = collateralMatch.marketPrefix) !== null && _b !== void 0 ? _b : null,
7126
- };
7127
- }
7128
- }
7129
- if (coinName.includes(':')) {
7130
- const [prefix, symbol] = coinName.split(':');
7131
- const exactMatch = perpMetaAssets.find((a) => {
7132
- var _a;
7133
- return a.name === symbol &&
7134
- ((_a = a.marketPrefix) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === prefix.toLowerCase();
7135
- });
7136
- if (exactMatch) {
7137
- return {
7138
- collateralToken: (_c = exactMatch.collateralToken) !== null && _c !== void 0 ? _c : 'USDC',
7139
- marketPrefix: (_d = exactMatch.marketPrefix) !== null && _d !== void 0 ? _d : null,
7140
- };
7141
- }
7142
- }
7143
- if (knownPrefix) {
7144
- const exactMatch = perpMetaAssets.find((a) => {
7145
- var _a;
7146
- return a.name === coinName &&
7147
- ((_a = a.marketPrefix) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === knownPrefix.toLowerCase();
7148
- });
7149
- if (exactMatch) {
7150
- return {
7151
- collateralToken: (_e = exactMatch.collateralToken) !== null && _e !== void 0 ? _e : 'USDC',
7152
- marketPrefix: (_f = exactMatch.marketPrefix) !== null && _f !== void 0 ? _f : null,
7153
- };
7154
- }
7155
- }
7156
- const regularAsset = perpMetaAssets.find((a) => a.name === coinName && !a.marketPrefix);
7157
- if (regularAsset) {
7158
- return {
7159
- collateralToken: (_g = regularAsset.collateralToken) !== null && _g !== void 0 ? _g : 'USDC',
7160
- marketPrefix: null,
7161
- };
7162
- }
7163
- const hip3Asset = perpMetaAssets.find((a) => a.name === coinName && a.marketPrefix);
7164
- if (hip3Asset) {
7165
- return {
7166
- collateralToken: (_h = hip3Asset.collateralToken) !== null && _h !== void 0 ? _h : 'USDC',
7167
- marketPrefix: (_j = hip3Asset.marketPrefix) !== null && _j !== void 0 ? _j : null,
7168
- };
7169
- }
7170
- return { collateralToken: 'USDC', marketPrefix: null };
7171
- }
7172
- function enrichPositionAssets(assets, perpMetaAssets) {
7173
- return assets.map((asset) => {
7174
- var _a;
7175
- if (asset.marketPrefix && asset.collateralToken) {
7176
- return asset;
7177
- }
7178
- const meta = findAssetMeta$3(asset.coin, perpMetaAssets, asset.marketPrefix, asset.collateralToken);
7179
- return {
7180
- ...asset,
7181
- marketPrefix: asset.marketPrefix || meta.marketPrefix,
7182
- collateralToken: (_a = asset.collateralToken) !== null && _a !== void 0 ? _a : meta.collateralToken,
7183
- };
7184
- });
7185
- }
7186
- function enrichPositions(positions, perpMetaAssets) {
7187
- return positions.map((position) => ({
7188
- ...position,
7189
- longAssets: enrichPositionAssets(position.longAssets, perpMetaAssets),
7190
- shortAssets: enrichPositionAssets(position.shortAssets, perpMetaAssets),
7191
- }));
7192
- }
7193
6866
  function usePosition() {
7194
6867
  const context = useContext(PearHyperliquidContext);
7195
6868
  if (!context) {
7196
6869
  throw new Error('usePosition must be used within a PearHyperliquidProvider');
7197
6870
  }
7198
6871
  const { apiBaseUrl, isConnected } = context;
7199
- const hip3Assets = useHyperliquidData((s) => s.hip3Assets);
7200
6872
  const createPosition$1 = async (payload) => {
7201
- return createPosition(apiBaseUrl, payload, hip3Assets);
6873
+ return createPosition(apiBaseUrl, payload);
7202
6874
  };
7203
6875
  const updateRiskParameters$1 = async (positionId, payload) => {
7204
6876
  return updateRiskParameters(apiBaseUrl, positionId, payload);
@@ -7213,7 +6885,7 @@ function usePosition() {
7213
6885
  return adjustPosition(apiBaseUrl, positionId, payload);
7214
6886
  };
7215
6887
  const adjustAdvancePosition$1 = async (positionId, payload) => {
7216
- return adjustAdvancePosition(apiBaseUrl, positionId, payload, hip3Assets);
6888
+ return adjustAdvancePosition(apiBaseUrl, positionId, payload);
7217
6889
  };
7218
6890
  const updateLeverage$1 = async (positionId, leverage) => {
7219
6891
  return updateLeverage(apiBaseUrl, positionId, { leverage });
@@ -7221,22 +6893,18 @@ function usePosition() {
7221
6893
  // Open positions using WS data, with derived values
7222
6894
  const userOpenPositions = useUserData((state) => state.rawOpenPositions);
7223
6895
  const aggregatedClearingHouseState = useHyperliquidData((state) => state.aggregatedClearingHouseState);
7224
- const allMids = useHyperliquidData((state) => state.allMids);
7225
- const allPerpMetaAssets = useHyperliquidData((state) => state.allPerpMetaAssets);
6896
+ const tokenMetadata = useHyperliquidData((state) => state.tokenMetadata);
6897
+ const { getAssetByName } = useMarket();
7226
6898
  const isLoading = useMemo(() => {
7227
6899
  return userOpenPositions === null && isConnected;
7228
6900
  }, [userOpenPositions, isConnected]);
7229
6901
  const openPositions = useMemo(() => {
7230
- if (!userOpenPositions || !aggregatedClearingHouseState || !allMids)
6902
+ if (!userOpenPositions ||
6903
+ !aggregatedClearingHouseState ||
6904
+ Object.keys(tokenMetadata).length === 0)
7231
6905
  return null;
7232
- const positions = buildPositionValue(userOpenPositions, aggregatedClearingHouseState, allMids);
7233
- return enrichPositions(positions, allPerpMetaAssets);
7234
- }, [
7235
- userOpenPositions,
7236
- aggregatedClearingHouseState,
7237
- allMids,
7238
- allPerpMetaAssets,
7239
- ]);
6906
+ return buildPositionValue(userOpenPositions, aggregatedClearingHouseState, getAssetByName);
6907
+ }, [userOpenPositions, aggregatedClearingHouseState, tokenMetadata, getAssetByName]);
7240
6908
  return {
7241
6909
  createPosition: createPosition$1,
7242
6910
  updateRiskParameters: updateRiskParameters$1,
@@ -7319,98 +6987,14 @@ async function executeSpotOrder(baseUrl, payload) {
7319
6987
  }
7320
6988
  }
7321
6989
 
7322
- function findAssetMeta$2(assetName, perpMetaAssets, knownPrefix, desiredCollateral) {
7323
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
7324
- if (!perpMetaAssets) {
7325
- return { collateralToken: 'USDC', marketPrefix: null };
7326
- }
7327
- if (desiredCollateral) {
7328
- const collateralMatch = perpMetaAssets.find((a) => a.name === assetName && a.collateralToken === desiredCollateral);
7329
- if (collateralMatch) {
7330
- return {
7331
- collateralToken: (_a = collateralMatch.collateralToken) !== null && _a !== void 0 ? _a : 'USDC',
7332
- marketPrefix: (_b = collateralMatch.marketPrefix) !== null && _b !== void 0 ? _b : null,
7333
- };
7334
- }
7335
- }
7336
- if (assetName.includes(':')) {
7337
- const [prefix, symbol] = assetName.split(':');
7338
- const exactMatch = perpMetaAssets.find((a) => {
7339
- var _a;
7340
- return a.name === symbol &&
7341
- ((_a = a.marketPrefix) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === prefix.toLowerCase();
7342
- });
7343
- if (exactMatch) {
7344
- return {
7345
- collateralToken: (_c = exactMatch.collateralToken) !== null && _c !== void 0 ? _c : 'USDC',
7346
- marketPrefix: (_d = exactMatch.marketPrefix) !== null && _d !== void 0 ? _d : null,
7347
- };
7348
- }
7349
- }
7350
- if (knownPrefix) {
7351
- const exactMatch = perpMetaAssets.find((a) => {
7352
- var _a;
7353
- return a.name === assetName &&
7354
- ((_a = a.marketPrefix) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === knownPrefix.toLowerCase();
7355
- });
7356
- if (exactMatch) {
7357
- return {
7358
- collateralToken: (_e = exactMatch.collateralToken) !== null && _e !== void 0 ? _e : 'USDC',
7359
- marketPrefix: (_f = exactMatch.marketPrefix) !== null && _f !== void 0 ? _f : null,
7360
- };
7361
- }
7362
- }
7363
- const regularAsset = perpMetaAssets.find((a) => a.name === assetName && !a.marketPrefix);
7364
- if (regularAsset) {
7365
- return {
7366
- collateralToken: (_g = regularAsset.collateralToken) !== null && _g !== void 0 ? _g : 'USDC',
7367
- marketPrefix: null,
7368
- };
7369
- }
7370
- const hip3Assets = perpMetaAssets.filter((a) => a.name === assetName && a.marketPrefix);
7371
- if (hip3Assets.length > 0) {
7372
- if (desiredCollateral) {
7373
- const collateralMatch = hip3Assets.find((a) => a.collateralToken === desiredCollateral);
7374
- if (collateralMatch) {
7375
- return {
7376
- collateralToken: (_h = collateralMatch.collateralToken) !== null && _h !== void 0 ? _h : 'USDC',
7377
- marketPrefix: (_j = collateralMatch.marketPrefix) !== null && _j !== void 0 ? _j : null,
7378
- };
7379
- }
7380
- }
7381
- const usdHMatch = hip3Assets.find((a) => a.collateralToken === 'USDH');
7382
- const chosen = usdHMatch !== null && usdHMatch !== void 0 ? usdHMatch : hip3Assets[0];
7383
- return {
7384
- collateralToken: (_k = chosen.collateralToken) !== null && _k !== void 0 ? _k : 'USDC',
7385
- marketPrefix: (_l = chosen.marketPrefix) !== null && _l !== void 0 ? _l : null,
7386
- };
7387
- }
7388
- return { collateralToken: 'USDC', marketPrefix: null };
7389
- }
7390
- function enrichOrderAssets$1(assets, perpMetaAssets) {
7391
- if (!assets)
7392
- return [];
7393
- return assets.map((asset) => {
7394
- var _a;
7395
- if (asset.marketPrefix && asset.collateralToken) {
7396
- return asset;
7397
- }
7398
- const meta = findAssetMeta$2(asset.asset, perpMetaAssets, asset.marketPrefix, asset.collateralToken);
7399
- return {
7400
- ...asset,
7401
- marketPrefix: asset.marketPrefix || meta.marketPrefix,
7402
- collateralToken: (_a = asset.collateralToken) !== null && _a !== void 0 ? _a : meta.collateralToken,
7403
- };
7404
- });
7405
- }
7406
6990
  function useOrders() {
7407
6991
  const context = useContext(PearHyperliquidContext);
7408
6992
  if (!context)
7409
6993
  throw new Error('useOrders must be used within a PearHyperliquidProvider');
7410
6994
  const { apiBaseUrl } = context;
7411
6995
  const openOrders = useUserData((state) => state.openOrders);
7412
- const allPerpMetaAssets = useHyperliquidData((state) => state.allPerpMetaAssets);
7413
6996
  const isLoading = useMemo(() => openOrders === null && context.isConnected, [openOrders, context.isConnected]);
6997
+ const { getAssetByName } = useMarket();
7414
6998
  const { openPositions } = usePosition();
7415
6999
  const positionsById = useMemo(() => {
7416
7000
  const map = new Map();
@@ -7423,22 +7007,26 @@ function useOrders() {
7423
7007
  const enrichedOpenOrders = useMemo(() => {
7424
7008
  if (!openOrders)
7425
7009
  return null;
7010
+ const mapOrderAssets = (assets) => assets.map((asset) => ({
7011
+ ...asset,
7012
+ metadata: getAssetByName(asset.asset),
7013
+ }));
7426
7014
  return openOrders.map((ord) => {
7427
- var _a, _b, _c, _d, _e;
7015
+ var _a, _b, _c, _d, _e, _f, _g;
7428
7016
  const isTpSl = ord.orderType === 'TP' || ord.orderType === 'SL';
7429
7017
  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;
7430
7018
  const pos = positionsById.get((_e = ord.positionId) !== null && _e !== void 0 ? _e : '');
7431
7019
  let enrichedOrd = {
7432
7020
  ...ord,
7433
- longAssets: enrichOrderAssets$1(ord.longAssets, allPerpMetaAssets),
7434
- shortAssets: enrichOrderAssets$1(ord.shortAssets, allPerpMetaAssets),
7021
+ longAssets: mapOrderAssets((_f = ord.longAssets) !== null && _f !== void 0 ? _f : []),
7022
+ shortAssets: mapOrderAssets((_g = ord.shortAssets) !== null && _g !== void 0 ? _g : []),
7435
7023
  };
7024
+ // For TP/SL orders without assets, derive them from the position
7436
7025
  if (isTpSl && !hasAssets && pos) {
7437
7026
  const mapAssets = (arr) => arr.map((a) => ({
7438
7027
  asset: a.coin,
7439
7028
  weight: a.initialWeight,
7440
- marketPrefix: a.marketPrefix,
7441
- collateralToken: a.collateralToken,
7029
+ metadata: getAssetByName(a.coin),
7442
7030
  }));
7443
7031
  enrichedOrd = {
7444
7032
  ...enrichedOrd,
@@ -7448,7 +7036,7 @@ function useOrders() {
7448
7036
  }
7449
7037
  return enrichedOrd;
7450
7038
  });
7451
- }, [openOrders, positionsById, allPerpMetaAssets]);
7039
+ }, [openOrders, positionsById, getAssetByName]);
7452
7040
  const adjustOrder$1 = async (orderId, payload) => {
7453
7041
  return adjustOrder(apiBaseUrl, orderId, payload);
7454
7042
  };
@@ -7506,108 +7094,27 @@ function useSpotOrder() {
7506
7094
  };
7507
7095
  }
7508
7096
 
7509
- function findAssetMeta$1(assetName, perpMetaAssets, knownPrefix, desiredCollateral) {
7510
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
7511
- if (!perpMetaAssets) {
7512
- return { collateralToken: 'USDC', marketPrefix: null };
7513
- }
7514
- if (desiredCollateral) {
7515
- const collateralMatch = perpMetaAssets.find((a) => a.name === assetName && a.collateralToken === desiredCollateral);
7516
- if (collateralMatch) {
7517
- return {
7518
- collateralToken: (_a = collateralMatch.collateralToken) !== null && _a !== void 0 ? _a : 'USDC',
7519
- marketPrefix: (_b = collateralMatch.marketPrefix) !== null && _b !== void 0 ? _b : null,
7520
- };
7521
- }
7522
- }
7523
- if (assetName.includes(':')) {
7524
- const [prefix, symbol] = assetName.split(':');
7525
- const exactMatch = perpMetaAssets.find((a) => {
7526
- var _a;
7527
- return a.name === symbol &&
7528
- ((_a = a.marketPrefix) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === prefix.toLowerCase();
7529
- });
7530
- if (exactMatch) {
7531
- return {
7532
- collateralToken: (_c = exactMatch.collateralToken) !== null && _c !== void 0 ? _c : 'USDC',
7533
- marketPrefix: (_d = exactMatch.marketPrefix) !== null && _d !== void 0 ? _d : null,
7534
- };
7535
- }
7536
- }
7537
- if (knownPrefix) {
7538
- const exactMatch = perpMetaAssets.find((a) => {
7539
- var _a;
7540
- return a.name === assetName &&
7541
- ((_a = a.marketPrefix) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === knownPrefix.toLowerCase();
7542
- });
7543
- if (exactMatch) {
7544
- return {
7545
- collateralToken: (_e = exactMatch.collateralToken) !== null && _e !== void 0 ? _e : 'USDC',
7546
- marketPrefix: (_f = exactMatch.marketPrefix) !== null && _f !== void 0 ? _f : null,
7547
- };
7548
- }
7549
- }
7550
- const regularAsset = perpMetaAssets.find((a) => a.name === assetName && !a.marketPrefix);
7551
- if (regularAsset) {
7552
- return {
7553
- collateralToken: (_g = regularAsset.collateralToken) !== null && _g !== void 0 ? _g : 'USDC',
7554
- marketPrefix: null,
7555
- };
7556
- }
7557
- const hip3Assets = perpMetaAssets.filter((a) => a.name === assetName && a.marketPrefix);
7558
- if (hip3Assets.length > 0) {
7559
- if (desiredCollateral) {
7560
- const collateralMatch = hip3Assets.find((a) => a.collateralToken === desiredCollateral);
7561
- if (collateralMatch) {
7562
- return {
7563
- collateralToken: (_h = collateralMatch.collateralToken) !== null && _h !== void 0 ? _h : 'USDC',
7564
- marketPrefix: (_j = collateralMatch.marketPrefix) !== null && _j !== void 0 ? _j : null,
7565
- };
7566
- }
7567
- }
7568
- const usdHMatch = hip3Assets.find((a) => a.collateralToken === 'USDH');
7569
- const chosen = usdHMatch !== null && usdHMatch !== void 0 ? usdHMatch : hip3Assets[0];
7570
- return {
7571
- collateralToken: (_k = chosen.collateralToken) !== null && _k !== void 0 ? _k : 'USDC',
7572
- marketPrefix: (_l = chosen.marketPrefix) !== null && _l !== void 0 ? _l : null,
7573
- };
7574
- }
7575
- return { collateralToken: 'USDC', marketPrefix: null };
7576
- }
7577
- function enrichOrderAssets(assets, perpMetaAssets) {
7578
- if (!assets)
7579
- return [];
7580
- return assets.map((asset) => {
7581
- var _a;
7582
- if (asset.marketPrefix && asset.collateralToken) {
7583
- return asset;
7584
- }
7585
- const meta = findAssetMeta$1(asset.asset, perpMetaAssets, asset.marketPrefix, asset.collateralToken);
7586
- return {
7587
- ...asset,
7588
- marketPrefix: asset.marketPrefix || meta.marketPrefix,
7589
- collateralToken: (_a = asset.collateralToken) !== null && _a !== void 0 ? _a : meta.collateralToken,
7590
- };
7591
- });
7592
- }
7593
- function enrichTwapOrders(orders, perpMetaAssets) {
7594
- return orders.map((order) => ({
7595
- ...order,
7596
- longAssets: enrichOrderAssets(order.longAssets, perpMetaAssets),
7597
- shortAssets: enrichOrderAssets(order.shortAssets, perpMetaAssets),
7598
- }));
7599
- }
7600
7097
  function useTwap() {
7601
7098
  const twapDetails = useUserData((state) => state.twapDetails);
7602
- const allPerpMetaAssets = useHyperliquidData((state) => state.allPerpMetaAssets);
7603
7099
  const context = useContext(PearHyperliquidContext);
7604
7100
  if (!context)
7605
7101
  throw new Error('useTwap must be used within a PearHyperliquidProvider');
7606
7102
  const { apiBaseUrl } = context;
7103
+ const { getAssetByName } = useMarket();
7607
7104
  const orders = useMemo(() => {
7608
- const rawOrders = twapDetails !== null && twapDetails !== void 0 ? twapDetails : [];
7609
- return enrichTwapOrders(rawOrders, allPerpMetaAssets);
7610
- }, [twapDetails, allPerpMetaAssets]);
7105
+ const mapAssets = (assets) => assets.map((asset) => ({
7106
+ ...asset,
7107
+ metadata: getAssetByName(asset.asset),
7108
+ }));
7109
+ return (twapDetails !== null && twapDetails !== void 0 ? twapDetails : []).map((order) => {
7110
+ var _a, _b;
7111
+ return ({
7112
+ ...order,
7113
+ longAssets: mapAssets((_a = order.longAssets) !== null && _a !== void 0 ? _a : []),
7114
+ shortAssets: mapAssets((_b = order.shortAssets) !== null && _b !== void 0 ? _b : []),
7115
+ });
7116
+ });
7117
+ }, [twapDetails, getAssetByName]);
7611
7118
  const cancelTwap$1 = async (orderId) => {
7612
7119
  return cancelTwap(apiBaseUrl, orderId);
7613
7120
  };
@@ -7690,62 +7197,19 @@ function useNotifications() {
7690
7197
  };
7691
7198
  }
7692
7199
 
7693
- // Helper to find asset metadata from perpMetaAssets
7694
- function findAssetMeta(assetName, perpMetaAssets) {
7695
- var _a, _b, _c, _d;
7696
- if (!perpMetaAssets) {
7697
- return { collateralToken: 'USDC', marketPrefix: null };
7698
- }
7699
- // Try exact match first (for prefixed assets like "xyz:TSLA")
7700
- const exactMatch = perpMetaAssets.find((a) => a.name === assetName);
7701
- if (exactMatch) {
7702
- return {
7703
- collateralToken: (_a = exactMatch.collateralToken) !== null && _a !== void 0 ? _a : 'USDC',
7704
- marketPrefix: (_b = exactMatch.marketPrefix) !== null && _b !== void 0 ? _b : null,
7705
- };
7706
- }
7707
- // Try matching by base symbol (for non-prefixed names in data)
7708
- const baseMatch = perpMetaAssets.find((a) => {
7709
- const baseName = a.name.includes(':') ? a.name.split(':')[1] : a.name;
7710
- return baseName === assetName;
7711
- });
7712
- if (baseMatch) {
7713
- return {
7714
- collateralToken: (_c = baseMatch.collateralToken) !== null && _c !== void 0 ? _c : 'USDC',
7715
- marketPrefix: (_d = baseMatch.marketPrefix) !== null && _d !== void 0 ? _d : null,
7716
- };
7717
- }
7718
- return { collateralToken: 'USDC', marketPrefix: null };
7719
- }
7720
- // Enrich a single asset with metadata
7721
- function enrichAsset(asset, perpMetaAssets) {
7722
- const meta = findAssetMeta(asset.asset, perpMetaAssets);
7723
- return {
7724
- ...asset,
7725
- collateralToken: meta.collateralToken,
7726
- marketPrefix: meta.marketPrefix,
7727
- };
7728
- }
7729
- // Enrich a basket item with collateral info
7730
- function enrichBasketItem(item, perpMetaAssets) {
7731
- const enrichedLongs = item.longAssets.map((a) => enrichAsset(a, perpMetaAssets));
7732
- const enrichedShorts = item.shortAssets.map((a) => enrichAsset(a, perpMetaAssets));
7733
- // Determine collateral type
7734
- const allAssets = [...enrichedLongs, ...enrichedShorts];
7735
- const hasUsdc = allAssets.some((a) => a.collateralToken === 'USDC');
7736
- const hasUsdh = allAssets.some((a) => a.collateralToken === 'USDH');
7737
- let collateralType = 'USDC';
7738
- if (hasUsdc && hasUsdh) {
7739
- collateralType = 'MIXED';
7740
- }
7741
- else if (hasUsdh) {
7742
- collateralType = 'USDH';
7743
- }
7200
+ // Convert a basket item to the expected type
7201
+ function enrichBasketItem(item) {
7202
+ const enrichedLongs = item.longAssets.map((a) => ({
7203
+ ...a,
7204
+ }));
7205
+ const enrichedShorts = item.shortAssets.map((a) => ({
7206
+ ...a,
7207
+ }));
7744
7208
  return {
7745
7209
  ...item,
7746
7210
  longAssets: enrichedLongs,
7747
7211
  shortAssets: enrichedShorts,
7748
- collateralType,
7212
+ collateralType: 'USDC', //TODO: change
7749
7213
  };
7750
7214
  }
7751
7215
  /**
@@ -7774,86 +7238,61 @@ function filterByCollateral(baskets, filter) {
7774
7238
  const useMarketDataPayload = () => {
7775
7239
  return useMarketData((s) => s.marketData);
7776
7240
  };
7777
- // Full payload for 'market-data-all' channel (raw from WS)
7778
- const useMarketDataAllPayload = () => {
7779
- return useMarketData((s) => s.marketDataAll);
7780
- };
7781
- // Access perpMetaAssets for enrichment
7782
- const usePerpMetaAssets = () => {
7783
- return useHyperliquidData((s) => s.perpMetaAssets);
7784
- };
7785
- // Active baskets (with collateral and market prefix info)
7241
+ // Active baskets
7786
7242
  const useActiveBaskets = (collateralFilter) => {
7787
7243
  const data = useMarketDataPayload();
7788
- const perpMetaAssets = usePerpMetaAssets();
7789
7244
  return useMemo(() => {
7790
7245
  if (!(data === null || data === void 0 ? void 0 : data.active))
7791
7246
  return [];
7792
- const enriched = data.active.map((item) => enrichBasketItem(item, perpMetaAssets));
7247
+ const enriched = data.active.map((item) => enrichBasketItem(item));
7793
7248
  return filterByCollateral(enriched, collateralFilter);
7794
- }, [data, perpMetaAssets, collateralFilter]);
7249
+ }, [data, collateralFilter]);
7795
7250
  };
7796
- // Top gainers (with collateral and market prefix info)
7251
+ // Top gainers
7797
7252
  const useTopGainers = (limit, collateralFilter) => {
7798
7253
  const data = useMarketDataPayload();
7799
- const perpMetaAssets = usePerpMetaAssets();
7800
7254
  return useMemo(() => {
7801
7255
  var _a;
7802
7256
  const list = (_a = data === null || data === void 0 ? void 0 : data.topGainers) !== null && _a !== void 0 ? _a : [];
7803
7257
  const limited = typeof limit === 'number' ? list.slice(0, Math.max(0, limit)) : list;
7804
- const enriched = limited.map((item) => enrichBasketItem(item, perpMetaAssets));
7258
+ const enriched = limited.map((item) => enrichBasketItem(item));
7805
7259
  return filterByCollateral(enriched, collateralFilter);
7806
- }, [data, perpMetaAssets, limit, collateralFilter]);
7260
+ }, [data, limit, collateralFilter]);
7807
7261
  };
7808
- // Top losers (with collateral and market prefix info)
7262
+ // Top losers
7809
7263
  const useTopLosers = (limit, collateralFilter) => {
7810
7264
  const data = useMarketDataPayload();
7811
- const perpMetaAssets = usePerpMetaAssets();
7812
7265
  return useMemo(() => {
7813
7266
  var _a;
7814
7267
  const list = (_a = data === null || data === void 0 ? void 0 : data.topLosers) !== null && _a !== void 0 ? _a : [];
7815
7268
  const limited = typeof limit === 'number' ? list.slice(0, Math.max(0, limit)) : list;
7816
- const enriched = limited.map((item) => enrichBasketItem(item, perpMetaAssets));
7269
+ const enriched = limited.map((item) => enrichBasketItem(item));
7817
7270
  return filterByCollateral(enriched, collateralFilter);
7818
- }, [data, perpMetaAssets, limit, collateralFilter]);
7271
+ }, [data, limit, collateralFilter]);
7819
7272
  };
7820
- // Highlighted baskets (with collateral and market prefix info)
7273
+ // Highlighted baskets
7821
7274
  const useHighlightedBaskets = (collateralFilter) => {
7822
7275
  const data = useMarketDataPayload();
7823
- const perpMetaAssets = usePerpMetaAssets();
7824
7276
  return useMemo(() => {
7825
7277
  if (!(data === null || data === void 0 ? void 0 : data.highlighted))
7826
7278
  return [];
7827
- const enriched = data.highlighted.map((item) => enrichBasketItem(item, perpMetaAssets));
7279
+ const enriched = data.highlighted.map((item) => enrichBasketItem(item));
7828
7280
  return filterByCollateral(enriched, collateralFilter);
7829
- }, [data, perpMetaAssets, collateralFilter]);
7281
+ }, [data, collateralFilter]);
7830
7282
  };
7831
- // Watchlist baskets (with collateral and market prefix info)
7283
+ // Watchlist baskets
7832
7284
  const useWatchlistBaskets = (collateralFilter) => {
7833
7285
  const data = useMarketDataPayload();
7834
- const perpMetaAssets = usePerpMetaAssets();
7835
7286
  return useMemo(() => {
7836
7287
  if (!(data === null || data === void 0 ? void 0 : data.watchlist))
7837
7288
  return [];
7838
- const enriched = data.watchlist.map((item) => enrichBasketItem(item, perpMetaAssets));
7839
- return filterByCollateral(enriched, collateralFilter);
7840
- }, [data, perpMetaAssets, collateralFilter]);
7841
- };
7842
- // All baskets (with collateral and market prefix info)
7843
- const useAllBaskets = (collateralFilter) => {
7844
- const dataAll = useMarketDataAllPayload();
7845
- const perpMetaAssets = usePerpMetaAssets();
7846
- return useMemo(() => {
7847
- if (!(dataAll === null || dataAll === void 0 ? void 0 : dataAll.all))
7848
- return [];
7849
- const enriched = dataAll.all.map((item) => enrichBasketItem(item, perpMetaAssets));
7289
+ const enriched = data.watchlist.map((item) => enrichBasketItem(item));
7850
7290
  return filterByCollateral(enriched, collateralFilter);
7851
- }, [dataAll, perpMetaAssets, collateralFilter]);
7291
+ }, [data, collateralFilter]);
7852
7292
  };
7853
7293
  // Find a basket by its exact asset composition (order-insensitive)
7854
7294
  const useFindBasket = (longs, shorts) => {
7855
7295
  const data = useMarketDataPayload();
7856
- const perpMetaAssets = usePerpMetaAssets();
7857
7296
  return useMemo(() => {
7858
7297
  if (!data)
7859
7298
  return undefined;
@@ -7871,18 +7310,17 @@ const useFindBasket = (longs, shorts) => {
7871
7310
  normalize(item.shortAssets) === sKey;
7872
7311
  const found = data.active.find(match) || data.highlighted.find(match);
7873
7312
  return found
7874
- ? enrichBasketItem(found, perpMetaAssets)
7313
+ ? enrichBasketItem(found)
7875
7314
  : undefined;
7876
- }, [data, longs, shorts, perpMetaAssets]);
7315
+ }, [data, longs, shorts]);
7877
7316
  };
7878
7317
 
7879
- async function toggleWatchlist(baseUrl, longAssets, shortAssets, hip3Assets) {
7318
+ async function toggleWatchlist(baseUrl, longAssets, shortAssets) {
7880
7319
  const url = joinUrl(baseUrl, '/watchlist');
7881
- const mapAssets = (arr) => arr.map((a) => ({ ...a, asset: toBackendSymbol(a.asset, hip3Assets) }));
7882
7320
  try {
7883
7321
  const response = await apiClient.post(url, {
7884
- longAssets: mapAssets(longAssets),
7885
- shortAssets: mapAssets(shortAssets),
7322
+ longAssets,
7323
+ shortAssets,
7886
7324
  }, { headers: { 'Content-Type': 'application/json' } });
7887
7325
  return {
7888
7326
  data: response.data,
@@ -7900,11 +7338,10 @@ function useWatchlist() {
7900
7338
  if (!context)
7901
7339
  throw new Error('useWatchlist must be used within a PearHyperliquidProvider');
7902
7340
  const { apiBaseUrl, isConnected } = context;
7903
- const hip3Assets = useHyperliquidData((s) => s.hip3Assets);
7904
7341
  const marketData = useMarketDataPayload();
7905
7342
  const isLoading = useMemo(() => !marketData && isConnected, [marketData, isConnected]);
7906
7343
  const toggle = async (longAssets, shortAssets) => {
7907
- const resp = await toggleWatchlist(apiBaseUrl, longAssets, shortAssets, hip3Assets);
7344
+ const resp = await toggleWatchlist(apiBaseUrl, longAssets, shortAssets);
7908
7345
  // Server will push updated market-data over WS; nothing to set here
7909
7346
  return resp;
7910
7347
  };
@@ -8162,7 +7599,6 @@ const useAllUserBalances = () => {
8162
7599
  const spotState = useUserData((state) => state.spotState);
8163
7600
  const aggregatedClearingHouseState = useHyperliquidData((state) => state.aggregatedClearingHouseState);
8164
7601
  const rawClearinghouseStates = useHyperliquidData((state) => state.rawClearinghouseStates);
8165
- const activeAssetData = useHyperliquidData((state) => state.activeAssetData);
8166
7602
  const { longTokensMetadata, shortTokensMetadata } = useTokenSelectionMetadata();
8167
7603
  return useMemo(() => {
8168
7604
  const isLoading = !spotState || !aggregatedClearingHouseState;
@@ -8185,39 +7621,50 @@ const useAllUserBalances = () => {
8185
7621
  }
8186
7622
  }
8187
7623
  }
7624
+ // Get available to trade from tokenMetadata for both USDC and USDH markets
7625
+ let availableToTradeUsdcFromAsset = 0;
8188
7626
  let availableToTradeUsdhFromAsset = 0;
8189
- // This activeAssetData only contains data for SELECTED tokens (user's long and short Tokens)
7627
+ // Token metadata only contains availableToTrade for SELECTED tokens (user's long and short Tokens)
8190
7628
  // It does NOT contain data for all tokens, so we cannot reliably use it for available to trade as used on hl trade page
8191
7629
  // so intead, we rely on rawClearinghouseStates which provides market-specific data
8192
- // if (activeAssetData) {
8193
- // Object.values(activeAssetData).forEach((assetData) => {
8194
- // if (!assetData.availableToTrade) return;
8195
- // const coinSymbol = assetData.coin;
8196
- // const availableValue = truncateToTwoDecimals(
8197
- // parseFloat(assetData.availableToTrade[0] || '0'),
8198
- // );
8199
- // // Determine collateral type based on market prefix
8200
- // // HIP3 markets have prefix: "xyz:SYMBOL", "flx:SYMBOL", "vntl:SYMBOL", etc.
8201
- // if (coinSymbol.includes(':')) {
8202
- // const prefix = coinSymbol.split(':')[0];
8203
- // if (prefix === 'xyz') {
8204
- // // xyz markets use USDC
8205
- // availableToTradeUsdcFromAsset = availableValue;
8206
- // } else {
8207
- // // flx, vntl, hyna and other markets use USDH
8208
- // availableToTradeUsdhFromAsset = availableValue;
8209
- // }
8210
- // } else {
8211
- // // Regular markets without prefix are automatically USDC
8212
- // availableToTradeUsdcFromAsset = availableValue;
8213
- // }
8214
- // });
8215
- // }
7630
+ const selectedMetadataEntries = [
7631
+ ...Object.entries(longTokensMetadata),
7632
+ ...Object.entries(shortTokensMetadata),
7633
+ ];
7634
+ selectedMetadataEntries.forEach(([symbol, metadata]) => {
7635
+ var _a;
7636
+ const availableStr = (_a = metadata === null || metadata === void 0 ? void 0 : metadata.availableToTrade) === null || _a === void 0 ? void 0 : _a[0];
7637
+ if (!availableStr)
7638
+ return;
7639
+ const availableValue = truncateToTwoDecimals(parseFloat(availableStr || '0'));
7640
+ if ((metadata === null || metadata === void 0 ? void 0 : metadata.collateralToken) === 'USDH') {
7641
+ availableToTradeUsdhFromAsset = Math.max(availableToTradeUsdhFromAsset, availableValue);
7642
+ return;
7643
+ }
7644
+ if ((metadata === null || metadata === void 0 ? void 0 : metadata.collateralToken) === 'USDC') {
7645
+ availableToTradeUsdcFromAsset = Math.max(availableToTradeUsdcFromAsset, availableValue);
7646
+ return;
7647
+ }
7648
+ if (symbol.includes(':')) {
7649
+ const prefix = symbol.split(':')[0];
7650
+ if (prefix === 'xyz') {
7651
+ availableToTradeUsdcFromAsset = Math.max(availableToTradeUsdcFromAsset, availableValue);
7652
+ }
7653
+ else {
7654
+ availableToTradeUsdhFromAsset = Math.max(availableToTradeUsdhFromAsset, availableValue);
7655
+ }
7656
+ return;
7657
+ }
7658
+ availableToTradeUsdcFromAsset = Math.max(availableToTradeUsdcFromAsset, availableValue);
7659
+ });
8216
7660
  // Calculate USDC available to trade
8217
7661
  // Priority 1: Use value from activeAssetData if available (> 0)
8218
7662
  // Priority 2: Calculate from USDC-specific clearinghouseState (empty prefix)
8219
7663
  let availableToTradeUsdcValue = undefined;
8220
- if (rawClearinghouseStates) {
7664
+ if (availableToTradeUsdcFromAsset > 0) {
7665
+ availableToTradeUsdcValue = availableToTradeUsdcFromAsset;
7666
+ }
7667
+ else if (rawClearinghouseStates) {
8221
7668
  // Find USDC market (empty prefix)
8222
7669
  const usdcMarket = rawClearinghouseStates.find(([prefix]) => prefix === '');
8223
7670
  const usdcState = usdcMarket === null || usdcMarket === void 0 ? void 0 : usdcMarket[1];
@@ -8245,7 +7692,6 @@ const useAllUserBalances = () => {
8245
7692
  spotState,
8246
7693
  aggregatedClearingHouseState,
8247
7694
  rawClearinghouseStates,
8248
- activeAssetData,
8249
7695
  longTokensMetadata,
8250
7696
  shortTokensMetadata,
8251
7697
  ]);
@@ -8390,12 +7836,10 @@ const PearHyperliquidContext = createContext(undefined);
8390
7836
  const PearHyperliquidProvider = ({ children, apiBaseUrl = 'https://hl-ui.pearprotocol.io', clientId = 'PEARPROTOCOLUI', wsUrl = 'wss://hl-ui.pearprotocol.io/ws', }) => {
8391
7837
  const address = useUserData((s) => s.address);
8392
7838
  const setAddress = useUserData((s) => s.setAddress);
8393
- const perpsMetaAssets = useHyperliquidData((state) => state.perpMetaAssets);
8394
- const setPerpMetaAssets = useHyperliquidData((state) => state.setPerpMetaAssets);
8395
- const setAllPerpMetaAssets = useHyperliquidData((state) => state.setAllPerpMetaAssets);
8396
- const setHip3Assets = useHyperliquidData((state) => state.setHip3Assets);
8397
- const setHip3MarketPrefixes = useHyperliquidData((state) => state.setHip3MarketPrefixes);
8398
- const websocketsEnabled = useMemo(() => Array.isArray(perpsMetaAssets) && perpsMetaAssets.length > 0, [perpsMetaAssets]);
7839
+ const perpMetasByDex = useHyperliquidData((state) => state.perpMetasByDex);
7840
+ const setPerpDexs = useHyperliquidData((state) => state.setPerpDexs);
7841
+ const setPerpMetasByDex = useHyperliquidData((state) => state.setPerpMetasByDex);
7842
+ const websocketsEnabled = useMemo(() => perpMetasByDex !== null && perpMetasByDex.size > 0, [perpMetasByDex]);
8399
7843
  const { handleUserFillsEvent } = useHyperliquidUserFills({
8400
7844
  baseUrl: apiBaseUrl,
8401
7845
  address,
@@ -8412,110 +7856,42 @@ const PearHyperliquidProvider = ({ children, apiBaseUrl = 'https://hl-ui.pearpro
8412
7856
  onUserFills: handleUserFillsEvent,
8413
7857
  });
8414
7858
  useEffect(() => {
8415
- if (perpsMetaAssets === null) {
8416
- fetchAllPerpMetas()
8417
- .then((res) => {
8418
- const assetToMarkets = new Map();
8419
- const marketPrefixes = new Map();
8420
- const FILTERED_PREFIXES = ['hyna'];
8421
- // Group assets by market prefix to match WebSocket flattening order
8422
- // WebSocket sends in order: "", "flx", "hyna", "vntl", "xyz" (we filter out hyna)
8423
- const assetsByPrefix = new Map();
8424
- const allAssetsByPrefix = new Map();
8425
- res.data.forEach((item) => {
8426
- const collateralToken = item.collateralToken === 360 ? 'USDH' : 'USDC';
8427
- item.universe.forEach((asset) => {
8428
- var _a;
8429
- const [maybePrefix, maybeMarket] = asset.name.split(':');
8430
- if (maybeMarket) {
8431
- // HIP3 asset with market prefix
8432
- const prefix = maybePrefix.toLowerCase();
8433
- const displayName = maybeMarket;
8434
- const fullName = `${prefix}:${displayName}`;
8435
- marketPrefixes.set(fullName, prefix);
8436
- if (!FILTERED_PREFIXES.includes(prefix)) {
8437
- const existingMarkets = (_a = assetToMarkets.get(displayName)) !== null && _a !== void 0 ? _a : [];
8438
- if (!existingMarkets.includes(fullName)) {
8439
- assetToMarkets.set(displayName, [
8440
- ...existingMarkets,
8441
- fullName,
8442
- ]);
8443
- }
8444
- }
8445
- const assetWithMeta = {
8446
- ...asset,
8447
- name: displayName,
8448
- marketPrefix: prefix,
8449
- collateralToken,
8450
- };
8451
- // Group by market prefix
8452
- const allList = allAssetsByPrefix.get(prefix) || [];
8453
- allList.push(assetWithMeta);
8454
- allAssetsByPrefix.set(prefix, allList);
8455
- if (!FILTERED_PREFIXES.includes(prefix)) {
8456
- const cleanedList = assetsByPrefix.get(prefix) || [];
8457
- cleanedList.push(assetWithMeta);
8458
- assetsByPrefix.set(prefix, cleanedList);
8459
- }
8460
- }
8461
- else {
8462
- // Default market asset (no prefix)
8463
- const assetWithMeta = {
8464
- ...asset,
8465
- collateralToken,
8466
- };
8467
- // Add to default market group ("")
8468
- const defaultList = assetsByPrefix.get('') || [];
8469
- defaultList.push(assetWithMeta);
8470
- assetsByPrefix.set('', defaultList);
8471
- const allDefaultList = allAssetsByPrefix.get('') || [];
8472
- allDefaultList.push(assetWithMeta);
8473
- allAssetsByPrefix.set('', allDefaultList);
8474
- }
8475
- });
8476
- });
8477
- // Flatten in consistent order: default market first, then HIP3 markets alphabetically
8478
- // This ensures both REST API and WebSocket data align properly
8479
- const cleanedPrefixes = Array.from(assetsByPrefix.keys()).sort((a, b) => {
8480
- // Empty prefix (default market) always comes first
8481
- if (a === '' && b !== '')
8482
- return -1;
8483
- if (a !== '' && b === '')
8484
- return 1;
8485
- // HIP3 markets sorted alphabetically
8486
- return a.localeCompare(b);
8487
- });
8488
- const allPrefixes = Array.from(allAssetsByPrefix.keys()).sort((a, b) => {
8489
- if (a === '' && b !== '')
8490
- return -1;
8491
- if (a !== '' && b === '')
8492
- return 1;
8493
- return a.localeCompare(b);
8494
- });
8495
- const cleanedPerpMetas = [];
8496
- const allPerpMetas = [];
8497
- cleanedPrefixes.forEach((prefix) => {
8498
- const assets = assetsByPrefix.get(prefix) || [];
8499
- cleanedPerpMetas.push(...assets);
8500
- });
8501
- allPrefixes.forEach((prefix) => {
8502
- const assets = allAssetsByPrefix.get(prefix) || [];
8503
- allPerpMetas.push(...assets);
7859
+ if (perpMetasByDex === null) {
7860
+ Promise.all([fetchPerpDexs(), fetchAllPerpMetas()])
7861
+ .then(([perpDexsRes, perpMetasRes]) => {
7862
+ const perpDexs = perpDexsRes.data;
7863
+ const perpMetas = perpMetasRes.data;
7864
+ setPerpDexs(perpDexs);
7865
+ const metasByDex = new Map();
7866
+ perpMetas.forEach((item, perpIndex) => {
7867
+ var _a, _b;
7868
+ const dexName = perpIndex === 0
7869
+ ? 'HYPERLIQUID'
7870
+ : ((_b = (_a = perpDexs[perpIndex]) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : `DEX_${perpIndex}`);
7871
+ var collateralToken;
7872
+ if (item.collateralToken === 360) {
7873
+ collateralToken = 'USDH';
7874
+ }
7875
+ if (item.collateralToken === 0) {
7876
+ collateralToken = 'USDC';
7877
+ }
7878
+ if (item.collateralToken === 235) {
7879
+ collateralToken = 'USDE';
7880
+ }
7881
+ if (item.collateralToken === 268) {
7882
+ collateralToken = 'USDT';
7883
+ }
7884
+ const universeAssets = item.universe.map((asset) => ({
7885
+ ...asset,
7886
+ collateralToken,
7887
+ }));
7888
+ metasByDex.set(dexName, universeAssets);
8504
7889
  });
8505
- setHip3Assets(assetToMarkets);
8506
- setHip3MarketPrefixes(marketPrefixes);
8507
- setPerpMetaAssets(cleanedPerpMetas);
8508
- setAllPerpMetaAssets(allPerpMetas);
7890
+ setPerpMetasByDex(metasByDex);
8509
7891
  })
8510
7892
  .catch(() => { });
8511
7893
  }
8512
- }, [
8513
- perpsMetaAssets,
8514
- setPerpMetaAssets,
8515
- setAllPerpMetaAssets,
8516
- setHip3Assets,
8517
- setHip3MarketPrefixes,
8518
- ]);
7894
+ }, [perpMetasByDex, setPerpDexs, setPerpMetasByDex]);
8519
7895
  const contextValue = useMemo(() => ({
8520
7896
  // Config
8521
7897
  clientId,
@@ -8799,4 +8175,4 @@ function getOrderTrailingInfo(order) {
8799
8175
  return undefined;
8800
8176
  }
8801
8177
 
8802
- 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, getKalshiMarkets, getMarketPrefix, getOrderDirection, getOrderLadderConfig, getOrderLeverage, getOrderReduceOnly, getOrderTpSlTriggerType, getOrderTrailingInfo, getOrderTriggerType, getOrderTriggerValue, getOrderTwapDuration, getOrderUsdValue, getPortfolio, isBtcDomOrder, isHip3Market, mapCandleIntervalToTradingViewInterval, mapTradingViewIntervalToCandleInterval, markNotificationReadById, markNotificationsRead, toBackendSymbol, toBackendSymbolWithMarket, toDisplaySymbol, toggleWatchlist, updateLeverage, updateRiskParameters, useAccountSummary, useActiveBaskets, useAgentWallet, useAllBaskets, useAllUserBalances, useAuth, useBasketCandles, useFindBasket, useHighlightedBaskets, useHistoricalPriceData, useHistoricalPriceDataStore, useHyperliquidNativeWebSocket, useHyperliquidUserFills, useHyperliquidWebSocket, useMarketData, useMarketDataAllPayload, useMarketDataPayload, useNotifications, useOpenOrders, useOrders, usePearHyperliquid, usePerformanceOverlays, usePerpMetaAssets, usePortfolio, usePosition, useSpotOrder, useTokenSelectionMetadata, useTopGainers, useTopLosers, useTradeHistories, useTwap, useUserSelection, useWatchlist, useWatchlistBaskets, useWebData, validateMaxAssetsPerLeg, validateMinimumAssetSize, validatePositionSize };
8178
+ 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, getAssetByName, getCompleteTimestamps, getKalshiMarkets, getOrderDirection, getOrderLadderConfig, getOrderLeverage, getOrderReduceOnly, getOrderTpSlTriggerType, getOrderTrailingInfo, getOrderTriggerType, getOrderTriggerValue, getOrderTwapDuration, getOrderUsdValue, getPortfolio, isBtcDomOrder, mapCandleIntervalToTradingViewInterval, mapTradingViewIntervalToCandleInterval, markNotificationReadById, markNotificationsRead, selectTokenMetadataBySymbols, toggleWatchlist, updateLeverage, updateRiskParameters, useAccountSummary, useActiveBaskets, useAgentWallet, useAllUserBalances, useAuth, useBasketCandles, useFindBasket, useHighlightedBaskets, useHistoricalPriceData, useHistoricalPriceDataStore, useHyperliquidNativeWebSocket, useHyperliquidUserFills, useHyperliquidWebSocket, useMarket, useMarketData, useMarketDataPayload, useNotifications, useOpenOrders, useOrders, usePearHyperliquid, usePerformanceOverlays, usePortfolio, usePosition, useSpotOrder, useTokenSelectionMetadata, useTopGainers, useTopLosers, useTradeHistories, useTwap, useUserSelection, useWatchlist, useWatchlistBaskets, validateMaxAssetsPerLeg, validateMinimumAssetSize, validatePositionSize };