@pear-protocol/hyperliquid-sdk 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/clients/positions.d.ts +1 -44
- package/dist/hooks/useAgentWallet.d.ts +1 -1
- package/dist/hooks/useAllUserBalances.d.ts +20 -6
- package/dist/hooks/useMarketData.d.ts +14 -8
- package/dist/hooks/usePosition.d.ts +2 -2
- package/dist/hooks/useTokenSelectionMetadata.d.ts +1 -1
- package/dist/hooks/useUserSelection.d.ts +16 -1
- package/dist/index.d.ts +203 -134
- package/dist/index.js +265 -214
- package/dist/store/tokenSelectionMetadataStore.d.ts +2 -3
- package/dist/types.d.ts +51 -3
- package/dist/utils/position-validator.d.ts +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1453,8 +1453,9 @@ const getAssetByName = (tokenMetadata, symbol) => {
|
|
|
1453
1453
|
* Hook to access webData
|
|
1454
1454
|
*/
|
|
1455
1455
|
const useMarket = () => {
|
|
1456
|
+
const supportedMarkets = ['USDT', 'USDT0', 'USDC', 'USDH'];
|
|
1456
1457
|
const tokenMetadata = useHyperliquidData((state) => state.tokenMetadata);
|
|
1457
|
-
const allTokenMetadata = useMemo(() => Object.values(tokenMetadata).filter((metadata) => Boolean(metadata)), [tokenMetadata]);
|
|
1458
|
+
const allTokenMetadata = useMemo(() => Object.values(tokenMetadata).filter((metadata) => Boolean(metadata)).filter((token) => { var _a; return supportedMarkets.includes((_a = token.collateralToken) !== null && _a !== void 0 ? _a : ''); }), [tokenMetadata]);
|
|
1458
1459
|
const getAssetByName$1 = useCallback((symbol) => getAssetByName(tokenMetadata, symbol), [tokenMetadata]);
|
|
1459
1460
|
return { allTokenMetadata, getAssetByName: getAssetByName$1 };
|
|
1460
1461
|
};
|
|
@@ -1513,7 +1514,36 @@ const useOpenOrders = () => {
|
|
|
1513
1514
|
};
|
|
1514
1515
|
|
|
1515
1516
|
const useUserSelection = () => {
|
|
1516
|
-
|
|
1517
|
+
const longTokens = useUserSelection$1((s) => s.longTokens);
|
|
1518
|
+
const shortTokens = useUserSelection$1((s) => s.shortTokens);
|
|
1519
|
+
const candleInterval = useUserSelection$1((s) => s.candleInterval);
|
|
1520
|
+
const openTokenSelector = useUserSelection$1((s) => s.openTokenSelector);
|
|
1521
|
+
const selectorConfig = useUserSelection$1((s) => s.selectorConfig);
|
|
1522
|
+
const openConflictModal = useUserSelection$1((s) => s.openConflictModal);
|
|
1523
|
+
const setLongTokens = useUserSelection$1((s) => s.setLongTokens);
|
|
1524
|
+
const setShortTokens = useUserSelection$1((s) => s.setShortTokens);
|
|
1525
|
+
const setCandleInterval = useUserSelection$1((s) => s.setCandleInterval);
|
|
1526
|
+
const setTokenSelections = useUserSelection$1((s) => s.setTokenSelections);
|
|
1527
|
+
const setOpenTokenSelector = useUserSelection$1((s) => s.setOpenTokenSelector);
|
|
1528
|
+
const setSelectorConfig = useUserSelection$1((s) => s.setSelectorConfig);
|
|
1529
|
+
const setOpenConflictModal = useUserSelection$1((s) => s.setOpenConflictModal);
|
|
1530
|
+
const addToken = useUserSelection$1((s) => s.addToken);
|
|
1531
|
+
return {
|
|
1532
|
+
longTokens,
|
|
1533
|
+
shortTokens,
|
|
1534
|
+
candleInterval,
|
|
1535
|
+
openTokenSelector,
|
|
1536
|
+
selectorConfig,
|
|
1537
|
+
openConflictModal,
|
|
1538
|
+
setLongTokens,
|
|
1539
|
+
setShortTokens,
|
|
1540
|
+
setCandleInterval,
|
|
1541
|
+
setTokenSelections,
|
|
1542
|
+
setOpenTokenSelector,
|
|
1543
|
+
setSelectorConfig,
|
|
1544
|
+
setOpenConflictModal,
|
|
1545
|
+
addToken,
|
|
1546
|
+
};
|
|
1517
1547
|
};
|
|
1518
1548
|
|
|
1519
1549
|
const useTokenSelectionMetadataStore = create((set) => ({
|
|
@@ -1529,11 +1559,10 @@ const useTokenSelectionMetadataStore = create((set) => ({
|
|
|
1529
1559
|
volume: "0",
|
|
1530
1560
|
sumNetFunding: 0,
|
|
1531
1561
|
maxLeverage: 0,
|
|
1532
|
-
|
|
1562
|
+
minSize: {},
|
|
1533
1563
|
leverageMatched: true,
|
|
1534
|
-
recompute: ({
|
|
1564
|
+
recompute: ({ tokenMetadata, marketData, longTokens, shortTokens, }) => {
|
|
1535
1565
|
const isPriceDataReady = Object.keys(tokenMetadata).length > 0;
|
|
1536
|
-
// Get token symbols for lookups
|
|
1537
1566
|
const longSymbols = longTokens.map((t) => t.symbol);
|
|
1538
1567
|
const shortSymbols = shortTokens.map((t) => t.symbol);
|
|
1539
1568
|
// Get metadata
|
|
@@ -1656,24 +1685,37 @@ const useTokenSelectionMetadataStore = create((set) => ({
|
|
|
1656
1685
|
})();
|
|
1657
1686
|
// Max leverage (maximum across all tokens)
|
|
1658
1687
|
const maxLeverage = (() => {
|
|
1659
|
-
if (!
|
|
1688
|
+
if (!tokenMetadata)
|
|
1660
1689
|
return 0;
|
|
1661
1690
|
const allSymbols = [...longSymbols, ...shortSymbols];
|
|
1662
1691
|
if (allSymbols.length === 0)
|
|
1663
1692
|
return 0;
|
|
1664
1693
|
let maxLev = 0;
|
|
1665
1694
|
allSymbols.forEach((symbol) => {
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1695
|
+
var _a;
|
|
1696
|
+
const tokenDetail = tokenMetadata[symbol];
|
|
1697
|
+
if ((_a = tokenDetail === null || tokenDetail === void 0 ? void 0 : tokenDetail.leverage) === null || _a === void 0 ? void 0 : _a.value) {
|
|
1698
|
+
maxLev = Math.max(maxLev, tokenDetail.leverage.value);
|
|
1669
1699
|
}
|
|
1670
1700
|
});
|
|
1671
1701
|
return maxLev;
|
|
1672
1702
|
})();
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
const
|
|
1676
|
-
|
|
1703
|
+
const minSize = (() => {
|
|
1704
|
+
const allSymbols = [...longSymbols, ...shortSymbols];
|
|
1705
|
+
const collateralCounts = {};
|
|
1706
|
+
allSymbols.forEach((symbol) => {
|
|
1707
|
+
var _a;
|
|
1708
|
+
const collateralToken = (_a = tokenMetadata[symbol]) === null || _a === void 0 ? void 0 : _a.collateralToken;
|
|
1709
|
+
if (collateralToken) {
|
|
1710
|
+
collateralCounts[collateralToken] =
|
|
1711
|
+
(collateralCounts[collateralToken] || 0) + 1;
|
|
1712
|
+
}
|
|
1713
|
+
});
|
|
1714
|
+
const minSizeMap = {};
|
|
1715
|
+
Object.entries(collateralCounts).forEach(([collateral, count]) => {
|
|
1716
|
+
minSizeMap[collateral] = 11 * count;
|
|
1717
|
+
});
|
|
1718
|
+
return minSizeMap;
|
|
1677
1719
|
})();
|
|
1678
1720
|
// Whether all tokens have matching leverage
|
|
1679
1721
|
const leverageMatched = (() => {
|
|
@@ -1708,7 +1750,7 @@ const useTokenSelectionMetadataStore = create((set) => ({
|
|
|
1708
1750
|
volume,
|
|
1709
1751
|
sumNetFunding,
|
|
1710
1752
|
maxLeverage,
|
|
1711
|
-
|
|
1753
|
+
minSize,
|
|
1712
1754
|
leverageMatched,
|
|
1713
1755
|
});
|
|
1714
1756
|
},
|
|
@@ -1723,11 +1765,10 @@ const useTokenSelectionMetadata = () => {
|
|
|
1723
1765
|
const tokenMetadata = useHyperliquidData((state) => state.tokenMetadata);
|
|
1724
1766
|
const marketData = useMarketData((state) => state.marketData);
|
|
1725
1767
|
const { longTokens, shortTokens } = useUserSelection$1();
|
|
1726
|
-
const { isLoading, isPriceDataReady, longTokensMetadata, shortTokensMetadata, weightedRatio, weightedRatio24h, priceRatio, priceRatio24h, openInterest, volume, sumNetFunding, maxLeverage,
|
|
1768
|
+
const { isLoading, isPriceDataReady, longTokensMetadata, shortTokensMetadata, weightedRatio, weightedRatio24h, priceRatio, priceRatio24h, openInterest, volume, sumNetFunding, maxLeverage, minSize, leverageMatched, recompute, } = useTokenSelectionMetadataStore();
|
|
1727
1769
|
// Recompute derived metadata when inputs change
|
|
1728
1770
|
useEffect(() => {
|
|
1729
1771
|
recompute({
|
|
1730
|
-
perpMetaAssets,
|
|
1731
1772
|
tokenMetadata,
|
|
1732
1773
|
marketData: marketData || null,
|
|
1733
1774
|
longTokens,
|
|
@@ -1751,8 +1792,8 @@ const useTokenSelectionMetadata = () => {
|
|
|
1751
1792
|
volume,
|
|
1752
1793
|
sumNetFunding,
|
|
1753
1794
|
maxLeverage,
|
|
1754
|
-
minMargin,
|
|
1755
1795
|
leverageMatched,
|
|
1796
|
+
minSize,
|
|
1756
1797
|
};
|
|
1757
1798
|
};
|
|
1758
1799
|
|
|
@@ -7197,122 +7238,62 @@ function useNotifications() {
|
|
|
7197
7238
|
};
|
|
7198
7239
|
}
|
|
7199
7240
|
|
|
7200
|
-
|
|
7201
|
-
function enrichBasketItem(item) {
|
|
7202
|
-
const enrichedLongs = item.longAssets.map((a) => ({
|
|
7203
|
-
...a,
|
|
7204
|
-
}));
|
|
7205
|
-
const enrichedShorts = item.shortAssets.map((a) => ({
|
|
7206
|
-
...a,
|
|
7207
|
-
}));
|
|
7241
|
+
function enrichBasketWithMetadata(basket, tokenMetadata) {
|
|
7208
7242
|
return {
|
|
7209
|
-
...
|
|
7210
|
-
longAssets:
|
|
7211
|
-
|
|
7212
|
-
|
|
7243
|
+
...basket,
|
|
7244
|
+
longAssets: basket.longAssets.map((asset) => {
|
|
7245
|
+
var _a;
|
|
7246
|
+
return ({
|
|
7247
|
+
...asset,
|
|
7248
|
+
metadata: (_a = tokenMetadata[asset.asset]) !== null && _a !== void 0 ? _a : null,
|
|
7249
|
+
});
|
|
7250
|
+
}),
|
|
7251
|
+
shortAssets: basket.shortAssets.map((asset) => {
|
|
7252
|
+
var _a;
|
|
7253
|
+
return ({
|
|
7254
|
+
...asset,
|
|
7255
|
+
metadata: (_a = tokenMetadata[asset.asset]) !== null && _a !== void 0 ? _a : null,
|
|
7256
|
+
});
|
|
7257
|
+
}),
|
|
7213
7258
|
};
|
|
7214
7259
|
}
|
|
7215
|
-
|
|
7216
|
-
|
|
7217
|
-
* - 'USDC': Only baskets where ALL assets use USDC (collateralType === 'USDC')
|
|
7218
|
-
* - 'USDH': Only baskets where ALL assets use USDH (collateralType === 'USDH')
|
|
7219
|
-
* - 'ALL' or undefined: No filtering, returns all baskets
|
|
7220
|
-
*/
|
|
7221
|
-
function filterByCollateral(baskets, filter) {
|
|
7222
|
-
if (!filter || filter === 'ALL') {
|
|
7223
|
-
return baskets;
|
|
7224
|
-
}
|
|
7225
|
-
return baskets.filter((basket) => {
|
|
7226
|
-
if (filter === 'USDC') {
|
|
7227
|
-
// Include baskets that are purely USDC or have USDC assets
|
|
7228
|
-
return (basket.collateralType === 'USDC' || basket.collateralType === 'MIXED');
|
|
7229
|
-
}
|
|
7230
|
-
if (filter === 'USDH') {
|
|
7231
|
-
// Include baskets that are purely USDH or have USDH assets
|
|
7232
|
-
return (basket.collateralType === 'USDH' || basket.collateralType === 'MIXED');
|
|
7233
|
-
}
|
|
7234
|
-
return true;
|
|
7235
|
-
});
|
|
7260
|
+
function enrichBasketsWithMetadata(baskets, tokenMetadata) {
|
|
7261
|
+
return baskets.map((basket) => enrichBasketWithMetadata(basket, tokenMetadata));
|
|
7236
7262
|
}
|
|
7237
|
-
|
|
7238
|
-
const
|
|
7239
|
-
|
|
7240
|
-
|
|
7241
|
-
// Active baskets
|
|
7242
|
-
const useActiveBaskets = (collateralFilter) => {
|
|
7243
|
-
const data = useMarketDataPayload();
|
|
7244
|
-
return useMemo(() => {
|
|
7245
|
-
if (!(data === null || data === void 0 ? void 0 : data.active))
|
|
7246
|
-
return [];
|
|
7247
|
-
const enriched = data.active.map((item) => enrichBasketItem(item));
|
|
7248
|
-
return filterByCollateral(enriched, collateralFilter);
|
|
7249
|
-
}, [data, collateralFilter]);
|
|
7250
|
-
};
|
|
7251
|
-
// Top gainers
|
|
7252
|
-
const useTopGainers = (limit, collateralFilter) => {
|
|
7253
|
-
const data = useMarketDataPayload();
|
|
7254
|
-
return useMemo(() => {
|
|
7255
|
-
var _a;
|
|
7256
|
-
const list = (_a = data === null || data === void 0 ? void 0 : data.topGainers) !== null && _a !== void 0 ? _a : [];
|
|
7257
|
-
const limited = typeof limit === 'number' ? list.slice(0, Math.max(0, limit)) : list;
|
|
7258
|
-
const enriched = limited.map((item) => enrichBasketItem(item));
|
|
7259
|
-
return filterByCollateral(enriched, collateralFilter);
|
|
7260
|
-
}, [data, limit, collateralFilter]);
|
|
7261
|
-
};
|
|
7262
|
-
// Top losers
|
|
7263
|
-
const useTopLosers = (limit, collateralFilter) => {
|
|
7264
|
-
const data = useMarketDataPayload();
|
|
7265
|
-
return useMemo(() => {
|
|
7266
|
-
var _a;
|
|
7267
|
-
const list = (_a = data === null || data === void 0 ? void 0 : data.topLosers) !== null && _a !== void 0 ? _a : [];
|
|
7268
|
-
const limited = typeof limit === 'number' ? list.slice(0, Math.max(0, limit)) : list;
|
|
7269
|
-
const enriched = limited.map((item) => enrichBasketItem(item));
|
|
7270
|
-
return filterByCollateral(enriched, collateralFilter);
|
|
7271
|
-
}, [data, limit, collateralFilter]);
|
|
7272
|
-
};
|
|
7273
|
-
// Highlighted baskets
|
|
7274
|
-
const useHighlightedBaskets = (collateralFilter) => {
|
|
7275
|
-
const data = useMarketDataPayload();
|
|
7276
|
-
return useMemo(() => {
|
|
7277
|
-
if (!(data === null || data === void 0 ? void 0 : data.highlighted))
|
|
7278
|
-
return [];
|
|
7279
|
-
const enriched = data.highlighted.map((item) => enrichBasketItem(item));
|
|
7280
|
-
return filterByCollateral(enriched, collateralFilter);
|
|
7281
|
-
}, [data, collateralFilter]);
|
|
7282
|
-
};
|
|
7283
|
-
// Watchlist baskets
|
|
7284
|
-
const useWatchlistBaskets = (collateralFilter) => {
|
|
7285
|
-
const data = useMarketDataPayload();
|
|
7263
|
+
const useMarketDataHook = (options = {}) => {
|
|
7264
|
+
const { topGainersLimit, topLosersLimit } = options;
|
|
7265
|
+
const data = useMarketData((s) => s.marketData);
|
|
7266
|
+
const tokenMetadata = useHyperliquidData((s) => s.tokenMetadata);
|
|
7286
7267
|
return useMemo(() => {
|
|
7287
|
-
|
|
7288
|
-
|
|
7289
|
-
const
|
|
7290
|
-
|
|
7291
|
-
|
|
7292
|
-
|
|
7293
|
-
|
|
7294
|
-
|
|
7295
|
-
|
|
7296
|
-
|
|
7297
|
-
|
|
7298
|
-
|
|
7299
|
-
|
|
7300
|
-
|
|
7301
|
-
.
|
|
7302
|
-
|
|
7303
|
-
|
|
7304
|
-
|
|
7305
|
-
|
|
7306
|
-
|
|
7307
|
-
|
|
7308
|
-
|
|
7309
|
-
|
|
7310
|
-
|
|
7311
|
-
|
|
7312
|
-
|
|
7313
|
-
|
|
7314
|
-
|
|
7315
|
-
}, [data,
|
|
7268
|
+
var _a, _b, _c;
|
|
7269
|
+
const activeBaskets = enrichBasketsWithMetadata((_a = data === null || data === void 0 ? void 0 : data.active) !== null && _a !== void 0 ? _a : [], tokenMetadata);
|
|
7270
|
+
const topGainers = (() => {
|
|
7271
|
+
var _a;
|
|
7272
|
+
const list = (_a = data === null || data === void 0 ? void 0 : data.topGainers) !== null && _a !== void 0 ? _a : [];
|
|
7273
|
+
const limited = typeof topGainersLimit === 'number'
|
|
7274
|
+
? list.slice(0, Math.max(0, topGainersLimit))
|
|
7275
|
+
: list;
|
|
7276
|
+
return enrichBasketsWithMetadata(limited, tokenMetadata);
|
|
7277
|
+
})();
|
|
7278
|
+
const topLosers = (() => {
|
|
7279
|
+
var _a;
|
|
7280
|
+
const list = (_a = data === null || data === void 0 ? void 0 : data.topLosers) !== null && _a !== void 0 ? _a : [];
|
|
7281
|
+
const limited = typeof topLosersLimit === 'number'
|
|
7282
|
+
? list.slice(0, Math.max(0, topLosersLimit))
|
|
7283
|
+
: list;
|
|
7284
|
+
return enrichBasketsWithMetadata(limited, tokenMetadata);
|
|
7285
|
+
})();
|
|
7286
|
+
const highlightedBaskets = enrichBasketsWithMetadata((_b = data === null || data === void 0 ? void 0 : data.highlighted) !== null && _b !== void 0 ? _b : [], tokenMetadata);
|
|
7287
|
+
const watchlistBaskets = enrichBasketsWithMetadata((_c = data === null || data === void 0 ? void 0 : data.watchlist) !== null && _c !== void 0 ? _c : [], tokenMetadata);
|
|
7288
|
+
return {
|
|
7289
|
+
marketData: data,
|
|
7290
|
+
activeBaskets,
|
|
7291
|
+
topGainers,
|
|
7292
|
+
topLosers,
|
|
7293
|
+
highlightedBaskets,
|
|
7294
|
+
watchlistBaskets,
|
|
7295
|
+
};
|
|
7296
|
+
}, [data, tokenMetadata, topGainersLimit, topLosersLimit]);
|
|
7316
7297
|
};
|
|
7317
7298
|
|
|
7318
7299
|
async function toggleWatchlist(baseUrl, longAssets, shortAssets) {
|
|
@@ -7338,7 +7319,7 @@ function useWatchlist() {
|
|
|
7338
7319
|
if (!context)
|
|
7339
7320
|
throw new Error('useWatchlist must be used within a PearHyperliquidProvider');
|
|
7340
7321
|
const { apiBaseUrl, isConnected } = context;
|
|
7341
|
-
const marketData =
|
|
7322
|
+
const marketData = useMarketData(s => s.marketData);
|
|
7342
7323
|
const isLoading = useMemo(() => !marketData && isConnected, [marketData, isConnected]);
|
|
7343
7324
|
const toggle = async (longAssets, shortAssets) => {
|
|
7344
7325
|
const resp = await toggleWatchlist(apiBaseUrl, longAssets, shortAssets);
|
|
@@ -7597,104 +7578,174 @@ function useAuth() {
|
|
|
7597
7578
|
|
|
7598
7579
|
const useAllUserBalances = () => {
|
|
7599
7580
|
const spotState = useUserData((state) => state.spotState);
|
|
7600
|
-
const aggregatedClearingHouseState = useHyperliquidData((state) => state.aggregatedClearingHouseState);
|
|
7601
|
-
const rawClearinghouseStates = useHyperliquidData((state) => state.rawClearinghouseStates);
|
|
7602
7581
|
const { longTokensMetadata, shortTokensMetadata } = useTokenSelectionMetadata();
|
|
7603
|
-
|
|
7604
|
-
|
|
7605
|
-
|
|
7606
|
-
const
|
|
7607
|
-
|
|
7608
|
-
};
|
|
7609
|
-
|
|
7610
|
-
|
|
7611
|
-
let spotUsdhBal = undefined;
|
|
7612
|
-
if (spotState) {
|
|
7613
|
-
const balances = spotState.balances || [];
|
|
7614
|
-
for (const balance of balances) {
|
|
7582
|
+
const { longTokens, shortTokens } = useUserSelection$1();
|
|
7583
|
+
const aggregatedClearingHouseState = useHyperliquidData((state) => state.aggregatedClearingHouseState);
|
|
7584
|
+
const { spotBalances, availableToTrades, isLoading } = useMemo(() => {
|
|
7585
|
+
const isLoading = !spotState;
|
|
7586
|
+
const spotBalances = {};
|
|
7587
|
+
const availableToTrades = {};
|
|
7588
|
+
if (spotState === null || spotState === void 0 ? void 0 : spotState.balances) {
|
|
7589
|
+
for (const balance of spotState.balances) {
|
|
7615
7590
|
const total = parseFloat(balance.total || '0');
|
|
7616
|
-
|
|
7617
|
-
spotUsdcBal = truncateToTwoDecimals(total);
|
|
7618
|
-
}
|
|
7619
|
-
if (balance.coin === 'USDH') {
|
|
7620
|
-
spotUsdhBal = truncateToTwoDecimals(total);
|
|
7621
|
-
}
|
|
7591
|
+
spotBalances[balance.coin] = total;
|
|
7622
7592
|
}
|
|
7623
7593
|
}
|
|
7624
|
-
|
|
7625
|
-
|
|
7626
|
-
|
|
7627
|
-
|
|
7628
|
-
|
|
7629
|
-
|
|
7630
|
-
|
|
7631
|
-
|
|
7632
|
-
|
|
7594
|
+
const allMetadataWithSource = [
|
|
7595
|
+
...Object.values(longTokensMetadata).map((m) => ({
|
|
7596
|
+
metadata: m,
|
|
7597
|
+
isLong: true,
|
|
7598
|
+
})),
|
|
7599
|
+
...Object.values(shortTokensMetadata).map((m) => ({
|
|
7600
|
+
metadata: m,
|
|
7601
|
+
isLong: false,
|
|
7602
|
+
})),
|
|
7633
7603
|
];
|
|
7634
|
-
|
|
7635
|
-
|
|
7636
|
-
|
|
7637
|
-
|
|
7638
|
-
|
|
7639
|
-
|
|
7640
|
-
if ((
|
|
7641
|
-
|
|
7642
|
-
|
|
7643
|
-
}
|
|
7644
|
-
if ((metadata === null || metadata === void 0 ? void 0 : metadata.collateralToken) === 'USDC') {
|
|
7645
|
-
availableToTradeUsdcFromAsset = Math.max(availableToTradeUsdcFromAsset, availableValue);
|
|
7646
|
-
return;
|
|
7647
|
-
}
|
|
7648
|
-
if (symbol.includes(':')) {
|
|
7649
|
-
const prefix = symbol.split(':')[0];
|
|
7650
|
-
if (prefix === 'xyz') {
|
|
7651
|
-
availableToTradeUsdcFromAsset = Math.max(availableToTradeUsdcFromAsset, availableValue);
|
|
7652
|
-
}
|
|
7653
|
-
else {
|
|
7654
|
-
availableToTradeUsdhFromAsset = Math.max(availableToTradeUsdhFromAsset, availableValue);
|
|
7655
|
-
}
|
|
7656
|
-
return;
|
|
7604
|
+
for (const { metadata, isLong } of allMetadataWithSource) {
|
|
7605
|
+
if (!(metadata === null || metadata === void 0 ? void 0 : metadata.collateralToken) || !(metadata === null || metadata === void 0 ? void 0 : metadata.availableToTrade))
|
|
7606
|
+
continue;
|
|
7607
|
+
const collateralCoin = metadata.collateralToken;
|
|
7608
|
+
const availableToTrade = metadata.availableToTrade;
|
|
7609
|
+
let value = parseFloat(availableToTrade[isLong ? 0 : 1] || '0');
|
|
7610
|
+
if (!(collateralCoin in availableToTrades) ||
|
|
7611
|
+
value < availableToTrades[collateralCoin]) {
|
|
7612
|
+
availableToTrades[collateralCoin] = value;
|
|
7657
7613
|
}
|
|
7658
|
-
availableToTradeUsdcFromAsset = Math.max(availableToTradeUsdcFromAsset, availableValue);
|
|
7659
|
-
});
|
|
7660
|
-
// Calculate USDC available to trade
|
|
7661
|
-
// Priority 1: Use value from activeAssetData if available (> 0)
|
|
7662
|
-
// Priority 2: Calculate from USDC-specific clearinghouseState (empty prefix)
|
|
7663
|
-
let availableToTradeUsdcValue = undefined;
|
|
7664
|
-
if (availableToTradeUsdcFromAsset > 0) {
|
|
7665
|
-
availableToTradeUsdcValue = availableToTradeUsdcFromAsset;
|
|
7666
7614
|
}
|
|
7667
|
-
|
|
7668
|
-
|
|
7669
|
-
const usdcMarket = rawClearinghouseStates.find(([prefix]) => prefix === '');
|
|
7670
|
-
const usdcState = usdcMarket === null || usdcMarket === void 0 ? void 0 : usdcMarket[1];
|
|
7671
|
-
if (usdcState === null || usdcState === void 0 ? void 0 : usdcState.marginSummary) {
|
|
7672
|
-
const accountValue = parseFloat(usdcState.marginSummary.accountValue || '0');
|
|
7673
|
-
const totalMarginUsed = parseFloat(usdcState.marginSummary.totalMarginUsed || '0');
|
|
7674
|
-
const calculatedValue = Math.max(0, accountValue - totalMarginUsed);
|
|
7675
|
-
availableToTradeUsdcValue = truncateToTwoDecimals(calculatedValue);
|
|
7676
|
-
}
|
|
7615
|
+
if (!availableToTrades['USDC']) {
|
|
7616
|
+
availableToTrades['USDC'] = parseFloat((aggregatedClearingHouseState === null || aggregatedClearingHouseState === void 0 ? void 0 : aggregatedClearingHouseState.marginSummary.totalRawUsd) || '0');
|
|
7677
7617
|
}
|
|
7678
|
-
// Calculate USDH available to trade
|
|
7679
|
-
// Priority 1: Use value from activeAssetData if available (> 0)
|
|
7680
|
-
// Priority 2: Use spot USDH balance
|
|
7681
|
-
const availableToTradeUsdhValue = availableToTradeUsdhFromAsset > 0
|
|
7682
|
-
? availableToTradeUsdhFromAsset
|
|
7683
|
-
: spotUsdhBal;
|
|
7684
7618
|
return {
|
|
7685
|
-
|
|
7686
|
-
|
|
7687
|
-
spotUsdhBalance: spotUsdhBal,
|
|
7688
|
-
availableToTradeUsdh: availableToTradeUsdhValue,
|
|
7619
|
+
spotBalances,
|
|
7620
|
+
availableToTrades,
|
|
7689
7621
|
isLoading,
|
|
7690
7622
|
};
|
|
7623
|
+
}, [spotState, longTokensMetadata, shortTokensMetadata, aggregatedClearingHouseState]);
|
|
7624
|
+
/**
|
|
7625
|
+
* Calculate margin required for every collateral token based on asset leverages and size.
|
|
7626
|
+
* Returns margin required per collateral and whether there's sufficient margin.
|
|
7627
|
+
*/
|
|
7628
|
+
const getMarginRequired = useCallback((assetsLeverage, size) => {
|
|
7629
|
+
const sizeValue = parseFloat(String(size)) || 0;
|
|
7630
|
+
// Group tokens by collateral type and calculate margin required
|
|
7631
|
+
const marginByCollateral = {};
|
|
7632
|
+
// Process all tokens (long and short)
|
|
7633
|
+
const allTokensWithMetadata = [
|
|
7634
|
+
...longTokens.map((t) => ({
|
|
7635
|
+
...t,
|
|
7636
|
+
metadata: longTokensMetadata[t.symbol],
|
|
7637
|
+
})),
|
|
7638
|
+
...shortTokens.map((t) => ({
|
|
7639
|
+
...t,
|
|
7640
|
+
metadata: shortTokensMetadata[t.symbol],
|
|
7641
|
+
})),
|
|
7642
|
+
];
|
|
7643
|
+
let totalMarginRequired = 0;
|
|
7644
|
+
allTokensWithMetadata.forEach((token) => {
|
|
7645
|
+
var _a;
|
|
7646
|
+
const weight = token.weight || 0;
|
|
7647
|
+
const assetSize = (sizeValue * weight) / 100;
|
|
7648
|
+
const assetLeverage = assetsLeverage[token.symbol] || 1;
|
|
7649
|
+
const assetMargin = assetLeverage > 0 ? assetSize / assetLeverage : 0;
|
|
7650
|
+
// Get collateral type from metadata, default to USDC
|
|
7651
|
+
const collateralToken = ((_a = token.metadata) === null || _a === void 0 ? void 0 : _a.collateralToken) || 'USDC';
|
|
7652
|
+
if (!marginByCollateral[collateralToken]) {
|
|
7653
|
+
marginByCollateral[collateralToken] = 0;
|
|
7654
|
+
}
|
|
7655
|
+
marginByCollateral[collateralToken] += assetMargin;
|
|
7656
|
+
totalMarginRequired += assetMargin;
|
|
7657
|
+
});
|
|
7658
|
+
const perCollateral = Object.entries(marginByCollateral).map(([collateral, marginRequired]) => {
|
|
7659
|
+
var _a;
|
|
7660
|
+
const collateralToken = collateral;
|
|
7661
|
+
const availableBalance = (_a = availableToTrades[collateralToken]) !== null && _a !== void 0 ? _a : 0;
|
|
7662
|
+
const hasEnough = marginRequired <= availableBalance;
|
|
7663
|
+
const shortfall = Math.max(0, marginRequired - availableBalance);
|
|
7664
|
+
return {
|
|
7665
|
+
collateral: collateralToken,
|
|
7666
|
+
marginRequired: Number(marginRequired.toFixed(2)),
|
|
7667
|
+
availableBalance: Number(availableBalance.toFixed(2)),
|
|
7668
|
+
hasEnough,
|
|
7669
|
+
shortfall: Number(shortfall.toFixed(2)),
|
|
7670
|
+
};
|
|
7671
|
+
});
|
|
7672
|
+
const hasEnoughTotal = perCollateral.every((c) => c.hasEnough);
|
|
7673
|
+
return {
|
|
7674
|
+
totalMarginRequired: Number(totalMarginRequired.toFixed(2)),
|
|
7675
|
+
orderValue: sizeValue,
|
|
7676
|
+
perCollateral,
|
|
7677
|
+
hasEnoughTotal,
|
|
7678
|
+
};
|
|
7679
|
+
}, [
|
|
7680
|
+
longTokens,
|
|
7681
|
+
shortTokens,
|
|
7682
|
+
longTokensMetadata,
|
|
7683
|
+
shortTokensMetadata,
|
|
7684
|
+
spotBalances,
|
|
7685
|
+
availableToTrades,
|
|
7686
|
+
]);
|
|
7687
|
+
/**
|
|
7688
|
+
* Calculate the maximum order size ($) based on available balances and asset leverages.
|
|
7689
|
+
* Returns the overall maximum order size constrained by all collateral types.
|
|
7690
|
+
*/
|
|
7691
|
+
const getMaxSize = useCallback((assetsLeverage) => {
|
|
7692
|
+
const marginFactorByCollateral = {};
|
|
7693
|
+
const allTokensWithMetadata = [
|
|
7694
|
+
...longTokens.map((t) => ({
|
|
7695
|
+
...t,
|
|
7696
|
+
metadata: longTokensMetadata[t.symbol],
|
|
7697
|
+
})),
|
|
7698
|
+
...shortTokens.map((t) => ({
|
|
7699
|
+
...t,
|
|
7700
|
+
metadata: shortTokensMetadata[t.symbol],
|
|
7701
|
+
})),
|
|
7702
|
+
];
|
|
7703
|
+
// Calculate the margin factor for each collateral type
|
|
7704
|
+
// marginFactor = sum of (weight / leverage) for all assets using that collateral
|
|
7705
|
+
allTokensWithMetadata.forEach((token) => {
|
|
7706
|
+
var _a;
|
|
7707
|
+
const weight = token.weight || 0;
|
|
7708
|
+
const assetLeverage = assetsLeverage[token.symbol] || 1;
|
|
7709
|
+
const collateralToken = ((_a = token.metadata) === null || _a === void 0 ? void 0 : _a.collateralToken) || 'USDC';
|
|
7710
|
+
// marginFactor represents how much margin is needed per $1 of order size
|
|
7711
|
+
const marginFactor = assetLeverage > 0 ? weight / (100 * assetLeverage) : 0;
|
|
7712
|
+
if (!marginFactorByCollateral[collateralToken]) {
|
|
7713
|
+
marginFactorByCollateral[collateralToken] = 0;
|
|
7714
|
+
}
|
|
7715
|
+
marginFactorByCollateral[collateralToken] += marginFactor;
|
|
7716
|
+
});
|
|
7717
|
+
// Calculate max size for each collateral type
|
|
7718
|
+
// maxSize = availableBalance / marginFactor
|
|
7719
|
+
// Each maxSize represents the total order size that collateral can support
|
|
7720
|
+
const maxSizePerCollateral = [];
|
|
7721
|
+
Object.entries(marginFactorByCollateral).forEach(([collateral, marginFactor]) => {
|
|
7722
|
+
var _a;
|
|
7723
|
+
const collateralToken = collateral;
|
|
7724
|
+
const availableBalance = (_a = availableToTrades[collateralToken]) !== null && _a !== void 0 ? _a : 0;
|
|
7725
|
+
if (marginFactor > 0) {
|
|
7726
|
+
const maxSize = availableBalance / marginFactor;
|
|
7727
|
+
maxSizePerCollateral.push(maxSize);
|
|
7728
|
+
}
|
|
7729
|
+
});
|
|
7730
|
+
if (maxSizePerCollateral.length === 0) {
|
|
7731
|
+
return 0;
|
|
7732
|
+
}
|
|
7733
|
+
const overallMaxSize = Math.min(...maxSizePerCollateral);
|
|
7734
|
+
return Number(overallMaxSize.toFixed(2));
|
|
7691
7735
|
}, [
|
|
7692
|
-
|
|
7693
|
-
|
|
7694
|
-
rawClearinghouseStates,
|
|
7736
|
+
longTokens,
|
|
7737
|
+
shortTokens,
|
|
7695
7738
|
longTokensMetadata,
|
|
7696
7739
|
shortTokensMetadata,
|
|
7740
|
+
availableToTrades,
|
|
7697
7741
|
]);
|
|
7742
|
+
return {
|
|
7743
|
+
spotBalances,
|
|
7744
|
+
availableToTrades,
|
|
7745
|
+
isLoading,
|
|
7746
|
+
getMarginRequired,
|
|
7747
|
+
getMaxSize,
|
|
7748
|
+
};
|
|
7698
7749
|
};
|
|
7699
7750
|
|
|
7700
7751
|
/**
|
|
@@ -7879,7 +7930,7 @@ const PearHyperliquidProvider = ({ children, apiBaseUrl = 'https://hl-ui.pearpro
|
|
|
7879
7930
|
collateralToken = 'USDE';
|
|
7880
7931
|
}
|
|
7881
7932
|
if (item.collateralToken === 268) {
|
|
7882
|
-
collateralToken = '
|
|
7933
|
+
collateralToken = 'USDT0';
|
|
7883
7934
|
}
|
|
7884
7935
|
const universeAssets = item.universe.map((asset) => ({
|
|
7885
7936
|
...asset,
|
|
@@ -8175,4 +8226,4 @@ function getOrderTrailingInfo(order) {
|
|
|
8175
8226
|
return undefined;
|
|
8176
8227
|
}
|
|
8177
8228
|
|
|
8178
|
-
export {
|
|
8229
|
+
export { ConflictDetector, MAX_ASSETS_PER_LEG, MINIMUM_ASSET_USD_VALUE, MaxAssetsPerLegError, MinimumPositionSizeError, PearHyperliquidProvider, adjustAdvancePosition, adjustOrder, adjustPosition, calculateMinimumPositionValue, calculateWeightedRatio, cancelOrder, cancelTwap, cancelTwapOrder, closeAllPositions, closePosition, computeBasketCandles, createCandleLookups, createPosition, executeSpotOrder, getCompleteTimestamps, getKalshiMarkets, getOrderDirection, getOrderLadderConfig, getOrderLeverage, getOrderReduceOnly, getOrderTpSlTriggerType, getOrderTrailingInfo, getOrderTriggerType, getOrderTriggerValue, getOrderTwapDuration, getOrderUsdValue, getPortfolio, isBtcDomOrder, mapCandleIntervalToTradingViewInterval, mapTradingViewIntervalToCandleInterval, markNotificationReadById, markNotificationsRead, toggleWatchlist, updateLeverage, updateRiskParameters, useAccountSummary, useAgentWallet, useAllUserBalances, useAuth, useBasketCandles, useHistoricalPriceData, useHistoricalPriceDataStore, useHyperliquidUserFills, useMarket, useMarketData, useMarketDataHook, useNotifications, useOpenOrders, useOrders, usePearHyperliquid, usePerformanceOverlays, usePortfolio, usePosition, useSpotOrder, useTokenSelectionMetadata, useTradeHistories, useTwap, useUserSelection, useWatchlist, validateMaxAssetsPerLeg, validateMinimumAssetSize, validatePositionSize };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { TokenSelection, TokenMetadata, ActiveAssetsResponse
|
|
1
|
+
import type { TokenSelection, TokenMetadata, ActiveAssetsResponse } from "../types";
|
|
2
2
|
export interface TokenSelectionMetadataState {
|
|
3
3
|
isPriceDataReady: boolean;
|
|
4
4
|
isLoading: boolean;
|
|
@@ -12,10 +12,9 @@ export interface TokenSelectionMetadataState {
|
|
|
12
12
|
volume: string;
|
|
13
13
|
sumNetFunding: number;
|
|
14
14
|
maxLeverage: number;
|
|
15
|
-
|
|
15
|
+
minSize: Record<string, number>;
|
|
16
16
|
leverageMatched: boolean;
|
|
17
17
|
recompute: (args: {
|
|
18
|
-
perpMetaAssets: UniverseAsset[] | null;
|
|
19
18
|
tokenMetadata: Record<string, TokenMetadata | null>;
|
|
20
19
|
marketData: ActiveAssetsResponse | null;
|
|
21
20
|
longTokens: TokenSelection[];
|