Commit 7b589561 authored by Jack Short's avatar Jack Short Committed by GitHub

fix: not using stablecoin to calc price impact pwat (#5997)

* feat: implementing graphql endpoint

* changing from hook to function call

* initial gql routing works

* feat: initial pwatRouting setup

* sending correct amount

* removing console

* it is working

* sufficient balance

* 0 if no inputCurrency

* removing value to send if erc20

* removing console

* permit2 optional flag

* removing not necessary stuff

* mobile fixes

* overlay needs to be here

* changing swap amount to pool reserves

* refactoring routing logic

* no route found button state

* better price loading for insufficient liquidity

* refactoring graphql routing code

* overflow

* initial comments

* resetting bag status on input currency change

* locking

* done

* remove helper text for eth

* fix: pay with any token routing bug

* reordering button

* zindex

* price updated

* keeping debounce

* feat: adding amplitude events for pwat

* bumping analytics version

* types and hooks

* moving erc20 flag to useSendTransaction

* why did i put it in a hook

* no return

* fix: not using usdc value to calculate price impact

* refactor + loading state
parent c9d3dc36
......@@ -4,8 +4,7 @@ import { parseEther } from '@ethersproject/units'
import { t, Trans } from '@lingui/macro'
import { sendAnalyticsEvent, TraceEvent } from '@uniswap/analytics'
import { BrowserEvent, InterfaceElementName, NFTEventName } from '@uniswap/analytics-events'
import { formatPriceImpact } from '@uniswap/conedison/format'
import { Currency, CurrencyAmount, Percent, Token, TradeType } from '@uniswap/sdk-core'
import { Currency, CurrencyAmount, Token, TradeType } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
import Column from 'components/Column'
import Loader from 'components/Loader'
......@@ -25,6 +24,7 @@ import { useBag } from 'nft/hooks/useBag'
import useDerivedPayWithAnyTokenSwapInfo from 'nft/hooks/useDerivedPayWithAnyTokenSwapInfo'
import usePayWithAnyTokenSwap from 'nft/hooks/usePayWithAnyTokenSwap'
import usePermit2Approval from 'nft/hooks/usePermit2Approval'
import { PriceImpact, usePriceImpact } from 'nft/hooks/usePriceImpact'
import { useTokenInput } from 'nft/hooks/useTokenInput'
import { useWalletBalance } from 'nft/hooks/useWalletBalance'
import { BagStatus } from 'nft/types'
......@@ -35,14 +35,9 @@ import { useToggleWalletModal } from 'state/application/hooks'
import { InterfaceTrade, TradeState } from 'state/routing/types'
import styled, { useTheme } from 'styled-components/macro'
import { ThemedText } from 'theme'
import { computeFiatValuePriceImpact } from 'utils/computeFiatValuePriceImpact'
import { warningSeverity } from 'utils/prices'
import { switchChain } from 'utils/switchChain'
import shallow from 'zustand/shallow'
const LOW_SEVERITY_THRESHOLD = 1
const MEDIUM_SEVERITY_THRESHOLD = 3
const FooterContainer = styled.div`
padding: 0px 12px;
`
......@@ -124,7 +119,7 @@ const PayButton = styled.button<{ $backgroundColor: string; $color: string }>`
const FiatLoadingBubble = styled(LoadingBubble)`
border-radius: 4px;
width: 4rem;
height: 1rem;
height: 20px;
align-self: end;
`
const PriceImpactContainer = styled(Row)`
......@@ -240,13 +235,11 @@ const InputCurrencyValue = ({
const FiatValue = ({
usdcValue,
priceImpact,
priceImpactColor,
tradeState,
usingPayWithAnyToken,
}: {
usdcValue: CurrencyAmount<Token> | null
priceImpact: Percent | undefined
priceImpactColor: string | undefined
priceImpact: PriceImpact | undefined
tradeState: TradeState
usingPayWithAnyToken: boolean
}) => {
......@@ -260,13 +253,13 @@ const FiatValue = ({
return (
<PriceImpactContainer>
{priceImpact && priceImpactColor && (
{priceImpact && (
<>
<MouseoverTooltip text={t`The estimated difference between the USD values of input and output amounts.`}>
<PriceImpactRow>
<AlertTriangle color={priceImpactColor} size="16px" />
<ThemedText.BodySmall style={{ color: priceImpactColor }} lineHeight="20px">
(<Trans>{formatPriceImpact(priceImpact)}</Trans>)
<AlertTriangle color={priceImpact.priceImpactSeverity.color} size="16px" />
<ThemedText.BodySmall style={{ color: priceImpact.priceImpactSeverity.color }} lineHeight="20px">
(<Trans>{priceImpact.displayPercentage()}</Trans>)
</ThemedText.BodySmall>
</PriceImpactRow>
</MouseoverTooltip>
......@@ -342,30 +335,11 @@ export const BagFooter = ({ totalEthPrice, fetchAssets, eventProperties }: BagFo
shouldUsePayWithAnyToken
)
usePayWithAnyTokenSwap(trade, allowance, allowedSlippage)
const priceImpact = usePriceImpact(trade)
const fiatValueTradeInput = useStablecoinValue(trade?.inputAmount)
const fiatValueTradeOutput = useStablecoinValue(parsedOutputAmount)
const usdcValue = usingPayWithAnyToken ? fiatValueTradeInput : fiatValueTradeOutput
const stablecoinPriceImpact = useMemo(
() =>
tradeState === TradeState.SYNCING || !trade
? undefined
: computeFiatValuePriceImpact(fiatValueTradeInput, fiatValueTradeOutput),
[fiatValueTradeInput, fiatValueTradeOutput, tradeState, trade]
)
const { priceImpactWarning, priceImpactColor } = useMemo(() => {
const severity = warningSeverity(stablecoinPriceImpact)
if (severity < LOW_SEVERITY_THRESHOLD) {
return { priceImpactWarning: false, priceImpactColor: undefined }
}
if (severity < MEDIUM_SEVERITY_THRESHOLD) {
return { priceImpactWarning: false, priceImpactColor: theme.accentWarning }
}
return { priceImpactWarning: true, priceImpactColor: theme.accentCritical }
}, [stablecoinPriceImpact, theme.accentCritical, theme.accentWarning])
const { balance: balanceInEth } = useWalletBalance()
const sufficientBalance = useMemo(() => {
......@@ -468,11 +442,11 @@ export const BagFooter = ({ totalEthPrice, fetchAssets, eventProperties }: BagFo
warningTextColor = theme.accentAction
warningText = <Trans>Price updated</Trans>
buttonText = <Trans>Pay</Trans>
} else if (priceImpactWarning && priceImpactColor) {
} else if (priceImpact && priceImpact.priceImpactSeverity.type === 'error') {
disabled = false
buttonColor = priceImpactColor
buttonColor = priceImpact.priceImpactSeverity.color
helperText = <Trans>Price impact warning</Trans>
helperTextColor = priceImpactColor
helperTextColor = priceImpact.priceImpactSeverity.color
buttonText = <Trans>Pay Anyway</Trans>
} else if (sufficientBalance === true) {
disabled = false
......@@ -506,8 +480,7 @@ export const BagFooter = ({ totalEthPrice, fetchAssets, eventProperties }: BagFo
usingPayWithAnyToken,
tradeState,
allowance.state,
priceImpactWarning,
priceImpactColor,
priceImpact,
connector,
toggleWalletModal,
setBagExpanded,
......@@ -522,6 +495,8 @@ export const BagFooter = ({ totalEthPrice, fetchAssets, eventProperties }: BagFo
...eventProperties,
}
console.log(bagStatus)
return (
<FooterContainer>
<Footer>
......@@ -562,8 +537,7 @@ export const BagFooter = ({ totalEthPrice, fetchAssets, eventProperties }: BagFo
</CurrencyRow>
<FiatValue
usdcValue={usdcValue}
priceImpact={stablecoinPriceImpact}
priceImpactColor={priceImpactColor}
priceImpact={priceImpact}
tradeState={tradeState}
usingPayWithAnyToken={usingPayWithAnyToken}
/>
......@@ -584,8 +558,7 @@ export const BagFooter = ({ totalEthPrice, fetchAssets, eventProperties }: BagFo
</Row>
<FiatValue
usdcValue={usdcValue}
priceImpact={stablecoinPriceImpact}
priceImpactColor={priceImpactColor}
priceImpact={priceImpact}
tradeState={tradeState}
usingPayWithAnyToken={usingPayWithAnyToken}
/>
......@@ -602,7 +575,7 @@ export const BagFooter = ({ totalEthPrice, fetchAssets, eventProperties }: BagFo
<Helper color={helperTextColor}>{helperText}</Helper>
<ActionButton
onClick={handleClick}
disabled={disabled}
disabled={disabled || isPending}
backgroundColor={buttonColor}
textColor={buttonTextColor}
>
......
import { Currency, Percent, TradeType } from '@uniswap/sdk-core'
import { useMemo } from 'react'
import { InterfaceTrade } from 'state/routing/types'
import { useTheme } from 'styled-components/macro'
import { computeRealizedPriceImpact, getPriceImpactWarning } from 'utils/prices'
export interface PriceImpact {
priceImpactSeverity: PriceImpactSeverity
displayPercentage(): string
}
interface PriceImpactSeverity {
type: 'warning' | 'error'
color: string
}
export function usePriceImpact(trade?: InterfaceTrade<Currency, Currency, TradeType>): PriceImpact | undefined {
const theme = useTheme()
return useMemo(() => {
const marketPriceImpact = trade ? computeRealizedPriceImpact(trade) : undefined
const priceImpactWarning = marketPriceImpact ? getPriceImpactWarning(marketPriceImpact) : undefined
const warningColor =
priceImpactWarning === 'error'
? theme.accentCritical
: priceImpactWarning === 'warning'
? theme.accentWarning
: undefined
return marketPriceImpact && priceImpactWarning && warningColor
? {
priceImpactSeverity: {
type: priceImpactWarning,
color: warningColor,
},
displayPercentage: () => toHumanReadablePercent(marketPriceImpact),
}
: undefined
}, [theme.accentCritical, theme.accentWarning, trade])
}
function toHumanReadablePercent(priceImpact: Percent): string {
const sign = priceImpact.lessThan(0) ? '+' : ''
const exactFloat = (Number(priceImpact.numerator) / Number(priceImpact.denominator)) * 100
if (exactFloat < 0.005) {
return '0.00%'
}
const number = parseFloat(priceImpact.multiply(-1)?.toFixed(2))
return `${sign}${number}%`
}
......@@ -92,3 +92,9 @@ export function warningSeverity(priceImpact: Percent | undefined): WarningSeveri
}
return 0
}
export function getPriceImpactWarning(priceImpact: Percent): 'warning' | 'error' | undefined {
if (priceImpact.greaterThan(ALLOWED_PRICE_IMPACT_HIGH)) return 'error'
if (priceImpact.greaterThan(ALLOWED_PRICE_IMPACT_MEDIUM)) return 'warning'
return
}
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