add checkbox to swap review to accept high price impact (#433)
* add checkbox to swap review to accept high price impact * use coingecko price
This commit is contained in:
parent
92199db112
commit
676f9e09a7
|
@ -6,6 +6,8 @@ const UninsuredNotification = ({ name }: { name: string | undefined }) => {
|
|||
const { t } = useTranslation(['common', 'account'])
|
||||
return (
|
||||
<InlineNotification
|
||||
hideBorder
|
||||
hidePadding
|
||||
type="info"
|
||||
desc={
|
||||
<>
|
||||
|
@ -13,7 +15,7 @@ const UninsuredNotification = ({ name }: { name: string | undefined }) => {
|
|||
wrapperClassName="inline"
|
||||
content={t('account:tooltip-warning-uninsured', { token: name })}
|
||||
>
|
||||
<span className="tooltip-underline">
|
||||
<span className="tooltip-underline text-th-fgd-3">
|
||||
{t('account:warning-uninsured', {
|
||||
token: name,
|
||||
})}
|
||||
|
|
|
@ -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<number | null>(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 = ({
|
|||
</div>
|
||||
</div>
|
||||
<div className="flex justify-center bg-th-bkg-1 px-6 pt-4">
|
||||
<div className="mb-3 flex w-full flex-col items-center border-b border-th-bkg-3 pb-4">
|
||||
<div className="flex w-full flex-col items-center pb-4">
|
||||
<div className="relative mb-2 w-[72px]">
|
||||
<TokenLogo bank={inputBank} size={40} />
|
||||
<div className="absolute right-0 top-0">
|
||||
<TokenLogo bank={outputBank} size={40} />
|
||||
</div>
|
||||
</div>
|
||||
<p className="mb-0.5 flex items-center text-center text-lg">
|
||||
<span className="mr-1 font-mono text-th-fgd-1">
|
||||
<FormatNumericValue value={amountIn} />
|
||||
</span>{' '}
|
||||
{inputTokenInfo?.symbol}
|
||||
<div className="mb-0.5 flex items-center text-center text-lg">
|
||||
<span>
|
||||
<span className="font-mono text-th-fgd-1">
|
||||
<FormatNumericValue value={amountIn} />
|
||||
</span>{' '}
|
||||
<span className="text-xs text-th-fgd-4">
|
||||
{inputBank?.name}
|
||||
</span>
|
||||
</span>
|
||||
<ArrowRightIcon className="mx-2 h-5 w-5 text-th-fgd-2" />
|
||||
<span className="mr-1 font-mono text-th-fgd-1">
|
||||
<FormatNumericValue value={amountOut} />
|
||||
</span>{' '}
|
||||
{`${outputTokenInfo?.symbol}`}
|
||||
</p>
|
||||
<span>
|
||||
<span className="font-mono text-th-fgd-1">
|
||||
<FormatNumericValue value={amountOut} />
|
||||
</span>{' '}
|
||||
<span className="text-xs text-th-fgd-4">
|
||||
{outputBank?.name}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-2 overflow-auto px-6">
|
||||
<div className="flex justify-between">
|
||||
<p className="text-sm text-th-fgd-3">{t('price')}</p>
|
||||
<p className="text-sm text-th-fgd-3">{t('swap:rate')}</p>
|
||||
<div>
|
||||
<div className="flex items-center justify-end">
|
||||
<p className="text-right font-mono text-sm text-th-fgd-2">
|
||||
|
@ -781,8 +800,7 @@ const SwapReviewRouteInfo = ({
|
|||
/>
|
||||
</div>
|
||||
<div className="space-y-2 px-1 text-xs">
|
||||
{coingeckoPrices?.outputCoingeckoPrice &&
|
||||
coingeckoPrices?.inputCoingeckoPrice ? (
|
||||
{coinGeckoPriceDifference ? (
|
||||
<div
|
||||
className={`text-right font-mono ${
|
||||
coinGeckoPriceDifference.gt(1)
|
||||
|
@ -995,18 +1013,29 @@ const SwapReviewRouteInfo = ({
|
|||
</>
|
||||
) : null}
|
||||
</div>
|
||||
{!isInsured ? (
|
||||
<div className="mt-4 px-6">
|
||||
<UninsuredNotification name={outputBank?.name} />
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="p-6">
|
||||
{showPriceImpactCheck ? (
|
||||
<div className="mb-4 rounded-md border border-th-error p-2">
|
||||
<Checkbox
|
||||
checked={acceptPriceImpact}
|
||||
onChange={(e) => setAcceptPriceImpact(e.target.checked)}
|
||||
>
|
||||
<p className="whitespace-normal text-th-fgd-2">
|
||||
{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'}
|
||||
</p>
|
||||
</Checkbox>
|
||||
</div>
|
||||
) : null}
|
||||
<div className="mb-4 flex items-center justify-center">
|
||||
<Button
|
||||
onClick={onClick}
|
||||
className="flex w-full items-center justify-center text-base"
|
||||
size="large"
|
||||
disabled={showPriceImpactCheck && !acceptPriceImpact}
|
||||
>
|
||||
{submitting ? (
|
||||
<Loading className="mr-2 h-5 w-5" />
|
||||
|
@ -1116,6 +1145,11 @@ const SwapReviewRouteInfo = ({
|
|||
)}
|
||||
</Disclosure>
|
||||
</div>
|
||||
{!isInsured ? (
|
||||
<div className="mt-4">
|
||||
<UninsuredNotification name={outputBank?.name} />
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
{showRoutesModal ? (
|
||||
<RoutesModal
|
||||
|
|
Loading…
Reference in New Issue