diff --git a/src/constants/index.ts b/src/constants/index.ts index 7fac3ed420..b8f2a4ef6e 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -141,7 +141,9 @@ export const BLOCKED_PRICE_IMPACT_NON_DEGEN: Percent = new Percent(JSBI.BigInt(1 export const BUNDLE_ID = '1' +export const COINGECKO_BFF_API_URL = `${ENV.BFF_API}/v1/coingecko/api/v3` export const COINGECKO_API_URL = 'https://api.coingecko.com/api/v3' + export const KNC_COINGECKO_ID = 'kyber-network-crystal' export const ETHER_ADDRESS = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE' diff --git a/src/hooks/useBasicChartData.ts b/src/hooks/useBasicChartData.ts index a16bad8827..fd7c961b70 100644 --- a/src/hooks/useBasicChartData.ts +++ b/src/hooks/useBasicChartData.ts @@ -1,3 +1,4 @@ +import { KyberOauth2Api } from '@kybernetwork/oauth2' import { ChainId, Token, WETH } from '@kyberswap/ks-sdk-core' import axios from 'axios' import { getUnixTime, subHours } from 'date-fns' @@ -5,10 +6,11 @@ import { useMemo } from 'react' import useSWR from 'swr' import { AGGREGATOR_API, PRICE_CHART_API } from 'constants/env' -import { COINGECKO_API_URL } from 'constants/index' import { NETWORKS_INFO } from 'constants/networks' import { useActiveWeb3React } from 'hooks' +import useCoingeckoAPI from './useCoingeckoAPI' + export enum LiveDataTimeframeEnum { HOUR = '1H', FOUR_HOURS = '4H', @@ -37,6 +39,7 @@ const getTimeFrameHours = (timeFrame: LiveDataTimeframeEnum) => { } } const generateCoingeckoUrl = ( + coingeckoAPI: string, chainId: ChainId, address: string | undefined, timeFrame: LiveDataTimeframeEnum | 'live', @@ -46,7 +49,7 @@ const generateCoingeckoUrl = ( timeFrame === 'live' ? timeTo - 1000 : getUnixTime(subHours(new Date(), getTimeFrameHours(timeFrame))) const cgkId = NETWORKS_INFO[chainId].coingeckoNetworkId if (!cgkId) return '' - return `${COINGECKO_API_URL}/coins/${cgkId}/contract/${address}/market_chart/range?vs_currency=usd&from=${timeFrom}&to=${timeTo}` + return `${coingeckoAPI}/coins/${cgkId}/contract/${address}/market_chart/range?vs_currency=usd&from=${timeFrom}&to=${timeTo}` } const getClosestPrice = (prices: any[], time: number) => { let closestIndex = 0 @@ -67,16 +70,14 @@ const fetchKyberDataSWR = async (url: string) => { } const fetchKyberDataSWRWithHeader = async (url: string) => { - const res = await axios - .get(url, { - timeout: 5000, - headers: { - 'accept-version': 'Latest', - }, - }) - .catch(error => { - throw error - }) + const res = await KyberOauth2Api.get(url, { + timeout: 5000, + headers: { + 'accept-version': 'Latest', + }, + }).catch(error => { + throw error + }) if (res.status === 204) { throw new Error('No content') @@ -84,15 +85,15 @@ const fetchKyberDataSWRWithHeader = async (url: string) => { return res.data } -const fetchCoingeckoDataSWR = async ([tokenAddresses, chainIds, timeFrame]: [ +const fetchCoingeckoDataSWR = async ([tokenAddresses, chainIds, timeFrame, coingeckoAPI]: [ tokenAddresses: string[], chainIds: ChainId[], timeFrame: any, + coingeckoAPI: string, ]): Promise => { return await Promise.all( [tokenAddresses[0], tokenAddresses[1]].map((address, i) => - axios - .get(generateCoingeckoUrl(chainIds[i], address, timeFrame), { timeout: 5000 }) + KyberOauth2Api.get(generateCoingeckoUrl(coingeckoAPI, chainIds[i], address, timeFrame), { timeout: 5000 }) .then(res => { if (res.status === 204) { throw new Error('No content') @@ -113,6 +114,7 @@ export default function useBasicChartData( timeFrame: LiveDataTimeframeEnum, ): { data: ChartData[]; loading: boolean; error: any } { const { chainId, isEVM, networkInfo } = useActiveWeb3React() + const coingeckoAPI = useCoingeckoAPI() const isReverse = useMemo(() => { if (!tokens || !tokens[0] || !tokens[1] || tokens[0].equals(tokens[1]) || tokens[0].chainId !== tokens[1].chainId) @@ -135,8 +137,9 @@ export default function useBasicChartData( isValidating: coingeckoLoading, } = useSWR( tokenAddresses[0] && tokenAddresses[1] - ? [tokenAddresses, [tokens[0]?.chainId, tokens[1]?.chainId], timeFrame] + ? [tokenAddresses, [tokens[0]?.chainId, tokens[1]?.chainId], timeFrame, coingeckoAPI] : null, + fetchCoingeckoDataSWR, { shouldRetryOnError: false, @@ -210,7 +213,9 @@ export default function useBasicChartData( ) const { data: liveCoingeckoData } = useSWR( - isKyberDataNotValid && coingeckoData ? [tokenAddresses, [tokens[0]?.chainId, tokens[1]?.chainId], 'live'] : null, + isKyberDataNotValid && coingeckoData + ? [tokenAddresses, [tokens[0]?.chainId, tokens[1]?.chainId], 'live', coingeckoAPI] + : null, fetchCoingeckoDataSWR, { refreshInterval: 60000, diff --git a/src/hooks/useCoingeckoAPI.ts b/src/hooks/useCoingeckoAPI.ts new file mode 100644 index 0000000000..4e0b27655c --- /dev/null +++ b/src/hooks/useCoingeckoAPI.ts @@ -0,0 +1,7 @@ +import { COINGECKO_API_URL, COINGECKO_BFF_API_URL } from 'constants/index' +import { useSessionInfo } from 'state/authen/hooks' + +export default function useCoingeckoAPI() { + const { authenticationSuccess } = useSessionInfo() + return authenticationSuccess ? COINGECKO_BFF_API_URL : COINGECKO_API_URL +} diff --git a/src/hooks/useTokenInfo.ts b/src/hooks/useTokenInfo.ts index c0ab346445..289faa3b66 100644 --- a/src/hooks/useTokenInfo.ts +++ b/src/hooks/useTokenInfo.ts @@ -1,10 +1,12 @@ +import { KyberOauth2Api } from '@kybernetwork/oauth2' import { Token, WETH } from '@kyberswap/ks-sdk-core' import useSWR from 'swr' -import { COINGECKO_API_URL } from 'constants/index' import { NETWORKS_INFO } from 'constants/networks' import { useActiveWeb3React } from 'hooks' +import useCoingeckoAPI from './useCoingeckoAPI' + export interface TokenInfo { price: number marketCap: number @@ -21,8 +23,20 @@ export interface TokenInfo { export default function useTokenInfo(token: Token | undefined): { data: TokenInfo; loading: boolean; error: any } { const { isSolana, chainId: currentChain } = useActiveWeb3React() const chainId = token?.chainId || currentChain - - const fetcher = (url: string) => (url ? fetch(url).then(r => r.json()) : Promise.reject({ data: {}, error: '' })) + const coingeckoAPI = useCoingeckoAPI() + const fetcher = (url: string) => + url + ? KyberOauth2Api.get(url) + .then(res => { + if (res.status === 204) { + throw new Error('No content') + } + return res.data + }) + .catch(error => { + throw error + }) + : Promise.reject({ data: {}, error: '' }) const tokenAddress = isSolana ? token?.address || '' : (token?.address || '').toLowerCase() @@ -30,9 +44,9 @@ export default function useTokenInfo(token: Token | undefined): { data: TokenInf if (tokenAddress.toLowerCase() === WETH[chainId].address.toLowerCase()) { // If the token is native token, we have to use different endpoint - url = `${COINGECKO_API_URL}/coins/${NETWORKS_INFO[chainId].coingeckoNativeTokenId}` + url = `${coingeckoAPI}/coins/${NETWORKS_INFO[chainId].coingeckoNativeTokenId}` } else if (tokenAddress) { - url = `${COINGECKO_API_URL}/coins/${NETWORKS_INFO[chainId].coingeckoNetworkId}/contract/${tokenAddress}` + url = `${coingeckoAPI}/coins/${NETWORKS_INFO[chainId].coingeckoNetworkId}/contract/${tokenAddress}` } const { data, error } = useSWR(url, fetcher, { diff --git a/src/pages/SwapV3/HeaderRightMenu.tsx b/src/pages/SwapV3/HeaderRightMenu.tsx index f868c783b9..f3b9919690 100644 --- a/src/pages/SwapV3/HeaderRightMenu.tsx +++ b/src/pages/SwapV3/HeaderRightMenu.tsx @@ -104,7 +104,9 @@ export default function HeaderRightMenu({ type={TutorialType.SWAP} customIcon={ mixpanelHandler(MIXPANEL_TYPE.SWAP_TUTORIAL_CLICK)}> - + + + } /> @@ -130,12 +132,7 @@ export default function HeaderRightMenu({ }} aria-label="Swap Settings" > - Settings} - placement="top" - width="fit-content" - disableTooltip={isMobile} - > +