diff --git a/src/common/FilterSearch/Helpers/TokenOption.tsx b/src/common/FilterSearch/Helpers/TokenOption.tsx index 3854dd2..9d1cf39 100644 --- a/src/common/FilterSearch/Helpers/TokenOption.tsx +++ b/src/common/FilterSearch/Helpers/TokenOption.tsx @@ -32,15 +32,15 @@ export const TokenOption: React.FC<{ {shortenAddress(option.symbol)} - - {shortenAddress(option.address)} - event.stopPropagation()}> + + {shortenAddress(option.address)} + Token address diff --git a/src/common/Pagination/InputPagination/style.tsx b/src/common/Pagination/InputPagination/style.tsx index 812f456..1efdc40 100644 --- a/src/common/Pagination/InputPagination/style.tsx +++ b/src/common/Pagination/InputPagination/style.tsx @@ -119,7 +119,7 @@ export const useStyles = makeStyles<{ fontWeight: 700, borderRadius: 4, appearance: 'textfield !important' as 'textfield', - border: `3px solid ${colors.invariant.green}`, + border: `3px solid ${colors.invariant.light}`, '&::-webkit-inner-spin-button, &::-webkit-outer-spin-button': { WebkitAppearance: 'none', margin: 0 diff --git a/src/common/Popover/CustomPopover.tsx b/src/common/Popover/CustomPopover.tsx new file mode 100644 index 0000000..e413e97 --- /dev/null +++ b/src/common/Popover/CustomPopover.tsx @@ -0,0 +1,113 @@ +import { Popover, Box, PopoverProps } from '@mui/material' +import { useState } from 'react' +import useStyles from './style' +import GradientBorder from '@common/GradientBorder/GradientBorder' + +interface CustomPopoverProps { + children: React.ReactElement + content: React.ReactNode + top?: number | string + left?: number | string + right?: number | string + bottom?: number | string + fullSpan?: boolean + gradient?: boolean + increasePadding?: boolean + maxWidth?: string | number + centerOnScreen?: boolean + textAlign?: 'left' | 'center' | 'right' + popoverProps?: Partial +} +export const CustomPopover = ({ + children, + content, + top, + left, + right, + bottom, + fullSpan = false, + gradient = false, + increasePadding = false, + maxWidth, + centerOnScreen = false, + textAlign = 'left', + ...props +}: CustomPopoverProps) => { + const { classes } = useStyles({ + top, + left, + right, + bottom, + fullSpan, + increasePadding, + maxWidth + }) + + const [anchorEl, setAnchorEl] = useState(null) + const [open, setOpen] = useState(false) + + const handleClick = (event: React.MouseEvent) => { + event.stopPropagation() + if (centerOnScreen) { + setOpen(prev => !prev) + } else { + setAnchorEl(prev => (prev ? null : event.currentTarget)) + setOpen(prev => !prev) + } + } + + const handleClose = () => { + setOpen(false) + setAnchorEl(null) + } + + return ( + <> + + {children} + + + + + + { + e.stopPropagation() + setOpen(false) + }}> + {content} + + + + + + ) +} diff --git a/src/common/Popover/style.ts b/src/common/Popover/style.ts new file mode 100644 index 0000000..cde44f8 --- /dev/null +++ b/src/common/Popover/style.ts @@ -0,0 +1,39 @@ +import { makeStyles } from 'tss-react/mui' +import { colors } from '@static/theme' + +const useStyles = makeStyles<{ + top?: number | string + left?: number | string + right?: number | string + bottom?: number | string + fullSpan?: boolean + increasePadding?: boolean + maxWidth?: string | number +}>()((_theme, { top, left, right, bottom, fullSpan, increasePadding, maxWidth }) => ({ + popover: { + minWidth: 'fit-content', + background: 'none', + top: top ? top : 'auto', + left: left ? left : 'auto', + right: right ? right : 'auto', + bottom: bottom ? bottom : 'auto', + padding: 0, + margin: 8 + }, + contentBox: { + padding: increasePadding ? '16px 24px' : '8px 12px', + background: colors.invariant.component, + overflow: 'hidden', + borderRadius: 12, + pointerEvents: 'auto', + maxWidth: maxWidth || 'none' + }, + tooltipSpan: { + width: fullSpan ? '100%' : 'auto', + display: 'inline-flex', + margin: 0, + padding: 0 + } +})) + +export default useStyles diff --git a/src/common/TooltipHover/style.ts b/src/common/TooltipHover/style.ts index cee9763..e73ee5c 100644 --- a/src/common/TooltipHover/style.ts +++ b/src/common/TooltipHover/style.ts @@ -16,7 +16,6 @@ const useStyles = makeStyles<{ borderRadius: 12, background: colors.invariant.component, ...typography.body2, - color: colors.invariant.textGrey, padding: increasePadding ? '16px 24px' : '8px 12px', top: top ? top : 'auto', left: left ? left : 'auto', @@ -44,7 +43,6 @@ const useStyles = makeStyles<{ borderRadius: 14, background: colors.invariant.component, ...typography.body2, - color: colors.invariant.textGrey, top: top ? top : 0, left: left ? left : 'auto', right: right ? right : 'auto', diff --git a/src/components/Inputs/RangeInput/RangeInput.tsx b/src/components/Inputs/RangeInput/RangeInput.tsx index 10332f1..6a02c8d 100644 --- a/src/components/Inputs/RangeInput/RangeInput.tsx +++ b/src/components/Inputs/RangeInput/RangeInput.tsx @@ -4,9 +4,8 @@ import RemoveIcon from '@mui/icons-material/Remove' import useStyles from './style' import { colors } from '@static/theme' import { Button, Grid, Input, Typography } from '@mui/material' -import { formatNumbers } from '@utils/utils' import AnimatedNumber from '@common/AnimatedNumber/AnimatedNumber' -import { FormatNumberThreshold } from '@store/consts/types' +import { formatNumberWithSuffix } from '@utils/utils' export interface IRangeInput { label: string @@ -85,36 +84,6 @@ export const RangeInput: React.FC = ({ } } - const percentageThresholds: FormatNumberThreshold[] = [ - { - value: 10, - decimals: 2 - }, - { - value: 1000, - decimals: 2 - }, - { - value: 10000, - decimals: 2 - }, - { - value: 1000000, - decimals: 2, - divider: 1000 - }, - { - value: 1000000000, - decimals: 2, - divider: 1000000 - }, - { - value: Infinity, - decimals: 2, - divider: 1000000000 - } - ] - return ( @@ -161,7 +130,13 @@ export const RangeInput: React.FC = ({ {percentDiff ? ( formatNumbers(percentageThresholds)(e.toString())} + format={e => + formatNumberWithSuffix(e.toString(), { + decimalsAfterDot: 2, + noSubNumbers: true, + alternativeConfig: true + }) + } duration={300} /> ) : ( diff --git a/src/components/Inputs/SimpleInput/SimpleInput.tsx b/src/components/Inputs/SimpleInput/SimpleInput.tsx index ce26cb7..c18c4fa 100644 --- a/src/components/Inputs/SimpleInput/SimpleInput.tsx +++ b/src/components/Inputs/SimpleInput/SimpleInput.tsx @@ -97,7 +97,11 @@ export const SimpleInput: React.FC = ({ onClick={() => { setValue(formatterFunction(suggestedPrice.toString())) }}> -

Suggested price

+

+ {value?.toString() === formatterFunction(suggestedPrice.toString()) + ? 'Existing price applied' + : 'Use existing price'} +

) : null diff --git a/src/components/Inputs/SimpleInput/style.ts b/src/components/Inputs/SimpleInput/style.ts index a921afc..ca9c249 100644 --- a/src/components/Inputs/SimpleInput/style.ts +++ b/src/components/Inputs/SimpleInput/style.ts @@ -20,7 +20,7 @@ export const useStyles = makeStyles()(() => ({ suggestedPriceText: { width: 148, fontSize: 14, - lineHeight: 0.8 + lineHeight: 1 } })) diff --git a/src/components/LiquidityPoolList/LiquidityPoolList.tsx b/src/components/LiquidityPoolList/LiquidityPoolList.tsx index dfe1279..51697ef 100644 --- a/src/components/LiquidityPoolList/LiquidityPoolList.tsx +++ b/src/components/LiquidityPoolList/LiquidityPoolList.tsx @@ -96,7 +96,7 @@ const LiquidityPoolList: React.FC = ({ interval }) => { const [page, setPage] = React.useState(1) - const [sortType, setSortType] = React.useState(SortTypePoolList.VOLUME_DESC) + const [sortType, setSortType] = React.useState(SortTypePoolList.FEE_24_DESC) const navigate = useNavigate() const [initialDataLength, setInitialDataLength] = useState(initialLength) const isCenterAligment = useMediaQuery(theme.breakpoints.down(1280)) diff --git a/src/components/Modals/ConnectWallet/ConnectWallet.tsx b/src/components/Modals/ConnectWallet/ConnectWallet.tsx index 5a18e6b..c608bf0 100644 --- a/src/components/Modals/ConnectWallet/ConnectWallet.tsx +++ b/src/components/Modals/ConnectWallet/ConnectWallet.tsx @@ -2,6 +2,7 @@ import React from 'react' import useStyles from './style' import { Grid, Popover, Typography } from '@mui/material' import { copyAddressIcon, disconnectIcon, walletIcon } from '@static/icons' +import useIsMobile from '@store/hooks/isMobile' export interface IConnectWalletModal { open: boolean @@ -20,6 +21,7 @@ export const ConnectWallet: React.FC = ({ callChangeWallet = () => {} }) => { const { classes } = useStyles() + const isMobile = useIsMobile(true) return ( = ({ Copy address icon Copy address
- - Change wallet icon - Change wallet - + {!isMobile && ( + + Change wallet icon + Change wallet + + )} Disconnect icon Disconnect diff --git a/src/components/Modals/LockStatsPopover/style.ts b/src/components/Modals/LockStatsPopover/style.ts index ecbee6f..5c92232 100644 --- a/src/components/Modals/LockStatsPopover/style.ts +++ b/src/components/Modals/LockStatsPopover/style.ts @@ -14,7 +14,7 @@ const useStyles = makeStyles()((theme: Theme) => { display: 'flex', alignItems: 'center', [theme.breakpoints.down('sm')]: { - width: 300 + width: 'auto' } }, leftWrapper: { diff --git a/src/components/NewPosition/FeeSwitch/FeeSwitch.tsx b/src/components/NewPosition/FeeSwitch/FeeSwitch.tsx index 86a99a6..019bb14 100644 --- a/src/components/NewPosition/FeeSwitch/FeeSwitch.tsx +++ b/src/components/NewPosition/FeeSwitch/FeeSwitch.tsx @@ -1,4 +1,4 @@ -import React, { useState, useRef, useLayoutEffect } from 'react' +import React, { useState, useRef, useLayoutEffect, useCallback } from 'react' import { Grid, Skeleton, Tab, Tabs, Typography } from '@mui/material' import { Box } from '@mui/material' import useStyles, { useSingleTabStyles, useTabsStyles } from './style' @@ -76,6 +76,29 @@ export const FeeSwitch: React.FC = ({ } } + const doesPoolExist = useCallback( + (tier: number) => { + return Object.prototype.hasOwnProperty.call(feeTiersWithTvl, tier) + }, + [feeTiersWithTvl] + ) + + const getTvlValue = useCallback( + (tier: number) => { + const poolExist = doesPoolExist(tier) + if (!poolExist || feeTiersWithTvl[tier] === 0) return '0' + if (Object.keys(feeTiersWithTvl).length === 1) return '100' + const percentage = feeTiersWithTvl[tier] + ? Math.round((feeTiersWithTvl[tier] / totalTvl) * 100) + : 0 + + if (percentage < 1) return '<1' + if (percentage > 99) return '>99' + return `${percentage}` + }, + [feeTiersWithTvl, totalTvl] + ) + return ( = ({ className={cx(classes.tabTvl, { [classes.tabSelectedTvl]: currentValue === index || bestTierIndex === index })}> - TVL{' '} - {feeTiersWithTvl[tier] - ? Math.round((feeTiersWithTvl[tier] / totalTvl) * 100) - : 0} - % + TVL {getTvlValue(tier)}% )} {showOnlyPercents ? `${tier}%` : `${tier}% fee`} @@ -117,10 +136,16 @@ export const FeeSwitch: React.FC = ({ className={cx(classes.tabTvl, { [classes.tabSelectedTvl]: currentValue === index || bestTierIndex === index })}> - {Object.prototype.hasOwnProperty.call(feeTiersWithTvl, tier) + {doesPoolExist(tier) ? `$${ - +formatNumberWithSuffix(feeTiersWithTvl[tier], true, 18) < 1000 - ? (+formatNumberWithSuffix(feeTiersWithTvl[tier], true, 18)).toFixed(2) + +formatNumberWithSuffix(feeTiersWithTvl[tier], { + noDecimals: true, + decimalsAfterDot: 18 + }) < 1000 + ? (+formatNumberWithSuffix(feeTiersWithTvl[tier], { + noDecimals: true, + decimalsAfterDot: 18 + })).toFixed(2) : formatNumberWithSuffix(feeTiersWithTvl[tier]) }` : 'Not created'} diff --git a/src/components/NewPosition/PoolInit/PoolInit.tsx b/src/components/NewPosition/PoolInit/PoolInit.tsx index 71f5bff..e664b9e 100644 --- a/src/components/NewPosition/PoolInit/PoolInit.tsx +++ b/src/components/NewPosition/PoolInit/PoolInit.tsx @@ -2,7 +2,6 @@ import RangeInput from '@components/Inputs/RangeInput/RangeInput' import SimpleInput from '@components/Inputs/SimpleInput/SimpleInput' import { Box, Button, Grid, Typography } from '@mui/material' import { - calcPriceBySqrtPrice, calcPriceByTickIndex, calculateConcentration, calculateConcentrationRange, @@ -68,7 +67,6 @@ export const PoolInit: React.FC = ({ yDecimal, tickSpacing, midPriceIndex, - midPriceSqrtPrice, onChangeMidPrice, currentPairReversed, positionOpeningMethod, @@ -100,37 +98,6 @@ export const PoolInit: React.FC = ({ const [leftInputRounded, setLeftInputRounded] = useState((+leftInput).toFixed(12)) const [rightInputRounded, setRightInputRounded] = useState((+rightInput).toFixed(12)) - const [midPriceInput, setMidPriceInput] = useState( - calcPriceBySqrtPrice(midPriceSqrtPrice, isXtoY, xDecimal, yDecimal).toFixed(8) - ) - - const handleUpdateConcentrationFromURL = (concentrationValue: number) => { - const mappedIndex = getConcentrationIndex(concentrationArray, concentrationValue) - - const validIndex = Math.max( - minimumSliderIndex, - Math.min(mappedIndex, concentrationArray.length - 1) - ) - - setConcentrationIndex(validIndex) - const { leftRange, rightRange } = calculateConcentrationRange( - tickSpacing, - concentrationArray[validIndex], - 2, - midPriceIndex, - isXtoY - ) - - changeRangeHandler(leftRange, rightRange) - } - - useEffect(() => { - if (tokenASymbol !== 'ABC' && tokenBSymbol !== 'XYZ') { - const concentrationValue = +initialConcentration - handleUpdateConcentrationFromURL(concentrationValue) - } - }, [currentFeeIndex, tokenASymbol, tokenBSymbol]) - const validConcentrationMidPrice = (midPrice: string) => { const minTick = getMinTick(tickSpacing) const maxTick = getMaxTick(tickSpacing) @@ -168,6 +135,68 @@ export const PoolInit: React.FC = ({ return Number(midPrice) } + const validateMidPriceInput = (midPriceInput: string) => { + if (positionOpeningMethod === 'concentration') { + const validatedMidPrice = validConcentrationMidPrice(midPriceInput) + + const validatedPrice = + validatedMidPrice < MINIMAL_POOL_INIT_PRICE ? MINIMAL_POOL_INIT_PRICE : validatedMidPrice + + return trimZeros(validatedPrice.toFixed(8)) + } else { + const minPriceFromTick = isXtoY + ? calcPriceByTickIndex(minTick, isXtoY, xDecimal, yDecimal) + : calcPriceByTickIndex(maxTick, isXtoY, xDecimal, yDecimal) + + const maxPriceFromTick = isXtoY + ? calcPriceByTickIndex(maxTick, isXtoY, xDecimal, yDecimal) + : calcPriceByTickIndex(minTick, isXtoY, xDecimal, yDecimal) + + const minimalAllowedInput = + minPriceFromTick < MINIMAL_POOL_INIT_PRICE ? MINIMAL_POOL_INIT_PRICE : minPriceFromTick + + const numericMidPriceInput = parseFloat(midPriceInput) + + const validatedMidPrice = Math.min( + Math.max(numericMidPriceInput, minimalAllowedInput), + maxPriceFromTick + ) + + return trimZeros(validatedMidPrice.toFixed(8)) + } + } + + const [midPriceInput, setMidPriceInput] = useState( + validateMidPriceInput(suggestedPrice.toString() || '') + ) + + const handleUpdateConcentrationFromURL = (concentrationValue: number) => { + const mappedIndex = getConcentrationIndex(concentrationArray, concentrationValue) + + const validIndex = Math.max( + minimumSliderIndex, + Math.min(mappedIndex, concentrationArray.length - 1) + ) + + setConcentrationIndex(validIndex) + const { leftRange, rightRange } = calculateConcentrationRange( + tickSpacing, + concentrationArray[validIndex], + 2, + midPriceIndex, + isXtoY + ) + + changeRangeHandler(leftRange, rightRange) + } + + useEffect(() => { + if (tokenASymbol !== 'ABC' && tokenBSymbol !== 'XYZ') { + const concentrationValue = +initialConcentration + handleUpdateConcentrationFromURL(concentrationValue) + } + }, [currentFeeIndex, tokenASymbol, tokenBSymbol]) + useEffect(() => { if (!wasRefreshed) { const midPriceInConcentrationMode = validConcentrationMidPrice(midPriceInput) @@ -264,37 +293,6 @@ export const PoolInit: React.FC = ({ } }, [midPriceInput, concentrationArray, midPriceIndex]) - const validateMidPriceInput = (midPriceInput: string) => { - if (positionOpeningMethod === 'concentration') { - const validatedMidPrice = validConcentrationMidPrice(midPriceInput) - - const validatedPrice = - validatedMidPrice < MINIMAL_POOL_INIT_PRICE ? MINIMAL_POOL_INIT_PRICE : validatedMidPrice - - return trimZeros(validatedPrice.toFixed(8)) - } else { - const minPriceFromTick = isXtoY - ? calcPriceByTickIndex(minTick, isXtoY, xDecimal, yDecimal) - : calcPriceByTickIndex(maxTick, isXtoY, xDecimal, yDecimal) - - const maxPriceFromTick = isXtoY - ? calcPriceByTickIndex(maxTick, isXtoY, xDecimal, yDecimal) - : calcPriceByTickIndex(minTick, isXtoY, xDecimal, yDecimal) - - const minimalAllowedInput = - minPriceFromTick < MINIMAL_POOL_INIT_PRICE ? MINIMAL_POOL_INIT_PRICE : minPriceFromTick - - const numericMidPriceInput = parseFloat(midPriceInput) - - const validatedMidPrice = Math.min( - Math.max(numericMidPriceInput, minimalAllowedInput), - maxPriceFromTick - ) - - return trimZeros(validatedMidPrice.toFixed(8)) - } - } - useEffect(() => { if (currentPairReversed !== null) { const validatedMidPrice = validateMidPriceInput((1 / +midPriceInput).toString()) @@ -348,17 +346,32 @@ export const PoolInit: React.FC = ({ bestFeeIndex !== -1 && suggestedPrice ? ( -

- Set the initial pool price based on the price from the most liquid existing - market,{' '} - - {tokenASymbol}/{tokenBSymbol}{' '} - {Number( - printBN(ALL_FEE_TIERS_DATA[bestFeeIndex].tier.fee, DECIMAL - 2) - ).toFixed(2)} - %{' '} - -

+ {midPriceInput?.toString() === + validateMidPriceInput(suggestedPrice.toString()) ? ( +

+ Initial pool price applied based on the price from the most liquid existing + market,{' '} + + {tokenASymbol}/{tokenBSymbol}{' '} + {Number( + printBN(ALL_FEE_TIERS_DATA[bestFeeIndex].tier.fee, DECIMAL - 2) + ).toFixed(2)} + %{' '} + +

+ ) : ( +

+ Set the initial pool price based on the price from the most liquid existing + market,{' '} + + {tokenASymbol}/{tokenBSymbol}{' '} + {Number( + printBN(ALL_FEE_TIERS_DATA[bestFeeIndex].tier.fee, DECIMAL - 2) + ).toFixed(2)} + %{' '} + +

+ )}
) : ( diff --git a/src/components/PositionDetails/SinglePositionInfo/PoolDetails/PoolDetails.tsx b/src/components/PositionDetails/SinglePositionInfo/PoolDetails/PoolDetails.tsx index 2bbb4c7..4db5756 100644 --- a/src/components/PositionDetails/SinglePositionInfo/PoolDetails/PoolDetails.tsx +++ b/src/components/PositionDetails/SinglePositionInfo/PoolDetails/PoolDetails.tsx @@ -26,8 +26,11 @@ export const PoolDetails = ({ tvl, volume24, fee24, showPoolDetailsLoader, inter ) : ( <> $ - {+formatNumberWithSuffix(tvl, true, 18) < 1000 - ? (+formatNumberWithSuffix(tvl, true, 18)).toFixed(2) + {+formatNumberWithSuffix(tvl, { noDecimals: true, decimalsAfterDot: 18 }) < 1000 + ? (+formatNumberWithSuffix(tvl, { + noDecimals: true, + decimalsAfterDot: 18 + })).toFixed(2) : formatNumberWithSuffix(tvl)} )} @@ -41,8 +44,11 @@ export const PoolDetails = ({ tvl, volume24, fee24, showPoolDetailsLoader, inter ) : ( <> $ - {+formatNumberWithSuffix(volume24, true, 18) < 1000 - ? (+formatNumberWithSuffix(volume24, true, 18)).toFixed(2) + {+formatNumberWithSuffix(volume24, { noDecimals: true, decimalsAfterDot: 18 }) < 1000 + ? (+formatNumberWithSuffix(volume24, { + noDecimals: true, + decimalsAfterDot: 18 + })).toFixed(2) : formatNumberWithSuffix(volume24)} )} @@ -56,8 +62,11 @@ export const PoolDetails = ({ tvl, volume24, fee24, showPoolDetailsLoader, inter ) : ( <> $ - {+formatNumberWithSuffix(fee24, true, 18) < 1000 - ? (+formatNumberWithSuffix(fee24, true, 18)).toFixed(2) + {+formatNumberWithSuffix(fee24, { noDecimals: true, decimalsAfterDot: 18 }) < 1000 + ? (+formatNumberWithSuffix(fee24, { + noDecimals: true, + decimalsAfterDot: 18 + })).toFixed(2) : formatNumberWithSuffix(fee24)} )} diff --git a/src/components/PositionDetails/SinglePositionInfo/PositionStats/PositionStats.tsx b/src/components/PositionDetails/SinglePositionInfo/PositionStats/PositionStats.tsx index ffd641b..8f47714 100644 --- a/src/components/PositionDetails/SinglePositionInfo/PositionStats/PositionStats.tsx +++ b/src/components/PositionDetails/SinglePositionInfo/PositionStats/PositionStats.tsx @@ -22,8 +22,11 @@ export const PositionStats = ({ value, pendingFees, poolApy, isLoading }: Props) ) : ( $ - {+formatNumberWithSuffix(value, true, 18) < 1000 - ? (+formatNumberWithSuffix(value, true, 18)).toFixed(2) + {+formatNumberWithSuffix(value, { noDecimals: true, decimalsAfterDot: 18 }) < 1000 + ? (+formatNumberWithSuffix(value, { + noDecimals: true, + decimalsAfterDot: 18 + })).toFixed(2) : formatNumberWithSuffix(value)} )} @@ -35,8 +38,12 @@ export const PositionStats = ({ value, pendingFees, poolApy, isLoading }: Props) ) : ( $ - {+formatNumberWithSuffix(pendingFees, true, 18) < 1000 - ? (+formatNumberWithSuffix(pendingFees, true, 18)).toFixed(2) + {+formatNumberWithSuffix(pendingFees, { noDecimals: true, decimalsAfterDot: 18 }) < + 1000 + ? (+formatNumberWithSuffix(pendingFees, { + noDecimals: true, + decimalsAfterDot: 18 + })).toFixed(2) : formatNumberWithSuffix(pendingFees)} )} diff --git a/src/components/PositionDetails/SinglePositionInfo/TokenDetails/TokenDetails.tsx b/src/components/PositionDetails/SinglePositionInfo/TokenDetails/TokenDetails.tsx index 41df213..0d7c02d 100644 --- a/src/components/PositionDetails/SinglePositionInfo/TokenDetails/TokenDetails.tsx +++ b/src/components/PositionDetails/SinglePositionInfo/TokenDetails/TokenDetails.tsx @@ -1,12 +1,8 @@ import { Box, Skeleton, Typography } from '@mui/material' import { useStyles } from './style' -import { - formatNumbers, - formatNumberWithSuffix, - thresholdsWithTokenDecimal, - trimZeros -} from '@utils/utils' +import { formatNumberWithSuffix, getThresholdsDecimals } from '@utils/utils' import { TokenBadge } from '../TokenBadge/TokenBadge' +import { thresholdsWithTokenDecimal } from '@store/consts/static' type Props = { icon: string @@ -38,9 +34,14 @@ export const TokenDetails = ({ icon, ticker, amount, decimal, price, isLoading } ) : ( - {trimZeros( - formatNumbers(thresholdsWithTokenDecimal(decimal))(parsedTokenAmount.toString()) - )} + {formatNumberWithSuffix(parsedTokenAmount, { + decimalsAfterDot: getThresholdsDecimals( + parsedTokenAmount, + thresholdsWithTokenDecimal(decimal) + ), + noSubNumbers: true, + alternativeConfig: true + })} )}
diff --git a/src/components/PositionDetails/SinglePositionPlot/SinglePositionPlot.tsx b/src/components/PositionDetails/SinglePositionPlot/SinglePositionPlot.tsx index 67fbfa3..c5a6c79 100644 --- a/src/components/PositionDetails/SinglePositionPlot/SinglePositionPlot.tsx +++ b/src/components/PositionDetails/SinglePositionPlot/SinglePositionPlot.tsx @@ -5,6 +5,7 @@ import { calcTicksAmountInRange, calculateConcentration, formatNumberWithoutSuffix, + formatNumberWithSuffix, numberToString, spacingMultiplicityGte, truncateString @@ -227,8 +228,8 @@ const SinglePositionPlot: React.FC = ({ setPlotMax(rangeCenter + diff / 2) } - const minPercentage = (min / currentPrice - 1) * 100 - const maxPercentage = (max / currentPrice - 1) * 100 + const minPercentage = ((+min - currentPrice) / currentPrice) * 100 + const maxPercentage = ((+max - currentPrice) / currentPrice) * 100 const concentration = calculateConcentration(leftRange.index, rightRange.index) return ( @@ -376,7 +377,12 @@ const SinglePositionPlot: React.FC = ({ color: minPercentage < 0 ? colors.invariant.Error : colors.invariant.green }}> {minPercentage > 0 && '+'} - {minPercentage.toFixed(2)}% + {formatNumberWithSuffix(minPercentage.toString(), { + decimalsAfterDot: 2, + noSubNumbers: true, + alternativeConfig: true + })} + % } @@ -394,7 +400,12 @@ const SinglePositionPlot: React.FC = ({ color: maxPercentage < 0 ? colors.invariant.Error : colors.invariant.green }}> {maxPercentage > 0 && '+'} - {maxPercentage.toFixed(2)}% + {formatNumberWithSuffix(maxPercentage.toString(), { + decimalsAfterDot: 2, + noSubNumbers: true, + alternativeConfig: true + })} + % } diff --git a/src/components/PositionDetails/SinglePositionPlot/Stat/style.ts b/src/components/PositionDetails/SinglePositionPlot/Stat/style.ts index be9aa32..cdd613d 100644 --- a/src/components/PositionDetails/SinglePositionPlot/Stat/style.ts +++ b/src/components/PositionDetails/SinglePositionPlot/Stat/style.ts @@ -15,6 +15,7 @@ export const useStyles = makeStyles()((_theme, { isHorizontal }) => ({ }, name: { height: 40, + minWidth: 46, color: colors.invariant.textGrey, background: colors.invariant.light, borderRadius: 12, diff --git a/src/components/Stats/PoolList/PoolList.tsx b/src/components/Stats/PoolList/PoolList.tsx index 7bfadeb..65b9d4c 100644 --- a/src/components/Stats/PoolList/PoolList.tsx +++ b/src/components/Stats/PoolList/PoolList.tsx @@ -103,7 +103,7 @@ const PoolList: React.FC = ({ const filteredTokenY = filteredTokens[1] ?? '' const [page, setPage] = React.useState(1) - const [sortType, setSortType] = React.useState(SortTypePoolList.VOLUME_DESC) + const [sortType, setSortType] = React.useState(SortTypePoolList.FEE_24_DESC) const sortedData = useMemo(() => { if (isLoading) { diff --git a/src/components/Stats/PoolListItem/PoolListItem.tsx b/src/components/Stats/PoolListItem/PoolListItem.tsx index 1a7f5a1..9f5688c 100644 --- a/src/components/Stats/PoolListItem/PoolListItem.tsx +++ b/src/components/Stats/PoolListItem/PoolListItem.tsx @@ -21,6 +21,7 @@ import { parseFeeToPathFee, ROUTES } from '@utils/utils' +import { CustomPopover } from '@common/Popover/CustomPopover' import { formatNumberWithSuffix } from '@utils/utils' import { DECIMAL } from '@invariant-labs/sdk-sonic/lib/utils' import { TooltipHover } from '@common/TooltipHover/TooltipHover' @@ -193,6 +194,11 @@ const PoolListItem: React.FC = ({ setShowInfo(false) } }, [isSmd]) + + useEffect(() => { + setShowInfo(false) + }, [itemNumber]) + //HOTFIX const { convertedApy, convertedApr } = calculateAPYAndAPR(apy, poolAddress, volume, fee, TVL) const ActionsButtons = ( @@ -215,9 +221,8 @@ const PoolListItem: React.FC = ({ {'Exchange'} {isLocked && ( - = ({ liquidityX={tokenAData.liquidity} liquidityY={tokenBData.liquidity} /> - }> - - + )} ) diff --git a/src/components/Stats/PoolListItem/style.ts b/src/components/Stats/PoolListItem/style.ts index 917020c..ab6c49c 100644 --- a/src/components/Stats/PoolListItem/style.ts +++ b/src/components/Stats/PoolListItem/style.ts @@ -25,7 +25,7 @@ export const useStyles = makeStyles<{ showInfo?: boolean }>()((_theme, { showInf color: colors.white.main, display: 'grid', alignItems: 'center', - gridTemplateColumns: '30px auto 190px 120px 120px 140px 120px 150px', + gridTemplateColumns: '40px auto 190px 120px 120px 140px 120px 150px', padding: '20px 26px 14px 24px', whiteSpace: 'nowrap', diff --git a/src/components/Stats/Volume/Volume.tsx b/src/components/Stats/Volume/Volume.tsx index 472f6fe..eee4d07 100644 --- a/src/components/Stats/Volume/Volume.tsx +++ b/src/components/Stats/Volume/Volume.tsx @@ -1,4 +1,3 @@ -import React from 'react' import { ResponsiveBar } from '@nivo/bar' import { colors, theme, typography } from '@static/theme' import { linearGradientDef } from '@nivo/core' @@ -6,9 +5,9 @@ import { useStyles } from './style' import { TimeData } from '@store/reducers/stats' import { Box, Grid, Typography, useMediaQuery } from '@mui/material' import { formatNumberWithoutSuffix, trimZeros } from '@utils/utils' -import { formatLargeNumber, formatPlotDataLabels, getLabelDate } from '@utils/uiUtils' -import useIsMobile from '@store/hooks/isMobile' import { Intervals as IntervalsKeys } from '@store/consts/static' +import { formatLargeNumber, formatPlotDataLabels, getLabelDate } from '@utils/uiUtils' +import { useState, useRef, useEffect, useCallback } from 'react' interface StatsInterface { volume: number | null @@ -28,11 +27,90 @@ const Volume: React.FC = ({ lastStatsTimestamp }) => { const { classes, cx } = useStyles() + const [hoveredBar, setHoveredBar] = useState(null) + const [hoveredBarPosition, setHoveredBarPosition] = useState<{ x: number; width: number } | null>( + null + ) + const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 }) + const chartContainerRef = useRef(null) + const hideTimeoutRef = useRef(null) volume = volume ?? 0 const isXsDown = useMediaQuery(theme.breakpoints.down('xs')) - const isMobile = useIsMobile() + const isMobile = useMediaQuery(theme.breakpoints.down('sm')) + + const hideTooltip = useCallback((immediate = false) => { + if (hideTimeoutRef.current) { + clearTimeout(hideTimeoutRef.current) + } + + if (immediate) { + setHoveredBar(null) + setHoveredBarPosition(null) + } else { + hideTimeoutRef.current = setTimeout(() => { + setHoveredBar(null) + setHoveredBarPosition(null) + }, 50) + } + }, []) + + const showTooltip = useCallback( + (barData: any, event: MouseEvent, barPosition: { x: number; width: number }) => { + if (hideTimeoutRef.current) { + clearTimeout(hideTimeoutRef.current) + } + setHoveredBar(barData) + setHoveredBarPosition(barPosition) + setMousePosition({ x: event.clientX, y: event.clientY }) + }, + [] + ) + + const handleGlobalMouseMove = useCallback( + (event: MouseEvent) => { + if (!chartContainerRef.current || !hoveredBar) return + + const rect = chartContainerRef.current.getBoundingClientRect() + const margin = { top: 30, bottom: 30, left: 30, right: 4 } // Same as chart margins + + const barAreaLeft = rect.left + margin.left + const barAreaRight = rect.right - margin.right + const barAreaTop = rect.top + margin.top + const barAreaBottom = rect.bottom - margin.bottom + + const isInsideBarArea = + event.clientX >= barAreaLeft && + event.clientX <= barAreaRight && + event.clientY >= barAreaTop && + event.clientY <= barAreaBottom + + if (!isInsideBarArea) { + hideTooltip(true) + } else { + setMousePosition({ x: event.clientX, y: event.clientY }) + } + }, + [hoveredBar, hideTooltip] + ) + + useEffect(() => { + if (hoveredBar) { + document.addEventListener('mousemove', handleGlobalMouseMove) + return () => { + document.removeEventListener('mousemove', handleGlobalMouseMove) + } + } + }, [hoveredBar, handleGlobalMouseMove]) + + useEffect(() => { + return () => { + if (hideTimeoutRef.current) { + clearTimeout(hideTimeoutRef.current) + } + } + }, []) const Theme = { axis: { @@ -44,6 +122,96 @@ const Volume: React.FC = ({ grid: { line: { stroke: colors.invariant.light } } } + const CustomHoverLayer = ({ bars, innerHeight, innerWidth }: any) => { + return ( + + {hoveredBarPosition && ( + + )} + + { + hideTooltip() + }} + style={{ pointerEvents: 'all' }} + /> + + {bars.map((bar: any) => { + const barData = { + timestamp: bar.data.indexValue || bar.data.timestamp, + value: bar.data.value, + ...bar.data + } + + const hoverWidth = bar.width + 2 + const hoverX = bar.x - 1 + + return ( + { + showTooltip(barData, event.nativeEvent, { x: bar.x, width: bar.width }) + }} + onMouseMove={event => { + setMousePosition({ x: event.nativeEvent.clientX, y: event.nativeEvent.clientY }) + }} + onMouseLeave={() => { + hideTooltip() + }} + style={{ pointerEvents: 'all' }} + /> + ) + })} + + ) + } + + const CustomTooltip = () => { + if (!hoveredBar) return null + + const timestamp = hoveredBar.timestamp || hoveredBar.indexValue + const date = getLabelDate(interval, timestamp, lastStatsTimestamp) + + return ( +
+ + {date} + + ${formatNumberWithoutSuffix(hoveredBar.value)} + + +
+ ) + } + return ( @@ -56,7 +224,11 @@ const Volume: React.FC = ({ -
+
hideTooltip(true)}> = ({ ? () => : ({ x, y, value }) => ( - {' '} = ({ enableLabel={false} enableGridY={true} innerPadding={isXsDown ? 1 : 2} - isInteractive + isInteractive={false} padding={0.03} indexScale={{ type: 'band', round: true }} defs={[ @@ -108,19 +279,9 @@ const Volume: React.FC = ({ ]} fill={[{ match: '*', id: 'gradient' }]} colors={colors.invariant.pink} - tooltip={({ data }) => { - const date = getLabelDate(interval, data.timestamp, lastStatsTimestamp) - - return ( - - {date} - - ${formatNumberWithoutSuffix(data.value)} - - - ) - }} + layers={['grid', 'axes', 'bars', 'markers', 'legends', 'annotations', CustomHoverLayer]} /> +
) diff --git a/src/components/Swap/style.ts b/src/components/Swap/style.ts index cb66680..62a3bfe 100644 --- a/src/components/Swap/style.ts +++ b/src/components/Swap/style.ts @@ -44,7 +44,7 @@ export const useStyles = makeStyles()((theme: Theme) => ({ } }, header: { - maxWidth: 500, + maxWidth: 510, display: 'flex', alignItems: 'center', justifyContent: 'space-between', @@ -161,7 +161,7 @@ export const useStyles = makeStyles()((theme: Theme) => ({ root: { flexDirection: 'column', position: 'relative', - maxWidth: 500, + maxWidth: 510, background: colors.invariant.component, borderRadius: 24, paddingInline: 24, @@ -278,10 +278,13 @@ export const useStyles = makeStyles()((theme: Theme) => ({ }, transactionDetailsHeader: { + width: 146, ...typography.caption2, whiteSpace: 'nowrap', pointerEvents: 'none', - color: colors.invariant.lightGrey + color: colors.invariant.lightGrey, + display: 'flex', + justifyContent: 'center' }, exchangeRateWrapper: { @@ -417,7 +420,7 @@ export const useStyles = makeStyles()((theme: Theme) => ({ backgroundColor: colors.invariant.component, color: colors.invariant.textGrey, fontSize: 16, - fontsWeigth: 500, + fontsWeigth: 510, cursor: 'pointer', userSelect: 'none', display: 'flex', @@ -482,7 +485,7 @@ export const useStyles = makeStyles()((theme: Theme) => ({ transition: 'all 0.3s ease-in-out' }, borderContainer: { - maxWidth: 500, + maxWidth: 510, width: '100%', borderRadius: 24, border: `1px solid ${colors.invariant.component}` diff --git a/src/containers/NewPositionWrapper/NewPositionWrapper.tsx b/src/containers/NewPositionWrapper/NewPositionWrapper.tsx index d5ca330..b3cc874 100644 --- a/src/containers/NewPositionWrapper/NewPositionWrapper.tsx +++ b/src/containers/NewPositionWrapper/NewPositionWrapper.tsx @@ -686,6 +686,9 @@ export const NewPositionWrapper: React.FC = ({ }, []) const { feeTiersWithTvl, totalTvl } = useMemo(() => { + if (tokenAIndex === null || tokenBIndex === null) { + return { feeTiersWithTvl: {}, totalTvl: 0 } + } const feeTiersWithTvl: Record = {} let totalTvl = 0 diff --git a/src/store/consts/static.ts b/src/store/consts/static.ts index d68d6ec..4f3abbf 100644 --- a/src/store/consts/static.ts +++ b/src/store/consts/static.ts @@ -2,7 +2,14 @@ import { FEE_TIERS, toDecimal } from '@invariant-labs/sdk-sonic/lib/utils' import { BN } from '@coral-xyz/anchor' import { PublicKey } from '@solana/web3.js' import { ISnackbar } from '@store/reducers/snackbars' -import { Chain, PrefixConfig, Token, TokenPriceData, WalletType } from './types' +import { + Chain, + FormatNumberThreshold, + PrefixConfig, + Token, + TokenPriceData, + WalletType +} from './types' import { cat1Icon, cat2Icon, dog1Icon, dog2Icon } from '@static/icons' import { TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID } from '@solana/spl-token' @@ -593,3 +600,72 @@ export const chartPlaceholder = { plotMax: 1.0113333501881372, tickSpacing: 10 } + +export const AlternativeFormatConfig = { + B: 1000000000, + M: 1000000, + K: 10000, + BDecimals: 9, + MDecimals: 6, + KDecimals: 3, + DecimalsAfterDot: 2 +} + +export const defaultThresholds: FormatNumberThreshold[] = [ + { + value: 10, + decimals: 4 + }, + { + value: 1000, + decimals: 2 + }, + { + value: 10000, + decimals: 2 + }, + { + value: 1000000, + decimals: 2, + divider: 1000 + }, + { + value: 1000000000, + decimals: 2, + divider: 1000000 + }, + { + value: Infinity, + decimals: 2, + divider: 1000000000 + } +] + +export const thresholdsWithTokenDecimal = (decimals: number): FormatNumberThreshold[] => [ + { + value: 10, + decimals + }, + { + value: 10000, + decimals: 6 + }, + { + value: 100000, + decimals: 4 + }, + { + value: 1000000, + decimals: 3 + }, + { + value: 1000000000, + decimals: 2, + divider: 1000000 + }, + { + value: Infinity, + decimals: 2, + divider: 1000000000 + } +] diff --git a/src/utils/uiUtils.ts b/src/utils/uiUtils.ts index 674b7b7..39c6573 100644 --- a/src/utils/uiUtils.ts +++ b/src/utils/uiUtils.ts @@ -1,7 +1,6 @@ import { BN } from '@coral-xyz/anchor' import { formatDate, printBN, trimDecimalZeros, trimZeros } from './utils' import { PublicKey } from '@solana/web3.js' -import { FormatNumberThreshold } from '@store/consts/types' import { Intervals, MONTH_NAMES } from '@store/consts/static' export const toBlur = 'global-blur' @@ -132,34 +131,6 @@ export const formatLargeNumber = (number: number) => { return `${trimZeros(scaledNumber.toFixed(1))}${suffixes[suffixIndex]}` } -export const thresholdsWithTokenDecimal = (decimals: number): FormatNumberThreshold[] => [ - { - value: 10, - decimals - }, - { - value: 10000, - decimals: 6 - }, - { - value: 100000, - decimals: 4 - }, - { - value: 1000000, - decimals: 3 - }, - { - value: 1000000000, - decimals: 2, - divider: 1000000 - }, - { - value: Infinity, - decimals: 2, - divider: 1000000000 - } -] export const shortenDate = (timestamp: number | string): string => { if (typeof timestamp === 'string') { return timestamp.slice(0, 6) + timestamp.slice(-2) diff --git a/src/utils/utils.ts b/src/utils/utils.ts index ed0c3f1..686df26 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -72,7 +72,9 @@ import { SSOL_MAIN, WSOL_MAIN, WSOL_TEST, - WRAPPED_SOL_ADDRESS + WRAPPED_SOL_ADDRESS, + AlternativeFormatConfig, + defaultThresholds } from '@store/consts/static' import { PoolWithAddress } from '@store/reducers/pools' import { bs58 } from '@coral-xyz/anchor/dist/cjs/utils/bytes' @@ -82,7 +84,6 @@ import { IncentiveRewardData, IPriceData, PoolSnapshot, - PrefixConfig, Token, TokenPriceData } from '@store/consts/types' @@ -204,80 +205,6 @@ export const removeTickerPrefix = (ticker: string, prefix: string[] = ['x', '$'] return ticker } -const defaultPrefixConfig: PrefixConfig = { - B: 1000000000, - M: 1000000, - K: 10000 -} - -export const showPrefix = (nr: number, config: PrefixConfig = defaultPrefixConfig): string => { - const abs = Math.abs(nr) - - if (typeof config.B !== 'undefined' && abs >= config.B) { - return 'B' - } - - if (typeof config.M !== 'undefined' && abs >= config.M) { - return 'M' - } - - if (typeof config.K !== 'undefined' && abs >= config.K) { - return 'K' - } - - return '' -} - -export const defaultThresholds: FormatNumberThreshold[] = [ - { - value: 10, - decimals: 4 - }, - { - value: 1000, - decimals: 2 - }, - { - value: 10000, - decimals: 1 - }, - { - value: 1000000, - decimals: 2, - divider: 1000 - }, - { - value: 1000000000, - decimals: 2, - divider: 1000000 - }, - { - value: Infinity, - decimals: 2, - divider: 1000000000 - } -] - -export const formatNumbers = - (thresholds: FormatNumberThreshold[] = defaultThresholds) => - (value: string) => { - const num = Number(value) - const abs = Math.abs(num) - const threshold = thresholds.sort((a, b) => a.value - b.value).find(thr => abs < thr.value) - - const formatted = threshold - ? (abs / (threshold.divider ?? 1)).toFixed(threshold.decimals) - : value - - return num < 0 && threshold ? '-' + formatted : formatted - } - -export const sqrtPriceToPrice = (sqrtPrice: BN) => { - const price = sqrtPrice.mul(sqrtPrice) - - return price.div(PRICE_DENOMINATOR) -} - export const priceToSqrtPrice = (price: BN) => { return sqrt(price.mul(PRICE_DENOMINATOR)) } @@ -719,11 +646,41 @@ export const printSubNumber = (amount: number): string => { .join('') } +interface FormatNumberWithSuffixConfig { + noDecimals?: boolean + decimalsAfterDot?: number + alternativeConfig?: boolean + noSubNumbers?: boolean +} + +export const getThresholdsDecimals = ( + number: number | bigint | string, + thresholds: FormatNumberThreshold[] = defaultThresholds +): number => { + const numberAsNumber = Number(number) + const found = thresholds.find(threshold => numberAsNumber < threshold.value) + + return found?.decimals ?? 2 +} export const formatNumberWithSuffix = ( number: number | bigint | string, - noDecimals?: boolean, - decimalsAfterDot: number = 3 + config?: FormatNumberWithSuffixConfig ): string => { + const { + noDecimals, + decimalsAfterDot, + alternativeConfig, + noSubNumbers + }: Required = { + noDecimals: false, + decimalsAfterDot: 3, + alternativeConfig: false, + noSubNumbers: false, + ...config + } + + const formatConfig = alternativeConfig ? AlternativeFormatConfig : FormatConfig + const numberAsNumber = Number(number) const isNegative = numberAsNumber < 0 const absNumberAsNumber = Math.abs(numberAsNumber) @@ -738,39 +695,43 @@ export const formatNumberWithSuffix = ( let formattedNumber - if (Math.abs(numberAsNumber) >= FormatConfig.B) { + if (Math.abs(numberAsNumber) >= formatConfig.B) { const formattedDecimals = noDecimals ? '' - : (FormatConfig.DecimalsAfterDot ? '.' : '') + - (beforeDot.slice(-FormatConfig.BDecimals) + (afterDot ? afterDot : '')).slice( + : '.' + + (beforeDot.slice(-formatConfig.BDecimals) + (afterDot ? afterDot : '')).slice( 0, - FormatConfig.DecimalsAfterDot + formatConfig.DecimalsAfterDot ) formattedNumber = - beforeDot.slice(0, -FormatConfig.BDecimals) + (noDecimals ? '' : formattedDecimals) + 'B' - } else if (Math.abs(numberAsNumber) >= FormatConfig.M) { + beforeDot.slice(0, -formatConfig.BDecimals) + (noDecimals ? '' : formattedDecimals) + 'B' + } else if (Math.abs(numberAsNumber) >= formatConfig.M) { const formattedDecimals = noDecimals ? '' - : (FormatConfig.DecimalsAfterDot ? '.' : '') + - (beforeDot.slice(-FormatConfig.MDecimals) + (afterDot ? afterDot : '')).slice( + : '.' + + (beforeDot.slice(-formatConfig.MDecimals) + (afterDot ? afterDot : '')).slice( 0, - FormatConfig.DecimalsAfterDot + formatConfig.DecimalsAfterDot ) formattedNumber = - beforeDot.slice(0, -FormatConfig.MDecimals) + (noDecimals ? '' : formattedDecimals) + 'M' - } else if (Math.abs(numberAsNumber) >= FormatConfig.K) { + beforeDot.slice(0, -formatConfig.MDecimals) + (noDecimals ? '' : formattedDecimals) + 'M' + } else if (Math.abs(numberAsNumber) >= formatConfig.K) { const formattedDecimals = noDecimals ? '' - : (FormatConfig.DecimalsAfterDot ? '.' : '') + - (beforeDot.slice(-FormatConfig.KDecimals) + (afterDot ? afterDot : '')).slice( + : '.' + + (beforeDot.slice(-formatConfig.KDecimals) + (afterDot ? afterDot : '')).slice( 0, - FormatConfig.DecimalsAfterDot + formatConfig.DecimalsAfterDot ) formattedNumber = - beforeDot.slice(0, -FormatConfig.KDecimals) + (noDecimals ? '' : formattedDecimals) + 'K' + beforeDot.slice(0, -formatConfig.KDecimals) + (noDecimals ? '' : formattedDecimals) + 'K' + } else if (afterDot && noSubNumbers) { + const roundedNumber = absNumberAsNumber.toFixed(decimalsAfterDot + 1).slice(0, -1) + + formattedNumber = trimZeros(roundedNumber) } else if (afterDot && countLeadingZeros(afterDot) <= decimalsAfterDot) { - const roundedNumber = numberAsNumber + const roundedNumber = absNumberAsNumber .toFixed(countLeadingZeros(afterDot) + decimalsAfterDot + 1) .slice(0, -1) @@ -783,7 +744,9 @@ export const formatNumberWithSuffix = ( ? String(parseInt(afterDot)).slice(0, decimalsAfterDot) : afterDot - if (parsedAfterDot) { + if (noSubNumbers && afterDot) { + formattedNumber = beforeDot + '.' + afterDot + } else if (parsedAfterDot && afterDot) { formattedNumber = beforeDot + '.' + @@ -1850,35 +1813,6 @@ export const getPositionsAddressesFromRange = async ( ) } -export const thresholdsWithTokenDecimal = (decimals: number): FormatNumberThreshold[] => [ - { - value: 10, - decimals - }, - { - value: 10000, - decimals: 6 - }, - { - value: 100000, - decimals: 4 - }, - { - value: 1000000, - decimals: 3 - }, - { - value: 1000000000, - decimals: 2, - divider: 1000000 - }, - { - value: Infinity, - decimals: 2, - divider: 1000000000 - } -] - export const getMockedTokenPrice = (symbol: string, network: NetworkType): TokenPriceData => { const sufix = network === NetworkType.Devnet ? '_DEV' : '_TEST' const prices = tokensPrices[network]