Commit ee693573 authored by Moody Salem's avatar Moody Salem

some minor refactoring with price impact functions

parent ce7f94f1
...@@ -3,7 +3,7 @@ import { Trade as V3Trade } from '@uniswap/v3-sdk' ...@@ -3,7 +3,7 @@ import { Trade as V3Trade } from '@uniswap/v3-sdk'
import React, { useContext } from 'react' import React, { useContext } from 'react'
import { ThemeContext } from 'styled-components' import { ThemeContext } from 'styled-components'
import { TYPE } from '../../theme' import { TYPE } from '../../theme'
import { computeTradePriceBreakdown } from '../../utils/prices' import { computeRealizedLPFeeAmount } from '../../utils/prices'
import { AutoColumn } from '../Column' import { AutoColumn } from '../Column'
import { RowBetween, RowFixed } from '../Row' import { RowBetween, RowFixed } from '../Row'
import SwapRoute from './SwapRoute' import SwapRoute from './SwapRoute'
...@@ -15,12 +15,7 @@ export interface AdvancedSwapDetailsProps { ...@@ -15,12 +15,7 @@ export interface AdvancedSwapDetailsProps {
export function AdvancedSwapDetails({ trade }: AdvancedSwapDetailsProps) { export function AdvancedSwapDetails({ trade }: AdvancedSwapDetailsProps) {
const theme = useContext(ThemeContext) const theme = useContext(ThemeContext)
const { realizedLPFee } = computeTradePriceBreakdown(trade) const realizedLPFee = computeRealizedLPFeeAmount(trade)
const showRoute = Boolean(
(trade && trade instanceof V2Trade && trade.route.pairs.length > 1) ||
(trade instanceof V3Trade && trade.route.pools.length > 1)
)
return !trade ? null : ( return !trade ? null : (
<AutoColumn gap="8px"> <AutoColumn gap="8px">
...@@ -35,18 +30,16 @@ export function AdvancedSwapDetails({ trade }: AdvancedSwapDetailsProps) { ...@@ -35,18 +30,16 @@ export function AdvancedSwapDetails({ trade }: AdvancedSwapDetailsProps) {
</TYPE.black> </TYPE.black>
</RowBetween> </RowBetween>
{showRoute && ( <RowBetween>
<RowBetween> <RowFixed>
<RowFixed> <TYPE.black fontSize={12} fontWeight={400} color={theme.text2}>
<TYPE.black fontSize={12} fontWeight={400} color={theme.text2}> Route
Route
</TYPE.black>
</RowFixed>
<TYPE.black fontSize={12} color={theme.text1}>
<SwapRoute trade={trade} />
</TYPE.black> </TYPE.black>
</RowBetween> </RowFixed>
)} <TYPE.black fontSize={12} color={theme.text1}>
<SwapRoute trade={trade} />
</TYPE.black>
</RowBetween>
</AutoColumn> </AutoColumn>
) )
} }
import { Trade as V2Trade } from '@uniswap/v2-sdk' import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk' import { Trade as V3Trade } from '@uniswap/v3-sdk'
import React, { useMemo } from 'react' import React from 'react'
import { Text } from 'rebass' import { Text } from 'rebass'
import { computeTradePriceBreakdown, warningSeverity } from '../../utils/prices'
import { ButtonError } from '../Button' import { ButtonError } from '../Button'
import {} from '../Column'
import { AutoRow } from '../Row' import { AutoRow } from '../Row'
import { SwapCallbackError } from './styleds' import { SwapCallbackError } from './styleds'
export default function SwapModalFooter({ export default function SwapModalFooter({
trade,
onConfirm, onConfirm,
swapErrorMessage, swapErrorMessage,
disabledConfirm, disabledConfirm,
...@@ -20,21 +17,17 @@ export default function SwapModalFooter({ ...@@ -20,21 +17,17 @@ export default function SwapModalFooter({
swapErrorMessage: string | undefined swapErrorMessage: string | undefined
disabledConfirm: boolean disabledConfirm: boolean
}) { }) {
const { priceImpactWithoutFee } = useMemo(() => computeTradePriceBreakdown(trade), [trade])
const severity = warningSeverity(priceImpactWithoutFee)
return ( return (
<> <>
<AutoRow> <AutoRow>
<ButtonError <ButtonError
onClick={onConfirm} onClick={onConfirm}
disabled={disabledConfirm} disabled={disabledConfirm}
error={severity > 2}
style={{ margin: '10px 0 0 0' }} style={{ margin: '10px 0 0 0' }}
id="confirm-swap-or-send" id="confirm-swap-or-send"
> >
<Text fontSize={20} fontWeight={500}> <Text fontSize={20} fontWeight={500}>
{severity > 2 ? 'Swap Anyway' : 'Confirm Swap'} Confirm Swap
</Text> </Text>
</ButtonError> </ButtonError>
......
...@@ -17,7 +17,6 @@ import { useCurrencyBalances } from '../wallet/hooks' ...@@ -17,7 +17,6 @@ import { useCurrencyBalances } from '../wallet/hooks'
import { Field, replaceSwapState, selectCurrency, setRecipient, switchCurrencies, typeInput } from './actions' import { Field, replaceSwapState, selectCurrency, setRecipient, switchCurrencies, typeInput } from './actions'
import { SwapState } from './reducer' import { SwapState } from './reducer'
import { useUserSlippageTolerance } from '../user/hooks' import { useUserSlippageTolerance } from '../user/hooks'
import { computeSlippageAdjustedAmounts } from '../../utils/prices'
export function useSwapState(): AppState['swap'] { export function useSwapState(): AppState['swap'] {
return useSelector<AppState, AppState['swap']>((state) => state.swap) return useSelector<AppState, AppState['swap']>((state) => state.swap)
...@@ -188,13 +187,8 @@ export function useDerivedSwapInfo(): { ...@@ -188,13 +187,8 @@ export function useDerivedSwapInfo(): {
const [allowedSlippage] = useUserSlippageTolerance() const [allowedSlippage] = useUserSlippageTolerance()
const slippageAdjustedAmounts = v2Trade && allowedSlippage && computeSlippageAdjustedAmounts(v2Trade, allowedSlippage)
// compare input balance to max input based on version // compare input balance to max input based on version
const [balanceIn, amountIn] = [ const [balanceIn, amountIn] = [currencyBalances[Field.INPUT], v2Trade?.maximumAmountIn(allowedSlippage)]
currencyBalances[Field.INPUT],
slippageAdjustedAmounts ? slippageAdjustedAmounts[Field.INPUT] : null,
]
if (balanceIn && amountIn && balanceIn.lessThan(amountIn)) { if (balanceIn && amountIn && balanceIn.lessThan(amountIn)) {
inputError = 'Insufficient ' + amountIn.currency.symbol + ' balance' inputError = 'Insufficient ' + amountIn.currency.symbol + ' balance'
......
import { ChainId, Percent, Token, TokenAmount, TradeType } from '@uniswap/sdk-core' import { ChainId, Percent, Token, TokenAmount, TradeType } from '@uniswap/sdk-core'
import { JSBI, Trade, Pair, Route } from '@uniswap/v2-sdk' import { JSBI, Trade, Pair, Route } from '@uniswap/v2-sdk'
import { computeTradePriceBreakdown, warningSeverity } from './prices' import { computeRealizedLPFeeAmount, warningSeverity } from './prices'
describe('prices', () => { describe('prices', () => {
const token1 = new Token(ChainId.MAINNET, '0x0000000000000000000000000000000000000001', 18) const token1 = new Token(ChainId.MAINNET, '0x0000000000000000000000000000000000000001', 18)
...@@ -12,7 +12,7 @@ describe('prices', () => { ...@@ -12,7 +12,7 @@ describe('prices', () => {
describe('#computeTradePriceBreakdown', () => { describe('#computeTradePriceBreakdown', () => {
it('returns undefined for undefined', () => { it('returns undefined for undefined', () => {
expect(computeTradePriceBreakdown(undefined)).toEqual({ expect(computeRealizedLPFeeAmount(undefined)).toEqual({
priceImpactWithoutFee: undefined, priceImpactWithoutFee: undefined,
realizedLPFee: undefined, realizedLPFee: undefined,
}) })
...@@ -20,7 +20,7 @@ describe('prices', () => { ...@@ -20,7 +20,7 @@ describe('prices', () => {
it('correct realized lp fee for single hop', () => { it('correct realized lp fee for single hop', () => {
expect( expect(
computeTradePriceBreakdown( computeRealizedLPFeeAmount(
new Trade(new Route([pair12], token1), new TokenAmount(token1, JSBI.BigInt(1000)), TradeType.EXACT_INPUT) new Trade(new Route([pair12], token1), new TokenAmount(token1, JSBI.BigInt(1000)), TradeType.EXACT_INPUT)
).realizedLPFee ).realizedLPFee
).toEqual(new TokenAmount(token1, JSBI.BigInt(3))) ).toEqual(new TokenAmount(token1, JSBI.BigInt(3)))
...@@ -28,7 +28,7 @@ describe('prices', () => { ...@@ -28,7 +28,7 @@ describe('prices', () => {
it('correct realized lp fee for double hop', () => { it('correct realized lp fee for double hop', () => {
expect( expect(
computeTradePriceBreakdown( computeRealizedLPFeeAmount(
new Trade( new Trade(
new Route([pair12, pair23], token1), new Route([pair12, pair23], token1),
new TokenAmount(token1, JSBI.BigInt(1000)), new TokenAmount(token1, JSBI.BigInt(1000)),
......
import JSBI from 'jsbi' import JSBI from 'jsbi'
import { BLOCKED_PRICE_IMPACT_NON_EXPERT, ZERO_PERCENT } from '../constants'
import { CurrencyAmount, Fraction, Percent, TokenAmount } from '@uniswap/sdk-core' import { CurrencyAmount, Fraction, Percent, TokenAmount } from '@uniswap/sdk-core'
import { Trade as V2Trade } from '@uniswap/v2-sdk' import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk' import { Trade as V3Trade } from '@uniswap/v3-sdk'
import {
import { ALLOWED_PRICE_IMPACT_HIGH, ALLOWED_PRICE_IMPACT_LOW, ALLOWED_PRICE_IMPACT_MEDIUM } from '../constants' ALLOWED_PRICE_IMPACT_HIGH,
import { Field } from '../state/swap/actions' ALLOWED_PRICE_IMPACT_LOW,
ALLOWED_PRICE_IMPACT_MEDIUM,
BLOCKED_PRICE_IMPACT_NON_EXPERT,
} from '../constants'
const THIRTY_BIPS_FEE = new Percent(JSBI.BigInt(30), JSBI.BigInt(10000)) const THIRTY_BIPS_FEE = new Percent(JSBI.BigInt(30), JSBI.BigInt(10000))
const ONE_HUNDRED_PERCENT = new Percent(JSBI.BigInt(10000), JSBI.BigInt(10000)) const ONE_HUNDRED_PERCENT = new Percent(JSBI.BigInt(10000), JSBI.BigInt(10000))
const INPUT_FRACTION_AFTER_FEE = ONE_HUNDRED_PERCENT.subtract(THIRTY_BIPS_FEE) const INPUT_FRACTION_AFTER_FEE = ONE_HUNDRED_PERCENT.subtract(THIRTY_BIPS_FEE)
// computes price breakdown for the trade // computes price breakdown for the trade
export function computeTradePriceBreakdown( export function computeRealizedLPFeeAmount(trade?: V2Trade | V3Trade | null): CurrencyAmount | undefined {
trade?: V2Trade | V3Trade | null
): { priceImpactWithoutFee: Percent | undefined; realizedLPFee: CurrencyAmount | undefined | null } {
if (trade instanceof V2Trade) { if (trade instanceof V2Trade) {
// for each hop in our trade, take away the x*y=k price impact from 0.3% fees // for each hop in our trade, take away the x*y=k price impact from 0.3% fees
// e.g. for 3 tokens/2 hops: 1 - ((1 - .03) * (1-.03)) // e.g. for 3 tokens/2 hops: 1 - ((1 - .03) * (1-.03))
...@@ -27,23 +27,14 @@ export function computeTradePriceBreakdown( ...@@ -27,23 +27,14 @@ export function computeTradePriceBreakdown(
) )
) )
// remove lp fees from price impact
const priceImpactWithoutFeeFraction = trade && realizedLPFee ? trade.priceImpact.subtract(realizedLPFee) : undefined
// the x*y=k impact
const priceImpactWithoutFeePercent = priceImpactWithoutFeeFraction
? new Percent(priceImpactWithoutFeeFraction?.numerator, priceImpactWithoutFeeFraction?.denominator)
: undefined
// the amount of the input that accrues to LPs // the amount of the input that accrues to LPs
const realizedLPFeeAmount = return (
realizedLPFee && realizedLPFee &&
trade && trade &&
(trade.inputAmount instanceof TokenAmount (trade.inputAmount instanceof TokenAmount
? new TokenAmount(trade.inputAmount.token, realizedLPFee.multiply(trade.inputAmount.raw).quotient) ? new TokenAmount(trade.inputAmount.token, realizedLPFee.multiply(trade.inputAmount.raw).quotient)
: CurrencyAmount.ether(realizedLPFee.multiply(trade.inputAmount.raw).quotient)) : CurrencyAmount.ether(realizedLPFee.multiply(trade.inputAmount.raw).quotient))
)
return { priceImpactWithoutFee: priceImpactWithoutFeePercent, realizedLPFee: realizedLPFeeAmount }
} else if (trade instanceof V3Trade) { } else if (trade instanceof V3Trade) {
const realizedLPFee = !trade const realizedLPFee = !trade
? undefined ? undefined
...@@ -54,35 +45,15 @@ export function computeTradePriceBreakdown( ...@@ -54,35 +45,15 @@ export function computeTradePriceBreakdown(
ONE_HUNDRED_PERCENT ONE_HUNDRED_PERCENT
) )
) )
const realizedLPFeeAmount = return (
realizedLPFee && realizedLPFee &&
trade && trade &&
(trade.inputAmount instanceof TokenAmount (trade.inputAmount instanceof TokenAmount
? new TokenAmount(trade.inputAmount.token, realizedLPFee.multiply(trade.inputAmount.raw).quotient) ? new TokenAmount(trade.inputAmount.token, realizedLPFee.multiply(trade.inputAmount.raw).quotient)
: CurrencyAmount.ether(realizedLPFee.multiply(trade.inputAmount.raw).quotient)) : CurrencyAmount.ether(realizedLPFee.multiply(trade.inputAmount.raw).quotient))
)
return {
// TODO: real price impact
priceImpactWithoutFee: new Percent(0),
realizedLPFee: realizedLPFeeAmount,
}
} else {
return {
priceImpactWithoutFee: undefined,
realizedLPFee: undefined,
}
}
}
// computes the minimum amount out and maximum amount in for a trade given a user specified allowed slippage in bips
export function computeSlippageAdjustedAmounts(
trade: V2Trade | V3Trade | undefined,
allowedSlippage: Percent
): { [field in Field]?: CurrencyAmount } {
return {
[Field.INPUT]: trade?.maximumAmountIn(allowedSlippage),
[Field.OUTPUT]: trade?.minimumAmountOut(allowedSlippage),
} }
return undefined
} }
const IMPACT_TIERS = [ const IMPACT_TIERS = [
...@@ -102,20 +73,3 @@ export function warningSeverity(priceImpact: Percent | undefined): WarningSeveri ...@@ -102,20 +73,3 @@ export function warningSeverity(priceImpact: Percent | undefined): WarningSeveri
} }
return 0 return 0
} }
export function formatExecutionPrice(
trade: V2Trade | V3Trade | undefined,
inverted: boolean | undefined,
slippageTolerance: Percent = ZERO_PERCENT
): string {
if (!trade) {
return ''
}
return inverted
? `${trade.worstExecutionPrice(slippageTolerance).invert().toSignificant(6)} ${
trade.inputAmount.currency.symbol
} / ${trade.outputAmount.currency.symbol}`
: `${trade.worstExecutionPrice(slippageTolerance).toSignificant(6)} ${trade.outputAmount.currency.symbol} / ${
trade.inputAmount.currency.symbol
}`
}
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