diff --git a/src/components/PopularPools/Card/Card.tsx b/src/components/PopularPools/Card/Card.tsx index 2f01be7c9..3cf6ce7f5 100644 --- a/src/components/PopularPools/Card/Card.tsx +++ b/src/components/PopularPools/Card/Card.tsx @@ -27,6 +27,7 @@ const Card: React.FC = ({ TVL, apy, // apyData, + poolAddress, isLoading, isUnknownFrom, fee, @@ -92,7 +93,7 @@ const Card: React.FC = ({ return ( - {isLoading ? ( + {isLoading || !poolAddress?.toString() ? ( ) : ( diff --git a/src/components/PopularPools/PopularPools.tsx b/src/components/PopularPools/PopularPools.tsx index d5b3227e8..4fa0e1702 100644 --- a/src/components/PopularPools/PopularPools.tsx +++ b/src/components/PopularPools/PopularPools.tsx @@ -1,4 +1,4 @@ -import { Grid, Typography, useMediaQuery } from '@mui/material' +import { Box, Grid, Typography, useMediaQuery } from '@mui/material' import { useStyles } from './style' import { PopularPoolData } from '@containers/PopularPoolsWrapper/PopularPoolsWrapper' import Card from './Card/Card' @@ -8,14 +8,26 @@ import 'slick-carousel/slick/slick.css' import 'slick-carousel/slick/slick-theme.css' import { theme } from '@static/theme' import { useMemo } from 'react' +import Intervals from '@components/Stats/Intervals/Intervals' +import { Intervals as IntervalsKeys } from '@store/consts/static' + export interface IPopularPools { pools: PopularPoolData[] isLoading: boolean network: NetworkType showAPY: boolean + updateInterval: (interval: IntervalsKeys) => void + lastUsedInterval: IntervalsKeys | null } -const PopularPools: React.FC = ({ pools, isLoading, network, showAPY }) => { +const PopularPools: React.FC = ({ + pools, + isLoading, + network, + showAPY, + updateInterval, + lastUsedInterval +}) => { const isLgDown = useMediaQuery(theme.breakpoints.down('lg')) const isMdDown = useMediaQuery(theme.breakpoints.down('md')) const isSmDown = useMediaQuery('@media (max-width:700px)') @@ -31,9 +43,13 @@ const PopularPools: React.FC = ({ pools, isLoading, network, show return ( - - Popular pools - + + Popular pools + +
= ({ pools, isLoading, network, show dotsClass={`slick-dots ${classes.dots}`} appendDots={dots =>
    {dots}
} rows={1}> - {pools.map(pool => ( - - ))} + {pools.map(pool => { + return ( + (isLoading || (!isLoading && pool?.poolAddress)) && ( + + ) + ) + })}
diff --git a/src/components/PopularPools/style.ts b/src/components/PopularPools/style.ts index 9c7ed2cd1..e13198f5a 100644 --- a/src/components/PopularPools/style.ts +++ b/src/components/PopularPools/style.ts @@ -5,7 +5,8 @@ export const useStyles = makeStyles()(theme => ({ title: { color: colors.invariant.text, ...typography.heading4, - fontWeight: 700 + fontWeight: 700, + textWrap: 'nowrap' }, cardsContainer: { width: '100%', diff --git a/src/components/Stats/PoolListItem/PoolListItem.tsx b/src/components/Stats/PoolListItem/PoolListItem.tsx index 8549ed056..dcaf6d276 100644 --- a/src/components/Stats/PoolListItem/PoolListItem.tsx +++ b/src/components/Stats/PoolListItem/PoolListItem.tsx @@ -261,7 +261,7 @@ const PoolListItem: React.FC = ({ />
- {fee}% + {fee && typeof fee === 'number' && {fee}%} {!isSmd && showAPY ? ( diff --git a/src/containers/PopularPoolsWrapper/PopularPoolsWrapper.tsx b/src/containers/PopularPoolsWrapper/PopularPoolsWrapper.tsx index b5e730fcd..b13382fa0 100644 --- a/src/containers/PopularPoolsWrapper/PopularPoolsWrapper.tsx +++ b/src/containers/PopularPoolsWrapper/PopularPoolsWrapper.tsx @@ -1,13 +1,14 @@ -import React, { useEffect, useMemo } from 'react' -import { useDispatch, useSelector } from 'react-redux' +import React, { useMemo } from 'react' +import { useSelector } from 'react-redux' import PopularPools from '@components/PopularPools/PopularPools' import { isLoading, poolsStatsWithTokensDetails } from '@store/selectors/stats' -import { actions } from '@store/reducers/stats' import { Grid } from '@mui/material' import { network } from '@store/selectors/solanaConnection' import { getPopularPools, Intervals } from '@store/consts/static' import { unknownTokenIcon } from '@static/icons' +import { PublicKey } from '@solana/web3.js' export interface PopularPoolData { + poolAddress?: PublicKey symbolFrom?: string symbolTo?: string iconFrom?: string @@ -25,9 +26,15 @@ export interface PopularPoolData { isUnknownTo?: boolean } -export const PopularPoolsWrapper: React.FC = () => { - const dispatch = useDispatch() +interface IPopularPoolsWrapper { + updateInterval: (interval: Intervals) => void + lastUsedInterval: Intervals | null +} +export const PopularPoolsWrapper: React.FC = ({ + lastUsedInterval, + updateInterval +}) => { const currentNetwork = useSelector(network) const isLoadingStats = useSelector(isLoading) const poolsList = useSelector(poolsStatsWithTokensDetails) @@ -60,14 +67,11 @@ export const PopularPoolsWrapper: React.FC = () => { return mockPools } if (popularPools.length === 0) { - popularPools = poolsList - .sort((a, b) => b.volume24 - a.volume24) - .slice(0, 4) - .map(pool => ({ - tokenX: pool.tokenX.toString(), - tokenY: pool.tokenY.toString(), - fee: pool.fee.toString() - })) + popularPools = poolsList.slice(0, 4).map(pool => ({ + tokenX: pool.tokenX.toString(), + tokenY: pool.tokenY.toString(), + fee: pool.fee.toString() + })) } popularPools.map(pool => { @@ -79,6 +83,7 @@ export const PopularPoolsWrapper: React.FC = () => { ) if (poolData) { data.push({ + poolAddress: poolData.poolAddress, symbolFrom: poolData?.tokenXDetails?.symbol ?? pool.tokenX, symbolTo: poolData?.tokenYDetails?.symbol ?? pool.tokenY, iconFrom: poolData?.tokenXDetails?.logoURI ?? unknownTokenIcon, @@ -97,8 +102,21 @@ export const PopularPoolsWrapper: React.FC = () => { }) } else { data.push({ - addressFrom: pool.tokenX, - addressTo: pool.tokenY + symbolFrom: '-', + symbolTo: '-', + iconFrom: unknownTokenIcon, + iconTo: unknownTokenIcon, + volume: 0, + TVL: 0, + fee: 0, + addressFrom: pool.tokenX.toString(), + addressTo: pool.tokenY.toString(), + apy: 0, + apyData: { + fees: 0 + }, + isUnknownFrom: false, + isUnknownTo: false }) } }) @@ -110,10 +128,6 @@ export const PopularPoolsWrapper: React.FC = () => { return list.some(pool => pool.apy !== 0) }, [list]) - useEffect(() => { - dispatch(actions.getCurrentIntervalStats({ interval: Intervals.Daily })) - }, []) - return ( { isLoading={isLoadingStats || list.length === 0} network={currentNetwork} showAPY={showAPY} + lastUsedInterval={lastUsedInterval} + updateInterval={updateInterval} /> ) diff --git a/src/containers/WrappedPoolList/WrappedPoolList.tsx b/src/containers/WrappedPoolList/WrappedPoolList.tsx index 2d55453e0..cd3172e8b 100644 --- a/src/containers/WrappedPoolList/WrappedPoolList.tsx +++ b/src/containers/WrappedPoolList/WrappedPoolList.tsx @@ -1,17 +1,15 @@ import { Box, Typography, useMediaQuery } from '@mui/material' import { isLoading, poolsStatsWithTokensDetails } from '@store/selectors/stats' -import { useEffect, useMemo, useState } from 'react' +import { useMemo, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import useStyles from './styles' import { VariantType } from 'notistack' import { actions as snackbarActions } from '@store/reducers/snackbars' import { network } from '@store/selectors/solanaConnection' -import { actions } from '@store/reducers/stats' import LiquidityPoolList from '@components/LiquidityPoolList/LiquidityPoolList' import { FilterSearch, ISearchToken } from '@common/FilterSearch/FilterSearch' import { theme } from '@static/theme' import { unknownTokenIcon } from '@static/icons' -import { Intervals } from '@store/consts/static' export const WrappedPoolList: React.FC = () => { const isXs = useMediaQuery(theme.breakpoints.down('sm')) @@ -58,10 +56,6 @@ export const WrappedPoolList: React.FC = () => { ) } - useEffect(() => { - dispatch(actions.getCurrentIntervalStats({ interval: Intervals.Daily })) - }, [dispatch]) - return (
diff --git a/src/pages/ListPage/ListPage.tsx b/src/pages/ListPage/ListPage.tsx index 7fdd4506f..4d55ce3d4 100644 --- a/src/pages/ListPage/ListPage.tsx +++ b/src/pages/ListPage/ListPage.tsx @@ -2,13 +2,36 @@ import { Grid } from '@mui/material' import useStyles from './styles' import PopularPoolsWrapper from '@containers/PopularPoolsWrapper/PopularPoolsWrapper' import { WrappedPoolList } from '@containers/WrappedPoolList/WrappedPoolList' +import { useEffect } from 'react' +import { useDispatch, useSelector } from 'react-redux' +import { currentInterval } from '@store/selectors/stats' +import { Intervals as IntervalsKeys } from '@store/consts/static' +import { actions } from '@store/reducers/stats' const ListPage: React.FC = () => { const { classes } = useStyles() + + const dispatch = useDispatch() + + const lastUsedInterval = useSelector(currentInterval) + + const updateInterval = (interval: IntervalsKeys) => { + dispatch(actions.getCurrentIntervalStats({ interval })) + dispatch(actions.setCurrentInterval({ interval })) + } + + useEffect(() => { + dispatch( + actions.getCurrentIntervalStats({ + interval: lastUsedInterval || IntervalsKeys.Daily + }) + ) + }, []) + return ( - + diff --git a/src/store/sagas/index.ts b/src/store/sagas/index.ts index af36c4f62..f3f48e517 100644 --- a/src/store/sagas/index.ts +++ b/src/store/sagas/index.ts @@ -4,13 +4,11 @@ import { poolsSaga } from './pool' import { swapHandler } from './swap' import { walletSaga } from './wallet' import { positionsSaga } from './positions' -import { intervalStatsHandler } from './stats' +import { statsSaga } from './stats' export function* rootSaga(): Generator { yield all( - [connectionSaga, walletSaga, swapHandler, positionsSaga, poolsSaga, intervalStatsHandler].map( - spawn - ) + [connectionSaga, walletSaga, swapHandler, positionsSaga, poolsSaga, statsSaga].map(spawn) ) } export default rootSaga diff --git a/src/store/sagas/stats.ts b/src/store/sagas/stats.ts index 12cb936b8..4050d8ab4 100644 --- a/src/store/sagas/stats.ts +++ b/src/store/sagas/stats.ts @@ -1,5 +1,5 @@ import { actions } from '@store/reducers/stats' -import { call, put, select, takeLatest } from 'typed-redux-saga' +import { all, call, put, select, spawn, takeLatest } from 'typed-redux-saga' import { network } from '@store/selectors/solanaConnection' import { ensureError, getIntervalsFullSnap } from '@utils/utils' import { PublicKey } from '@solana/web3.js' @@ -106,3 +106,6 @@ export function* getIntervalStats(action: PayloadAction<{ interval: Intervals }> export function* intervalStatsHandler(): Generator { yield* takeLatest(actions.getCurrentIntervalStats, getIntervalStats) } +export function* statsSaga(): Generator { + yield* all([intervalStatsHandler].map(spawn)) +}