Skip to content
This repository was archived by the owner on Jun 24, 2022. It is now read-only.

Commit

Permalink
[USD Price] Add coingecko api and hooks (#1356)
Browse files Browse the repository at this point in the history
* coingecko api

* coingecko usd hooks

* use in swapmod

* replace useUSDCValue with useHigherUSDValue

* comment

* mod computeFiatValue fn

* made dumb comp

* smarter container

* naming

* remove unnecessary mod

* parse usd price from API as USDC

* fix infiniLoop (TM)

* remove trans from priceImpact

* fix baseAmount
  • Loading branch information
W3stside committed Sep 22, 2021
1 parent 30b582b commit 24d4b56
Show file tree
Hide file tree
Showing 10 changed files with 262 additions and 24 deletions.
98 changes: 98 additions & 0 deletions src/custom/api/coingecko/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { SupportedChainId as ChainId } from 'constants/chains'
import { PriceInformation } from 'utils/price'

function getApiUrl(): string {
// it's all the same base url
return 'https://api.coingecko.com/api'
}

// https://api.coingecko.com/api/v3/simple/token_price/ethereum?contract_addresses=0x33e18a092a93ff21ad04746c7da12e35d34dc7c4&vs_currencies=usd
// Defaults
const API_NAME = 'Coingecko'
const API_BASE_URL = getApiUrl()
const API_VERSION = 'v3'
const DEFAULT_HEADERS = {
'Content-Type': 'application/json',
}

function _getApiBaseUrl(chainId: ChainId): string {
const baseUrl = API_BASE_URL

if (!baseUrl) {
throw new Error(`Unsupported Network. The ${API_NAME} API is not deployed in the Network ${chainId}`)
} else {
return baseUrl + '/' + API_VERSION
}
}

function _getCoinGeckoAssetPlatform(chainId: ChainId) {
switch (chainId) {
// Use of asset platforms - supports ethereum and xdai
// https://api.coingecko.com/api/v3/asset_platforms
case ChainId.MAINNET:
return 'ethereum'
case ChainId.XDAI:
return 'xdai'
default:
return null
}
}

function _fetch(chainId: ChainId, url: string, method: 'GET' | 'POST' | 'DELETE', data?: any): Promise<Response> {
const baseUrl = _getApiBaseUrl(chainId)
return fetch(baseUrl + url, {
headers: DEFAULT_HEADERS,
method,
body: data !== undefined ? JSON.stringify(data) : data,
})
}

// TODO: consider making these _get/_delete/_post etc reusable across apis
function _get(chainId: ChainId, url: string): Promise<Response> {
return _fetch(chainId, url, 'GET')
}

export interface CoinGeckoUsdPriceParams {
chainId: ChainId
tokenAddress: string
}

interface CoinGeckoUsdQuote {
[address: string]: {
usd: number
}
}

export async function getUSDPriceQuote(params: CoinGeckoUsdPriceParams): Promise<CoinGeckoUsdQuote | null> {
const { chainId, tokenAddress } = params
// ethereum/xdai (chains)
const assetPlatform = _getCoinGeckoAssetPlatform(chainId)
if (assetPlatform == null) {
// Unsupported
return null
}

console.log(`[api:${API_NAME}] Get USD price from ${API_NAME}`, params)

const response = await _get(
chainId,
`/simple/token_price/${assetPlatform}?contract_addresses=${tokenAddress}&vs_currencies=usd`
).catch((error) => {
console.error(`Error getting ${API_NAME} USD price quote:`, error)
throw new Error(error)
})

return response.json()
}

export function toPriceInformation(priceRaw: CoinGeckoUsdQuote | null): PriceInformation | null {
// We only receive/want the first key/value pair in the return object
const token = priceRaw ? Object.keys(priceRaw)[0] : null

if (!token || !priceRaw?.[token].usd) {
return null
}

const { usd } = priceRaw[token]
return { amount: usd.toString(), token }
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export function FiatValue({
)}
{priceImpact ? (
<span style={{ color: priceImpactColor }}>
&nbsp;(<Trans>{formatSmart(priceImpact.multiply(-1), PERCENTAGE_PRECISION)}%</Trans>)
&nbsp;({formatSmart(priceImpact.multiply(-1), PERCENTAGE_PRECISION)}%)
</span>
) : null}
</TYPE.body>
Expand Down
16 changes: 13 additions & 3 deletions src/custom/components/swap/FeeInformationTooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import React, { useMemo } from 'react'
import TradeGp from 'state/swap/TradeGp'
import QuestionHelper from 'components/QuestionHelper'
import styled from 'styled-components'
import { useUSDCValue } from 'hooks/useUSDCPrice'
import { formatMax, formatSmart } from 'utils/format'
import useTheme from 'hooks/useTheme'
import { FIAT_PRECISION } from 'constants/index'
import { CurrencyAmount, Token } from '@uniswap/sdk-core'

interface FeeInformationTooltipProps {
trade?: TradeGp
Expand All @@ -15,6 +15,7 @@ interface FeeInformationTooltipProps {
amountAfterFees?: string
feeAmount?: string
type: 'From' | 'To'
fiatValue: CurrencyAmount<Token> | null
showFiat?: boolean
}

Expand Down Expand Up @@ -73,10 +74,19 @@ const FeeInnerWrapper = styled.div`
`

export default function FeeInformationTooltip(props: FeeInformationTooltipProps) {
const { trade, label, amountBeforeFees, amountAfterFees, feeAmount, type, showHelper, showFiat = false } = props
const {
trade,
label,
amountBeforeFees,
amountAfterFees,
feeAmount,
type,
showHelper,
fiatValue,
showFiat = false,
} = props

const theme = useTheme()
const fiatValue = useUSDCValue(type === 'From' ? trade?.inputAmount : trade?.outputAmount)

const [symbol, fullFeeAmount] = useMemo(() => {
const amount = trade?.[type === 'From' ? 'inputAmount' : 'outputAmount']
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import React, { useState, useContext, useMemo } from 'react'
import { ArrowDown, AlertTriangle } from 'react-feather'
import { Text } from 'rebass'
import styled, { ThemeContext } from 'styled-components'
import { useUSDCValue } from 'hooks/useUSDCPrice'
import { useHigherUSDValue /* , useUSDCValue */ } from 'hooks/useUSDCPrice'
import { TYPE } from 'theme'
import { ButtonPrimary } from 'components/Button'
import { isAddress, shortenAddress } from 'utils'
Expand Down Expand Up @@ -89,8 +89,10 @@ SwapModalHeaderProps) {
const [showInverted, setShowInverted] = useState<boolean>(false)

// show fiatValue for unadjusted trade amounts!
const fiatValueInput = useUSDCValue(trade.inputAmountWithoutFee)
const fiatValueOutput = useUSDCValue(trade.outputAmountWithoutFee)
// const fiatValueInput = useUSDCValue(trade.inputAmountWithoutFee)
// const fiatValueOutput = useUSDCValue(trade.outputAmountWithoutFee)
const fiatValueInput = useHigherUSDValue(trade.inputAmountWithoutFee)
const fiatValueOutput = useHigherUSDValue(trade.outputAmountWithoutFee)

const [slippageIn, slippageOut] = useMemo(
() => [slippageAdjustedAmounts[Field.INPUT], slippageAdjustedAmounts[Field.OUTPUT]],
Expand Down Expand Up @@ -148,6 +150,7 @@ SwapModalHeaderProps) {
showHelper
trade={trade}
type="From"
fiatValue={fiatValueInput}
/>
</AuxInformationContainer>
)}
Expand Down Expand Up @@ -200,6 +203,7 @@ SwapModalHeaderProps) {
showHelper
trade={trade}
type="To"
fiatValue={fiatValueOutput}
/>
</AuxInformationContainer>
)}
Expand Down
5 changes: 3 additions & 2 deletions src/custom/components/swap/TradePrice/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useMemo } from 'react'
import TradePriceMod, { TradePriceProps } from './TradePriceMod'
import { useUSDCValue } from 'hooks/useUSDCPrice'
import { useHigherUSDValue /* useUSDCValue */ } from 'hooks/useUSDCPrice'
import { formatSmart } from 'utils/format'
import { tryParseAmount } from 'state/swap/hooks'
import { FIAT_PRECISION } from 'constants/index'
Expand All @@ -17,7 +17,8 @@ export default function TradePrice(props: Omit<TradePriceProps, 'fiatValue'>) {
: tryParseAmount(price.toFixed(price.quoteCurrency.decimals), price.quoteCurrency),
[price, showInverted]
)
const amount = useUSDCValue(priceSide)
// const amount = useUSDCValue(priceSide)
const amount = useHigherUSDValue(priceSide)
const fiatValueFormatted = formatSmart(amount, FIAT_PRECISION)

return <TradePriceMod {...props} fiatValue={fiatValueFormatted} />
Expand Down
8 changes: 3 additions & 5 deletions src/custom/components/swap/TradeSummary/RowFee.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useContext } from 'react'
import { CurrencyAmount, Currency, TradeType } from '@uniswap/sdk-core'
import { CurrencyAmount, Currency, TradeType, Token } from '@uniswap/sdk-core'
import { ThemeContext } from 'styled-components'
import { TYPE } from 'theme'

Expand All @@ -10,7 +10,6 @@ import { RowBetween, RowFixed } from 'components/Row'
import { MouseoverTooltipContent } from 'components/Tooltip'
import { AMOUNT_PRECISION, FIAT_PRECISION } from 'constants/index'
import { LightGreyText } from 'pages/Swap'
import { useUSDCValue } from 'hooks/useUSDCPrice'

export const GASLESS_FEE_TOOLTIP_MSG =
'On CowSwap you sign your order (hence no gas costs!). The fees are covering your gas costs already.'
Expand Down Expand Up @@ -39,7 +38,7 @@ export interface RowFeeProps {
// Even for invalid trades, we want to display the fee, this is why there's another "fee" parameter
trade?: TradeGp
fee?: CurrencyAmount<Currency>

feeFiatValue: CurrencyAmount<Token> | null
showHelpers: boolean
allowsOffchainSigning: boolean
fontWeight?: number
Expand All @@ -50,6 +49,7 @@ export interface RowFeeProps {
export function RowFee({
trade,
fee,
feeFiatValue,
allowsOffchainSigning,
showHelpers,
fontSize = 14,
Expand All @@ -60,8 +60,6 @@ export function RowFee({
const { realizedFee } = React.useMemo(() => computeTradePriceBreakdown(trade), [trade])
// trades are null when there is a fee quote error e.g
// so we can take both
const feeAmount = trade?.fee.feeAsCurrency || fee
const feeFiatValue = useUSDCValue(feeAmount)
const feeFiatDisplay = `(≈$${formatSmart(feeFiatValue, FIAT_PRECISION)})`

const displayFee = realizedFee || fee
Expand Down
3 changes: 3 additions & 0 deletions src/custom/components/swap/TradeSummary/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { RowFixed } from 'components/Row'
import { RowFee } from './RowFee'
import { RowSlippage } from './RowSlippage'
import { RowReceivedAfterSlippage } from './RowReceivedAfterSlippage'
import { useHigherUSDValue } from 'hooks/useUSDCPrice'

const Wrapper = styled.div`
${RowFixed} {
Expand All @@ -22,6 +23,7 @@ export type TradeSummaryProps = Required<AdvancedSwapDetailsProps>

export default function TradeSummary({ trade, allowedSlippage, showHelpers, showFee }: TradeSummaryProps) {
const allowsOffchainSigning = true // TODO: Next PR will handle this
const feeFiatValue = useHigherUSDValue(trade.fee.feeAsCurrency)

return (
<Wrapper>
Expand All @@ -30,6 +32,7 @@ export default function TradeSummary({ trade, allowedSlippage, showHelpers, show
{showFee && (
<RowFee
trade={trade}
feeFiatValue={feeFiatValue}
allowsOffchainSigning={allowsOffchainSigning}
showHelpers={showHelpers}
fontSize={12}
Expand Down
Loading

0 comments on commit 24d4b56

Please sign in to comment.