From 901616f2a7bf469b9606a5e9b8324fd543d50583 Mon Sep 17 00:00:00 2001 From: Divhead Date: Mon, 13 Jan 2025 11:21:53 +0300 Subject: [PATCH 1/6] fix swap caps --- .../Synthetics/GmList/MintableAmount.tsx | 6 +- .../MarketStatsWithComposition.tsx | 6 +- src/domain/synthetics/markets/utils.ts | 22 +++++-- src/domain/synthetics/trade/types.ts | 1 + .../synthetics/trade/utils/swapRouting.ts | 21 ++++++- .../synthetics/trade/utils/swapStats.ts | 8 ++- src/pages/SyntheticsStats/SyntheticsStats.tsx | 61 ++++++++++++------- 7 files changed, 89 insertions(+), 36 deletions(-) diff --git a/src/components/Synthetics/GmList/MintableAmount.tsx b/src/components/Synthetics/GmList/MintableAmount.tsx index 19d1b4c889..bf42528488 100644 --- a/src/components/Synthetics/GmList/MintableAmount.tsx +++ b/src/components/Synthetics/GmList/MintableAmount.tsx @@ -6,7 +6,7 @@ import { formatTokenAmount, formatTokenAmountWithUsd, formatUsd } from "lib/numb import StatsTooltipRow from "components/StatsTooltip/StatsTooltipRow"; import TooltipWithPortal from "components/Tooltip/TooltipWithPortal"; -import { getMaxPoolUsd, getPoolUsdWithoutPnl, GlvOrMarketInfo } from "domain/synthetics/markets"; +import { getPoolUsdWithoutPnl, getStrictestMaxPoolUsdForDeposit, GlvOrMarketInfo } from "domain/synthetics/markets"; import { TokenData } from "domain/synthetics/tokens"; import { isGlvInfo } from "domain/synthetics/markets/glv"; @@ -49,7 +49,7 @@ export function MintableAmount({ longToken.decimals ) : "-", - `(${formatUsd(getPoolUsdWithoutPnl(market, true, "midPrice"))} / ${formatUsd(getMaxPoolUsd(market, true))})`, + `(${formatUsd(getPoolUsdWithoutPnl(market, true, "midPrice"))} / ${formatUsd(getStrictestMaxPoolUsdForDeposit(market, true))})`, ], [isGlv, longToken, market, mintableInfo] ); @@ -66,7 +66,7 @@ export function MintableAmount({ shortToken.decimals ) : "-", - `(${formatUsd(getPoolUsdWithoutPnl(market, false, "midPrice"))} / ${formatUsd(getMaxPoolUsd(market, false))})`, + `(${formatUsd(getPoolUsdWithoutPnl(market, false, "midPrice"))} / ${formatUsd(getStrictestMaxPoolUsdForDeposit(market, false))})`, ], [isGlv, market, mintableInfo, shortToken] ); diff --git a/src/components/Synthetics/MarketStats/MarketStatsWithComposition.tsx b/src/components/Synthetics/MarketStats/MarketStatsWithComposition.tsx index 67d95393cb..51c84ed5a2 100644 --- a/src/components/Synthetics/MarketStats/MarketStatsWithComposition.tsx +++ b/src/components/Synthetics/MarketStats/MarketStatsWithComposition.tsx @@ -10,7 +10,7 @@ import { getMarketIndexName, getGlvOrMarketAddress, getMarketPoolName, - getMaxPoolUsd, + getStrictestMaxPoolUsdForDeposit, getPoolUsdWithoutPnl, } from "domain/synthetics/markets"; import { TokenData, TokensData, convertToTokenAmount, convertToUsd } from "domain/synthetics/tokens"; @@ -118,7 +118,7 @@ export function MarketStatsWithComposition(p: Props) { longToken?.decimals ), marketInfo - ? `(${formatUsd(getPoolUsdWithoutPnl(marketInfo, true, "midPrice"))} / ${formatUsd(getMaxPoolUsd(marketInfo, true))})` + ? `(${formatUsd(getPoolUsdWithoutPnl(marketInfo, true, "midPrice"))} / ${formatUsd(getStrictestMaxPoolUsdForDeposit(marketInfo, true))})` : "", ], [ @@ -142,7 +142,7 @@ export function MarketStatsWithComposition(p: Props) { shortToken?.decimals ), marketInfo - ? `(${formatUsd(getPoolUsdWithoutPnl(marketInfo, false, "midPrice"))} / ${formatUsd(getMaxPoolUsd(marketInfo, false))})` + ? `(${formatUsd(getPoolUsdWithoutPnl(marketInfo, false, "midPrice"))} / ${formatUsd(getStrictestMaxPoolUsdForDeposit(marketInfo, false))})` : "", ], [ diff --git a/src/domain/synthetics/markets/utils.ts b/src/domain/synthetics/markets/utils.ts index 4f9a662d67..df8f7e87a1 100644 --- a/src/domain/synthetics/markets/utils.ts +++ b/src/domain/synthetics/markets/utils.ts @@ -405,13 +405,13 @@ export function getTotalAccruedFundingUsd(positions: PositionInfo[]) { function getDepositCapacityAmount(marketInfo: MarketInfo, isLong: boolean) { const poolAmount = isLong ? marketInfo.longPoolAmount : marketInfo.shortPoolAmount; - const maxPoolAmount = getMaxPoolAmount(marketInfo, isLong); + const maxPoolAmount = getStrictestMaxPoolAmountForDeposit(marketInfo, isLong); const capacityAmount = maxPoolAmount - poolAmount; return bigMath.max(0n, capacityAmount); } -export function getMaxPoolAmount(marketInfo: MarketInfo, isLong: boolean) { +export function getStrictestMaxPoolAmountForDeposit(marketInfo: MarketInfo, isLong: boolean) { const maxPoolUsdForDeposit = isLong ? marketInfo.maxLongPoolUsdForDeposit : marketInfo.maxShortPoolUsdForDeposit; const maxPoolAmount = isLong ? marketInfo.maxLongPoolAmount : marketInfo.maxShortPoolAmount; const token = isLong ? marketInfo.longToken : marketInfo.shortToken; @@ -422,16 +422,28 @@ export function getMaxPoolAmount(marketInfo: MarketInfo, isLong: boolean) { return bigMath.min(maxPoolAmount, maxPoolAmountForDeposit); } -export function getMaxPoolUsd(marketInfo: MarketInfo, isLong: boolean) { +export function getStrictestMaxPoolUsdForDeposit(marketInfo: MarketInfo, isLong: boolean) { const token = isLong ? marketInfo.longToken : marketInfo.shortToken; - const maxPoolAmount = getMaxPoolAmount(marketInfo, isLong); + const maxPoolAmount = getStrictestMaxPoolAmountForDeposit(marketInfo, isLong); return convertToUsd(maxPoolAmount, token.decimals, getMidPrice(token.prices))!; } +export function getSwapCapacityUsd(marketInfo: MarketInfo, isLong: boolean) { + const poolAmount = isLong ? marketInfo.longPoolAmount : marketInfo.shortPoolAmount; + const maxPoolAmount = isLong ? marketInfo.maxLongPoolAmount : marketInfo.maxShortPoolAmount; + + const capacityAmount = maxPoolAmount - poolAmount; + const token = isLong ? marketInfo.longToken : marketInfo.shortToken; + + const capacityUsd = convertToUsd(capacityAmount, token.decimals, getMidPrice(token.prices))!; + + return capacityUsd; +} + export function getDepositCapacityUsd(marketInfo: MarketInfo, isLong: boolean) { const poolUsd = getPoolUsdWithoutPnl(marketInfo, isLong, "midPrice"); - const maxPoolUsd = getMaxPoolUsd(marketInfo, isLong); + const maxPoolUsd = getStrictestMaxPoolUsdForDeposit(marketInfo, isLong); const capacityUsd = maxPoolUsd - poolUsd; diff --git a/src/domain/synthetics/trade/types.ts b/src/domain/synthetics/trade/types.ts index 4b5237fa02..1ffbaba043 100644 --- a/src/domain/synthetics/trade/types.ts +++ b/src/domain/synthetics/trade/types.ts @@ -167,6 +167,7 @@ export type SwapStats = { isWrap: boolean; isUnwrap: boolean; isOutLiquidity?: boolean; + isOutCapacity?: boolean; swapFeeAmount: bigint; swapFeeUsd: bigint; priceImpactDeltaUsd: bigint; diff --git a/src/domain/synthetics/trade/utils/swapRouting.ts b/src/domain/synthetics/trade/utils/swapRouting.ts index 53cdb695af..a21d5b9d27 100644 --- a/src/domain/synthetics/trade/utils/swapRouting.ts +++ b/src/domain/synthetics/trade/utils/swapRouting.ts @@ -1,7 +1,13 @@ -import { getAvailableUsdLiquidityForCollateral, MarketInfo, MarketsInfoData } from "domain/synthetics/markets"; +import { + getAvailableUsdLiquidityForCollateral, + getSwapCapacityUsd, + MarketInfo, + MarketsInfoData, +} from "domain/synthetics/markets"; import { MarketEdge, MarketsGraph, SwapEstimator, SwapRoute } from "../types"; import { getMaxSwapPathLiquidity, getSwapStats } from "./swapStats"; import { SWAP_GRAPH_MAX_MARKETS_PER_TOKEN } from "config/markets"; +import { bigMath } from "lib/bigmath"; // limit the number of markets to most N=SWAP_GRAPH_MAX_MARKETS_PER_TOKEN liquid markets for each collateral export function limitMarketsPerTokens(markets: MarketInfo[]): MarketInfo[] { @@ -30,8 +36,16 @@ export function limitMarketsPerTokens(markets: MarketInfo[]): MarketInfo[] { const sortedMarkets = markets.sort((m1, m2) => { const liq1 = getAvailableUsdLiquidityForCollateral(m1, m1.longTokenAddress === tokenAddress); + const cap1 = getSwapCapacityUsd(m1, m1.longTokenAddress === tokenAddress); + + const limit1 = bigMath.min(liq1, cap1); + const liq2 = getAvailableUsdLiquidityForCollateral(m2, m2.longTokenAddress === tokenAddress); - return Number(liq2 - liq1); + const cap2 = getSwapCapacityUsd(m2, m2.longTokenAddress === tokenAddress); + + const limit2 = bigMath.min(liq2, cap2); + + return Number(limit2 - limit1); }); let marketsPerTokenCount = 0; @@ -102,9 +116,10 @@ export const createSwapEstimator = (marketsInfoData: MarketsInfoData): SwapEstim }); const isOutLiquidity = swapStats?.isOutLiquidity; + const isOutCapacity = swapStats?.isOutCapacity; const usdOut = swapStats?.usdOut; - if (usdOut === undefined || isOutLiquidity) { + if (usdOut === undefined || isOutLiquidity || isOutCapacity) { return { usdOut: 0n, }; diff --git a/src/domain/synthetics/trade/utils/swapStats.ts b/src/domain/synthetics/trade/utils/swapStats.ts index ddcdb2eaef..44b1550c9d 100644 --- a/src/domain/synthetics/trade/utils/swapStats.ts +++ b/src/domain/synthetics/trade/utils/swapStats.ts @@ -1,15 +1,16 @@ -import { NATIVE_TOKEN_ADDRESS } from "sdk/configs/tokens"; import { getSwapFee } from "domain/synthetics/fees"; import { MarketInfo, MarketsInfoData, getAvailableUsdLiquidityForCollateral, getOppositeCollateral, + getSwapCapacityUsd, getTokenPoolType, } from "domain/synthetics/markets"; import { convertToTokenAmount, convertToUsd } from "domain/synthetics/tokens"; import { ethers } from "ethers"; import { getByKey } from "lib/objects"; +import { NATIVE_TOKEN_ADDRESS } from "sdk/configs/tokens"; import { applySwapImpactWithCap, getPriceImpactForSwap } from "../../fees/utils/priceImpact"; import { SwapPathStats, SwapStats } from "../types"; @@ -323,6 +324,10 @@ export function getSwapStats(p: { amountOut = convertToTokenAmount(usdOut, tokenOut.decimals, priceOut)!; + const capacityUsd = getSwapCapacityUsd(marketInfo, getTokenPoolType(marketInfo, tokenInAddress) === "long"); + + const isOutCapacity = capacityUsd < usdInAfterFees; + const liquidity = getAvailableUsdLiquidityForCollateral( marketInfo, getTokenPoolType(marketInfo, tokenOutAddress) === "long" @@ -345,5 +350,6 @@ export function getSwapStats(p: { amountOut, usdOut, isOutLiquidity, + isOutCapacity, }; } diff --git a/src/pages/SyntheticsStats/SyntheticsStats.tsx b/src/pages/SyntheticsStats/SyntheticsStats.tsx index c7204e8ee1..53ec3ddbce 100644 --- a/src/pages/SyntheticsStats/SyntheticsStats.tsx +++ b/src/pages/SyntheticsStats/SyntheticsStats.tsx @@ -1,38 +1,40 @@ +import { ethers } from "ethers"; import { useChainId } from "lib/chains"; import { CHART_PERIODS } from "lib/legacy"; -import { ethers } from "ethers"; import { expandDecimals, formatAmount, formatUsd, PRECISION } from "lib/numbers"; import cx from "classnames"; +import { DownloadAsCsv } from "components/DownloadAsCsv/DownloadAsCsv"; import { ShareBar } from "components/ShareBar/ShareBar"; import StatsTooltipRow from "components/StatsTooltip/StatsTooltipRow"; +import TooltipWithPortal from "components/Tooltip/TooltipWithPortal"; +import { FACTOR_TO_PERCENT_MULTIPLIER_BIGINT } from "config/factors"; +import { format } from "date-fns"; import { getBorrowingFactorPerPeriod, getFundingFactorPerPeriod, getPriceImpactUsd } from "domain/synthetics/fees"; import { - MarketInfo, - getUsedLiquidity, getAvailableUsdLiquidityForCollateral, + getCappedPoolPnl, getMarketIndexName, + getMarketNetPnl, + getMarketPnl, getMarketPoolName, getMaxOpenInterestUsd, getMaxReservedUsd, + getPoolUsdWithoutPnl, getReservedUsd, + getStrictestMaxPoolUsdForDeposit, + getSwapCapacityUsd, + getUsedLiquidity, + MarketInfo, useMarketsInfoRequest, - getMarketNetPnl, - getMarketPnl, - getCappedPoolPnl, - getPoolUsdWithoutPnl, } from "domain/synthetics/markets"; +import { useKinkModelMarketsRates } from "domain/synthetics/markets/useKinkModelMarketsRates"; import { usePositionsConstantsRequest } from "domain/synthetics/positions"; import { convertToUsd, getMidPrice } from "domain/synthetics/tokens"; -import "./SyntheticsStats.scss"; -import TooltipWithPortal from "components/Tooltip/TooltipWithPortal"; -import { DownloadAsCsv } from "components/DownloadAsCsv/DownloadAsCsv"; -import { format } from "date-fns"; -import { getPlusOrMinusSymbol, getPositiveOrNegativeClass } from "lib/utils"; -import { useKinkModelMarketsRates } from "domain/synthetics/markets/useKinkModelMarketsRates"; import { bigMath } from "lib/bigmath"; import { formatAmountHuman } from "lib/numbers"; -import { FACTOR_TO_PERCENT_MULTIPLIER_BIGINT } from "config/factors"; +import { getPlusOrMinusSymbol, getPositiveOrNegativeClass } from "lib/utils"; +import "./SyntheticsStats.scss"; function pow(bn: bigint, exponent: bigint) { // this is just aproximation @@ -366,17 +368,34 @@ export function SyntheticsStats() { function renderPoolCapCell(isLong: boolean) { const poolAmount = isLong ? market.longPoolAmount : market.shortPoolAmount; - const maxPoolUsdForDeposit = isLong - ? market.maxLongPoolUsdForDeposit - : market.maxShortPoolUsdForDeposit; + const maxPoolUsdForSwap = getSwapCapacityUsd(market, isLong); + const maxPoolUsdForDeposit = getStrictestMaxPoolUsdForDeposit(market, isLong); const token = isLong ? market.longToken : market.shortToken; const poolUsd = convertToUsd(poolAmount, token.decimals, getMidPrice(token.prices)); return ( -
- {formatAmountHuman(poolAmount, token.decimals)} {token.symbol} / {formatUsd(maxPoolUsdForDeposit)}{" "} - -
+ + {formatAmountHuman(poolAmount, token.decimals)} {token.symbol} / {formatUsd(maxPoolUsdForSwap)}{" "} + + + } + renderContent={() => ( + <> + + + + )} + /> ); } From 7fd2c0a30c4f69b9fde82d959e1f4d4cd0bbaa00 Mon Sep 17 00:00:00 2001 From: Divhead Date: Mon, 13 Jan 2025 13:09:01 +0300 Subject: [PATCH 2/6] fix swap capacity --- src/domain/synthetics/markets/utils.ts | 7 +++++++ src/pages/SyntheticsStats/SyntheticsStats.tsx | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/domain/synthetics/markets/utils.ts b/src/domain/synthetics/markets/utils.ts index df8f7e87a1..4c64f725e3 100644 --- a/src/domain/synthetics/markets/utils.ts +++ b/src/domain/synthetics/markets/utils.ts @@ -429,6 +429,13 @@ export function getStrictestMaxPoolUsdForDeposit(marketInfo: MarketInfo, isLong: return convertToUsd(maxPoolAmount, token.decimals, getMidPrice(token.prices))!; } +export function getMaxPoolUseForSwap(marketInfo: MarketInfo, isLong: boolean) { + const token = isLong ? marketInfo.longToken : marketInfo.shortToken; + const maxPoolAmount = isLong ? marketInfo.maxLongPoolAmount : marketInfo.maxShortPoolAmount; + + return convertToUsd(maxPoolAmount, token.decimals, getMidPrice(token.prices))!; +} + export function getSwapCapacityUsd(marketInfo: MarketInfo, isLong: boolean) { const poolAmount = isLong ? marketInfo.longPoolAmount : marketInfo.shortPoolAmount; const maxPoolAmount = isLong ? marketInfo.maxLongPoolAmount : marketInfo.maxShortPoolAmount; diff --git a/src/pages/SyntheticsStats/SyntheticsStats.tsx b/src/pages/SyntheticsStats/SyntheticsStats.tsx index 53ec3ddbce..a1cf8964bd 100644 --- a/src/pages/SyntheticsStats/SyntheticsStats.tsx +++ b/src/pages/SyntheticsStats/SyntheticsStats.tsx @@ -368,7 +368,7 @@ export function SyntheticsStats() { function renderPoolCapCell(isLong: boolean) { const poolAmount = isLong ? market.longPoolAmount : market.shortPoolAmount; - const maxPoolUsdForSwap = getSwapCapacityUsd(market, isLong); + const maxPoolUsdForSwap = getMaxPoolUseForSwap(market, isLong); const maxPoolUsdForDeposit = getStrictestMaxPoolUsdForDeposit(market, isLong); const token = isLong ? market.longToken : market.shortToken; const poolUsd = convertToUsd(poolAmount, token.decimals, getMidPrice(token.prices)); From 89a1462f396edaa77e40add6dd658c9ef6437a7f Mon Sep 17 00:00:00 2001 From: Divhead Date: Mon, 13 Jan 2025 13:09:40 +0300 Subject: [PATCH 3/6] fix swap max capacity --- src/pages/SyntheticsStats/SyntheticsStats.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/SyntheticsStats/SyntheticsStats.tsx b/src/pages/SyntheticsStats/SyntheticsStats.tsx index a1cf8964bd..eaa6c37742 100644 --- a/src/pages/SyntheticsStats/SyntheticsStats.tsx +++ b/src/pages/SyntheticsStats/SyntheticsStats.tsx @@ -19,11 +19,11 @@ import { getMarketPnl, getMarketPoolName, getMaxOpenInterestUsd, + getMaxPoolUseForSwap, getMaxReservedUsd, getPoolUsdWithoutPnl, getReservedUsd, getStrictestMaxPoolUsdForDeposit, - getSwapCapacityUsd, getUsedLiquidity, MarketInfo, useMarketsInfoRequest, From 15335b65382b99192e29f57e5d8f946e028a32d4 Mon Sep 17 00:00:00 2001 From: Divhead Date: Mon, 13 Jan 2025 14:40:23 +0300 Subject: [PATCH 4/6] fix typo --- src/domain/synthetics/markets/utils.ts | 2 +- src/pages/SyntheticsStats/SyntheticsStats.tsx | 26 ++++++++++++++----- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/domain/synthetics/markets/utils.ts b/src/domain/synthetics/markets/utils.ts index 4c64f725e3..ce5d1562b1 100644 --- a/src/domain/synthetics/markets/utils.ts +++ b/src/domain/synthetics/markets/utils.ts @@ -429,7 +429,7 @@ export function getStrictestMaxPoolUsdForDeposit(marketInfo: MarketInfo, isLong: return convertToUsd(maxPoolAmount, token.decimals, getMidPrice(token.prices))!; } -export function getMaxPoolUseForSwap(marketInfo: MarketInfo, isLong: boolean) { +export function getMaxPoolUsdForSwap(marketInfo: MarketInfo, isLong: boolean) { const token = isLong ? marketInfo.longToken : marketInfo.shortToken; const maxPoolAmount = isLong ? marketInfo.maxLongPoolAmount : marketInfo.maxShortPoolAmount; diff --git a/src/pages/SyntheticsStats/SyntheticsStats.tsx b/src/pages/SyntheticsStats/SyntheticsStats.tsx index eaa6c37742..55fbca8f11 100644 --- a/src/pages/SyntheticsStats/SyntheticsStats.tsx +++ b/src/pages/SyntheticsStats/SyntheticsStats.tsx @@ -19,7 +19,7 @@ import { getMarketPnl, getMarketPoolName, getMaxOpenInterestUsd, - getMaxPoolUseForSwap, + getMaxPoolUsdForSwap, getMaxReservedUsd, getPoolUsdWithoutPnl, getReservedUsd, @@ -368,8 +368,12 @@ export function SyntheticsStats() { function renderPoolCapCell(isLong: boolean) { const poolAmount = isLong ? market.longPoolAmount : market.shortPoolAmount; - const maxPoolUsdForSwap = getMaxPoolUseForSwap(market, isLong); - const maxPoolUsdForDeposit = getStrictestMaxPoolUsdForDeposit(market, isLong); + const maxPoolUsdForSwap = getMaxPoolUsdForSwap(market, isLong); + const maxPoolUsdForDeposit = isLong + ? market.maxLongPoolUsdForDeposit + : market.maxShortPoolUsdForDeposit; + const maxPoolAmount = isLong ? market.maxLongPoolAmount : market.maxShortPoolAmount; + const maxPoolUsd = getStrictestMaxPoolUsdForDeposit(market, isLong); const token = isLong ? market.longToken : market.shortToken; const poolUsd = convertToUsd(poolAmount, token.decimals, getMidPrice(token.prices)); @@ -378,21 +382,31 @@ export function SyntheticsStats() { handle={
{formatAmountHuman(poolAmount, token.decimals)} {token.symbol} / {formatUsd(maxPoolUsdForSwap)}{" "} - +
} renderContent={() => ( <> + + )} /> From d73e9836ff264e64f6629e2dfe6f04a065729a5c Mon Sep 17 00:00:00 2001 From: Divhead Date: Mon, 13 Jan 2025 19:12:17 +0300 Subject: [PATCH 5/6] use min caps --- src/pages/SyntheticsStats/SyntheticsStats.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/SyntheticsStats/SyntheticsStats.tsx b/src/pages/SyntheticsStats/SyntheticsStats.tsx index 55fbca8f11..a18992e3ad 100644 --- a/src/pages/SyntheticsStats/SyntheticsStats.tsx +++ b/src/pages/SyntheticsStats/SyntheticsStats.tsx @@ -381,7 +381,7 @@ export function SyntheticsStats() { - {formatAmountHuman(poolAmount, token.decimals)} {token.symbol} / {formatUsd(maxPoolUsdForSwap)}{" "} + {formatAmountHuman(poolAmount, token.decimals)} {token.symbol} / {formatUsd(maxPoolUsd)}{" "} } From abe6b2c363a965909e81eae6b5fc4e4e2e076be4 Mon Sep 17 00:00:00 2001 From: Divhead Date: Mon, 13 Jan 2025 22:27:17 +0300 Subject: [PATCH 6/6] rebuild