From b60f6dff602da7fb77c80ea1a57f335c002b25f1 Mon Sep 17 00:00:00 2001 From: Matias Poblete <86752543+MattPoblete@users.noreply.github.com> Date: Tue, 26 Nov 2024 11:19:12 -0300 Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=9A=A7=20Move=20liquidty=20page=20to?= =?UTF-8?q?=20pools=20and=20add=20pool=20table=20with=20shares?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cypress/component/liquidity.test.tsx | 2 +- cypress/e2e/flows.test.ts | 4 +- package.json | 2 +- pages/liquidity/index.tsx | 171 ----- .../{liquidity => pools}/add/[...tokens].tsx | 2 +- pages/{liquidity => pools}/add/index.tsx | 4 +- pages/pools/index.tsx | 595 ++++++++++++++++++ .../remove/[...tokens].tsx | 2 +- src/components/Bridge/BridgeConfirmModal.tsx | 4 +- .../Add/AddLiquidityComponent.tsx | 2 +- .../Add/AddModalFooter.tsx | 0 .../Add/AddModalHeader.tsx | 0 .../{Liquidity => Pools}/AddRemoveHeader.tsx | 2 +- .../LiquidityPoolInfoModal.tsx | 6 +- .../Remove/RemoveLiquidityComponent.tsx | 2 +- .../{Liquidity => Pools}/styleds.tsx | 0 src/functions/getLpTokens.tsx | 3 +- yarn.lock | 8 +- 18 files changed, 617 insertions(+), 192 deletions(-) delete mode 100644 pages/liquidity/index.tsx rename pages/{liquidity => pools}/add/[...tokens].tsx (90%) rename pages/{liquidity => pools}/add/index.tsx (79%) create mode 100644 pages/pools/index.tsx rename pages/{liquidity => pools}/remove/[...tokens].tsx (70%) rename src/components/{Liquidity => Pools}/Add/AddLiquidityComponent.tsx (99%) rename src/components/{Liquidity => Pools}/Add/AddModalFooter.tsx (100%) rename src/components/{Liquidity => Pools}/Add/AddModalHeader.tsx (100%) rename src/components/{Liquidity => Pools}/AddRemoveHeader.tsx (99%) rename src/components/{Liquidity => Pools}/LiquidityPoolInfoModal.tsx (94%) rename src/components/{Liquidity => Pools}/Remove/RemoveLiquidityComponent.tsx (99%) rename src/components/{Liquidity => Pools}/styleds.tsx (100%) diff --git a/cypress/component/liquidity.test.tsx b/cypress/component/liquidity.test.tsx index 653c8e2a..c372e322 100644 --- a/cypress/component/liquidity.test.tsx +++ b/cypress/component/liquidity.test.tsx @@ -1,7 +1,7 @@ import '../../styles/globals.css'; import MockRouter from '../utils/router'; import Providers from 'components/Providers/Providers'; -import AddLiquidityComponent from 'components/Liquidity/Add/AddLiquidityComponent'; +import AddLiquidityComponent from 'components/Pools/Add/AddLiquidityComponent'; import { mockedFreighterConnector, sleep, testnetXLM } from '../utils/utils'; import { useApiTokens } from 'hooks/tokens/useApiTokens'; diff --git a/cypress/e2e/flows.test.ts b/cypress/e2e/flows.test.ts index 05834980..5476ea97 100644 --- a/cypress/e2e/flows.test.ts +++ b/cypress/e2e/flows.test.ts @@ -253,9 +253,9 @@ describe('Navigation flow', () => { cy.visit('/'); cy.get('[data-testid="navbar__container"]').click(); // cy.wait(1500); - cy.contains('Liquidity').click(); + cy.contains('Pools').click(); // cy.wait(3000); - cy.contains('List of your liquidity positions'); + cy.contains('Liquidity pools'); }); it('should navigate to bridge', () => { cy.visit('/'); diff --git a/package.json b/package.json index 614a6199..6feaef0f 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,7 @@ "react-window": "^1.8.9", "redux": "^4.2.1", "soroswap-router-sdk": "1.4.6", - "soroswap-ui": "^1.0.0", + "soroswap-ui": "^1.1.0", "swr": "^2.2.0", "typescript": "5.3.3", "use-resize-observer": "^9.1.0" diff --git a/pages/liquidity/index.tsx b/pages/liquidity/index.tsx deleted file mode 100644 index dcf4c82a..00000000 --- a/pages/liquidity/index.tsx +++ /dev/null @@ -1,171 +0,0 @@ -import { CircularProgress, styled, useMediaQuery, useTheme } from 'soroswap-ui'; -import { useSorobanReact } from '@soroban-react/core'; -import { ButtonPrimary } from 'components/Buttons/Button'; -import { WalletButton } from 'components/Buttons/WalletButton'; -import { AutoColumn } from 'components/Column'; -import LiquidityPoolInfoModal from 'components/Liquidity/LiquidityPoolInfoModal'; -import { LPPercentage } from 'components/Liquidity/styleds'; -import CurrencyLogo from 'components/Logo/CurrencyLogo'; -import { Dots } from 'components/Pool/styleds'; -import { AutoRow } from 'components/Row'; -import SettingsTab from 'components/Settings'; -import { BodySmall, SubHeader } from 'components/Text'; -import { AppContext } from 'contexts'; -import { LpTokensObj } from 'functions/getLpTokens'; -import useGetLpTokens from 'hooks/useGetLpTokens'; -import { useRouter } from 'next/router'; -import { useContext, useState } from 'react'; -import SEO from '../../src/components/SEO'; -import { DEFAULT_SLIPPAGE_INPUT_VALUE } from 'components/Settings/MaxSlippageSettings'; - -const PageWrapper = styled(AutoColumn)` - position: relative; - background: ${({ theme }) => `linear-gradient(${theme.palette.customBackground.bg2}, ${theme.palette.customBackground.bg2 - }) padding-box, - linear-gradient(150deg, rgba(136,102,221,1) 0%, rgba(${theme.palette.mode == 'dark' ? '33,29,50,1' : '255,255,255,1' - }) 35%, rgba(${theme.palette.mode == 'dark' ? '33,29,50,1' : '255,255,255,1' - }) 65%, rgba(136,102,221,1) 100%) border-box`}; - border: 1px solid transparent; - border-radius: 16px; - padding: 32px; - transition: transform 250ms ease; - max-width: 875px; - width: 100%; - display: flex; - flex-direction: column; - align-items: center; - gap: 24px; -`; - -const LPTokensContainer = styled('div')` - width: calc(100% + 64px); - background-color: ${({ theme }) => theme.palette.customBackground.surface}; - min-height: 100px; - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - padding: 32px; - gap: 24px; -`; - -const LPCard = styled('div')` - background-color: ${({ theme }) => theme.palette.customBackground.bg1}; - background-color: ${({ theme }) => theme.palette.customBackground.bg1}; - border-radius: 16px; - width: 100%; - min-height: 86px; - padding: 16px 32px; - display: flex; - justify-content: space-between; - align-items: center; - cursor: pointer; -`; - -const StatusWrapper = styled('div')` - background-color: ${({ theme }) => theme.palette.customBackground.accentAction}; - font-size: 20px; - font-weight: 600; - padding: 16px; - color: ${({ theme }) => theme.palette.custom.accentTextLightPrimary}; - width: 100%; - max-width: 110px; - display: flex; - align-items: center; - justify-content: center; - border-radius: 16px; -`; - -export default function LiquidityPage() { - const sorobanContext = useSorobanReact(); - const { address } = sorobanContext; - const router = useRouter(); - const theme = useTheme(); - const isMobile = useMediaQuery(theme.breakpoints.down('sm')); - const { ConnectWalletModal } = useContext(AppContext); - const { isConnectWalletModalOpen, setConnectWalletModalOpen } = ConnectWalletModal; - - const v2IsLoading = false; - const noLiquidity = false; - const isCreate = false; - - const { lpTokens, isLoading, mutate } = useGetLpTokens(); - - const [isModalOpen, setModalOpen] = useState(false); - const [selectedLP, setSelectedLP] = useState(); - - const handleLPClick = (obj: LpTokensObj) => { - setSelectedLP(obj); - setModalOpen(true); - }; - - return ( - <> - - -
- - Your liquidity - - -
- List of your liquidity positions -
-
- {!address ? ( - - - <>Connect to a wallet to view your liquidity. - - - ) : v2IsLoading ? ( - - - - <>Loading - - - - ) : lpTokens && lpTokens?.length > 0 ? ( - - {lpTokens.map((obj: any, index: number) => ( - handleLPClick(obj)} key={index}> - - - - - {obj.token_0.code} - {obj.token_1.code} - - {obj.lpPercentage}% - - {obj.status} - - ))} - - ) : isLoading ? ( - - - - ) : ( - - - <>No liquidity found. - - - )} - {address ? ( - router.push('/liquidity/add')}> - + Add Liquidity - - ) : ( - - )} -
- setModalOpen(false)} - /> - - ); -} diff --git a/pages/liquidity/add/[...tokens].tsx b/pages/pools/add/[...tokens].tsx similarity index 90% rename from pages/liquidity/add/[...tokens].tsx rename to pages/pools/add/[...tokens].tsx index f9af2c2f..fde30c7f 100644 --- a/pages/liquidity/add/[...tokens].tsx +++ b/pages/pools/add/[...tokens].tsx @@ -1,5 +1,5 @@ import { useSorobanReact } from '@soroban-react/core'; -import AddLiquidityComponent from 'components/Liquidity/Add/AddLiquidityComponent'; +import AddLiquidityComponent from 'components/Pools/Add/AddLiquidityComponent'; import SEO from 'components/SEO'; import { xlmTokenList } from 'constants/xlmToken'; import { useRouter } from 'next/router'; diff --git a/pages/liquidity/add/index.tsx b/pages/pools/add/index.tsx similarity index 79% rename from pages/liquidity/add/index.tsx rename to pages/pools/add/index.tsx index 671bc744..624881c8 100644 --- a/pages/liquidity/add/index.tsx +++ b/pages/pools/add/index.tsx @@ -1,4 +1,4 @@ -import AddLiquidityComponent from 'components/Liquidity/Add/AddLiquidityComponent'; +import AddLiquidityComponent from 'components/Pools/Add/AddLiquidityComponent'; import SEO from 'components/SEO'; import { useApiTokens } from 'hooks/tokens/useApiTokens'; import { useRouter } from 'next/router'; @@ -12,7 +12,7 @@ export default function AddLiquidityPage() { if (!tokens) return; const xlm = tokens.find((token) => token.code === 'XLM'); - if (xlm) router.push(`/liquidity/add/${xlm.contract}`); + if (xlm) router.push(`/pools/add/${xlm.contract}`); }, [tokens, router]); return ( diff --git a/pages/pools/index.tsx b/pages/pools/index.tsx new file mode 100644 index 00000000..cd9167ad --- /dev/null +++ b/pages/pools/index.tsx @@ -0,0 +1,595 @@ +import { Card, CircularProgress, Skeleton, Stack, styled, Switch, Tooltip, Typography, useMediaQuery, useTheme } from 'soroswap-ui'; +import { useSorobanReact } from '@soroban-react/core'; +import { ButtonPrimary } from 'components/Buttons/Button'; +import { WalletButton } from 'components/Buttons/WalletButton'; +import { AutoColumn } from 'components/Column'; +import LiquidityPoolInfoModal from 'components/Pools/LiquidityPoolInfoModal'; +import { LPPercentage } from 'components/Pools/styleds'; +import CurrencyLogo from 'components/Logo/CurrencyLogo'; +import { Dots } from 'components/Pool/styleds'; +import { AutoRow } from 'components/Row'; +import SettingsTab from 'components/Settings'; +import { BodySmall, SubHeader } from 'components/Text'; +import { AppContext } from 'contexts'; +import { LpTokensObj } from 'functions/getLpTokens'; +import useGetLpTokens from 'hooks/useGetLpTokens'; +import { useRouter } from 'next/router'; +import { ImgHTMLAttributes, useContext, useEffect, useState } from 'react'; +import SEO from '../../src/components/SEO'; +import { DEFAULT_SLIPPAGE_INPUT_VALUE } from 'components/Settings/MaxSlippageSettings'; + +import { visuallyHidden } from '@mui/utils'; +import { + Box, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TablePagination, + TableRow, + TableSortLabel, +} from 'soroswap-ui'; +import { shortenAddress } from 'helpers/address'; +import { relevantTokensType, tokenBalance, tokenBalances } from 'hooks'; +import useBoolean, { UseBooleanReturnProps } from 'hooks/useBoolean'; +import useGetMyBalances from 'hooks/useGetMyBalances'; +import useTable from 'hooks/useTable'; +import ClipboardComponent from 'components/Clipboard/ClipboardComponent'; +import { TokenType } from 'interfaces'; +const PageWrapper = styled(AutoColumn)` + position: relative; + background: ${({ theme }) => `linear-gradient(${theme.palette.customBackground.bg2}, ${theme.palette.customBackground.bg2 + }) padding-box, + linear-gradient(150deg, rgba(136,102,221,1) 0%, rgba(${theme.palette.mode == 'dark' ? '33,29,50,1' : '255,255,255,1' + }) 35%, rgba(${theme.palette.mode == 'dark' ? '33,29,50,1' : '255,255,255,1' + }) 65%, rgba(136,102,221,1) 100%) border-box`}; + border: 1px solid transparent; + border-radius: 16px; + padding: 32px; + transition: transform 250ms ease; + max-width: 99vw; + width: 95vw; + display: flex; + flex-direction: column; + align-items: center; + gap: 24px; +`; + +const LPTokensContainer = styled('div')` + width: calc(100% + 64px); + background-color: ${({ theme }) => theme.palette.customBackground.surface}; + min-height: 100px; + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + padding: 32px; + gap: 24px; +`; + +const LPCard = styled('div')` + background-color: ${({ theme }) => theme.palette.customBackground.bg1}; + background-color: ${({ theme }) => theme.palette.customBackground.bg1}; + border-radius: 16px; + width: 100%; + min-height: 86px; + padding: 16px 32px; + display: flex; + justify-content: space-between; + align-items: center; + cursor: pointer; +`; + +const StatusWrapper = styled('div')` + background-color: ${({ theme }) => theme.palette.customBackground.accentAction}; + font-size: 20px; + font-weight: 600; + padding: 16px; + color: ${({ theme }) => theme.palette.custom.accentTextLightPrimary}; + width: 100%; + max-width: 110px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 16px; +`; +interface TokenProps extends ImgHTMLAttributes { + token?: any; + imageUrl?: string; +} + +const TokenImage: React.FC = ({ imageUrl, ...imgProps }) => { + return ( + + ); +}; +const shortenStellarClassicAddress = (address: string) => { + const [first, last] = address.split(':'); + return `${first}:${shortenAddress(last)}`; +}; + +export const formatNumberToMoney = ( + number: number | undefined, + decimals: number = 7 +) => { + if (!number) return "-"; + + if (typeof number === "string") { + number = parseFloat(number); + } + + if (typeof number !== "number") return "$0.00"; + + if (number > 1000000000) { + return `$${(number / 1000000000).toFixed(2)}b`; + } + if (number > 1000000) { + return `$${(number / 1000000).toFixed(2)}m`; + } + if (number > 1000) { + return `$${(number / 1000).toFixed(2)}k`; + } + return `$${number.toFixed(decimals)}`; +}; + +export const shouldShortenCode = (contract: string) => { + if (!contract) return; + if (contract.length > 10) return shortenAddress(contract); + return contract; +}; +export const StyledTableCell = styled(TableCell)(({ theme }) => ({ + border: 0, + height: 10, +})); + +interface PoolsCell { + name: string; + address: string; + tvl: string; + volume24h: string; + volume7d: string; + fees24h: string; + feesYearly: string; +} + +interface HeadCell { + id: keyof PoolsCell | 'shares'; + label: string; + numeric: boolean; + align: 'left' | 'center' | 'right'; +} + +const headCells: readonly HeadCell[] = [ + { + id: 'name', + numeric: false, + label: 'Pool', + align: 'left', + }, + { + id: 'tvl', + numeric: false, + label: 'TVL', + align: 'center', + }, + { + id: 'volume24h', + numeric: false, + label: 'Volume 24h', + align: 'center', + }, + { + id: 'volume7d', + numeric: true, + label: 'Volume 7d', + align: 'center', + }, + { + id: 'fees24h', + numeric: true, + label: 'Fees 24h', + align: 'center', + }, + { + id: 'feesYearly', + numeric: true, + label: 'Fees Yearly', + align: 'center', + }, + { + id: 'shares', + numeric: true, + label: 'Shares', + align: 'center' + }, +]; +interface BalancesTableProps { + onRequestSort: ( + event: React.MouseEvent, + property: keyof PoolsCell | 'shares', + ) => void; + order: 'asc' | 'desc'; + orderBy: string; +} + +function PoolsTableHead(props: BalancesTableProps) { + const { order, orderBy, onRequestSort } = props; + const createSortHandler = + (property: keyof PoolsCell | 'shares') => (event: React.MouseEvent) => { + onRequestSort(event, property); + }; + const { address } = useSorobanReact(); + return ( + + + {headCells.map((headCell) => { + if (headCell.id === 'shares' && !address) return null; + return ( + + + {headCell.label} + {orderBy === headCell.id ? ( + + {order === 'desc' ? 'sorted descending' : 'sorted ascending'} + + ) : null} + + + ) + } + )} + {address && Action} + + + ); +} + +interface PoolData { + address: string; + fees24h: number; + feesChartData: any[]; + feesYearly: number; + reserveA: string; + reserveB: string; + tokenA: TokenType; + tokenAPrice: number; + tokenB: TokenType; + tokenBPrice: number; + tvl: number; + tvlChartData: any[]; + volume7d: number; + volume24h: number; + volumeChartData: any[]; + totalShares: number; +} + + + +function PoolsTable(props: any) { + const { nativeToken } = props; + const { tokens, tokenBalancesResponse } = useGetMyBalances(); + const { lpTokens, isLoading, mutate } = useGetLpTokens(); + + const { activeChain } = useSorobanReact() + + const [poolsData, setPoolsData] = useState([]); + + const fetchPools = async () => { + const response = await fetch(`https://info.soroswap.finance/api/pairs?network=${activeChain?.id.toUpperCase()}`); + const data = await response.json(); + setPoolsData(data); + } + const [rows, setRows] = useState([]); + const [loadingShares, setLoadingShares] = useState(true); + + useEffect(() => { + const fetchRows = async () => { + console.log('setting shares for pools') + await setLoadingShares(true); + const tempRows = await Promise.all(poolsData.map(async (x: any) => { + if (lpTokens) { + console.log('lpTokens', lpTokens) + const tempShare = lpTokens.find((lp: any) => lp.address === x.address)?.totalShares; + console.log('tempShare', tempShare) + return ({ ...x, totalShares: tempShare ?? 0 }); + } else { + return ({ ...x, totalShares: 0 }); + } + })) + setRows(tempRows); + }; + fetchRows(); + }, [poolsData, lpTokens]) + + useEffect(() => { + console.log('activeChain', activeChain) + fetchPools(); + }, [activeChain]); + + const { + order, + orderBy, + handleRequestSort, + visibleRows, + emptyRows, + rowsPerPage, + page, + handleChangePage, + handleChangeRowsPerPage, + } = useTable({ + rows, + defaultOrder: 'desc', + defaultOrderBy: 'address', + defaultRowsPerPage: 5, + }); + + const onClickRow = (pool: string) => { + // router.push(`/pools/${pool}`); + }; + + const { address } = useSorobanReact(); + + if (rows.length === 0) { + return No pools found.; + } + + return ( + + + + + {visibleRows.map((row, index) => { + return ( + onClickRow(row.address)} key={index}> + + + token.contract === row.tokenA.contract)} + size={'16px'} + style={{ marginRight: '4px' }} + /> + token.contract === row.tokenB.contract)} + size={'16px'} + style={{ marginRight: '8px' }} + /> + + + {shouldShortenCode(row.tokenA?.code)} /{" "} + {shouldShortenCode(row.tokenB?.code)} + + + {formatNumberToMoney(row.tvl, 2)} + + + {formatNumberToMoney(row.volume24h / 10 ** 7, 2)} + + + {formatNumberToMoney(row.volume7d / 10 ** 7, 2)} + + + {formatNumberToMoney(row.fees24h / 10 ** 7, 2)} + + + {formatNumberToMoney(row.feesYearly / 10 ** 7, 2)} + + {address && ( + + {(loadingShares) ? + : formatNumberToMoney(row.totalShares / 10 ** 7, 2) + } + + )} + {address && ( + + add liquidity + + )} + + ); + })} + {emptyRows > 0 && ( + + + + )} + +
+ +
+ ); +} + + +export default function LiquidityPage() { + const sorobanContext = useSorobanReact(); + const { address } = sorobanContext; + const router = useRouter(); + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down('sm')); + const { ConnectWalletModal } = useContext(AppContext); + const { isConnectWalletModalOpen, setConnectWalletModalOpen } = ConnectWalletModal; + + const v2IsLoading = false; + const noLiquidity = false; + const isCreate = false; + + const { lpTokens, isLoading, mutate } = useGetLpTokens(); + + const [isModalOpen, setModalOpen] = useState(false); + const [selectedLP, setSelectedLP] = useState(); + + const handleLPClick = (obj: LpTokensObj) => { + setSelectedLP(obj); + setModalOpen(true); + }; + + return ( + <> + + +
+ Liquidity Pools + + + Your liquidity + + +
+ List of your liquidity positions +
+
+ {!address ? ( + + + <>Connect to a wallet to view your liquidity. + + + ) : v2IsLoading ? ( + + + + <>Loading + + + + ) : lpTokens && lpTokens?.length > 0 ? ( + + {lpTokens.map((obj: any, index: number) => ( + handleLPClick(obj)} key={index}> + + + + + {obj.token_0.code} - {obj.token_1.code} + + {obj.lpPercentage}% + + {obj.status} + + ))} + + ) : isLoading ? ( + + + + ) : ( + + + <>No liquidity found. + + + )} + {address ? ( + router.push('/pools/add')}> + + Add Liquidity + + ) : ( + + )} + {/*
+ + Your liquidity + + +
+ List of your liquidity positions +
+
+ {!address ? ( + + + <>Connect to a wallet to view your liquidity. + + + ) : v2IsLoading ? ( + + + + <>Loading + + + + ) : lpTokens && lpTokens?.length > 0 ? ( + + {lpTokens.map((obj: any, index: number) => ( + handleLPClick(obj)} key={index}> + + + + + {obj.token_0.code} - {obj.token_1.code} + + {obj.lpPercentage}% + + {obj.status} + + ))} + + ) : isLoading ? ( + + + + ) : ( + + + <>No liquidity found. + + + )} + {address ? ( + router.push('/liquidity/add')}> + + Add Liquidity + + ) : ( + + )} */} +
+ setModalOpen(false)} + /> + + ); +} diff --git a/pages/liquidity/remove/[...tokens].tsx b/pages/pools/remove/[...tokens].tsx similarity index 70% rename from pages/liquidity/remove/[...tokens].tsx rename to pages/pools/remove/[...tokens].tsx index 96909d9c..e4943433 100644 --- a/pages/liquidity/remove/[...tokens].tsx +++ b/pages/pools/remove/[...tokens].tsx @@ -1,4 +1,4 @@ -import RemoveLiquidityComponent from "components/Liquidity/Remove/RemoveLiquidityComponent"; +import RemoveLiquidityComponent from "components/Pools/Remove/RemoveLiquidityComponent"; import SEO from "components/SEO"; export default function MintPage() { diff --git a/src/components/Bridge/BridgeConfirmModal.tsx b/src/components/Bridge/BridgeConfirmModal.tsx index 23b0cc4d..881d3f5a 100644 --- a/src/components/Bridge/BridgeConfirmModal.tsx +++ b/src/components/Bridge/BridgeConfirmModal.tsx @@ -14,8 +14,8 @@ import { ButtonPrimary } from 'components/Buttons/Button'; import { CloseButton } from 'components/Buttons/CloseButton'; import { AutoColumn } from 'components/Column'; import CopyTxHash from 'components/CopyTxHash/CopyTxHash'; -import { DetailRowValue } from 'components/Liquidity/Add/AddModalFooter'; -import { Label } from 'components/Liquidity/Add/AddModalHeader'; +import { DetailRowValue } from 'components/Pools/Add/AddModalFooter'; +import { Label } from 'components/Pools/Add/AddModalHeader'; import { AnimatedEntranceConfirmationIcon, LoadingIndicatorOverlay, diff --git a/src/components/Liquidity/Add/AddLiquidityComponent.tsx b/src/components/Pools/Add/AddLiquidityComponent.tsx similarity index 99% rename from src/components/Liquidity/Add/AddLiquidityComponent.tsx rename to src/components/Pools/Add/AddLiquidityComponent.tsx index cd1bfa46..dabd9fb7 100644 --- a/src/components/Liquidity/Add/AddLiquidityComponent.tsx +++ b/src/components/Pools/Add/AddLiquidityComponent.tsx @@ -271,7 +271,7 @@ export default function AddLiquidityComponent({ handleAddLiquidity, ]); - const baseRoute = `/liquidity/add/`; + const baseRoute = `/pools/add/`; const handleCurrencyASelect = useCallback( (currencyA: TokenType) => { diff --git a/src/components/Liquidity/Add/AddModalFooter.tsx b/src/components/Pools/Add/AddModalFooter.tsx similarity index 100% rename from src/components/Liquidity/Add/AddModalFooter.tsx rename to src/components/Pools/Add/AddModalFooter.tsx diff --git a/src/components/Liquidity/Add/AddModalHeader.tsx b/src/components/Pools/Add/AddModalHeader.tsx similarity index 100% rename from src/components/Liquidity/Add/AddModalHeader.tsx rename to src/components/Pools/Add/AddModalHeader.tsx diff --git a/src/components/Liquidity/AddRemoveHeader.tsx b/src/components/Pools/AddRemoveHeader.tsx similarity index 99% rename from src/components/Liquidity/AddRemoveHeader.tsx rename to src/components/Pools/AddRemoveHeader.tsx index 2fca843c..b626625e 100644 --- a/src/components/Liquidity/AddRemoveHeader.tsx +++ b/src/components/Pools/AddRemoveHeader.tsx @@ -87,7 +87,7 @@ export function AddRemoveTabs({ { // if (adding) { // // not 100% sure both of these are needed diff --git a/src/components/Liquidity/LiquidityPoolInfoModal.tsx b/src/components/Pools/LiquidityPoolInfoModal.tsx similarity index 94% rename from src/components/Liquidity/LiquidityPoolInfoModal.tsx rename to src/components/Pools/LiquidityPoolInfoModal.tsx index e99b5445..b889963a 100644 --- a/src/components/Liquidity/LiquidityPoolInfoModal.tsx +++ b/src/components/Pools/LiquidityPoolInfoModal.tsx @@ -12,7 +12,7 @@ import { formatTokenAmount } from 'helpers/format'; import { useRouter } from 'next/router'; import { LPPercentage } from './styleds'; -const ContentWrapper = styled('div')<{ isMobile: boolean }>` +const ContentWrapper = styled('div') <{ isMobile: boolean }>` display: flex; flex-direction: column; gap: 24px; @@ -37,12 +37,12 @@ export default function LiquidityPoolInfoModal({ if (!selectedLP) return null; const handleAddClick = () => { - router.push(`/liquidity/add/${selectedLP.token_0?.contract}/${selectedLP.token_1?.contract}`); + router.push(`/pools/add/${selectedLP.token_0?.contract}/${selectedLP.token_1?.contract}`); }; const handleRemoveClick = () => { router.push( - `/liquidity/remove/${selectedLP.token_0?.contract}/${selectedLP.token_1?.contract}`, + `/pools/remove/${selectedLP.token_0?.contract}/${selectedLP.token_1?.contract}`, ); }; diff --git a/src/components/Liquidity/Remove/RemoveLiquidityComponent.tsx b/src/components/Pools/Remove/RemoveLiquidityComponent.tsx similarity index 99% rename from src/components/Liquidity/Remove/RemoveLiquidityComponent.tsx rename to src/components/Pools/Remove/RemoveLiquidityComponent.tsx index 0f0eaabb..f7598763 100644 --- a/src/components/Liquidity/Remove/RemoveLiquidityComponent.tsx +++ b/src/components/Pools/Remove/RemoveLiquidityComponent.tsx @@ -144,7 +144,7 @@ export default function RemoveLiquidityComponent() { // if there was a tx hash, we want to clear the input if (txHash) { onUserInput(Field.LIQUIDITY_PERCENT, ''); - router.push('/liquidity'); + router.push('/pools'); } setTxHash(undefined); }, [onUserInput, router, txHash]); diff --git a/src/components/Liquidity/styleds.tsx b/src/components/Pools/styleds.tsx similarity index 100% rename from src/components/Liquidity/styleds.tsx rename to src/components/Pools/styleds.tsx diff --git a/src/functions/getLpTokens.tsx b/src/functions/getLpTokens.tsx index 3e2ebb51..9aabb5a3 100644 --- a/src/functions/getLpTokens.tsx +++ b/src/functions/getLpTokens.tsx @@ -44,7 +44,7 @@ const getLpResultsFromBackendPairs = async ( if (pairLpTokens != 0) { const token_0 = await findToken(element.tokenA, tokensAsMap, sorobanContext); const token_1 = await findToken(element.tokenB, tokensAsMap, sorobanContext); - + const address = element.address; const totalShares = await getTotalShares(element.address, sorobanContext); const lpPercentage = BigNumber(pairLpTokens as BigNumber) @@ -62,6 +62,7 @@ const getLpResultsFromBackendPairs = async ( .dividedBy(Number(totalShares)); const toReturn = { + address, token_0, token_1, balance: pairLpTokens, diff --git a/yarn.lock b/yarn.lock index 1f87f26b..7289a8db 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8120,10 +8120,10 @@ soroswap-router-sdk@1.4.6: tiny-invariant "^1.3.1" toformat "^2.0.0" -soroswap-ui@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/soroswap-ui/-/soroswap-ui-1.0.0.tgz#38e141745ef10c73dd287ac9a4f5a4c5db1e0085" - integrity sha512-50YxrEv+JDL4V+zgLgYrulk05zeWa0r6jtuMMxCDJHYbzxI8Klsd1Sa4eUa6FHeQ66HlwpVEwXrUReYeAK1C8A== +soroswap-ui@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/soroswap-ui/-/soroswap-ui-1.1.0.tgz#b8a78311cf9f7f64f5f6b42dcdb25f1093c43cb3" + integrity sha512-igV11/zIt+0joH8q9SCVi4oZWDTTUkHfft+3uae63HwbtV+oLz+vTn0CBy0PHhvOv5Hy0pBWkpnTsjwkil0VXA== dependencies: "@emotion/react" "^11.11.4" "@emotion/styled" "^11.11.5" From d461f9cf3ff6829b1fdff068baa700b13f30b57b Mon Sep 17 00:00:00 2001 From: Matias Poblete <86752543+MattPoblete@users.noreply.github.com> Date: Wed, 27 Nov 2024 09:08:16 -0300 Subject: [PATCH 2/4] =?UTF-8?q?=E2=9C=A8=20Add=20pools=20table?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/pools/index.tsx | 451 ++-------------------------- src/components/Pools/PoolsTable.tsx | 350 +++++++++++++++++++++ src/helpers/utils.tsx | 31 ++ 3 files changed, 402 insertions(+), 430 deletions(-) create mode 100644 src/components/Pools/PoolsTable.tsx diff --git a/pages/pools/index.tsx b/pages/pools/index.tsx index cd9167ad..e0058020 100644 --- a/pages/pools/index.tsx +++ b/pages/pools/index.tsx @@ -1,4 +1,4 @@ -import { Card, CircularProgress, Skeleton, Stack, styled, Switch, Tooltip, Typography, useMediaQuery, useTheme } from 'soroswap-ui'; +import { CircularProgress, styled, useMediaQuery, useTheme } from 'soroswap-ui'; import { useSorobanReact } from '@soroban-react/core'; import { ButtonPrimary } from 'components/Buttons/Button'; import { WalletButton } from 'components/Buttons/WalletButton'; @@ -14,29 +14,13 @@ import { AppContext } from 'contexts'; import { LpTokensObj } from 'functions/getLpTokens'; import useGetLpTokens from 'hooks/useGetLpTokens'; import { useRouter } from 'next/router'; -import { ImgHTMLAttributes, useContext, useEffect, useState } from 'react'; +import { useContext, useState } from 'react'; import SEO from '../../src/components/SEO'; import { DEFAULT_SLIPPAGE_INPUT_VALUE } from 'components/Settings/MaxSlippageSettings'; -import { visuallyHidden } from '@mui/utils'; -import { - Box, - Table, - TableBody, - TableCell, - TableContainer, - TableHead, - TablePagination, - TableRow, - TableSortLabel, -} from 'soroswap-ui'; -import { shortenAddress } from 'helpers/address'; -import { relevantTokensType, tokenBalance, tokenBalances } from 'hooks'; -import useBoolean, { UseBooleanReturnProps } from 'hooks/useBoolean'; -import useGetMyBalances from 'hooks/useGetMyBalances'; -import useTable from 'hooks/useTable'; -import ClipboardComponent from 'components/Clipboard/ClipboardComponent'; -import { TokenType } from 'interfaces'; +import { PoolsTable } from 'components/Pools/PoolsTable'; + + const PageWrapper = styled(AutoColumn)` position: relative; background: ${({ theme }) => `linear-gradient(${theme.palette.customBackground.bg2}, ${theme.palette.customBackground.bg2 @@ -94,351 +78,6 @@ const StatusWrapper = styled('div')` justify-content: center; border-radius: 16px; `; -interface TokenProps extends ImgHTMLAttributes { - token?: any; - imageUrl?: string; -} - -const TokenImage: React.FC = ({ imageUrl, ...imgProps }) => { - return ( - - ); -}; -const shortenStellarClassicAddress = (address: string) => { - const [first, last] = address.split(':'); - return `${first}:${shortenAddress(last)}`; -}; - -export const formatNumberToMoney = ( - number: number | undefined, - decimals: number = 7 -) => { - if (!number) return "-"; - - if (typeof number === "string") { - number = parseFloat(number); - } - - if (typeof number !== "number") return "$0.00"; - - if (number > 1000000000) { - return `$${(number / 1000000000).toFixed(2)}b`; - } - if (number > 1000000) { - return `$${(number / 1000000).toFixed(2)}m`; - } - if (number > 1000) { - return `$${(number / 1000).toFixed(2)}k`; - } - return `$${number.toFixed(decimals)}`; -}; - -export const shouldShortenCode = (contract: string) => { - if (!contract) return; - if (contract.length > 10) return shortenAddress(contract); - return contract; -}; -export const StyledTableCell = styled(TableCell)(({ theme }) => ({ - border: 0, - height: 10, -})); - -interface PoolsCell { - name: string; - address: string; - tvl: string; - volume24h: string; - volume7d: string; - fees24h: string; - feesYearly: string; -} - -interface HeadCell { - id: keyof PoolsCell | 'shares'; - label: string; - numeric: boolean; - align: 'left' | 'center' | 'right'; -} - -const headCells: readonly HeadCell[] = [ - { - id: 'name', - numeric: false, - label: 'Pool', - align: 'left', - }, - { - id: 'tvl', - numeric: false, - label: 'TVL', - align: 'center', - }, - { - id: 'volume24h', - numeric: false, - label: 'Volume 24h', - align: 'center', - }, - { - id: 'volume7d', - numeric: true, - label: 'Volume 7d', - align: 'center', - }, - { - id: 'fees24h', - numeric: true, - label: 'Fees 24h', - align: 'center', - }, - { - id: 'feesYearly', - numeric: true, - label: 'Fees Yearly', - align: 'center', - }, - { - id: 'shares', - numeric: true, - label: 'Shares', - align: 'center' - }, -]; -interface BalancesTableProps { - onRequestSort: ( - event: React.MouseEvent, - property: keyof PoolsCell | 'shares', - ) => void; - order: 'asc' | 'desc'; - orderBy: string; -} - -function PoolsTableHead(props: BalancesTableProps) { - const { order, orderBy, onRequestSort } = props; - const createSortHandler = - (property: keyof PoolsCell | 'shares') => (event: React.MouseEvent) => { - onRequestSort(event, property); - }; - const { address } = useSorobanReact(); - return ( - - - {headCells.map((headCell) => { - if (headCell.id === 'shares' && !address) return null; - return ( - - - {headCell.label} - {orderBy === headCell.id ? ( - - {order === 'desc' ? 'sorted descending' : 'sorted ascending'} - - ) : null} - - - ) - } - )} - {address && Action} - - - ); -} - -interface PoolData { - address: string; - fees24h: number; - feesChartData: any[]; - feesYearly: number; - reserveA: string; - reserveB: string; - tokenA: TokenType; - tokenAPrice: number; - tokenB: TokenType; - tokenBPrice: number; - tvl: number; - tvlChartData: any[]; - volume7d: number; - volume24h: number; - volumeChartData: any[]; - totalShares: number; -} - - - -function PoolsTable(props: any) { - const { nativeToken } = props; - const { tokens, tokenBalancesResponse } = useGetMyBalances(); - const { lpTokens, isLoading, mutate } = useGetLpTokens(); - - const { activeChain } = useSorobanReact() - - const [poolsData, setPoolsData] = useState([]); - - const fetchPools = async () => { - const response = await fetch(`https://info.soroswap.finance/api/pairs?network=${activeChain?.id.toUpperCase()}`); - const data = await response.json(); - setPoolsData(data); - } - const [rows, setRows] = useState([]); - const [loadingShares, setLoadingShares] = useState(true); - - useEffect(() => { - const fetchRows = async () => { - console.log('setting shares for pools') - await setLoadingShares(true); - const tempRows = await Promise.all(poolsData.map(async (x: any) => { - if (lpTokens) { - console.log('lpTokens', lpTokens) - const tempShare = lpTokens.find((lp: any) => lp.address === x.address)?.totalShares; - console.log('tempShare', tempShare) - return ({ ...x, totalShares: tempShare ?? 0 }); - } else { - return ({ ...x, totalShares: 0 }); - } - })) - setRows(tempRows); - }; - fetchRows(); - }, [poolsData, lpTokens]) - - useEffect(() => { - console.log('activeChain', activeChain) - fetchPools(); - }, [activeChain]); - - const { - order, - orderBy, - handleRequestSort, - visibleRows, - emptyRows, - rowsPerPage, - page, - handleChangePage, - handleChangeRowsPerPage, - } = useTable({ - rows, - defaultOrder: 'desc', - defaultOrderBy: 'address', - defaultRowsPerPage: 5, - }); - - const onClickRow = (pool: string) => { - // router.push(`/pools/${pool}`); - }; - - const { address } = useSorobanReact(); - - if (rows.length === 0) { - return No pools found.; - } - - return ( - - - - - {visibleRows.map((row, index) => { - return ( - onClickRow(row.address)} key={index}> - - - token.contract === row.tokenA.contract)} - size={'16px'} - style={{ marginRight: '4px' }} - /> - token.contract === row.tokenB.contract)} - size={'16px'} - style={{ marginRight: '8px' }} - /> - - - {shouldShortenCode(row.tokenA?.code)} /{" "} - {shouldShortenCode(row.tokenB?.code)} - - - {formatNumberToMoney(row.tvl, 2)} - - - {formatNumberToMoney(row.volume24h / 10 ** 7, 2)} - - - {formatNumberToMoney(row.volume7d / 10 ** 7, 2)} - - - {formatNumberToMoney(row.fees24h / 10 ** 7, 2)} - - - {formatNumberToMoney(row.feesYearly / 10 ** 7, 2)} - - {address && ( - - {(loadingShares) ? - : formatNumberToMoney(row.totalShares / 10 ** 7, 2) - } - - )} - {address && ( - - add liquidity - - )} - - ); - })} - {emptyRows > 0 && ( - - - - )} - -
- -
- ); -} export default function LiquidityPage() { @@ -469,15 +108,17 @@ export default function LiquidityPage() {
- Liquidity Pools - - Your liquidity - + Liquidity Pools + {address ? ( + router.push('/pools/add')}> + + Add Liquidity + + ) : ( + + )} -
- List of your liquidity positions -
+
{!address ? ( @@ -495,6 +136,13 @@ export default function LiquidityPage() { ) : lpTokens && lpTokens?.length > 0 ? ( + + Your liquidity + + +
+ List of your liquidity positions +
{lpTokens.map((obj: any, index: number) => ( handleLPClick(obj)} key={index}> @@ -527,63 +175,6 @@ export default function LiquidityPage() { ) : ( )} - {/*
- - Your liquidity - - -
- List of your liquidity positions -
-
- {!address ? ( - - - <>Connect to a wallet to view your liquidity. - - - ) : v2IsLoading ? ( - - - - <>Loading - - - - ) : lpTokens && lpTokens?.length > 0 ? ( - - {lpTokens.map((obj: any, index: number) => ( - handleLPClick(obj)} key={index}> - - - - - {obj.token_0.code} - {obj.token_1.code} - - {obj.lpPercentage}% - - {obj.status} - - ))} - - ) : isLoading ? ( - - - - ) : ( - - - <>No liquidity found. - - - )} - {address ? ( - router.push('/liquidity/add')}> - + Add Liquidity - - ) : ( - - )} */}
, + property: keyof PoolsCell | 'shares', + ) => void; + order: 'asc' | 'desc'; + orderBy: string; +} +export const StyledTableCell = styled(TableCell)(({ theme }) => ({ + border: 0, + height: 10, +})); + +function PoolsTableHead(props: BalancesTableProps) { + const { order, orderBy, onRequestSort } = props; + const createSortHandler = + (property: keyof PoolsCell | 'shares') => (event: React.MouseEvent) => { + onRequestSort(event, property); + }; + const { address } = useSorobanReact(); + return ( + + + {headCells.map((headCell) => { + if (headCell.id === 'totalShares' && !address) return null; + return ( + + + {headCell.label} + {orderBy === headCell.id ? ( + + {order === 'desc' ? 'sorted descending' : 'sorted ascending'} + + ) : null} + + + ) + } + )} + {address && Action} + + + ); +} + +export function PoolsTable(props: any) { + const { nativeToken } = props; + const { tokens, tokenBalancesResponse } = useGetMyBalances(); + const { lpTokens, isLoading, mutate } = useGetLpTokens(); + const router = useRouter(); + const { address } = useSorobanReact(); + const { activeChain } = useSorobanReact() + const [rows, setRows] = useState([]); + const [loadingShares, setLoadingShares] = useState(true); + const [isModalOpen, setModalOpen] = useState(false); + const [selectedLP, setSelectedLP] = useState(); + + const { + order, + orderBy, + handleRequestSort, + visibleRows, + emptyRows, + rowsPerPage, + page, + handleChangePage, + handleChangeRowsPerPage, + } = useTable({ + rows, + defaultOrder: 'desc', + defaultOrderBy: 'totalShares', + defaultRowsPerPage: 5, + }); + + useEffect(() => { + const fetchPools = async () => { + const response = await fetch(`https://info.soroswap.finance/api/pairs?network=${activeChain?.id.toUpperCase()}`); + if (address && lpTokens) { + response.json().then((data) => { + const pools = data.map((pool: any) => { + const tempShare = lpTokens?.find((lpToken: any) => lpToken.address === pool.address)?.balance; + return { + ...pool, + totalShares: tempShare ?? 0, + }; + }); + setRows(pools); + setLoadingShares(false); + }) + } else { + response.json().then((data) => { + setRows(data); + }) + } + } + fetchPools(); + }, [activeChain, address, lpTokens]); + + + const handleLPClick = (obj: any) => { + const parsedData: LpTokensObj = { + token_0: obj.tokenA, + token_1: obj.tokenB, + balance: obj.totalShares, + lpPercentage: obj.totalShares, + status: 'Active', + reserve0: obj.reserveA, + reserve1: obj.reserveB, + totalShares: obj.totalShares, + myReserve0: obj.reserveA, + myReserve1: obj.reserveB, + }; + setSelectedLP(parsedData); + setModalOpen(true); + }; + + if (rows.length === 0) { + return No pools found.; + } + const tableButtonStyle = { height: 10, fontSize: 12, width: 120, justifySelf: 'center', borderRadius: 16 } + return ( + + + + + {visibleRows.map((row, index) => { + return ( + + + + token.contract === row.tokenA.contract)} + size={'16px'} + style={{ marginRight: '4px' }} + /> + token.contract === row.tokenB.contract)} + size={'16px'} + style={{ marginRight: '8px' }} + /> + + + {shouldShortenCode(row.tokenA?.code)} /{" "} + {shouldShortenCode(row.tokenB?.code)} + + + {formatNumberToMoney(row.tvl, 2)} + + + {formatNumberToMoney(row.volume24h / 10 ** 7, 2)} + + + {formatNumberToMoney(row.volume7d / 10 ** 7, 2)} + + + {formatNumberToMoney(row.fees24h / 10 ** 7, 2)} + + + {formatNumberToMoney(row.feesYearly / 10 ** 7, 2)} + + {address && ( + + {(loadingShares || isLoading) ? + : formatNumberToMoney(row.totalShares / 10 ** 7, 2) + } + + )} + {address && ( + + {(loadingShares || isLoading) && + + } + {row.totalShares === 0 && ( + router.push(`pools/add/${row.tokenA.contract}/${row.tokenB.contract}`)}> + + Add Liquidity + + )} + {row.totalShares > 0 && ( + handleLPClick(row)}> + Manage + + )} + + )} + + ); + })} + {emptyRows > 0 && ( + + + + )} + +
+ + setModalOpen(false)} + /> +
+ ); +} \ No newline at end of file diff --git a/src/helpers/utils.tsx b/src/helpers/utils.tsx index 7aa35a54..34484d74 100644 --- a/src/helpers/utils.tsx +++ b/src/helpers/utils.tsx @@ -1,6 +1,7 @@ import BigNumber from 'bignumber.js'; import * as StellarSdk from '@stellar/stellar-sdk'; import { I128 } from './xdr'; +import { shortenAddress } from './address'; let xdr = StellarSdk.xdr; @@ -203,3 +204,33 @@ export function bigNumberToU32(value: BigNumber): StellarSdk.xdr.ScVal { return xdr.ScVal.scvU32(num); } + +export const formatNumberToMoney = ( + number: number | undefined, + decimals: number = 7 +) => { + if (!number) return "-"; + + if (typeof number === "string") { + number = parseFloat(number); + } + + if (typeof number !== "number") return "$0.00"; + + if (number > 1000000000) { + return `$${(number / 1000000000).toFixed(2)}b`; + } + if (number > 1000000) { + return `$${(number / 1000000).toFixed(2)}m`; + } + if (number > 1000) { + return `$${(number / 1000).toFixed(2)}k`; + } + return `$${number.toFixed(decimals)}`; +}; + +export const shouldShortenCode = (contract: string) => { + if (!contract) return; + if (contract.length > 10) return shortenAddress(contract); + return contract; +}; From bb838099b763d1456f92f0aef78261282685d974 Mon Sep 17 00:00:00 2001 From: Matias Poblete <86752543+MattPoblete@users.noreply.github.com> Date: Tue, 10 Dec 2024 09:14:39 -0300 Subject: [PATCH 3/4] =?UTF-8?q?=E2=9C=A8=20Add=20loading=20skeleton,=20tvl?= =?UTF-8?q?=20as=20default=20sorting=20&=20token=20list=20filter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Pools/PoolsTable.tsx | 95 +++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 6 deletions(-) diff --git a/src/components/Pools/PoolsTable.tsx b/src/components/Pools/PoolsTable.tsx index 49e13edc..4c124bd9 100644 --- a/src/components/Pools/PoolsTable.tsx +++ b/src/components/Pools/PoolsTable.tsx @@ -29,6 +29,7 @@ import { styled } from 'soroswap-ui'; import { visuallyHidden } from '@mui/utils'; +import { fetchTokens } from 'services/tokens'; interface PoolData { @@ -173,6 +174,7 @@ export function PoolsTable(props: any) { const { address } = useSorobanReact(); const { activeChain } = useSorobanReact() const [rows, setRows] = useState([]); + const [loadingRows, setLoadingRows] = useState(true); const [loadingShares, setLoadingShares] = useState(true); const [isModalOpen, setModalOpen] = useState(false); const [selectedLP, setSelectedLP] = useState(); @@ -190,15 +192,38 @@ export function PoolsTable(props: any) { } = useTable({ rows, defaultOrder: 'desc', - defaultOrderBy: 'totalShares', + defaultOrderBy: 'tvl', defaultRowsPerPage: 5, }); + const filterTokens = async (rows: any) => { + if (!activeChain) return; + let allowedTokens = await fetchTokens(activeChain?.id).then((data) => { + switch (activeChain?.id) { + case 'testnet': + return data[1].assets; + case 'mainnet': + return data.assets; + default: + return data; + } + }); + console.log(rows) + console.log(allowedTokens) + const filteredRows = rows.filter((row: any) => + allowedTokens.some((token: any) => token.contract === row.tokenA.contract) && + allowedTokens.some((token: any) => token.contract === row.tokenB.contract) || + allowedTokens.some((token: any) => token.contract === row.tokenB.contract) && + allowedTokens.some((token: any) => token.contract === row.tokenA.contract) + ); + return filteredRows; + } + useEffect(() => { const fetchPools = async () => { const response = await fetch(`https://info.soroswap.finance/api/pairs?network=${activeChain?.id.toUpperCase()}`); if (address && lpTokens) { - response.json().then((data) => { + response.json().then(async (data) => { const pools = data.map((pool: any) => { const tempShare = lpTokens?.find((lpToken: any) => lpToken.address === pool.address)?.balance; return { @@ -206,14 +231,17 @@ export function PoolsTable(props: any) { totalShares: tempShare ?? 0, }; }); - setRows(pools); + const filteredTokens = await filterTokens(pools); + setRows(filteredTokens); setLoadingShares(false); }) } else { - response.json().then((data) => { - setRows(data); + response.json().then(async (data) => { + const filteredTokens = await filterTokens(data); + setRows(filteredTokens); }) } + setLoadingRows(false); } fetchPools(); }, [activeChain, address, lpTokens]); @@ -236,9 +264,64 @@ export function PoolsTable(props: any) { setModalOpen(true); }; - if (rows.length === 0) { + if (rows.length === 0 && !loadingRows) { return No pools found.; } + if (rows.length === 0 && loadingRows) { + const skeletonRow = () => { + return ( + + + + + + + + + + + + + + + + + + + + {address && ( + <> + + + + + + + + + )} + + ) + } + return ( + + + + + {skeletonRow()} + {skeletonRow()} + {skeletonRow()} + {skeletonRow()} + {skeletonRow()} + +
+
) + } + const tableButtonStyle = { height: 10, fontSize: 12, width: 120, justifySelf: 'center', borderRadius: 16 } return ( From 77842d4d1972a66460df67a43bb85ee09114bd43 Mon Sep 17 00:00:00 2001 From: Matias Poblete <86752543+MattPoblete@users.noreply.github.com> Date: Tue, 10 Dec 2024 09:16:28 -0300 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=94=A5Remove=20unused=20logs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Pools/PoolsTable.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/Pools/PoolsTable.tsx b/src/components/Pools/PoolsTable.tsx index 4c124bd9..b7e9158f 100644 --- a/src/components/Pools/PoolsTable.tsx +++ b/src/components/Pools/PoolsTable.tsx @@ -208,8 +208,6 @@ export function PoolsTable(props: any) { return data; } }); - console.log(rows) - console.log(allowedTokens) const filteredRows = rows.filter((row: any) => allowedTokens.some((token: any) => token.contract === row.tokenA.contract) && allowedTokens.some((token: any) => token.contract === row.tokenB.contract) ||