(false)\n\n const open = useCallback(() => setShow(true), [setShow])\n const close = useCallback(() => setShow(false), [setShow])\n\n return (\n \n \n \n \n \n \n \n )\n}\n","import React, { useState } from 'react'\nimport styled from 'styled-components'\nimport { Tooltip } from '../QuestionHelper'\n\nconst TextWrapper = styled.div`\n position: relative;\n margin-left: ${({ margin }) => margin && '4px'};\n color: ${({ theme, link }) => (link ? theme.blue : theme.text1)};\n font-size: ${({ fontSize }) => fontSize ?? 'inherit'};\n\n :hover {\n cursor: pointer;\n }\n\n @media screen and (max-width: 600px) {\n font-size: ${({ adjustSize }) => adjustSize && '12px'};\n }\n`\n\nconst FormattedName = ({ text, maxCharacters, margin = false, adjustSize = false, fontSize, link, ...rest }) => {\n const [showHover, setShowHover] = useState(false)\n\n if (!text) {\n return ''\n }\n\n if (text.length > maxCharacters) {\n return (\n \n setShowHover(true)}\n onMouseLeave={() => setShowHover(false)}\n margin={margin}\n adjustSize={adjustSize}\n link={link}\n fontSize={fontSize}\n {...rest}\n >\n {' ' + text.slice(0, maxCharacters - 1) + '...'}\n \n \n )\n }\n\n return (\n \n {text}\n \n )\n}\n\nexport default FormattedName\n","import React, { useState, useEffect } from 'react'\nimport { useMedia } from 'react-use'\nimport dayjs from 'dayjs'\nimport LocalLoader from '../LocalLoader'\nimport utc from 'dayjs/plugin/utc'\nimport { Box, Flex, Text } from 'rebass'\nimport styled from 'styled-components'\n\nimport { CustomLink } from '../Link'\nimport { Divider } from '../../components'\nimport { withRouter } from 'react-router-dom'\nimport { formattedNum, formattedPercent } from '../../utils'\nimport DoubleTokenLogo from '../DoubleLogo'\nimport FormattedName from '../FormattedName'\nimport QuestionHelper from '../QuestionHelper'\nimport { TYPE } from '../../Theme'\n\ndayjs.extend(utc)\n\nconst PageButtons = styled.div`\n width: 100%;\n display: flex;\n justify-content: center;\n margin-top: 2em;\n margin-bottom: 0.5em;\n`\n\nconst Arrow = styled.div`\n color: ${({ theme }) => theme.primary1};\n opacity: ${(props) => (props.faded ? 0.3 : 1)};\n padding: 0 20px;\n user-select: none;\n :hover {\n cursor: pointer;\n }\n`\n\nconst List = styled(Box)`\n -webkit-overflow-scrolling: touch;\n`\n\nconst DashGrid = styled.div`\n display: grid;\n grid-gap: 1em;\n grid-template-columns: 100px 1fr 1fr;\n grid-template-areas: 'name liq vol';\n padding: 0 1.125rem;\n\n > * {\n justify-content: flex-end;\n\n :first-child {\n justify-content: flex-start;\n text-align: left;\n width: 20px;\n }\n }\n\n @media screen and (min-width: 740px) {\n padding: 0 1.125rem;\n grid-template-columns: 1.5fr 1fr 1fr};\n grid-template-areas: ' name liq vol pool ';\n }\n\n @media screen and (min-width: 1080px) {\n padding: 0 1.125rem;\n grid-template-columns: 1.5fr 1fr 1fr 1fr 1fr 1fr;\n grid-template-areas: ' name liq vol volWeek fees apy';\n }\n\n @media screen and (min-width: 1200px) {\n grid-template-columns: 1.5fr 1fr 1fr 1fr 1fr 1fr;\n grid-template-areas: ' name liq vol volWeek fees apy';\n }\n`\n\nconst ListWrapper = styled.div``\n\nconst ClickableText = styled(Text)`\n color: ${({ theme }) => theme.text1};\n &:hover {\n cursor: pointer;\n opacity: 0.6;\n }\n text-align: end;\n user-select: none;\n`\n\nconst DataText = styled(Flex)`\n align-items: center;\n text-align: center;\n color: ${({ theme }) => theme.text1};\n\n & > * {\n font-size: 14px;\n }\n\n @media screen and (max-width: 600px) {\n font-size: 12px;\n }\n`\n\nconst SORT_FIELD = {\n LIQ: 0,\n VOL: 1,\n VOL_7DAYS: 3,\n FEES: 4,\n APY: 5,\n}\n\nconst FIELD_TO_VALUE = {\n [SORT_FIELD.LIQ]: 'trackedReserveUSD', // sort with tracked volume only\n [SORT_FIELD.VOL]: 'oneDayVolumeUSD',\n [SORT_FIELD.VOL_7DAYS]: 'oneWeekVolumeUSD',\n [SORT_FIELD.FEES]: 'oneDayVolumeUSD',\n}\n\nfunction PairList({ pairs, color, disbaleLinks, maxItems = 10 }) {\n const below600 = useMedia('(max-width: 600px)')\n const below740 = useMedia('(max-width: 740px)')\n const below1080 = useMedia('(max-width: 1080px)')\n\n // pagination\n const [page, setPage] = useState(1)\n const [maxPage, setMaxPage] = useState(1)\n const ITEMS_PER_PAGE = maxItems\n\n // sorting\n const [sortDirection, setSortDirection] = useState(true)\n const [sortedColumn, setSortedColumn] = useState(SORT_FIELD.LIQ)\n\n useEffect(() => {\n setMaxPage(1) // edit this to do modular\n setPage(1)\n }, [pairs])\n\n useEffect(() => {\n if (pairs) {\n let extraPages = 1\n if (Object.keys(pairs).length % ITEMS_PER_PAGE === 0) {\n extraPages = 0\n }\n setMaxPage(Math.floor(Object.keys(pairs).length / ITEMS_PER_PAGE) + extraPages)\n }\n }, [ITEMS_PER_PAGE, pairs])\n\n const ListItem = ({ pairAddress, index }) => {\n const pairData = pairs[pairAddress]\n\n if (pairData && pairData.token0 && pairData.token1) {\n const liquidity = formattedNum(pairData.reserveUSD, true)\n const volume = formattedNum(pairData.oneDayVolumeUSD, true)\n const apy = formattedPercent((pairData.oneDayVolumeUSD * 0.002 * 365 * 100) / pairData.reserveUSD)\n\n return (\n \n \n {!below600 && {index}
}\n \n \n \n \n \n {liquidity} \n {volume} \n {!below1080 && {formattedNum(pairData.oneWeekVolumeUSD, true)} }\n {!below1080 && {formattedNum(pairData.oneDayVolumeUSD * 0.002, true)} }\n {!below1080 && {apy} }\n \n )\n } else {\n return ''\n }\n }\n\n const pairList =\n pairs &&\n Object.keys(pairs)\n .sort((addressA, addressB) => {\n const pairA = pairs[addressA]\n const pairB = pairs[addressB]\n if (sortedColumn === SORT_FIELD.APY) {\n const apy0 = parseFloat(pairA.oneDayVolumeUSD * 0.002 * 356 * 100) / parseFloat(pairA.reserveUSD)\n const apy1 = parseFloat(pairB.oneDayVolumeUSD * 0.002 * 356 * 100) / parseFloat(pairB.reserveUSD)\n return apy0 > apy1 ? (sortDirection ? -1 : 1) * 1 : (sortDirection ? -1 : 1) * -1\n }\n return parseFloat(pairA[FIELD_TO_VALUE[sortedColumn]]) > parseFloat(pairB[FIELD_TO_VALUE[sortedColumn]])\n ? (sortDirection ? -1 : 1) * 1\n : (sortDirection ? -1 : 1) * -1\n })\n .slice(ITEMS_PER_PAGE * (page - 1), page * ITEMS_PER_PAGE)\n .map((pairAddress, index) => {\n return (\n pairAddress && (\n \n )\n )\n })\n\n return (\n \n \n \n Name \n \n \n {\n setSortedColumn(SORT_FIELD.LIQ)\n setSortDirection(sortedColumn !== SORT_FIELD.LIQ ? true : !sortDirection)\n }}\n >\n Liquidity {sortedColumn === SORT_FIELD.LIQ ? (!sortDirection ? '↑' : '↓') : ''}\n \n \n \n {\n setSortedColumn(SORT_FIELD.VOL)\n setSortDirection(sortedColumn !== SORT_FIELD.VOL ? true : !sortDirection)\n }}\n >\n Volume (24hrs)\n {sortedColumn === SORT_FIELD.VOL ? (!sortDirection ? '↑' : '↓') : ''}\n \n \n {!below1080 && (\n \n {\n setSortedColumn(SORT_FIELD.VOL_7DAYS)\n setSortDirection(sortedColumn !== SORT_FIELD.VOL_7DAYS ? true : !sortDirection)\n }}\n >\n Volume (7d) {sortedColumn === SORT_FIELD.VOL_7DAYS ? (!sortDirection ? '↑' : '↓') : ''}\n \n \n )}\n {!below1080 && (\n \n {\n setSortedColumn(SORT_FIELD.FEES)\n setSortDirection(sortedColumn !== SORT_FIELD.FEES ? true : !sortDirection)\n }}\n >\n Fees (24hr) {sortedColumn === SORT_FIELD.FEES ? (!sortDirection ? '↑' : '↓') : ''}\n \n \n )}\n {!below1080 && (\n \n {\n setSortedColumn(SORT_FIELD.APY)\n setSortDirection(sortedColumn !== SORT_FIELD.APY ? true : !sortDirection)\n }}\n >\n 1y Fees / Liquidity {sortedColumn === SORT_FIELD.APY ? (!sortDirection ? '↑' : '↓') : ''}\n \n \n \n )}\n \n \n {!pairList ? : pairList}
\n \n {\n setPage(page === 1 ? page : page - 1)\n }}\n >\n
← \n
\n {'Page ' + page + ' of ' + maxPage} \n {\n setPage(page === maxPage ? page : page + 1)\n }}\n >\n
→ \n
\n \n \n )\n}\n\nexport default withRouter(PairList)\n","import React, { useState, useEffect, useMemo } from 'react'\nimport styled from 'styled-components'\nimport dayjs from 'dayjs'\nimport utc from 'dayjs/plugin/utc'\n\nimport { Box, Flex, Text } from 'rebass'\nimport TokenLogo from '../TokenLogo'\nimport { CustomLink } from '../Link'\nimport Row from '../Row'\nimport { Divider } from '..'\n\nimport { formattedNum, formattedPercent } from '../../utils'\nimport { useMedia } from 'react-use'\nimport { withRouter } from 'react-router-dom'\nimport { OVERVIEW_TOKEN_BLACKLIST } from '../../constants'\nimport FormattedName from '../FormattedName'\nimport { TYPE } from '../../Theme'\n\ndayjs.extend(utc)\n\nconst PageButtons = styled.div`\n width: 100%;\n display: flex;\n justify-content: center;\n margin-top: 2em;\n margin-bottom: 2em;\n`\n\nconst Arrow = styled.div`\n color: ${({ theme }) => theme.primary1};\n opacity: ${(props) => (props.faded ? 0.3 : 1)};\n padding: 0 20px;\n user-select: none;\n :hover {\n cursor: pointer;\n }\n`\n\nconst List = styled(Box)`\n -webkit-overflow-scrolling: touch;\n`\n\nconst DashGrid = styled.div`\n display: grid;\n grid-gap: 1em;\n grid-template-columns: 100px 1fr 1fr;\n grid-template-areas: 'name liq vol';\n padding: 0 1.125rem;\n\n > * {\n justify-content: flex-end;\n\n &:first-child {\n justify-content: flex-start;\n text-align: left;\n width: 100px;\n }\n }\n\n @media screen and (min-width: 680px) {\n display: grid;\n grid-gap: 1em;\n grid-template-columns: 180px 1fr 1fr 1fr;\n grid-template-areas: 'name symbol liq vol ';\n\n > * {\n justify-content: flex-end;\n width: 100%;\n\n &:first-child {\n justify-content: flex-start;\n }\n }\n }\n\n @media screen and (min-width: 1080px) {\n display: grid;\n grid-gap: 0.5em;\n grid-template-columns: 1.5fr 0.6fr 1fr 1fr 1fr 1fr;\n grid-template-areas: 'name symbol liq vol price change';\n }\n`\n\nconst ListWrapper = styled.div``\n\nconst ClickableText = styled(Text)`\n text-align: end;\n &:hover {\n cursor: pointer;\n opacity: 0.6;\n }\n user-select: none;\n color: ${({ theme }) => theme.text1};\n\n @media screen and (max-width: 640px) {\n font-size: 0.85rem;\n }\n`\n\nconst DataText = styled(Flex)`\n align-items: center;\n text-align: center;\n color: ${({ theme }) => theme.text1};\n\n & > * {\n font-size: 14px;\n }\n\n @media screen and (max-width: 600px) {\n font-size: 12px;\n }\n`\n\nconst SORT_FIELD = {\n LIQ: 'totalLiquidityUSD',\n VOL: 'oneDayVolumeUSD',\n SYMBOL: 'symbol',\n NAME: 'name',\n PRICE: 'priceUSD',\n CHANGE: 'priceChangeUSD',\n}\n\n// @TODO rework into virtualized list\nfunction TopTokenList({ tokens, itemMax = 10 }) {\n // page state\n const [page, setPage] = useState(1)\n const [maxPage, setMaxPage] = useState(1)\n\n // sorting\n const [sortDirection, setSortDirection] = useState(true)\n const [sortedColumn, setSortedColumn] = useState(SORT_FIELD.LIQ)\n\n const below1080 = useMedia('(max-width: 1080px)')\n const below680 = useMedia('(max-width: 680px)')\n const below600 = useMedia('(max-width: 600px)')\n\n useEffect(() => {\n setMaxPage(1) // edit this to do modular\n setPage(1)\n }, [tokens])\n\n const formattedTokens = useMemo(() => {\n return (\n tokens &&\n Object.keys(tokens)\n .filter((key) => {\n return !OVERVIEW_TOKEN_BLACKLIST.includes(key)\n })\n .map((key) => tokens[key])\n )\n }, [tokens])\n\n useEffect(() => {\n if (tokens && formattedTokens) {\n let extraPages = 1\n if (formattedTokens.length % itemMax === 0) {\n extraPages = 0\n }\n setMaxPage(Math.floor(formattedTokens.length / itemMax) + extraPages)\n }\n }, [tokens, formattedTokens, itemMax])\n\n const filteredList = useMemo(() => {\n return (\n formattedTokens &&\n formattedTokens\n .sort((a, b) => {\n if (sortedColumn === SORT_FIELD.SYMBOL || sortedColumn === SORT_FIELD.NAME) {\n return a[sortedColumn] > b[sortedColumn] ? (sortDirection ? -1 : 1) * 1 : (sortDirection ? -1 : 1) * -1\n }\n return parseFloat(a[sortedColumn]) > parseFloat(b[sortedColumn])\n ? (sortDirection ? -1 : 1) * 1\n : (sortDirection ? -1 : 1) * -1\n })\n .slice(itemMax * (page - 1), page * itemMax)\n )\n }, [formattedTokens, itemMax, page, sortDirection, sortedColumn])\n\n const ListItem = ({ item, index }) => {\n return (\n \n \n \n {!below680 && {index}
}\n \n \n \n \n
\n \n {!below680 && (\n \n \n \n )}\n {formattedNum(item.totalLiquidityUSD, true, false)} \n {formattedNum(item.oneDayVolumeUSD, true, false)} \n {!below1080 && (\n \n {formattedNum(item.priceUSD, true)}\n \n )}\n {!below1080 && {formattedPercent(item.priceChangeUSD)} }\n \n )\n }\n\n return (\n \n \n \n {\n setSortedColumn(SORT_FIELD.NAME)\n setSortDirection(sortedColumn !== SORT_FIELD.NAME ? true : !sortDirection)\n }}\n >\n {below680 ? 'Symbol' : 'Name'} {sortedColumn === SORT_FIELD.NAME ? (!sortDirection ? '↑' : '↓') : ''}\n \n \n {!below680 && (\n \n {\n setSortedColumn(SORT_FIELD.SYMBOL)\n setSortDirection(sortedColumn !== SORT_FIELD.SYMBOL ? true : !sortDirection)\n }}\n >\n Symbol {sortedColumn === SORT_FIELD.SYMBOL ? (!sortDirection ? '↑' : '↓') : ''}\n \n \n )}\n\n \n {\n setSortedColumn(SORT_FIELD.LIQ)\n setSortDirection(sortedColumn !== SORT_FIELD.LIQ ? true : !sortDirection)\n }}\n >\n Liquidity {sortedColumn === SORT_FIELD.LIQ ? (!sortDirection ? '↑' : '↓') : ''}\n \n \n \n {\n setSortedColumn(SORT_FIELD.VOL)\n setSortDirection(sortedColumn !== SORT_FIELD.VOL ? true : !sortDirection)\n }}\n >\n Volume (24hrs)\n {sortedColumn === SORT_FIELD.VOL ? (!sortDirection ? '↑' : '↓') : ''}\n \n \n {!below1080 && (\n \n {\n setSortedColumn(SORT_FIELD.PRICE)\n setSortDirection(sortedColumn !== SORT_FIELD.PRICE ? true : !sortDirection)\n }}\n >\n Price {sortedColumn === SORT_FIELD.PRICE ? (!sortDirection ? '↑' : '↓') : ''}\n \n \n )}\n {!below1080 && (\n \n {\n setSortedColumn(SORT_FIELD.CHANGE)\n setSortDirection(sortedColumn !== SORT_FIELD.CHANGE ? true : !sortDirection)\n }}\n >\n Price Change (24hrs)\n {sortedColumn === SORT_FIELD.CHANGE ? (!sortDirection ? '↑' : '↓') : ''}\n \n \n )}\n \n \n \n {filteredList &&\n filteredList.map((item, index) => {\n return (\n \n )\n })}\n
\n \n setPage(page === 1 ? page : page - 1)}>\n
← \n
\n {'Page ' + page + ' of ' + maxPage} \n setPage(page === maxPage ? page : page + 1)}>\n
→ \n
\n \n \n )\n}\n\nexport default withRouter(TopTokenList)\n","import React, { useState } from 'react'\nimport styled from 'styled-components'\n\nimport Row, { RowBetween } from '../Row'\nimport { AutoColumn } from '../Column'\nimport { ChevronDown as Arrow } from 'react-feather'\nimport { TYPE } from '../../Theme'\nimport { StyledIcon } from '..'\n\nconst Wrapper = styled.div`\n z-index: 20;\n position: relative;\n background-color: ${({ theme }) => theme.panelColor};\n border: 1px solid ${({ open, color }) => (open ? color : 'rgba(0, 0, 0, 0.15);')} \n width: 100px;\n padding: 4px 10px;\n padding-right: 6px;\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n\n :hover {\n cursor: pointer;\n }\n`\n\nconst Dropdown = styled.div`\n position: absolute;\n top: 34px;\n padding-top: 40px;\n width: calc(100% - 40px);\n background-color: ${({ theme }) => theme.bg1};\n border: 1px solid rgba(0, 0, 0, 0.15);\n padding: 10px 10px;\n border-radius: 8px;\n width: calc(100% - 20px);\n font-weight: 500;\n font-size: 1rem;\n color: black;\n :hover {\n cursor: pointer;\n }\n`\n\nconst ArrowStyled = styled(Arrow)`\n height: 20px;\n width: 20px;\n margin-left: 6px;\n`\n\nconst DropdownSelect = ({ options, active, setActive, color }) => {\n const [showDropdown, toggleDropdown] = useState(false)\n\n return (\n \n toggleDropdown(!showDropdown)} justify=\"center\">\n {active} \n \n \n \n \n {showDropdown && (\n \n \n {Object.keys(options).map((key, index) => {\n let option = options[key]\n return (\n option !== active && (\n {\n toggleDropdown(!showDropdown)\n setActive(option)\n }}\n key={index}\n >\n {option} \n
\n )\n )\n })}\n \n \n )}\n \n )\n}\n\nexport default DropdownSelect\n","import React, { useState, useEffect } from 'react'\nimport styled from 'styled-components'\nimport dayjs from 'dayjs'\nimport utc from 'dayjs/plugin/utc'\n\nimport { formatTime, formattedNum, urls } from '../../utils'\nimport { useMedia } from 'react-use'\nimport { useCurrentCurrency } from '../../contexts/Application'\nimport { RowFixed, RowBetween } from '../Row'\n\nimport LocalLoader from '../LocalLoader'\nimport { Box, Flex, Text } from 'rebass'\nimport Link from '../Link'\nimport { Divider, EmptyCard } from '..'\nimport DropdownSelect from '../DropdownSelect'\nimport FormattedName from '../FormattedName'\nimport { TYPE } from '../../Theme'\nimport { updateNameData } from '../../utils/data'\n\ndayjs.extend(utc)\n\nconst PageButtons = styled.div`\n width: 100%;\n display: flex;\n justify-content: center;\n margin-top: 2em;\n margin-bottom: 0.5em;\n`\n\nconst Arrow = styled.div`\n color: #2f80ed;\n opacity: ${(props) => (props.faded ? 0.3 : 1)};\n padding: 0 20px;\n user-select: none;\n :hover {\n cursor: pointer;\n }\n`\n\nconst List = styled(Box)`\n -webkit-overflow-scrolling: touch;\n`\n\nconst DashGrid = styled.div`\n display: grid;\n grid-gap: 1em;\n grid-template-columns: 100px 1fr 1fr;\n grid-template-areas: 'txn value time';\n\n > * {\n justify-content: flex-end;\n width: 100%;\n\n &:first-child {\n justify-content: flex-start;\n text-align: left;\n width: 100px;\n }\n }\n\n @media screen and (min-width: 500px) {\n > * {\n &:first-child {\n width: 180px;\n }\n }\n }\n\n @media screen and (min-width: 780px) {\n max-width: 1320px;\n grid-template-columns: 1.2fr 1fr 1fr 1fr 1fr;\n grid-template-areas: 'txn value amountToken amountOther time';\n\n > * {\n &:first-child {\n width: 180px;\n }\n }\n }\n\n @media screen and (min-width: 1080px) {\n max-width: 1320px;\n grid-template-columns: 1.2fr 1fr 1fr 1fr 1fr 1fr;\n grid-template-areas: 'txn value amountToken amountOther account time';\n }\n`\n\nconst ClickableText = styled(Text)`\n color: ${({ theme }) => theme.text1};\n user-select: none;\n text-align: end;\n\n &:hover {\n cursor: pointer;\n opacity: 0.6;\n }\n\n @media screen and (max-width: 640px) {\n font-size: 14px;\n }\n`\n\nconst DataText = styled(Flex)`\n align-items: center;\n text-align: right;\n color: ${({ theme }) => theme.text1};\n\n & > * {\n font-size: 1em;\n }\n\n @media screen and (max-width: 40em) {\n font-size: 0.85rem;\n }\n`\n\nconst SortText = styled.button`\n cursor: pointer;\n font-weight: ${({ active, theme }) => (active ? 500 : 400)};\n margin-right: 0.75rem !important;\n border: none;\n background-color: transparent;\n font-size: 1rem;\n padding: 0px;\n color: ${({ active, theme }) => (active ? theme.text1 : theme.text3)};\n outline: none;\n\n @media screen and (max-width: 600px) {\n font-size: 14px;\n }\n`\n\nconst SORT_FIELD = {\n VALUE: 'amountUSD',\n AMOUNT0: 'token0Amount',\n AMOUNT1: 'token1Amount',\n TIMESTAMP: 'timestamp',\n}\n\nconst TXN_TYPE = {\n ALL: 'All',\n SWAP: 'Swaps',\n ADD: 'Adds',\n REMOVE: 'Removes',\n}\n\nconst ITEMS_PER_PAGE = 10\n\nfunction getTransactionType(event, symbol0, symbol1) {\n const formattedS0 = symbol0?.length > 8 ? symbol0.slice(0, 7) + '...' : symbol0\n const formattedS1 = symbol1?.length > 8 ? symbol1.slice(0, 7) + '...' : symbol1\n switch (event) {\n case TXN_TYPE.ADD:\n return 'Add ' + formattedS0 + ' and ' + formattedS1\n case TXN_TYPE.REMOVE:\n return 'Remove ' + formattedS0 + ' and ' + formattedS1\n case TXN_TYPE.SWAP:\n return 'Swap ' + formattedS0 + ' for ' + formattedS1\n default:\n return ''\n }\n}\n\n// @TODO rework into virtualized list\nfunction TxnList({ transactions, symbol0Override, symbol1Override, color }) {\n // page state\n const [page, setPage] = useState(1)\n const [maxPage, setMaxPage] = useState(1)\n\n // sorting\n const [sortDirection, setSortDirection] = useState(true)\n const [sortedColumn, setSortedColumn] = useState(SORT_FIELD.TIMESTAMP)\n const [filteredItems, setFilteredItems] = useState()\n const [txFilter, setTxFilter] = useState(TXN_TYPE.ALL)\n\n const [currency] = useCurrentCurrency()\n\n useEffect(() => {\n setMaxPage(1) // edit this to do modular\n setPage(1)\n }, [transactions])\n\n // parse the txns and format for UI\n useEffect(() => {\n if (transactions && transactions.mints && transactions.burns && transactions.swaps) {\n let newTxns = []\n if (transactions.mints.length > 0) {\n transactions.mints.map((mint) => {\n let newTxn = {}\n newTxn.hash = mint.transaction.id\n newTxn.timestamp = mint.transaction.timestamp\n newTxn.type = TXN_TYPE.ADD\n newTxn.token0Amount = mint.amount0\n newTxn.token1Amount = mint.amount1\n newTxn.account = mint.to\n newTxn.token0Symbol = updateNameData(mint.pair).token0.symbol\n newTxn.token1Symbol = updateNameData(mint.pair).token1.symbol\n newTxn.amountUSD = mint.amountUSD\n return newTxns.push(newTxn)\n })\n }\n if (transactions.burns.length > 0) {\n transactions.burns.map((burn) => {\n let newTxn = {}\n newTxn.hash = burn.transaction.id\n newTxn.timestamp = burn.transaction.timestamp\n newTxn.type = TXN_TYPE.REMOVE\n newTxn.token0Amount = burn.amount0\n newTxn.token1Amount = burn.amount1\n newTxn.account = burn.sender\n newTxn.token0Symbol = updateNameData(burn.pair).token0.symbol\n newTxn.token1Symbol = updateNameData(burn.pair).token1.symbol\n newTxn.amountUSD = burn.amountUSD\n return newTxns.push(newTxn)\n })\n }\n if (transactions.swaps.length > 0) {\n transactions.swaps.map((swap) => {\n const netToken0 = swap.amount0In - swap.amount0Out\n const netToken1 = swap.amount1In - swap.amount1Out\n\n let newTxn = {}\n\n if (netToken0 < 0) {\n newTxn.token0Symbol = updateNameData(swap.pair).token0.symbol\n newTxn.token1Symbol = updateNameData(swap.pair).token1.symbol\n newTxn.token0Amount = Math.abs(netToken0)\n newTxn.token1Amount = Math.abs(netToken1)\n } else if (netToken1 < 0) {\n newTxn.token0Symbol = updateNameData(swap.pair).token1.symbol\n newTxn.token1Symbol = updateNameData(swap.pair).token0.symbol\n newTxn.token0Amount = Math.abs(netToken1)\n newTxn.token1Amount = Math.abs(netToken0)\n }\n\n newTxn.hash = swap.transaction.id\n newTxn.timestamp = swap.transaction.timestamp\n newTxn.type = TXN_TYPE.SWAP\n\n newTxn.amountUSD = swap.amountUSD\n newTxn.account = swap.to\n return newTxns.push(newTxn)\n })\n }\n\n const filtered = newTxns.filter((item) => {\n if (txFilter !== TXN_TYPE.ALL) {\n return item.type === txFilter\n }\n return true\n })\n setFilteredItems(filtered)\n let extraPages = 1\n if (filtered.length % ITEMS_PER_PAGE === 0) {\n extraPages = 0\n }\n if (filtered.length === 0) {\n setMaxPage(1)\n } else {\n setMaxPage(Math.floor(filtered.length / ITEMS_PER_PAGE) + extraPages)\n }\n }\n }, [transactions, txFilter])\n\n useEffect(() => {\n setPage(1)\n }, [txFilter])\n\n const filteredList =\n filteredItems &&\n filteredItems\n .sort((a, b) => {\n return parseFloat(a[sortedColumn]) > parseFloat(b[sortedColumn])\n ? (sortDirection ? -1 : 1) * 1\n : (sortDirection ? -1 : 1) * -1\n })\n .slice(ITEMS_PER_PAGE * (page - 1), page * ITEMS_PER_PAGE)\n\n const below1080 = useMedia('(max-width: 1080px)')\n const below780 = useMedia('(max-width: 780px)')\n\n const ListItem = ({ item }) => {\n return (\n \n \n \n {getTransactionType(item.type, item.token1Symbol, item.token0Symbol)}\n \n \n \n {currency === 'BNB' ? 'Ξ ' + formattedNum(item.valueETH) : formattedNum(item.amountUSD, true)}\n \n {!below780 && (\n <>\n \n {formattedNum(item.token1Amount) + ' '}{' '}\n \n \n \n {formattedNum(item.token0Amount) + ' '}{' '}\n \n \n >\n )}\n {!below1080 && (\n \n \n {item.account && item.account.slice(0, 6) + '...' + item.account.slice(38, 42)}\n \n \n )}\n {formatTime(item.timestamp)} \n \n )\n }\n\n return (\n <>\n \n {below780 ? (\n \n \n \n ) : (\n \n {\n setTxFilter(TXN_TYPE.ALL)\n }}\n active={txFilter === TXN_TYPE.ALL}\n >\n All\n \n {\n setTxFilter(TXN_TYPE.SWAP)\n }}\n active={txFilter === TXN_TYPE.SWAP}\n >\n Swaps\n \n {\n setTxFilter(TXN_TYPE.ADD)\n }}\n active={txFilter === TXN_TYPE.ADD}\n >\n Adds\n \n {\n setTxFilter(TXN_TYPE.REMOVE)\n }}\n active={txFilter === TXN_TYPE.REMOVE}\n >\n Removes\n \n \n )}\n\n \n {\n setSortedColumn(SORT_FIELD.VALUE)\n setSortDirection(sortedColumn !== SORT_FIELD.VALUE ? true : !sortDirection)\n }}\n >\n Total Value {sortedColumn === SORT_FIELD.VALUE ? (!sortDirection ? '↑' : '↓') : ''}\n \n \n {!below780 && (\n \n {\n setSortedColumn(SORT_FIELD.AMOUNT0)\n setSortDirection(sortedColumn !== SORT_FIELD.AMOUNT0 ? true : !sortDirection)\n }}\n >\n {symbol0Override ? symbol0Override + ' Amount' : 'Token Amount'}{' '}\n {sortedColumn === SORT_FIELD.AMOUNT0 ? (sortDirection ? '↑' : '↓') : ''}\n \n \n )}\n <>\n {!below780 && (\n \n {\n setSortedColumn(SORT_FIELD.AMOUNT1)\n setSortDirection(sortedColumn !== SORT_FIELD.AMOUNT1 ? true : !sortDirection)\n }}\n >\n {symbol1Override ? symbol1Override + ' Amount' : 'Token Amount'}{' '}\n {sortedColumn === SORT_FIELD.AMOUNT1 ? (sortDirection ? '↑' : '↓') : ''}\n \n \n )}\n {!below1080 && (\n \n Account \n \n )}\n \n {\n setSortedColumn(SORT_FIELD.TIMESTAMP)\n setSortDirection(sortedColumn !== SORT_FIELD.TIMESTAMP ? true : !sortDirection)\n }}\n >\n Time {sortedColumn === SORT_FIELD.TIMESTAMP ? (!sortDirection ? '↑' : '↓') : ''}\n \n \n >\n \n \n \n {!filteredList ? (\n \n ) : filteredList.length === 0 ? (\n No recent transactions found. \n ) : (\n filteredList.map((item, index) => {\n return (\n \n )\n })\n )}\n
\n \n {\n setPage(page === 1 ? page : page - 1)\n }}\n >\n
← \n
\n {'Page ' + page + ' of ' + maxPage} \n {\n setPage(page === maxPage ? page : page + 1)\n }}\n >\n
→ \n
\n \n >\n )\n}\n\nexport default TxnList\n","import React, { useState, useEffect, useRef } from 'react'\nimport { createChart } from 'lightweight-charts'\nimport dayjs from 'dayjs'\nimport utc from 'dayjs/plugin/utc'\nimport { formattedNum } from '../../utils'\nimport styled from 'styled-components'\nimport { usePrevious } from 'react-use'\nimport { Play } from 'react-feather'\nimport { useDarkModeManager } from '../../contexts/LocalStorage'\nimport { IconWrapper } from '..'\n\ndayjs.extend(utc)\n\nexport const CHART_TYPES = {\n BAR: 'BAR',\n AREA: 'AREA',\n}\n\nconst Wrapper = styled.div`\n position: relative;\n`\n\n// constant height for charts\nconst HEIGHT = 300\n\nconst TradingViewChart = ({\n type = CHART_TYPES.BAR,\n data,\n base,\n baseChange,\n field,\n title,\n width,\n useWeekly = false,\n}) => {\n // reference for DOM element to create with chart\n const ref = useRef()\n\n // pointer to the chart object\n const [chartCreated, setChartCreated] = useState(false)\n const dataPrev = usePrevious(data)\n\n useEffect(() => {\n if (data !== dataPrev && chartCreated && type === CHART_TYPES.BAR) {\n // remove the tooltip element\n let tooltip = document.getElementById('tooltip-id' + type)\n let node = document.getElementById('test-id' + type)\n node.removeChild(tooltip)\n chartCreated.resize(0, 0)\n setChartCreated()\n }\n }, [chartCreated, data, dataPrev, type])\n\n // parese the data and format for tardingview consumption\n const formattedData = data?.map((entry) => {\n return {\n time: dayjs.unix(entry.date).utc().format('YYYY-MM-DD'),\n value: parseFloat(entry[field]),\n }\n })\n\n // adjust the scale based on the type of chart\n const topScale = type === CHART_TYPES.AREA ? 0.32 : 0.2\n\n const [darkMode] = useDarkModeManager()\n const textColor = darkMode ? 'white' : 'black'\n const previousTheme = usePrevious(darkMode)\n\n // reset the chart if them switches\n useEffect(() => {\n if (chartCreated && previousTheme !== darkMode) {\n // remove the tooltip element\n let tooltip = document.getElementById('tooltip-id' + type)\n let node = document.getElementById('test-id' + type)\n node.removeChild(tooltip)\n chartCreated.resize(0, 0)\n setChartCreated()\n }\n }, [chartCreated, darkMode, previousTheme, type])\n\n // if no chart created yet, create one with options and add to DOM manually\n useEffect(() => {\n if (!chartCreated && formattedData) {\n var chart = createChart(ref.current, {\n width: width,\n height: HEIGHT,\n layout: {\n backgroundColor: 'transparent',\n textColor: textColor,\n },\n rightPriceScale: {\n scaleMargins: {\n top: topScale,\n bottom: 0,\n },\n borderVisible: false,\n },\n timeScale: {\n borderVisible: false,\n },\n grid: {\n horzLines: {\n color: 'rgba(79, 216, 222, 0.5)',\n visible: false,\n },\n vertLines: {\n color: 'rgba(79, 216, 222, 0.5)',\n visible: false,\n },\n },\n crosshair: {\n horzLine: {\n visible: false,\n labelVisible: false,\n },\n vertLine: {\n visible: true,\n style: 0,\n width: 2,\n color: 'rgba(32, 38, 46, 0.1)',\n labelVisible: false,\n },\n },\n localization: {\n priceFormatter: (val) => formattedNum(val, true),\n },\n })\n\n var series =\n type === CHART_TYPES.BAR\n ? chart.addHistogramSeries({\n color: '#e6433b',\n priceFormat: {\n type: 'volume',\n },\n scaleMargins: {\n top: 0.32,\n bottom: 0,\n },\n lineColor: '#e6433b',\n lineWidth: 3,\n })\n : chart.addAreaSeries({\n topColor: '#e6433b',\n bottomColor: 'rgba(79, 216, 222, 0)',\n lineColor: '#e6433b',\n lineWidth: 3,\n })\n\n series.setData(formattedData)\n var toolTip = document.createElement('div')\n toolTip.setAttribute('id', 'tooltip-id' + type)\n toolTip.className = darkMode ? 'three-line-legend-dark' : 'three-line-legend'\n ref.current.appendChild(toolTip)\n toolTip.style.display = 'block'\n toolTip.style.fontWeight = '500'\n toolTip.style.left = -4 + 'px'\n toolTip.style.top = '-' + 8 + 'px'\n toolTip.style.backgroundColor = 'transparent'\n\n // format numbers\n let percentChange = baseChange?.toFixed(2)\n // let formattedPercentChange = (percentChange > 0 ? '+' : '') + percentChange + '%'\n let color = percentChange >= 0 ? 'green' : 'red'\n\n // get the title of the chart\n function setLastBarText() {\n toolTip.innerHTML =\n `${title} ${\n type === CHART_TYPES.BAR && !useWeekly ? '(24hr)' : ''\n }
` +\n `` +\n formattedNum(base ?? 0, true) +\n `${''} ` +\n '
'\n }\n setLastBarText()\n\n // update the title when hovering on the chart\n chart.subscribeCrosshairMove(function (param) {\n if (\n param === undefined ||\n param.time === undefined ||\n param.point.x < 0 ||\n param.point.x > width ||\n param.point.y < 0 ||\n param.point.y > HEIGHT\n ) {\n setLastBarText()\n } else {\n let dateStr = useWeekly\n ? dayjs(param.time.year + '-' + param.time.month + '-' + param.time.day)\n .startOf('week')\n .format('MMMM D, YYYY') +\n '-' +\n dayjs(param.time.year + '-' + param.time.month + '-' + param.time.day)\n .endOf('week')\n .format('MMMM D, YYYY')\n : dayjs(param.time.year + '-' + param.time.month + '-' + param.time.day).format('MMMM D, YYYY')\n var price = param.seriesPrices.get(series)\n\n toolTip.innerHTML =\n `${title}
` +\n `` +\n formattedNum(price, true) +\n '
' +\n '' +\n dateStr +\n '
'\n }\n })\n\n chart.timeScale().fitContent()\n\n setChartCreated(chart)\n }\n }, [\n base,\n baseChange,\n chartCreated,\n darkMode,\n data,\n formattedData,\n textColor,\n title,\n topScale,\n type,\n useWeekly,\n width,\n ])\n\n // responsiveness\n useEffect(() => {\n if (width) {\n chartCreated && chartCreated.resize(width, HEIGHT)\n chartCreated && chartCreated.timeScale().scrollToPosition(0)\n }\n }, [chartCreated, width])\n\n return (\n \n
\n \n {\n chartCreated && chartCreated.timeScale().fitContent()\n }}\n />\n \n \n )\n}\n\nexport default TradingViewChart\n","import React from 'react'\nimport { Button as RebassButton } from 'rebass/styled-components'\nimport styled from 'styled-components'\nimport { Plus, ChevronDown, ChevronUp } from 'react-feather'\nimport { darken, transparentize } from 'polished'\nimport { RowBetween } from '../Row'\nimport { StyledIcon } from '..'\n\nconst Base = styled(RebassButton)`\n padding: 8px 12px;\n font-size: 0.825rem;\n font-weight: 600;\n border-radius: 12px;\n cursor: pointer;\n outline: none;\n border: 1px solid transparent;\n outline: none;\n border-bottom-right-radius: ${({ open }) => open && '0'};\n border-bottom-left-radius: ${({ open }) => open && '0'};\n`\n\nconst BaseCustom = styled(RebassButton)`\n padding: 16px 12px;\n font-size: 0.825rem;\n font-weight: 400;\n border-radius: 12px;\n cursor: pointer;\n outline: none;\n`\n\nconst Dull = styled(Base)`\n background-color: rgba(255, 255, 255, 0.15);\n border: 1px solid rgba(255, 255, 255, 0.15);\n color: black;\n height: 100%;\n font-weight: 400;\n &:hover,\n :focus {\n background-color: rgba(255, 255, 255, 0.25);\n border-color: rgba(255, 255, 255, 0.25);\n }\n &:focus {\n box-shadow: 0 0 0 1pt rgba(255, 255, 255, 0.25);\n }\n &:active {\n background-color: rgba(255, 255, 255, 0.25);\n border-color: rgba(255, 255, 255, 0.25);\n }\n`\n\nexport default function ButtonStyled({ children, ...rest }) {\n return {children}\n}\n\nconst ContentWrapper = styled.div`\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: space-between;\n`\n\nexport const ButtonLight = styled(Base)`\n background-color: ${({ color, theme }) => (color ? transparentize(0.9, color) : transparentize(0.9, theme.primary1))};\n color: ${({ color, theme }) => (color ? darken(0.1, color) : theme.primary1)};\n\n min-width: fit-content;\n border-radius: 12px;\n white-space: nowrap;\n\n a {\n color: ${({ color, theme }) => (color ? darken(0.1, color) : theme.primary1)};\n }\n\n :hover {\n background-color: ${({ color, theme }) =>\n color ? transparentize(0.8, color) : transparentize(0.8, theme.primary1)};\n }\n`\n\nexport function ButtonDropdown({ disabled = false, children, open, ...rest }) {\n return (\n \n \n {children}
\n {open ? (\n \n \n \n ) : (\n \n \n \n )}\n \n \n )\n}\n\nexport const ButtonDark = styled(Base)`\n background-color: ${({ color, theme }) => (color ? color : theme.primary1)};\n color: white;\n width: fit-content;\n border-radius: 12px;\n white-space: nowrap;\n\n :hover {\n background-color: ${({ color, theme }) => (color ? darken(0.1, color) : darken(0.1, theme.primary1))};\n }\n`\n\nexport const ButtonFaded = styled(Base)`\n background-color: ${({ theme }) => theme.bg2};\n color: (255, 255, 255, 0.5);\n white-space: nowrap;\n\n :hover {\n opacity: 0.5;\n }\n`\n\nexport function ButtonPlusDull({ disabled, children, ...rest }) {\n return (\n \n \n \n {children}
\n \n \n )\n}\n\nexport function ButtonCustom({ children, bgColor, color, ...rest }) {\n return (\n \n {children}\n \n )\n}\n\nexport const OptionButton = styled.div`\n font-weight: 500;\n width: fit-content;\n white-space: nowrap;\n padding: 6px;\n border-radius: 6px;\n border: 1px solid ${({ theme }) => theme.bg4};\n background-color: ${({ active, theme }) => active && theme.bg3};\n color: ${({ theme }) => theme.text1};\n\n :hover {\n cursor: ${({ disabled }) => !disabled && 'pointer'};\n }\n`\n","import React, { useState, useMemo, useEffect, useRef } from 'react'\nimport { ResponsiveContainer } from 'recharts'\nimport { timeframeOptions } from '../../constants'\nimport { useGlobalChartData, useGlobalData } from '../../contexts/GlobalData'\nimport { useMedia } from 'react-use'\nimport DropdownSelect from '../DropdownSelect'\nimport TradingViewChart, { CHART_TYPES } from '../TradingviewChart'\nimport { RowFixed } from '../Row'\nimport { OptionButton } from '../ButtonStyled'\nimport { getTimeframe } from '../../utils'\nimport { TYPE } from '../../Theme'\n\nconst CHART_VIEW = {\n VOLUME: 'Volume',\n LIQUIDITY: 'Liquidity',\n}\n\nconst VOLUME_WINDOW = {\n WEEKLY: 'WEEKLY',\n DAYS: 'DAYS',\n}\nconst GlobalChart = ({ display }) => {\n // chart options\n const [chartView, setChartView] = useState(display === 'volume' ? CHART_VIEW.VOLUME : CHART_VIEW.LIQUIDITY)\n\n // time window and window size for chart\n const timeWindow = timeframeOptions.ALL_TIME\n const [volumeWindow, setVolumeWindow] = useState(VOLUME_WINDOW.DAYS)\n\n // global historical data\n const [dailyData, weeklyData] = useGlobalChartData()\n const { totalLiquidityUSD, oneDayVolumeUSD, volumeChangeUSD, liquidityChangeUSD, oneWeekVolume, weeklyVolumeChange } =\n useGlobalData()\n\n // based on window, get starttim\n let utcStartTime = getTimeframe(timeWindow)\n\n const chartDataFiltered = useMemo(() => {\n let currentData = volumeWindow === VOLUME_WINDOW.DAYS ? dailyData : weeklyData\n return (\n currentData &&\n Object.keys(currentData)\n ?.map((key) => {\n let item = currentData[key]\n if (item.date > utcStartTime) {\n return item\n } else {\n return null\n }\n })\n .filter((item) => {\n return !!item\n })\n )\n }, [dailyData, utcStartTime, volumeWindow, weeklyData])\n const below800 = useMedia('(max-width: 800px)')\n\n // update the width on a window resize\n const ref = useRef()\n const isClient = typeof window === 'object'\n const [width, setWidth] = useState(ref?.current?.container?.clientWidth)\n useEffect(() => {\n if (!isClient) {\n return false\n }\n function handleResize() {\n setWidth(ref?.current?.container?.clientWidth ?? width)\n }\n window.addEventListener('resize', handleResize)\n return () => window.removeEventListener('resize', handleResize)\n }, [isClient, width]) // Empty array ensures that effect is only run on mount and unmount\n\n return chartDataFiltered ? (\n <>\n {below800 && (\n \n )}\n\n {chartDataFiltered && chartView === CHART_VIEW.LIQUIDITY && (\n \n \n \n )}\n {chartDataFiltered && chartView === CHART_VIEW.VOLUME && (\n \n \n \n )}\n {display === 'volume' && (\n \n setVolumeWindow(VOLUME_WINDOW.DAYS)}\n >\n D \n \n setVolumeWindow(VOLUME_WINDOW.WEEKLY)}\n >\n W \n \n \n )}\n >\n ) : (\n ''\n )\n}\n\nexport default GlobalChart\n","import React, { useState, useEffect, useMemo, useRef } from 'react'\nimport styled from 'styled-components'\n\nimport Row, { RowFixed } from '../Row'\nimport TokenLogo from '../TokenLogo'\nimport { Search as SearchIcon, X } from 'react-feather'\nimport { BasicLink } from '../Link'\n\nimport { useAllTokenData, useTokenData } from '../../contexts/TokenData'\nimport { useAllPairData, usePairData } from '../../contexts/PairData'\nimport DoubleTokenLogo from '../DoubleLogo'\nimport { useMedia } from 'react-use'\nimport { useAllPairsInUniswap, useAllTokensInUniswap } from '../../contexts/GlobalData'\nimport { OVERVIEW_TOKEN_BLACKLIST, PAIR_BLACKLIST } from '../../constants'\n\nimport { transparentize } from 'polished'\nimport { client } from '../../apollo/client'\nimport { PAIR_SEARCH, TOKEN_SEARCH } from '../../apollo/queries'\nimport FormattedName from '../FormattedName'\nimport { TYPE } from '../../Theme'\nimport { updateNameData } from '../../utils/data'\n\nconst Container = styled.div`\n height: 48px;\n z-index: 30;\n position: relative;\n\n @media screen and (max-width: 600px) {\n width: 100%;\n }\n`\n\nconst Wrapper = styled.div`\n display: flex;\n position: relative;\n flex-direction: row;\n align-items: center;\n justify-content: flex-end;\n padding: 12px 16px;\n border-radius: 12px;\n background: ${({ theme, small, open }) =>\n small ? (open ? transparentize(0.4, theme.bg1) : 'none') : transparentize(0.4, theme.bg6)};\n border-bottom-right-radius: ${({ open }) => (open ? '0px' : '12px')};\n border-bottom-left-radius: ${({ open }) => (open ? '0px' : '12px')};\n z-index: 9999;\n width: 100%;\n min-width: 300px;\n box-sizing: border-box;\n box-shadow: ${({ open, small }) =>\n !open && !small\n ? '0px 24px 32px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 0px 1px rgba(0, 0, 0, 0.04) '\n : 'none'};\n @media screen and (max-width: 500px) {\n background: ${({ theme }) => transparentize(0.4, theme.bg1)};\n box-shadow: ${({ open }) =>\n !open\n ? '0px 24px 32px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 0px 1px rgba(0, 0, 0, 0.04) '\n : 'none'};\n }\n`\nconst Input = styled.input`\n position: relative;\n display: flex;\n align-items: center;\n white-space: nowrap;\n background: none;\n border: none;\n outline: none;\n width: 100%;\n color: ${({ theme }) => theme.text1};\n font-size: ${({ large }) => (large ? '20px' : '14px')};\n\n ::placeholder {\n color: ${({ theme }) => theme.text3};\n font-size: 16px;\n }\n\n @media screen and (max-width: 640px) {\n ::placeholder {\n font-size: 1rem;\n }\n }\n`\n\nconst SearchIconLarge = styled(SearchIcon)`\n height: 20px;\n width: 20px;\n margin-right: 0.5rem;\n position: absolute;\n right: 10px;\n pointer-events: none;\n color: ${({ theme }) => theme.text3};\n`\n\nconst CloseIcon = styled(X)`\n height: 20px;\n width: 20px;\n margin-right: 0.5rem;\n position: absolute;\n right: 10px;\n color: ${({ theme }) => theme.text3};\n :hover {\n cursor: pointer;\n }\n`\n\nconst Menu = styled.div`\n display: flex;\n flex-direction: column;\n z-index: 9999;\n width: 100%;\n top: 50px;\n max-height: 540px;\n overflow: auto;\n left: 0;\n padding-bottom: 20px;\n background: ${({ theme }) => theme.bg6};\n border-bottom-right-radius: 12px;\n border-bottom-left-radius: 12px;\n box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.04), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04),\n 0px 24px 32px rgba(0, 0, 0, 0.04);\n display: ${({ hide }) => hide && 'none'};\n`\n\nconst MenuItem = styled(Row)`\n padding: 1rem;\n font-size: 0.85rem;\n & > * {\n margin-right: 6px;\n }\n :hover {\n cursor: pointer;\n background-color: ${({ theme }) => theme.bg2};\n }\n`\n\nconst Heading = styled(Row)`\n padding: 1rem;\n display: ${({ hide = false }) => hide && 'none'};\n`\n\nconst Gray = styled.span`\n color: #888d9b;\n`\n\nconst Blue = styled.span`\n color: #2172e5;\n :hover {\n cursor: pointer;\n }\n`\n\nexport const Search = ({ small = false }) => {\n let allTokens = useAllTokensInUniswap()\n const allTokenData = useAllTokenData()\n\n let allPairs = useAllPairsInUniswap()\n const allPairData = useAllPairData()\n\n const [showMenu, toggleMenu] = useState(false)\n const [value, setValue] = useState('')\n const [, toggleShadow] = useState(false)\n const [, toggleBottomShadow] = useState(false)\n\n // fetch new data on tokens and pairs if needed\n useTokenData(value)\n usePairData(value)\n\n const below700 = useMedia('(max-width: 700px)')\n const below470 = useMedia('(max-width: 470px)')\n const below410 = useMedia('(max-width: 410px)')\n\n useEffect(() => {\n if (value !== '') {\n toggleMenu(true)\n } else {\n toggleMenu(false)\n }\n }, [value])\n\n const [searchedTokens, setSearchedTokens] = useState([])\n const [searchedPairs, setSearchedPairs] = useState([])\n\n useEffect(() => {\n async function fetchData() {\n try {\n if (value?.length > 0) {\n let tokens = await client.query({\n query: TOKEN_SEARCH,\n variables: {\n value: value ? value.toUpperCase() : '',\n id: value,\n },\n })\n\n let pairs = await client.query({\n query: PAIR_SEARCH,\n variables: {\n tokens: tokens.data.asSymbol?.map((t) => t.id),\n id: value,\n },\n })\n\n setSearchedPairs(\n updateNameData(pairs.data.as0)\n .concat(updateNameData(pairs.data.as1))\n .concat(updateNameData(pairs.data.asAddress))\n )\n const foundTokens = tokens.data.asSymbol.concat(tokens.data.asAddress).concat(tokens.data.asName)\n setSearchedTokens(foundTokens)\n }\n } catch (e) {\n console.log(e)\n }\n }\n fetchData()\n }, [value])\n\n function escapeRegExp(string) {\n return string.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&') // $& means the whole matched string\n }\n\n // add the searched tokens to the list if not found yet\n allTokens = allTokens.concat(\n searchedTokens.filter((searchedToken) => {\n let included = false\n updateNameData()\n allTokens.map((token) => {\n if (token.id === searchedToken.id) {\n included = true\n }\n return true\n })\n return !included\n })\n )\n\n let uniqueTokens = []\n let found = {}\n allTokens &&\n allTokens.map((token) => {\n if (!found[token.id]) {\n found[token.id] = true\n uniqueTokens.push(token)\n }\n return true\n })\n\n allPairs = allPairs.concat(\n searchedPairs.filter((searchedPair) => {\n let included = false\n allPairs.map((pair) => {\n if (pair.id === searchedPair.id) {\n included = true\n }\n return true\n })\n return !included\n })\n )\n\n let uniquePairs = []\n let pairsFound = {}\n allPairs &&\n allPairs.map((pair) => {\n if (!pairsFound[pair.id]) {\n pairsFound[pair.id] = true\n uniquePairs.push(pair)\n }\n return true\n })\n\n const filteredTokenList = useMemo(() => {\n return uniqueTokens\n ? uniqueTokens\n .sort((a, b) => {\n if (OVERVIEW_TOKEN_BLACKLIST.includes(a.id)) {\n return 1\n }\n if (OVERVIEW_TOKEN_BLACKLIST.includes(b.id)) {\n return -1\n }\n const tokenA = allTokenData[a.id]\n const tokenB = allTokenData[b.id]\n if (tokenA?.oneDayVolumeUSD && tokenB?.oneDayVolumeUSD) {\n return tokenA.oneDayVolumeUSD > tokenB.oneDayVolumeUSD ? -1 : 1\n }\n if (tokenA?.oneDayVolumeUSD && !tokenB?.oneDayVolumeUSD) {\n return -1\n }\n if (!tokenA?.oneDayVolumeUSD && tokenB?.oneDayVolumeUSD) {\n return tokenA?.totalLiquidity > tokenB?.totalLiquidity ? -1 : 1\n }\n return 1\n })\n .filter((token) => {\n if (OVERVIEW_TOKEN_BLACKLIST.includes(token.id)) {\n return false\n }\n const regexMatches = Object.keys(token).map((tokenEntryKey) => {\n const isAddress = value.slice(0, 2) === '0x'\n if (tokenEntryKey === 'id' && isAddress) {\n return token[tokenEntryKey].match(new RegExp(escapeRegExp(value), 'i'))\n }\n if (tokenEntryKey === 'symbol' && !isAddress) {\n return token[tokenEntryKey].match(new RegExp(escapeRegExp(value), 'i'))\n }\n if (tokenEntryKey === 'name' && !isAddress) {\n return token[tokenEntryKey].match(new RegExp(escapeRegExp(value), 'i'))\n }\n return false\n })\n return regexMatches.some((m) => m)\n })\n : []\n }, [allTokenData, uniqueTokens, value])\n\n const filteredPairList = useMemo(() => {\n return uniquePairs\n ? uniquePairs\n .sort((a, b) => {\n const pairA = allPairData[a.id]\n const pairB = allPairData[b.id]\n if (pairA?.trackedReserveBNB && pairB?.trackedReserveBNB) {\n return parseFloat(pairA.trackedReserveBNB) > parseFloat(pairB.trackedReserveBNB) ? -1 : 1\n }\n if (pairA?.trackedReserveBNB && !pairB?.trackedReserveBNB) {\n return -1\n }\n if (!pairA?.trackedReserveBNB && pairB?.trackedReserveBNB) {\n return 1\n }\n return 0\n })\n .filter((pair) => {\n if (PAIR_BLACKLIST.includes(pair.id)) {\n return false\n }\n if (value && value.includes(' ')) {\n const pairA = value.split(' ')[0]?.toUpperCase()\n const pairB = value.split(' ')[1]?.toUpperCase()\n return (\n (pair.token0.symbol.includes(pairA) || pair.token0.symbol.includes(pairB)) &&\n (pair.token1.symbol.includes(pairA) || pair.token1.symbol.includes(pairB))\n )\n }\n if (value && value.includes('-')) {\n const pairA = value.split('-')[0]?.toUpperCase()\n const pairB = value.split('-')[1]?.toUpperCase()\n return (\n (pair.token0.symbol.includes(pairA) || pair.token0.symbol.includes(pairB)) &&\n (pair.token1.symbol.includes(pairA) || pair.token1.symbol.includes(pairB))\n )\n }\n const regexMatches = Object.keys(pair).map((field) => {\n const isAddress = value.slice(0, 2) === '0x'\n if (field === 'id' && isAddress) {\n return pair[field].match(new RegExp(escapeRegExp(value), 'i'))\n }\n if (field === 'token0') {\n return (\n pair[field].symbol.match(new RegExp(escapeRegExp(value), 'i')) ||\n pair[field].name.match(new RegExp(escapeRegExp(value), 'i'))\n )\n }\n if (field === 'token1') {\n return (\n pair[field].symbol.match(new RegExp(escapeRegExp(value), 'i')) ||\n pair[field].name.match(new RegExp(escapeRegExp(value), 'i'))\n )\n }\n return false\n })\n return regexMatches.some((m) => m)\n })\n : []\n }, [allPairData, uniquePairs, value])\n\n useEffect(() => {\n if (Object.keys(filteredTokenList).length > 2) {\n toggleShadow(true)\n } else {\n toggleShadow(false)\n }\n }, [filteredTokenList])\n\n useEffect(() => {\n if (Object.keys(filteredPairList).length > 2) {\n toggleBottomShadow(true)\n } else {\n toggleBottomShadow(false)\n }\n }, [filteredPairList])\n\n const [tokensShown, setTokensShown] = useState(3)\n const [pairsShown, setPairsShown] = useState(3)\n\n function onDismiss() {\n setPairsShown(3)\n setTokensShown(3)\n toggleMenu(false)\n setValue('')\n }\n\n // refs to detect clicks outside modal\n const wrapperRef = useRef()\n const menuRef = useRef()\n\n const handleClick = (e) => {\n if (\n !(menuRef.current && menuRef.current.contains(e.target)) &&\n !(wrapperRef.current && wrapperRef.current.contains(e.target))\n ) {\n setPairsShown(3)\n setTokensShown(3)\n toggleMenu(false)\n }\n }\n\n useEffect(() => {\n document.addEventListener('click', handleClick)\n return () => {\n document.removeEventListener('click', handleClick)\n }\n })\n\n return (\n \n \n {\n setValue(e.target.value)\n }}\n onFocus={() => {\n if (!showMenu) {\n toggleMenu(true)\n }\n }}\n />\n {!showMenu ? : toggleMenu(false)} />}\n \n \n \n Pairs \n \n \n {filteredPairList && Object.keys(filteredPairList).length === 0 && (\n \n No results \n \n )}\n {filteredPairList &&\n filteredPairList.slice(0, pairsShown).map((pair) => {\n //format incorrect names\n updateNameData(pair)\n return (\n \n \n \n \n {pair.token0.symbol + '-' + pair.token1.symbol} Pair\n \n \n \n )\n })}\n 3 && Object.keys(filteredPairList).length >= pairsShown)}\n >\n {\n setPairsShown(pairsShown + 5)\n }}\n >\n See more...\n \n \n
\n \n Tokens \n \n \n {Object.keys(filteredTokenList).length === 0 && (\n \n No results \n \n )}\n {filteredTokenList.slice(0, tokensShown).map((token) => {\n // update displayed names\n updateNameData({ token0: token })\n return (\n \n \n \n \n \n ( )\n \n \n \n )\n })}\n\n 3 && Object.keys(filteredTokenList).length >= tokensShown)}\n >\n {\n setTokensShown(tokensShown + 5)\n }}\n >\n See more...\n \n \n
\n \n \n )\n}\n\nexport default Search\n","import React, { useState } from 'react'\nimport styled from 'styled-components'\nimport { RowFixed, RowBetween } from '../Row'\nimport { useMedia } from 'react-use'\nimport { useGlobalData, useBnbPrice } from '../../contexts/GlobalData'\nimport { formattedNum, localNumber } from '../../utils'\n\nimport { TYPE } from '../../Theme'\n\nconst Header = styled.div`\n width: 100%;\n position: sticky;\n top: 0;\n`\n\nconst Medium = styled.span`\n font-weight: 500;\n`\n\nexport default function GlobalStats() {\n const below1295 = useMedia('(max-width: 1295px)')\n const below1180 = useMedia('(max-width: 1180px)')\n const below1024 = useMedia('(max-width: 1024px)')\n const below400 = useMedia('(max-width: 400px)')\n const below816 = useMedia('(max-width: 816px)')\n\n const [, setShowPriceCard] = useState(false)\n\n const { oneDayVolumeUSD, oneDayTxns, pairCount } = useGlobalData()\n const [bnbPrice] = useBnbPrice()\n const formattedEthPrice = bnbPrice ? formattedNum(bnbPrice, true) : '-'\n const oneDayFees = oneDayVolumeUSD ? formattedNum(oneDayVolumeUSD * 0.002, true) : ''\n\n return (\n \n \n \n {!below400 && (\n {\n setShowPriceCard(true)\n }}\n onMouseLeave={() => {\n setShowPriceCard(false)\n }}\n style={{ position: 'relative' }}\n >\n BNB Price: {formattedEthPrice} \n \n )}\n\n {!below1180 && (\n \n Transactions (24H): {localNumber(oneDayTxns)} \n \n )}\n {!below1024 && (\n \n Pairs: {localNumber(pairCount)} \n \n )}\n {!below1295 && (\n \n Fees (24H): {oneDayFees} \n \n )}\n \n \n \n )\n}\n","import { Box as RebassBox } from 'rebass'\nimport styled, { css } from 'styled-components'\n\nconst panelPseudo = css`\n :after {\n content: '';\n position: absolute;\n left: 0;\n right: 0;\n height: 10px;\n }\n\n @media only screen and (min-width: 40em) {\n :after {\n content: unset;\n }\n }\n`\n\nconst Panel = styled(RebassBox)`\n position: relative;\n background-color: ${({ theme }) => theme.advancedBG};\n padding: 1.25rem;\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n border-radius: 8px;\n border: 1px solid ${({ theme }) => theme.bg3};\n box-shadow: 0px 6px 10px rgba(0, 0, 0, 0.05); /* box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.01), 0px 4px 8px rgba(0, 0, 0, 0.01), 0px 16px 24px rgba(0, 0, 0, 0.01), 0px 24px 32px rgba(0, 0, 0, 0.01); */\n :hover {\n cursor: ${({ hover }) => hover && 'pointer'};\n border: ${({ hover, theme }) => hover && '1px solid' + theme.bg5};\n }\n\n ${(props) => props.background && `background-color: ${props.theme.advancedBG};`}\n\n ${(props) => (props.area ? `grid-area: ${props.area};` : null)}\n\n ${(props) =>\n props.grouped &&\n css`\n @media only screen and (min-width: 40em) {\n &:first-of-type {\n border-radius: 20px 20px 0 0;\n }\n &:last-of-type {\n border-radius: 0 0 20px 20px;\n }\n }\n `}\n\n ${(props) =>\n props.rounded &&\n css`\n border-radius: 8px;\n @media only screen and (min-width: 40em) {\n border-radius: 10px;\n }\n `};\n\n ${(props) => !props.last && panelPseudo}\n`\n\nexport default Panel\n\n// const Panel = styled.div`\n// width: 100%;\n// height: 100%;\n// display: flex;\n// flex-direction: column;\n// justify-content: flex-start;\n// border-radius: 12px;\n// background-color: ${({ theme }) => theme.advancedBG};\n// padding: 1.25rem;\n// box-sizing: border-box;\n// box-shadow: 0 1.1px 2.8px -9px rgba(0, 0, 0, 0.008), 0 2.7px 6.7px -9px rgba(0, 0, 0, 0.012),\n// 0 5px 12.6px -9px rgba(0, 0, 0, 0.015), 0 8.9px 22.6px -9px rgba(0, 0, 0, 0.018),\n// 0 16.7px 42.2px -9px rgba(0, 0, 0, 0.022), 0 40px 101px -9px rgba(0, 0, 0, 0.03);\n// `\n","import React, { useEffect } from 'react'\nimport { withRouter } from 'react-router-dom'\nimport { Box } from 'rebass'\nimport styled from 'styled-components'\n\nimport { AutoRow, RowBetween } from '../components/Row'\nimport { AutoColumn } from '../components/Column'\nimport PairList from '../components/PairList'\nimport TopTokenList from '../components/TokenList'\nimport TxnList from '../components/TxnList'\nimport GlobalChart from '../components/GlobalChart'\nimport Search from '../components/Search'\nimport GlobalStats from '../components/GlobalStats'\n\nimport { useGlobalData, useGlobalTransactions } from '../contexts/GlobalData'\nimport { useAllPairData } from '../contexts/PairData'\nimport { useMedia } from 'react-use'\nimport Panel from '../components/Panel'\nimport { useAllTokenData } from '../contexts/TokenData'\nimport { formattedNum, formattedPercent } from '../utils'\nimport { TYPE, ThemedBackground } from '../Theme'\nimport { transparentize } from 'polished'\nimport { CustomLink } from '../components/Link'\n\nimport { PageWrapper, ContentWrapper } from '../components'\n\nconst ListOptions = styled(AutoRow)`\n height: 40px;\n width: 100%;\n font-size: 1.25rem;\n font-weight: 600;\n\n @media screen and (max-width: 640px) {\n font-size: 1rem;\n }\n`\n\nconst GridRow = styled.div`\n display: grid;\n width: 100%;\n grid-template-columns: 1fr 1fr;\n column-gap: 6px;\n align-items: start;\n justify-content: space-between;\n`\n\nfunction GlobalPage() {\n // get data for lists and totals\n const allPairs = useAllPairData()\n const allTokens = useAllTokenData()\n const transactions = useGlobalTransactions()\n const { totalLiquidityUSD, oneDayVolumeUSD, volumeChangeUSD, liquidityChangeUSD } = useGlobalData()\n\n // breakpoints\n const below800 = useMedia('(max-width: 800px)')\n\n // scrolling refs\n\n useEffect(() => {\n document.querySelector('body').scrollTo({\n behavior: 'smooth',\n top: 0,\n })\n }, [])\n\n return (\n \n \n \n \n
\n {below800 ? 'Analytics' : 'Neverswap Analytics'} \n \n \n \n {below800 && ( // mobile card\n
\n \n \n \n \n \n Volume (24hrs) \n
\n \n \n \n {formattedNum(oneDayVolumeUSD, true)}\n \n {formattedPercent(volumeChangeUSD)} \n \n \n \n \n Total Liquidity \n
\n \n \n \n {formattedNum(totalLiquidityUSD, true)}\n \n {formattedPercent(liquidityChangeUSD)} \n \n \n \n \n \n \n )}\n {!below800 && (\n
\n \n \n \n \n \n \n \n )}\n {below800 && (\n
\n \n \n \n \n )}\n
\n \n Top Tokens \n See All \n \n \n
\n \n \n
\n \n Top Pairs \n See All \n \n \n
\n \n \n\n
\n \n Transactions\n \n \n
\n \n \n
\n \n \n )\n}\n\nexport default withRouter(GlobalPage)\n","import React, { useState, useEffect, useRef } from 'react'\nimport { createChart, CrosshairMode } from 'lightweight-charts'\nimport dayjs from 'dayjs'\nimport { formattedNum } from '../../utils'\nimport { usePrevious } from 'react-use'\nimport styled from 'styled-components'\nimport { Play } from 'react-feather'\nimport { useDarkModeManager } from '../../contexts/LocalStorage'\n\nconst IconWrapper = styled.div`\n position: absolute;\n right: 10px;\n color: ${({ theme }) => theme.text1}\n border-radius: 3px;\n height: 16px;\n width: 16px;\n padding: 0px;\n bottom: 10px;\n display: flex;\n align-items: center;\n justify-content: center;\n\n :hover {\n cursor: pointer;\n opacity: 0.7;\n }\n`\n\nconst CandleStickChart = ({\n data,\n width,\n height = 300,\n base,\n margin = true,\n valueFormatter = (val) => formattedNum(val, true),\n}) => {\n // reference for DOM element to create with chart\n const ref = useRef()\n\n const formattedData = data?.map((entry) => {\n return {\n time: parseFloat(entry.timestamp),\n open: parseFloat(entry.open),\n low: parseFloat(entry.open),\n close: parseFloat(entry.close),\n high: parseFloat(entry.close),\n }\n })\n\n if (formattedData && formattedData.length > 0) {\n formattedData.push({\n time: dayjs.utc().unix(),\n open: parseFloat(formattedData[formattedData.length - 1].close),\n close: parseFloat(base),\n low: Math.min(parseFloat(base), parseFloat(formattedData[formattedData.length - 1].close)),\n high: Math.max(parseFloat(base), parseFloat(formattedData[formattedData.length - 1].close)),\n })\n }\n\n // pointer to the chart object\n const [chartCreated, setChartCreated] = useState(false)\n const dataPrev = usePrevious(data)\n\n const [darkMode] = useDarkModeManager()\n const textColor = darkMode ? 'white' : 'black'\n const previousTheme = usePrevious(darkMode)\n\n // reset the chart if theme switches\n useEffect(() => {\n if (chartCreated && previousTheme !== darkMode) {\n // remove the tooltip element\n let tooltip = document.getElementById('tooltip-id')\n let node = document.getElementById('test-id')\n node.removeChild(tooltip)\n chartCreated.resize(0, 0)\n setChartCreated()\n }\n }, [chartCreated, darkMode, previousTheme])\n\n useEffect(() => {\n if (data !== dataPrev && chartCreated) {\n // remove the tooltip element\n let tooltip = document.getElementById('tooltip-id')\n let node = document.getElementById('test-id')\n node.removeChild(tooltip)\n chartCreated.resize(0, 0)\n setChartCreated()\n }\n }, [chartCreated, data, dataPrev])\n\n // if no chart created yet, create one with options and add to DOM manually\n useEffect(() => {\n if (!chartCreated) {\n const chart = createChart(ref.current, {\n width: width,\n height: height,\n layout: {\n backgroundColor: 'transparent',\n textColor: textColor,\n },\n grid: {\n vertLines: {\n color: 'rgba(197, 203, 206, 0.5)',\n },\n horzLines: {\n color: 'rgba(197, 203, 206, 0.5)',\n },\n },\n crosshair: {\n mode: CrosshairMode.Normal,\n },\n rightPriceScale: {\n borderColor: 'rgba(197, 203, 206, 0.8)',\n visible: true,\n },\n timeScale: {\n borderColor: 'rgba(197, 203, 206, 0.8)',\n },\n localization: {\n priceFormatter: (val) => formattedNum(val),\n },\n })\n\n var candleSeries = chart.addCandlestickSeries({\n upColor: 'green',\n downColor: 'red',\n borderDownColor: 'red',\n borderUpColor: 'green',\n wickDownColor: 'red',\n wickUpColor: 'green',\n })\n\n candleSeries.setData(formattedData)\n\n var toolTip = document.createElement('div')\n toolTip.setAttribute('id', 'tooltip-id')\n toolTip.className = 'three-line-legend'\n ref.current.appendChild(toolTip)\n toolTip.style.display = 'block'\n toolTip.style.left = (margin ? 116 : 10) + 'px'\n toolTip.style.top = 50 + 'px'\n toolTip.style.backgroundColor = 'transparent'\n\n // get the title of the chart\n function setLastBarText() {\n toolTip.innerHTML = base\n ? `` + valueFormatter(base) + '
'\n : ''\n }\n setLastBarText()\n\n // update the title when hovering on the chart\n chart.subscribeCrosshairMove(function (param) {\n if (\n param === undefined ||\n param.time === undefined ||\n param.point.x < 0 ||\n param.point.x > width ||\n param.point.y < 0 ||\n param.point.y > height\n ) {\n setLastBarText()\n } else {\n var price = param.seriesPrices.get(candleSeries).close\n const time = dayjs.unix(param.time).format('MM/DD h:mm A')\n toolTip.innerHTML =\n `` +\n valueFormatter(price) +\n `` +\n time +\n ' UTC' +\n ' ' +\n '
'\n }\n })\n\n chart.timeScale().fitContent()\n\n setChartCreated(chart)\n }\n }, [chartCreated, formattedData, width, height, valueFormatter, base, margin, textColor])\n\n // responsiveness\n useEffect(() => {\n if (width) {\n chartCreated && chartCreated.resize(width, height)\n chartCreated && chartCreated.timeScale().scrollToPosition(0)\n }\n }, [chartCreated, height, width])\n\n return (\n \n
\n
\n {\n chartCreated && chartCreated.timeScale().fitContent()\n }}\n />\n \n
\n )\n}\n\nexport default CandleStickChart\n","import React, { useState, useRef, useEffect } from 'react'\nimport styled from 'styled-components'\nimport { Area, XAxis, YAxis, ResponsiveContainer, Tooltip, AreaChart, BarChart, Bar } from 'recharts'\nimport { AutoRow, RowBetween, RowFixed } from '../Row'\n\nimport { toK, toNiceDate, toNiceDateYear, formattedNum, getTimeframe } from '../../utils'\nimport { OptionButton } from '../ButtonStyled'\nimport { darken } from 'polished'\nimport { useMedia, usePrevious } from 'react-use'\nimport { timeframeOptions } from '../../constants'\nimport { useTokenChartData, useTokenPriceData } from '../../contexts/TokenData'\nimport DropdownSelect from '../DropdownSelect'\nimport CandleStickChart from '../CandleChart'\nimport LocalLoader from '../LocalLoader'\nimport { AutoColumn } from '../Column'\nimport { Activity } from 'react-feather'\nimport { useDarkModeManager } from '../../contexts/LocalStorage'\n\nconst ChartWrapper = styled.div`\n height: 100%;\n min-height: 300px;\n\n @media screen and (max-width: 600px) {\n min-height: 200px;\n }\n`\n\nconst PriceOption = styled(OptionButton)`\n border-radius: 2px;\n`\n\nconst CHART_VIEW = {\n VOLUME: 'Volume',\n LIQUIDITY: 'Liquidity',\n PRICE: 'Price',\n LINE_PRICE: 'Price (Line)',\n}\n\nconst DATA_FREQUENCY = {\n DAY: 'DAY',\n HOUR: 'HOUR',\n LINE: 'LINE',\n}\n\nconst TokenChart = ({ address, color, base }) => {\n // settings for the window and candle width\n const [chartFilter, setChartFilter] = useState(CHART_VIEW.PRICE)\n const [frequency, setFrequency] = useState(DATA_FREQUENCY.HOUR)\n\n const [darkMode] = useDarkModeManager()\n const textColor = darkMode ? 'white' : 'black'\n\n // reset view on new address\n const addressPrev = usePrevious(address)\n useEffect(() => {\n if (address !== addressPrev && addressPrev) {\n setChartFilter(CHART_VIEW.LIQUIDITY)\n }\n }, [address, addressPrev])\n\n let chartData = useTokenChartData(address)\n\n const [timeWindow, setTimeWindow] = useState(timeframeOptions.ALL_TIME)\n const prevWindow = usePrevious(timeWindow)\n\n // hourly and daily price data based on the current time window\n const hourlyWeek = useTokenPriceData(address, timeframeOptions.WEEK, 3600)\n const hourlyMonth = useTokenPriceData(address, timeframeOptions.MONTH, 3600)\n const hourlyAll = useTokenPriceData(address, timeframeOptions.ALL_TIME, 3600)\n const dailyWeek = useTokenPriceData(address, timeframeOptions.WEEK, 86400)\n const dailyMonth = useTokenPriceData(address, timeframeOptions.MONTH, 86400)\n const dailyAll = useTokenPriceData(address, timeframeOptions.ALL_TIME, 86400)\n\n const priceData =\n timeWindow === timeframeOptions.MONTH\n ? // monthly selected\n frequency === DATA_FREQUENCY.DAY\n ? dailyMonth\n : hourlyMonth\n : // weekly selected\n timeWindow === timeframeOptions.WEEK\n ? frequency === DATA_FREQUENCY.DAY\n ? dailyWeek\n : hourlyWeek\n : // all time selected\n frequency === DATA_FREQUENCY.DAY\n ? dailyAll\n : hourlyAll\n\n // switch to hourly data when switched to week window\n useEffect(() => {\n if (timeWindow === timeframeOptions.WEEK && prevWindow && prevWindow !== timeframeOptions.WEEK) {\n setFrequency(DATA_FREQUENCY.HOUR)\n }\n }, [prevWindow, timeWindow])\n\n // switch to daily data if switche to month or all time view\n useEffect(() => {\n if (timeWindow === timeframeOptions.MONTH && prevWindow && prevWindow !== timeframeOptions.MONTH) {\n setFrequency(DATA_FREQUENCY.DAY)\n }\n if (timeWindow === timeframeOptions.ALL_TIME && prevWindow && prevWindow !== timeframeOptions.ALL_TIME) {\n setFrequency(DATA_FREQUENCY.DAY)\n }\n }, [prevWindow, timeWindow])\n\n const below1080 = useMedia('(max-width: 1080px)')\n const below600 = useMedia('(max-width: 600px)')\n\n let utcStartTime = getTimeframe(timeWindow)\n const domain = [(dataMin) => (dataMin > utcStartTime ? dataMin : utcStartTime), 'dataMax']\n const aspect = below1080 ? 60 / 32 : below600 ? 60 / 42 : 60 / 22\n\n chartData = chartData?.filter((entry) => entry.date >= utcStartTime)\n\n // update the width on a window resize\n const ref = useRef()\n const isClient = typeof window === 'object'\n const [width, setWidth] = useState(ref?.current?.container?.clientWidth)\n useEffect(() => {\n if (!isClient) {\n return false\n }\n function handleResize() {\n setWidth(ref?.current?.container?.clientWidth ?? width)\n }\n window.addEventListener('resize', handleResize)\n return () => window.removeEventListener('resize', handleResize)\n }, [isClient, width]) // Empty array ensures that effect is only run on mount and unmount\n\n return (\n \n {below600 ? (\n \n \n \n \n ) : (\n \n \n \n setChartFilter(CHART_VIEW.LIQUIDITY)}\n style={{ marginRight: '6px' }}\n >\n Liquidity\n \n setChartFilter(CHART_VIEW.VOLUME)}\n style={{ marginRight: '6px' }}\n >\n Volume\n \n {\n setChartFilter(CHART_VIEW.PRICE)\n }}\n >\n Price\n \n \n {chartFilter === CHART_VIEW.PRICE && (\n \n {\n setTimeWindow(timeframeOptions.MONTH)\n setFrequency(DATA_FREQUENCY.DAY)\n }}\n >\n D\n \n setFrequency(DATA_FREQUENCY.HOUR)}\n >\n H\n \n setFrequency(DATA_FREQUENCY.LINE)}\n >\n \n \n \n )}\n \n \n setTimeWindow(timeframeOptions.WEEK)}\n >\n 1W\n \n setTimeWindow(timeframeOptions.MONTH)}\n >\n 1M\n \n setTimeWindow(timeframeOptions.ALL_TIME)}\n >\n All\n \n \n \n )}\n {chartFilter === CHART_VIEW.LIQUIDITY && chartData && (\n \n \n \n \n \n \n \n \n toNiceDate(tick)}\n dataKey=\"date\"\n tick={{ fill: textColor }}\n type={'number'}\n domain={['dataMin', 'dataMax']}\n />\n '$' + toK(tick)}\n axisLine={false}\n tickLine={false}\n interval=\"preserveEnd\"\n minTickGap={80}\n yAxisId={0}\n tick={{ fill: textColor }}\n />\n formattedNum(val, true)}\n labelFormatter={(label) => toNiceDateYear(label)}\n labelStyle={{ paddingTop: 4 }}\n contentStyle={{\n padding: '10px 14px',\n borderRadius: 10,\n borderColor: color,\n color: 'black',\n }}\n wrapperStyle={{ top: -70, left: -10 }}\n />\n \n \n \n )}\n {chartFilter === CHART_VIEW.PRICE &&\n (frequency === DATA_FREQUENCY.LINE ? (\n \n \n \n \n \n \n \n \n toNiceDate(tick)}\n dataKey=\"date\"\n tick={{ fill: textColor }}\n type={'number'}\n domain={domain}\n />\n '$' + toK(tick)}\n axisLine={false}\n tickLine={false}\n interval=\"preserveEnd\"\n minTickGap={80}\n yAxisId={0}\n tick={{ fill: textColor }}\n />\n formattedNum(val, true)}\n labelFormatter={(label) => toNiceDateYear(label)}\n labelStyle={{ paddingTop: 4 }}\n contentStyle={{\n padding: '10px 14px',\n borderRadius: 10,\n borderColor: color,\n color: 'black',\n }}\n wrapperStyle={{ top: -70, left: -10 }}\n />\n \n \n \n ) : priceData ? (\n \n \n \n ) : (\n \n ))}\n\n {chartFilter === CHART_VIEW.VOLUME && (\n \n \n toNiceDate(tick)}\n dataKey=\"date\"\n tick={{ fill: textColor }}\n type={'number'}\n domain={['dataMin', 'dataMax']}\n />\n '$' + toK(tick)}\n tickLine={false}\n orientation=\"right\"\n interval=\"preserveEnd\"\n minTickGap={80}\n yAxisId={0}\n tick={{ fill: textColor }}\n />\n formattedNum(val, true)}\n labelFormatter={(label) => toNiceDateYear(label)}\n labelStyle={{ paddingTop: 4 }}\n contentStyle={{\n padding: '10px 14px',\n borderRadius: 10,\n borderColor: color,\n color: 'black',\n }}\n wrapperStyle={{ top: -70, left: -10 }}\n />\n \n \n \n )}\n \n )\n}\n\nexport default TokenChart\n","import React from 'react'\nimport styled from 'styled-components'\nimport { useCopyClipboard } from '../../hooks'\nimport { CheckCircle, Copy } from 'react-feather'\nimport { StyledIcon } from '..'\n\nconst CopyIcon = styled.div`\n color: #aeaeae;\n flex-shrink: 0;\n margin-right: 1rem;\n margin-left: 0.5rem;\n text-decoration: none;\n :hover,\n :active,\n :focus {\n text-decoration: none;\n opacity: 0.8;\n cursor: pointer;\n }\n`\nconst TransactionStatusText = styled.span`\n margin-left: 0.25rem;\n ${({ theme }) => theme.flexRowNoWrap};\n align-items: center;\n color: black;\n`\n\nexport default function CopyHelper({ toCopy }) {\n const [isCopied, setCopied] = useCopyClipboard()\n\n return (\n setCopied(toCopy)}>\n {isCopied ? (\n \n \n \n \n \n ) : (\n \n \n \n \n \n )}\n \n )\n}\n","import React from 'react'\nimport 'feather-icons'\nimport styled from 'styled-components'\nimport { Text } from 'rebass'\nimport { AlertTriangle } from 'react-feather'\nimport { RowBetween, RowFixed } from '../Row'\nimport { ButtonDark } from '../ButtonStyled'\nimport { AutoColumn } from '../Column'\nimport { Hover } from '..'\nimport Link from '../Link'\nimport { useMedia } from 'react-use'\n\nconst WarningWrapper = styled.div`\n border-radius: 20px;\n border: 1px solid #f82d3a;\n background: rgba(248, 45, 58, 0.05);\n padding: 1rem;\n color: #f82d3a;\n display: ${({ show }) => !show && 'none'};\n margin: 0 2rem 2rem 2rem;\n position: relative;\n\n @media screen and (max-width: 800px) {\n width: 80% !important;\n margin-left: 5%;\n }\n`\n\nconst StyledWarningIcon = styled(AlertTriangle)`\n min-height: 20px;\n min-width: 20px;\n stroke: red;\n`\n\nexport default function Warning({ type, show, setShow, address }) {\n const below800 = useMedia('(max-width: 800px)')\n\n const textContent = below800 ? (\n \n \n Anyone can create and name any BEP20 token on BSC, including creating fake versions of existing tokens and\n tokens that claim to represent projects that do not have a token.\n \n \n Similar to bscscan.com, this site automatically tracks analytics for all BEP20 tokens independent of token\n integrity. Please do your own research before interacting with any BEP20 token.\n \n
\n ) : (\n \n Anyone can create and name any BEP20 token on BSC, including creating fake versions of existing tokens and tokens\n that claim to represent projects that do not have a token. Similar to bscscan.com, this site automatically tracks\n analytics for all BEP20 tokens independent of token integrity. Please do your own research before interacting with\n any BEP20 token.\n \n )\n\n return (\n \n \n \n \n \n Token Safety Alert\n \n \n {textContent}\n {below800 ? (\n \n
\n \n View {type === 'token' ? 'token' : 'pair'} contract on bscscan.com\n \n \n
\n
\n setShow(false)}>\n I understand\n \n \n
\n ) : (\n \n \n \n View {type === 'token' ? 'token' : 'pair'} contract on bscscan.com\n \n \n setShow(false)}>\n I understand\n \n \n )}\n \n \n )\n}\n","import React, { useState } from 'react'\nimport 'feather-icons'\nimport { withRouter } from 'react-router-dom'\nimport { Text } from 'rebass'\nimport styled from 'styled-components'\nimport Link from '../components/Link'\nimport Panel from '../components/Panel'\nimport TokenLogo from '../components/TokenLogo'\nimport PairList from '../components/PairList'\nimport Loader from '../components/LocalLoader'\nimport { AutoRow, RowBetween, RowFixed } from '../components/Row'\nimport Column, { AutoColumn } from '../components/Column'\nimport { ButtonLight, ButtonDark } from '../components/ButtonStyled'\nimport TxnList from '../components/TxnList'\nimport TokenChart from '../components/TokenChart'\nimport { BasicLink } from '../components/Link'\nimport Search from '../components/Search'\nimport { formattedNum, formattedPercent, getPoolLink, getSwapLink, localNumber } from '../utils'\nimport { useTokenData, useTokenTransactions, useTokenPairs } from '../contexts/TokenData'\nimport { TYPE, ThemedBackground } from '../Theme'\nimport { transparentize } from 'polished'\nimport { useColor } from '../hooks'\nimport CopyHelper from '../components/Copy'\nimport { useMedia } from 'react-use'\nimport { useDataForList } from '../contexts/PairData'\nimport { useEffect } from 'react'\nimport Warning from '../components/Warning'\nimport { usePathDismissed, useSavedTokens } from '../contexts/LocalStorage'\nimport { Hover, PageWrapper, ContentWrapper, StyledIcon } from '../components'\nimport { PlusCircle, Bookmark } from 'react-feather'\nimport FormattedName from '../components/FormattedName'\nimport { useListedTokens } from '../contexts/Application'\n\nconst DashboardWrapper = styled.div`\n width: 100%;\n`\n\nconst PanelWrapper = styled.div`\n grid-template-columns: repeat(3, 1fr);\n grid-template-rows: max-content;\n gap: 6px;\n display: inline-grid;\n width: 100%;\n align-items: start;\n @media screen and (max-width: 1024px) {\n grid-template-columns: 1fr;\n align-items: stretch;\n > * {\n grid-column: 1 / 4;\n }\n\n > * {\n &:first-child {\n width: 100%;\n }\n }\n }\n`\n\nconst TokenDetailsLayout = styled.div`\n display: inline-grid;\n width: 100%;\n grid-template-columns: auto auto auto 1fr;\n column-gap: 30px;\n align-items: start;\n\n &:last-child {\n align-items: center;\n justify-items: end;\n }\n @media screen and (max-width: 1024px) {\n grid-template-columns: 1fr;\n align-items: stretch;\n > * {\n grid-column: 1 / 4;\n margin-bottom: 1rem;\n }\n\n &:last-child {\n align-items: start;\n justify-items: start;\n }\n }\n`\n\nconst WarningGrouping = styled.div`\n opacity: ${({ disabled }) => disabled && '0.4'};\n pointer-events: ${({ disabled }) => disabled && 'none'};\n`\n\nfunction TokenPage({ address, history }) {\n const {\n id,\n name,\n symbol,\n priceUSD,\n oneDayVolumeUSD,\n totalLiquidityUSD,\n volumeChangeUSD,\n oneDayVolumeUT,\n volumeChangeUT,\n priceChangeUSD,\n liquidityChangeUSD,\n oneDayTxns,\n txnChange,\n } = useTokenData(address)\n\n useEffect(() => {\n document.querySelector('body').scrollTo(0, 0)\n }, [])\n\n // detect color from token\n const backgroundColor = useColor(id, symbol)\n\n const allPairs = useTokenPairs(address)\n\n // pairs to show in pair list\n const fetchedPairsList = useDataForList(allPairs)\n\n // all transactions with this token\n const transactions = useTokenTransactions(address)\n\n // price\n const price = priceUSD ? formattedNum(priceUSD, true) : ''\n const priceChange = priceChangeUSD ? formattedPercent(priceChangeUSD) : ''\n\n // volume\n const volume =\n oneDayVolumeUSD || oneDayVolumeUSD === 0\n ? formattedNum(oneDayVolumeUSD === 0 ? oneDayVolumeUT : oneDayVolumeUSD, true)\n : oneDayVolumeUSD === 0\n ? '$0'\n : '-'\n\n // mark if using untracked volume\n const [usingUtVolume, setUsingUtVolume] = useState(false)\n useEffect(() => {\n setUsingUtVolume(oneDayVolumeUSD === 0 ? true : false)\n }, [oneDayVolumeUSD])\n\n const volumeChange = formattedPercent(!usingUtVolume ? volumeChangeUSD : volumeChangeUT)\n\n // liquidity\n const liquidity = totalLiquidityUSD ? formattedNum(totalLiquidityUSD, true) : totalLiquidityUSD === 0 ? '$0' : '-'\n const liquidityChange = formattedPercent(liquidityChangeUSD)\n\n // transactions\n const txnChangeFormatted = formattedPercent(txnChange)\n\n const below1080 = useMedia('(max-width: 1080px)')\n const below800 = useMedia('(max-width: 800px)')\n const below600 = useMedia('(max-width: 600px)')\n const below500 = useMedia('(max-width: 500px)')\n\n // format for long symbol\n const LENGTH = below1080 ? 10 : 16\n const formattedSymbol = symbol?.length > LENGTH ? symbol.slice(0, LENGTH) + '...' : symbol\n\n const [dismissed, markAsDismissed] = usePathDismissed(history.location.pathname)\n const [savedTokens, addToken] = useSavedTokens()\n const listedTokens = useListedTokens()\n\n useEffect(() => {\n window.scrollTo({\n behavior: 'smooth',\n top: 0,\n })\n }, [])\n\n return (\n \n \n\n \n \n \n \n \n {'Tokens '} → {symbol}\n {' '}\n \n \n \n ({address.slice(0, 8) + '...' + address.slice(36, 42)})\n \n \n \n {!below600 && }\n \n\n \n \n \n \n \n \n \n \n {' '}\n {formattedSymbol ? `(${formattedSymbol})` : ''}\n \n {' '}\n {!below1080 && (\n <>\n \n {price}\n \n {priceChange}\n >\n )}\n \n \n \n \n {!!!savedTokens[address] && !below800 ? (\n addToken(address, symbol)}>\n \n \n \n \n ) : !below1080 ? (\n \n \n \n ) : (\n <>>\n )}\n \n + Add Liquidity \n \n \n \n Trade\n \n \n \n \n \n\n <>\n \n {below1080 && price && (\n \n \n \n Price \n
\n \n \n {' '}\n \n {price}\n \n {priceChange} \n \n \n \n )}\n \n \n \n Total Liquidity \n
\n \n \n \n {liquidity}\n \n {liquidityChange} \n \n \n \n \n \n \n Volume (24hrs) {usingUtVolume && '(Untracked)'} \n
\n \n \n \n {volume}\n \n {volumeChange} \n \n \n \n\n \n \n \n Transactions (24hrs) \n
\n \n \n \n {oneDayTxns ? localNumber(oneDayTxns) : oneDayTxns === 0 ? 0 : '-'}\n \n {txnChangeFormatted} \n \n \n \n \n \n \n \n >\n\n \n \n Top Pairs\n \n \n \n {address && fetchedPairsList ? (\n \n ) : (\n \n )}\n \n \n Transactions
\n \n \n {transactions ? : }\n \n <>\n \n Token Information {' '}\n \n \n \n \n Symbol \n \n \n \n \n \n Name \n \n \n \n \n \n Address \n \n \n {address.slice(0, 8) + '...' + address.slice(36, 42)}\n \n \n \n \n \n \n View on bscscan.com ↗\n \n \n \n \n >\n \n \n \n \n )\n}\n\nexport default withRouter(TokenPage)\n","import React, { useState, useRef, useEffect } from 'react'\nimport styled from 'styled-components'\nimport { Area, XAxis, YAxis, ResponsiveContainer, Tooltip, AreaChart, BarChart, Bar } from 'recharts'\nimport { RowBetween, AutoRow } from '../Row'\n\nimport { toK, toNiceDate, toNiceDateYear, formattedNum, getTimeframe } from '../../utils'\nimport { OptionButton } from '../ButtonStyled'\nimport { darken } from 'polished'\nimport { usePairChartData, useHourlyRateData, usePairData } from '../../contexts/PairData'\nimport { timeframeOptions } from '../../constants'\nimport { useMedia } from 'react-use'\nimport { EmptyCard } from '..'\nimport DropdownSelect from '../DropdownSelect'\nimport CandleStickChart from '../CandleChart'\nimport LocalLoader from '../LocalLoader'\nimport { useDarkModeManager } from '../../contexts/LocalStorage'\n\nconst ChartWrapper = styled.div`\n height: 100%;\n max-height: 340px;\n\n @media screen and (max-width: 600px) {\n min-height: 200px;\n }\n`\n\nconst OptionsRow = styled.div`\n display: flex;\n flex-direction: row;\n width: 100%;\n margin-bottom: 40px;\n`\n\nconst CHART_VIEW = {\n VOLUME: 'Volume',\n LIQUIDITY: 'Liquidity',\n RATE0: 'Rate 0',\n RATE1: 'Rate 1',\n}\n\nconst PairChart = ({ address, color, base0, base1 }) => {\n const [chartFilter, setChartFilter] = useState(CHART_VIEW.LIQUIDITY)\n\n const [timeWindow, setTimeWindow] = useState(timeframeOptions.ALL_TIME)\n\n const [darkMode] = useDarkModeManager()\n const textColor = darkMode ? 'white' : 'black'\n\n // update the width on a window resize\n const ref = useRef()\n const isClient = typeof window === 'object'\n const [width, setWidth] = useState(ref?.current?.container?.clientWidth)\n const [height, setHeight] = useState(ref?.current?.container?.clientHeight)\n useEffect(() => {\n if (!isClient) {\n return false\n }\n function handleResize() {\n setWidth(ref?.current?.container?.clientWidth ?? width)\n setHeight(ref?.current?.container?.clientHeight ?? height)\n }\n window.addEventListener('resize', handleResize)\n return () => window.removeEventListener('resize', handleResize)\n }, [height, isClient, width]) // Empty array ensures that effect is only run on mount and unmount\n\n // get data for pair, and rates\n const pairData = usePairData(address)\n let chartData = usePairChartData(address)\n const hourlyData = useHourlyRateData(address, timeWindow)\n const hourlyRate0 = hourlyData && hourlyData[0]\n const hourlyRate1 = hourlyData && hourlyData[1]\n\n // formatted symbols for overflow\n const formattedSymbol0 =\n pairData?.token0?.symbol.length > 6 ? pairData?.token0?.symbol.slice(0, 5) + '...' : pairData?.token0?.symbol\n const formattedSymbol1 =\n pairData?.token1?.symbol.length > 6 ? pairData?.token1?.symbol.slice(0, 5) + '...' : pairData?.token1?.symbol\n\n const below1600 = useMedia('(max-width: 1600px)')\n const below1080 = useMedia('(max-width: 1080px)')\n const below600 = useMedia('(max-width: 600px)')\n\n let utcStartTime = getTimeframe(timeWindow)\n chartData = chartData?.filter((entry) => entry.date >= utcStartTime)\n\n if (chartData && chartData.length === 0) {\n return (\n \n No historical data yet. {' '}\n \n )\n }\n\n /**\n * Used to format values on chart on scroll\n * Needs to be raw html for chart API to parse styles\n * @param {*} val\n */\n function valueFormatter(val) {\n if (chartFilter === CHART_VIEW.RATE0) {\n return (\n formattedNum(val) +\n `${formattedSymbol1}/${formattedSymbol0}`\n )\n }\n if (chartFilter === CHART_VIEW.RATE1) {\n return (\n formattedNum(val) +\n `${formattedSymbol0}/${formattedSymbol1}`\n )\n }\n }\n\n const aspect = below1080 ? 60 / 20 : below1600 ? 60 / 28 : 60 / 22\n\n return (\n \n {below600 ? (\n \n \n \n \n ) : (\n \n \n {\n setTimeWindow(timeframeOptions.ALL_TIME)\n setChartFilter(CHART_VIEW.LIQUIDITY)\n }}\n >\n Liquidity\n \n {\n setTimeWindow(timeframeOptions.ALL_TIME)\n setChartFilter(CHART_VIEW.VOLUME)\n }}\n >\n Volume\n \n {\n setTimeWindow(timeframeOptions.WEEK)\n setChartFilter(CHART_VIEW.RATE0)\n }}\n >\n {pairData.token0 ? formattedSymbol1 + '/' + formattedSymbol0 : '-'}\n \n {\n setTimeWindow(timeframeOptions.WEEK)\n setChartFilter(CHART_VIEW.RATE1)\n }}\n >\n {pairData.token0 ? formattedSymbol0 + '/' + formattedSymbol1 : '-'}\n \n \n \n setTimeWindow(timeframeOptions.WEEK)}\n >\n 1W\n \n setTimeWindow(timeframeOptions.MONTH)}\n >\n 1M\n \n setTimeWindow(timeframeOptions.ALL_TIME)}\n >\n All\n \n \n \n )}\n {chartFilter === CHART_VIEW.LIQUIDITY && (\n \n \n \n \n \n \n \n \n toNiceDate(tick)}\n dataKey=\"date\"\n tick={{ fill: textColor }}\n type={'number'}\n domain={['dataMin', 'dataMax']}\n />\n '$' + toK(tick)}\n axisLine={false}\n tickLine={false}\n interval=\"preserveEnd\"\n minTickGap={80}\n yAxisId={0}\n tickMargin={16}\n tick={{ fill: textColor }}\n />\n formattedNum(val, true)}\n labelFormatter={(label) => toNiceDateYear(label)}\n labelStyle={{ paddingTop: 4 }}\n contentStyle={{\n padding: '10px 14px',\n borderRadius: 10,\n borderColor: color,\n color: 'black',\n }}\n wrapperStyle={{ top: -70, left: -10 }}\n />\n \n \n \n )}\n\n {chartFilter === CHART_VIEW.RATE1 &&\n (hourlyRate1 ? (\n \n \n \n ) : (\n \n ))}\n\n {chartFilter === CHART_VIEW.RATE0 &&\n (hourlyRate0 ? (\n \n \n \n ) : (\n \n ))}\n\n {chartFilter === CHART_VIEW.VOLUME && (\n \n \n toNiceDate(tick)}\n dataKey=\"date\"\n tick={{ fill: textColor }}\n type={'number'}\n domain={['dataMin', 'dataMax']}\n />\n '$' + toK(tick)}\n tickLine={false}\n interval=\"preserveEnd\"\n orientation=\"right\"\n minTickGap={80}\n yAxisId={0}\n tick={{ fill: textColor }}\n />\n formattedNum(val, true)}\n labelFormatter={(label) => toNiceDateYear(label)}\n labelStyle={{ paddingTop: 4 }}\n contentStyle={{\n padding: '10px 14px',\n borderRadius: 10,\n borderColor: color,\n color: 'black',\n }}\n wrapperStyle={{ top: -70, left: -10 }}\n />\n \n \n \n )}\n \n )\n}\n\nexport default PairChart\n","import React, { useEffect, useState } from 'react'\nimport { withRouter } from 'react-router-dom'\nimport 'feather-icons'\nimport styled from 'styled-components'\nimport Panel from '../components/Panel'\nimport { PageWrapper, ContentWrapperLarge, StyledIcon } from '../components/index'\nimport { AutoRow, RowBetween, RowFixed } from '../components/Row'\nimport Column, { AutoColumn } from '../components/Column'\nimport { ButtonLight, ButtonDark } from '../components/ButtonStyled'\nimport PairChart from '../components/PairChart'\nimport Link from '../components/Link'\nimport TxnList from '../components/TxnList'\nimport Loader from '../components/LocalLoader'\nimport { BasicLink } from '../components/Link'\nimport Search from '../components/Search'\nimport { formattedNum, formattedPercent, getPoolLink, getSwapLink } from '../utils'\nimport { useColor } from '../hooks'\nimport { usePairData, usePairTransactions } from '../contexts/PairData'\nimport { TYPE, ThemedBackground } from '../Theme'\nimport { transparentize } from 'polished'\nimport CopyHelper from '../components/Copy'\nimport { useMedia } from 'react-use'\nimport DoubleTokenLogo from '../components/DoubleLogo'\nimport TokenLogo from '../components/TokenLogo'\nimport { Hover } from '../components'\nimport { useBnbPrice } from '../contexts/GlobalData'\nimport Warning from '../components/Warning'\nimport { usePathDismissed, useSavedPairs } from '../contexts/LocalStorage'\n\nimport { Bookmark, PlusCircle } from 'react-feather'\nimport FormattedName from '../components/FormattedName'\nimport { useListedTokens } from '../contexts/Application'\n\nconst DashboardWrapper = styled.div`\n width: 100%;\n`\n\nconst PanelWrapper = styled.div`\n grid-template-columns: repeat(3, 1fr);\n grid-template-rows: max-content;\n gap: 6px;\n display: inline-grid;\n width: 100%;\n align-items: start;\n @media screen and (max-width: 1024px) {\n grid-template-columns: 1fr;\n align-items: stretch;\n > * {\n grid-column: 1 / 4;\n }\n\n > * {\n &:first-child {\n width: 100%;\n }\n }\n }\n`\n\nconst TokenDetailsLayout = styled.div`\n display: inline-grid;\n width: 100%;\n grid-template-columns: auto auto auto auto 1fr;\n column-gap: 60px;\n align-items: start;\n\n &:last-child {\n align-items: center;\n justify-items: end;\n }\n @media screen and (max-width: 1024px) {\n grid-template-columns: 1fr;\n align-items: stretch;\n > * {\n grid-column: 1 / 4;\n margin-bottom: 1rem;\n }\n\n &:last-child {\n align-items: start;\n justify-items: start;\n }\n }\n`\n\nconst FixedPanel = styled(Panel)`\n width: fit-content;\n padding: 8px 12px;\n border-radius: 10px;\n\n :hover {\n cursor: pointer;\n background-color: ${({ theme }) => theme.bg2};\n }\n`\n\nconst HoverSpan = styled.span`\n :hover {\n cursor: pointer;\n opacity: 0.7;\n }\n`\n\nconst WarningGrouping = styled.div`\n opacity: ${({ disabled }) => disabled && '0.4'};\n pointer-events: ${({ disabled }) => disabled && 'none'};\n`\n\nfunction PairPage({ pairAddress, history }) {\n const {\n token0,\n token1,\n reserve0,\n reserve1,\n reserveUSD,\n trackedReserveUSD,\n oneDayVolumeUSD,\n volumeChangeUSD,\n oneDayVolumeUntracked,\n volumeChangeUntracked,\n liquidityChangeUSD,\n } = usePairData(pairAddress)\n\n useEffect(() => {\n document.querySelector('body').scrollTo(0, 0)\n }, [])\n\n const transactions = usePairTransactions(pairAddress)\n const backgroundColor = useColor(pairAddress)\n\n // liquidity\n const liquidity = trackedReserveUSD\n ? formattedNum(trackedReserveUSD, true)\n : reserveUSD\n ? formattedNum(reserveUSD, true)\n : '-'\n const liquidityChange = formattedPercent(liquidityChangeUSD)\n\n // mark if using untracked liquidity\n const [usingTracked, setUsingTracked] = useState(true)\n useEffect(() => {\n setUsingTracked(!trackedReserveUSD ? false : true)\n }, [trackedReserveUSD])\n\n // volume\t // volume\n const volume =\n oneDayVolumeUSD || oneDayVolumeUSD === 0\n ? formattedNum(oneDayVolumeUSD === 0 ? oneDayVolumeUntracked : oneDayVolumeUSD, true)\n : oneDayVolumeUSD === 0\n ? '$0'\n : '-'\n\n // mark if using untracked volume\n const [usingUtVolume, setUsingUtVolume] = useState(false)\n useEffect(() => {\n setUsingUtVolume(oneDayVolumeUSD === 0 ? true : false)\n }, [oneDayVolumeUSD])\n\n const volumeChange = formattedPercent(!usingUtVolume ? volumeChangeUSD : volumeChangeUntracked)\n\n // get fees\t // get fees\n const fees =\n oneDayVolumeUSD || oneDayVolumeUSD === 0\n ? usingUtVolume\n ? formattedNum(oneDayVolumeUntracked * 0.002, true)\n : formattedNum(oneDayVolumeUSD * 0.002, true)\n : '-'\n\n // token data for usd\n const [bnbPrice] = useBnbPrice()\n const token0USD =\n token0?.derivedBNB && bnbPrice ? formattedNum(parseFloat(token0.derivedBNB) * parseFloat(bnbPrice), true) : ''\n\n const token1USD =\n token1?.derivedBNB && bnbPrice ? formattedNum(parseFloat(token1.derivedBNB) * parseFloat(bnbPrice), true) : ''\n\n // rates\n const token0Rate = reserve0 && reserve1 ? formattedNum(reserve1 / reserve0) : '-'\n const token1Rate = reserve0 && reserve1 ? formattedNum(reserve0 / reserve1) : '-'\n\n // formatted symbols for overflow\n const formattedSymbol0 = token0?.symbol.length > 6 ? token0?.symbol.slice(0, 5) + '...' : token0?.symbol\n const formattedSymbol1 = token1?.symbol.length > 6 ? token1?.symbol.slice(0, 5) + '...' : token1?.symbol\n\n const below1080 = useMedia('(max-width: 1080px)')\n const below900 = useMedia('(max-width: 900px)')\n const below600 = useMedia('(max-width: 600px)')\n\n const [dismissed, markAsDismissed] = usePathDismissed(history.location.pathname)\n\n useEffect(() => {\n window.scrollTo({\n behavior: 'smooth',\n top: 0,\n })\n }, [])\n\n const [savedPairs, addPair] = useSavedPairs()\n\n const listedTokens = useListedTokens()\n\n return (\n \n \n \n \n \n \n \n {'Pairs '} → {token0?.symbol}-{token1?.symbol}\n \n {!below600 && }\n \n \n \n \n \n
\n \n {token0 && token1 && (\n \n )}{' '}\n \n {token0 && token1 ? (\n <>\n history.push(`/token/${token0?.id}`)}>{token0.symbol} \n - \n history.push(`/token/${token1?.id}`)}>\n {token1.symbol}\n {' '}\n Pair\n >\n ) : (\n ''\n )}\n \n \n \n
\n {!!!savedPairs[pairAddress] && !below1080 ? (\n addPair(pairAddress, token0.id, token1.id, token0.symbol, token1.symbol)}>\n \n \n \n \n ) : !below1080 ? (\n \n \n \n ) : (\n <>>\n )}\n\n \n + Add Liquidity \n \n \n \n Trade\n \n \n \n
\n \n \n history.push(`/token/${token0?.id}`)}>\n \n \n \n {token0 && token1\n ? `1 ${formattedSymbol0} = ${token0Rate} ${formattedSymbol1} ${\n parseFloat(token0?.derivedBNB) ? '(' + token0USD + ')' : ''\n }`\n : '-'}\n \n \n \n history.push(`/token/${token1?.id}`)}>\n \n \n \n {token0 && token1\n ? `1 ${formattedSymbol1} = ${token1Rate} ${formattedSymbol0} ${\n parseFloat(token1?.derivedBNB) ? '(' + token1USD + ')' : ''\n }`\n : '-'}\n \n \n \n \n <>\n {!below1080 && Pair Stats }\n \n \n \n \n Total Liquidity {!usingTracked ? '(Untracked)' : ''} \n
\n \n \n \n {liquidity}\n \n {liquidityChange} \n \n \n \n \n \n \n Volume (24hrs) {usingUtVolume && '(Untracked)'} \n
\n \n \n \n {volume}\n \n {volumeChange} \n \n \n \n \n \n \n Fees (24hrs) \n
\n \n \n \n {fees}\n \n {volumeChange} \n \n \n \n\n \n \n \n Pooled Tokens \n
\n \n history.push(`/token/${token0?.id}`)} fade={true}>\n \n \n \n \n {reserve0 ? formattedNum(reserve0) : ''}{' '}\n \n \n \n \n \n history.push(`/token/${token1?.id}`)} fade={true}>\n \n \n \n \n {reserve1 ? formattedNum(reserve1) : ''}{' '}\n \n \n \n \n \n \n \n \n \n \n \n \n Transactions\n {' '}\n \n {transactions ? : }\n \n \n Pair Information {' '}\n \n \n \n \n Pair Name \n \n \n \n -\n \n \n \n \n \n Pair Address \n \n \n {pairAddress.slice(0, 6) + '...' + pairAddress.slice(38, 42)}\n \n \n \n \n \n \n \n {' '}\n Address \n \n \n \n \n {token0 && token0.id.slice(0, 6) + '...' + token0.id.slice(38, 42)}\n \n \n \n \n \n \n \n {' '}\n Address \n \n \n \n \n {token1 && token1.id.slice(0, 6) + '...' + token1.id.slice(38, 42)}\n \n \n \n \n \n \n View on bscscan.com ↗\n \n \n \n \n >\n \n \n \n \n )\n}\n\nexport default withRouter(PairPage)\n","import React, { useMemo, useEffect, useCallback } from 'react'\nimport styled from 'styled-components'\nimport { useUserTransactions } from '../contexts/User'\nimport TxnList from '../components/TxnList'\nimport Panel from '../components/Panel'\nimport { formattedNum } from '../utils'\nimport { AutoRow, RowBetween } from '../components/Row'\nimport { AutoColumn } from '../components/Column'\nimport { TYPE } from '../Theme'\nimport { PageWrapper, ContentWrapper, StyledIcon } from '../components'\nimport { Bookmark } from 'react-feather'\nimport Link from '../components/Link'\nimport { BasicLink } from '../components/Link'\nimport { useMedia } from 'react-use'\nimport Search from '../components/Search'\nimport { useSavedAccounts } from '../contexts/LocalStorage'\n\nconst AccountWrapper = styled.div`\n background-color: rgba(255, 255, 255, 0.2);\n padding: 6px 16px;\n border-radius: 100px;\n display: flex;\n align-items: center;\n justify-content: center;\n`\n\nconst Header = styled.div``\n\nconst DashboardWrapper = styled.div`\n width: 100%;\n`\n\nfunction AccountPage({ account }) {\n // get data for this account\n const transactions = useUserTransactions(account)\n\n // get data for user stats\n const transactionCount = transactions?.swaps?.length + transactions?.burns?.length + transactions?.mints?.length\n\n // get derived totals\n let totalSwappedUSD = useMemo(() => {\n return transactions?.swaps\n ? transactions?.swaps.reduce((total, swap) => {\n return total + parseFloat(swap.amountUSD)\n }, 0)\n : 0\n }, [transactions])\n\n useEffect(() => {\n window.scrollTo({\n behavior: 'smooth',\n top: 0,\n })\n }, [])\n\n const below600 = useMedia('(max-width: 600px)')\n\n // adding/removing account from saved accounts\n const [savedAccounts, addAccount, removeAccount] = useSavedAccounts()\n const isBookmarked = savedAccounts.includes(account)\n const handleBookmarkClick = useCallback(() => {\n ;(isBookmarked ? removeAccount : addAccount)(account)\n }, [account, isBookmarked, addAccount, removeAccount])\n\n return (\n \n \n \n \n {'Accounts '} →{' '}\n \n {' '}\n {account?.slice(0, 42)}{' '}\n \n \n {!below600 && }\n \n \n \n \n {account?.slice(0, 6) + '...' + account?.slice(38, 42)} \n \n View on bscscan.com \n \n \n \n \n \n \n \n \n \n \n \n Wallet Stats\n {' '}\n \n \n \n {totalSwappedUSD ? formattedNum(totalSwappedUSD, true) : '-'} \n Total Value Swapped \n \n \n \n {totalSwappedUSD ? formattedNum(totalSwappedUSD * 0.002, true) : '-'}\n \n Total Fees Paid \n \n \n {transactionCount ? transactionCount : '-'} \n Total Transactions \n \n \n \n \n Transactions\n {' '}\n \n \n \n \n \n \n )\n}\n\nexport default AccountPage\n","import React, { useEffect } from 'react'\nimport 'feather-icons'\n\nimport TopTokenList from '../components/TokenList'\nimport { TYPE } from '../Theme'\nimport Panel from '../components/Panel'\nimport { useAllTokenData } from '../contexts/TokenData'\nimport { PageWrapper, FullWrapper } from '../components'\nimport { RowBetween } from '../components/Row'\nimport Search from '../components/Search'\nimport { useMedia } from 'react-use'\n\nfunction AllTokensPage() {\n const allTokens = useAllTokenData()\n\n useEffect(() => {\n window.scrollTo(0, 0)\n }, [])\n\n const below600 = useMedia('(max-width: 800px)')\n\n return (\n \n \n \n Top Tokens \n {!below600 && }\n \n \n \n \n \n \n )\n}\n\nexport default AllTokensPage\n","import React, { useEffect } from 'react'\nimport 'feather-icons'\n\nimport { TYPE } from '../Theme'\nimport Panel from '../components/Panel'\nimport { useAllPairData } from '../contexts/PairData'\nimport PairList from '../components/PairList'\nimport { PageWrapper, FullWrapper } from '../components'\nimport { RowBetween } from '../components/Row'\nimport Search from '../components/Search'\nimport { useMedia } from 'react-use'\n\nfunction AllPairsPage() {\n const allPairs = useAllPairData()\n\n useEffect(() => {\n window.scrollTo(0, 0)\n }, [])\n\n const below800 = useMedia('(max-width: 800px)')\n\n return (\n \n \n \n Top Pairs \n {!below800 && }\n \n \n \n \n \n \n )\n}\n\nexport default AllPairsPage\n","import React, { useState } from 'react'\nimport 'feather-icons'\nimport { withRouter } from 'react-router-dom'\nimport styled from 'styled-components'\nimport { ButtonLight, ButtonFaded } from '../ButtonStyled'\nimport { AutoRow, RowBetween } from '../Row'\nimport { isAddress } from '../../utils'\nimport { useSavedAccounts } from '../../contexts/LocalStorage'\nimport { AutoColumn } from '../Column'\nimport { TYPE } from '../../Theme'\nimport { Hover, StyledIcon } from '..'\nimport Panel from '../Panel'\nimport { Divider } from '..'\nimport { Flex } from 'rebass'\n\nimport { X } from 'react-feather'\n\nconst Wrapper = styled.div`\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: flex-end;\n width: 100%;\n border-radius: 12px;\n`\n\nconst Input = styled.input`\n position: relative;\n display: flex;\n align-items: center;\n width: 100%;\n white-space: nowrap;\n background: none;\n border: none;\n outline: none;\n padding: 12px 16px;\n border-radius: 12px;\n color: ${({ theme }) => theme.text1};\n background-color: ${({ theme }) => theme.bg1};\n font-size: 16px;\n margin-right: 1rem;\n border: 1px solid ${({ theme }) => theme.bg3};\n\n ::placeholder {\n color: ${({ theme }) => theme.text3};\n font-size: 14px;\n }\n\n @media screen and (max-width: 640px) {\n ::placeholder {\n font-size: 1rem;\n }\n }\n`\n\nconst AccountLink = styled.span`\n display: flex;\n cursor: pointer;\n color: ${({ theme }) => theme.link};\n font-size: 14px;\n font-weight: 500;\n`\n\nconst DashGrid = styled.div`\n display: grid;\n grid-gap: 1em;\n grid-template-columns: 1fr;\n grid-template-areas: 'account';\n padding: 0 4px;\n\n > * {\n justify-content: flex-end;\n }\n`\n\nfunction AccountSearch({ history, small }) {\n const [accountValue, setAccountValue] = useState()\n const [savedAccounts, addAccount, removeAccount] = useSavedAccounts()\n\n function handleAccountSearch() {\n if (isAddress(accountValue)) {\n history.push('/account/' + accountValue)\n if (!savedAccounts.includes(accountValue)) {\n addAccount(accountValue)\n }\n }\n }\n\n return (\n \n {!small && (\n <>\n \n \n {\n setAccountValue(e.target.value)\n }}\n />\n \n Load Account Details \n \n >\n )}\n\n \n {!small && (\n \n \n Saved Accounts \n \n \n {savedAccounts?.length > 0 ? (\n savedAccounts.map((account) => {\n return (\n \n history.push('/account/' + account)}\n >\n {account?.slice(0, 42)} \n {\n e.stopPropagation()\n removeAccount(account)\n }}\n >\n \n \n \n \n \n \n )\n })\n ) : (\n No saved accounts \n )}\n \n )}\n\n {small && (\n <>\n {'Accounts'} \n {savedAccounts?.length > 0 ? (\n savedAccounts.map((account) => {\n return (\n \n history.push('/account/' + account)}>\n {small ? (\n {account?.slice(0, 6) + '...' + account?.slice(38, 42)} \n ) : (\n {account?.slice(0, 42)} \n )}\n \n removeAccount(account)}>\n \n \n \n \n \n )\n })\n ) : (\n No pinned wallets \n )}\n >\n )}\n \n \n )\n}\n\nexport default withRouter(AccountSearch)\n","import React from 'react'\nimport { withRouter } from 'react-router-dom'\nimport styled from 'styled-components'\nimport { RowBetween, RowFixed } from '../Row'\nimport { AutoColumn } from '../Column'\nimport { TYPE } from '../../Theme'\nimport { useSavedTokens, useSavedPairs } from '../../contexts/LocalStorage'\nimport { Hover } from '..'\nimport TokenLogo from '../TokenLogo'\nimport AccountSearch from '../AccountSearch'\nimport { Bookmark, ChevronRight, X } from 'react-feather'\nimport { ButtonFaded } from '../ButtonStyled'\nimport FormattedName from '../FormattedName'\n\nconst RightColumn = styled.div`\n position: fixed;\n right: 0;\n top: 0px;\n height: 100vh;\n width: ${({ open }) => (open ? '160px' : '23px')};\n padding: 1.25rem;\n border-left: ${({ theme, open }) => '1px solid' + theme.bg3};\n background-color: ${({ theme }) => theme.bg1};\n z-index: 9999;\n overflow: auto;\n :hover {\n cursor: pointer;\n }\n`\n\nconst SavedButton = styled(RowBetween)`\n padding-bottom: ${({ open }) => open && '20px'};\n border-bottom: ${({ theme, open }) => open && '1px solid' + theme.bg3};\n margin-bottom: ${({ open }) => open && '1.25rem'};\n\n :hover {\n cursor: pointer;\n }\n`\n\nconst ScrollableDiv = styled(AutoColumn)`\n overflow: auto;\n padding-bottom: 60px;\n`\n\nconst StyledIcon = styled.div`\n color: ${({ theme }) => theme.text2};\n`\n\nfunction PinnedData({ history, open, setSavedOpen }) {\n const [savedPairs, , removePair] = useSavedPairs()\n const [savedTokens, , removeToken] = useSavedTokens()\n\n return !open ? (\n setSavedOpen(true)}>\n \n \n \n \n \n \n ) : (\n \n setSavedOpen(false)} open={open}>\n \n \n \n \n Saved \n \n \n \n \n \n \n \n \n Pinned Pairs \n {Object.keys(savedPairs).filter((key) => {\n return !!savedPairs[key]\n }).length > 0 ? (\n Object.keys(savedPairs)\n .filter((address) => {\n return !!savedPairs[address]\n })\n .map((address) => {\n const pair = savedPairs[address]\n return (\n \n history.push('/pair/' + address)}>\n \n \n \n \n \n \n removePair(pair.address)}>\n \n \n \n \n \n )\n })\n ) : (\n Pinned pairs will appear here. \n )}\n \n \n Pinned Tokens \n {Object.keys(savedTokens).filter((key) => {\n return !!savedTokens[key]\n }).length > 0 ? (\n Object.keys(savedTokens)\n .filter((address) => {\n return !!savedTokens[address]\n })\n .map((address) => {\n const token = savedTokens[address]\n return (\n \n history.push('/token/' + address)}>\n \n \n \n \n \n \n \n removeToken(address)}>\n \n \n \n \n \n )\n })\n ) : (\n Pinned tokens will appear here. \n )}\n \n \n \n )\n}\n\nexport default withRouter(PinnedData)\n","import React from 'react'\nimport { useHistory } from 'react-router-dom'\nimport styled from 'styled-components'\n\nimport { Flex } from 'rebass'\nimport Link from '../Link'\nimport { RowFixed } from '../Row'\nimport Logo from '../../assets/logo-white.png'\n\nconst TitleWrapper = styled.div`\n text-decoration: none;\n\n &:hover {\n cursor: pointer;\n }\n\n z-index: 10;\n`\n\nconst UniIcon = styled(Link)`\n transition: transform 0.3s ease;\n :hover {\n transform: rotate(-5deg);\n }\n`\n\nexport default function Title() {\n const history = useHistory()\n\n return (\n history.push('/')}>\n \n \n history.push('/')}>\n \n \n \n \n \n )\n}\n","import React from 'react'\nimport styled from 'styled-components'\nimport { Sun, Moon } from 'react-feather'\n\nconst IconWrapper = styled.div<{ isActive?: boolean }>`\n opacity: ${({ isActive }) => (isActive ? 0.8 : 0.4)};\n\n :hover {\n opacity: 1;\n }\n`\n\nconst StyledToggle = styled.div`\n display: flex;\n width: fit-content;\n cursor: pointer;\n text-decoration: none;\n margin-top: 1rem;\n color: white;\n\n :hover {\n text-decoration: none;\n }\n`\n\nexport interface ToggleProps {\n isActive: boolean\n toggle: () => void\n}\n\nexport default function Toggle({ isActive, toggle }: ToggleProps) {\n return (\n \n \n \n \n \n \n {' / '} \n \n \n \n \n \n \n )\n}\n","import React from 'react'\nimport styled from 'styled-components'\nimport { AutoColumn } from '../Column'\nimport Title from '../Title'\nimport { BasicLink } from '../Link'\nimport { useMedia } from 'react-use'\nimport { transparentize } from 'polished'\nimport { TYPE } from '../../Theme'\nimport { withRouter } from 'react-router-dom'\nimport { TrendingUp, List, PieChart, Disc } from 'react-feather'\nimport Link from '../Link'\nimport { useSessionStart } from '../../contexts/Application'\nimport { useDarkModeManager } from '../../contexts/LocalStorage'\nimport Toggle from '../Toggle'\n\nconst Wrapper = styled.div`\n height: ${({ isMobile }) => (isMobile ? 'initial' : '100vh')};\n background-color: ${({ theme }) => transparentize(0.4, theme.bg1)};\n color: ${({ theme }) => theme.text1};\n padding: 0.5rem 0.5rem 0.5rem 0.75rem;\n position: sticky;\n top: 0px;\n z-index: 9999;\n box-sizing: border-box;\n background: linear-gradient(193.68deg, #1b1c22 0.68%, #000000 100.48%);\n color: ${({ theme }) => theme.bg2};\n\n @media screen and (max-width: 800px) {\n grid-template-columns: 1fr;\n position: relative;\n }\n\n @media screen and (max-width: 600px) {\n padding: 1rem;\n }\n`\n\nconst Option = styled.div`\n font-weight: 500;\n font-size: 14px;\n opacity: ${({ activeText }) => (activeText ? 1 : 0.6)};\n color: ${({ theme }) => theme.white};\n display: flex;\n :hover {\n opacity: 1;\n }\n`\n\nconst DesktopWrapper = styled.div`\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n height: 100vh;\n`\n\nconst MobileWrapper = styled.div`\n display: flex;\n justify-content: space-between;\n align-items: center;\n`\n\nconst HeaderText = styled.div`\n margin-right: 0.75rem;\n font-size: 0.825rem;\n font-weight: 500;\n display: inline-box;\n display: -webkit-inline-box;\n opacity: 0.8;\n :hover {\n opacity: 1;\n }\n a {\n color: ${({ theme }) => theme.white};\n }\n`\n\nconst Polling = styled.div`\n position: fixed;\n display: flex;\n left: 0;\n bottom: 0;\n padding: 1rem;\n color: white;\n opacity: 0.4;\n transition: opacity 0.25s ease;\n :hover {\n opacity: 1;\n }\n`\nconst PollingDot = styled.div`\n width: 8px;\n height: 8px;\n min-height: 8px;\n min-width: 8px;\n margin-right: 0.5rem;\n margin-top: 3px;\n border-radius: 50%;\n background-color: ${({ theme }) => theme.green1};\n`\n\nfunction SideNav({ history }) {\n const below1080 = useMedia('(max-width: 1080px)')\n\n const below1180 = useMedia('(max-width: 1180px)')\n\n const seconds = useSessionStart()\n\n const [isDark, toggleDarkMode] = useDarkModeManager()\n\n return (\n \n {!below1080 ? (\n \n \n \n {!below1080 && (\n \n \n \n \n Overview\n \n \n \n \n \n Tokens\n \n \n \n \n \n Pairs\n \n \n\n \n \n
\n Accounts\n \n \n \n )}\n \n \n \n \n Neverswap\n \n \n \n \n Docs\n \n \n \n \n Twitter\n \n \n \n \n {!below1180 && (\n \n \n \n \n Updated {!!seconds ? seconds + 's' : '-'} ago \n \n \n \n )}\n \n ) : (\n \n \n \n )}\n \n )\n}\n\nexport default withRouter(SideNav)\n","import React, { useEffect } from 'react'\nimport 'feather-icons'\nimport { withRouter } from 'react-router-dom'\nimport { TYPE } from '../Theme'\nimport { PageWrapper, FullWrapper } from '../components'\nimport styled from 'styled-components'\nimport AccountSearch from '../components/AccountSearch'\nimport { RowBetween } from '../components/Row'\nimport { useMedia } from 'react-use'\nimport Search from '../components/Search'\n\nconst AccountWrapper = styled.div`\n @media screen and (max-width: 600px) {\n width: 100%;\n }\n`\n\nfunction AccountLookup() {\n // scroll to top\n useEffect(() => {\n window.scrollTo(0, 0)\n }, [])\n\n const below600 = useMedia('(max-width: 600px)')\n\n return (\n \n \n \n Wallet analytics \n {!below600 && }\n \n \n \n \n \n \n )\n}\n\nexport default withRouter(AccountLookup)\n","import React, { useState } from 'react'\nimport styled from 'styled-components'\nimport { ApolloProvider } from 'react-apollo'\nimport { client } from './apollo/client'\nimport { Route, Switch, BrowserRouter, Redirect } from 'react-router-dom'\nimport GlobalPage from './pages/GlobalPage'\nimport TokenPage from './pages/TokenPage'\nimport PairPage from './pages/PairPage'\nimport { useGlobalData, useGlobalChartData } from './contexts/GlobalData'\nimport { isAddress } from './utils'\nimport AccountPage from './pages/AccountPage'\nimport AllTokensPage from './pages/AllTokensPage'\nimport AllPairsPage from './pages/AllPairsPage'\nimport PinnedData from './components/PinnedData'\n\nimport SideNav from './components/SideNav'\nimport AccountLookup from './pages/AccountLookup'\nimport { OVERVIEW_TOKEN_BLACKLIST, PAIR_BLACKLIST } from './constants'\nimport LocalLoader from './components/LocalLoader'\nimport { useLatestBlocks } from './contexts/Application'\n\nconst AppWrapper = styled.div`\n position: relative;\n width: 100%;\n`\nconst ContentWrapper = styled.div`\n display: grid;\n grid-template-columns: ${({ open }) => (open ? '220px 1fr 200px' : '220px 1fr 64px')};\n\n @media screen and (max-width: 1400px) {\n grid-template-columns: 220px 1fr;\n }\n\n @media screen and (max-width: 1080px) {\n grid-template-columns: 1fr;\n max-width: 100vw;\n overflow: hidden;\n grid-gap: 0;\n }\n`\n\nconst Right = styled.div`\n position: fixed;\n right: 0;\n bottom: 0rem;\n z-index: 99;\n width: ${({ open }) => (open ? '220px' : '64px')};\n height: ${({ open }) => (open ? 'fit-content' : '64px')};\n overflow: auto;\n background-color: ${({ theme }) => theme.bg1};\n @media screen and (max-width: 1400px) {\n display: none;\n }\n`\n\nconst Center = styled.div`\n height: 100%;\n z-index: 9999;\n transition: width 0.25s ease;\n background-color: ${({ theme }) => theme.onlyLight};\n`\n\nconst WarningWrapper = styled.div`\n width: 100%;\n display: flex;\n justify-content: center;\n`\n\nconst WarningBanner = styled.div`\n background-color: ${({ theme }) => theme.bg1};\n padding: 1.5rem;\n color: white;\n width: 100%;\n text-align: center;\n font-weight: 500;\n`\n\n/**\n * Wrap the component with the header and sidebar pinned tab\n */\nconst LayoutWrapper = ({ children, savedOpen, setSavedOpen }) => {\n return (\n <>\n \n \n {children} \n \n \n \n \n >\n )\n}\n\nconst BLOCK_DIFFERENCE_THRESHOLD = 30\n\nfunction App() {\n const [savedOpen, setSavedOpen] = useState(false)\n\n const globalData = useGlobalData()\n const globalChartData = useGlobalChartData()\n const [latestBlock, headBlock] = useLatestBlocks()\n\n // show warning\n const showWarning = headBlock && latestBlock ? headBlock - latestBlock > BLOCK_DIFFERENCE_THRESHOLD : false\n\n return (\n \n \n {showWarning && (\n \n \n {`The data on this site has only synced to BSC Chain block ${latestBlock} (out of ${headBlock}). Please check back soon.`}\n \n \n )}\n {globalData &&\n Object.keys(globalData).length > 0 &&\n globalChartData &&\n Object.keys(globalChartData).length > 0 ? (\n \n \n {\n if (OVERVIEW_TOKEN_BLACKLIST.includes(match.params.tokenAddress.toLowerCase())) {\n return \n }\n if (isAddress(match.params.tokenAddress.toLowerCase())) {\n return (\n \n \n \n )\n } else {\n return \n }\n }}\n />\n {\n if (PAIR_BLACKLIST.includes(match.params.pairAddress.toLowerCase())) {\n return \n }\n if (isAddress(match.params.pairAddress.toLowerCase())) {\n return (\n \n \n \n )\n } else {\n return \n }\n }}\n />\n {\n if (isAddress(match.params.accountAddress.toLowerCase())) {\n return (\n \n \n \n )\n } else {\n return \n }\n }}\n />\n\n \n \n \n \n \n\n \n \n \n \n \n\n \n \n \n \n \n\n \n \n \n \n \n\n \n \n \n ) : (\n \n )}\n \n \n )\n}\n\nexport default App\n","import React from 'react'\nimport ReactDOM from 'react-dom'\nimport ThemeProvider, { GlobalStyle } from './Theme'\nimport LocalStorageContextProvider, { Updater as LocalStorageContextUpdater } from './contexts/LocalStorage'\nimport TokenDataContextProvider, { Updater as TokenDataContextUpdater } from './contexts/TokenData'\nimport GlobalDataContextProvider from './contexts/GlobalData'\nimport PairDataContextProvider, { Updater as PairDataContextUpdater } from './contexts/PairData'\nimport ApplicationContextProvider from './contexts/Application'\nimport UserContextProvider from './contexts/User'\nimport App from './App'\n\nfunction ContextProviders({ children }) {\n return (\n \n \n \n \n \n {children} \n \n \n \n \n \n )\n}\n\nfunction Updaters() {\n return (\n <>\n \n \n \n >\n )\n}\n\nReactDOM.render(\n \n \n \n <>\n \n \n >\n \n ,\n document.getElementById('root')\n)\n"],"sourceRoot":""}