diff --git a/src/App.tsx b/src/App.tsx
index 1a48c6738..2a144e82a 100755
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -16,6 +16,7 @@ import {
PoolsPage,
SwapPage,
AnalyticsTokenDetails,
+ AnalyticsPairDetails,
} from 'pages';
import { PageLayout } from 'layouts';
import { getLibrary } from 'utils';
@@ -133,6 +134,11 @@ const App: React.FC = () => {
+
+
+
+
+
diff --git a/src/apollo/client.js b/src/apollo/client.js
index d0554476d..a1df72408 100755
--- a/src/apollo/client.js
+++ b/src/apollo/client.js
@@ -18,6 +18,14 @@ export const healthClient = new ApolloClient({
shouldBatch: true,
});
+export const txClient = new ApolloClient({
+ link: new HttpLink({
+ uri: 'https://polygon.furadao.org/subgraphs/name/quickswap',
+ }),
+ cache: new InMemoryCache(),
+ shouldBatch: true,
+});
+
export const v1Client = new ApolloClient({
link: new HttpLink({
uri: 'https://api.thegraph.com/subgraphs/name/ianlapham/uniswap',
diff --git a/src/apollo/queries.ts b/src/apollo/queries.ts
index ec133668f..1547b89b6 100755
--- a/src/apollo/queries.ts
+++ b/src/apollo/queries.ts
@@ -127,10 +127,46 @@ export const TOKEN_CHART = gql`
}
`;
+export const PAIR_CHART = gql`
+ query pairDayDatas($pairAddress: Bytes!, $skip: Int!, $startTime: Int!) {
+ pairDayDatas(
+ first: 1000
+ skip: $skip
+ orderBy: date
+ orderDirection: asc
+ where: { pairAddress: $pairAddress, date_gt: $startTime }
+ ) {
+ id
+ date
+ dailyVolumeToken0
+ dailyVolumeToken1
+ dailyVolumeUSD
+ reserveUSD
+ }
+ }
+`;
+
+export const HOURLY_PAIR_RATES = (pairAddress: string, blocks: any[]) => {
+ let queryString = 'query blocks {';
+ queryString += blocks.map(
+ (block) => `
+ t${block.timestamp}: pair(id:"${pairAddress}", block: { number: ${block.number} }) {
+ token0Price
+ token1Price
+ }
+ `,
+ );
+
+ queryString += '}';
+ return gql(queryString);
+};
+
const PairFields = `
fragment PairFields on Pair {
id
trackedReserveETH
+ reserve0
+ reserve1
volumeUSD
reserveUSD
totalSupply
@@ -138,11 +174,13 @@ const PairFields = `
symbol
id
decimals
+ derivedETH
}
token1 {
symbol
id
decimals
+ derivedETH
}
}
`;
@@ -487,3 +525,88 @@ export const GET_BLOCKS: any = (timestamps: number[]) => {
queryString += '}';
return gql(queryString);
};
+
+export const FILTERED_TRANSACTIONS = gql`
+ query($allPairs: [Bytes]!) {
+ mints(
+ first: 20
+ where: { pair_in: $allPairs }
+ orderBy: timestamp
+ orderDirection: desc
+ ) {
+ transaction {
+ id
+ timestamp
+ }
+ pair {
+ token0 {
+ id
+ symbol
+ }
+ token1 {
+ id
+ symbol
+ }
+ }
+ to
+ liquidity
+ amount0
+ amount1
+ amountUSD
+ }
+ burns(
+ first: 20
+ where: { pair_in: $allPairs }
+ orderBy: timestamp
+ orderDirection: desc
+ ) {
+ transaction {
+ id
+ timestamp
+ }
+ pair {
+ token0 {
+ id
+ symbol
+ }
+ token1 {
+ id
+ symbol
+ }
+ }
+ sender
+ liquidity
+ amount0
+ amount1
+ amountUSD
+ }
+ swaps(
+ first: 30
+ where: { pair_in: $allPairs }
+ orderBy: timestamp
+ orderDirection: desc
+ ) {
+ transaction {
+ id
+ timestamp
+ }
+ id
+ pair {
+ token0 {
+ id
+ symbol
+ }
+ token1 {
+ id
+ symbol
+ }
+ }
+ amount0In
+ amount0Out
+ amount1In
+ amount1Out
+ amountUSD
+ to
+ }
+ }
+`;
diff --git a/src/components/CurrencySearchModal/CurrencySearch.tsx b/src/components/CurrencySearchModal/CurrencySearch.tsx
index 1a248ed51..3d6519a08 100755
--- a/src/components/CurrencySearchModal/CurrencySearch.tsx
+++ b/src/components/CurrencySearchModal/CurrencySearch.tsx
@@ -37,7 +37,7 @@ const useStyles = makeStyles(({ palette, breakpoints }) => ({
flexDirection: 'column',
background: palette.background.paper,
backdropFilter: 'blur(9.9px)',
- border: '1px solid #3e4252',
+ border: `1px solid ${palette.grey.A400}`,
[breakpoints.down('xs')]: {
height: '90vh',
},
diff --git a/src/components/FarmDualCard/FarmDualCard.tsx b/src/components/FarmDualCard/FarmDualCard.tsx
index 08bcda032..0e6faab1f 100755
--- a/src/components/FarmDualCard/FarmDualCard.tsx
+++ b/src/components/FarmDualCard/FarmDualCard.tsx
@@ -64,7 +64,7 @@ const useStyles = makeStyles(({ palette, breakpoints }) => ({
},
},
buttonToken: {
- backgroundColor: '#3e4252',
+ backgroundColor: palette.grey.A400,
borderRadius: '10px',
height: '50px',
display: 'flex',
diff --git a/src/components/FarmLPCard/FarmLPCard.tsx b/src/components/FarmLPCard/FarmLPCard.tsx
index 98ee490d5..57b5e4823 100755
--- a/src/components/FarmLPCard/FarmLPCard.tsx
+++ b/src/components/FarmLPCard/FarmLPCard.tsx
@@ -53,7 +53,7 @@ const useStyles = makeStyles(({ palette, breakpoints }) => ({
},
},
buttonToken: {
- backgroundColor: '#3e4252',
+ backgroundColor: palette.grey.A400,
borderRadius: '10px',
height: '50px',
display: 'flex',
diff --git a/src/components/FarmLPCard/FarmLPCardDetails.tsx b/src/components/FarmLPCard/FarmLPCardDetails.tsx
index 1f880192f..d77516fdb 100644
--- a/src/components/FarmLPCard/FarmLPCardDetails.tsx
+++ b/src/components/FarmLPCard/FarmLPCardDetails.tsx
@@ -60,7 +60,7 @@ const useStyles = makeStyles(({ palette, breakpoints }) => ({
},
},
buttonToken: {
- backgroundColor: '#3e4252',
+ backgroundColor: palette.grey.A400,
borderRadius: '10px',
height: '50px',
display: 'flex',
diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx
index 1e0677799..40587c6cd 100755
--- a/src/components/Header/Header.tsx
+++ b/src/components/Header/Header.tsx
@@ -134,7 +134,7 @@ const useStyles = makeStyles(({ palette, breakpoints }) => ({
},
},
accountDetails: {
- border: `solid 1px #3e4252`,
+ border: `solid 1px ${palette.grey.A400}`,
padding: '0 16px',
height: 36,
cursor: 'pointer',
diff --git a/src/components/PairsTable/PairsTable.tsx b/src/components/PairsTable/PairsTable.tsx
index e69136aff..18e26ef2f 100644
--- a/src/components/PairsTable/PairsTable.tsx
+++ b/src/components/PairsTable/PairsTable.tsx
@@ -1,5 +1,6 @@
import React from 'react';
import { Box, Typography, Divider } from '@material-ui/core';
+import { Link } from 'react-router-dom';
import { ChainId, Token } from '@uniswap/sdk';
import { getAddress } from '@ethersproject/address';
import { DoubleCurrencyLogo, CustomTable } from 'components';
@@ -102,12 +103,23 @@ const PairTable: React.FC = ({ data }) => {
)}
-
-
-
- {token0.symbol} / {token1.symbol}
-
-
+
+
+
+
+
+ {token0.symbol} / {token1.symbol}
+
+
+
+
= ({ data }) => {
const liquidity = pair.trackedReserveUSD
? pair.trackedReserveUSD
: pair.reserveUSD;
- const oneDayVolume = pair.oneDayVolumeUSD
- ? pair.oneDayVolumeUSD
- : pair.oneDayVolumeUntracked;
- const oneWeekVolume = pair.oneWeekVolumeUSD
- ? pair.oneWeekVolumeUSD
- : pair.oneWeekVolumeUntracked;
+ const oneDayVolume =
+ pair.oneDayVolumeUSD && !isNaN(pair.oneDayVolumeUSD)
+ ? pair.oneDayVolumeUSD
+ : pair.oneDayVolumeUntracked && !isNaN(pair.oneDayVolumeUntracked)
+ ? pair.oneDayVolumeUntracked
+ : 0;
+ const oneWeekVolume =
+ pair.oneWeekVolumeUSD && !isNaN(pair.oneWeekVolumeUSD)
+ ? pair.oneWeekVolumeUSD
+ : pair.oneWeekVolumeUntracked && !isNaN(pair.oneWeekVolumeUntracked)
+ ? pair.oneWeekVolumeUntracked
+ : 0;
const oneDayFee = (Number(oneDayVolume) * 0.003).toLocaleString();
return [
{
@@ -203,16 +221,23 @@ const PairTable: React.FC = ({ data }) => {
)}
-
-
-
- {token0.symbol} / {token1.symbol}
-
-
+
+
+
+
+
+ {token0.symbol} / {token1.symbol}
+
+
+
+
),
},
diff --git a/src/components/SyrupCard/SyrupCard.tsx b/src/components/SyrupCard/SyrupCard.tsx
index c15873147..a897e3d6b 100755
--- a/src/components/SyrupCard/SyrupCard.tsx
+++ b/src/components/SyrupCard/SyrupCard.tsx
@@ -230,7 +230,7 @@ const SyrupCard: React.FC<{ syrup: SyrupInfo }> = ({ syrup }) => {
= ({ data }) => {
to={`/analytics/token/${tokenCurrency.address}`}
style={{ textDecoration: 'none' }}
>
-
+
= ({ data }) => {
to={`/analytics/token/${tokenCurrency.address}`}
style={{ textDecoration: 'none' }}
>
-
+
({
+ priceChangeWrapper: {
+ height: 25,
+ padding: '0 12px',
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ borderRadius: 16,
+ },
+ mobileRow: {
+ width: '100%',
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ margin: '8px 0',
+ },
+}));
+
+interface TransactionsTableProps {
+ data: any[];
+}
+
+const headCells = (
+ txFilter: string,
+ setTxFilter: (txFilter: string) => void,
+) => [
+ {
+ id: 'description',
+ numeric: false,
+ label: (
+
+ setTxFilter('')}
+ >
+ All
+
+ setTxFilter('Swap')}
+ style={{ marginLeft: 12 }}
+ >
+ Swap
+
+ setTxFilter('Add')}
+ style={{ marginLeft: 12 }}
+ >
+ Add
+
+ setTxFilter('Remove')}
+ style={{ marginLeft: 12 }}
+ >
+ Remove
+
+
+ ),
+ sortDisabled: true,
+ },
+ {
+ id: 'totalvalue',
+ numeric: false,
+ label: 'Total Value',
+ sortKey: (item: any) => Number(item.amountUSD),
+ },
+ {
+ id: 'tokenamount1',
+ numeric: false,
+ label: 'Token Amount',
+ sortKey: (item: any) => Number(item.amount1),
+ },
+ {
+ id: 'tokenamount2',
+ numeric: false,
+ label: 'Token Amount',
+ sortKey: (item: any) => Number(item.amount0),
+ },
+ {
+ id: 'txn',
+ numeric: false,
+ label: 'TXN',
+ sortKey: (item: any) => item.transaction.id,
+ },
+ {
+ id: 'time',
+ numeric: false,
+ label: 'Time',
+ sortKey: (item: any) => Number(item.transaction.timestamp) * -1,
+ },
+];
+
+const TransactionsTable: React.FC = ({ data }) => {
+ const [txFilter, setTxFilter] = useState('');
+ const tokenHeadCells = headCells(txFilter, setTxFilter);
+ const classes = useStyles();
+ const { chainId } = useActiveWeb3React();
+ const { palette, breakpoints } = useTheme();
+ const isMobile = useMediaQuery(breakpoints.down('xs'));
+ const mobileHTML = (txn: any, index: number) => {
+ return (
+
+
+ {chainId ? (
+
+
+ {txn.type} {txn.pair.token0.symbol}{' '}
+ {txn.type === 'Swap' ? 'for' : 'and'} {txn.pair.token1.symbol}
+
+
+ ) : (
+
+ {txn.type} {txn.pair.token0.symbol}{' '}
+ {txn.type === 'Swap' ? 'for' : 'and'} {txn.pair.token1.symbol}
+
+ )}
+
+
+
+ Total Value
+
+ ${Number(txn.amountUSD).toLocaleString()}
+
+
+
+ Token Amount
+
+ {Number(txn.amount1) < 0.0001
+ ? '< 0.0001'
+ : Number(txn.amount1).toFixed(
+ Number(txn.amount1) < 1 ? 4 : 2,
+ )}{' '}
+ {txn.pair.token1.symbol}
+
+
+
+ Token Amount
+
+ {Number(txn.amount0) < 0.0001
+ ? '< 0.0001'
+ : Number(txn.amount0).toFixed(
+ Number(txn.amount0) < 1 ? 4 : 2,
+ )}{' '}
+ {txn.pair.token0.symbol}
+
+
+
+ TXN
+ {chainId ? (
+
+
+ {txn.transaction.id.substring(0, 6)}...
+ {txn.transaction.id.substring(txn.transaction.id.length - 4)}
+
+
+ ) : (
+
+ {txn.transaction.id.substring(0, 6)}...
+ {txn.transaction.id.substring(txn.transaction.id.length - 4)}
+
+ )}
+
+
+ Time
+
+ {moment(Number(txn.transaction.timestamp) * 1000).fromNow()}
+
+
+
+ );
+ };
+
+ const desktopHTML = (txn: any) => {
+ return [
+ {
+ html: chainId ? (
+
+
+ {txn.type} {txn.pair.token0.symbol}{' '}
+ {txn.type === 'Swap' ? 'for' : 'and'} {txn.pair.token1.symbol}
+
+
+ ) : (
+
+ {txn.type} {txn.pair.token0.symbol}{' '}
+ {txn.type === 'Swap' ? 'for' : 'and'} {txn.pair.token1.symbol}
+
+ ),
+ },
+ {
+ html: (
+
+ ${Number(txn.amountUSD).toLocaleString()}
+
+ ),
+ },
+ {
+ html: (
+
+ {Number(txn.amount1) < 0.0001
+ ? '< 0.0001'
+ : Number(txn.amount1).toFixed(
+ Number(txn.amount1) < 1 ? 4 : 2,
+ )}{' '}
+ {txn.pair.token1.symbol}
+
+ ),
+ },
+ {
+ html: (
+
+ {Number(txn.amount0) < 0.0001
+ ? '< 0.0001'
+ : Number(txn.amount0).toFixed(
+ Number(txn.amount0) < 1 ? 4 : 2,
+ )}{' '}
+ {txn.pair.token0.symbol}
+
+ ),
+ },
+ {
+ html: chainId ? (
+
+
+ {txn.transaction.id.substring(0, 6)}...
+ {txn.transaction.id.substring(txn.transaction.id.length - 4)}
+
+
+ ) : (
+
+ {txn.transaction.id.substring(0, 6)}...
+ {txn.transaction.id.substring(txn.transaction.id.length - 4)}
+
+ ),
+ },
+ {
+ html: (
+
+ {moment(Number(txn.transaction.timestamp) * 1000).fromNow()}
+
+ ),
+ },
+ ];
+ };
+
+ return (
+
+ {isMobile && (
+
+ setTxFilter('')}>
+
+ All
+
+
+ setTxFilter('Swap')}>
+
+ Swap
+
+
+ setTxFilter('Add')}>
+
+ Add
+
+
+ setTxFilter('Remove')}>
+
+ Remove
+
+
+
+ )}
+ 10}
+ headCells={tokenHeadCells}
+ rowsPerPage={10}
+ data={data.filter((item) =>
+ txFilter === '' ? true : item.type === txFilter,
+ )}
+ mobileHTML={mobileHTML}
+ desktopHTML={desktopHTML}
+ />
+
+ );
+};
+
+export default TransactionsTable;
diff --git a/src/components/TransactionsTable/index.ts b/src/components/TransactionsTable/index.ts
new file mode 100644
index 000000000..c7801e020
--- /dev/null
+++ b/src/components/TransactionsTable/index.ts
@@ -0,0 +1 @@
+export { default } from './TransactionsTable';
diff --git a/src/components/index.ts b/src/components/index.ts
index f8c86ac8e..43590fa9d 100755
--- a/src/components/index.ts
+++ b/src/components/index.ts
@@ -49,3 +49,4 @@ export { default as SwapTokenDetails } from './SwapTokenDetails';
export { default as TopMovers } from './TopMovers';
export { default as TokensTable } from './TokensTable';
export { default as PairTable } from './PairsTable';
+export { default as TransactionsTable } from './TransactionsTable';
diff --git a/src/constants/index.ts b/src/constants/index.ts
index 01ec5d925..9a1d277bf 100755
--- a/src/constants/index.ts
+++ b/src/constants/index.ts
@@ -1059,8 +1059,8 @@ export const KOM = new Token(
);
export const UST = new Token(
ChainId.MATIC,
- '0x692597b009d13C4049a947CAB2239b7d6517875F',
- 18,
+ '0xE6469Ba6D2fD6130788E0eA9C0a0515900563b59',
+ 6,
'UST',
'Wrapped UST Token',
);
@@ -1890,4 +1890,4 @@ export const BETTER_TRADE_LINK_THRESHOLD = new Percent(
// the Uniswap Default token list lives here
export const DEFAULT_TOKEN_LIST_URL =
- 'https://unpkg.com/quickswap-default-token-list@1.2.17/build/quickswap-default.tokenlist.json';
+ 'https://unpkg.com/quickswap-default-token-list@1.2.18/build/quickswap-default.tokenlist.json';
diff --git a/src/constants/lists.ts b/src/constants/lists.ts
index d499df16f..4650ca0d6 100755
--- a/src/constants/lists.ts
+++ b/src/constants/lists.ts
@@ -1,5 +1,5 @@
// the Quickswap Default token list lives here
export const DEFAULT_TOKEN_LIST_URL =
- 'https://unpkg.com/quickswap-default-token-list@1.2.17/build/quickswap-default.tokenlist.json';
+ 'https://unpkg.com/quickswap-default-token-list@1.2.18/build/quickswap-default.tokenlist.json';
export const DEFAULT_LIST_OF_LISTS: string[] = [DEFAULT_TOKEN_LIST_URL];
diff --git a/src/pages/AnalyticsPage/AnalyticsInfo.tsx b/src/pages/AnalyticsPage/AnalyticsInfo.tsx
index dce07df7f..8216282c4 100644
--- a/src/pages/AnalyticsPage/AnalyticsInfo.tsx
+++ b/src/pages/AnalyticsPage/AnalyticsInfo.tsx
@@ -1,10 +1,12 @@
import React, { useEffect } from 'react';
import { Box, Typography } from '@material-ui/core';
+import { useTheme } from '@material-ui/core/styles';
import { useGlobalData, useEthPrice } from 'state/application/hooks';
import { getEthPrice, getGlobalData } from 'utils';
import { Skeleton } from '@material-ui/lab';
const AnalyticsInfo: React.FC = () => {
+ const { palette } = useTheme();
const { ethPrice, updateEthPrice } = useEthPrice();
const { globalData, updateGlobalData } = useGlobalData();
useEffect(() => {
@@ -28,7 +30,7 @@ const AnalyticsInfo: React.FC = () => {
({
panel: {
- background: '#1b1d26',
+ background: palette.grey.A700,
borderRadius: 20,
},
volumeType: {
@@ -353,7 +353,9 @@ const AnalyticsOverview: React.FC = ({
setVolumeIndex(0)}
>
D
@@ -361,7 +363,9 @@ const AnalyticsOverview: React.FC = ({
setVolumeIndex(1)}
>
W
diff --git a/src/pages/AnalyticsPage/AnalyticsPage.tsx b/src/pages/AnalyticsPage/AnalyticsPage.tsx
index eae0442f1..1ad39640d 100755
--- a/src/pages/AnalyticsPage/AnalyticsPage.tsx
+++ b/src/pages/AnalyticsPage/AnalyticsPage.tsx
@@ -38,7 +38,7 @@ const useStyles = makeStyles(({ palette }) => ({
display: 'flex',
alignItems: 'center',
padding: '0 16px',
- background: '#1b1d26',
+ background: palette.grey.A700,
height: 46,
borderRadius: 10,
margin: '12px 0',
@@ -55,7 +55,7 @@ const useStyles = makeStyles(({ palette }) => ({
searchContent: {
position: 'absolute',
width: '100%',
- background: '#1b1d26',
+ background: palette.grey.A700,
borderRadius: 10,
padding: 12,
zIndex: 2,
@@ -332,7 +332,14 @@ const AnalyticsPage: React.FC = () => {
val.token1.decimals,
);
return (
-
+ history.push(`/analytics/pair/${val.id}`)}
+ >
({
+const useStyles = makeStyles(({ palette, breakpoints }) => ({
tokensFilter: {
cursor: 'pointer',
display: 'flex',
},
panel: {
- background: '#1b1d26',
+ background: palette.grey.A700,
borderRadius: 20,
padding: 24,
[breakpoints.down('xs')]: {
diff --git a/src/pages/AnalyticsPage/AnalyticsTokens.tsx b/src/pages/AnalyticsPage/AnalyticsTokens.tsx
index 53feb26d2..3426a0c82 100644
--- a/src/pages/AnalyticsPage/AnalyticsTokens.tsx
+++ b/src/pages/AnalyticsPage/AnalyticsTokens.tsx
@@ -6,14 +6,14 @@ import { useTopTokens, useBookmarkTokens } from 'state/application/hooks';
import { getEthPrice, getTopTokens } from 'utils';
import { Skeleton } from '@material-ui/lab';
-const useStyles = makeStyles(({ breakpoints }) => ({
+const useStyles = makeStyles(({ palette, breakpoints }) => ({
tokensFilter: {
cursor: 'pointer',
display: 'flex',
margin: '8px 16px 8px 0',
},
panel: {
- background: '#1b1d26',
+ background: palette.grey.A700,
borderRadius: 20,
padding: 24,
[breakpoints.down('xs')]: {
@@ -57,7 +57,7 @@ const AnalyticsTokens: React.FC = () => {
return (
<>
-
+
({
+ panel: {
+ background: palette.grey.A700,
+ borderRadius: 20,
+ padding: 24,
+ [breakpoints.down('xs')]: {
+ padding: 12,
+ },
+ },
+ breadcrumb: {
+ display: 'flex',
+ alignItems: 'center',
+ color: palette.text.hint,
+ marginBottom: 50,
+ '& svg': {
+ width: 12,
+ margin: '0 6px',
+ },
+ },
+ link: {
+ cursor: 'pointer',
+ '&:hover': {
+ textDecoration: 'underline',
+ },
+ },
+ heading1: {
+ fontSize: 32,
+ fontWeight: 'bold',
+ color: palette.text.primary,
+ lineHeight: 1,
+ [breakpoints.down('xs')]: {
+ fontSize: 22,
+ fontWeight: 600,
+ },
+ },
+ heading2: {
+ fontSize: 32,
+ lineHeight: 1.2,
+ fontWeight: 600,
+ color: palette.text.primary,
+ marginLeft: 6,
+ [breakpoints.down('xs')]: {
+ fontSize: 18,
+ },
+ },
+ priceChangeWrapper: {
+ height: 25,
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ borderRadius: 16,
+ padding: '0 8px',
+ },
+ button: {
+ display: 'flex',
+ alignItems: 'center',
+ height: 40,
+ padding: '0 28px',
+ borderRadius: 10,
+ color: palette.text.primary,
+ cursor: 'pointer',
+ },
+ filledButton: {
+ background: 'linear-gradient(279deg, rgb(0, 76, 230), rgb(61, 113, 255))',
+ },
+ chartType: {
+ height: 20,
+ padding: '0 6px',
+ borderRadius: 10,
+ display: 'flex',
+ alignItems: 'center',
+ cursor: 'pointer',
+ },
+}));
+
+const AnalyticsPairDetails: React.FC = () => {
+ const classes = useStyles();
+ const { palette, breakpoints } = useTheme();
+ const isMobile = useMediaQuery(breakpoints.down('xs'));
+ const history = useHistory();
+ const match = useRouteMatch<{ id: string }>();
+ const pairAddress = match.params.id;
+ const [pairData, setPairData] = useState(null);
+ const [pairChartData, setPairChartData] = useState(null);
+ const [pairTransactions, setPairTransactions] = useState(null);
+ const pairTransactionsList = useMemo(() => {
+ if (pairTransactions) {
+ const mints = pairTransactions.mints.map((item: any) => {
+ return { ...item, type: 'Add' };
+ });
+ const swaps = pairTransactions.mints.map((item: any) => {
+ return { ...item, type: 'Swap' };
+ });
+ const burns = pairTransactions.mints.map((item: any) => {
+ return { ...item, type: 'Remove' };
+ });
+ return mints.concat(swaps).concat(burns);
+ } else {
+ return null;
+ }
+ }, [pairTransactions]);
+ const { chainId } = useActiveWeb3React();
+ const currency0 = pairData
+ ? new Token(
+ ChainId.MATIC,
+ getAddress(pairData.token0.id),
+ pairData.token0.decimals,
+ )
+ : undefined;
+ const currency1 = pairData
+ ? new Token(
+ ChainId.MATIC,
+ getAddress(pairData.token1.id),
+ pairData.token1.decimals,
+ )
+ : undefined;
+
+ const token0Rate =
+ pairData && pairData.reserve0 && pairData.reserve1
+ ? Number(pairData.reserve1) / Number(pairData.reserve0) >= 0.0001
+ ? (Number(pairData.reserve1) / Number(pairData.reserve0)).toFixed(
+ Number(pairData.reserve1) / Number(pairData.reserve0) > 1 ? 2 : 4,
+ )
+ : '< 0.0001'
+ : '-';
+ const token1Rate =
+ pairData && pairData.reserve0 && pairData.reserve1
+ ? Number(pairData.reserve0) / Number(pairData.reserve1) >= 0.0001
+ ? (Number(pairData.reserve0) / Number(pairData.reserve1)).toFixed(
+ Number(pairData.reserve0) / Number(pairData.reserve1) > 1 ? 2 : 4,
+ )
+ : '< 0.0001'
+ : '-';
+ const usingUtVolume =
+ pairData &&
+ pairData.oneDayVolumeUSD === 0 &&
+ !!pairData.oneDayVolumeUntracked;
+ const fees =
+ pairData && (pairData.oneDayVolumeUSD || pairData.oneDayVolumeUSD === 0)
+ ? usingUtVolume
+ ? (Number(pairData.oneDayVolumeUntracked) * 0.003).toLocaleString()
+ : (Number(pairData.oneDayVolumeUSD) * 0.003).toLocaleString()
+ : '-';
+ const [chartIndex, setChartIndex] = useState(0);
+
+ useEffect(() => {
+ async function checkEthPrice() {
+ const [newPrice] = await getEthPrice();
+ const pairInfo = await getBulkPairData([pairAddress], newPrice);
+ if (pairInfo && pairInfo.length > 0) {
+ setPairData(pairInfo[0]);
+ }
+ }
+ async function fetchTransctions() {
+ const transactions = await getPairTransactions(pairAddress);
+ if (transactions) {
+ setPairTransactions(transactions);
+ }
+ }
+ checkEthPrice();
+ fetchTransctions();
+ }, [pairAddress]);
+
+ const chartData = useMemo(() => {
+ if (pairChartData) {
+ return pairChartData.map((item: any) =>
+ chartIndex === 0
+ ? Number(item.dailyVolumeUSD)
+ : chartIndex === 1
+ ? Number(item.reserveUSD)
+ : Number(item.dailyVolumeUSD) * 0.003,
+ );
+ } else {
+ return null;
+ }
+ }, [pairChartData, chartIndex]);
+
+ const yAxisValues = useMemo(() => {
+ if (chartData) {
+ const minValue = Math.min(...chartData) * 0.99;
+ const maxValue = Math.max(...chartData) * 1.01;
+ const step = (maxValue - minValue) / 8;
+ const values = [];
+ for (let i = 0; i < 9; i++) {
+ values.push(maxValue - i * step);
+ }
+ return values;
+ } else {
+ return undefined;
+ }
+ }, [chartData]);
+
+ const chartDates = useMemo(() => {
+ if (pairChartData) {
+ const dates: string[] = [];
+ pairChartData.forEach((value: any, ind: number) => {
+ const month = moment(Number(value.date) * 1000).format('MMM');
+ const monthLastDate =
+ ind > 0
+ ? moment(Number(pairChartData[ind - 1].date) * 1000).format('MMM')
+ : '';
+ if (monthLastDate !== month) {
+ dates.push(month);
+ }
+ const dateStr = moment(Number(value.date) * 1000).format('D');
+ if (Number(dateStr) % 7 === 0) {
+ dates.push(dateStr);
+ }
+ });
+ return dates;
+ } else {
+ return [];
+ }
+ }, [pairChartData]);
+
+ const currentData = useMemo(
+ () =>
+ chartData && chartData.length > 1
+ ? chartData[chartData.length - 1]
+ : null,
+ [chartData],
+ );
+ const currentPercent = useMemo(() => {
+ if (chartData && chartData.length > 1) {
+ const prevData = chartData[chartData.length - 2];
+ const nowData = chartData[chartData.length - 1];
+ return (nowData - prevData) / prevData;
+ } else {
+ return null;
+ }
+ }, [chartData]);
+
+ useEffect(() => {
+ async function fetchPairChartData() {
+ const chartData = await getPairChartData(pairAddress);
+ if (chartData && chartData.length > 0) {
+ setPairChartData(chartData);
+ }
+ }
+ fetchPairChartData();
+ }, [pairAddress]);
+
+ return (
+ <>
+ {pairData ? (
+ <>
+
+ {
+ history.push('/analytics');
+ }}
+ >
+ Analytics
+
+
+ {
+ history.push('/analytics?tabIndex=2');
+ }}
+ >
+ Pairs
+
+
+
+
+ {pairData.token0.symbol}/{pairData.token1.symbol}
+
+ ({shortenAddress(pairAddress)})
+
+
+
+
+
+
+
+
+ {pairData.token0.symbol} / {pairData.token1.symbol}
+
+
+
+
+
+
+
+ 1 {pairData.token0.symbol} = {token0Rate}{' '}
+ {pairData.token1.symbol}
+
+
+
+
+
+ 1 {pairData.token1.symbol} = {token1Rate}{' '}
+ {pairData.token0.symbol}
+
+
+
+
+
+ {
+ history.push(
+ `/pools?currency0=${pairData.token0.id}¤cy1=${pairData.token1.id}`,
+ );
+ }}
+ >
+ Add Liquidity
+
+ {
+ history.push(
+ `/swap?currency0=${pairData.token0.id}¤cy1=${pairData.token1.id}`,
+ );
+ }}
+ >
+ Swap
+
+
+
+
+
+
+
+
+
+ {chartIndex === 0
+ ? 'Volume'
+ : chartIndex === 1
+ ? 'Liquidity'
+ : 'Price'}
+
+
+ {chartData && currentData ? (
+ <>
+
+
+ $
+ {currentData > 100000
+ ? formatCompact(currentData)
+ : currentData.toLocaleString()}
+
+ 0
+ ? 'rgba(15, 198, 121, 0.1)'
+ : Number(currentPercent) < 0
+ ? 'rgba(255, 82, 82, 0.1)'
+ : 'rgba(99, 103, 128, 0.1)'
+ }
+ color={
+ Number(currentPercent) > 0
+ ? 'rgb(15, 198, 121)'
+ : Number(currentPercent) < 0
+ ? 'rgb(255, 82, 82)'
+ : 'rgb(99, 103, 128)'
+ }
+ >
+
+ {Number(currentPercent) < 0.001 &&
+ Number(currentPercent) > 0
+ ? '<0.001'
+ : Number(currentPercent) > -0.001 &&
+ Number(currentPercent) < 0
+ ? '>-0.001'
+ : (Number(currentPercent) > 0 ? '+' : '') +
+ Number(currentPercent).toLocaleString()}
+ %
+
+
+
+
+
+ {moment().format('MMM DD, YYYY')}
+
+
+ >
+ ) : (
+
+ )}
+
+
+
+ setChartIndex(0)}
+ >
+ Volume
+
+ setChartIndex(1)}
+ >
+ Liquidity
+
+ setChartIndex(2)}
+ >
+ Fees
+
+
+
+
+ {chartData && pairChartData ? (
+ value.date)}
+ width='100%'
+ height={240}
+ categories={chartDates}
+ />
+ ) : (
+
+ )}
+
+
+
+
+
+
+
+
+ TOTAL TOKENS LOCKED
+
+
+
+
+
+
+ {pairData.token0.symbol} :
+
+
+
+ {Number(pairData.reserve0).toLocaleString()}
+
+
+
+
+
+
+ {pairData.token1.symbol} :
+
+
+
+ {Number(pairData.reserve1).toLocaleString()}
+
+
+
+
+
+
+ 7d Trading Vol
+
+
+ ${pairData.oneWeekVolumeUSD.toLocaleString()}
+
+
+
+
+ 24h FEES
+
+
+ ${fees}
+
+
+
+
+
+ TOTAL LIQUIDITY
+
+
+ $
+ {Number(
+ pairData.reserveUSD
+ ? pairData.reserveUSD
+ : pairData.trackedReserveUSD,
+ ).toLocaleString()}
+
+
+
+ 24h Trading Vol
+
+
+ ${pairData.oneDayVolumeUSD.toLocaleString()}
+
+
+
+
+ Contract Address
+
+
+ {chainId ? (
+
+ {shortenAddress(pairData.id)}
+
+ ) : (
+ shortenAddress(pairData.id)
+ )}
+
+
+
+
+
+
+
+
+
+ Transactions
+
+
+ {pairTransactionsList ? (
+
+ ) : (
+
+ )}
+
+ >
+ ) : (
+
+ )}
+ >
+ );
+};
+
+export default AnalyticsPairDetails;
diff --git a/src/pages/AnalyticsPairDetails/index.ts b/src/pages/AnalyticsPairDetails/index.ts
new file mode 100644
index 000000000..9d23d20b0
--- /dev/null
+++ b/src/pages/AnalyticsPairDetails/index.ts
@@ -0,0 +1 @@
+export { default } from './AnalyticsPairDetails';
diff --git a/src/pages/AnalyticsTokenDetails/AnalyticsTokenDetails.tsx b/src/pages/AnalyticsTokenDetails/AnalyticsTokenDetails.tsx
index 844f7913d..201b17f67 100644
--- a/src/pages/AnalyticsTokenDetails/AnalyticsTokenDetails.tsx
+++ b/src/pages/AnalyticsTokenDetails/AnalyticsTokenDetails.tsx
@@ -10,11 +10,7 @@ import cx from 'classnames';
import { shortenAddress, getEtherscanLink, formatCompact } from 'utils';
import { useActiveWeb3React } from 'hooks';
import { CurrencyLogo, PairTable, AreaChart } from 'components';
-import {
- useTokenPairs,
- useBookmarkTokens,
- useTokenChartData,
-} from 'state/application/hooks';
+import { useBookmarkTokens } from 'state/application/hooks';
import {
getTokenInfo,
getEthPrice,
@@ -28,7 +24,7 @@ import { getAddress } from '@ethersproject/address';
const useStyles = makeStyles(({ palette, breakpoints }) => ({
panel: {
- background: '#1b1d26',
+ background: palette.grey.A700,
borderRadius: 20,
padding: 24,
[breakpoints.down('xs')]: {
@@ -113,10 +109,14 @@ const AnalyticsTokenDetails: React.FC = () => {
const currency = token
? new Token(ChainId.MATIC, getAddress(token.id), token.decimals)
: undefined;
- const { tokenChartData, updateTokenChartData } = useTokenChartData();
+ const [tokenChartData, updateTokenChartData] = useState(null);
const [chartIndex, setChartIndex] = useState(0);
- const { tokenPairs, updateTokenPairs } = useTokenPairs();
- const { bookmarkTokens } = useBookmarkTokens();
+ const [tokenPairs, updateTokenPairs] = useState(null);
+ const {
+ bookmarkTokens,
+ addBookmarkToken,
+ removeBookmarkToken,
+ } = useBookmarkTokens();
useEffect(() => {
async function checkEthPrice() {
@@ -211,7 +211,6 @@ const AnalyticsTokenDetails: React.FC = () => {
}
async function fetchTokenPairs() {
const [newPrice] = await getEthPrice();
- updateTokenPairs({ data: null });
const tokenPairs = await getTokenPairs2(tokenAddress);
const formattedPairs = tokenPairs
? tokenPairs.map((pair: any) => {
@@ -220,7 +219,7 @@ const AnalyticsTokenDetails: React.FC = () => {
: [];
const pairData = await getBulkPairData(formattedPairs, newPrice);
if (pairData) {
- updateTokenPairs({ data: pairData });
+ updateTokenPairs(pairData);
}
}
fetchTokenPairs();
@@ -277,9 +276,11 @@ const AnalyticsTokenDetails: React.FC = () => {
{bookmarkTokens.includes(token.id) ? (
-
+ removeBookmarkToken(token.id)}
+ />
) : (
-
+ addBookmarkToken(token.id)} />
)}
@@ -417,7 +418,9 @@ const AnalyticsTokenDetails: React.FC = () => {
setChartIndex(0)}
>
@@ -425,14 +428,18 @@ const AnalyticsTokenDetails: React.FC = () => {
setChartIndex(1)}
>
Liquidity
setChartIndex(2)}
>
diff --git a/src/pages/index.ts b/src/pages/index.ts
index 28b559eea..a086e6e75 100755
--- a/src/pages/index.ts
+++ b/src/pages/index.ts
@@ -5,3 +5,4 @@ export { default as FarmPage } from './FarmPage';
export { default as DragonPage } from './DragonPage';
export { default as AnalyticsPage } from './AnalyticsPage';
export { default as AnalyticsTokenDetails } from './AnalyticsTokenDetails';
+export { default as AnalyticsPairDetails } from './AnalyticsPairDetails';
diff --git a/src/state/application/actions.ts b/src/state/application/actions.ts
index d34a3f14d..42fa07056 100755
--- a/src/state/application/actions.ts
+++ b/src/state/application/actions.ts
@@ -100,7 +100,3 @@ export const updateBookmarkPairs = createAction(
);
export const updateTopPairs = createAction('application/updateTopPairs');
-
-export const updateTokenChartData = createAction(
- 'application/updateTokenChartData',
-);
diff --git a/src/state/application/hooks.ts b/src/state/application/hooks.ts
index e82d68e6a..081e4d27f 100755
--- a/src/state/application/hooks.ts
+++ b/src/state/application/hooks.ts
@@ -21,7 +21,6 @@ import {
updateTopPairs,
addBookMarkPair,
removeBookmarkPair,
- updateTokenChartData,
} from './actions';
export function useBlockNumber(): number | undefined {
@@ -315,20 +314,3 @@ export function useTopPairs(): {
);
return { topPairs, updateTopPairs: _updateTopPairs };
}
-
-export function useTokenChartData(): {
- tokenChartData: any;
- updateTokenChartData: (data: any) => void;
-} {
- const tokenChartData = useSelector(
- (state: AppState) => state.application.tokenChartData,
- );
- const dispatch = useDispatch();
- const _updateTokenChartData = useCallback(
- (data) => {
- dispatch(updateTokenChartData(data));
- },
- [dispatch],
- );
- return { tokenChartData, updateTokenChartData: _updateTokenChartData };
-}
diff --git a/src/state/application/reducer.ts b/src/state/application/reducer.ts
index 80303d51d..4099c7960 100755
--- a/src/state/application/reducer.ts
+++ b/src/state/application/reducer.ts
@@ -20,7 +20,6 @@ import {
addBookMarkPair,
removeBookmarkPair,
updateBookmarkPairs,
- updateTokenChartData,
} from './actions';
type PopupList = Array<{
@@ -179,8 +178,5 @@ export default createReducer(initialState, (builder) =>
})
.addCase(updateBookmarkPairs, (state, { payload }) => {
state.bookmarkedPairs = payload;
- })
- .addCase(updateTokenChartData, (state, { payload }) => {
- state.tokenChartData = payload;
}),
);
diff --git a/src/state/lists/reducer.test.ts b/src/state/lists/reducer.test.ts
index 3d1e462fe..007ec9b3a 100755
--- a/src/state/lists/reducer.test.ts
+++ b/src/state/lists/reducer.test.ts
@@ -391,7 +391,7 @@ describe('list reducer', () => {
expect(store.getState()).toEqual({
byUrl: {},
selectedListUrl:
- 'https://unpkg.com/quickswap-default-token-list@1.2.17/build/quickswap-default.tokenlist.json',
+ 'https://unpkg.com/quickswap-default-token-list@1.2.18/build/quickswap-default.tokenlist.json',
});
});
});
diff --git a/src/state/stake/hooks.ts b/src/state/stake/hooks.ts
index ef0b9b6d2..6a38468b3 100755
--- a/src/state/stake/hooks.ts
+++ b/src/state/stake/hooks.ts
@@ -267,6 +267,16 @@ export const SYRUP_REWARDS_INFO: {
}[];
} = {
[ChainId.MATIC]: [
+ {
+ token: SNE,
+ stakingRewardAddress: '0xf6Fe46F0001FDeFAde6b5E08635ED303f2E0a3aA',
+ ended: false,
+ lp: '',
+ name: '',
+ baseToken: USDC,
+ rate: 160000,
+ ending: 1643302635,
+ },
{
token: POLYPUG,
stakingRewardAddress: '0xA206A97b30343a0802553dB48d71af349AbF563A',
@@ -347,16 +357,6 @@ export const SYRUP_REWARDS_INFO: {
rate: 40610.66,
ending: 1644090690,
},
- {
- token: UFI,
- stakingRewardAddress: '0xE707bB8513873c2360811F01BfBd0e9EBFd96b0D',
- ended: false,
- lp: '',
- name: '',
- baseToken: MATIC,
- rate: 18315,
- ending: 1640485140,
- },
{
token: WSG,
stakingRewardAddress: '0x2b91d985AEb645cc580E35BdF52DF2694e742ADF',
@@ -483,6 +483,16 @@ export const OLD_SYRUP_REWARDS_INFO: {
}[];
} = {
[ChainId.MATIC]: [
+ {
+ token: UFI,
+ stakingRewardAddress: '0xE707bB8513873c2360811F01BfBd0e9EBFd96b0D',
+ ended: true,
+ lp: '',
+ name: '',
+ baseToken: MATIC,
+ rate: 18315,
+ ending: 1640485140,
+ },
{
token: UCO,
stakingRewardAddress: '0xC328d6eC46d11a6ABdA3C02434861beA14739E1f',
diff --git a/src/theme.ts b/src/theme.ts
index 42fcf58cd..5e440c8ad 100755
--- a/src/theme.ts
+++ b/src/theme.ts
@@ -22,6 +22,8 @@ const textDisabled = '#626680';
const textHint = '#636780';
const bgColor = '#12131a';
const bgPalette = '#1b1e29';
+const greyBgLight = '#3e4252';
+const greyBg = '#1b1d26';
const successMain = '#0fc679';
const successDark = '#1DB2D5';
@@ -60,6 +62,10 @@ export const mainTheme = responsiveFontSizes(
main: primary,
dark: primaryDark,
},
+ grey: {
+ A400: greyBgLight,
+ A700: greyBg,
+ },
secondary: {
main: secondary,
light: secondaryLight,
diff --git a/src/utils/index.ts b/src/utils/index.ts
index b030d886c..8832225fd 100755
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -4,7 +4,7 @@ import { Contract } from '@ethersproject/contracts';
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import weekOfYear from 'dayjs/plugin/weekOfYear';
-import { blockClient, client } from 'apollo/client';
+import { blockClient, client, txClient } from 'apollo/client';
import {
GET_BLOCK,
GLOBAL_DATA,
@@ -17,6 +17,7 @@ import {
TOKEN_DATA,
TOKEN_DATA1,
TOKEN_DATA2,
+ PAIR_CHART,
PAIR_DATA,
PAIRS_BULK1,
PAIRS_HISTORICAL_BULK,
@@ -26,6 +27,8 @@ import {
ALL_TOKENS,
TOKEN_INFO,
TOKEN_INFO_OLD,
+ FILTERED_TRANSACTIONS,
+ HOURLY_PAIR_RATES,
} from 'apollo/queries';
import { JsonRpcSigner, Web3Provider } from '@ethersproject/providers';
import { abi as IUniswapV2Router02ABI } from '@uniswap/v2-periphery/build/IUniswapV2Router02.json';
@@ -720,6 +723,26 @@ export const getIntervalTokenData = async (
}
};
+export const getPairTransactions = async (pairAddress: string) => {
+ try {
+ const result = await txClient.query({
+ query: FILTERED_TRANSACTIONS,
+ variables: {
+ allPairs: [pairAddress],
+ },
+ fetchPolicy: 'no-cache',
+ });
+ return {
+ mints: result.data.mints,
+ burns: result.data.burns,
+ swaps: result.data.swaps,
+ };
+ } catch (e) {
+ console.log(e);
+ return null;
+ }
+};
+
export const getTokenChartData = async (tokenAddress: string) => {
let data: any[] = [];
const utcEndTime = dayjs.utc();
@@ -788,6 +811,154 @@ export const getTokenChartData = async (tokenAddress: string) => {
return data;
};
+export const getPairChartData = async (pairAddress: string) => {
+ let data: any[] = [];
+ const utcEndTime = dayjs.utc();
+ const utcStartTime = utcEndTime.subtract(2, 'month');
+ const startTime = utcStartTime.unix() - 1;
+ try {
+ let allFound = false;
+ let skip = 0;
+ while (!allFound) {
+ const result = await client.query({
+ query: PAIR_CHART,
+ variables: {
+ startTime: startTime,
+ pairAddress: pairAddress,
+ skip,
+ },
+ fetchPolicy: 'cache-first',
+ });
+ skip += 1000;
+ data = data.concat(result.data.pairDayDatas);
+ if (result.data.pairDayDatas.length < 1000) {
+ allFound = true;
+ }
+ }
+
+ const dayIndexSet = new Set();
+ const dayIndexArray: any[] = [];
+ const oneDay = 24 * 60 * 60;
+ data.forEach((dayData, i) => {
+ // add the day index to the set of days
+ dayIndexSet.add((data[i].date / oneDay).toFixed(0));
+ dayIndexArray.push(data[i]);
+ dayData.dailyVolumeUSD = parseFloat(dayData.dailyVolumeUSD);
+ dayData.reserveUSD = parseFloat(dayData.reserveUSD);
+ });
+
+ if (data[0]) {
+ // fill in empty days
+ let timestamp = data[0].date ? data[0].date : startTime;
+ let latestLiquidityUSD = data[0].reserveUSD;
+ let index = 1;
+ while (timestamp < utcEndTime.unix() - oneDay) {
+ const nextDay = timestamp + oneDay;
+ const currentDayIndex = (nextDay / oneDay).toFixed(0);
+ if (!dayIndexSet.has(currentDayIndex)) {
+ data.push({
+ date: nextDay,
+ dayString: nextDay,
+ dailyVolumeUSD: 0,
+ reserveUSD: latestLiquidityUSD,
+ });
+ } else {
+ latestLiquidityUSD = dayIndexArray[index].reserveUSD;
+ index = index + 1;
+ }
+ timestamp = nextDay;
+ }
+ }
+
+ data = data.sort((a, b) => (parseInt(a.date) > parseInt(b.date) ? 1 : -1));
+ } catch (e) {
+ console.log(e);
+ }
+
+ return data;
+};
+
+export const getHourlyRateData = async (
+ pairAddress: string,
+ latestBlock: number,
+) => {
+ try {
+ const utcEndTime = dayjs.utc();
+ const utcStartTime = utcEndTime.subtract(2, 'month');
+ const startTime = utcStartTime.unix() - 1;
+ let time = startTime;
+
+ // create an array of hour start times until we reach current hour
+ const timestamps = [];
+ while (time <= utcEndTime.unix()) {
+ timestamps.push(time);
+ time += 3600 * 24;
+ }
+
+ // backout if invalid timestamp format
+ if (timestamps.length === 0) {
+ return [];
+ }
+
+ // once you have all the timestamps, get the blocks for each timestamp in a bulk query
+ let blocks;
+
+ blocks = await getBlocksFromTimestamps(timestamps, 100);
+
+ // catch failing case
+ if (!blocks || blocks?.length === 0) {
+ return [];
+ }
+
+ if (latestBlock) {
+ blocks = blocks.filter((b) => {
+ return parseFloat(b.number) <= latestBlock;
+ });
+ }
+
+ const result = await splitQuery(
+ HOURLY_PAIR_RATES,
+ client,
+ [pairAddress],
+ blocks,
+ 100,
+ );
+
+ // format token ETH price results
+ const values = [];
+ for (const row in result) {
+ const timestamp = row.split('t')[1];
+ if (timestamp) {
+ values.push({
+ timestamp,
+ rate0: parseFloat(result[row]?.token0Price),
+ rate1: parseFloat(result[row]?.token1Price),
+ });
+ }
+ }
+
+ const formattedHistoryRate0 = [];
+ const formattedHistoryRate1 = [];
+
+ // for each hour, construct the open and close price
+ for (let i = 0; i < values.length - 1; i++) {
+ formattedHistoryRate0.push({
+ timestamp: values[i].timestamp,
+ rate: values[i].rate0,
+ });
+ formattedHistoryRate1.push({
+ timestamp: values[i].timestamp,
+ rate: values[i].rate1,
+ });
+ }
+
+ return [formattedHistoryRate0, formattedHistoryRate1];
+ } catch (e) {
+ console.log(e);
+ return [[], []];
+ }
+};
+
export const getBulkPairData: (
pairList: any,
ethPrice: any,