@pear-protocol/hyperliquid-sdk 0.1.2 → 0.1.3
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 +263 -213
- 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
|
@@ -1513,7 +1513,36 @@ const useOpenOrders = () => {
|
|
|
1513
1513
|
};
|
|
1514
1514
|
|
|
1515
1515
|
const useUserSelection = () => {
|
|
1516
|
-
|
|
1516
|
+
const longTokens = useUserSelection$1((s) => s.longTokens);
|
|
1517
|
+
const shortTokens = useUserSelection$1((s) => s.shortTokens);
|
|
1518
|
+
const candleInterval = useUserSelection$1((s) => s.candleInterval);
|
|
1519
|
+
const openTokenSelector = useUserSelection$1((s) => s.openTokenSelector);
|
|
1520
|
+
const selectorConfig = useUserSelection$1((s) => s.selectorConfig);
|
|
1521
|
+
const openConflictModal = useUserSelection$1((s) => s.openConflictModal);
|
|
1522
|
+
const setLongTokens = useUserSelection$1((s) => s.setLongTokens);
|
|
1523
|
+
const setShortTokens = useUserSelection$1((s) => s.setShortTokens);
|
|
1524
|
+
const setCandleInterval = useUserSelection$1((s) => s.setCandleInterval);
|
|
1525
|
+
const setTokenSelections = useUserSelection$1((s) => s.setTokenSelections);
|
|
1526
|
+
const setOpenTokenSelector = useUserSelection$1((s) => s.setOpenTokenSelector);
|
|
1527
|
+
const setSelectorConfig = useUserSelection$1((s) => s.setSelectorConfig);
|
|
1528
|
+
const setOpenConflictModal = useUserSelection$1((s) => s.setOpenConflictModal);
|
|
1529
|
+
const addToken = useUserSelection$1((s) => s.addToken);
|
|
1530
|
+
return {
|
|
1531
|
+
longTokens,
|
|
1532
|
+
shortTokens,
|
|
1533
|
+
candleInterval,
|
|
1534
|
+
openTokenSelector,
|
|
1535
|
+
selectorConfig,
|
|
1536
|
+
openConflictModal,
|
|
1537
|
+
setLongTokens,
|
|
1538
|
+
setShortTokens,
|
|
1539
|
+
setCandleInterval,
|
|
1540
|
+
setTokenSelections,
|
|
1541
|
+
setOpenTokenSelector,
|
|
1542
|
+
setSelectorConfig,
|
|
1543
|
+
setOpenConflictModal,
|
|
1544
|
+
addToken,
|
|
1545
|
+
};
|
|
1517
1546
|
};
|
|
1518
1547
|
|
|
1519
1548
|
const useTokenSelectionMetadataStore = create((set) => ({
|
|
@@ -1529,11 +1558,10 @@ const useTokenSelectionMetadataStore = create((set) => ({
|
|
|
1529
1558
|
volume: "0",
|
|
1530
1559
|
sumNetFunding: 0,
|
|
1531
1560
|
maxLeverage: 0,
|
|
1532
|
-
|
|
1561
|
+
minSize: {},
|
|
1533
1562
|
leverageMatched: true,
|
|
1534
|
-
recompute: ({
|
|
1563
|
+
recompute: ({ tokenMetadata, marketData, longTokens, shortTokens, }) => {
|
|
1535
1564
|
const isPriceDataReady = Object.keys(tokenMetadata).length > 0;
|
|
1536
|
-
// Get token symbols for lookups
|
|
1537
1565
|
const longSymbols = longTokens.map((t) => t.symbol);
|
|
1538
1566
|
const shortSymbols = shortTokens.map((t) => t.symbol);
|
|
1539
1567
|
// Get metadata
|
|
@@ -1656,24 +1684,37 @@ const useTokenSelectionMetadataStore = create((set) => ({
|
|
|
1656
1684
|
})();
|
|
1657
1685
|
// Max leverage (maximum across all tokens)
|
|
1658
1686
|
const maxLeverage = (() => {
|
|
1659
|
-
if (!
|
|
1687
|
+
if (!tokenMetadata)
|
|
1660
1688
|
return 0;
|
|
1661
1689
|
const allSymbols = [...longSymbols, ...shortSymbols];
|
|
1662
1690
|
if (allSymbols.length === 0)
|
|
1663
1691
|
return 0;
|
|
1664
1692
|
let maxLev = 0;
|
|
1665
1693
|
allSymbols.forEach((symbol) => {
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1694
|
+
var _a;
|
|
1695
|
+
const tokenDetail = tokenMetadata[symbol];
|
|
1696
|
+
if ((_a = tokenDetail === null || tokenDetail === void 0 ? void 0 : tokenDetail.leverage) === null || _a === void 0 ? void 0 : _a.value) {
|
|
1697
|
+
maxLev = Math.max(maxLev, tokenDetail.leverage.value);
|
|
1669
1698
|
}
|
|
1670
1699
|
});
|
|
1671
1700
|
return maxLev;
|
|
1672
1701
|
})();
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
const
|
|
1676
|
-
|
|
1702
|
+
const minSize = (() => {
|
|
1703
|
+
const allSymbols = [...longSymbols, ...shortSymbols];
|
|
1704
|
+
const collateralCounts = {};
|
|
1705
|
+
allSymbols.forEach((symbol) => {
|
|
1706
|
+
var _a;
|
|
1707
|
+
const collateralToken = (_a = tokenMetadata[symbol]) === null || _a === void 0 ? void 0 : _a.collateralToken;
|
|
1708
|
+
if (collateralToken) {
|
|
1709
|
+
collateralCounts[collateralToken] =
|
|
1710
|
+
(collateralCounts[collateralToken] || 0) + 1;
|
|
1711
|
+
}
|
|
1712
|
+
});
|
|
1713
|
+
const minSizeMap = {};
|
|
1714
|
+
Object.entries(collateralCounts).forEach(([collateral, count]) => {
|
|
1715
|
+
minSizeMap[collateral] = 11 * count;
|
|
1716
|
+
});
|
|
1717
|
+
return minSizeMap;
|
|
1677
1718
|
})();
|
|
1678
1719
|
// Whether all tokens have matching leverage
|
|
1679
1720
|
const leverageMatched = (() => {
|
|
@@ -1708,7 +1749,7 @@ const useTokenSelectionMetadataStore = create((set) => ({
|
|
|
1708
1749
|
volume,
|
|
1709
1750
|
sumNetFunding,
|
|
1710
1751
|
maxLeverage,
|
|
1711
|
-
|
|
1752
|
+
minSize,
|
|
1712
1753
|
leverageMatched,
|
|
1713
1754
|
});
|
|
1714
1755
|
},
|
|
@@ -1723,11 +1764,10 @@ const useTokenSelectionMetadata = () => {
|
|
|
1723
1764
|
const tokenMetadata = useHyperliquidData((state) => state.tokenMetadata);
|
|
1724
1765
|
const marketData = useMarketData((state) => state.marketData);
|
|
1725
1766
|
const { longTokens, shortTokens } = useUserSelection$1();
|
|
1726
|
-
const { isLoading, isPriceDataReady, longTokensMetadata, shortTokensMetadata, weightedRatio, weightedRatio24h, priceRatio, priceRatio24h, openInterest, volume, sumNetFunding, maxLeverage,
|
|
1767
|
+
const { isLoading, isPriceDataReady, longTokensMetadata, shortTokensMetadata, weightedRatio, weightedRatio24h, priceRatio, priceRatio24h, openInterest, volume, sumNetFunding, maxLeverage, minSize, leverageMatched, recompute, } = useTokenSelectionMetadataStore();
|
|
1727
1768
|
// Recompute derived metadata when inputs change
|
|
1728
1769
|
useEffect(() => {
|
|
1729
1770
|
recompute({
|
|
1730
|
-
perpMetaAssets,
|
|
1731
1771
|
tokenMetadata,
|
|
1732
1772
|
marketData: marketData || null,
|
|
1733
1773
|
longTokens,
|
|
@@ -1751,8 +1791,8 @@ const useTokenSelectionMetadata = () => {
|
|
|
1751
1791
|
volume,
|
|
1752
1792
|
sumNetFunding,
|
|
1753
1793
|
maxLeverage,
|
|
1754
|
-
minMargin,
|
|
1755
1794
|
leverageMatched,
|
|
1795
|
+
minSize,
|
|
1756
1796
|
};
|
|
1757
1797
|
};
|
|
1758
1798
|
|
|
@@ -7197,122 +7237,62 @@ function useNotifications() {
|
|
|
7197
7237
|
};
|
|
7198
7238
|
}
|
|
7199
7239
|
|
|
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
|
-
}));
|
|
7240
|
+
function enrichBasketWithMetadata(basket, tokenMetadata) {
|
|
7208
7241
|
return {
|
|
7209
|
-
...
|
|
7210
|
-
longAssets:
|
|
7211
|
-
|
|
7212
|
-
|
|
7242
|
+
...basket,
|
|
7243
|
+
longAssets: basket.longAssets.map((asset) => {
|
|
7244
|
+
var _a;
|
|
7245
|
+
return ({
|
|
7246
|
+
...asset,
|
|
7247
|
+
metadata: (_a = tokenMetadata[asset.asset]) !== null && _a !== void 0 ? _a : null,
|
|
7248
|
+
});
|
|
7249
|
+
}),
|
|
7250
|
+
shortAssets: basket.shortAssets.map((asset) => {
|
|
7251
|
+
var _a;
|
|
7252
|
+
return ({
|
|
7253
|
+
...asset,
|
|
7254
|
+
metadata: (_a = tokenMetadata[asset.asset]) !== null && _a !== void 0 ? _a : null,
|
|
7255
|
+
});
|
|
7256
|
+
}),
|
|
7213
7257
|
};
|
|
7214
7258
|
}
|
|
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
|
-
});
|
|
7259
|
+
function enrichBasketsWithMetadata(baskets, tokenMetadata) {
|
|
7260
|
+
return baskets.map((basket) => enrichBasketWithMetadata(basket, tokenMetadata));
|
|
7236
7261
|
}
|
|
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();
|
|
7262
|
+
const useMarketDataHook = (options = {}) => {
|
|
7263
|
+
const { topGainersLimit, topLosersLimit } = options;
|
|
7264
|
+
const data = useMarketData((s) => s.marketData);
|
|
7265
|
+
const tokenMetadata = useHyperliquidData((s) => s.tokenMetadata);
|
|
7286
7266
|
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,
|
|
7267
|
+
var _a, _b, _c;
|
|
7268
|
+
const activeBaskets = enrichBasketsWithMetadata((_a = data === null || data === void 0 ? void 0 : data.active) !== null && _a !== void 0 ? _a : [], tokenMetadata);
|
|
7269
|
+
const topGainers = (() => {
|
|
7270
|
+
var _a;
|
|
7271
|
+
const list = (_a = data === null || data === void 0 ? void 0 : data.topGainers) !== null && _a !== void 0 ? _a : [];
|
|
7272
|
+
const limited = typeof topGainersLimit === 'number'
|
|
7273
|
+
? list.slice(0, Math.max(0, topGainersLimit))
|
|
7274
|
+
: list;
|
|
7275
|
+
return enrichBasketsWithMetadata(limited, tokenMetadata);
|
|
7276
|
+
})();
|
|
7277
|
+
const topLosers = (() => {
|
|
7278
|
+
var _a;
|
|
7279
|
+
const list = (_a = data === null || data === void 0 ? void 0 : data.topLosers) !== null && _a !== void 0 ? _a : [];
|
|
7280
|
+
const limited = typeof topLosersLimit === 'number'
|
|
7281
|
+
? list.slice(0, Math.max(0, topLosersLimit))
|
|
7282
|
+
: list;
|
|
7283
|
+
return enrichBasketsWithMetadata(limited, tokenMetadata);
|
|
7284
|
+
})();
|
|
7285
|
+
const highlightedBaskets = enrichBasketsWithMetadata((_b = data === null || data === void 0 ? void 0 : data.highlighted) !== null && _b !== void 0 ? _b : [], tokenMetadata);
|
|
7286
|
+
const watchlistBaskets = enrichBasketsWithMetadata((_c = data === null || data === void 0 ? void 0 : data.watchlist) !== null && _c !== void 0 ? _c : [], tokenMetadata);
|
|
7287
|
+
return {
|
|
7288
|
+
marketData: data,
|
|
7289
|
+
activeBaskets,
|
|
7290
|
+
topGainers,
|
|
7291
|
+
topLosers,
|
|
7292
|
+
highlightedBaskets,
|
|
7293
|
+
watchlistBaskets,
|
|
7294
|
+
};
|
|
7295
|
+
}, [data, tokenMetadata, topGainersLimit, topLosersLimit]);
|
|
7316
7296
|
};
|
|
7317
7297
|
|
|
7318
7298
|
async function toggleWatchlist(baseUrl, longAssets, shortAssets) {
|
|
@@ -7338,7 +7318,7 @@ function useWatchlist() {
|
|
|
7338
7318
|
if (!context)
|
|
7339
7319
|
throw new Error('useWatchlist must be used within a PearHyperliquidProvider');
|
|
7340
7320
|
const { apiBaseUrl, isConnected } = context;
|
|
7341
|
-
const marketData =
|
|
7321
|
+
const marketData = useMarketData(s => s.marketData);
|
|
7342
7322
|
const isLoading = useMemo(() => !marketData && isConnected, [marketData, isConnected]);
|
|
7343
7323
|
const toggle = async (longAssets, shortAssets) => {
|
|
7344
7324
|
const resp = await toggleWatchlist(apiBaseUrl, longAssets, shortAssets);
|
|
@@ -7597,104 +7577,174 @@ function useAuth() {
|
|
|
7597
7577
|
|
|
7598
7578
|
const useAllUserBalances = () => {
|
|
7599
7579
|
const spotState = useUserData((state) => state.spotState);
|
|
7600
|
-
const aggregatedClearingHouseState = useHyperliquidData((state) => state.aggregatedClearingHouseState);
|
|
7601
|
-
const rawClearinghouseStates = useHyperliquidData((state) => state.rawClearinghouseStates);
|
|
7602
7580
|
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) {
|
|
7581
|
+
const { longTokens, shortTokens } = useUserSelection$1();
|
|
7582
|
+
const aggregatedClearingHouseState = useHyperliquidData((state) => state.aggregatedClearingHouseState);
|
|
7583
|
+
const { spotBalances, availableToTrades, isLoading } = useMemo(() => {
|
|
7584
|
+
const isLoading = !spotState;
|
|
7585
|
+
const spotBalances = {};
|
|
7586
|
+
const availableToTrades = {};
|
|
7587
|
+
if (spotState === null || spotState === void 0 ? void 0 : spotState.balances) {
|
|
7588
|
+
for (const balance of spotState.balances) {
|
|
7615
7589
|
const total = parseFloat(balance.total || '0');
|
|
7616
|
-
|
|
7617
|
-
spotUsdcBal = truncateToTwoDecimals(total);
|
|
7618
|
-
}
|
|
7619
|
-
if (balance.coin === 'USDH') {
|
|
7620
|
-
spotUsdhBal = truncateToTwoDecimals(total);
|
|
7621
|
-
}
|
|
7590
|
+
spotBalances[balance.coin] = total;
|
|
7622
7591
|
}
|
|
7623
7592
|
}
|
|
7624
|
-
|
|
7625
|
-
|
|
7626
|
-
|
|
7627
|
-
|
|
7628
|
-
|
|
7629
|
-
|
|
7630
|
-
|
|
7631
|
-
|
|
7632
|
-
|
|
7593
|
+
const allMetadataWithSource = [
|
|
7594
|
+
...Object.values(longTokensMetadata).map((m) => ({
|
|
7595
|
+
metadata: m,
|
|
7596
|
+
isLong: true,
|
|
7597
|
+
})),
|
|
7598
|
+
...Object.values(shortTokensMetadata).map((m) => ({
|
|
7599
|
+
metadata: m,
|
|
7600
|
+
isLong: false,
|
|
7601
|
+
})),
|
|
7633
7602
|
];
|
|
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;
|
|
7603
|
+
for (const { metadata, isLong } of allMetadataWithSource) {
|
|
7604
|
+
if (!(metadata === null || metadata === void 0 ? void 0 : metadata.collateralToken) || !(metadata === null || metadata === void 0 ? void 0 : metadata.availableToTrade))
|
|
7605
|
+
continue;
|
|
7606
|
+
const collateralCoin = metadata.collateralToken;
|
|
7607
|
+
const availableToTrade = metadata.availableToTrade;
|
|
7608
|
+
let value = parseFloat(availableToTrade[isLong ? 0 : 1] || '0');
|
|
7609
|
+
if (!(collateralCoin in availableToTrades) ||
|
|
7610
|
+
value < availableToTrades[collateralCoin]) {
|
|
7611
|
+
availableToTrades[collateralCoin] = value;
|
|
7657
7612
|
}
|
|
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
7613
|
}
|
|
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
|
-
}
|
|
7614
|
+
if (!availableToTrades['USDC']) {
|
|
7615
|
+
availableToTrades['USDC'] = parseFloat((aggregatedClearingHouseState === null || aggregatedClearingHouseState === void 0 ? void 0 : aggregatedClearingHouseState.marginSummary.totalRawUsd) || '0');
|
|
7677
7616
|
}
|
|
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
7617
|
return {
|
|
7685
|
-
|
|
7686
|
-
|
|
7687
|
-
spotUsdhBalance: spotUsdhBal,
|
|
7688
|
-
availableToTradeUsdh: availableToTradeUsdhValue,
|
|
7618
|
+
spotBalances,
|
|
7619
|
+
availableToTrades,
|
|
7689
7620
|
isLoading,
|
|
7690
7621
|
};
|
|
7622
|
+
}, [spotState, longTokensMetadata, shortTokensMetadata, aggregatedClearingHouseState]);
|
|
7623
|
+
/**
|
|
7624
|
+
* Calculate margin required for every collateral token based on asset leverages and size.
|
|
7625
|
+
* Returns margin required per collateral and whether there's sufficient margin.
|
|
7626
|
+
*/
|
|
7627
|
+
const getMarginRequired = useCallback((assetsLeverage, size) => {
|
|
7628
|
+
const sizeValue = parseFloat(String(size)) || 0;
|
|
7629
|
+
// Group tokens by collateral type and calculate margin required
|
|
7630
|
+
const marginByCollateral = {};
|
|
7631
|
+
// Process all tokens (long and short)
|
|
7632
|
+
const allTokensWithMetadata = [
|
|
7633
|
+
...longTokens.map((t) => ({
|
|
7634
|
+
...t,
|
|
7635
|
+
metadata: longTokensMetadata[t.symbol],
|
|
7636
|
+
})),
|
|
7637
|
+
...shortTokens.map((t) => ({
|
|
7638
|
+
...t,
|
|
7639
|
+
metadata: shortTokensMetadata[t.symbol],
|
|
7640
|
+
})),
|
|
7641
|
+
];
|
|
7642
|
+
let totalMarginRequired = 0;
|
|
7643
|
+
allTokensWithMetadata.forEach((token) => {
|
|
7644
|
+
var _a;
|
|
7645
|
+
const weight = token.weight || 0;
|
|
7646
|
+
const assetSize = (sizeValue * weight) / 100;
|
|
7647
|
+
const assetLeverage = assetsLeverage[token.symbol] || 1;
|
|
7648
|
+
const assetMargin = assetLeverage > 0 ? assetSize / assetLeverage : 0;
|
|
7649
|
+
// Get collateral type from metadata, default to USDC
|
|
7650
|
+
const collateralToken = ((_a = token.metadata) === null || _a === void 0 ? void 0 : _a.collateralToken) || 'USDC';
|
|
7651
|
+
if (!marginByCollateral[collateralToken]) {
|
|
7652
|
+
marginByCollateral[collateralToken] = 0;
|
|
7653
|
+
}
|
|
7654
|
+
marginByCollateral[collateralToken] += assetMargin;
|
|
7655
|
+
totalMarginRequired += assetMargin;
|
|
7656
|
+
});
|
|
7657
|
+
const perCollateral = Object.entries(marginByCollateral).map(([collateral, marginRequired]) => {
|
|
7658
|
+
var _a;
|
|
7659
|
+
const collateralToken = collateral;
|
|
7660
|
+
const availableBalance = (_a = availableToTrades[collateralToken]) !== null && _a !== void 0 ? _a : 0;
|
|
7661
|
+
const hasEnough = marginRequired <= availableBalance;
|
|
7662
|
+
const shortfall = Math.max(0, marginRequired - availableBalance);
|
|
7663
|
+
return {
|
|
7664
|
+
collateral: collateralToken,
|
|
7665
|
+
marginRequired: Number(marginRequired.toFixed(2)),
|
|
7666
|
+
availableBalance: Number(availableBalance.toFixed(2)),
|
|
7667
|
+
hasEnough,
|
|
7668
|
+
shortfall: Number(shortfall.toFixed(2)),
|
|
7669
|
+
};
|
|
7670
|
+
});
|
|
7671
|
+
const hasEnoughTotal = perCollateral.every((c) => c.hasEnough);
|
|
7672
|
+
return {
|
|
7673
|
+
totalMarginRequired: Number(totalMarginRequired.toFixed(2)),
|
|
7674
|
+
orderValue: sizeValue,
|
|
7675
|
+
perCollateral,
|
|
7676
|
+
hasEnoughTotal,
|
|
7677
|
+
};
|
|
7678
|
+
}, [
|
|
7679
|
+
longTokens,
|
|
7680
|
+
shortTokens,
|
|
7681
|
+
longTokensMetadata,
|
|
7682
|
+
shortTokensMetadata,
|
|
7683
|
+
spotBalances,
|
|
7684
|
+
availableToTrades,
|
|
7685
|
+
]);
|
|
7686
|
+
/**
|
|
7687
|
+
* Calculate the maximum order size ($) based on available balances and asset leverages.
|
|
7688
|
+
* Returns the overall maximum order size constrained by all collateral types.
|
|
7689
|
+
*/
|
|
7690
|
+
const getMaxSize = useCallback((assetsLeverage) => {
|
|
7691
|
+
const marginFactorByCollateral = {};
|
|
7692
|
+
const allTokensWithMetadata = [
|
|
7693
|
+
...longTokens.map((t) => ({
|
|
7694
|
+
...t,
|
|
7695
|
+
metadata: longTokensMetadata[t.symbol],
|
|
7696
|
+
})),
|
|
7697
|
+
...shortTokens.map((t) => ({
|
|
7698
|
+
...t,
|
|
7699
|
+
metadata: shortTokensMetadata[t.symbol],
|
|
7700
|
+
})),
|
|
7701
|
+
];
|
|
7702
|
+
// Calculate the margin factor for each collateral type
|
|
7703
|
+
// marginFactor = sum of (weight / leverage) for all assets using that collateral
|
|
7704
|
+
allTokensWithMetadata.forEach((token) => {
|
|
7705
|
+
var _a;
|
|
7706
|
+
const weight = token.weight || 0;
|
|
7707
|
+
const assetLeverage = assetsLeverage[token.symbol] || 1;
|
|
7708
|
+
const collateralToken = ((_a = token.metadata) === null || _a === void 0 ? void 0 : _a.collateralToken) || 'USDC';
|
|
7709
|
+
// marginFactor represents how much margin is needed per $1 of order size
|
|
7710
|
+
const marginFactor = assetLeverage > 0 ? weight / (100 * assetLeverage) : 0;
|
|
7711
|
+
if (!marginFactorByCollateral[collateralToken]) {
|
|
7712
|
+
marginFactorByCollateral[collateralToken] = 0;
|
|
7713
|
+
}
|
|
7714
|
+
marginFactorByCollateral[collateralToken] += marginFactor;
|
|
7715
|
+
});
|
|
7716
|
+
// Calculate max size for each collateral type
|
|
7717
|
+
// maxSize = availableBalance / marginFactor
|
|
7718
|
+
// Each maxSize represents the total order size that collateral can support
|
|
7719
|
+
const maxSizePerCollateral = [];
|
|
7720
|
+
Object.entries(marginFactorByCollateral).forEach(([collateral, marginFactor]) => {
|
|
7721
|
+
var _a;
|
|
7722
|
+
const collateralToken = collateral;
|
|
7723
|
+
const availableBalance = (_a = availableToTrades[collateralToken]) !== null && _a !== void 0 ? _a : 0;
|
|
7724
|
+
if (marginFactor > 0) {
|
|
7725
|
+
const maxSize = availableBalance / marginFactor;
|
|
7726
|
+
maxSizePerCollateral.push(maxSize);
|
|
7727
|
+
}
|
|
7728
|
+
});
|
|
7729
|
+
if (maxSizePerCollateral.length === 0) {
|
|
7730
|
+
return 0;
|
|
7731
|
+
}
|
|
7732
|
+
const overallMaxSize = Math.min(...maxSizePerCollateral);
|
|
7733
|
+
return Number(overallMaxSize.toFixed(2));
|
|
7691
7734
|
}, [
|
|
7692
|
-
|
|
7693
|
-
|
|
7694
|
-
rawClearinghouseStates,
|
|
7735
|
+
longTokens,
|
|
7736
|
+
shortTokens,
|
|
7695
7737
|
longTokensMetadata,
|
|
7696
7738
|
shortTokensMetadata,
|
|
7739
|
+
availableToTrades,
|
|
7697
7740
|
]);
|
|
7741
|
+
return {
|
|
7742
|
+
spotBalances,
|
|
7743
|
+
availableToTrades,
|
|
7744
|
+
isLoading,
|
|
7745
|
+
getMarginRequired,
|
|
7746
|
+
getMaxSize,
|
|
7747
|
+
};
|
|
7698
7748
|
};
|
|
7699
7749
|
|
|
7700
7750
|
/**
|
|
@@ -7879,7 +7929,7 @@ const PearHyperliquidProvider = ({ children, apiBaseUrl = 'https://hl-ui.pearpro
|
|
|
7879
7929
|
collateralToken = 'USDE';
|
|
7880
7930
|
}
|
|
7881
7931
|
if (item.collateralToken === 268) {
|
|
7882
|
-
collateralToken = '
|
|
7932
|
+
collateralToken = 'USDT0';
|
|
7883
7933
|
}
|
|
7884
7934
|
const universeAssets = item.universe.map((asset) => ({
|
|
7885
7935
|
...asset,
|
|
@@ -8175,4 +8225,4 @@ function getOrderTrailingInfo(order) {
|
|
|
8175
8225
|
return undefined;
|
|
8176
8226
|
}
|
|
8177
8227
|
|
|
8178
|
-
export {
|
|
8228
|
+
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[];
|