show v3 quotes

This commit is contained in:
Moody Salem 2021-04-26 19:35:27 -05:00
parent bb17c57a84
commit ccbd5dfcf7
No known key found for this signature in database
GPG Key ID: 8CB5CD10385138DB
9 changed files with 86 additions and 74 deletions

@ -1,5 +1,6 @@
import { TradeType } from '@uniswap/sdk-core'
import { Trade } from '@uniswap/v2-sdk'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
import React, { useContext } from 'react'
import styled, { ThemeContext } from 'styled-components'
import { Field } from '../../state/swap/actions'
@ -12,17 +13,7 @@ import { RowBetween, RowFixed } from '../Row'
import FormattedPriceImpact from './FormattedPriceImpact'
import SwapRoute from './SwapRoute'
const InfoLink = styled(ExternalLink)`
width: 100%;
border: 1px solid ${({ theme }) => theme.bg3};
padding: 6px 6px;
border-radius: 8px;
text-align: center;
font-size: 14px;
color: ${({ theme }) => theme.text1};
`
function TradeSummary({ trade, allowedSlippage }: { trade: Trade; allowedSlippage: number }) {
function TradeSummary({ trade, allowedSlippage }: { trade: V2Trade | V3Trade; allowedSlippage: number }) {
const theme = useContext(ThemeContext)
const { priceImpactWithoutFee, realizedLPFee } = computeTradePriceBreakdown(trade)
const isExactIn = trade.tradeType === TradeType.EXACT_INPUT
@ -75,7 +66,7 @@ function TradeSummary({ trade, allowedSlippage }: { trade: Trade; allowedSlippag
}
export interface AdvancedSwapDetailsProps {
trade?: Trade
trade?: V2Trade | V3Trade
}
export function AdvancedSwapDetails({ trade }: AdvancedSwapDetailsProps) {
@ -83,7 +74,10 @@ export function AdvancedSwapDetails({ trade }: AdvancedSwapDetailsProps) {
const [allowedSlippage] = useUserSlippageTolerance()
const showRoute = Boolean(trade && trade.route.path.length > 2)
const showRoute = Boolean(
(trade && trade instanceof V2Trade && trade.route.pairs.length > 2) ||
(trade instanceof V3Trade && trade.route.pools.length > 2)
)
return (
<AutoColumn gap="0px">
@ -103,16 +97,6 @@ export function AdvancedSwapDetails({ trade }: AdvancedSwapDetailsProps) {
</RowBetween>
</>
)}
{!showRoute && (
<AutoColumn style={{ padding: '12px 16px 0 16px' }}>
<InfoLink
href={'https://info.uniswap.org/pair/' + trade.route.pairs[0].liquidityToken.address}
target="_blank"
>
View pair analytics
</InfoLink>
</AutoColumn>
)}
</>
)}
</AutoColumn>

@ -1,5 +1,6 @@
import { currencyEquals } from '@uniswap/sdk-core'
import { Trade } from '@uniswap/v2-sdk'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
import React, { useCallback, useMemo } from 'react'
import TransactionConfirmationModal, {
ConfirmationModalContent,
@ -10,10 +11,10 @@ import SwapModalHeader from './SwapModalHeader'
/**
* Returns true if the trade requires a confirmation of details before we can submit it
* @param tradeA trade A
* @param tradeB trade B
* @param args either a pair of V2 trades or a pair of V3 trades
*/
function tradeMeaningfullyDiffers(tradeA: Trade, tradeB: Trade): boolean {
function tradeMeaningfullyDiffers(...args: [V2Trade, V2Trade] | [V3Trade, V3Trade]): boolean {
const [tradeA, tradeB] = args
return (
tradeA.tradeType !== tradeB.tradeType ||
!currencyEquals(tradeA.inputAmount.currency, tradeB.inputAmount.currency) ||
@ -37,8 +38,8 @@ export default function ConfirmSwapModal({
txHash,
}: {
isOpen: boolean
trade: Trade | undefined
originalTrade: Trade | undefined
trade: V2Trade | V3Trade | undefined
originalTrade: V2Trade | V3Trade | undefined
attemptingTxn: boolean
txHash: string | undefined
recipient: string | null
@ -49,7 +50,15 @@ export default function ConfirmSwapModal({
onDismiss: () => void
}) {
const showAcceptChanges = useMemo(
() => Boolean(trade && originalTrade && tradeMeaningfullyDiffers(trade, originalTrade)),
() =>
Boolean(
(trade instanceof V2Trade &&
originalTrade instanceof V2Trade &&
tradeMeaningfullyDiffers(trade, originalTrade)) ||
(trade instanceof V3Trade &&
originalTrade instanceof V3Trade &&
tradeMeaningfullyDiffers(trade, originalTrade))
),
[originalTrade, trade]
)

@ -1,4 +1,5 @@
import { Trade } from '@uniswap/v2-sdk'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
import { TradeType } from '@uniswap/sdk-core'
import React, { useContext, useMemo, useState } from 'react'
import { Repeat } from 'react-feather'
@ -26,7 +27,7 @@ export default function SwapModalFooter({
swapErrorMessage,
disabledConfirm,
}: {
trade: Trade
trade: V2Trade | V3Trade
allowedSlippage: number
onConfirm: () => void
swapErrorMessage: string | undefined

@ -1,5 +1,6 @@
import { TradeType } from '@uniswap/sdk-core'
import { Trade } from '@uniswap/v2-sdk'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
import React, { useContext, useMemo } from 'react'
import { ArrowDown, AlertTriangle } from 'react-feather'
import { Text } from 'rebass'
@ -21,7 +22,7 @@ export default function SwapModalHeader({
showAcceptChanges,
onAcceptChanges,
}: {
trade: Trade
trade: V2Trade | V3Trade
allowedSlippage: number
recipient: string | null
showAcceptChanges: boolean

@ -1,4 +1,5 @@
import { Trade } from '@uniswap/v2-sdk'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
import React, { Fragment, memo, useContext } from 'react'
import { ChevronRight } from 'react-feather'
import { Flex } from 'rebass'
@ -6,11 +7,12 @@ import { ThemeContext } from 'styled-components'
import { TYPE } from '../../theme'
import { unwrappedToken } from 'utils/wrappedCurrency'
export default memo(function SwapRoute({ trade }: { trade: Trade }) {
export default memo(function SwapRoute({ trade }: { trade: V2Trade | V3Trade }) {
const tokenPath = trade instanceof V2Trade ? trade.route.path : trade.route.tokenPath
const theme = useContext(ThemeContext)
return (
<Flex flexWrap="wrap" width="100%" justifyContent="flex-end" alignItems="center">
{trade.route.path.map((token, i, path) => {
{tokenPath.map((token, i, path) => {
const isLastItem: boolean = i === path.length - 1
const currency = unwrappedToken(token)
return (

@ -1,5 +1,7 @@
import JSBI from 'jsbi'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'
import { JSBI, Trade } from '@uniswap/v2-sdk'
import { Trade as V2Trade } from '@uniswap/v2-sdk'
import { Trade as V3Trade } from '@uniswap/v3-sdk'
import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react'
import { ArrowDown } from 'react-feather'
import ReactGA from 'react-ga'
@ -22,6 +24,7 @@ import ProgressSteps from '../../components/ProgressSteps'
import SwapHeader from '../../components/swap/SwapHeader'
import { INITIAL_ALLOWED_SLIPPAGE } from '../../constants'
import useToggledVersion, { Version } from '../../hooks/useToggledVersion'
import { getTradeVersion } from '../../utils/getTradeVersion'
import { useActiveWeb3React } from '../../hooks'
import { useCurrency, useAllTokens } from '../../hooks/Tokens'
@ -90,6 +93,7 @@ export default function Swap({ history }: RouteComponentProps) {
const { independentField, typedValue, recipient } = useSwapState()
const {
v2Trade,
v3Trade,
currencyBalances,
parsedAmount,
currencies,
@ -104,13 +108,13 @@ export default function Swap({ history }: RouteComponentProps) {
)
const showWrap: boolean = wrapType !== WrapType.NOT_APPLICABLE
const { address: recipientAddress } = useENSAddress(recipient)
// const toggledVersion = useToggledVersion()
const toggledVersion = useToggledVersion()
const trade = showWrap
? undefined
: v2Trade /*{
: {
[Version.v2]: v2Trade,
[Version.v3]: v3Trade,
}[toggledVersion]*/
}[toggledVersion]
const parsedAmounts = showWrap
? {
@ -148,7 +152,7 @@ export default function Swap({ history }: RouteComponentProps) {
// modal and loading
const [{ showConfirm, tradeToConfirm, swapErrorMessage, attemptingTxn, txHash }, setSwapState] = useState<{
showConfirm: boolean
tradeToConfirm: Trade | undefined
tradeToConfirm: V2Trade | V3Trade | undefined
attemptingTxn: boolean
swapErrorMessage: string | undefined
txHash: string | undefined
@ -190,7 +194,11 @@ export default function Swap({ history }: RouteComponentProps) {
const atMaxAmountInput = Boolean(maxAmountInput && parsedAmounts[Field.INPUT]?.equalTo(maxAmountInput))
// the callback to execute the swap
const { callback: swapCallback, error: swapCallbackError } = useV2SwapCallback(trade, allowedSlippage, recipient)
const { callback: swapCallback, error: swapCallbackError } = useV2SwapCallback(
trade instanceof V2Trade ? trade : undefined,
allowedSlippage,
recipient
)
const { priceImpactWithoutFee } = computeTradePriceBreakdown(trade)

@ -89,8 +89,8 @@ export default createReducer(initialState, (builder) =>
calls.forEach((call) => {
const callKey = toCallKey(call)
const current = state.callResults[chainId][callKey]
if (!current) return // only should be dispatched if we are already fetching
if (current.fetchingBlockNumber === fetchingBlockNumber) {
if (!current || typeof current.fetchingBlockNumber !== 'number') return // only should be dispatched if we are already fetching
if (current.fetchingBlockNumber <= fetchingBlockNumber) {
delete current.fetchingBlockNumber
current.data = null
current.blockNumber = fetchingBlockNumber

@ -30,7 +30,7 @@ async function fetchChunk(
results: { success: boolean; returnData: string }[]
blockNumber: number
}> {
console.debug('Fetching chunk', multicall2Contract, chunk, minBlockNumber)
console.debug('Fetching chunk', chunk, minBlockNumber)
let resultsBlockNumber: number
let results: { success: boolean; returnData: string }[]
try {
@ -41,7 +41,7 @@ async function fetchChunk(
resultsBlockNumber = blockNumber.toNumber()
results = returnData
} catch (error) {
console.debug('Failed to fetch chunk inside retry', error)
console.debug('Failed to fetch chunk', error)
throw error
}
if (resultsBlockNumber < minBlockNumber) {
@ -205,12 +205,12 @@ export default function Updater(): null {
// dispatch any errored calls
if (erroredCalls.length > 0) {
console.debug('Errored calls', erroredCalls)
console.debug('Calls errored in fetch', erroredCalls)
dispatch(
errorFetchingMulticallResults({
calls: erroredCalls,
chainId,
fetchingBlockNumber: latestBlockNumber,
fetchingBlockNumber: fetchBlockNumber,
})
)
}

@ -14,36 +14,43 @@ const INPUT_FRACTION_AFTER_FEE = ONE_HUNDRED_PERCENT.subtract(BASE_FEE)
// computes price breakdown for the trade
export function computeTradePriceBreakdown(
trade?: V2Trade | null
trade?: V2Trade | V3Trade | null
): { priceImpactWithoutFee: Percent | undefined; realizedLPFee: CurrencyAmount | undefined | null } {
// 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))
const realizedLPFee = !trade
? undefined
: ONE_HUNDRED_PERCENT.subtract(
trade.route.pairs.reduce<Fraction>(
(currentFee: Fraction): Fraction => currentFee.multiply(INPUT_FRACTION_AFTER_FEE),
ONE_HUNDRED_PERCENT
if (trade instanceof V2Trade) {
// 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))
const realizedLPFee = !trade
? undefined
: ONE_HUNDRED_PERCENT.subtract(
trade.route.pairs.reduce<Fraction>(
(currentFee: Fraction): Fraction => currentFee.multiply(INPUT_FRACTION_AFTER_FEE),
ONE_HUNDRED_PERCENT
)
)
)
// remove lp fees from price impact
const priceImpactWithoutFeeFraction = trade && realizedLPFee ? trade.priceImpact.subtract(realizedLPFee) : undefined
// 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 x*y=k impact
const priceImpactWithoutFeePercent = priceImpactWithoutFeeFraction
? new Percent(priceImpactWithoutFeeFraction?.numerator, priceImpactWithoutFeeFraction?.denominator)
: undefined
// the amount of the input that accrues to LPs
const realizedLPFeeAmount =
realizedLPFee &&
trade &&
(trade.inputAmount instanceof TokenAmount
? new TokenAmount(trade.inputAmount.token, realizedLPFee.multiply(trade.inputAmount.raw).quotient)
: CurrencyAmount.ether(realizedLPFee.multiply(trade.inputAmount.raw).quotient))
// the amount of the input that accrues to LPs
const realizedLPFeeAmount =
realizedLPFee &&
trade &&
(trade.inputAmount instanceof TokenAmount
? new TokenAmount(trade.inputAmount.token, realizedLPFee.multiply(trade.inputAmount.raw).quotient)
: CurrencyAmount.ether(realizedLPFee.multiply(trade.inputAmount.raw).quotient))
return { priceImpactWithoutFee: priceImpactWithoutFeePercent, realizedLPFee: realizedLPFeeAmount }
return { priceImpactWithoutFee: priceImpactWithoutFeePercent, 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