Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion sdk/src/configs/factors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ export { USD_DECIMALS, BASIS_POINTS_DIVISOR, BASIS_POINTS_DIVISOR_BIGINT, BASIS_

// V2
export const HIGH_PRICE_IMPACT_BPS = 80; // 0.8%
export const HIGH_POSITION_IMPACT_BPS = 50; // 0.5%
export const HIGH_COLLATERAL_IMPACT_BPS = 2500; // 25%
export const HIGH_SWAP_IMPACT_BPS = 50; // 0.5%
export const DEFAULT_ACCEPTABLE_PRICE_IMPACT_BUFFER = 30; // 0.3%
Expand Down
82 changes: 55 additions & 27 deletions src/components/DepthChart/DepthChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import {
} from "lib/numbers";
import { sendDepthChartInteractionEvent } from "lib/userAnalytics";
import { bigMath } from "sdk/utils/bigmath";
import { getPriceImpactForPosition } from "sdk/utils/fees/priceImpact";
import { getCappedPositionImpactUsd, getPriceImpactForPosition } from "sdk/utils/fees/priceImpact";

import { ChartTooltip, ChartTooltipHandle } from "./DepthChartTooltip";

Expand Down Expand Up @@ -800,9 +800,16 @@ function useDepthChartPricesData(
const leftInc = (leftMax - DOLLAR) / SIDE_POINTS_COUNT;
// from left to center
for (let positionSize = leftMax; positionSize >= DOLLAR; positionSize -= leftInc) {
const { priceImpactDeltaUsd: priceImpactUsd } = getPriceImpactForPosition(marketInfo, positionSize, false, {
fallbackToZero: true,
});
const { priceImpactDeltaUsd: priceImpactUsd } = getCappedPositionImpactUsd(
marketInfo,
positionSize,
false,
true,
{
fallbackToZero: true,
shouldCapNegativeImpact: true,
}
);

const executionPrice = getDepthChartExecutionPrice({
isIncrease: true,
Expand Down Expand Up @@ -831,8 +838,9 @@ function useDepthChartPricesData(
});

if (positionSize - leftInc < leftMin && positionSize > leftMin && leftMin > DOLLAR) {
const { priceImpactDeltaUsd: priceImpactUsd } = getPriceImpactForPosition(marketInfo, leftMin, false, {
const { priceImpactDeltaUsd: priceImpactUsd } = getCappedPositionImpactUsd(marketInfo, leftMin, false, true, {
fallbackToZero: true,
shouldCapNegativeImpact: true,
});

const executionPrice = getDepthChartExecutionPrice({
Expand Down Expand Up @@ -866,8 +874,9 @@ function useDepthChartPricesData(
}

if (positionSize - leftInc < DOLLAR && positionSize > DOLLAR) {
const { priceImpactDeltaUsd: priceImpactUsd } = getPriceImpactForPosition(marketInfo, DOLLAR, false, {
const { priceImpactDeltaUsd: priceImpactUsd } = getCappedPositionImpactUsd(marketInfo, DOLLAR, false, true, {
fallbackToZero: true,
shouldCapNegativeImpact: true,
});

const executionPrice = getDepthChartExecutionPrice({
Expand Down Expand Up @@ -905,9 +914,16 @@ function useDepthChartPricesData(

// from right max to center
for (let positionSize = rightMax; positionSize >= DOLLAR; positionSize -= rightInc) {
const { priceImpactDeltaUsd: priceImpactUsd } = getPriceImpactForPosition(marketInfo, positionSize, true, {
fallbackToZero: true,
});
const { priceImpactDeltaUsd: priceImpactUsd } = getCappedPositionImpactUsd(
marketInfo,
positionSize,
true,
true,
{
fallbackToZero: true,
shouldCapNegativeImpact: true,
}
);

const executionPrice = getDepthChartExecutionPrice({
isIncrease: true,
Expand Down Expand Up @@ -936,8 +952,9 @@ function useDepthChartPricesData(
});

if (positionSize - rightInc < rightMin && positionSize > rightMin && rightMin > DOLLAR) {
const { priceImpactDeltaUsd: priceImpactUsd } = getPriceImpactForPosition(marketInfo, rightMin, true, {
const { priceImpactDeltaUsd: priceImpactUsd } = getCappedPositionImpactUsd(marketInfo, rightMin, true, true, {
fallbackToZero: true,
shouldCapNegativeImpact: true,
});

const executionPrice = getDepthChartExecutionPrice({
Expand Down Expand Up @@ -971,8 +988,9 @@ function useDepthChartPricesData(
}

if (positionSize - rightInc < DOLLAR && positionSize > DOLLAR) {
const { priceImpactDeltaUsd: priceImpactUsd } = getPriceImpactForPosition(marketInfo, DOLLAR, true, {
const { priceImpactDeltaUsd: priceImpactUsd } = getCappedPositionImpactUsd(marketInfo, DOLLAR, true, true, {
fallbackToZero: true,
shouldCapNegativeImpact: true,
});

const executionPrice = getDepthChartExecutionPrice({
Expand Down Expand Up @@ -1145,9 +1163,13 @@ function useEdgePoints(
let rightMaxExecutionPrice = 0n;

{
const { priceImpactDeltaUsd: priceImpactUsd } = getPriceImpactForPosition(marketInfo, rightMax, true, {
const { priceImpactDeltaUsd: uncappedPriceImpactUsd } = getPriceImpactForPosition(marketInfo, rightMax, true, {
fallbackToZero: true,
});
const { priceImpactDeltaUsd: priceImpactUsd } = getCappedPositionImpactUsd(marketInfo, rightMax, true, true, {
fallbackToZero: true,
shouldCapNegativeImpact: true,
});

const executionPrice = getDepthChartExecutionPrice({
isIncrease: true,
Expand All @@ -1158,25 +1180,31 @@ function useEdgePoints(
visualMultiplier: marketInfo.indexToken.visualMultiplier,
})!;

rightMaxExecutionPrice = executionPrice;
const isCapReached = uncappedPriceImpactUsd < priceImpactUsd;

rightMaxExecutionPrice = executionPrice + (isCapReached ? bigMath.mulDiv(executionPrice, 1n, 1000n) : 0n);
}

{
const { priceImpactDeltaUsd: priceImpactUsd } = getPriceImpactForPosition(marketInfo, leftMax, false, {
fallbackToZero: true,
});
const { priceImpactDeltaUsd: uncappedPriceImpactUsd } = getPriceImpactForPosition(marketInfo, leftMax, false, {
fallbackToZero: true,
});
const { priceImpactDeltaUsd: priceImpactUsd } = getCappedPositionImpactUsd(marketInfo, leftMax, false, true, {
fallbackToZero: true,
shouldCapNegativeImpact: true,
});

const executionPrice = getDepthChartExecutionPrice({
isIncrease: true,
isLong: false,
priceImpactUsd,
sizeDeltaUsd: leftMax === 0n ? DOLLAR : leftMax,
triggerPrice: marketInfo.indexToken.prices.minPrice,
visualMultiplier: marketInfo.indexToken.visualMultiplier,
})!;
const executionPrice = getDepthChartExecutionPrice({
isIncrease: true,
isLong: false,
priceImpactUsd,
sizeDeltaUsd: leftMax === 0n ? DOLLAR : leftMax,
triggerPrice: marketInfo.indexToken.prices.minPrice,
visualMultiplier: marketInfo.indexToken.visualMultiplier,
})!;

leftMaxExecutionPrice = executionPrice;
}
const isCapReached = uncappedPriceImpactUsd < priceImpactUsd;

leftMaxExecutionPrice = executionPrice - (isCapReached ? bigMath.mulDiv(executionPrice, 1n, 1000n) : 0n);

return {
leftMaxExecutionPrice,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { t } from "@lingui/macro";
import { t, Trans } from "@lingui/macro";
import { useMemo } from "react";

import { DOCS_LINKS } from "config/links";
import { FeeItem } from "domain/synthetics/fees";
import { WarningState } from "domain/synthetics/trade/usePriceImpactWarningState";
import { formatPercentage, formatUsd } from "lib/numbers";
import { formatUsd } from "lib/numbers";

import { AlertInfoCard } from "components/AlertInfo/AlertInfoCard";
import ExternalLink from "components/ExternalLink/ExternalLink";
import TooltipWithPortal from "components/Tooltip/TooltipWithPortal";

export type Props = {
priceImpactWarningState: WarningState;
collateralImpact?: FeeItem;
positionImpact?: FeeItem;
swapPriceImpact?: FeeItem;
swapProfitFee?: FeeItem;
externalSwapFeeItem?: FeeItem;
Expand All @@ -19,28 +20,27 @@ export type Props = {

export function HighPriceImpactOrFeesWarningCard({
priceImpactWarningState,
collateralImpact,
positionImpact,
swapPriceImpact,
swapProfitFee,
externalSwapFeeItem,
executionFeeUsd,
}: Props) {
const warnings = useMemo(() => {
const warnings: { id: string; key: React.ReactNode; value?: React.ReactNode }[] = [];
if (priceImpactWarningState.shouldShowWarningForPosition) {
warnings.push({
id: "high-price-impact",
key: t`High price impact`,
value: formatPercentage(positionImpact?.precisePercentage, { signed: true, bps: false, displayDecimals: 3 }),
});
}
const warnings: { id: string; key: React.ReactNode; value?: React.ReactNode; tooltipContent?: React.ReactNode }[] =
[];

if (priceImpactWarningState.shouldShowWarningForCollateral) {
warnings.push({
id: "high-impact-on-collateral",
key: t`High impact on collateral`,
value: formatPercentage(collateralImpact?.precisePercentage, { signed: true, bps: false, displayDecimals: 3 }),
key: t`High Net Price Impact`,
value: undefined,
tooltipContent: (
<Trans>
The potential net price impact that will apply when closing this position may be high compared to the amount
of collateral you're using. Consider reducing leverage.{" "}
<ExternalLink href={DOCS_LINKS.priceImpact}>Read more</ExternalLink>.
</Trans>
),
});
}

Expand Down Expand Up @@ -94,8 +94,6 @@ export function HighPriceImpactOrFeesWarningCard({
}, [
priceImpactWarningState,
externalSwapFeeItem,
positionImpact?.precisePercentage,
collateralImpact?.precisePercentage,
executionFeeUsd,
swapPriceImpact?.deltaUsd,
swapProfitFee?.deltaUsd,
Expand All @@ -108,12 +106,20 @@ export function HighPriceImpactOrFeesWarningCard({
return (
<AlertInfoCard className="h-fit" type="warning" onClose={() => priceImpactWarningState.setIsDismissed(true)}>
<div className="flex flex-col gap-4">
{warnings.map((warning) => (
<div key={warning.id} className="flex justify-between gap-4">
<div>{warning.key}</div>
<div className="font-medium text-yellow-300">{warning.value}</div>
</div>
))}
{warnings.map((warning) => {
const warningContent = (
<div key={warning.id} className="flex justify-between gap-4">
<div>{warning.key}</div>
<div className="font-medium text-yellow-300">{warning.value}</div>
</div>
);

return warning.tooltipContent ? (
<TooltipWithPortal handle={warningContent} content={warning.tooltipContent} position="bottom" />
) : (
warningContent
);
})}
</div>
</AlertInfoCard>
);
Expand Down
33 changes: 1 addition & 32 deletions src/components/PoolSelector2/PoolSelector2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type { MarketLiquidityAndFeeStat } from "context/SyntheticsStateContext/s
import { getMarketPoolName } from "domain/synthetics/markets/utils";
import type { MarketStat } from "domain/synthetics/stats/marketsInfoDataToIndexTokensStats";
import { TradeType } from "domain/synthetics/trade";
import { formatAmountHuman, formatPercentage, formatRatePercentage, formatUsd } from "lib/numbers";
import { formatAmountHuman, formatRatePercentage, formatUsd } from "lib/numbers";

import { TableTd, TableTh, TableTheadTr } from "components/Table/Table";
import TokenIcon from "components/TokenIcon/TokenIcon";
Expand Down Expand Up @@ -62,9 +62,6 @@ function PoolSelector2Desktop(props: Props) {
<TableTh padding="compact">
<Trans>Net Rate</Trans>
</TableTh>
<TableTh padding="compact">
<Trans>Impact+Fees</Trans>
</TableTh>
</TableTheadTr>
</thead>
<tbody>
Expand All @@ -73,7 +70,6 @@ function PoolSelector2Desktop(props: Props) {
key={option.marketInfo.marketTokenAddress}
marketStat={option}
tradeType={props.tradeType}
openFees={props.positionStats[option.marketInfo.marketTokenAddress].openFees}
isEnoughLiquidity={props.positionStats[option.marketInfo.marketTokenAddress].isEnoughLiquidity}
liquidity={props.positionStats[option.marketInfo.marketTokenAddress].liquidity}
data-qa="pool-selector-row"
Expand All @@ -91,7 +87,6 @@ function PoolSelector2Desktop(props: Props) {
function PoolListItemDesktop({
marketStat,
tradeType,
openFees,
isEnoughLiquidity,
liquidity,
onSelect,
Expand All @@ -106,8 +101,6 @@ function PoolListItemDesktop({

const formattedNetRate = formatRatePercentage(isLong ? marketStat.netFeeLong : marketStat.netFeeShort);
const netRateState = numberToState(isLong ? marketStat.netFeeLong : marketStat.netFeeShort);
const formattedOpenFees = openFees !== undefined ? formatPercentage(openFees, { signed: true }) : "-";
const openFeesState = numberToState(openFees);
const handleClick = useCallback(
(e: React.MouseEvent) => {
e.stopPropagation();
Expand Down Expand Up @@ -139,15 +132,6 @@ function PoolListItemDesktop({
>
<Trans>{formattedNetRate} / 1h</Trans>
</TableTd>
<TableTd
padding="compact"
className={cx("PoolSelector2-column-open-fees", {
"text-red-500": openFeesState === "error",
"text-green-500": openFeesState === "success",
})}
>
{formattedOpenFees}
</TableTd>
</SelectorBaseDesktopRow>
);
}
Expand All @@ -162,7 +146,6 @@ function PoolSelector2Mobile(props: Props) {
key={option.marketInfo.marketTokenAddress}
marketStat={option}
tradeType={props.tradeType}
openFees={props.positionStats[option.marketInfo.marketTokenAddress].openFees}
isEnoughLiquidity={props.positionStats[option.marketInfo.marketTokenAddress].isEnoughLiquidity}
liquidity={props.positionStats[option.marketInfo.marketTokenAddress].liquidity}
onSelect={() => {
Expand All @@ -178,7 +161,6 @@ function PoolSelector2Mobile(props: Props) {
function PoolListItemMobile({
marketStat,
tradeType,
openFees,
isEnoughLiquidity,
liquidity,
onSelect,
Expand All @@ -195,8 +177,6 @@ function PoolListItemMobile({
const formattedNetRate = formatRatePercentage(isLong ? marketStat.netFeeLong : marketStat.netFeeShort);

const netRateState = numberToState(isLong ? marketStat.netFeeLong : marketStat.netFeeShort);
const formattedOpenFees = openFees !== undefined ? formatPercentage(openFees, { signed: true }) : "-";
const openFeesState = numberToState(openFees);

return (
<SelectorBaseMobileButton
Expand Down Expand Up @@ -237,17 +217,6 @@ function PoolListItemMobile({
>
{formattedNetRate} / 1h
</dd>
<dt>
<Trans>Impact+Fees</Trans>
</dt>
<dd
className={cx({
"text-red-500": openFeesState === "error",
"text-green-500": openFeesState === "success",
})}
>
{formattedOpenFees}
</dd>
</dl>
</SelectorBaseMobileButton>
);
Expand Down
2 changes: 0 additions & 2 deletions src/components/PositionEditor/PositionEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,6 @@ export function PositionEditor() {

const priceImpactWarningState = usePriceImpactWarningState({
collateralNetPriceImpact: fees?.collateralNetPriceImpact,
positionNetPriceImpact: fees?.positionNetPriceImpact,
swapPriceImpact: fees?.swapPriceImpact,
swapProfitFee: fees?.swapProfitFee,
executionFeeUsd: executionFee?.feeUsd,
Expand Down Expand Up @@ -397,7 +396,6 @@ export function PositionEditor() {
<div className="flex flex-col gap-14">
<HighPriceImpactOrFeesWarningCard
priceImpactWarningState={priceImpactWarningState}
collateralImpact={fees?.collateralNetPriceImpact}
swapPriceImpact={fees?.swapPriceImpact}
swapProfitFee={fees?.swapProfitFee}
executionFeeUsd={executionFee?.feeUsd}
Expand Down
Loading