diff --git a/.env b/.env index e800b7d45..7eabada29 100644 --- a/.env +++ b/.env @@ -7,10 +7,11 @@ REACT_APP_PORTIS_ID="e086c1f2-2d26-4443-804f-3398bbab069e" REACT_APP_FORTMATIC_KEY="pk_live_F937DF033A1666BF" REACT_APP_MOONPAY_KEY="pk_live_72EGoobLnlgc8WB7AaxyiWu2S43dj8eY" REACT_APP_TRANSAK_KEY="258960cf-1e17-4419-bf7f-77443282f5da" -REACT_APP_GRAPH_API_URL="https://polygon.furadao.org/subgraphs/name/quickswap" +REACT_APP_GRAPH_API_URL="https://api.fura.org/subgraphs/name/quickswap" REACT_APP_PRDT_URL="https://prdt-quickswap-main.pages.dev/" REACT_APP_SCAN_BASE_URL="https://polygonscan.com" REACT_APP_TOKEN_LIST_DEFAULT_URL="https://unpkg.com/quickswap-default-token-list@latest/build/quickswap-default.tokenlist.json" REACT_APP_STAKING_LIST_DEFAULT_URL="https://unpkg.com/quickswap-default-staking-list@latest/build/quickswap-default.lpfarms.json" REACT_APP_DUAL_STAKING_LIST_DEFAULT_URL="https://unpkg.com/quickswap-default-staking-list@latest/build/quickswap-default.dualfarms.json" REACT_APP_SYRUP_LIST_DEFAULT_URL="https://unpkg.com/quickswap-default-staking-list@latest/build/quickswap-default.syrups.json" +REACT_APP_LEGACY_APP_URL="https://legacy.quickswap.exchange" \ No newline at end of file diff --git a/.env.production b/.env.production index c9bebbc3b..7e0bd1ca5 100644 --- a/.env.production +++ b/.env.production @@ -5,4 +5,4 @@ REACT_APP_FORTMATIC_KEY="pk_live_F937DF033A1666BF" REACT_APP_GOOGLE_ANALYTICS_ID="UA-188438708-1" REACT_APP_MOONPAY_KEY="pk_live_72EGoobLnlgc8WB7AaxyiWu2S43dj8eY" REACT_APP_TRANSAK_KEY="258960cf-1e17-4419-bf7f-77443282f5da" -REACT_APP_GRAPH_API_URL="https://polygon.furadao.org/subgraphs/name/quickswap" \ No newline at end of file +REACT_APP_GRAPH_API_URL="https://api.fura.org/subgraphs/name/quickswap" \ No newline at end of file diff --git a/public/locales/en.json b/public/locales/en.json index a98a7dea3..af386ad5e 100755 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -242,7 +242,7 @@ "transactionsWillAppear": "Your transactions will appear here", "copied": "Copied", "showPortis": "Show Portis", - "betaWarningDesc": "This site is in beta. By using this software, you understand, acknowledge and accept that Quickswap and/or the underlying software are provided “as is” and “as available” basis and without warranties or representations of any kind either expressed or implied.", + "betaWarningDesc": "You're on the new productions site if you'd like to use the old site please navigate to: ", "fiatProviders": "Fiat gateway providers", "buy": "Buy", "fiatServiceDesc": "Fiat services on Quickswap are provided by third-parties. Quickswap is not associated with, responsible or liable for the performance of these third-party services. Any claims & questions should be addressed with the selected provider.", @@ -288,7 +288,7 @@ "timeRemaining": "Time Remaining", "rewardsEnded": "Rewards Ended", "24hPer": "24H %", - "24hTopMovers": "24h TOP MOVERS", + "24hMostVolume": "24h MOST VOLUME", "waitingConfirm": "Waiting For Confirmation", "confirmTxinWallet": "Please confirm this transaction in your wallet.", "txSubmitted": "Transaction Submitted", diff --git a/src/apollo/queries.ts b/src/apollo/queries.ts index b0687c5a5..9215ed55d 100755 --- a/src/apollo/queries.ts +++ b/src/apollo/queries.ts @@ -29,6 +29,7 @@ export const TOKEN_SEARCH = gql` symbol name decimals + tradeVolumeUSD totalLiquidity } asName: tokens( @@ -40,6 +41,7 @@ export const TOKEN_SEARCH = gql` symbol name decimals + tradeVolumeUSD totalLiquidity } asAddress: tokens( @@ -51,6 +53,7 @@ export const TOKEN_SEARCH = gql` symbol name decimals + tradeVolumeUSD totalLiquidity } } @@ -60,6 +63,7 @@ export const PAIR_SEARCH = gql` query pairs($tokens: [Bytes]!, $id: String) { as0: pairs(where: { token0_in: $tokens }) { id + trackedReserveETH token0 { id symbol @@ -75,6 +79,7 @@ export const PAIR_SEARCH = gql` } as1: pairs(where: { token1_in: $tokens }) { id + trackedReserveETH token0 { id symbol @@ -90,6 +95,7 @@ export const PAIR_SEARCH = gql` } asAddress: pairs(where: { id: $id }) { id + trackedReserveETH token0 { id symbol @@ -219,6 +225,7 @@ export const ALL_TOKENS = gql` name symbol decimals + tradeVolumeUSD totalLiquidity } } @@ -233,6 +240,7 @@ export const ALL_PAIRS = gql` orderDirection: desc ) { id + trackedReserveETH token0 { id symbol @@ -418,10 +426,10 @@ export const TOKEN_DATA1: any = ( export const TOKEN_DATA2: any = (tokenAddress: string) => { const queryString = ` query tokens { - pairs0: pairs(where: {token0: "${tokenAddress}"}, first: 100, orderBy: reserveUSD, orderDirection: desc){ + pairs0: pairs(where: {token0: "${tokenAddress}"}, first: 50, orderBy: reserveUSD, orderDirection: desc){ id } - pairs1: pairs(where: {token1: "${tokenAddress}"}, first: 100, orderBy: reserveUSD, orderDirection: desc){ + pairs1: pairs(where: {token1: "${tokenAddress}"}, first: 50, orderBy: reserveUSD, orderDirection: desc){ id } } @@ -462,22 +470,6 @@ export const ETH_PRICE: any = (block?: number) => { return gql(queryString); }; -export const ETH_ALLPRICE: any = (block?: number) => { - const queryString = ` - query bundles { - oneDayBackPrice: bundles(where: { id: ${GlobalConst.utils.BUNDLE_ID} } block: {number: ${block}}) { - id - ethPrice - } - currentPrice: bundles(where: { id: ${GlobalConst.utils.BUNDLE_ID} }) { - id - ethPrice - } - } - `; - return gql(queryString); -}; - export const PAIRS_HISTORICAL_BULK: any = (block: number, pairs: any[]) => { let pairsString = `[`; pairs.map((pair) => { diff --git a/src/components/AnalyticsSearch/index.tsx b/src/components/AnalyticsSearch/index.tsx new file mode 100644 index 000000000..d2efb9626 --- /dev/null +++ b/src/components/AnalyticsSearch/index.tsx @@ -0,0 +1,357 @@ +import React, { useEffect, useState, useRef, useMemo } from 'react'; +import { useHistory } from 'react-router-dom'; +import { Box } from '@material-ui/core'; +import { ReactComponent as SearchIcon } from 'assets/images/SearchIcon.svg'; +import { client } from 'apollo/client'; +import { TOKEN_SEARCH, PAIR_SEARCH, TOKEN_INFO_OLD } from 'apollo/queries'; +import { + getAllTokensOnUniswap, + getAllPairsOnUniswap, + getBlockFromTimestamp, +} from 'utils'; +import { GlobalConst, MATIC_CHAIN } from 'constants/index'; +import { CurrencyLogo, DoubleCurrencyLogo } from 'components'; +import { ChainId, Token } from '@uniswap/sdk'; +import { getAddress } from '@ethersproject/address'; +import 'components/styles/SearchWidget.scss'; +import { useTranslation } from 'react-i18next'; +import dayjs from 'dayjs'; +import utc from 'dayjs/plugin/utc'; +import useDebouncedChangeHandler from 'utils/useDebouncedChangeHandler'; +dayjs.extend(utc); + +const AnalyticsSearch: React.FC = () => { + const { t } = useTranslation(); + const history = useHistory(); + const [searchVal, setSearchVal] = useState(''); + const [searchValInput, setSearchValInput] = useDebouncedChangeHandler( + searchVal, + setSearchVal, + ); + const [menuOpen, setMenuOpen] = useState(false); + const menuRef = useRef(null); + const wrapperRef = useRef(null); + const [searchedTokens, setSearchedTokens] = useState([]); + const [searchedPairs, setSearchedPairs] = useState([]); + const [tokensShown, setTokensShown] = useState(3); + const [pairsShown, setPairsShown] = useState(3); + + const escapeRegExp = (str: string) => { + return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + }; + + const filteredTokens = useMemo(() => { + const uniqueTokens: any[] = []; + const found: any = {}; + if (searchedTokens && searchedTokens.length > 0) { + searchedTokens.map((token) => { + if (!found[token.id]) { + found[token.id] = true; + uniqueTokens.push(token); + } + return true; + }); + } + const filtered = + uniqueTokens && uniqueTokens.length > 0 + ? uniqueTokens + .sort((tokenA, tokenB) => { + return tokenA.oneDayVolumeUSD > tokenB.oneDayVolumeUSD ? -1 : 1; + }) + .filter((token) => { + if (GlobalConst.blacklists.TOKEN_BLACKLIST.includes(token.id)) { + return false; + } + const regexMatches = Object.keys(token).map((tokenEntryKey) => { + const isAddress = searchVal.slice(0, 2) === '0x'; + if (tokenEntryKey === 'id' && isAddress) { + return token[tokenEntryKey].match( + new RegExp(escapeRegExp(searchVal), 'i'), + ); + } + if (tokenEntryKey === 'symbol' && !isAddress) { + return token[tokenEntryKey].match( + new RegExp(escapeRegExp(searchVal), 'i'), + ); + } + if (tokenEntryKey === 'name' && !isAddress) { + return token[tokenEntryKey].match( + new RegExp(escapeRegExp(searchVal), 'i'), + ); + } + return false; + }); + return regexMatches.some((m) => m); + }) + : []; + return filtered; + }, [searchedTokens, searchVal]); + + const filteredPairs = useMemo(() => { + const uniquePairs: any[] = []; + const pairsFound: any = {}; + if (searchedPairs && searchedPairs.length > 0) + searchedPairs.map((pair) => { + if (!pairsFound[pair.id]) { + pairsFound[pair.id] = true; + uniquePairs.push(pair); + } + return true; + }); + + const filtered = uniquePairs + ? uniquePairs + .sort((pairA, pairB) => { + const pairAReserveETH = Number(pairA?.trackedReserveETH ?? 0); + const pairBReserveETH = Number(pairB?.trackedReserveETH ?? 0); + return pairAReserveETH > pairBReserveETH ? -1 : 1; + }) + .filter((pair) => { + if (GlobalConst.blacklists.PAIR_BLACKLIST.includes(pair.id)) { + return false; + } + if (searchVal && searchVal.includes(' ')) { + const pairA = searchVal.split(' ')[0]?.toUpperCase(); + const pairB = searchVal.split(' ')[1]?.toUpperCase(); + return ( + (pair.token0.symbol.includes(pairA) || + pair.token0.symbol.includes(pairB)) && + (pair.token1.symbol.includes(pairA) || + pair.token1.symbol.includes(pairB)) + ); + } + if (searchVal && searchVal.includes('-')) { + const pairA = searchVal.split('-')[0]?.toUpperCase(); + const pairB = searchVal.split('-')[1]?.toUpperCase(); + return ( + (pair.token0.symbol.includes(pairA) || + pair.token0.symbol.includes(pairB)) && + (pair.token1.symbol.includes(pairA) || + pair.token1.symbol.includes(pairB)) + ); + } + const regexMatches = Object.keys(pair).map((field) => { + const isAddress = searchVal.slice(0, 2) === '0x'; + if (field === 'id' && isAddress) { + return pair[field].match( + new RegExp(escapeRegExp(searchVal), 'i'), + ); + } + if (field === 'token0' || field === 'token1') { + return ( + pair[field].symbol.match( + new RegExp(escapeRegExp(searchVal), 'i'), + ) || + pair[field].name.match( + new RegExp(escapeRegExp(searchVal), 'i'), + ) + ); + } + return false; + }); + return regexMatches.some((m) => m); + }) + : []; + return filtered; + }, [searchedPairs, searchVal]); + + useEffect(() => { + async function fetchData() { + try { + const allTokensUniswap = await getAllTokensOnUniswap(); + const allPairsUniswap = await getAllPairsOnUniswap(); + let allTokens = allTokensUniswap ?? []; + let allPairs = allPairsUniswap ?? []; + if (searchVal.length > 0) { + const tokens = await client.query({ + query: TOKEN_SEARCH, + variables: { + value: searchVal ? searchVal.toUpperCase() : '', + id: searchVal, + }, + }); + + const pairs = await client.query({ + query: PAIR_SEARCH, + variables: { + tokens: tokens.data.asSymbol?.map((t: any) => t.id), + id: searchVal, + }, + }); + + const foundPairs = pairs.data.as0 + .concat(pairs.data.as1) + .concat(pairs.data.asAddress); + + allPairs = allPairs.concat( + foundPairs.filter((searchedPair: any) => { + let included = false; + allPairs.map((pair) => { + if (pair.id === searchedPair.id) { + included = true; + } + return true; + }); + return !included; + }), + ); + + const foundTokens = tokens.data.asSymbol + .concat(tokens.data.asAddress) + .concat(tokens.data.asName); + + allTokens = allTokens.concat( + foundTokens.filter((searchedToken: any) => { + let included = false; + allTokens.map((token) => { + if (token.id === searchedToken.id) { + included = true; + } + return true; + }); + return !included; + }), + ); + } + + const foundTokensWithData = await Promise.all( + allTokens.map(async (token: any) => { + const utcCurrentTime = dayjs(); + const utcOneDayBack = utcCurrentTime.subtract(1, 'day').unix(); + const oneDayBlock = await getBlockFromTimestamp(utcOneDayBack); + const oneDayResult = await client.query({ + query: TOKEN_INFO_OLD(oneDayBlock, token.id), + fetchPolicy: 'network-only', + }); + if ( + oneDayResult && + oneDayResult.data && + oneDayResult.data.tokens && + oneDayResult.data.tokens.length > 0 + ) { + const oneDayHistory = oneDayResult.data.tokens[0]; + const oneDayVolumeUSD = + (token?.tradeVolumeUSD ?? 0) - + (oneDayHistory?.tradeVolumeUSD ?? 0); + return { ...token, oneDayVolumeUSD }; + } + return token; + }), + ); + setSearchedTokens(foundTokensWithData); + setSearchedPairs(allPairs); + } catch (e) { + console.log(e); + } + } + fetchData(); + }, [searchVal]); + + const handleClick = (e: any) => { + if ( + !(menuRef.current && menuRef.current.contains(e.target)) && + !(wrapperRef.current && wrapperRef.current.contains(e.target)) + ) { + setPairsShown(3); + setTokensShown(3); + setMenuOpen(false); + } + }; + + useEffect(() => { + document.addEventListener('click', handleClick); + return () => { + document.removeEventListener('click', handleClick); + }; + }, []); + + return ( + + + setMenuOpen(true)} + onChange={(evt) => setSearchValInput(evt.target.value)} + /> + + + + + {menuOpen && ( +
+
{t('pairs')}
+ {filteredPairs.slice(0, pairsShown).map((val, ind) => { + const currency0 = new Token( + MATIC_CHAIN, + getAddress(val.token0.id), + val.token0.decimals, + ); + const currency1 = new Token( + MATIC_CHAIN, + getAddress(val.token1.id), + val.token1.decimals, + ); + return ( + { + history.push(`/analytics/pair/${val.id}`); + setMenuOpen(false); + }} + > + + + {val.token0.symbol} - {val.token1.symbol} {t('pair')} + + + ); + })} + setPairsShown(pairsShown + 5)} + > + {t('showMore')} + +
{t('tokens')}
+ {filteredTokens.slice(0, tokensShown).map((val, ind) => { + const currency = new Token( + MATIC_CHAIN, + getAddress(val.id), + val.decimals, + ); + return ( + { + history.push(`/analytics/token/${val.id}`); + setMenuOpen(false); + }} + > + + + {val.name} {val.symbol} + + + ); + })} + setTokensShown(tokensShown + 5)} + > + {t('showMore')} + +
+ )} +
+ ); +}; + +export default React.memo(AnalyticsSearch); diff --git a/src/components/AreaChart/AreaChart.tsx b/src/components/AreaChart/AreaChart.tsx index 8eb006823..5a4cf42a4 100644 --- a/src/components/AreaChart/AreaChart.tsx +++ b/src/components/AreaChart/AreaChart.tsx @@ -1,9 +1,8 @@ import React from 'react'; import { Box } from '@material-ui/core'; import Chart from 'react-apexcharts'; -import dayjs from 'dayjs'; import { useIsDarkMode } from 'state/user/hooks'; -import { formatCompact, formatNumber } from 'utils'; +import { formatCompact, formatDateFromTimeStamp, formatNumber } from 'utils'; import 'components/styles/AreaChart.scss'; export interface AreaChartProps { @@ -117,9 +116,10 @@ const AreaChart: React.FC = ({ theme: dark ? 'dark' : 'light', fillSeriesColor: false, custom: ({ series, seriesIndex, dataPointIndex }: any) => { - return `
${dayjs( - dates[dataPointIndex] * 1000, - ).format('MMM DD, YYYY')}$${formatCompact( + return `
${formatDateFromTimeStamp( + dates[dataPointIndex], + 'MMM DD, YYYY', + )}$${formatCompact( series[seriesIndex][dataPointIndex], )}
`; }, diff --git a/src/components/BetaWarningBanner/BetaWarningBanner.tsx b/src/components/BetaWarningBanner/BetaWarningBanner.tsx index 8fbf9e315..254f9aa7d 100644 --- a/src/components/BetaWarningBanner/BetaWarningBanner.tsx +++ b/src/components/BetaWarningBanner/BetaWarningBanner.tsx @@ -12,7 +12,16 @@ const BetaWarningBanner: React.FC = () => { {showBanner && ( - {t('betaWarningDesc')} + + {t('betaWarningDesc')} + + {process.env.REACT_APP_LEGACY_APP_URL} + + setShowBanner(false)} className='closeBanner'> diff --git a/src/components/CustomTable/CustomTable.tsx b/src/components/CustomTable/CustomTable.tsx index 5a98590cf..cda854cc1 100644 --- a/src/components/CustomTable/CustomTable.tsx +++ b/src/components/CustomTable/CustomTable.tsx @@ -40,9 +40,9 @@ const CustomTable: React.FC> = ({ {mobileWindowSize ? ( <> - {data.map((item: any, index: number) => { - return mobileHTML(item, index); - })} + {data.map((item: any, index: number) => ( + {mobileHTML(item, index)} + ))} ) : ( [ @@ -56,7 +58,10 @@ const headCells = () => [ const liquidityHeadCellIndex = 1; -const PairTable: React.FC = ({ data }) => { +const PairTable: React.FC = ({ + data, + showPagination = true, +}) => { const { t } = useTranslation(); const pairHeadCells = headCells(); const { @@ -86,9 +91,9 @@ const PairTable: React.FC = ({ data }) => { const oneWeekVolume = pair.oneWeekVolumeUSD ? pair.oneWeekVolumeUSD : pair.oneWeekVolumeUntracked; - const oneDayFee = ( - Number(oneDayVolume) * GlobalConst.utils.FEEPERCENT - ).toLocaleString(); + const oneDayFee = formatNumber( + Number(oneDayVolume) * GlobalConst.utils.FEEPERCENT, + ); return ( @@ -128,15 +133,15 @@ const PairTable: React.FC = ({ data }) => {

{t('liquidity')}

-

${Number(liquidity).toLocaleString()}

+

${formatNumber(liquidity)}

{t('24hVol')}

-

${Number(oneDayVolume).toLocaleString()}

+

${formatNumber(oneDayVolume)}

{t('7dVol')}

-

${Number(oneWeekVolume).toLocaleString()}

+

${formatNumber(oneWeekVolume)}

{t('24hFees')}

@@ -174,9 +179,9 @@ const PairTable: React.FC = ({ data }) => { : pair.oneWeekVolumeUntracked && !isNaN(pair.oneWeekVolumeUntracked) ? pair.oneWeekVolumeUntracked : 0; - const oneDayFee = ( - Number(oneDayVolume) * GlobalConst.utils.FEEPERCENT - ).toLocaleString(); + const oneDayFee = formatNumber( + Number(oneDayVolume) * GlobalConst.utils.FEEPERCENT, + ); return [ { html: ( @@ -217,13 +222,13 @@ const PairTable: React.FC = ({ data }) => { ), }, { - html:

${Number(liquidity).toLocaleString()}

, + html:

${formatNumber(liquidity)}

, }, { - html:

${Number(oneDayVolume).toLocaleString()}

, + html:

${formatNumber(oneDayVolume)}

, }, { - html:

${Number(oneWeekVolume).toLocaleString()}

, + html:

${formatNumber(oneWeekVolume)}

, }, { html:

${oneDayFee}

, @@ -235,7 +240,7 @@ const PairTable: React.FC = ({ data }) => { GlobalConst.utils.ROWSPERPAGE} + showPagination={showPagination} headCells={pairHeadCells} rowsPerPage={GlobalConst.utils.ROWSPERPAGE} data={data} diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx deleted file mode 100644 index 4f0f59061..000000000 --- a/src/components/Search/index.tsx +++ /dev/null @@ -1,301 +0,0 @@ -import React, { useEffect, useState, useRef, useMemo } from 'react'; -import { useHistory } from 'react-router-dom'; -import { Box } from '@material-ui/core'; -import { ReactComponent as SearchIcon } from 'assets/images/SearchIcon.svg'; -import { client } from 'apollo/client'; -import { TOKEN_SEARCH, PAIR_SEARCH } from 'apollo/queries'; -import { getAllTokensOnUniswap, getAllPairsOnUniswap } from 'utils'; -import { GlobalConst } from 'constants/index'; -import { CurrencyLogo, DoubleCurrencyLogo } from 'components'; -import { ChainId, Token } from '@uniswap/sdk'; -import { getAddress } from '@ethersproject/address'; -import 'components/styles/SearchWidget.scss'; -import { useTranslation } from 'react-i18next'; - -const Search: React.FC = () => { - const { t } = useTranslation(); - const history = useHistory(); - const [searchVal, setSearchVal] = useState(''); - const [menuOpen, setMenuOpen] = useState(false); - const menuRef = useRef(null); - const wrapperRef = useRef(null); - const [searchedTokens, setSearchedTokens] = useState([]); - const [searchedPairs, setSearchedPairs] = useState([]); - const [tokensShown, setTokensShown] = useState(3); - const [pairsShown, setPairsShown] = useState(3); - const [allTokens, setAllTokens] = useState([]); - const [allPairs, setAllPairs] = useState([]); - - const escapeRegExp = (str: string) => { - return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); - }; - - const filteredTokens = useMemo(() => { - const tokens = allTokens.concat( - searchedTokens.filter((searchedToken) => { - let included = false; - allTokens.map((token) => { - if (token.id === searchedToken.id) { - included = true; - } - return true; - }); - return !included; - }), - ); - const filtered = tokens - ? tokens.filter((token) => { - if (GlobalConst.blacklists.TOKEN_BLACKLIST.includes(token.id)) { - return false; - } - const regexMatches = Object.keys(token).map((tokenEntryKey) => { - const isAddress = searchVal.slice(0, 2) === '0x'; - if (tokenEntryKey === 'id' && isAddress) { - return token[tokenEntryKey].match( - new RegExp(escapeRegExp(searchVal), 'i'), - ); - } - if (tokenEntryKey === 'symbol' && !isAddress) { - return token[tokenEntryKey].match( - new RegExp(escapeRegExp(searchVal), 'i'), - ); - } - if (tokenEntryKey === 'name' && !isAddress) { - return token[tokenEntryKey].match( - new RegExp(escapeRegExp(searchVal), 'i'), - ); - } - return false; - }); - return regexMatches.some((m) => m); - }) - : []; - return filtered; - }, [allTokens, searchedTokens, searchVal]); - - const filteredPairs = useMemo(() => { - const pairs = allPairs.concat( - searchedPairs.filter((searchedPair) => { - let included = false; - allPairs.map((pair) => { - if (pair.id === searchedPair.id) { - included = true; - } - return true; - }); - return !included; - }), - ); - const filtered = pairs - ? pairs.filter((pair) => { - if (GlobalConst.blacklists.PAIR_BLACKLIST.includes(pair.id)) { - return false; - } - if (searchVal && searchVal.includes(' ')) { - const pairA = searchVal.split(' ')[0]?.toUpperCase(); - const pairB = searchVal.split(' ')[1]?.toUpperCase(); - return ( - (pair.token0.symbol.includes(pairA) || - pair.token0.symbol.includes(pairB)) && - (pair.token1.symbol.includes(pairA) || - pair.token1.symbol.includes(pairB)) - ); - } - if (searchVal && searchVal.includes('-')) { - const pairA = searchVal.split('-')[0]?.toUpperCase(); - const pairB = searchVal.split('-')[1]?.toUpperCase(); - return ( - (pair.token0.symbol.includes(pairA) || - pair.token0.symbol.includes(pairB)) && - (pair.token1.symbol.includes(pairA) || - pair.token1.symbol.includes(pairB)) - ); - } - const regexMatches = Object.keys(pair).map((field) => { - const isAddress = searchVal.slice(0, 2) === '0x'; - if (field === 'id' && isAddress) { - return pair[field].match( - new RegExp(escapeRegExp(searchVal), 'i'), - ); - } - if (field === 'token0') { - return ( - pair[field].symbol.match( - new RegExp(escapeRegExp(searchVal), 'i'), - ) || - pair[field].name.match(new RegExp(escapeRegExp(searchVal), 'i')) - ); - } - if (field === 'token1') { - return ( - pair[field].symbol.match( - new RegExp(escapeRegExp(searchVal), 'i'), - ) || - pair[field].name.match(new RegExp(escapeRegExp(searchVal), 'i')) - ); - } - return false; - }); - return regexMatches.some((m) => m); - }) - : []; - return filtered; - }, [allPairs, searchedPairs, searchVal]); - - useEffect(() => { - async function fetchAllData() { - const tokens = await getAllTokensOnUniswap(); - const pairs = await getAllPairsOnUniswap(); - if (tokens) { - setAllTokens(tokens); - } - if (pairs) { - setAllPairs(pairs); - } - } - fetchAllData(); - }, []); - - useEffect(() => { - async function fetchData() { - try { - if (searchVal.length > 0) { - const tokens = await client.query({ - query: TOKEN_SEARCH, - variables: { - value: searchVal ? searchVal.toUpperCase() : '', - id: searchVal, - }, - }); - - const pairs = await client.query({ - query: PAIR_SEARCH, - variables: { - tokens: tokens.data.asSymbol?.map((t: any) => t.id), - id: searchVal, - }, - }); - - setSearchedPairs( - pairs.data.as0.concat(pairs.data.as1).concat(pairs.data.asAddress), - ); - const foundTokens = tokens.data.asSymbol - .concat(tokens.data.asAddress) - .concat(tokens.data.asName); - setSearchedTokens(foundTokens); - } - } catch (e) { - console.log(e); - } - } - fetchData(); - }, [searchVal]); - - const handleClick = (e: any) => { - if ( - !(menuRef.current && menuRef.current.contains(e.target)) && - !(wrapperRef.current && wrapperRef.current.contains(e.target)) - ) { - setPairsShown(3); - setTokensShown(3); - setMenuOpen(false); - } - }; - - useEffect(() => { - document.addEventListener('click', handleClick); - return () => { - document.removeEventListener('click', handleClick); - }; - }); - - return ( - - - setMenuOpen(true)} - onChange={(evt) => setSearchVal(evt.target.value)} - /> - - - - - {menuOpen && ( -
-

{t('pairs')}

- {filteredPairs.slice(0, pairsShown).map((val, ind) => { - const currency0 = new Token( - ChainId.MATIC, - getAddress(val.token0.id), - val.token0.decimals, - ); - const currency1 = new Token( - ChainId.MATIC, - getAddress(val.token1.id), - val.token1.decimals, - ); - return ( - history.push(`/analytics/pair/${val.id}`)} - > - - - {val.token0.symbol} - {val.token1.symbol} {t('pair')} - - - ); - })} - setPairsShown(pairsShown + 5)} - margin='8px 0' - > - {t('showMore')} - -

{t('tokens')}

- {filteredTokens.slice(0, tokensShown).map((val, ind) => { - const currency = new Token( - ChainId.MATIC, - getAddress(val.id), - val.decimals, - ); - return ( - history.push(`/analytics/token/${val.id}`)} - > - - - - {val.name} {val.symbol} - - - - ); - })} - setTokensShown(tokensShown + 5)} - > - {t('showMore')} - -
- )} -
- ); -}; - -export default React.memo(Search); diff --git a/src/components/Swap/Swap.tsx b/src/components/Swap/Swap.tsx index 943fe077c..bdae3934e 100755 --- a/src/components/Swap/Swap.tsx +++ b/src/components/Swap/Swap.tsx @@ -35,7 +35,6 @@ import { addMaticToMetamask, isSupportedNetwork, confirmPriceImpactWithoutFee, - halfAmountSpend, maxAmountSpend, } from 'utils'; import { computeTradePriceBreakdown, warningSeverity } from 'utils/prices'; @@ -294,17 +293,17 @@ const Swap: React.FC<{ currencyBalances[Field.INPUT], ); - const halfAmountInput: CurrencyAmount | undefined = halfAmountSpend( - currencyBalances[Field.INPUT], - ); - const handleMaxInput = useCallback(() => { maxAmountInput && onUserInput(Field.INPUT, maxAmountInput.toExact()); }, [maxAmountInput, onUserInput]); const handleHalfInput = useCallback(() => { - halfAmountInput && onUserInput(Field.INPUT, halfAmountInput.toExact()); - }, [halfAmountInput, onUserInput]); + maxAmountInput && + onUserInput( + Field.INPUT, + (Number(maxAmountInput.toExact()) / 2).toString(), + ); + }, [maxAmountInput, onUserInput]); const atMaxAmountInput = Boolean( maxAmountInput && parsedAmounts[Field.INPUT]?.equalTo(maxAmountInput), diff --git a/src/components/TokensTable/TokensTable.tsx b/src/components/TokensTable/TokensTable.tsx index 4c496131a..37507625b 100644 --- a/src/components/TokensTable/TokensTable.tsx +++ b/src/components/TokensTable/TokensTable.tsx @@ -14,11 +14,15 @@ import { useTranslation } from 'react-i18next'; interface TokensTableProps { data: any[]; + showPagination?: boolean; } const liquidityHeadCellIndex = 4; -const TokensTable: React.FC = ({ data }) => { +const TokensTable: React.FC = ({ + data, + showPagination = true, +}) => { const { t } = useTranslation(); const tokenHeadCells = [ { @@ -116,11 +120,11 @@ const TokensTable: React.FC = ({ data }) => {

{t('24hVol')}

-

${Number(token.oneDayVolumeUSD).toLocaleString()}

+

${formatNumber(token.oneDayVolumeUSD)}

{t('liquidity')}

-

${Number(token.totalLiquidityUSD).toLocaleString()}

+

${formatNumber(token.totalLiquidityUSD)}

); @@ -178,7 +182,7 @@ const TokensTable: React.FC = ({ data }) => { { html: ( -

${Number(token.priceUSD).toLocaleString()}

+

${formatNumber(token.priceUSD)}

), }, @@ -190,10 +194,10 @@ const TokensTable: React.FC = ({ data }) => { ), }, { - html:

${Number(token.oneDayVolumeUSD).toLocaleString()}

, + html:

${formatNumber(token.oneDayVolumeUSD)}

, }, { - html:

${Number(token.totalLiquidityUSD).toLocaleString()}

, + html:

${formatNumber(token.totalLiquidityUSD)}

, }, ]; }; @@ -202,7 +206,7 @@ const TokensTable: React.FC = ({ data }) => { GlobalConst.utils.ROWSPERPAGE} + showPagination={showPagination} headCells={tokenHeadCells} rowsPerPage={GlobalConst.utils.ROWSPERPAGE} data={data} diff --git a/src/components/TopMovers/TopMovers.tsx b/src/components/TopMovers/TopMovers.tsx index 8a4daac68..fbb426a3a 100755 --- a/src/components/TopMovers/TopMovers.tsx +++ b/src/components/TopMovers/TopMovers.tsx @@ -34,7 +34,7 @@ const TopMovers: React.FC = ({ hideArrow = false }) => { return ( -

{t('24hTopMovers')}

+

{t('24hMostVolume')}

{topMoverTokens ? ( diff --git a/src/components/styles/BetaWarningBanner.scss b/src/components/styles/BetaWarningBanner.scss index 0babc9c2c..3d72dceeb 100644 --- a/src/components/styles/BetaWarningBanner.scss +++ b/src/components/styles/BetaWarningBanner.scss @@ -12,7 +12,6 @@ padding: 8px 32px 8px 16px; & span { margin-left: 8px; - text-transform: uppercase; width: calc(100% - 32px); text-align: left; } diff --git a/src/components/styles/SearchWidget.scss b/src/components/styles/SearchWidget.scss index 5374d59e0..5ec758ad3 100644 --- a/src/components/styles/SearchWidget.scss +++ b/src/components/styles/SearchWidget.scss @@ -1,4 +1,13 @@ @use 'styles/variables' as *; +@use 'styles/breakpoints' as *; + +.searchWidgetWrapper { + width: 320px; + position: relative; + @include media("screen", " h6 { + margin: 12px; + } +} + +.searchWidgetRow { + display: flex; + align-items: center; + padding: 4px 12px; + margin: 4px 0; + cursor: pointer; + & small { + margin-left: 8px; + color: $textPrimary; + } + &:hover { + background-color: $secondary1; + } +} + +.searchWidgetShowMore { + cursor: pointer; + margin: 8px 0 12px 12px; + & small { + color: $primary; + } } \ No newline at end of file diff --git a/src/constants/index.ts b/src/constants/index.ts index 2d5f51a77..9b4fe7645 100755 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -23,6 +23,9 @@ const WETH_ONLY: ChainTokenList = { [ChainId.MATIC]: [WETH[ChainId.MATIC]], }; +// TODO: Remove this constant when supporting multichain +export const MATIC_CHAIN = ChainId.MATIC; + export enum TxnType { SWAP, ADD, @@ -91,6 +94,8 @@ export const GlobalConst = { DEFAULT_DUAL_FARMS_LIST_URL: process.env.REACT_APP_DUAL_STAKING_LIST_DEFAULT_URL + '', DEFAULT_SYRUP_LIST_URL: process.env.REACT_APP_SYRUP_LIST_DEFAULT_URL + '', + ANALYTICS_TOKENS_COUNT: 200, + ANALYTICS_PAIRS_COUNT: 400, }, analyticChart: { ONE_MONTH_CHART: 1, diff --git a/src/pages/AnalyticsPage/AnalyticsHeader.tsx b/src/pages/AnalyticsPage/AnalyticsHeader.tsx index 8dc3232c6..2fc066817 100755 --- a/src/pages/AnalyticsPage/AnalyticsHeader.tsx +++ b/src/pages/AnalyticsPage/AnalyticsHeader.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { useHistory, useLocation } from 'react-router-dom'; import { Box } from '@material-ui/core'; import { ArrowForwardIos } from '@material-ui/icons'; -import Search from 'components/Search'; +import AnalyticsSearch from 'components/AnalyticsSearch'; import { shortenAddress } from 'utils'; import 'pages/styles/analytics.scss'; import { useTranslation } from 'react-i18next'; @@ -86,7 +86,7 @@ const AnalyticsHeader: React.FC = ({ data, type }) => { )} - +
); diff --git a/src/pages/AnalyticsPage/AnalyticsLiquidityChart.tsx b/src/pages/AnalyticsPage/AnalyticsLiquidityChart.tsx index d78b558f7..1914ce059 100644 --- a/src/pages/AnalyticsPage/AnalyticsLiquidityChart.tsx +++ b/src/pages/AnalyticsPage/AnalyticsLiquidityChart.tsx @@ -2,6 +2,7 @@ import React, { useEffect, useState, useMemo } from 'react'; import { Box } from '@material-ui/core'; import Skeleton from '@material-ui/lab/Skeleton'; import dayjs from 'dayjs'; +import utc from 'dayjs/plugin/utc'; import { useGlobalData } from 'state/application/hooks'; import { formatCompact, @@ -14,6 +15,7 @@ import { import { GlobalConst, GlobalData } from 'constants/index'; import { AreaChart, ChartType } from 'components'; import { useTranslation } from 'react-i18next'; +dayjs.extend(utc); const AnalyticsLiquidityChart: React.FC = () => { const { t } = useTranslation(); @@ -104,7 +106,9 @@ const AnalyticsLiquidityChart: React.FC = () => {
)} - {dayjs().format('MMM DD, YYYY')} + + {dayjs.utc().format('MMM DD, YYYY')} + {globalChartData ? ( @@ -113,11 +117,7 @@ const AnalyticsLiquidityChart: React.FC = () => { Number(value.totalLiquidityUSD), )} yAxisValues={yAxisValues} - dates={globalChartData.map((value: any) => - dayjs(value.date * 1000) - .add(1, 'day') - .unix(), - )} + dates={globalChartData.map((value: any) => value.date)} width='100%' height={250} categories={getChartDates(globalChartData, durationIndex)} diff --git a/src/pages/AnalyticsPage/AnalyticsOverview.tsx b/src/pages/AnalyticsPage/AnalyticsOverview.tsx index 168ee3aed..1135495e3 100644 --- a/src/pages/AnalyticsPage/AnalyticsOverview.tsx +++ b/src/pages/AnalyticsPage/AnalyticsOverview.tsx @@ -43,7 +43,7 @@ const AnalyticsOverview: React.FC = () => { const topTokensData = await getTopTokens( newPrice, oneDayPrice, - GlobalConst.utils.ROWSPERPAGE, + GlobalConst.utils.ANALYTICS_TOKENS_COUNT, ); if (topTokensData) { updateTopTokens(topTokensData); @@ -52,7 +52,7 @@ const AnalyticsOverview: React.FC = () => { const fetchTopPairs = async () => { updateTopPairs(null); const [newPrice] = await getEthPrice(); - const pairs = await getTopPairs(GlobalConst.utils.ROWSPERPAGE); + const pairs = await getTopPairs(GlobalConst.utils.ANALYTICS_PAIRS_COUNT); const formattedPairs = pairs ? pairs.map((pair: any) => { return pair.id; @@ -107,7 +107,7 @@ const AnalyticsOverview: React.FC = () => { {topTokens ? ( - + ) : ( )} @@ -128,7 +128,7 @@ const AnalyticsOverview: React.FC = () => { {topPairs ? ( - + ) : ( )} diff --git a/src/pages/AnalyticsPage/AnalyticsPairs.tsx b/src/pages/AnalyticsPage/AnalyticsPairs.tsx index 74d25f9fd..d36a660f2 100644 --- a/src/pages/AnalyticsPage/AnalyticsPairs.tsx +++ b/src/pages/AnalyticsPage/AnalyticsPairs.tsx @@ -4,6 +4,7 @@ import { PairTable } from 'components'; import { getEthPrice, getTopPairs, getBulkPairData } from 'utils'; import { Skeleton } from '@material-ui/lab'; import { useTranslation } from 'react-i18next'; +import { GlobalConst } from 'constants/index'; const AnalyticsPairs: React.FC = () => { const { t } = useTranslation(); @@ -13,7 +14,7 @@ const AnalyticsPairs: React.FC = () => { const fetchTopPairs = async () => { updateTopPairs(null); const [newPrice] = await getEthPrice(); - const pairs = await getTopPairs(500); + const pairs = await getTopPairs(GlobalConst.utils.ANALYTICS_PAIRS_COUNT); const formattedPairs = pairs ? pairs.map((pair: any) => { return pair.id; diff --git a/src/pages/AnalyticsPage/AnalyticsTokens.tsx b/src/pages/AnalyticsPage/AnalyticsTokens.tsx index 7a245989a..0e4b9da89 100644 --- a/src/pages/AnalyticsPage/AnalyticsTokens.tsx +++ b/src/pages/AnalyticsPage/AnalyticsTokens.tsx @@ -5,6 +5,7 @@ import { useBookmarkTokens } from 'state/application/hooks'; import { getEthPrice, getTopTokens } from 'utils'; import { Skeleton } from '@material-ui/lab'; import { useTranslation } from 'react-i18next'; +import { GlobalConst } from 'constants/index'; const AnalyticsTokens: React.FC = () => { const { t } = useTranslation(); @@ -27,13 +28,16 @@ const AnalyticsTokens: React.FC = () => { const fetchTopTokens = async () => { updateTopTokens(null); //set top tokens as null to show loading status when fetching tokens data const [newPrice, oneDayPrice] = await getEthPrice(); - const topTokensData = await getTopTokens(newPrice, oneDayPrice, 200); + const topTokensData = await getTopTokens( + newPrice, + oneDayPrice, + GlobalConst.utils.ANALYTICS_TOKENS_COUNT, + ); if (topTokensData) { updateTopTokens(topTokensData); } }; fetchTopTokens(); - // eslint-disable-next-line react-hooks/exhaustive-deps }, [updateTopTokens]); return ( diff --git a/src/pages/AnalyticsPage/AnalyticsVolumeChart.tsx b/src/pages/AnalyticsPage/AnalyticsVolumeChart.tsx index 0a6653ba7..00143450e 100644 --- a/src/pages/AnalyticsPage/AnalyticsVolumeChart.tsx +++ b/src/pages/AnalyticsPage/AnalyticsVolumeChart.tsx @@ -137,7 +137,7 @@ const AnalyticsVolumeChart: React.FC = () => { globalChartData.week[Math.max(0, selectedVolumeIndex - 1)].date, ), 'MMM DD, YYYY', - selectedVolumeIndex > 0 ? 2 : -5, + selectedVolumeIndex > 0 ? 1 : -6, ); const weekEnd = formatDateFromTimeStamp( Number(globalChartData.week[selectedVolumeIndex].date), diff --git a/src/pages/AnalyticsPairDetails/AnalyticsPairChart.tsx b/src/pages/AnalyticsPairDetails/AnalyticsPairChart.tsx index 0c053840a..d6a9bc1ac 100644 --- a/src/pages/AnalyticsPairDetails/AnalyticsPairChart.tsx +++ b/src/pages/AnalyticsPairDetails/AnalyticsPairChart.tsx @@ -172,11 +172,7 @@ const AnalyticsPairChart: React.FC<{ pairData: any }> = ({ pairData }) => { - dayjs(value.date * 1000) - .add(1, 'day') - .unix(), - )} + dates={pairChartData.map((value: any) => value.date)} width='100%' height={240} categories={getChartDates(pairChartData, durationIndex)} diff --git a/src/pages/AnalyticsPairDetails/AnalyticsPairDetails.tsx b/src/pages/AnalyticsPairDetails/AnalyticsPairDetails.tsx index a5f108d47..3f8eadea9 100644 --- a/src/pages/AnalyticsPairDetails/AnalyticsPairDetails.tsx +++ b/src/pages/AnalyticsPairDetails/AnalyticsPairDetails.tsx @@ -9,6 +9,7 @@ import { getPairTransactions, getEthPrice, getBulkPairData, + formatNumber, } from 'utils'; import { useActiveWeb3React } from 'hooks'; import { @@ -97,13 +98,13 @@ const AnalyticsPairDetails: React.FC = () => { const fees = pairData && (pairData.oneDayVolumeUSD || pairData.oneDayVolumeUSD === 0) ? usingUtVolume - ? ( + ? formatNumber( Number(pairData.oneDayVolumeUntracked) * - GlobalConst.utils.FEEPERCENT - ).toLocaleString() - : ( - Number(pairData.oneDayVolumeUSD) * GlobalConst.utils.FEEPERCENT - ).toLocaleString() + GlobalConst.utils.FEEPERCENT, + ) + : formatNumber( + Number(pairData.oneDayVolumeUSD) * GlobalConst.utils.FEEPERCENT, + ) : '-'; useEffect(() => { @@ -216,9 +217,7 @@ const AnalyticsPairDetails: React.FC = () => { {pairData.token0.symbol} : - - {Number(pairData.reserve0).toLocaleString()} - + {formatNumber(pairData.reserve0)}
{ {pairData.token1.symbol} : - - {Number(pairData.reserve1).toLocaleString()} - + {formatNumber(pairData.reserve1)}
@@ -240,7 +237,7 @@ const AnalyticsPairDetails: React.FC = () => { {t('7dTradingVol')} -
${pairData.oneWeekVolumeUSD.toLocaleString()}
+
${formatNumber(pairData.oneWeekVolumeUSD)}
{t('24hFees')} @@ -253,17 +250,17 @@ const AnalyticsPairDetails: React.FC = () => {
$ - {Number( + {formatNumber( pairData.reserveUSD ? pairData.reserveUSD : pairData.trackedReserveUSD, - ).toLocaleString()} + )}
{t('24hTradingVol1')} -
${pairData.oneDayVolumeUSD.toLocaleString()}
+
${formatNumber(pairData.oneDayVolumeUSD)}
diff --git a/src/pages/AnalyticsTokenDetails/AnalyticsTokenChart.tsx b/src/pages/AnalyticsTokenDetails/AnalyticsTokenChart.tsx index 689320891..6dc049083 100644 --- a/src/pages/AnalyticsTokenDetails/AnalyticsTokenChart.tsx +++ b/src/pages/AnalyticsTokenDetails/AnalyticsTokenChart.tsx @@ -155,11 +155,7 @@ const AnalyticsTokenChart: React.FC<{ token: any }> = ({ token }) => { - dayjs(value.date * 1000) - .add(1, 'day') - .unix(), - )} + dates={tokenChartData.map((value: any) => value.date)} width='100%' height={240} categories={getChartDates(tokenChartData, durationIndex)} diff --git a/src/pages/AnalyticsTokenDetails/AnalyticsTokenDetails.tsx b/src/pages/AnalyticsTokenDetails/AnalyticsTokenDetails.tsx index fc54f779d..fde03f868 100644 --- a/src/pages/AnalyticsTokenDetails/AnalyticsTokenDetails.tsx +++ b/src/pages/AnalyticsTokenDetails/AnalyticsTokenDetails.tsx @@ -9,16 +9,14 @@ import { getFormattedPrice, getPriceClass, formatNumber, -} from 'utils'; -import { useActiveWeb3React } from 'hooks'; -import { CurrencyLogo, PairTable } from 'components'; -import { useBookmarkTokens } from 'state/application/hooks'; -import { getTokenInfo, getEthPrice, getTokenPairs2, getBulkPairData, } from 'utils'; +import { useActiveWeb3React } from 'hooks'; +import { CurrencyLogo, PairTable } from 'components'; +import { useBookmarkTokens } from 'state/application/hooks'; import { ReactComponent as StarChecked } from 'assets/images/StarChecked.svg'; import { ReactComponent as StarUnchecked } from 'assets/images/StarUnchecked.svg'; import { getAddress } from '@ethersproject/address'; @@ -46,18 +44,13 @@ const AnalyticsTokenDetails: React.FC = () => { useEffect(() => { async function fetchTokenInfo() { + setToken(null); + updateTokenPairs(null); const [newPrice, oneDayPrice] = await getEthPrice(); const tokenInfo = await getTokenInfo(newPrice, oneDayPrice, tokenAddress); if (tokenInfo) { setToken(tokenInfo[0]); } - } - fetchTokenInfo(); - }, [tokenAddress]); - - useEffect(() => { - async function fetchTokenPairs() { - const [newPrice] = await getEthPrice(); const tokenPairs = await getTokenPairs2(tokenAddress); const formattedPairs = tokenPairs ? tokenPairs.map((pair: any) => { @@ -69,9 +62,8 @@ const AnalyticsTokenDetails: React.FC = () => { updateTokenPairs(pairData); } } - fetchTokenPairs(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [updateTokenPairs, tokenAddress]); + fetchTokenInfo(); + }, [tokenAddress]); const tokenPercentClass = getPriceClass( token ? Number(token.priceChangeUSD) : 0, @@ -144,11 +136,11 @@ const AnalyticsTokenDetails: React.FC = () => { {t('totalLiquidity')} -
${token.totalLiquidityUSD.toLocaleString()}
+
${formatNumber(token.totalLiquidityUSD)}
{t('7dTradingVol')} -
${token.oneWeekVolumeUSD.toLocaleString()}
+
${formatNumber(token.oneWeekVolumeUSD)}
@@ -156,15 +148,15 @@ const AnalyticsTokenDetails: React.FC = () => { {t('24hTradingVol1')} -
${token.oneDayVolumeUSD.toLocaleString()}
+
${formatNumber(token.oneDayVolumeUSD)}
{t('24hFees')}
$ - {( - token.oneDayVolumeUSD * GlobalConst.utils.FEEPERCENT - ).toLocaleString()} + {formatNumber( + token.oneDayVolumeUSD * GlobalConst.utils.FEEPERCENT, + )}
diff --git a/src/state/stake/hooks.ts b/src/state/stake/hooks.ts index 5cf51cdf5..65ee9b3e0 100755 --- a/src/state/stake/hooks.ts +++ b/src/state/stake/hooks.ts @@ -1207,6 +1207,7 @@ function useLairInfo( oneDayVol: oneDayVol, }; }, [ + lairAddress, quickBalance, dQuickBalance, _dQuickTotalSupply, diff --git a/src/utils/index.ts b/src/utils/index.ts index c77017178..0b091c203 100755 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -13,7 +13,6 @@ import { TOKENS_CURRENT, TOKENS_DYNAMIC, TOKEN_CHART, - TOKEN_DATA, TOKEN_DATA1, TOKEN_DATA2, PAIR_CHART, @@ -30,7 +29,7 @@ import { SWAP_TRANSACTIONS, HOURLY_PAIR_RATES, GLOBAL_ALLDATA, - ETH_ALLPRICE, + ETH_PRICE, PAIR_ID, } from 'apollo/queries'; import { JsonRpcSigner, Web3Provider } from '@ethersproject/providers'; @@ -43,18 +42,13 @@ import { ETHER, Token, TokenAmount, - Price, Pair, } from '@uniswap/sdk'; import { BigNumber, BigNumberish } from '@ethersproject/bignumber'; import { formatUnits } from 'ethers/lib/utils'; import { AddressZero } from '@ethersproject/constants'; import { GlobalConst, GlobalValue, SUPPORTED_WALLETS } from 'constants/index'; -import { - TokenAddressMap, - useSelectedTokenList, - WrappedTokenInfo, -} from 'state/lists/hooks'; +import { TokenAddressMap } from 'state/lists/hooks'; import tokenData from 'constants/tokens.json'; import { DualStakingInfo, @@ -62,13 +56,11 @@ import { StakingInfo, SyrupBasic, SyrupInfo, - SyrupRaw, } from 'types'; import { unwrappedToken } from './wrappedCurrency'; import { useUSDCPriceToken } from './useUSDCPrice'; import { CallState } from 'state/multicall/hooks'; import { DualStakingBasic, StakingBasic } from 'types'; -import { useCallback } from 'react'; import { AbstractConnector } from '@web3-react/abstract-connector'; import { injected } from 'connectors'; @@ -250,11 +242,15 @@ export const getEthPrice: () => Promise = async () => { try { const oneDayBlock = await getBlockFromTimestamp(utcOneDayBack); const result = await client.query({ - query: ETH_ALLPRICE(oneDayBlock), + query: ETH_PRICE(), + fetchPolicy: 'network-only', + }); + const resultOneDay = await client.query({ + query: ETH_PRICE(oneDayBlock), fetchPolicy: 'network-only', }); - const currentPrice = result?.data['currentPrice'][0].ethPrice; - const oneDayBackPrice = result?.data['oneDayBackPrice'][0].ethPrice; + const currentPrice = result?.data?.bundles[0]?.ethPrice; + const oneDayBackPrice = resultOneDay?.data?.bundles[0]?.ethPrice; priceChangeETH = getPercentChange(currentPrice, oneDayBackPrice); ethPrice = currentPrice; @@ -328,33 +324,41 @@ export const getTokenInfo = async ( current?.data?.tokens?.map(async (token: any) => { const data = token; - // let liquidityDataThisToken = liquidityData?.[token.id] let oneDayHistory = oneDayData?.[token.id]; let twoDayHistory = twoDayData?.[token.id]; let oneWeekHistory = oneWeekData?.[token.id]; - // catch the case where token wasnt in top list in previous days - if (!oneDayHistory) { - const oneDayResult = await client.query({ - query: TOKEN_DATA(token.id, oneDayBlock), - fetchPolicy: 'network-only', - }); - oneDayHistory = oneDayResult.data.tokens[0]; - } - if (!twoDayHistory) { - const twoDayResult = await client.query({ - query: TOKEN_DATA(token.id, twoDayBlock), - fetchPolicy: 'network-only', - }); - twoDayHistory = twoDayResult.data.tokens[0]; + // this is because old history data returns exact same data as current data when the old data does not exist + if ( + Number(oneDayHistory?.totalLiquidity ?? 0) === + Number(data?.totalLiquidity ?? 0) && + Number(oneDayHistory?.tradeVolume ?? 0) === + Number(data?.tradeVolume ?? 0) && + Number(oneDayHistory?.derivedETH ?? 0) === + Number(data?.derivedETH ?? 0) + ) { + oneDayHistory = null; } - if (!oneWeekHistory) { - const oneWeekResult = await client.query({ - query: TOKEN_DATA(token.id, oneWeekBlock), - fetchPolicy: 'network-only', - }); - oneWeekHistory = oneWeekResult.data.tokens[0]; + if ( + Number(twoDayHistory?.totalLiquidity ?? 0) === + Number(data?.totalLiquidity ?? 0) && + Number(twoDayHistory?.tradeVolume ?? 0) === + Number(data?.tradeVolume ?? 0) && + Number(twoDayHistory?.derivedETH ?? 0) === + Number(data?.derivedETH ?? 0) + ) { + twoDayHistory = null; + } + if ( + Number(oneWeekHistory?.totalLiquidity ?? 0) === + Number(data?.totalLiquidity ?? 0) && + Number(oneWeekHistory?.tradeVolume ?? 0) === + Number(data?.tradeVolume ?? 0) && + Number(oneWeekHistory?.derivedETH ?? 0) === + Number(data?.derivedETH ?? 0) + ) { + oneWeekHistory = null; } // calculate percentage changes and daily changes @@ -365,14 +369,14 @@ export const getTokenInfo = async ( ); const oneWeekVolumeUSD = - oneDayHistory.tradeVolumeUSD - oneWeekHistory.tradeVolumeUSD; + data.tradeVolumeUSD - (oneWeekHistory?.tradeVolumeUSD ?? 0); const currentLiquidityUSD = data?.totalLiquidity * ethPrice * data?.derivedETH; const oldLiquidityUSD = - oneDayHistory?.totalLiquidity * + (oneDayHistory?.totalLiquidity ?? 0) * ethPriceOld * - oneDayHistory?.derivedETH; + (oneDayHistory?.derivedETH ?? 0); // percent changes const priceChangeUSD = getPercentChange( @@ -412,7 +416,7 @@ export const getTokenInfo = async ( fetchPolicy: 'network-only', }); const result = aaveData.data.pairs[0]; - data.totalLiquidityUSD = parseFloat(result.reserveUSD) / 2; + data.totalLiquidityUSD = Number(result.reserveUSD) / 2; data.liquidityChangeUSD = 0; data.priceChangeUSD = 0; } @@ -433,10 +437,8 @@ export const getTopTokens = async ( const utcCurrentTime = dayjs(); const utcOneDayBack = utcCurrentTime.subtract(1, 'day').unix(); const utcTwoDaysBack = utcCurrentTime.subtract(2, 'day').unix(); - const utcOneWeekBack = utcCurrentTime.subtract(7, 'day').unix(); const oneDayBlock = await getBlockFromTimestamp(utcOneDayBack); const twoDayBlock = await getBlockFromTimestamp(utcTwoDaysBack); - const oneWeekBlock = await getBlockFromTimestamp(utcOneWeekBack); try { const current = await client.query({ @@ -454,11 +456,6 @@ export const getTopTokens = async ( fetchPolicy: 'network-only', }); - const oneWeekResult = await client.query({ - query: TOKENS_DYNAMIC(oneWeekBlock, count), - fetchPolicy: 'network-only', - }); - const oneDayData = oneDayResult?.data?.tokens.reduce( (obj: any, cur: any) => { return { ...obj, [cur.id]: cur }; @@ -473,13 +470,6 @@ export const getTopTokens = async ( {}, ); - const oneWeekData = oneWeekResult?.data?.tokens.reduce( - (obj: any, cur: any) => { - return { ...obj, [cur.id]: cur }; - }, - {}, - ); - const bulkResults = await Promise.all( current && oneDayData && @@ -490,30 +480,28 @@ export const getTopTokens = async ( // let liquidityDataThisToken = liquidityData?.[token.id] let oneDayHistory = oneDayData?.[token.id]; let twoDayHistory = twoDayData?.[token.id]; - let oneWeekHistory = oneWeekData?.[token.id]; - // catch the case where token wasnt in top list in previous days - if (!oneDayHistory) { - const oneDayResult = await client.query({ - query: TOKEN_DATA(token.id, oneDayBlock), - fetchPolicy: 'network-only', - }); - oneDayHistory = oneDayResult.data.tokens[0]; - } - if (!twoDayHistory) { - const twoDayResult = await client.query({ - query: TOKEN_DATA(token.id, twoDayBlock), - fetchPolicy: 'network-only', - }); - twoDayHistory = twoDayResult.data.tokens[0]; + // this is because old history data returns exact same data as current data when the old data does not exist + if ( + Number(oneDayHistory?.totalLiquidity ?? 0) === + Number(data?.totalLiquidity ?? 0) && + Number(oneDayHistory?.tradeVolume ?? 0) === + Number(data?.tradeVolume ?? 0) && + Number(oneDayHistory?.derivedETH ?? 0) === + Number(data?.derivedETH ?? 0) + ) { + oneDayHistory = null; } - if (!oneWeekHistory) { - const oneWeekResult = await client.query({ - query: TOKEN_DATA(token.id, oneWeekBlock), - fetchPolicy: 'network-only', - }); - oneWeekHistory = oneWeekResult.data.tokens[0]; + if ( + Number(twoDayHistory?.totalLiquidity ?? 0) === + Number(data?.totalLiquidity ?? 0) && + Number(twoDayHistory?.tradeVolume ?? 0) === + Number(data?.tradeVolume ?? 0) && + Number(twoDayHistory?.derivedETH ?? 0) === + Number(data?.derivedETH ?? 0) + ) { + twoDayHistory = null; } // calculate percentage changes and daily changes @@ -523,15 +511,12 @@ export const getTopTokens = async ( twoDayHistory?.tradeVolumeUSD ?? 0, ); - const oneWeekVolumeUSD = - oneDayHistory.tradeVolumeUSD - oneWeekHistory.tradeVolumeUSD; - const currentLiquidityUSD = data?.totalLiquidity * ethPrice * data?.derivedETH; const oldLiquidityUSD = - oneDayHistory?.totalLiquidity * + (oneDayHistory?.totalLiquidity ?? 0) * ethPriceOld * - oneDayHistory?.derivedETH; + (oneDayHistory?.derivedETH ?? 0); // percent changes const priceChangeUSD = getPercentChange( @@ -545,7 +530,6 @@ export const getTopTokens = async ( data.priceUSD = data?.derivedETH * ethPrice; data.totalLiquidityUSD = currentLiquidityUSD; data.oneDayVolumeUSD = oneDayVolumeUSD; - data.oneWeekVolumeUSD = oneWeekVolumeUSD; data.volumeChangeUSD = volumeChangeUSD; data.priceChangeUSD = priceChangeUSD; data.liquidityChangeUSD = getPercentChange( @@ -571,7 +555,7 @@ export const getTopTokens = async ( fetchPolicy: 'network-only', }); const result = aaveData.data.pairs[0]; - data.totalLiquidityUSD = parseFloat(result.reserveUSD) / 2; + data.totalLiquidityUSD = Number(result.reserveUSD) / 2; data.liquidityChangeUSD = 0; data.priceChangeUSD = 0; } @@ -686,7 +670,7 @@ export const getIntervalTokenData = async ( if (latestBlock) { blocks = blocks.filter((b) => { - return parseFloat(b.number) <= latestBlock; + return Number(b.number) <= latestBlock; }); } @@ -702,7 +686,7 @@ export const getIntervalTokenData = async ( const values: any[] = []; for (const row in result) { const timestamp = row.split('t')[1]; - const derivedETH = parseFloat(result[row]?.derivedETH); + const derivedETH = Number(result[row]?.derivedETH ?? 0); if (timestamp) { values.push({ timestamp, @@ -728,8 +712,8 @@ export const getIntervalTokenData = async ( for (let i = 0; i < values.length - 1; i++) { formattedHistory.push({ timestamp: values[i].timestamp, - open: parseFloat(values[i].priceUSD), - close: parseFloat(values[i + 1].priceUSD), + open: Number(values[i].priceUSD), + close: Number(values[i + 1].priceUSD), }); } @@ -844,7 +828,7 @@ export const getTokenChartData = async ( // add the day index to the set of days dayIndexSet.add((data[i].date / oneDay).toFixed(0)); dayIndexArray.push(data[i]); - dayData.dailyVolumeUSD = parseFloat(dayData.dailyVolumeUSD); + dayData.dailyVolumeUSD = Number(dayData.dailyVolumeUSD); }); // fill in empty days @@ -913,8 +897,8 @@ export const getPairChartData = async ( // add the day index to the set of days dayIndexSet.add((data[i].date / oneDay).toFixed(0)); dayIndexArray.push(data[i]); - dayData.dailyVolumeUSD = parseFloat(dayData.dailyVolumeUSD); - dayData.reserveUSD = parseFloat(dayData.reserveUSD); + dayData.dailyVolumeUSD = Number(dayData.dailyVolumeUSD); + dayData.reserveUSD = Number(dayData.reserveUSD); }); if (data[0]) { @@ -983,7 +967,7 @@ export const getRateData = async ( if (latestBlock) { blocks = blocks.filter((b) => { - return parseFloat(b.number) <= latestBlock; + return Number(b.number) <= latestBlock; }); } @@ -1090,6 +1074,40 @@ export const getBulkPairData: ( }); oneWeekHistory = newData.data.pairs[0]; } + + // this is because old history data returns exact same data as current data when the old data does not exist + if ( + Number(oneDayHistory?.reserveUSD ?? 0) === + Number(data?.reserveUSD ?? 0) && + Number(oneDayHistory?.volumeUSD ?? 0) === + Number(data?.volumeUSD ?? 0) && + Number(oneDayHistory?.totalSupply ?? 0) === + Number(data?.totalSupply ?? 0) + ) { + oneDayHistory = null; + } + + if ( + Number(twoDayHistory?.reserveUSD ?? 0) === + Number(data?.reserveUSD ?? 0) && + Number(twoDayHistory?.volumeUSD ?? 0) === + Number(data?.volumeUSD ?? 0) && + Number(twoDayHistory?.totalSupply ?? 0) === + Number(data?.totalSupply ?? 0) + ) { + twoDayHistory = null; + } + if ( + Number(oneWeekHistory?.reserveUSD ?? 0) === + Number(data?.reserveUSD ?? 0) && + Number(oneWeekHistory?.volumeUSD ?? 0) === + Number(data?.volumeUSD ?? 0) && + Number(oneWeekHistory?.totalSupply ?? 0) === + Number(data?.totalSupply ?? 0) + ) { + oneWeekHistory = null; + } + data = parseData( data, oneDayHistory, @@ -1123,17 +1141,15 @@ const parseData = ( ); const [oneDayVolumeUntracked, volumeChangeUntracked] = get2DayPercentChange( data?.untrackedVolumeUSD, - oneDayData?.untrackedVolumeUSD - ? parseFloat(oneDayData?.untrackedVolumeUSD) - : 0, + oneDayData?.untrackedVolumeUSD ? Number(oneDayData?.untrackedVolumeUSD) : 0, twoDayData?.untrackedVolumeUSD ? twoDayData?.untrackedVolumeUSD : 0, ); - const oneWeekVolumeUSD = parseFloat( + const oneWeekVolumeUSD = Number( oneWeekData ? data?.volumeUSD - oneWeekData?.volumeUSD : data.volumeUSD, ); - const oneWeekVolumeUntracked = parseFloat( + const oneWeekVolumeUntracked = Number( oneWeekData ? data?.untrackedVolumeUSD - oneWeekData?.untrackedVolumeUSD : data.untrackedVolumeUSD, @@ -1156,13 +1172,13 @@ const parseData = ( // format if pair hasnt existed for a day or a week if (!oneDayData && data && data.createdAtBlockNumber > oneDayBlock) { - data.oneDayVolumeUSD = parseFloat(data.volumeUSD); + data.oneDayVolumeUSD = Number(data.volumeUSD); } if (!oneDayData && data) { - data.oneDayVolumeUSD = parseFloat(data.volumeUSD); + data.oneDayVolumeUSD = Number(data.volumeUSD); } if (!oneWeekData && data) { - data.oneWeekVolumeUSD = parseFloat(data.volumeUSD); + data.oneWeekVolumeUSD = Number(data.volumeUSD); } // format incorrect names @@ -1509,15 +1525,6 @@ export function maxAmountSpend( return currencyAmount; } -export function halfAmountSpend( - currencyAmount?: CurrencyAmount, -): CurrencyAmount | undefined { - const maxAmount = maxAmountSpend(currencyAmount); - if (!maxAmount) return undefined; - - return CurrencyAmount.ether(JSBI.divide(maxAmount.raw, JSBI.BigInt(2))); -} - export function isTokenOnList( defaultTokens: TokenAddressMap, currency?: Currency, @@ -1640,10 +1647,12 @@ export function calculateGasMargin(value: BigNumber): BigNumber { export function formatDateFromTimeStamp( timestamp: number, format: string, - addedDay = 1, + addedDay = 0, ) { - return dayjs(timestamp * 1000) //multiply 1000 to get timestamp in milliseconds - .add(addedDay, 'day') //add days to get correct date + return dayjs + .unix(timestamp) + .add(addedDay, 'day') + .utc() .format(format); } @@ -1875,9 +1884,9 @@ export function useLairDQUICKAPY(isNew: boolean, lair?: LairInfo) { ? GlobalValue.tokens.COMMON.NEW_QUICK : GlobalValue.tokens.COMMON.OLD_QUICK; const quickPrice = useUSDCPriceToken(quickToken); - const dQUICKPrice: any = Number(lair?.dQUICKtoQUICK?.toExact()) * quickPrice; - if (!lair) return '0'; + if (!lair) return ''; + const dQUICKPrice: any = Number(lair.dQUICKtoQUICK.toExact()) * quickPrice; const dQUICKAPR = (((Number(lair.oneDayVol) * GlobalConst.utils.DQUICKFEE * @@ -1885,7 +1894,7 @@ export function useLairDQUICKAPY(isNew: boolean, lair?: LairInfo) { Number(lair.dQuickTotalSupply.toExact())) * daysCurrentYear) / dQUICKPrice; - if (!dQUICKAPR) return '0'; + if (!dQUICKAPR) return ''; const temp = Math.pow(1 + dQUICKAPR / daysCurrentYear, daysCurrentYear) - 1; if (temp > 100) { return '> 10000';