diff --git a/components/shared/UninsuredNotification.tsx b/components/shared/UninsuredNotification.tsx index cca493c7..d1a181fc 100644 --- a/components/shared/UninsuredNotification.tsx +++ b/components/shared/UninsuredNotification.tsx @@ -6,6 +6,8 @@ const UninsuredNotification = ({ name }: { name: string | undefined }) => { const { t } = useTranslation(['common', 'account']) return ( @@ -13,7 +15,7 @@ const UninsuredNotification = ({ name }: { name: string | undefined }) => { wrapperClassName="inline" content={t('account:tooltip-warning-uninsured', { token: name })} > - + {t('account:warning-uninsured', { token: name, })} diff --git a/components/swap/SwapReviewRouteInfo.tsx b/components/swap/SwapReviewRouteInfo.tsx index bac28a63..8b8d46db 100644 --- a/components/swap/SwapReviewRouteInfo.tsx +++ b/components/swap/SwapReviewRouteInfo.tsx @@ -67,6 +67,7 @@ import { isTokenInsured } from '@components/DepositForm' import UninsuredNotification from '@components/shared/UninsuredNotification' import { sendTxAndConfirm } from 'utils/governance/tools' import useAnalytics from 'hooks/useAnalytics' +import Checkbox from '@components/forms/Checkbox' type JupiterRouteInfoProps = { amountIn: Decimal @@ -320,6 +321,7 @@ const SwapReviewRouteInfo = ({ const [feeValue] = useState(null) const [submitting, setSubmitting] = useState(false) const [coingeckoPrices, setCoingeckoPrices] = useState(EMPTY_COINGECKO_PRICES) + const [acceptPriceImpact, setAcceptPriceImpact] = useState(false) const { jupiterTokens } = useJupiterMints() const { inputTokenInfo, outputTokenInfo } = useJupiterSwapData() const inputBank = mangoStore((s) => s.swap.inputBank) @@ -656,17 +658,21 @@ const SwapReviewRouteInfo = ({ }, [amountIn, inputBank, outputBank]) const coinGeckoPriceDifference = useMemo(() => { - return amountOut?.toNumber() - ? amountIn - .div(amountOut) - .minus( - new Decimal(coingeckoPrices?.outputCoingeckoPrice).div( - coingeckoPrices?.inputCoingeckoPrice, - ), - ) - .div(amountIn.div(amountOut)) - .mul(100) - : new Decimal(0) + if ( + !coingeckoPrices?.outputCoingeckoPrice || + !coingeckoPrices?.inputCoingeckoPrice || + !amountOut + ) + return + return amountIn + .div(amountOut) + .minus( + new Decimal(coingeckoPrices.outputCoingeckoPrice).div( + coingeckoPrices.inputCoingeckoPrice, + ), + ) + .div(amountIn.div(amountOut)) + .mul(100) }, [coingeckoPrices, amountIn, amountOut]) const isInsured = useMemo(() => { @@ -674,6 +680,11 @@ const SwapReviewRouteInfo = ({ return isTokenInsured(outputBank, group) }, [outputBank]) + const showPriceImpactCheck = useMemo(() => { + if (!coinGeckoPriceDifference) return true + return coinGeckoPriceDifference.gte(5) + }, [coinGeckoPriceDifference]) + return routes?.length && selectedRoute && inputTokenInfo && @@ -725,29 +736,37 @@ const SwapReviewRouteInfo = ({
-
+
-

- - - {' '} - {inputTokenInfo?.symbol} +

+ + + + {' '} + + {inputBank?.name} + + - - - {' '} - {`${outputTokenInfo?.symbol}`} -

+ + + + {' '} + + {outputBank?.name} + + +
-

{t('price')}

+

{t('swap:rate')}

@@ -781,8 +800,7 @@ const SwapReviewRouteInfo = ({ />

- {coingeckoPrices?.outputCoingeckoPrice && - coingeckoPrices?.inputCoingeckoPrice ? ( + {coinGeckoPriceDifference ? (
) : null}
- {!isInsured ? ( -
- -
- ) : null}
+ {showPriceImpactCheck ? ( +
+ setAcceptPriceImpact(e.target.checked)} + > +

+ {coinGeckoPriceDifference + ? `I accept the rate for this swap is + ${coinGeckoPriceDifference.toFixed(1)}% worse than Coingecko` + : 'I accept the price of this swap has not been benchmarked to Coingecko and could differ to current market prices'} +

+
+
+ ) : null}
+ {!isInsured ? ( +
+ +
+ ) : null}
{showRoutesModal ? (