Commit 303fa152 authored by Mike Grabowski's avatar Mike Grabowski Committed by GitHub

feat: show affordance in swap UI when we can't fetch usd quote (#6622)

* initial commit:

* add todo to linear
parent d180aef3
import { Trans } from '@lingui/macro'
// eslint-disable-next-line no-restricted-imports
import { t } from '@lingui/macro'
import { formatNumber, formatPriceImpact, NumberType } from '@uniswap/conedison/format'
import { Percent } from '@uniswap/sdk-core'
import Row from 'components/Row'
import { LoadingBubble } from 'components/Tokens/loading'
import { MouseoverTooltip } from 'components/Tooltip'
import { useMemo } from 'react'
import styled, { useTheme } from 'styled-components/macro'
import { ThemedText } from '../../theme'
import { warningSeverity } from '../../utils/prices'
import styled from 'styled-components/macro'
import { ThemedText } from 'theme'
import { warningSeverity } from 'utils/prices'
const FiatLoadingBubble = styled(LoadingBubble)`
border-radius: 4px;
......@@ -21,36 +19,40 @@ export function FiatValue({
fiatValue,
priceImpact,
}: {
fiatValue?: { data?: number; isLoading: boolean }
fiatValue: { data?: number; isLoading: boolean }
priceImpact?: Percent
}) {
const theme = useTheme()
const priceImpactColor = useMemo(() => {
if (!priceImpact) return undefined
if (priceImpact.lessThan('0')) return theme.accentSuccess
if (priceImpact.lessThan('0')) return 'accentSuccess'
const severity = warningSeverity(priceImpact)
if (severity < 1) return theme.textTertiary
if (severity < 3) return theme.deprecated_yellow1
return theme.accentFailure
}, [priceImpact, theme.accentSuccess, theme.accentFailure, theme.textTertiary, theme.deprecated_yellow1])
if (severity < 1) return 'textTertiary'
if (severity < 3) return 'deprecated_yellow1'
return 'accentFailure'
}, [priceImpact])
if (fiatValue.isLoading) {
return <FiatLoadingBubble />
}
return (
<ThemedText.DeprecatedBody fontSize={14} color={theme.textSecondary}>
{fiatValue?.isLoading ? (
<FiatLoadingBubble />
) : (
<div>
{fiatValue?.data ? formatNumber(fiatValue.data, NumberType.FiatTokenPrice) : undefined}
{priceImpact && (
<span style={{ color: priceImpactColor }}>
{' '}
<MouseoverTooltip text={t`The estimated difference between the USD values of input and output amounts.`}>
(<Trans>{formatPriceImpact(priceImpact)}</Trans>)
</MouseoverTooltip>
</span>
)}
</div>
<Row gap="sm">
<ThemedText.BodySmall>
{fiatValue.data ? (
formatNumber(fiatValue.data, NumberType.FiatTokenPrice)
) : (
<MouseoverTooltip text={<Trans>Not enough liquidity to show accurate USD value.</Trans>}>-</MouseoverTooltip>
)}
</ThemedText.BodySmall>
{priceImpact && (
<ThemedText.BodySmall color={priceImpactColor}>
<MouseoverTooltip
text={<Trans>The estimated difference between the USD values of input and output amounts.</Trans>}
>
(<Trans>{formatPriceImpact(priceImpact)}</Trans>)
</MouseoverTooltip>
</ThemedText.BodySmall>
)}
</ThemedText.DeprecatedBody>
</Row>
)
}
......@@ -195,7 +195,7 @@ interface SwapCurrencyInputPanelProps {
pair?: Pair | null
hideInput?: boolean
otherCurrency?: Currency | null
fiatValue: { data?: number; isLoading: boolean }
fiatValue?: { data?: number; isLoading: boolean }
priceImpact?: Percent
id: string
showCommonBases?: boolean
......@@ -308,7 +308,7 @@ export default function SwapCurrencyInputPanel({
<FiatRow>
<RowBetween>
<LoadingOpacityContainer $loading={loading}>
<FiatValue fiatValue={fiatValue} priceImpact={priceImpact} />
{fiatValue && <FiatValue fiatValue={fiatValue} priceImpact={priceImpact} />}
</LoadingOpacityContainer>
{account ? (
<RowFixed style={{ height: '17px' }}>
......
import { Trans } from '@lingui/macro'
import { TraceEvent } from '@uniswap/analytics'
import { BrowserEvent, InterfaceElementName, SwapEventName } from '@uniswap/analytics-events'
import { Currency, CurrencyAmount, Percent } from '@uniswap/sdk-core'
import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
import { Pair } from '@uniswap/v2-sdk'
import { useWeb3React } from '@web3-react/core'
import { AutoColumn } from 'components/Column'
......@@ -183,7 +183,6 @@ interface CurrencyInputPanelProps {
hideInput?: boolean
otherCurrency?: Currency | null
fiatValue?: { data?: number; isLoading: boolean }
priceImpact?: Percent
id: string
showCommonBases?: boolean
showCurrencyAmount?: boolean
......@@ -207,7 +206,6 @@ export default function CurrencyInputPanel({
disableNonToken,
renderBalance,
fiatValue,
priceImpact,
hideBalance = false,
pair = null, // used for double token logo
hideInput = false,
......@@ -293,7 +291,7 @@ export default function CurrencyInputPanel({
<FiatRow>
<RowBetween>
<LoadingOpacityContainer $loading={loading}>
<FiatValue fiatValue={fiatValue} priceImpact={priceImpact} />
{fiatValue && <FiatValue fiatValue={fiatValue} />}
</LoadingOpacityContainer>
{account ? (
<RowFixed style={{ height: '17px' }}>
......
......@@ -50,6 +50,9 @@ function useETHValue(currencyAmount?: CurrencyAmount<Currency>): {
return { data: price.quote(currencyAmount), isLoading: false }
}
// TODO(WEB-2095): This hook should early return `null` when `currencyAmount` is undefined. Otherwise,
// it is not possible to differentiate between a loading state and a state where `currencyAmount`
// is undefined
export function useUSDPrice(currencyAmount?: CurrencyAmount<Currency>): {
data?: number
isLoading: boolean
......
......@@ -287,8 +287,11 @@ export function Swap({
},
[independentField, parsedAmount, showWrap, trade]
)
const fiatValueInput = useUSDPrice(parsedAmounts[Field.INPUT])
const fiatValueOutput = useUSDPrice(parsedAmounts[Field.OUTPUT])
const showFiatValueInput = Boolean(parsedAmounts[Field.INPUT])
const showFiatValueOutput = Boolean(parsedAmounts[Field.OUTPUT])
const [routeNotFound, routeIsLoading, routeIsSyncing] = useMemo(
() => [!trade?.swaps, TradeState.LOADING === tradeState, TradeState.LOADING === tradeState && Boolean(trade)],
......@@ -580,10 +583,10 @@ export function Swap({
currency={currencies[Field.INPUT] ?? null}
onUserInput={handleTypeInput}
onMax={handleMaxInput}
fiatValue={fiatValueInput}
fiatValue={showFiatValueInput ? fiatValueInput : undefined}
onCurrencySelect={handleInputSelect}
otherCurrency={currencies[Field.OUTPUT]}
showCommonBases={true}
showCommonBases
id={InterfaceSectionName.CURRENCY_INPUT_PANEL}
loading={independentField === Field.OUTPUT && routeIsSyncing}
/>
......@@ -621,12 +624,12 @@ export function Swap({
label={independentField === Field.INPUT && !showWrap ? <Trans>To (at least)</Trans> : <Trans>To</Trans>}
showMaxButton={false}
hideBalance={false}
fiatValue={fiatValueOutput}
fiatValue={showFiatValueOutput ? fiatValueOutput : undefined}
priceImpact={stablecoinPriceImpact}
currency={currencies[Field.OUTPUT] ?? null}
onCurrencySelect={handleOutputSelect}
otherCurrency={currencies[Field.INPUT]}
showCommonBases={true}
showCommonBases
id={InterfaceSectionName.CURRENCY_OUTPUT_PANEL}
loading={independentField === Field.INPUT && routeIsSyncing}
/>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment