fix: impact rendering (#3553)
* fix: price impact rendering * fix: webkit-compat gradient
This commit is contained in:
parent
377026bca8
commit
f508788026
@ -18,7 +18,7 @@ const ExpandoColumn = styled(Column)<{ height: number; open: boolean }>`
|
||||
transition: height 0.25s, padding 0.25s;
|
||||
|
||||
:after {
|
||||
background: linear-gradient(#ffffff00, ${({ theme }) => theme.dialog});
|
||||
background: linear-gradient(transparent, ${({ theme }) => theme.dialog});
|
||||
bottom: 0;
|
||||
content: '';
|
||||
height: 0.75em;
|
||||
|
@ -83,7 +83,7 @@ export default function Output({ disabled, focused, children }: PropsWithChildre
|
||||
<Row>
|
||||
<USDC gap={0.5} isLoading={isRouteLoading}>
|
||||
{outputUSDC ? `$${formatCurrencyAmount(outputUSDC, 6, 'en', 2)}` : '-'}{' '}
|
||||
{impact.display && <ThemedText.Body2 color={impact.warning}>({impact.display})</ThemedText.Body2>}
|
||||
{impact && <ThemedText.Body2 color={impact.warning}>({impact.toString()})</ThemedText.Body2>}
|
||||
</USDC>
|
||||
{balance && (
|
||||
<Balance focused={focused}>
|
||||
|
@ -1,10 +1,12 @@
|
||||
import { t } from '@lingui/macro'
|
||||
import { useLingui } from '@lingui/react'
|
||||
import { Trade } from '@uniswap/router-sdk'
|
||||
import { Currency, Percent, TradeType } from '@uniswap/sdk-core'
|
||||
import { Currency, TradeType } from '@uniswap/sdk-core'
|
||||
import { useAtomValue } from 'jotai/utils'
|
||||
import Column from 'lib/components/Column'
|
||||
import Row from 'lib/components/Row'
|
||||
import { Slippage } from 'lib/hooks/useSlippage'
|
||||
import { PriceImpact } from 'lib/hooks/useUSDCPriceImpact'
|
||||
import { feeOptionsAtom } from 'lib/state/swap'
|
||||
import styled, { Color, ThemedText } from 'lib/theme'
|
||||
import { useMemo } from 'react'
|
||||
@ -36,11 +38,11 @@ function Detail({ label, value, color }: DetailProps) {
|
||||
|
||||
interface DetailsProps {
|
||||
trade: Trade<Currency, Currency, TradeType>
|
||||
slippage: { auto: boolean; allowed: Percent; warning?: Color }
|
||||
priceImpact: { priceImpact?: string; warning?: Color }
|
||||
slippage: Slippage
|
||||
impact?: PriceImpact
|
||||
}
|
||||
|
||||
export default function Details({ trade, slippage, priceImpact }: DetailsProps) {
|
||||
export default function Details({ trade, slippage, impact }: DetailsProps) {
|
||||
const { inputAmount, outputAmount } = trade
|
||||
const inputCurrency = inputAmount.currency
|
||||
const outputCurrency = outputAmount.currency
|
||||
@ -61,8 +63,8 @@ export default function Details({ trade, slippage, priceImpact }: DetailsProps)
|
||||
}
|
||||
}
|
||||
|
||||
if (priceImpact.priceImpact) {
|
||||
rows.push([t`Price impact`, priceImpact.priceImpact, priceImpact.warning])
|
||||
if (impact) {
|
||||
rows.push([t`Price impact`, impact.toString(), impact.warning])
|
||||
}
|
||||
|
||||
if (lpFeeAmount) {
|
||||
@ -85,15 +87,15 @@ export default function Details({ trade, slippage, priceImpact }: DetailsProps)
|
||||
return rows
|
||||
}, [
|
||||
feeOptions,
|
||||
priceImpact,
|
||||
lpFeeAmount,
|
||||
trade,
|
||||
slippage,
|
||||
outputAmount,
|
||||
i18n.locale,
|
||||
integrator,
|
||||
outputCurrency,
|
||||
impact,
|
||||
inputCurrency,
|
||||
integrator,
|
||||
lpFeeAmount,
|
||||
outputAmount,
|
||||
outputCurrency,
|
||||
slippage,
|
||||
trade,
|
||||
])
|
||||
|
||||
return (
|
||||
|
@ -42,16 +42,16 @@ interface SummaryProps {
|
||||
output: CurrencyAmount<Currency>
|
||||
inputUSDC?: CurrencyAmount<Currency>
|
||||
outputUSDC?: CurrencyAmount<Currency>
|
||||
priceImpact?: PriceImpact
|
||||
impact?: PriceImpact
|
||||
}
|
||||
|
||||
export default function Summary({ input, output, inputUSDC, outputUSDC, priceImpact }: SummaryProps) {
|
||||
export default function Summary({ input, output, inputUSDC, outputUSDC, impact }: SummaryProps) {
|
||||
return (
|
||||
<Row gap={priceImpact ? 1 : 0.25}>
|
||||
<Row gap={impact ? 1 : 0.25}>
|
||||
<TokenValue input={input} usdc={inputUSDC} />
|
||||
<ArrowRight />
|
||||
<TokenValue input={output} usdc={outputUSDC}>
|
||||
{priceImpact && <ThemedText.Caption color={priceImpact.warning}>({priceImpact.display})</ThemedText.Caption>}
|
||||
{impact && <ThemedText.Caption color={impact.warning}>({impact.toString()})</ThemedText.Caption>}
|
||||
</TokenValue>
|
||||
</Row>
|
||||
)
|
||||
|
@ -10,7 +10,7 @@ import Row from 'lib/components/Row'
|
||||
import { Slippage } from 'lib/hooks/useSlippage'
|
||||
import { PriceImpact } from 'lib/hooks/useUSDCPriceImpact'
|
||||
import { AlertTriangle, BarChart, Info } from 'lib/icons'
|
||||
import styled, { Color, ThemedText } from 'lib/theme'
|
||||
import styled, { ThemedText } from 'lib/theme'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import { formatCurrencyAmount } from 'utils/formatCurrencyAmount'
|
||||
import { tradeMeaningfullyDiffers } from 'utils/tradeMeaningFullyDiffer'
|
||||
@ -41,16 +41,16 @@ const Body = styled(Column)<{ open: boolean }>`
|
||||
}
|
||||
`
|
||||
|
||||
function Subhead({ priceImpact, slippage }: { priceImpact: { warning?: Color }; slippage: Slippage }) {
|
||||
function Subhead({ impact, slippage }: { impact?: PriceImpact; slippage: Slippage }) {
|
||||
return (
|
||||
<Row gap={0.5}>
|
||||
{priceImpact.warning || slippage.warning ? (
|
||||
<AlertTriangle color={priceImpact.warning || slippage.warning} />
|
||||
{impact?.warning || slippage.warning ? (
|
||||
<AlertTriangle color={impact?.warning || slippage.warning} />
|
||||
) : (
|
||||
<Info color="secondary" />
|
||||
)}
|
||||
<ThemedText.Subhead2 color={priceImpact.warning || slippage.warning || 'secondary'}>
|
||||
{priceImpact.warning ? (
|
||||
<ThemedText.Subhead2 color={impact?.warning || slippage.warning || 'secondary'}>
|
||||
{impact?.warning ? (
|
||||
<Trans>High price impact</Trans>
|
||||
) : slippage.warning ? (
|
||||
<Trans>High slippage</Trans>
|
||||
@ -132,7 +132,7 @@ interface SummaryDialogProps {
|
||||
slippage: Slippage
|
||||
inputUSDC?: CurrencyAmount<Currency>
|
||||
outputUSDC?: CurrencyAmount<Currency>
|
||||
impact: PriceImpact
|
||||
impact?: PriceImpact
|
||||
onConfirm: () => void
|
||||
}
|
||||
|
||||
@ -152,23 +152,23 @@ export function SummaryDialog({ trade, slippage, inputUSDC, outputUSDC, impact,
|
||||
output={outputAmount}
|
||||
inputUSDC={inputUSDC}
|
||||
outputUSDC={outputUSDC}
|
||||
priceImpact={impact}
|
||||
impact={impact}
|
||||
/>
|
||||
<Price trade={trade} />
|
||||
</Heading>
|
||||
<Column gap={open ? 0 : 0.75} style={{ transition: 'gap 0.25s' }}>
|
||||
<Expando
|
||||
title={<Subhead priceImpact={impact} slippage={slippage} />}
|
||||
title={<Subhead impact={impact} slippage={slippage} />}
|
||||
open={open}
|
||||
onExpand={onExpand}
|
||||
height={7}
|
||||
>
|
||||
<Details trade={trade} slippage={slippage} priceImpact={impact} />
|
||||
<Details trade={trade} slippage={slippage} impact={impact} />
|
||||
</Expando>
|
||||
<Footing>
|
||||
<Estimate trade={trade} slippage={slippage} />
|
||||
</Footing>
|
||||
<ConfirmButton trade={trade} highPriceImpact={impact.warning === 'error'} onConfirm={onConfirm} />
|
||||
<ConfirmButton trade={trade} highPriceImpact={impact?.warning === 'error'} onConfirm={onConfirm} />
|
||||
</Column>
|
||||
</Body>
|
||||
</>
|
||||
|
@ -84,16 +84,17 @@ export function Trade({
|
||||
}: {
|
||||
trade: InterfaceTrade<Currency, Currency, TradeType>
|
||||
outputUSDC?: CurrencyAmount<Currency>
|
||||
impact: PriceImpact
|
||||
impact?: PriceImpact
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
<Tooltip placement="bottom" icon={impact.warning ? AlertTriangle : Info}>
|
||||
<Tooltip placement="bottom" icon={impact?.warning ? AlertTriangle : Info}>
|
||||
<Column gap={0.75}>
|
||||
{impact.warning && (
|
||||
{impact?.warning && (
|
||||
<>
|
||||
<ThemedText.Caption>
|
||||
The output amount is estimated at {impact.display} less than the input amount due to high price impact
|
||||
The output amount is estimated at {impact.toString()} less than the input amount due to high price
|
||||
impact
|
||||
</ThemedText.Caption>
|
||||
<Rule />
|
||||
</>
|
||||
|
@ -17,6 +17,7 @@ function TokenImg({ token, ...rest }: TokenImgProps) {
|
||||
// Use the wrapped token info so that it includes the logoURI.
|
||||
const tokenInfo = useToken(token.isToken ? token.wrapped.address : undefined) ?? token
|
||||
|
||||
// TODO(zzmp): TokenImg takes a frame to switch.
|
||||
const srcs = useCurrencyLogoURIs(tokenInfo)
|
||||
const [src, setSrc] = useState<string | undefined>()
|
||||
useEffect(() => {
|
||||
|
@ -28,7 +28,7 @@ interface SwapInfo {
|
||||
state: TradeState
|
||||
}
|
||||
slippage: Slippage
|
||||
impact: PriceImpact
|
||||
impact?: PriceImpact
|
||||
}
|
||||
|
||||
// from the current swap inputs, compute the best trade and return it.
|
||||
@ -65,11 +65,7 @@ function useComputeSwapInfo(): SwapInfo {
|
||||
// Compute slippage and impact off of the trade so that it refreshes with the trade.
|
||||
// (Using amountIn/amountOut would show (incorrect) intermediate values.)
|
||||
const slippage = useSlippage(trade.trade)
|
||||
const {
|
||||
inputUSDC: usdcIn,
|
||||
outputUSDC: usdcOut,
|
||||
priceImpact: impact,
|
||||
} = useUSDCPriceImpact(trade.trade?.inputAmount, trade.trade?.outputAmount)
|
||||
const { inputUSDC, outputUSDC, impact } = useUSDCPriceImpact(trade.trade?.inputAmount, trade.trade?.outputAmount)
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
@ -77,19 +73,31 @@ function useComputeSwapInfo(): SwapInfo {
|
||||
currency: currencyIn,
|
||||
amount: amountIn,
|
||||
balance: balanceIn,
|
||||
usdc: usdcIn,
|
||||
usdc: inputUSDC,
|
||||
},
|
||||
[Field.OUTPUT]: {
|
||||
currency: currencyOut,
|
||||
amount: amountOut,
|
||||
balance: balanceOut,
|
||||
usdc: usdcOut,
|
||||
usdc: outputUSDC,
|
||||
},
|
||||
trade,
|
||||
slippage,
|
||||
impact,
|
||||
}),
|
||||
[amountIn, amountOut, balanceIn, balanceOut, currencyIn, currencyOut, impact, slippage, trade, usdcIn, usdcOut]
|
||||
[
|
||||
amountIn,
|
||||
amountOut,
|
||||
balanceIn,
|
||||
balanceOut,
|
||||
currencyIn,
|
||||
currencyOut,
|
||||
impact,
|
||||
inputUSDC,
|
||||
outputUSDC,
|
||||
slippage,
|
||||
trade,
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
@ -98,7 +106,6 @@ const swapInfoAtom = atom<SwapInfo>({
|
||||
[Field.OUTPUT]: {},
|
||||
trade: { state: TradeState.INVALID },
|
||||
slippage: { auto: true, allowed: new Percent(0) },
|
||||
impact: {},
|
||||
})
|
||||
|
||||
export function SwapInfoUpdater() {
|
||||
|
@ -5,8 +5,9 @@ import { computeFiatValuePriceImpact } from 'utils/computeFiatValuePriceImpact'
|
||||
import { getPriceImpactWarning } from 'utils/prices'
|
||||
|
||||
export interface PriceImpact {
|
||||
display?: string
|
||||
percent: Percent
|
||||
warning?: 'warning' | 'error'
|
||||
toString(): string
|
||||
}
|
||||
|
||||
/**
|
||||
@ -19,22 +20,20 @@ export default function useUSDCPriceImpact(
|
||||
): {
|
||||
inputUSDC?: CurrencyAmount<Token>
|
||||
outputUSDC?: CurrencyAmount<Token>
|
||||
priceImpact: PriceImpact
|
||||
impact?: PriceImpact
|
||||
} {
|
||||
const inputUSDC = useUSDCValue(inputAmount) ?? undefined
|
||||
const outputUSDC = useUSDCValue(outputAmount) ?? undefined
|
||||
return useMemo(() => {
|
||||
const priceImpact = computeFiatValuePriceImpact(inputUSDC, outputUSDC)
|
||||
const warning = getPriceImpactWarning(priceImpact)
|
||||
return {
|
||||
inputUSDC,
|
||||
outputUSDC,
|
||||
priceImpact: {
|
||||
priceImpact,
|
||||
display: priceImpact && toHumanReadablePriceImpact(priceImpact),
|
||||
warning,
|
||||
},
|
||||
}
|
||||
const impact = priceImpact
|
||||
? {
|
||||
percent: priceImpact,
|
||||
warning: getPriceImpactWarning(priceImpact),
|
||||
toString: () => toHumanReadablePriceImpact(priceImpact),
|
||||
}
|
||||
: undefined
|
||||
return { inputUSDC, outputUSDC, impact }
|
||||
}, [inputUSDC, outputUSDC])
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user