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