@pear-protocol/hyperliquid-sdk 0.0.78 → 0.1.0
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/README.md +1141 -0
- package/dist/clients/hyperliquid.d.ts +1 -1
- package/dist/clients/positions.d.ts +2 -2
- package/dist/clients/watchlist.d.ts +1 -1
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/useMarket.d.ts +8 -0
- package/dist/hooks/useMarketData.d.ts +1 -4
- package/dist/hooks/useTrading.d.ts +1 -2
- package/dist/index.d.ts +26 -123
- package/dist/index.js +554 -1198
- package/dist/store/hyperliquidDataStore.d.ts +3 -7
- package/dist/store/marketDataStore.d.ts +1 -3
- package/dist/store/tokenSelectionMetadataStore.d.ts +2 -4
- package/dist/types.d.ts +12 -31
- package/dist/utils/market-symbol.d.ts +5 -0
- package/dist/utils/position-processor.d.ts +2 -2
- package/dist/utils/token-metadata-extractor.d.ts +5 -9
- package/dist/utils/token-metadata-selectors.d.ts +4 -0
- package/package.json +1 -1
- package/dist/hooks/useWebData.d.ts +0 -30
- package/dist/utils/symbol-translator.d.ts +0 -40
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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,6 +309,192 @@ const useHyperliquidWebSocket = ({ wsUrl, address, enabled = true, }) => {
|
|
|
457
309
|
};
|
|
458
310
|
};
|
|
459
311
|
|
|
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 || 'hyperliquid',
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
return { symbolName: symbol, marketName: 'hyperliquid' };
|
|
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
|
+
* Extracts comprehensive token metadata
|
|
345
|
+
* @param symbol - Token symbol (e.g., "BTC", "TSLA")
|
|
346
|
+
* @param perpMetaAssets - Aggregated universe assets (flattened across dexes)
|
|
347
|
+
* @param finalAssetContexts - Aggregated asset contexts (flattened across dexes)
|
|
348
|
+
* @param allMids - AllMids data containing current prices
|
|
349
|
+
* @param activeAssetData - Optional active asset data containing leverage information
|
|
350
|
+
* @returns TokenMetadata or null if token not found
|
|
351
|
+
*/
|
|
352
|
+
static extractTokenMetadata(symbol, perpMetaAssets, finalAssetContexts, allMids, activeAssetData, finalAtOICaps) {
|
|
353
|
+
if (!perpMetaAssets || !finalAssetContexts || !allMids) {
|
|
354
|
+
return null;
|
|
355
|
+
}
|
|
356
|
+
const universeIndex = perpMetaAssets.findIndex((asset) => symbolsMatch(asset.name, symbol));
|
|
357
|
+
if (universeIndex === -1) {
|
|
358
|
+
return null;
|
|
359
|
+
}
|
|
360
|
+
const universeAsset = perpMetaAssets[universeIndex];
|
|
361
|
+
const assetCtx = finalAssetContexts[universeIndex];
|
|
362
|
+
if (!assetCtx) {
|
|
363
|
+
return null;
|
|
364
|
+
}
|
|
365
|
+
// Get current price - prefer assetCtx.midPx as it's already index-matched,
|
|
366
|
+
// fall back to allMids lookup if midPx is null
|
|
367
|
+
const actualSymbol = universeAsset.name;
|
|
368
|
+
let currentPrice = 0;
|
|
369
|
+
// Primary source: assetCtx.midPx (already properly indexed)
|
|
370
|
+
if (assetCtx.midPx) {
|
|
371
|
+
currentPrice = parseFloat(assetCtx.midPx);
|
|
372
|
+
}
|
|
373
|
+
// Fallback: allMids lookup
|
|
374
|
+
if (!currentPrice || isNaN(currentPrice)) {
|
|
375
|
+
const currentPriceStr = allMids.mids[actualSymbol] || allMids.mids[symbol];
|
|
376
|
+
currentPrice = currentPriceStr ? parseFloat(currentPriceStr) : 0;
|
|
377
|
+
}
|
|
378
|
+
// Get previous day price
|
|
379
|
+
const prevDayPrice = parseFloat(assetCtx.prevDayPx);
|
|
380
|
+
// Calculate 24h price change
|
|
381
|
+
const priceChange24h = currentPrice - prevDayPrice;
|
|
382
|
+
const priceChange24hPercent = prevDayPrice !== 0 ? (priceChange24h / prevDayPrice) * 100 : 0;
|
|
383
|
+
// Parse other metadata
|
|
384
|
+
const netFunding = parseFloat(assetCtx.funding) * 100;
|
|
385
|
+
const markPrice = parseFloat(assetCtx.markPx);
|
|
386
|
+
const oraclePrice = parseFloat(assetCtx.oraclePx);
|
|
387
|
+
// Extract leverage info from activeAssetData if available
|
|
388
|
+
const tokenActiveData = (activeAssetData === null || activeAssetData === void 0 ? void 0 : activeAssetData[actualSymbol]) || (activeAssetData === null || activeAssetData === void 0 ? void 0 : activeAssetData[symbol]);
|
|
389
|
+
const leverage = tokenActiveData === null || tokenActiveData === void 0 ? void 0 : tokenActiveData.leverage;
|
|
390
|
+
const maxTradeSzs = tokenActiveData === null || tokenActiveData === void 0 ? void 0 : tokenActiveData.maxTradeSzs;
|
|
391
|
+
const availableToTrade = tokenActiveData === null || tokenActiveData === void 0 ? void 0 : tokenActiveData.availableToTrade;
|
|
392
|
+
const { symbolName, marketName } = getMarketInfoFromSymbol(actualSymbol);
|
|
393
|
+
const assetName = symbolName;
|
|
394
|
+
return {
|
|
395
|
+
assetName,
|
|
396
|
+
symbolName,
|
|
397
|
+
marketName,
|
|
398
|
+
isAtOiCaps: finalAtOICaps
|
|
399
|
+
? finalAtOICaps.includes(symbol)
|
|
400
|
+
: false,
|
|
401
|
+
currentPrice,
|
|
402
|
+
prevDayPrice,
|
|
403
|
+
priceChange24h,
|
|
404
|
+
priceChange24hPercent,
|
|
405
|
+
netFunding,
|
|
406
|
+
maxLeverage: universeAsset.maxLeverage,
|
|
407
|
+
markPrice,
|
|
408
|
+
oraclePrice,
|
|
409
|
+
openInterest: assetCtx.openInterest,
|
|
410
|
+
dayVolume: assetCtx.dayNtlVlm,
|
|
411
|
+
leverage,
|
|
412
|
+
maxTradeSzs,
|
|
413
|
+
availableToTrade,
|
|
414
|
+
collateralToken: universeAsset.collateralToken,
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Extracts metadata for multiple tokens
|
|
419
|
+
* @param tokens - Array of token strings (e.g., "BTC", "TSLA")
|
|
420
|
+
* @param perpMetaAssets - Aggregated universe assets
|
|
421
|
+
* @param finalAssetContexts - Aggregated asset contexts
|
|
422
|
+
* @param allMids - AllMids data
|
|
423
|
+
* @param activeAssetData - Optional active asset data containing leverage information
|
|
424
|
+
* @returns Record of token string to TokenMetadata (keys match input tokens exactly)
|
|
425
|
+
*/
|
|
426
|
+
static extractMultipleTokensMetadata(tokens, perpMetaAssets, finalAssetContexts, allMids, activeAssetData, finalAtOICaps) {
|
|
427
|
+
const result = {};
|
|
428
|
+
for (const token of tokens) {
|
|
429
|
+
result[token] = this.extractTokenMetadata(token, perpMetaAssets, finalAssetContexts, allMids, activeAssetData, finalAtOICaps);
|
|
430
|
+
}
|
|
431
|
+
return result;
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Checks if token data is available in aggregated universe assets
|
|
435
|
+
* @param symbol - Token symbol
|
|
436
|
+
* @param perpMetaAssets - Aggregated universe assets
|
|
437
|
+
* @returns boolean indicating if token exists in universe
|
|
438
|
+
*/
|
|
439
|
+
static isTokenAvailable(symbol, perpMetaAssets) {
|
|
440
|
+
if (!perpMetaAssets)
|
|
441
|
+
return false;
|
|
442
|
+
return perpMetaAssets.some((asset) => symbolsMatch(asset.name, symbol));
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const buildOiCapSet = (finalAtOICaps) => new Set((finalAtOICaps !== null && finalAtOICaps !== void 0 ? finalAtOICaps : [])
|
|
447
|
+
.filter(Boolean)
|
|
448
|
+
.map((value) => value.toUpperCase()));
|
|
449
|
+
const isAtOiCaps = (symbol, symbolName, oiCapSet) => oiCapSet.has(symbol.toUpperCase()) ||
|
|
450
|
+
oiCapSet.has(symbolName.toUpperCase());
|
|
451
|
+
const applyMetadataContext = (symbol, metadata, oiCapSet) => {
|
|
452
|
+
if (!metadata)
|
|
453
|
+
return null;
|
|
454
|
+
const { symbolName, marketName } = getMarketInfoFromSymbol(symbol);
|
|
455
|
+
const assetName = symbolName;
|
|
456
|
+
return {
|
|
457
|
+
...metadata,
|
|
458
|
+
assetName,
|
|
459
|
+
symbolName,
|
|
460
|
+
marketName,
|
|
461
|
+
isAtOiCaps: isAtOiCaps(symbol, symbolName, oiCapSet),
|
|
462
|
+
};
|
|
463
|
+
};
|
|
464
|
+
const applyOiCapsToMetadataMap = (tokenMetadata, finalAtOICaps) => {
|
|
465
|
+
if (!tokenMetadata || Object.keys(tokenMetadata).length === 0) {
|
|
466
|
+
return tokenMetadata;
|
|
467
|
+
}
|
|
468
|
+
const oiCapSet = buildOiCapSet(finalAtOICaps);
|
|
469
|
+
const next = {};
|
|
470
|
+
Object.entries(tokenMetadata).forEach(([symbol, metadata]) => {
|
|
471
|
+
next[symbol] = applyMetadataContext(symbol, metadata, oiCapSet);
|
|
472
|
+
});
|
|
473
|
+
return next;
|
|
474
|
+
};
|
|
475
|
+
const buildTokenMetadataMap = ({ perpMetaAssets, finalAssetContexts, allMids, activeAssetData, finalAtOICaps, }) => {
|
|
476
|
+
if (!perpMetaAssets || !finalAssetContexts || !allMids) {
|
|
477
|
+
return {};
|
|
478
|
+
}
|
|
479
|
+
const oiCapSet = buildOiCapSet(finalAtOICaps);
|
|
480
|
+
const symbols = perpMetaAssets.map((asset) => asset.name);
|
|
481
|
+
const metadataMap = TokenMetadataExtractor.extractMultipleTokensMetadata(symbols, perpMetaAssets, finalAssetContexts, allMids, activeAssetData, finalAtOICaps);
|
|
482
|
+
symbols.forEach((symbol) => {
|
|
483
|
+
metadataMap[symbol] = applyMetadataContext(symbol, metadataMap[symbol], oiCapSet);
|
|
484
|
+
});
|
|
485
|
+
return metadataMap;
|
|
486
|
+
};
|
|
487
|
+
const updateTokenMetadataForSymbols = (prev, symbols, { perpMetaAssets, finalAssetContexts, allMids, activeAssetData, finalAtOICaps, }) => {
|
|
488
|
+
if (!perpMetaAssets || !finalAssetContexts || !allMids) {
|
|
489
|
+
return prev;
|
|
490
|
+
}
|
|
491
|
+
const oiCapSet = buildOiCapSet(finalAtOICaps);
|
|
492
|
+
const next = { ...prev };
|
|
493
|
+
symbols.forEach((symbol) => {
|
|
494
|
+
next[symbol] = applyMetadataContext(symbol, TokenMetadataExtractor.extractTokenMetadata(symbol, perpMetaAssets, finalAssetContexts, allMids, activeAssetData), oiCapSet);
|
|
495
|
+
});
|
|
496
|
+
return next;
|
|
497
|
+
};
|
|
460
498
|
const useHyperliquidData = create((set, get) => ({
|
|
461
499
|
allMids: null,
|
|
462
500
|
activeAssetData: null,
|
|
@@ -466,13 +504,30 @@ const useHyperliquidData = create((set, get) => ({
|
|
|
466
504
|
aggregatedClearingHouseState: null,
|
|
467
505
|
rawClearinghouseStates: null,
|
|
468
506
|
perpMetaAssets: null,
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
507
|
+
tokenMetadata: {},
|
|
508
|
+
setAllMids: (value) => set((state) => ({
|
|
509
|
+
allMids: value,
|
|
510
|
+
tokenMetadata: buildTokenMetadataMap({
|
|
511
|
+
perpMetaAssets: state.perpMetaAssets,
|
|
512
|
+
finalAssetContexts: state.finalAssetContexts,
|
|
513
|
+
allMids: value,
|
|
514
|
+
activeAssetData: state.activeAssetData,
|
|
515
|
+
finalAtOICaps: state.finalAtOICaps,
|
|
516
|
+
}),
|
|
475
517
|
})),
|
|
518
|
+
setActiveAssetData: (value) => set((state) => {
|
|
519
|
+
const activeAssetData = typeof value === 'function' ? value(state.activeAssetData) : value;
|
|
520
|
+
return {
|
|
521
|
+
activeAssetData,
|
|
522
|
+
tokenMetadata: buildTokenMetadataMap({
|
|
523
|
+
perpMetaAssets: state.perpMetaAssets,
|
|
524
|
+
finalAssetContexts: state.finalAssetContexts,
|
|
525
|
+
allMids: state.allMids,
|
|
526
|
+
activeAssetData,
|
|
527
|
+
finalAtOICaps: state.finalAtOICaps,
|
|
528
|
+
}),
|
|
529
|
+
};
|
|
530
|
+
}),
|
|
476
531
|
deleteActiveAssetData: (key) => {
|
|
477
532
|
set((state) => {
|
|
478
533
|
if (!state.activeAssetData || !(key in state.activeAssetData)) {
|
|
@@ -480,7 +535,16 @@ const useHyperliquidData = create((set, get) => ({
|
|
|
480
535
|
}
|
|
481
536
|
const updated = { ...state.activeAssetData };
|
|
482
537
|
delete updated[key];
|
|
483
|
-
return {
|
|
538
|
+
return {
|
|
539
|
+
activeAssetData: updated,
|
|
540
|
+
tokenMetadata: updateTokenMetadataForSymbols(state.tokenMetadata, [key], {
|
|
541
|
+
perpMetaAssets: state.perpMetaAssets,
|
|
542
|
+
finalAssetContexts: state.finalAssetContexts,
|
|
543
|
+
allMids: state.allMids,
|
|
544
|
+
activeAssetData: updated,
|
|
545
|
+
finalAtOICaps: state.finalAtOICaps,
|
|
546
|
+
}),
|
|
547
|
+
};
|
|
484
548
|
});
|
|
485
549
|
},
|
|
486
550
|
addCandleData(symbol, candle) {
|
|
@@ -502,20 +566,49 @@ const useHyperliquidData = create((set, get) => ({
|
|
|
502
566
|
});
|
|
503
567
|
},
|
|
504
568
|
setCandleData: (value) => set({ candleData: value }),
|
|
505
|
-
upsertActiveAssetData: (key, value) => set((state) =>
|
|
506
|
-
|
|
507
|
-
|
|
569
|
+
upsertActiveAssetData: (key, value) => set((state) => {
|
|
570
|
+
var _a;
|
|
571
|
+
const activeAssetData = {
|
|
572
|
+
...((_a = state.activeAssetData) !== null && _a !== void 0 ? _a : {}),
|
|
508
573
|
[key]: value,
|
|
509
|
-
}
|
|
574
|
+
};
|
|
575
|
+
return {
|
|
576
|
+
activeAssetData,
|
|
577
|
+
tokenMetadata: updateTokenMetadataForSymbols(state.tokenMetadata, [key], {
|
|
578
|
+
perpMetaAssets: state.perpMetaAssets,
|
|
579
|
+
finalAssetContexts: state.finalAssetContexts,
|
|
580
|
+
allMids: state.allMids,
|
|
581
|
+
activeAssetData,
|
|
582
|
+
finalAtOICaps: state.finalAtOICaps,
|
|
583
|
+
}),
|
|
584
|
+
};
|
|
585
|
+
}),
|
|
586
|
+
setFinalAssetContexts: (value) => set((state) => ({
|
|
587
|
+
finalAssetContexts: value,
|
|
588
|
+
tokenMetadata: buildTokenMetadataMap({
|
|
589
|
+
perpMetaAssets: state.perpMetaAssets,
|
|
590
|
+
finalAssetContexts: value,
|
|
591
|
+
allMids: state.allMids,
|
|
592
|
+
activeAssetData: state.activeAssetData,
|
|
593
|
+
finalAtOICaps: state.finalAtOICaps,
|
|
594
|
+
}),
|
|
595
|
+
})),
|
|
596
|
+
setFinalAtOICaps: (value) => set((state) => ({
|
|
597
|
+
finalAtOICaps: value,
|
|
598
|
+
tokenMetadata: applyOiCapsToMetadataMap(state.tokenMetadata, value),
|
|
510
599
|
})),
|
|
511
|
-
setFinalAssetContexts: (value) => set({ finalAssetContexts: value }),
|
|
512
|
-
setFinalAtOICaps: (value) => set({ finalAtOICaps: value }),
|
|
513
600
|
setAggregatedClearingHouseState: (value) => set({ aggregatedClearingHouseState: value }),
|
|
514
601
|
setRawClearinghouseStates: (value) => set({ rawClearinghouseStates: value }),
|
|
515
|
-
setPerpMetaAssets: (value) => set(
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
602
|
+
setPerpMetaAssets: (value) => set((state) => ({
|
|
603
|
+
perpMetaAssets: value,
|
|
604
|
+
tokenMetadata: buildTokenMetadataMap({
|
|
605
|
+
perpMetaAssets: value,
|
|
606
|
+
finalAssetContexts: state.finalAssetContexts,
|
|
607
|
+
allMids: state.allMids,
|
|
608
|
+
activeAssetData: state.activeAssetData,
|
|
609
|
+
finalAtOICaps: state.finalAtOICaps,
|
|
610
|
+
}),
|
|
611
|
+
}))
|
|
519
612
|
}));
|
|
520
613
|
|
|
521
614
|
/**
|
|
@@ -781,6 +874,7 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, onUserFills, }
|
|
|
781
874
|
const { setAllMids, setActiveAssetData, upsertActiveAssetData, setCandleData, deleteCandleSymbol, deleteActiveAssetData, addCandleData, setFinalAssetContexts, setFinalAtOICaps, setAggregatedClearingHouseState, setRawClearinghouseStates, } = useHyperliquidData();
|
|
782
875
|
const { setSpotState } = useUserData();
|
|
783
876
|
const { candleInterval } = useUserSelection$1();
|
|
877
|
+
const userSummary = useUserData((state) => state.accountSummary);
|
|
784
878
|
const longTokens = useUserSelection$1((s) => s.longTokens);
|
|
785
879
|
const shortTokens = useUserSelection$1((s) => s.shortTokens);
|
|
786
880
|
const selectedTokenSymbols = useMemo(() => [...longTokens, ...shortTokens].map((t) => t.symbol), [longTokens, shortTokens]);
|
|
@@ -888,51 +982,20 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, onUserFills, }
|
|
|
888
982
|
case 'allMids':
|
|
889
983
|
{
|
|
890
984
|
const data = response.data;
|
|
891
|
-
|
|
892
|
-
// This ensures xyz:TSLA and flx:TSLA are stored separately,
|
|
893
|
-
// while also maintaining backward compatibility with non-prefixed lookups
|
|
894
|
-
const mids = {};
|
|
895
|
-
Object.entries(data.mids || {}).forEach(([k, v]) => {
|
|
896
|
-
// Normalize prefixed keys to lowercase prefix (e.g., "XYZ:TSLA" -> "xyz:TSLA")
|
|
897
|
-
// This matches how we look up tokens in the SDK
|
|
898
|
-
let normalizedKey = k;
|
|
899
|
-
if (k.includes(':')) {
|
|
900
|
-
const [prefix, ...rest] = k.split(':');
|
|
901
|
-
normalizedKey = `${prefix.toLowerCase()}:${rest.join(':')}`;
|
|
902
|
-
}
|
|
903
|
-
// Store with normalized key
|
|
904
|
-
mids[normalizedKey] = v;
|
|
905
|
-
// Also store with original key for backward compatibility
|
|
906
|
-
if (k !== normalizedKey) {
|
|
907
|
-
mids[k] = v;
|
|
908
|
-
}
|
|
909
|
-
// Also store with display symbol for backward compatibility
|
|
910
|
-
const displayKey = toDisplaySymbol(k);
|
|
911
|
-
// Only set display key if it doesn't already exist (avoid overwriting market-specific prices)
|
|
912
|
-
if (!(displayKey in mids)) {
|
|
913
|
-
mids[displayKey] = v;
|
|
914
|
-
}
|
|
915
|
-
});
|
|
916
|
-
setAllMids({ mids });
|
|
985
|
+
setAllMids(data);
|
|
917
986
|
}
|
|
918
987
|
break;
|
|
919
988
|
case 'activeAssetData':
|
|
920
989
|
{
|
|
921
990
|
const assetData = response.data;
|
|
922
|
-
|
|
923
|
-
const normalized = {
|
|
924
|
-
...assetData,
|
|
925
|
-
coin: symbol,
|
|
926
|
-
};
|
|
927
|
-
upsertActiveAssetData(symbol, normalized);
|
|
991
|
+
upsertActiveAssetData(assetData.coin, assetData);
|
|
928
992
|
}
|
|
929
993
|
break;
|
|
930
994
|
case 'candle':
|
|
931
995
|
{
|
|
932
996
|
const candleDataItem = response.data;
|
|
933
|
-
const symbol =
|
|
934
|
-
|
|
935
|
-
addCandleData(symbol, normalized);
|
|
997
|
+
const symbol = candleDataItem.s || '';
|
|
998
|
+
addCandleData(symbol, candleDataItem);
|
|
936
999
|
}
|
|
937
1000
|
break;
|
|
938
1001
|
case 'spotState':
|
|
@@ -1155,9 +1218,8 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, onUserFills, }
|
|
|
1155
1218
|
setRawClearinghouseStates,
|
|
1156
1219
|
setSpotState,
|
|
1157
1220
|
]);
|
|
1158
|
-
// Subscribe to userFills only after allDexsClearinghouseState data is received
|
|
1159
1221
|
useEffect(() => {
|
|
1160
|
-
if (!isConnected || !subscribedAddress || !clearinghouseStateReceived)
|
|
1222
|
+
if (!isConnected || !subscribedAddress || !clearinghouseStateReceived || !userSummary)
|
|
1161
1223
|
return;
|
|
1162
1224
|
const subscribeUserFills = {
|
|
1163
1225
|
method: 'subscribe',
|
|
@@ -1167,7 +1229,7 @@ const useHyperliquidNativeWebSocket = ({ address, enabled = true, onUserFills, }
|
|
|
1167
1229
|
},
|
|
1168
1230
|
};
|
|
1169
1231
|
sendJsonMessage(subscribeUserFills);
|
|
1170
|
-
}, [isConnected, subscribedAddress, clearinghouseStateReceived, sendJsonMessage]);
|
|
1232
|
+
}, [isConnected, subscribedAddress, clearinghouseStateReceived, userSummary, sendJsonMessage]);
|
|
1171
1233
|
// Handle token subscriptions for activeAssetData
|
|
1172
1234
|
useEffect(() => {
|
|
1173
1235
|
if (!isConnected || !address)
|
|
@@ -1338,381 +1400,116 @@ class AccountSummaryCalculator {
|
|
|
1338
1400
|
getClearinghouseState() {
|
|
1339
1401
|
return this.clearinghouseState || null;
|
|
1340
1402
|
}
|
|
1341
|
-
/**
|
|
1342
|
-
* Check if real-time data is available
|
|
1343
|
-
*/
|
|
1344
|
-
hasRealTimeData() {
|
|
1345
|
-
return !!this.clearinghouseState;
|
|
1346
|
-
}
|
|
1347
|
-
}
|
|
1348
|
-
|
|
1349
|
-
const useAccountSummary = () => {
|
|
1350
|
-
const context = useContext(PearHyperliquidContext);
|
|
1351
|
-
if (!context) {
|
|
1352
|
-
throw new Error('useAccountSummary must be used within a PearHyperliquidProvider');
|
|
1353
|
-
}
|
|
1354
|
-
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
|
|
1403
|
+
/**
|
|
1404
|
+
* Check if real-time data is available
|
|
1688
1405
|
*/
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
return false;
|
|
1692
|
-
return perpMetaAssets.some((asset) => symbolsMatch(asset.name, symbol));
|
|
1406
|
+
hasRealTimeData() {
|
|
1407
|
+
return !!this.clearinghouseState;
|
|
1693
1408
|
}
|
|
1694
1409
|
}
|
|
1695
1410
|
|
|
1411
|
+
const useAccountSummary = () => {
|
|
1412
|
+
const context = useContext(PearHyperliquidContext);
|
|
1413
|
+
if (!context) {
|
|
1414
|
+
throw new Error('useAccountSummary must be used within a PearHyperliquidProvider');
|
|
1415
|
+
}
|
|
1416
|
+
const platformAccountSummary = useUserData((state) => state.accountSummary);
|
|
1417
|
+
const aggregatedClearingHouseState = useHyperliquidData((state) => state.aggregatedClearingHouseState);
|
|
1418
|
+
const registeredAgentWallets = useUserData((state) => state.userExtraAgents);
|
|
1419
|
+
const isLoading = useMemo(() => {
|
|
1420
|
+
return !platformAccountSummary || !registeredAgentWallets || !aggregatedClearingHouseState;
|
|
1421
|
+
}, [platformAccountSummary, registeredAgentWallets, aggregatedClearingHouseState]);
|
|
1422
|
+
// Create calculator and compute account summary
|
|
1423
|
+
const calculator = new AccountSummaryCalculator(aggregatedClearingHouseState);
|
|
1424
|
+
const calculated = calculator.calculateAccountSummary(platformAccountSummary, registeredAgentWallets || []);
|
|
1425
|
+
return { data: calculated, isLoading };
|
|
1426
|
+
};
|
|
1427
|
+
|
|
1428
|
+
const selectTokenMetadataBySymbols = (tokenMetadata, symbols) => {
|
|
1429
|
+
const result = {};
|
|
1430
|
+
symbols.forEach((symbol) => {
|
|
1431
|
+
var _a;
|
|
1432
|
+
result[symbol] = (_a = tokenMetadata[symbol]) !== null && _a !== void 0 ? _a : null;
|
|
1433
|
+
});
|
|
1434
|
+
return result;
|
|
1435
|
+
};
|
|
1436
|
+
const getAssetByName = (tokenMetadata, symbol) => {
|
|
1437
|
+
var _a, _b;
|
|
1438
|
+
if (symbol in tokenMetadata) {
|
|
1439
|
+
return (_a = tokenMetadata[symbol]) !== null && _a !== void 0 ? _a : null;
|
|
1440
|
+
}
|
|
1441
|
+
const normalizedSymbol = symbol.toUpperCase();
|
|
1442
|
+
const matchKey = Object.keys(tokenMetadata).find((key) => key.toUpperCase() === normalizedSymbol);
|
|
1443
|
+
return matchKey ? (_b = tokenMetadata[matchKey]) !== null && _b !== void 0 ? _b : null : null;
|
|
1444
|
+
};
|
|
1445
|
+
|
|
1696
1446
|
/**
|
|
1697
|
-
*
|
|
1698
|
-
* This allows us to keep the full name (xyz:GOOGL) for URLs/tags while extracting just the symbol for SDK lookups.
|
|
1447
|
+
* Hook to access webData
|
|
1699
1448
|
*/
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1449
|
+
const useMarket = () => {
|
|
1450
|
+
const tokenMetadata = useHyperliquidData((state) => state.tokenMetadata);
|
|
1451
|
+
const allTokenMetadata = useMemo(() => Object.values(tokenMetadata).filter((metadata) => Boolean(metadata)), [tokenMetadata]);
|
|
1452
|
+
const getAssetByName$1 = useCallback((symbol) => getAssetByName(tokenMetadata, symbol), [tokenMetadata]);
|
|
1453
|
+
return { allTokenMetadata, getAssetByName: getAssetByName$1 };
|
|
1454
|
+
};
|
|
1455
|
+
|
|
1456
|
+
const useTradeHistories = () => {
|
|
1457
|
+
const context = useContext(PearHyperliquidContext);
|
|
1458
|
+
if (!context) {
|
|
1459
|
+
throw new Error('useTradeHistories must be used within a PearHyperliquidProvider');
|
|
1709
1460
|
}
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1461
|
+
const tradeHistories = useUserData((state) => state.tradeHistories);
|
|
1462
|
+
const { getAssetByName } = useMarket();
|
|
1463
|
+
const enrichedTradeHistories = useMemo(() => {
|
|
1464
|
+
if (!tradeHistories)
|
|
1465
|
+
return null;
|
|
1466
|
+
return tradeHistories.map((history) => ({
|
|
1467
|
+
...history,
|
|
1468
|
+
closedLongAssets: history.closedLongAssets.map((asset) => ({
|
|
1469
|
+
...asset,
|
|
1470
|
+
metadata: getAssetByName(asset.coin),
|
|
1471
|
+
})),
|
|
1472
|
+
closedShortAssets: history.closedShortAssets.map((asset) => ({
|
|
1473
|
+
...asset,
|
|
1474
|
+
metadata: getAssetByName(asset.coin),
|
|
1475
|
+
})),
|
|
1476
|
+
}));
|
|
1477
|
+
}, [tradeHistories, getAssetByName]);
|
|
1478
|
+
const isLoading = useMemo(() => {
|
|
1479
|
+
return tradeHistories === null && context.isConnected;
|
|
1480
|
+
}, [tradeHistories, context.isConnected]);
|
|
1481
|
+
return { data: enrichedTradeHistories, isLoading };
|
|
1482
|
+
};
|
|
1483
|
+
const useOpenOrders = () => {
|
|
1484
|
+
const context = useContext(PearHyperliquidContext);
|
|
1485
|
+
if (!context) {
|
|
1486
|
+
throw new Error('useOpenOrders must be used within a PearHyperliquidProvider');
|
|
1487
|
+
}
|
|
1488
|
+
const openOrders = useUserData((state) => state.openOrders);
|
|
1489
|
+
const { getAssetByName } = useMarket();
|
|
1490
|
+
const enrichedOpenOrders = useMemo(() => {
|
|
1491
|
+
if (!openOrders)
|
|
1492
|
+
return null;
|
|
1493
|
+
const mapAssets = (assets) => (assets !== null && assets !== void 0 ? assets : []).map((asset) => ({
|
|
1494
|
+
...asset,
|
|
1495
|
+
metadata: getAssetByName(asset.asset),
|
|
1496
|
+
}));
|
|
1497
|
+
return openOrders.map((order) => ({
|
|
1498
|
+
...order,
|
|
1499
|
+
longAssets: mapAssets(order.longAssets),
|
|
1500
|
+
shortAssets: mapAssets(order.shortAssets),
|
|
1501
|
+
}));
|
|
1502
|
+
}, [openOrders, getAssetByName]);
|
|
1503
|
+
const isLoading = useMemo(() => {
|
|
1504
|
+
return openOrders === null && context.isConnected;
|
|
1505
|
+
}, [openOrders, context.isConnected]);
|
|
1506
|
+
return { data: enrichedOpenOrders, isLoading };
|
|
1507
|
+
};
|
|
1508
|
+
|
|
1509
|
+
const useUserSelection = () => {
|
|
1510
|
+
return useUserSelection$1();
|
|
1511
|
+
};
|
|
1512
|
+
|
|
1716
1513
|
const useTokenSelectionMetadataStore = create((set) => ({
|
|
1717
1514
|
isPriceDataReady: false,
|
|
1718
1515
|
isLoading: true,
|
|
@@ -1728,59 +1525,18 @@ const useTokenSelectionMetadataStore = create((set) => ({
|
|
|
1728
1525
|
maxLeverage: 0,
|
|
1729
1526
|
minMargin: 0,
|
|
1730
1527
|
leverageMatched: true,
|
|
1731
|
-
recompute: ({ perpMetaAssets,
|
|
1732
|
-
const isPriceDataReady =
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
//
|
|
1737
|
-
const
|
|
1738
|
-
|
|
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)
|
|
1528
|
+
recompute: ({ perpMetaAssets, tokenMetadata, marketData, longTokens, shortTokens, }) => {
|
|
1529
|
+
const isPriceDataReady = Object.keys(tokenMetadata).length > 0;
|
|
1530
|
+
// Get token symbols for lookups
|
|
1531
|
+
const longSymbols = longTokens.map((t) => t.symbol);
|
|
1532
|
+
const shortSymbols = shortTokens.map((t) => t.symbol);
|
|
1533
|
+
// Get metadata
|
|
1534
|
+
const longTokensMetadata = isPriceDataReady
|
|
1535
|
+
? selectTokenMetadataBySymbols(tokenMetadata, longSymbols)
|
|
1761
1536
|
: {};
|
|
1762
|
-
const
|
|
1763
|
-
?
|
|
1537
|
+
const shortTokensMetadata = isPriceDataReady
|
|
1538
|
+
? selectTokenMetadataBySymbols(tokenMetadata, shortSymbols)
|
|
1764
1539
|
: {};
|
|
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
1540
|
// Determine loading state
|
|
1785
1541
|
const allTokens = [...longTokens, ...shortTokens];
|
|
1786
1542
|
const isLoading = (() => {
|
|
@@ -1795,13 +1551,12 @@ const useTokenSelectionMetadataStore = create((set) => ({
|
|
|
1795
1551
|
return allTokens.some((token) => !allMetadata[token.symbol]);
|
|
1796
1552
|
})();
|
|
1797
1553
|
// Open interest and volume (from market data for matching asset basket)
|
|
1798
|
-
// Use base symbols (without prefix) for matching against market data
|
|
1799
1554
|
const { openInterest, volume } = (() => {
|
|
1800
1555
|
const empty = { openInterest: "0", volume: "0" };
|
|
1801
1556
|
if (!(marketData === null || marketData === void 0 ? void 0 : marketData.active) || (!longTokens.length && !shortTokens.length))
|
|
1802
1557
|
return empty;
|
|
1803
|
-
const selectedLong =
|
|
1804
|
-
const selectedShort =
|
|
1558
|
+
const selectedLong = longSymbols.slice().sort();
|
|
1559
|
+
const selectedShort = shortSymbols.slice().sort();
|
|
1805
1560
|
const match = marketData.active.find((item) => {
|
|
1806
1561
|
const longs = [...item.longAssets].sort();
|
|
1807
1562
|
const shorts = [...item.shortAssets].sort();
|
|
@@ -1894,27 +1649,18 @@ const useTokenSelectionMetadataStore = create((set) => ({
|
|
|
1894
1649
|
return totalFunding;
|
|
1895
1650
|
})();
|
|
1896
1651
|
// Max leverage (maximum across all tokens)
|
|
1897
|
-
// Use tokens with their market prefixes for proper lookup in perpMetaAssets
|
|
1898
1652
|
const maxLeverage = (() => {
|
|
1899
1653
|
if (!perpMetaAssets)
|
|
1900
1654
|
return 0;
|
|
1901
|
-
const
|
|
1902
|
-
|
|
1903
|
-
...shortTokensForLookup,
|
|
1904
|
-
];
|
|
1905
|
-
if (allTokensForLookup.length === 0)
|
|
1655
|
+
const allSymbols = [...longSymbols, ...shortSymbols];
|
|
1656
|
+
if (allSymbols.length === 0)
|
|
1906
1657
|
return 0;
|
|
1907
1658
|
let maxLev = 0;
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
(
|
|
1912
|
-
|
|
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);
|
|
1659
|
+
allSymbols.forEach((symbol) => {
|
|
1660
|
+
const tokenUniverse = perpMetaAssets.find((u) => u.name === symbol);
|
|
1661
|
+
if (tokenUniverse === null || tokenUniverse === void 0 ? void 0 : tokenUniverse.maxLeverage) {
|
|
1662
|
+
maxLev = Math.max(maxLev, tokenUniverse.maxLeverage);
|
|
1663
|
+
}
|
|
1918
1664
|
});
|
|
1919
1665
|
return maxLev;
|
|
1920
1666
|
})();
|
|
@@ -1968,9 +1714,7 @@ const useTokenSelectionMetadata = () => {
|
|
|
1968
1714
|
throw new Error('useTokenSelection must be used within PearHyperliquidProvider');
|
|
1969
1715
|
}
|
|
1970
1716
|
const perpMetaAssets = useHyperliquidData((state) => state.perpMetaAssets);
|
|
1971
|
-
const
|
|
1972
|
-
const allMids = useHyperliquidData((state) => state.allMids);
|
|
1973
|
-
const activeAssetData = useHyperliquidData((state) => state.activeAssetData);
|
|
1717
|
+
const tokenMetadata = useHyperliquidData((state) => state.tokenMetadata);
|
|
1974
1718
|
const marketData = useMarketData((state) => state.marketData);
|
|
1975
1719
|
const { longTokens, shortTokens } = useUserSelection$1();
|
|
1976
1720
|
const { isLoading, isPriceDataReady, longTokensMetadata, shortTokensMetadata, weightedRatio, weightedRatio24h, priceRatio, priceRatio24h, openInterest, volume, sumNetFunding, maxLeverage, minMargin, leverageMatched, recompute, } = useTokenSelectionMetadataStore();
|
|
@@ -1978,16 +1722,14 @@ const useTokenSelectionMetadata = () => {
|
|
|
1978
1722
|
useEffect(() => {
|
|
1979
1723
|
recompute({
|
|
1980
1724
|
perpMetaAssets,
|
|
1981
|
-
|
|
1982
|
-
allMids,
|
|
1983
|
-
activeAssetData: activeAssetData || null,
|
|
1725
|
+
tokenMetadata,
|
|
1984
1726
|
marketData: marketData || null,
|
|
1985
1727
|
longTokens,
|
|
1986
1728
|
shortTokens,
|
|
1987
1729
|
});
|
|
1988
1730
|
// We want to recompute when token lists or upstream data change
|
|
1989
1731
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1990
|
-
}, [perpMetaAssets,
|
|
1732
|
+
}, [perpMetaAssets, tokenMetadata, JSON.stringify(longTokens), JSON.stringify(shortTokens)]);
|
|
1991
1733
|
return {
|
|
1992
1734
|
// Loading states
|
|
1993
1735
|
isLoading,
|
|
@@ -6114,10 +5856,9 @@ function addAuthInterceptors(params) {
|
|
|
6114
5856
|
/**
|
|
6115
5857
|
* Fetch historical candle data from HyperLiquid API
|
|
6116
5858
|
*/
|
|
6117
|
-
const fetchHistoricalCandles = async (coin, startTime, endTime, interval
|
|
6118
|
-
const backendCoin = toBackendSymbol(coin, hip3Assets);
|
|
5859
|
+
const fetchHistoricalCandles = async (coin, startTime, endTime, interval) => {
|
|
6119
5860
|
const request = {
|
|
6120
|
-
req: { coin
|
|
5861
|
+
req: { coin, startTime, endTime, interval },
|
|
6121
5862
|
type: 'candleSnapshot',
|
|
6122
5863
|
};
|
|
6123
5864
|
try {
|
|
@@ -6274,10 +6015,9 @@ const useHistoricalPriceData = () => {
|
|
|
6274
6015
|
setTokenLoading(token.symbol, true);
|
|
6275
6016
|
});
|
|
6276
6017
|
try {
|
|
6277
|
-
const hip3Assets = useHyperliquidData.getState().hip3Assets;
|
|
6278
6018
|
const fetchPromises = tokensToFetch.map(async (token) => {
|
|
6279
6019
|
try {
|
|
6280
|
-
const response = await fetchHistoricalCandles(token.symbol, startTime, endTime, interval
|
|
6020
|
+
const response = await fetchHistoricalCandles(token.symbol, startTime, endTime, interval);
|
|
6281
6021
|
addHistoricalPriceData(token.symbol, interval, response.data, { start: startTime, end: endTime });
|
|
6282
6022
|
return { symbol: token.symbol, candles: response.data, success: true };
|
|
6283
6023
|
}
|
|
@@ -6825,24 +6565,14 @@ function useAgentWallet() {
|
|
|
6825
6565
|
* @throws MinimumPositionSizeError if any asset has less than $11 USD value
|
|
6826
6566
|
* @throws MaxAssetsPerLegError if any leg exceeds the maximum allowed assets (15)
|
|
6827
6567
|
*/
|
|
6828
|
-
async function createPosition(baseUrl, payload
|
|
6568
|
+
async function createPosition(baseUrl, payload) {
|
|
6829
6569
|
// Validate maximum assets per leg before creating position
|
|
6830
6570
|
validateMaxAssetsPerLeg(payload.longAssets, payload.shortAssets);
|
|
6831
6571
|
// Validate minimum asset size before creating position
|
|
6832
6572
|
validateMinimumAssetSize(payload.usdValue, payload.longAssets, payload.shortAssets);
|
|
6833
6573
|
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
6574
|
try {
|
|
6845
|
-
const resp = await apiClient.post(url,
|
|
6575
|
+
const resp = await apiClient.post(url, payload, {
|
|
6846
6576
|
headers: {
|
|
6847
6577
|
"Content-Type": "application/json",
|
|
6848
6578
|
},
|
|
@@ -6934,15 +6664,10 @@ async function adjustPosition(baseUrl, positionId, payload) {
|
|
|
6934
6664
|
throw toApiError(error);
|
|
6935
6665
|
}
|
|
6936
6666
|
}
|
|
6937
|
-
async function adjustAdvancePosition(baseUrl, positionId, payload
|
|
6667
|
+
async function adjustAdvancePosition(baseUrl, positionId, payload) {
|
|
6938
6668
|
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
6669
|
try {
|
|
6945
|
-
const resp = await apiClient.post(url,
|
|
6670
|
+
const resp = await apiClient.post(url, payload, {
|
|
6946
6671
|
headers: {
|
|
6947
6672
|
"Content-Type": "application/json",
|
|
6948
6673
|
},
|
|
@@ -7002,7 +6727,7 @@ async function updateLeverage(baseUrl, positionId, payload) {
|
|
|
7002
6727
|
}
|
|
7003
6728
|
}
|
|
7004
6729
|
|
|
7005
|
-
const calculatePositionAsset = (asset, currentPrice, totalInitialPositionSize, leverage, isLong = true) => {
|
|
6730
|
+
const calculatePositionAsset = (asset, currentPrice, totalInitialPositionSize, leverage, metadata, isLong = true) => {
|
|
7006
6731
|
var _a;
|
|
7007
6732
|
const entryNotional = asset.entryPrice * asset.size;
|
|
7008
6733
|
const currentNotional = currentPrice * asset.size;
|
|
@@ -7021,13 +6746,12 @@ const calculatePositionAsset = (asset, currentPrice, totalInitialPositionSize, l
|
|
|
7021
6746
|
entryPositionValue: entryNotional,
|
|
7022
6747
|
initialWeight: totalInitialPositionSize > 0 ? entryNotional / totalInitialPositionSize : 0,
|
|
7023
6748
|
fundingPaid: (_a = asset.fundingPaid) !== null && _a !== void 0 ? _a : 0,
|
|
7024
|
-
|
|
7025
|
-
marketPrefix: asset.marketPrefix,
|
|
7026
|
-
collateralToken: asset.collateralToken,
|
|
6749
|
+
metadata,
|
|
7027
6750
|
};
|
|
7028
6751
|
};
|
|
7029
|
-
const buildPositionValue = (rawPositions, clearinghouseState,
|
|
6752
|
+
const buildPositionValue = (rawPositions, clearinghouseState, getAssetByName) => {
|
|
7030
6753
|
return rawPositions.map((position) => {
|
|
6754
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
7031
6755
|
let mappedPosition = {
|
|
7032
6756
|
positionId: position.positionId,
|
|
7033
6757
|
address: position.address,
|
|
@@ -7045,11 +6769,12 @@ const buildPositionValue = (rawPositions, clearinghouseState, allMids) => {
|
|
|
7045
6769
|
const totalInitialPositionSize = position.longAssets.reduce((acc, asset) => acc + asset.entryPrice * asset.size, 0) +
|
|
7046
6770
|
position.shortAssets.reduce((acc, asset) => acc + asset.entryPrice * asset.size, 0);
|
|
7047
6771
|
mappedPosition.longAssets = position.longAssets.map((longAsset) => {
|
|
7048
|
-
var _a, _b, _c;
|
|
7049
|
-
const
|
|
7050
|
-
const
|
|
7051
|
-
const
|
|
7052
|
-
const
|
|
6772
|
+
var _a, _b, _c, _d;
|
|
6773
|
+
const metadata = getAssetByName(longAsset.coin);
|
|
6774
|
+
const currentPrice = (_a = metadata === null || metadata === void 0 ? void 0 : metadata.currentPrice) !== null && _a !== void 0 ? _a : 0;
|
|
6775
|
+
const assetState = (_b = clearinghouseState.assetPositions.find((ap) => ap.position.coin === longAsset.coin)) === null || _b === void 0 ? void 0 : _b.position;
|
|
6776
|
+
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;
|
|
6777
|
+
const mappedPositionAssets = calculatePositionAsset(longAsset, currentPrice, totalInitialPositionSize, leverage, metadata, true);
|
|
7053
6778
|
mappedPosition.entryPositionValue +=
|
|
7054
6779
|
mappedPositionAssets.entryPositionValue;
|
|
7055
6780
|
mappedPosition.unrealizedPnl += mappedPositionAssets.unrealizedPnl;
|
|
@@ -7060,11 +6785,12 @@ const buildPositionValue = (rawPositions, clearinghouseState, allMids) => {
|
|
|
7060
6785
|
return mappedPositionAssets;
|
|
7061
6786
|
});
|
|
7062
6787
|
mappedPosition.shortAssets = position.shortAssets.map((shortAsset) => {
|
|
7063
|
-
var _a, _b, _c;
|
|
7064
|
-
const
|
|
7065
|
-
const
|
|
7066
|
-
const
|
|
7067
|
-
const
|
|
6788
|
+
var _a, _b, _c, _d;
|
|
6789
|
+
const metadata = getAssetByName(shortAsset.coin);
|
|
6790
|
+
const currentPrice = (_a = metadata === null || metadata === void 0 ? void 0 : metadata.currentPrice) !== null && _a !== void 0 ? _a : 0;
|
|
6791
|
+
const assetState = (_b = clearinghouseState.assetPositions.find((ap) => ap.position.coin === shortAsset.coin)) === null || _b === void 0 ? void 0 : _b.position;
|
|
6792
|
+
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;
|
|
6793
|
+
const mappedPositionAssets = calculatePositionAsset(shortAsset, currentPrice, totalInitialPositionSize, leverage, metadata, false);
|
|
7068
6794
|
mappedPosition.entryPositionValue +=
|
|
7069
6795
|
mappedPositionAssets.entryPositionValue;
|
|
7070
6796
|
mappedPosition.unrealizedPnl += mappedPositionAssets.unrealizedPnl;
|
|
@@ -7079,8 +6805,8 @@ const buildPositionValue = (rawPositions, clearinghouseState, allMids) => {
|
|
|
7079
6805
|
if (position.longAssets.length === 1 && position.shortAssets.length === 1) {
|
|
7080
6806
|
const long = position.longAssets[0];
|
|
7081
6807
|
const short = position.shortAssets[0];
|
|
7082
|
-
const longMark =
|
|
7083
|
-
const shortMark =
|
|
6808
|
+
const longMark = (_b = (_a = getAssetByName(long.coin)) === null || _a === void 0 ? void 0 : _a.currentPrice) !== null && _b !== void 0 ? _b : 0;
|
|
6809
|
+
const shortMark = (_d = (_c = getAssetByName(short.coin)) === null || _c === void 0 ? void 0 : _c.currentPrice) !== null && _d !== void 0 ? _d : 0;
|
|
7084
6810
|
if (long.size > 0 && short.size > 0) {
|
|
7085
6811
|
mappedPosition.entryPriceRatio = long.entryPrice / short.entryPrice;
|
|
7086
6812
|
mappedPosition.markPriceRatio = longMark / shortMark;
|
|
@@ -7096,13 +6822,13 @@ const buildPositionValue = (rawPositions, clearinghouseState, allMids) => {
|
|
|
7096
6822
|
}
|
|
7097
6823
|
if (position.longAssets.length === 1 && position.shortAssets.length === 0) {
|
|
7098
6824
|
const long = position.longAssets[0];
|
|
7099
|
-
const longMark =
|
|
6825
|
+
const longMark = (_f = (_e = getAssetByName(long.coin)) === null || _e === void 0 ? void 0 : _e.currentPrice) !== null && _f !== void 0 ? _f : 0;
|
|
7100
6826
|
mappedPosition.entryPriceRatio = long.entryPrice;
|
|
7101
6827
|
mappedPosition.markPriceRatio = longMark;
|
|
7102
6828
|
}
|
|
7103
6829
|
if (position.longAssets.length === 0 && position.shortAssets.length === 1) {
|
|
7104
6830
|
const short = position.shortAssets[0];
|
|
7105
|
-
const shortMark =
|
|
6831
|
+
const shortMark = (_h = (_g = getAssetByName(short.coin)) === null || _g === void 0 ? void 0 : _g.currentPrice) !== null && _h !== void 0 ? _h : 0;
|
|
7106
6832
|
mappedPosition.entryPriceRatio = short.entryPrice;
|
|
7107
6833
|
mappedPosition.markPriceRatio = shortMark;
|
|
7108
6834
|
}
|
|
@@ -7112,93 +6838,14 @@ const buildPositionValue = (rawPositions, clearinghouseState, allMids) => {
|
|
|
7112
6838
|
});
|
|
7113
6839
|
};
|
|
7114
6840
|
|
|
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
6841
|
function usePosition() {
|
|
7194
6842
|
const context = useContext(PearHyperliquidContext);
|
|
7195
6843
|
if (!context) {
|
|
7196
6844
|
throw new Error('usePosition must be used within a PearHyperliquidProvider');
|
|
7197
6845
|
}
|
|
7198
6846
|
const { apiBaseUrl, isConnected } = context;
|
|
7199
|
-
const hip3Assets = useHyperliquidData((s) => s.hip3Assets);
|
|
7200
6847
|
const createPosition$1 = async (payload) => {
|
|
7201
|
-
return createPosition(apiBaseUrl, payload
|
|
6848
|
+
return createPosition(apiBaseUrl, payload);
|
|
7202
6849
|
};
|
|
7203
6850
|
const updateRiskParameters$1 = async (positionId, payload) => {
|
|
7204
6851
|
return updateRiskParameters(apiBaseUrl, positionId, payload);
|
|
@@ -7213,7 +6860,7 @@ function usePosition() {
|
|
|
7213
6860
|
return adjustPosition(apiBaseUrl, positionId, payload);
|
|
7214
6861
|
};
|
|
7215
6862
|
const adjustAdvancePosition$1 = async (positionId, payload) => {
|
|
7216
|
-
return adjustAdvancePosition(apiBaseUrl, positionId, payload
|
|
6863
|
+
return adjustAdvancePosition(apiBaseUrl, positionId, payload);
|
|
7217
6864
|
};
|
|
7218
6865
|
const updateLeverage$1 = async (positionId, leverage) => {
|
|
7219
6866
|
return updateLeverage(apiBaseUrl, positionId, { leverage });
|
|
@@ -7221,22 +6868,18 @@ function usePosition() {
|
|
|
7221
6868
|
// Open positions using WS data, with derived values
|
|
7222
6869
|
const userOpenPositions = useUserData((state) => state.rawOpenPositions);
|
|
7223
6870
|
const aggregatedClearingHouseState = useHyperliquidData((state) => state.aggregatedClearingHouseState);
|
|
7224
|
-
const
|
|
7225
|
-
const
|
|
6871
|
+
const tokenMetadata = useHyperliquidData((state) => state.tokenMetadata);
|
|
6872
|
+
const { getAssetByName } = useMarket();
|
|
7226
6873
|
const isLoading = useMemo(() => {
|
|
7227
6874
|
return userOpenPositions === null && isConnected;
|
|
7228
6875
|
}, [userOpenPositions, isConnected]);
|
|
7229
6876
|
const openPositions = useMemo(() => {
|
|
7230
|
-
if (!userOpenPositions ||
|
|
6877
|
+
if (!userOpenPositions ||
|
|
6878
|
+
!aggregatedClearingHouseState ||
|
|
6879
|
+
Object.keys(tokenMetadata).length === 0)
|
|
7231
6880
|
return null;
|
|
7232
|
-
|
|
7233
|
-
|
|
7234
|
-
}, [
|
|
7235
|
-
userOpenPositions,
|
|
7236
|
-
aggregatedClearingHouseState,
|
|
7237
|
-
allMids,
|
|
7238
|
-
allPerpMetaAssets,
|
|
7239
|
-
]);
|
|
6881
|
+
return buildPositionValue(userOpenPositions, aggregatedClearingHouseState, getAssetByName);
|
|
6882
|
+
}, [userOpenPositions, aggregatedClearingHouseState, tokenMetadata, getAssetByName]);
|
|
7240
6883
|
return {
|
|
7241
6884
|
createPosition: createPosition$1,
|
|
7242
6885
|
updateRiskParameters: updateRiskParameters$1,
|
|
@@ -7319,98 +6962,14 @@ async function executeSpotOrder(baseUrl, payload) {
|
|
|
7319
6962
|
}
|
|
7320
6963
|
}
|
|
7321
6964
|
|
|
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
6965
|
function useOrders() {
|
|
7407
6966
|
const context = useContext(PearHyperliquidContext);
|
|
7408
6967
|
if (!context)
|
|
7409
6968
|
throw new Error('useOrders must be used within a PearHyperliquidProvider');
|
|
7410
6969
|
const { apiBaseUrl } = context;
|
|
7411
6970
|
const openOrders = useUserData((state) => state.openOrders);
|
|
7412
|
-
const allPerpMetaAssets = useHyperliquidData((state) => state.allPerpMetaAssets);
|
|
7413
6971
|
const isLoading = useMemo(() => openOrders === null && context.isConnected, [openOrders, context.isConnected]);
|
|
6972
|
+
const { getAssetByName } = useMarket();
|
|
7414
6973
|
const { openPositions } = usePosition();
|
|
7415
6974
|
const positionsById = useMemo(() => {
|
|
7416
6975
|
const map = new Map();
|
|
@@ -7423,22 +6982,26 @@ function useOrders() {
|
|
|
7423
6982
|
const enrichedOpenOrders = useMemo(() => {
|
|
7424
6983
|
if (!openOrders)
|
|
7425
6984
|
return null;
|
|
6985
|
+
const mapOrderAssets = (assets) => assets.map((asset) => ({
|
|
6986
|
+
...asset,
|
|
6987
|
+
metadata: getAssetByName(asset.asset),
|
|
6988
|
+
}));
|
|
7426
6989
|
return openOrders.map((ord) => {
|
|
7427
|
-
var _a, _b, _c, _d, _e;
|
|
6990
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
7428
6991
|
const isTpSl = ord.orderType === 'TP' || ord.orderType === 'SL';
|
|
7429
6992
|
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
6993
|
const pos = positionsById.get((_e = ord.positionId) !== null && _e !== void 0 ? _e : '');
|
|
7431
6994
|
let enrichedOrd = {
|
|
7432
6995
|
...ord,
|
|
7433
|
-
longAssets:
|
|
7434
|
-
shortAssets:
|
|
6996
|
+
longAssets: mapOrderAssets((_f = ord.longAssets) !== null && _f !== void 0 ? _f : []),
|
|
6997
|
+
shortAssets: mapOrderAssets((_g = ord.shortAssets) !== null && _g !== void 0 ? _g : []),
|
|
7435
6998
|
};
|
|
6999
|
+
// For TP/SL orders without assets, derive them from the position
|
|
7436
7000
|
if (isTpSl && !hasAssets && pos) {
|
|
7437
7001
|
const mapAssets = (arr) => arr.map((a) => ({
|
|
7438
7002
|
asset: a.coin,
|
|
7439
7003
|
weight: a.initialWeight,
|
|
7440
|
-
|
|
7441
|
-
collateralToken: a.collateralToken,
|
|
7004
|
+
metadata: getAssetByName(a.coin),
|
|
7442
7005
|
}));
|
|
7443
7006
|
enrichedOrd = {
|
|
7444
7007
|
...enrichedOrd,
|
|
@@ -7448,7 +7011,7 @@ function useOrders() {
|
|
|
7448
7011
|
}
|
|
7449
7012
|
return enrichedOrd;
|
|
7450
7013
|
});
|
|
7451
|
-
}, [openOrders, positionsById,
|
|
7014
|
+
}, [openOrders, positionsById, getAssetByName]);
|
|
7452
7015
|
const adjustOrder$1 = async (orderId, payload) => {
|
|
7453
7016
|
return adjustOrder(apiBaseUrl, orderId, payload);
|
|
7454
7017
|
};
|
|
@@ -7506,108 +7069,27 @@ function useSpotOrder() {
|
|
|
7506
7069
|
};
|
|
7507
7070
|
}
|
|
7508
7071
|
|
|
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
7072
|
function useTwap() {
|
|
7601
7073
|
const twapDetails = useUserData((state) => state.twapDetails);
|
|
7602
|
-
const allPerpMetaAssets = useHyperliquidData((state) => state.allPerpMetaAssets);
|
|
7603
7074
|
const context = useContext(PearHyperliquidContext);
|
|
7604
7075
|
if (!context)
|
|
7605
7076
|
throw new Error('useTwap must be used within a PearHyperliquidProvider');
|
|
7606
7077
|
const { apiBaseUrl } = context;
|
|
7078
|
+
const { getAssetByName } = useMarket();
|
|
7607
7079
|
const orders = useMemo(() => {
|
|
7608
|
-
const
|
|
7609
|
-
|
|
7610
|
-
|
|
7080
|
+
const mapAssets = (assets) => assets.map((asset) => ({
|
|
7081
|
+
...asset,
|
|
7082
|
+
metadata: getAssetByName(asset.asset),
|
|
7083
|
+
}));
|
|
7084
|
+
return (twapDetails !== null && twapDetails !== void 0 ? twapDetails : []).map((order) => {
|
|
7085
|
+
var _a, _b;
|
|
7086
|
+
return ({
|
|
7087
|
+
...order,
|
|
7088
|
+
longAssets: mapAssets((_a = order.longAssets) !== null && _a !== void 0 ? _a : []),
|
|
7089
|
+
shortAssets: mapAssets((_b = order.shortAssets) !== null && _b !== void 0 ? _b : []),
|
|
7090
|
+
});
|
|
7091
|
+
});
|
|
7092
|
+
}, [twapDetails, getAssetByName]);
|
|
7611
7093
|
const cancelTwap$1 = async (orderId) => {
|
|
7612
7094
|
return cancelTwap(apiBaseUrl, orderId);
|
|
7613
7095
|
};
|
|
@@ -7690,62 +7172,29 @@ function useNotifications() {
|
|
|
7690
7172
|
};
|
|
7691
7173
|
}
|
|
7692
7174
|
|
|
7693
|
-
//
|
|
7694
|
-
function
|
|
7695
|
-
|
|
7696
|
-
|
|
7697
|
-
|
|
7698
|
-
|
|
7699
|
-
|
|
7700
|
-
|
|
7701
|
-
|
|
7702
|
-
|
|
7703
|
-
|
|
7704
|
-
|
|
7705
|
-
|
|
7706
|
-
|
|
7707
|
-
//
|
|
7708
|
-
|
|
7709
|
-
|
|
7710
|
-
|
|
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
|
-
}
|
|
7175
|
+
// Convert a basket item to the expected type
|
|
7176
|
+
function enrichBasketItem(item) {
|
|
7177
|
+
const enrichedLongs = item.longAssets.map((a) => ({
|
|
7178
|
+
...a,
|
|
7179
|
+
}));
|
|
7180
|
+
const enrichedShorts = item.shortAssets.map((a) => ({
|
|
7181
|
+
...a,
|
|
7182
|
+
}));
|
|
7183
|
+
// // Determine collateral type
|
|
7184
|
+
// const allAssets = [...enrichedLongs, ...enrichedShorts];
|
|
7185
|
+
// const hasUsdc = allAssets.some((a) => a.collateralToken === 'USDC');
|
|
7186
|
+
// const hasUsdh = allAssets.some((a) => a.collateralToken === 'USDH');
|
|
7187
|
+
// let collateralType: 'USDC' | 'USDH' | 'MIXED' = 'USDC';
|
|
7188
|
+
// if (hasUsdc && hasUsdh) {
|
|
7189
|
+
// collateralType = 'MIXED';
|
|
7190
|
+
// } else if (hasUsdh) {
|
|
7191
|
+
// collateralType = 'USDH';
|
|
7192
|
+
// }
|
|
7744
7193
|
return {
|
|
7745
7194
|
...item,
|
|
7746
7195
|
longAssets: enrichedLongs,
|
|
7747
7196
|
shortAssets: enrichedShorts,
|
|
7748
|
-
collateralType,
|
|
7197
|
+
collateralType: 'USDC', //TODO: change
|
|
7749
7198
|
};
|
|
7750
7199
|
}
|
|
7751
7200
|
/**
|
|
@@ -7774,86 +7223,61 @@ function filterByCollateral(baskets, filter) {
|
|
|
7774
7223
|
const useMarketDataPayload = () => {
|
|
7775
7224
|
return useMarketData((s) => s.marketData);
|
|
7776
7225
|
};
|
|
7777
|
-
//
|
|
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)
|
|
7226
|
+
// Active baskets
|
|
7786
7227
|
const useActiveBaskets = (collateralFilter) => {
|
|
7787
7228
|
const data = useMarketDataPayload();
|
|
7788
|
-
const perpMetaAssets = usePerpMetaAssets();
|
|
7789
7229
|
return useMemo(() => {
|
|
7790
7230
|
if (!(data === null || data === void 0 ? void 0 : data.active))
|
|
7791
7231
|
return [];
|
|
7792
|
-
const enriched = data.active.map((item) => enrichBasketItem(item
|
|
7232
|
+
const enriched = data.active.map((item) => enrichBasketItem(item));
|
|
7793
7233
|
return filterByCollateral(enriched, collateralFilter);
|
|
7794
|
-
}, [data,
|
|
7234
|
+
}, [data, collateralFilter]);
|
|
7795
7235
|
};
|
|
7796
|
-
// Top gainers
|
|
7236
|
+
// Top gainers
|
|
7797
7237
|
const useTopGainers = (limit, collateralFilter) => {
|
|
7798
7238
|
const data = useMarketDataPayload();
|
|
7799
|
-
const perpMetaAssets = usePerpMetaAssets();
|
|
7800
7239
|
return useMemo(() => {
|
|
7801
7240
|
var _a;
|
|
7802
7241
|
const list = (_a = data === null || data === void 0 ? void 0 : data.topGainers) !== null && _a !== void 0 ? _a : [];
|
|
7803
7242
|
const limited = typeof limit === 'number' ? list.slice(0, Math.max(0, limit)) : list;
|
|
7804
|
-
const enriched = limited.map((item) => enrichBasketItem(item
|
|
7243
|
+
const enriched = limited.map((item) => enrichBasketItem(item));
|
|
7805
7244
|
return filterByCollateral(enriched, collateralFilter);
|
|
7806
|
-
}, [data,
|
|
7245
|
+
}, [data, limit, collateralFilter]);
|
|
7807
7246
|
};
|
|
7808
|
-
// Top losers
|
|
7247
|
+
// Top losers
|
|
7809
7248
|
const useTopLosers = (limit, collateralFilter) => {
|
|
7810
7249
|
const data = useMarketDataPayload();
|
|
7811
|
-
const perpMetaAssets = usePerpMetaAssets();
|
|
7812
7250
|
return useMemo(() => {
|
|
7813
7251
|
var _a;
|
|
7814
7252
|
const list = (_a = data === null || data === void 0 ? void 0 : data.topLosers) !== null && _a !== void 0 ? _a : [];
|
|
7815
7253
|
const limited = typeof limit === 'number' ? list.slice(0, Math.max(0, limit)) : list;
|
|
7816
|
-
const enriched = limited.map((item) => enrichBasketItem(item
|
|
7254
|
+
const enriched = limited.map((item) => enrichBasketItem(item));
|
|
7817
7255
|
return filterByCollateral(enriched, collateralFilter);
|
|
7818
|
-
}, [data,
|
|
7256
|
+
}, [data, limit, collateralFilter]);
|
|
7819
7257
|
};
|
|
7820
|
-
// Highlighted baskets
|
|
7258
|
+
// Highlighted baskets
|
|
7821
7259
|
const useHighlightedBaskets = (collateralFilter) => {
|
|
7822
7260
|
const data = useMarketDataPayload();
|
|
7823
|
-
const perpMetaAssets = usePerpMetaAssets();
|
|
7824
7261
|
return useMemo(() => {
|
|
7825
7262
|
if (!(data === null || data === void 0 ? void 0 : data.highlighted))
|
|
7826
7263
|
return [];
|
|
7827
|
-
const enriched = data.highlighted.map((item) => enrichBasketItem(item
|
|
7264
|
+
const enriched = data.highlighted.map((item) => enrichBasketItem(item));
|
|
7828
7265
|
return filterByCollateral(enriched, collateralFilter);
|
|
7829
|
-
}, [data,
|
|
7266
|
+
}, [data, collateralFilter]);
|
|
7830
7267
|
};
|
|
7831
|
-
// Watchlist baskets
|
|
7268
|
+
// Watchlist baskets
|
|
7832
7269
|
const useWatchlistBaskets = (collateralFilter) => {
|
|
7833
7270
|
const data = useMarketDataPayload();
|
|
7834
|
-
const perpMetaAssets = usePerpMetaAssets();
|
|
7835
7271
|
return useMemo(() => {
|
|
7836
7272
|
if (!(data === null || data === void 0 ? void 0 : data.watchlist))
|
|
7837
7273
|
return [];
|
|
7838
|
-
const enriched = data.watchlist.map((item) => enrichBasketItem(item
|
|
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));
|
|
7274
|
+
const enriched = data.watchlist.map((item) => enrichBasketItem(item));
|
|
7850
7275
|
return filterByCollateral(enriched, collateralFilter);
|
|
7851
|
-
}, [
|
|
7276
|
+
}, [data, collateralFilter]);
|
|
7852
7277
|
};
|
|
7853
7278
|
// Find a basket by its exact asset composition (order-insensitive)
|
|
7854
7279
|
const useFindBasket = (longs, shorts) => {
|
|
7855
7280
|
const data = useMarketDataPayload();
|
|
7856
|
-
const perpMetaAssets = usePerpMetaAssets();
|
|
7857
7281
|
return useMemo(() => {
|
|
7858
7282
|
if (!data)
|
|
7859
7283
|
return undefined;
|
|
@@ -7871,18 +7295,17 @@ const useFindBasket = (longs, shorts) => {
|
|
|
7871
7295
|
normalize(item.shortAssets) === sKey;
|
|
7872
7296
|
const found = data.active.find(match) || data.highlighted.find(match);
|
|
7873
7297
|
return found
|
|
7874
|
-
? enrichBasketItem(found
|
|
7298
|
+
? enrichBasketItem(found)
|
|
7875
7299
|
: undefined;
|
|
7876
|
-
}, [data, longs, shorts
|
|
7300
|
+
}, [data, longs, shorts]);
|
|
7877
7301
|
};
|
|
7878
7302
|
|
|
7879
|
-
async function toggleWatchlist(baseUrl, longAssets, shortAssets
|
|
7303
|
+
async function toggleWatchlist(baseUrl, longAssets, shortAssets) {
|
|
7880
7304
|
const url = joinUrl(baseUrl, '/watchlist');
|
|
7881
|
-
const mapAssets = (arr) => arr.map((a) => ({ ...a, asset: toBackendSymbol(a.asset, hip3Assets) }));
|
|
7882
7305
|
try {
|
|
7883
7306
|
const response = await apiClient.post(url, {
|
|
7884
|
-
longAssets
|
|
7885
|
-
shortAssets
|
|
7307
|
+
longAssets,
|
|
7308
|
+
shortAssets,
|
|
7886
7309
|
}, { headers: { 'Content-Type': 'application/json' } });
|
|
7887
7310
|
return {
|
|
7888
7311
|
data: response.data,
|
|
@@ -7900,11 +7323,10 @@ function useWatchlist() {
|
|
|
7900
7323
|
if (!context)
|
|
7901
7324
|
throw new Error('useWatchlist must be used within a PearHyperliquidProvider');
|
|
7902
7325
|
const { apiBaseUrl, isConnected } = context;
|
|
7903
|
-
const hip3Assets = useHyperliquidData((s) => s.hip3Assets);
|
|
7904
7326
|
const marketData = useMarketDataPayload();
|
|
7905
7327
|
const isLoading = useMemo(() => !marketData && isConnected, [marketData, isConnected]);
|
|
7906
7328
|
const toggle = async (longAssets, shortAssets) => {
|
|
7907
|
-
const resp = await toggleWatchlist(apiBaseUrl, longAssets, shortAssets
|
|
7329
|
+
const resp = await toggleWatchlist(apiBaseUrl, longAssets, shortAssets);
|
|
7908
7330
|
// Server will push updated market-data over WS; nothing to set here
|
|
7909
7331
|
return resp;
|
|
7910
7332
|
};
|
|
@@ -8162,7 +7584,6 @@ const useAllUserBalances = () => {
|
|
|
8162
7584
|
const spotState = useUserData((state) => state.spotState);
|
|
8163
7585
|
const aggregatedClearingHouseState = useHyperliquidData((state) => state.aggregatedClearingHouseState);
|
|
8164
7586
|
const rawClearinghouseStates = useHyperliquidData((state) => state.rawClearinghouseStates);
|
|
8165
|
-
const activeAssetData = useHyperliquidData((state) => state.activeAssetData);
|
|
8166
7587
|
const { longTokensMetadata, shortTokensMetadata } = useTokenSelectionMetadata();
|
|
8167
7588
|
return useMemo(() => {
|
|
8168
7589
|
const isLoading = !spotState || !aggregatedClearingHouseState;
|
|
@@ -8185,39 +7606,50 @@ const useAllUserBalances = () => {
|
|
|
8185
7606
|
}
|
|
8186
7607
|
}
|
|
8187
7608
|
}
|
|
7609
|
+
// Get available to trade from tokenMetadata for both USDC and USDH markets
|
|
7610
|
+
let availableToTradeUsdcFromAsset = 0;
|
|
8188
7611
|
let availableToTradeUsdhFromAsset = 0;
|
|
8189
|
-
//
|
|
7612
|
+
// Token metadata only contains availableToTrade for SELECTED tokens (user's long and short Tokens)
|
|
8190
7613
|
// 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
7614
|
// so intead, we rely on rawClearinghouseStates which provides market-specific data
|
|
8192
|
-
|
|
8193
|
-
|
|
8194
|
-
|
|
8195
|
-
|
|
8196
|
-
|
|
8197
|
-
|
|
8198
|
-
|
|
8199
|
-
|
|
8200
|
-
|
|
8201
|
-
|
|
8202
|
-
|
|
8203
|
-
|
|
8204
|
-
|
|
8205
|
-
|
|
8206
|
-
|
|
8207
|
-
|
|
8208
|
-
|
|
8209
|
-
|
|
8210
|
-
|
|
8211
|
-
|
|
8212
|
-
|
|
8213
|
-
|
|
8214
|
-
|
|
8215
|
-
|
|
7615
|
+
const selectedMetadataEntries = [
|
|
7616
|
+
...Object.entries(longTokensMetadata),
|
|
7617
|
+
...Object.entries(shortTokensMetadata),
|
|
7618
|
+
];
|
|
7619
|
+
selectedMetadataEntries.forEach(([symbol, metadata]) => {
|
|
7620
|
+
var _a;
|
|
7621
|
+
const availableStr = (_a = metadata === null || metadata === void 0 ? void 0 : metadata.availableToTrade) === null || _a === void 0 ? void 0 : _a[0];
|
|
7622
|
+
if (!availableStr)
|
|
7623
|
+
return;
|
|
7624
|
+
const availableValue = truncateToTwoDecimals(parseFloat(availableStr || '0'));
|
|
7625
|
+
if ((metadata === null || metadata === void 0 ? void 0 : metadata.collateralToken) === 'USDH') {
|
|
7626
|
+
availableToTradeUsdhFromAsset = Math.max(availableToTradeUsdhFromAsset, availableValue);
|
|
7627
|
+
return;
|
|
7628
|
+
}
|
|
7629
|
+
if ((metadata === null || metadata === void 0 ? void 0 : metadata.collateralToken) === 'USDC') {
|
|
7630
|
+
availableToTradeUsdcFromAsset = Math.max(availableToTradeUsdcFromAsset, availableValue);
|
|
7631
|
+
return;
|
|
7632
|
+
}
|
|
7633
|
+
if (symbol.includes(':')) {
|
|
7634
|
+
const prefix = symbol.split(':')[0];
|
|
7635
|
+
if (prefix === 'xyz') {
|
|
7636
|
+
availableToTradeUsdcFromAsset = Math.max(availableToTradeUsdcFromAsset, availableValue);
|
|
7637
|
+
}
|
|
7638
|
+
else {
|
|
7639
|
+
availableToTradeUsdhFromAsset = Math.max(availableToTradeUsdhFromAsset, availableValue);
|
|
7640
|
+
}
|
|
7641
|
+
return;
|
|
7642
|
+
}
|
|
7643
|
+
availableToTradeUsdcFromAsset = Math.max(availableToTradeUsdcFromAsset, availableValue);
|
|
7644
|
+
});
|
|
8216
7645
|
// Calculate USDC available to trade
|
|
8217
7646
|
// Priority 1: Use value from activeAssetData if available (> 0)
|
|
8218
7647
|
// Priority 2: Calculate from USDC-specific clearinghouseState (empty prefix)
|
|
8219
7648
|
let availableToTradeUsdcValue = undefined;
|
|
8220
|
-
if (
|
|
7649
|
+
if (availableToTradeUsdcFromAsset > 0) {
|
|
7650
|
+
availableToTradeUsdcValue = availableToTradeUsdcFromAsset;
|
|
7651
|
+
}
|
|
7652
|
+
else if (rawClearinghouseStates) {
|
|
8221
7653
|
// Find USDC market (empty prefix)
|
|
8222
7654
|
const usdcMarket = rawClearinghouseStates.find(([prefix]) => prefix === '');
|
|
8223
7655
|
const usdcState = usdcMarket === null || usdcMarket === void 0 ? void 0 : usdcMarket[1];
|
|
@@ -8245,7 +7677,6 @@ const useAllUserBalances = () => {
|
|
|
8245
7677
|
spotState,
|
|
8246
7678
|
aggregatedClearingHouseState,
|
|
8247
7679
|
rawClearinghouseStates,
|
|
8248
|
-
activeAssetData,
|
|
8249
7680
|
longTokensMetadata,
|
|
8250
7681
|
shortTokensMetadata,
|
|
8251
7682
|
]);
|
|
@@ -8347,7 +7778,7 @@ function useHyperliquidUserFills(options) {
|
|
|
8347
7778
|
if (!userState.accountSummary)
|
|
8348
7779
|
return;
|
|
8349
7780
|
const clearinghouseState = useHyperliquidData.getState().aggregatedClearingHouseState;
|
|
8350
|
-
if (!
|
|
7781
|
+
if (!clearinghouseState)
|
|
8351
7782
|
return;
|
|
8352
7783
|
setIsSyncing(true);
|
|
8353
7784
|
setError(null);
|
|
@@ -8392,9 +7823,6 @@ const PearHyperliquidProvider = ({ children, apiBaseUrl = 'https://hl-ui.pearpro
|
|
|
8392
7823
|
const setAddress = useUserData((s) => s.setAddress);
|
|
8393
7824
|
const perpsMetaAssets = useHyperliquidData((state) => state.perpMetaAssets);
|
|
8394
7825
|
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
7826
|
const websocketsEnabled = useMemo(() => Array.isArray(perpsMetaAssets) && perpsMetaAssets.length > 0, [perpsMetaAssets]);
|
|
8399
7827
|
const { handleUserFillsEvent } = useHyperliquidUserFills({
|
|
8400
7828
|
baseUrl: apiBaseUrl,
|
|
@@ -8415,106 +7843,34 @@ const PearHyperliquidProvider = ({ children, apiBaseUrl = 'https://hl-ui.pearpro
|
|
|
8415
7843
|
if (perpsMetaAssets === null) {
|
|
8416
7844
|
fetchAllPerpMetas()
|
|
8417
7845
|
.then((res) => {
|
|
8418
|
-
const
|
|
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();
|
|
7846
|
+
const allPerpMetas = [];
|
|
8425
7847
|
res.data.forEach((item) => {
|
|
8426
|
-
|
|
7848
|
+
// Only include USDC and USDH collateral tokens
|
|
7849
|
+
if (item.collateralToken !== 360 && item.collateralToken !== 0) {
|
|
7850
|
+
return;
|
|
7851
|
+
}
|
|
7852
|
+
var collateralToken;
|
|
7853
|
+
if (item.collateralToken === 360) {
|
|
7854
|
+
collateralToken = 'USDH';
|
|
7855
|
+
}
|
|
7856
|
+
if (item.collateralToken === 0) {
|
|
7857
|
+
collateralToken = 'USDC';
|
|
7858
|
+
}
|
|
8427
7859
|
item.universe.forEach((asset) => {
|
|
8428
|
-
|
|
8429
|
-
|
|
8430
|
-
|
|
8431
|
-
|
|
8432
|
-
|
|
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
|
-
}
|
|
7860
|
+
const assetWithMeta = {
|
|
7861
|
+
...asset,
|
|
7862
|
+
collateralToken,
|
|
7863
|
+
};
|
|
7864
|
+
allPerpMetas.push(assetWithMeta);
|
|
8475
7865
|
});
|
|
8476
7866
|
});
|
|
8477
|
-
|
|
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);
|
|
8504
|
-
});
|
|
8505
|
-
setHip3Assets(assetToMarkets);
|
|
8506
|
-
setHip3MarketPrefixes(marketPrefixes);
|
|
8507
|
-
setPerpMetaAssets(cleanedPerpMetas);
|
|
8508
|
-
setAllPerpMetaAssets(allPerpMetas);
|
|
7867
|
+
setPerpMetaAssets(allPerpMetas);
|
|
8509
7868
|
})
|
|
8510
7869
|
.catch(() => { });
|
|
8511
7870
|
}
|
|
8512
7871
|
}, [
|
|
8513
7872
|
perpsMetaAssets,
|
|
8514
7873
|
setPerpMetaAssets,
|
|
8515
|
-
setAllPerpMetaAssets,
|
|
8516
|
-
setHip3Assets,
|
|
8517
|
-
setHip3MarketPrefixes,
|
|
8518
7874
|
]);
|
|
8519
7875
|
const contextValue = useMemo(() => ({
|
|
8520
7876
|
// Config
|
|
@@ -8799,4 +8155,4 @@ function getOrderTrailingInfo(order) {
|
|
|
8799
8155
|
return undefined;
|
|
8800
8156
|
}
|
|
8801
8157
|
|
|
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,
|
|
8158
|
+
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 };
|