From 8eaeefb1243791b9bca7ec6512843b9da876e0c1 Mon Sep 17 00:00:00 2001 From: jakubkowolik Date: Mon, 24 Feb 2025 14:12:55 +0100 Subject: [PATCH 1/4] added prices to selectTokenModal --- .../SelectTokenModal/SelectTokenModal.tsx | 112 ++++++++++++------ 1 file changed, 74 insertions(+), 38 deletions(-) diff --git a/src/components/Modals/SelectModals/SelectTokenModal/SelectTokenModal.tsx b/src/components/Modals/SelectModals/SelectTokenModal/SelectTokenModal.tsx index 41f9f228..132e27cc 100644 --- a/src/components/Modals/SelectModals/SelectTokenModal/SelectTokenModal.tsx +++ b/src/components/Modals/SelectModals/SelectTokenModal/SelectTokenModal.tsx @@ -16,7 +16,7 @@ import { Typography, useMediaQuery } from '@mui/material' -import { formatNumberWithSuffix, printBN } from '@utils/utils' +import { formatNumberWithSuffix, getTokenPrice, printBN } from '@utils/utils' import { SwapToken } from '@store/selectors/solanaWallet' import Scrollbars from 'rc-scrollbars' import icons from '@static/icons' @@ -77,10 +77,10 @@ export const SelectTokenModal: React.FC = memo( }) => { const { classes } = useStyles() const isXs = useMediaQuery(theme.breakpoints.down('sm')) - const [value, setValue] = useState('') const [isAddOpen, setIsAddOpen] = useState(false) const [hideUnknown, setHideUnknown] = useState(initialHideUnknownTokensValue) + const [prices, setPrices] = useState>({}) const outerRef = useRef(null) const inputRef = useRef(null) @@ -99,6 +99,21 @@ export const SelectTokenModal: React.FC = memo( [tokens] ) + useEffect(() => { + tokensWithIndexes.forEach(token => { + const balanceStr = printBN(token.balance, token.decimals) + const balance = Number(balanceStr) + if (balance > 0) { + const addr = token.assetAddress.toString() + if (prices[addr] === undefined) { + getTokenPrice(addr).then(price => { + setPrices(prev => ({ ...prev, [addr]: price || 0 })) + }) + } + } + }) + }, [tokensWithIndexes]) + const commonTokensList = useMemo( () => tokensWithIndexes.filter( @@ -108,42 +123,47 @@ export const SelectTokenModal: React.FC = memo( ) const filteredTokens = useMemo(() => { - const list = tokensWithIndexes.filter(token => { - return ( + const list = tokensWithIndexes.filter( + token => token.symbol.toLowerCase().includes(value.toLowerCase()) || token.name.toLowerCase().includes(value.toLowerCase()) || token.strAddress.includes(value) - ) + ) + + const tokensWithPrice = list.filter(token => { + const price = prices[token.assetAddress.toString()] + return price !== undefined && price > 0 }) - const sorted = list.sort((a, b) => { - const aBalance = +printBN(a.balance, a.decimals) - const bBalance = +printBN(b.balance, b.decimals) - if ((aBalance === 0 && bBalance === 0) || (aBalance > 0 && bBalance > 0)) { - if (value.length) { - if ( - a.symbol.toLowerCase().startsWith(value.toLowerCase()) && - !b.symbol.toLowerCase().startsWith(value.toLowerCase()) - ) { - return -1 - } + const tokensNoPrice = list.filter(token => { + const price = prices[token.assetAddress.toString()] + return price === undefined || price === 0 + }) - if ( - b.symbol.toLowerCase().startsWith(value.toLowerCase()) && - !a.symbol.toLowerCase().startsWith(value.toLowerCase()) - ) { - return 1 - } - } + tokensWithPrice.sort((a, b) => { + const aNative = +printBN(a.balance, a.decimals) + const bNative = +printBN(b.balance, b.decimals) + const aPrice = prices[a.assetAddress.toString()]! + const bPrice = prices[b.assetAddress.toString()]! + const aUSD = aNative * aPrice + const bUSD = bNative * bPrice - return a.symbol.toLowerCase().localeCompare(b.symbol.toLowerCase()) - } + if (aUSD !== bUSD) return bUSD - aUSD + if (aNative !== bNative) return bNative - aNative + return a.symbol.toLowerCase().localeCompare(b.symbol.toLowerCase()) + }) - return aBalance === 0 ? 1 : -1 + tokensNoPrice.sort((a, b) => { + const aNative = +printBN(a.balance, a.decimals) + const bNative = +printBN(b.balance, b.decimals) + if (aNative !== bNative) return bNative - aNative + return a.symbol.toLowerCase().localeCompare(b.symbol.toLowerCase()) }) + const sorted = [...tokensWithPrice, ...tokensNoPrice] + return hideUnknown ? sorted.filter(token => !token.isUnknown) : sorted - }, [value, tokens, hideUnknown, open]) + }, [value, tokensWithIndexes, hideUnknown, prices]) const searchToken = (e: React.ChangeEvent) => { setValue(e.target.value) @@ -290,6 +310,8 @@ export const SelectTokenModal: React.FC = memo( {({ index, style }: { index: number; style: React.CSSProperties }) => { const token = filteredTokens[index] const tokenBalance = printBN(token.balance, token.decimals) + const price = prices[token.assetAddress.toString()] + const usdBalance = price ? Number(tokenBalance) * price : 0 return ( = memo( {token.name.length > (isXs ? 20 : 30) ? '...' : ''} - - {!hideBalances && Number(tokenBalance) > 0 ? ( - <> - Balance: -   {formatNumberWithSuffix(tokenBalance)} - - ) : null} + + + {!hideBalances && Number(tokenBalance) > 0 ? ( + <> + Balance: +   {formatNumberWithSuffix(tokenBalance)} + + ) : null} + + + {!hideBalances && Number(tokenBalance) > 0 ? ( + <> + ~$ + {formatNumberWithSuffix(usdBalance)} + + ) : null} + ) From 412203443c4d2d1cd1534856b18c52e9b85aed22 Mon Sep 17 00:00:00 2001 From: Jakub Kowolik Date: Mon, 24 Feb 2025 18:52:33 +0100 Subject: [PATCH 2/4] rounding to 2 decimals --- .../Modals/SelectModals/SelectTokenModal/SelectTokenModal.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/Modals/SelectModals/SelectTokenModal/SelectTokenModal.tsx b/src/components/Modals/SelectModals/SelectTokenModal/SelectTokenModal.tsx index 132e27cc..1bb09dbe 100644 --- a/src/components/Modals/SelectModals/SelectTokenModal/SelectTokenModal.tsx +++ b/src/components/Modals/SelectModals/SelectTokenModal/SelectTokenModal.tsx @@ -388,7 +388,9 @@ export const SelectTokenModal: React.FC = memo( {!hideBalances && Number(tokenBalance) > 0 ? ( <> ~$ - {formatNumberWithSuffix(usdBalance)} + + {formatNumberWithSuffix(usdBalance.toFixed(2))} + ) : null} From f53054d2d326445b3d50151d3f091cb192995a4c Mon Sep 17 00:00:00 2001 From: jakubkowolik Date: Tue, 25 Feb 2025 12:16:22 +0100 Subject: [PATCH 3/4] design chagned --- .../SelectTokenModal/SelectTokenModal.tsx | 5 ++-- .../SelectModals/SelectTokenModal/style.ts | 6 ++-- src/components/Modals/SelectModals/style.ts | 30 ++++++++++++------- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/components/Modals/SelectModals/SelectTokenModal/SelectTokenModal.tsx b/src/components/Modals/SelectModals/SelectTokenModal/SelectTokenModal.tsx index 3bf44da0..d08abc6e 100644 --- a/src/components/Modals/SelectModals/SelectTokenModal/SelectTokenModal.tsx +++ b/src/components/Modals/SelectModals/SelectTokenModal/SelectTokenModal.tsx @@ -129,7 +129,6 @@ const RowItem: React.FC> = React.memo( className={classes.tokenBalanceStatus}> {!hideBalances && Number(tokenBalance) > 0 ? ( <> - Balance:   {formatNumberWithSuffix(tokenBalance)} ) : null} @@ -138,10 +137,10 @@ const RowItem: React.FC> = React.memo( container justifyContent='flex-end' wrap='wrap' - className={classes.tokenBalanceStatus}> + className={classes.tokenBalanceUSDStatus}> {!hideBalances && Number(tokenBalance) > 0 ? ( <> - ~$ + $ {usdBalance.toFixed(2)} ) : null} diff --git a/src/components/Modals/SelectModals/SelectTokenModal/style.ts b/src/components/Modals/SelectModals/SelectTokenModal/style.ts index ba7fdeb8..e1f8e202 100644 --- a/src/components/Modals/SelectModals/SelectTokenModal/style.ts +++ b/src/components/Modals/SelectModals/SelectTokenModal/style.ts @@ -216,9 +216,9 @@ const useStyles = makeStyles()((theme: Theme) => { }, tokenIcon: { - minWidth: 30, - maxWidth: 30, - height: 30, + minWidth: 36, + maxWidth: 36, + height: 36, marginRight: 16, borderRadius: '50%', boxShadow: '0px 0px 10px rgba(216, 255, 181, 0.5)' diff --git a/src/components/Modals/SelectModals/style.ts b/src/components/Modals/SelectModals/style.ts index 4c71a4d0..6fa5692c 100644 --- a/src/components/Modals/SelectModals/style.ts +++ b/src/components/Modals/SelectModals/style.ts @@ -166,7 +166,7 @@ const useStyles = makeStyles()((theme: Theme) => { }, tokenName: { color: colors.white.main, - ...typography.heading4 + ...typography.heading3 }, tokenAddress: { backgroundColor: colors.invariant.newDark, @@ -196,33 +196,41 @@ const useStyles = makeStyles()((theme: Theme) => { }, tokenDescrpiption: { color: colors.invariant.textGrey, + opacity: 0.5, ...typography.caption2, lineHeight: '16px', whiteSpace: 'nowrap' }, tokenBalanceStatus: { + color: colors.invariant.text, + maxHeight: 40, + opacity: 0.85, + '& p': { + ...typography.heading4 + } + }, + tokenBalanceUSDStatus: { color: colors.invariant.textGrey, + opacity: 0.85, maxHeight: 40, '& p': { ...typography.body2 - }, - - '& p:last-child': { - color: colors.invariant.text } }, imageContainer: { - minWidth: 30, - maxWidth: 30, - height: 30, + minWidth: 36, + maxWidth: 36, + height: 36, + width: 36, marginRight: 16, position: 'relative' }, tokenIcon: { - minWidth: 30, - maxWidth: 30, - height: 30, + minWidth: 36, + maxWidth: 36, + height: 36, + width: 36, marginRight: 16, borderRadius: '50%', boxShadow: '0px 0px 10px rgba(216, 255, 181, 0.5)' From 968f31c93dd621ae859736ebaa7912849c70553c Mon Sep 17 00:00:00 2001 From: jakubkowolik Date: Tue, 25 Feb 2025 13:45:03 +0100 Subject: [PATCH 4/4] wrap changed --- .../SelectTokenModal/SelectTokenModal.tsx | 39 +++++++------------ .../SelectModals/SelectTokenModal/style.ts | 6 ++- src/components/Modals/SelectModals/style.ts | 39 +++++++++++++------ 3 files changed, 45 insertions(+), 39 deletions(-) diff --git a/src/components/Modals/SelectModals/SelectTokenModal/SelectTokenModal.tsx b/src/components/Modals/SelectModals/SelectTokenModal/SelectTokenModal.tsx index d08abc6e..0a409930 100644 --- a/src/components/Modals/SelectModals/SelectTokenModal/SelectTokenModal.tsx +++ b/src/components/Modals/SelectModals/SelectTokenModal/SelectTokenModal.tsx @@ -107,9 +107,9 @@ const RowItem: React.FC> = React.memo( event.stopPropagation() }}> - {token.assetAddress.toString().slice(0, 4) + + {token.assetAddress.toString().slice(0, isXs ? 3 : 4) + '...' + - token.assetAddress.toString().slice(-5, -1)} + token.assetAddress.toString().slice(isXs ? -4 : -5, -1)} {'Token @@ -121,30 +121,17 @@ const RowItem: React.FC> = React.memo( {token.name.length > (isXs ? 20 : 30) ? '...' : ''} - - - {!hideBalances && Number(tokenBalance) > 0 ? ( - <> -   {formatNumberWithSuffix(tokenBalance)} - - ) : null} - - - {!hideBalances && Number(tokenBalance) > 0 ? ( - <> - $ - {usdBalance.toFixed(2)} - - ) : null} - + + {!hideBalances && Number(tokenBalance) > 0 ? ( + <> + + {formatNumberWithSuffix(tokenBalance)} + + + ${usdBalance.toFixed(2)} + + + ) : null} ) diff --git a/src/components/Modals/SelectModals/SelectTokenModal/style.ts b/src/components/Modals/SelectModals/SelectTokenModal/style.ts index e1f8e202..137f962f 100644 --- a/src/components/Modals/SelectModals/SelectTokenModal/style.ts +++ b/src/components/Modals/SelectModals/SelectTokenModal/style.ts @@ -219,9 +219,11 @@ const useStyles = makeStyles()((theme: Theme) => { minWidth: 36, maxWidth: 36, height: 36, - marginRight: 16, + marginRight: 12, borderRadius: '50%', - boxShadow: '0px 0px 10px rgba(216, 255, 181, 0.5)' + [theme.breakpoints.up('sm')]: { + boxShadow: '0px 0px 10px rgba(216, 255, 181, 0.5)' + } }, tokenBalance: { ...typography.body2, diff --git a/src/components/Modals/SelectModals/style.ts b/src/components/Modals/SelectModals/style.ts index 6fa5692c..78273df4 100644 --- a/src/components/Modals/SelectModals/style.ts +++ b/src/components/Modals/SelectModals/style.ts @@ -21,7 +21,7 @@ const useStyles = makeStyles()((theme: Theme) => { width: 500, [theme.breakpoints.down('sm')]: { maxWidth: '100vw', - padding: '20px 16px' + padding: '20px 12px' }, '.MuiFormControlLabel-label': { color: colors.invariant.lightGrey, @@ -144,7 +144,9 @@ const useStyles = makeStyles()((theme: Theme) => { tokenContainer: { display: 'flex', flexDirection: 'column', - minWidth: 'min-content' + minWidth: 'min-content', + flexGrow: 1, + overflow: 'hidden' }, tokenItem: { @@ -153,7 +155,12 @@ const useStyles = makeStyles()((theme: Theme) => { marginBottom: 4, borderRadius: 24, cursor: 'pointer', - padding: '0 16px ', + padding: '0 12px', + position: 'relative', + overflow: 'hidden', + [theme.breakpoints.down('sm')]: { + padding: 0 + }, '& > p': { whiteSpace: 'nowrap' @@ -166,7 +173,10 @@ const useStyles = makeStyles()((theme: Theme) => { }, tokenName: { color: colors.white.main, - ...typography.heading3 + ...typography.heading3, + [theme.breakpoints.down('sm')]: { + ...typography.heading4 + } }, tokenAddress: { backgroundColor: colors.invariant.newDark, @@ -174,11 +184,15 @@ const useStyles = makeStyles()((theme: Theme) => { padding: '2px 4px', width: 'min-content', height: 'min-content', + whiteSpace: 'nowrap', '& a': { display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '12px', + [theme.breakpoints.down('sm')]: { + gap: '6px' + }, textDecoration: 'none', '&:hover': { @@ -194,6 +208,7 @@ const useStyles = makeStyles()((theme: Theme) => { } } }, + tokenDescrpiption: { color: colors.invariant.textGrey, opacity: 0.5, @@ -205,17 +220,16 @@ const useStyles = makeStyles()((theme: Theme) => { color: colors.invariant.text, maxHeight: 40, opacity: 0.85, - '& p': { - ...typography.heading4 - } + ...typography.heading4, + whiteSpace: 'nowrap' }, + tokenBalanceUSDStatus: { color: colors.invariant.textGrey, opacity: 0.85, maxHeight: 40, - '& p': { - ...typography.body2 - } + whiteSpace: 'nowrap', + ...typography.body2 }, imageContainer: { @@ -224,6 +238,9 @@ const useStyles = makeStyles()((theme: Theme) => { height: 36, width: 36, marginRight: 16, + [theme.breakpoints.down('sm')]: { + marginRight: 12 + }, position: 'relative' }, tokenIcon: { @@ -245,7 +262,7 @@ const useStyles = makeStyles()((theme: Theme) => { tokenBalance: { ...typography.body2, color: colors.invariant.textGrey, - whiteSpace: 'nowrap' + overflow: 'visible' }, searchIcon: { color: colors.invariant.light