Commit 980eb8a5 authored by Justin Domingue's avatar Justin Domingue Committed by GitHub

Leverage Trade api for USDC price with v2 & v3 support (#1610)

* calculate usdc price using trade exact out

* fix typo

* add support for non-mainnet

* use fromRawAmount instead of tryParseAmount
parent a11e89c0
import { ChainId, Currency, CurrencyAmount, currencyEquals, Price, Token, WETH9 } from '@uniswap/sdk-core' import { ChainId, Currency, CurrencyAmount, Price, Token } from '@uniswap/sdk-core'
import JSBI from 'jsbi'
import { useMemo } from 'react' import { useMemo } from 'react'
import { USDC } from '../constants/tokens' import { USDC } from '../constants/tokens'
import { PairState, useV2Pairs } from './useV2Pairs' import { useV2TradeExactOut } from './useV2Trade'
import { useBestV3TradeExactOut, V3TradeState } from './useBestV3Trade'
import { useActiveWeb3React } from './web3' import { useActiveWeb3React } from './web3'
import { wrappedCurrency } from '../utils/wrappedCurrency'
// USDC amount used when calculating spot price for a given currency.
// The amount is large enough to filter low liquidity pairs.
const usdcCurrencyAmount = CurrencyAmount.fromRawAmount(USDC, 10_000e6)
/** /**
* Returns the price in USDC of the input currency * Returns the price in USDC of the input currency
...@@ -12,23 +15,15 @@ import { wrappedCurrency } from '../utils/wrappedCurrency' ...@@ -12,23 +15,15 @@ import { wrappedCurrency } from '../utils/wrappedCurrency'
*/ */
export default function useUSDCPrice(currency?: Currency): Price<Currency, Token> | undefined { export default function useUSDCPrice(currency?: Currency): Price<Currency, Token> | undefined {
const { chainId } = useActiveWeb3React() const { chainId } = useActiveWeb3React()
const wrapped = wrappedCurrency(currency, chainId)
const weth = WETH9[chainId as ChainId]
const tokenPairs: [Currency | undefined, Currency | undefined][] = useMemo( const v2USDCTrade = useV2TradeExactOut(currency, chainId === ChainId.MAINNET ? usdcCurrencyAmount : undefined)
() => [ const v3USDCTrade = useBestV3TradeExactOut(currency, chainId === ChainId.MAINNET ? usdcCurrencyAmount : undefined)
[chainId && wrapped && currencyEquals(weth, wrapped) ? undefined : currency, chainId ? weth : undefined],
[wrapped?.equals(USDC) ? undefined : wrapped, chainId === ChainId.MAINNET ? USDC : undefined],
[chainId ? weth : undefined, chainId === ChainId.MAINNET ? USDC : undefined],
],
[chainId, currency, weth, wrapped]
)
const [[ethPairState, ethPair], [usdcPairState, usdcPair], [usdcEthPairState, usdcEthPair]] = useV2Pairs(tokenPairs)
return useMemo(() => { return useMemo(() => {
if (!currency || !wrapped || !chainId) { if (!currency || !chainId) {
return undefined return undefined
} }
// return some fake price data for non-mainnet // return some fake price data for non-mainnet
if (chainId !== ChainId.MAINNET) { if (chainId !== ChainId.MAINNET) {
const fakeUSDC = new Token(chainId, '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 6, 'fUSDC', 'Fake USDC') const fakeUSDC = new Token(chainId, '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 6, 'fUSDC', 'Fake USDC')
...@@ -40,42 +35,17 @@ export default function useUSDCPrice(currency?: Currency): Price<Currency, Token ...@@ -40,42 +35,17 @@ export default function useUSDCPrice(currency?: Currency): Price<Currency, Token
) )
} }
// handle weth/eth // use v2 price if available, v3 as fallback
if (wrapped.equals(weth)) { if (v2USDCTrade) {
if (usdcPair) { const { numerator, denominator } = v2USDCTrade.route.midPrice
const price = usdcPair.priceOf(weth) return new Price(currency, USDC, denominator, numerator)
return new Price(currency, USDC, price.denominator, price.numerator) } else if (v3USDCTrade.state === V3TradeState.VALID && v3USDCTrade.trade) {
} else { const { numerator, denominator } = v3USDCTrade.trade.route.midPrice
return undefined return new Price(currency, USDC, denominator, numerator)
}
}
// handle usdc
if (wrapped.equals(USDC)) {
return new Price(USDC, USDC, '1', '1')
} }
const ethPairETHAmount = ethPair?.reserveOf(weth)
const ethPairETHUSDCValue: JSBI =
ethPairETHAmount?.greaterThan(0) && usdcEthPair?.reserveOf(weth)?.greaterThan(0)
? usdcEthPair.priceOf(weth).quote(ethPairETHAmount).quotient
: JSBI.BigInt(0)
// all other tokens
// first try the usdc pair
if (usdcPairState === PairState.EXISTS && usdcPair && usdcPair.reserveOf(USDC).greaterThan(ethPairETHUSDCValue)) {
const price = usdcPair.priceOf(wrapped)
return new Price(currency, USDC, price.denominator, price.numerator)
}
if (ethPairState === PairState.EXISTS && ethPair && usdcEthPairState === PairState.EXISTS && usdcEthPair) {
if (usdcEthPair.reserveOf(USDC).greaterThan('0') && ethPair.reserveOf(weth).greaterThan('0')) {
const ethUsdcPrice = usdcEthPair.priceOf(USDC)
const currencyEthPrice = ethPair.priceOf(weth)
const usdcPrice = ethUsdcPrice.multiply(currencyEthPrice).invert()
return new Price(currency, USDC, usdcPrice.denominator, usdcPrice.numerator)
}
}
return undefined return undefined
}, [chainId, currency, ethPair, ethPairState, usdcEthPair, usdcEthPairState, usdcPair, usdcPairState, weth, wrapped]) }, [chainId, currency, v2USDCTrade, v3USDCTrade])
} }
export function useUSDCValue(currencyAmount: CurrencyAmount<Currency> | undefined | null) { export function useUSDCValue(currencyAmount: CurrencyAmount<Currency> | undefined | null) {
......
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