From 2db777f65e61fad015afd9edae82136a6a3ed1ac Mon Sep 17 00:00:00 2001 From: franm Date: Mon, 9 Sep 2024 13:43:36 -0300 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A5=20remove=20old=20file?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/staking/Progress/index.tsx | 2 +- components/staking/StakingProgress/index.tsx | 544 +++++++++--------- .../StakingProgress/stakingProgressBar.tsx | 301 ---------- 3 files changed, 270 insertions(+), 577 deletions(-) delete mode 100644 components/staking/StakingProgress/stakingProgressBar.tsx diff --git a/components/staking/Progress/index.tsx b/components/staking/Progress/index.tsx index 2c3e3d16b..90d8b95a5 100644 --- a/components/staking/Progress/index.tsx +++ b/components/staking/Progress/index.tsx @@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next'; import { useStakeEXA } from 'contexts/StakeEXAContext'; import { parseEther } from 'viem'; import WAD from '@exactly/lib/esm/fixed-point-math/WAD'; -import StakingProgressBar from '../StakingProgress/stakingProgressBar'; +import StakingProgressBar from '../StakingProgress'; import { InfoOutlined } from '@mui/icons-material'; function Progress() { diff --git a/components/staking/StakingProgress/index.tsx b/components/staking/StakingProgress/index.tsx index a7adb6849..5642a7d30 100644 --- a/components/staking/StakingProgress/index.tsx +++ b/components/staking/StakingProgress/index.tsx @@ -1,307 +1,301 @@ -import React, { useCallback, useMemo, useRef, useState } from 'react'; -import { - Avatar, - AvatarGroup, - Box, - Dialog, - DialogContent, - IconButton, - Paper, - PaperProps, - Slide, - Typography, - useMediaQuery, - useTheme, -} from '@mui/material'; -import { useTranslation } from 'react-i18next'; +import React, { FC, ReactNode } from 'react'; +import Tooltip from '@mui/material/Tooltip'; +import { styled } from '@mui/system'; +import { Avatar, AvatarGroup, Box, Typography, useTheme } from '@mui/material'; import formatNumber from 'utils/formatNumber'; +import { formatEther } from 'viem'; import { useStakeEXA } from 'contexts/StakeEXAContext'; -import { formatEther, parseEther } from 'viem'; -import { Transaction } from 'types/Transaction'; -import { toPercentage } from 'utils/utils'; -import parseTimestamp from 'utils/parseTimestamp'; -import WAD from '@exactly/lib/esm/fixed-point-math/WAD'; -import waitForTransaction from 'utils/waitForTransaction'; -import { useStakedEXA } from 'hooks/useStakedEXA'; -import { useWeb3 } from 'hooks/useWeb3'; -import { gasLimit } from 'utils/gas'; -import Draggable from 'react-draggable'; -import { TransitionProps } from 'react-transition-group/Transition'; -import CloseIcon from '@mui/icons-material/Close'; -import LoadingTransaction from 'components/common/modal/Loading'; -import { LoadingButton } from '@mui/lab'; +import Image from 'next/image'; +import { useTranslation } from 'react-i18next'; -function PaperComponent(props: PaperProps | undefined) { - const ref = useRef(null); - return ( - - - - ); -} +const ProgressBar = styled('div')<{ ended: boolean }>(({ ended, theme }) => ({ + display: 'flex', + height: 24, + borderRadius: 999, + width: '100%', + position: 'relative', + overflow: 'hidden', + ...(!ended && { border: `1px solid ${theme.palette.figma.green[100]}` }), +})); -const Transition = React.forwardRef(function Transition( - props: TransitionProps & { - children: React.ReactElement; +const ClaimedProgressBar = styled('div')<{ width: number }>(({ width, theme }) => ({ + width: `${width}%`, + borderRadius: '0px 0 0 0px', + backgroundColor: theme.palette.figma.green[500], + transition: 'background-color 0.3s', + position: 'relative', + overflow: 'visible', + '&:hover': { + cursor: 'pointer', + }, + '&::before': { + content: '""', + position: 'absolute', + right: -4, + top: 0, + bottom: 0, + width: 10, + backgroundColor: theme.palette.figma.green[500], + transform: 'scaleX(0.6)', + transition: 'background-color 0.3s', }, - ref: React.Ref, -) { - return ; -}); +})); -function LoadingModal({ tx, onClose }: { tx: Transaction; onClose: () => void }) { - const { t } = useTranslation(); - const { breakpoints, spacing, palette } = useTheme(); - const isMobile = useMediaQuery(breakpoints.down('sm')); - const loadingTx = useMemo(() => tx && (tx.status === 'loading' || tx.status === 'processing'), [tx]); +const RestProgressBar = styled('div')<{ width: number; ended?: boolean }>(({ width, ended, theme }) => ({ + width: `${width}%`, + borderRadius: '0 4px 4px 0', + backgroundColor: ended ? 'transparent' : theme.palette.figma.green[50], + transition: 'background-color 0.3s', + position: 'relative', + '&:hover': { + cursor: 'pointer', + }, + ...(ended && { + backgroundImage: `repeating-linear-gradient( + -70deg, + red, + red 3px, + #ffffff 3px, + #ffffff 6px + )`, + }), + '&::before': { + content: '""', + position: 'absolute', + right: -4, + top: 0, + bottom: 0, + width: 10, + backgroundColor: ended ? 'transparent' : theme.palette.figma.green[50], + backgroundImage: ended + ? `repeating-linear-gradient( + -70deg, + #ffffff , + #ffffff 3px + red 3px, + red 6px, + )` + : 'none', + }, +})); - const handleClose = useCallback(() => { - if (loadingTx) return; - onClose(); - }, [loadingTx, onClose]); +const ClaimableProgressBar = styled('div')<{ width: number }>(({ width, theme }) => ({ + width: `${width}%`, + backgroundColor: theme.palette.figma.green[50], + transition: 'background-color 0.3s', + '&:hover': { + cursor: 'pointer', + }, + backgroundImage: `repeating-linear-gradient( + -70deg, + ${theme.palette.figma.green[500]}, + ${theme.palette.figma.green[500]} 3px, + #ffffff 3px, + #ffffff 6px + )`, +})); - return ( - - - - - - - - - - - ); +interface DualProgressBarProps { + claimed: bigint; + claimable: bigint; + total: bigint; + tooltip1?: ReactNode; + tooltip2?: ReactNode; + tooltip3?: ReactNode; + ended: boolean; } -function StakingProgress() { +const StakingProgressBar: FC = ({ + claimed = 0n, + claimable = 0n, + total = 0n, + tooltip1 = `$${formatNumber(formatEther(claimed), 'USD')}`, + tooltip2 = `$${formatNumber(formatEther(claimable), 'USD')}`, + tooltip3 = `$${formatNumber(formatEther(total - claimable - claimed), 'USD')}`, + ended = false, +}) => { + const { palette } = useTheme(); const { t } = useTranslation(); - const stakedEXA = useStakedEXA(); - const { opts } = useWeb3(); - const [tx, setTx] = useState(); - const [isLoading, setIsLoading] = useState(false); - - const { refetch, start, rewardsTokens, totalClaimable, totalClaimed, totalEarned, penalty, parameters } = - useStakeEXA(); - - const claimAll = useCallback(async () => { - if (!stakedEXA || !opts) return; + const { rewardsTokens, claimableTokens, claimedTokens, earnedTokens } = useStakeEXA(); - setIsLoading(true); - let hash; - try { - const gas = await stakedEXA.estimateGas.claimAll(opts); - hash = await stakedEXA.write.claimAll({ ...opts, gasLimit: gasLimit(gas) }); + const claimedPercentage = total > 0n ? Number((claimed * 100n) / total) : 0; + const claimablePercentage = total > 0n ? Number((claimable * 100n) / total) : 0; + const restValue = Math.max(0, 100 - claimedPercentage - claimablePercentage); - setTx({ status: 'processing', hash }); + const remainingTokens = Object.keys(claimableTokens).reduce( + (acc, symbol) => { + const claimableValue = claimableTokens[symbol] || 0n; + const claimedValue = claimedTokens[symbol] || 0n; + const totalValue = earnedTokens[symbol] || 0n; - const { status, transactionHash } = await waitForTransaction({ hash }); + const remainingValue = totalValue - claimableValue - claimedValue; - setTx({ status: status === 'success' ? 'success' : 'error', hash: transactionHash }); - } catch (e) { - if (hash) setTx({ status: 'error', hash }); - } finally { - refetch(); - setIsLoading(false); - } - }, [stakedEXA, opts, refetch]); + acc[symbol] = remainingValue; - const progress = useMemo(() => { - if (!start || !parameters) return 0; - const now = Math.floor(Date.now() / 1000); - const avgStart = start === 0n ? parseEther(now.toString()) : start; - const startTime = Number(avgStart / WAD); - const endTime = Number(avgStart / WAD + parameters.refTime); - const elapsedTime = now - startTime; - const percentage = elapsedTime / (endTime - startTime); - - return Math.min(percentage, 100); - }, [parameters, start]); - - const onClose = useCallback(() => { - setTx(undefined); - }, []); + return acc; + }, + {} as Record, + ); return ( - - (palette.mode === 'light' ? '0px 6px 10px 0px rgba(97, 102, 107, 0.20)' : '')} - display="flex" - flexDirection="column" - justifyContent="space-between" - position="relative" - overflow="hidden" - > - - - - {t('Staking progress')} - - - {toPercentage(progress)} - - {progress > 0 && start !== undefined && ( - - {t('Started on')} {parseTimestamp(formatEther(start))} + + + + + + + + + + + + + + + + + + {t('Claimed')} - )} - - - - (palette.mode === 'light' ? '0px 6px 10px 0px rgba(97, 102, 107, 0.20)' : '')} - display="flex" - flexDirection="column" - justifyContent="space-between" - > - - - {t('Rewards to date')} - + - ${formatNumber(formatEther(totalClaimable), 'USD')} - - {rewardsTokens.map((symbol) => ( - - ))} - + ${formatNumber(formatEther(claimed), 'USD')} + } placement="top" arrow> + + {Object.entries(claimedTokens).map(([symbol]) => { + const isExaToken = symbol.length > 3 && symbol.startsWith('exa'); + const imagePath = isExaToken ? `/img/exaTokens/${symbol}.svg` : `/img/assets/${symbol}.svg`; + return ; + })} + + + + - - {t('Claimed: ')} - - - ${formatNumber(formatEther(totalClaimed), 'USD')} + + + Available to claim - - {totalEarned > 0n && ( - - - ${formatNumber(formatEther(totalEarned), 'USD')} - - + ${formatNumber(formatEther(claimable), 'USD')} + } placement="top" arrow> + - {toPercentage(Number(formatEther(penalty)), 1)} {t('penalty')} - - - )} - - {tx && } - - { - claimAll(); - }} - fullWidth - > - {t('Claim rewards to date')} - + {Object.entries(claimableTokens).map(([symbol]) => { + const isExaToken = symbol.length > 3 && symbol.startsWith('exa'); + const imagePath = isExaToken ? `/img/exaTokens/${symbol}.svg` : `/img/assets/${symbol}.svg`; + return ; + })} + + + - - - (palette.mode === 'light' ? '0px 6px 10px 0px rgba(97, 102, 107, 0.20)' : '')} - display="flex" - flexDirection="column" - justifyContent="space-between" - > - - {t('Total rewards')} + + + + + {ended ? t('Not available to claim') : t('Projected Remainder')} + + - ${formatNumber(formatEther(totalEarned), 'USD')} - - {rewardsTokens.map((symbol) => ( - - ))} - + ${formatNumber(formatEther(total - claimable - claimed), 'USD')} + } placement="top" arrow> + + {rewardsTokens.map((symbol) => { + const isExaToken = symbol.length > 3 && symbol.startsWith('exa'); + const imagePath = isExaToken ? `/img/exaTokens/${symbol}.svg` : `/img/assets/${symbol}.svg`; + return ; + })} + + - {totalEarned > 0n && start !== undefined && parameters && ( - - {t('By staking end on ')} {parseTimestamp(start / WAD + parameters.refTime)} - - )} ); -} -export default React.memo(StakingProgress); +}; + +type TooltipContentProps = { + tokensData?: Record; +}; + +const TooltipContent: FC = ({ tokensData }) => { + if (!tokensData) return null; + + return ( + + {Object.entries(tokensData).map(([symbol, valueUSD]) => { + const isExaToken = symbol.length > 3 && symbol.startsWith('exa'); + const imagePath = isExaToken ? `/img/exaTokens/${symbol}.svg` : `/img/assets/${symbol}.svg`; + return ( + + + {symbol} + + {symbol} + + ${formatNumber(formatEther(valueUSD), 'USD')} + + + ); + })} + + ); +}; + +export default StakingProgressBar; diff --git a/components/staking/StakingProgress/stakingProgressBar.tsx b/components/staking/StakingProgress/stakingProgressBar.tsx deleted file mode 100644 index 5642a7d30..000000000 --- a/components/staking/StakingProgress/stakingProgressBar.tsx +++ /dev/null @@ -1,301 +0,0 @@ -import React, { FC, ReactNode } from 'react'; -import Tooltip from '@mui/material/Tooltip'; -import { styled } from '@mui/system'; -import { Avatar, AvatarGroup, Box, Typography, useTheme } from '@mui/material'; -import formatNumber from 'utils/formatNumber'; -import { formatEther } from 'viem'; -import { useStakeEXA } from 'contexts/StakeEXAContext'; -import Image from 'next/image'; -import { useTranslation } from 'react-i18next'; - -const ProgressBar = styled('div')<{ ended: boolean }>(({ ended, theme }) => ({ - display: 'flex', - height: 24, - borderRadius: 999, - width: '100%', - position: 'relative', - overflow: 'hidden', - ...(!ended && { border: `1px solid ${theme.palette.figma.green[100]}` }), -})); - -const ClaimedProgressBar = styled('div')<{ width: number }>(({ width, theme }) => ({ - width: `${width}%`, - borderRadius: '0px 0 0 0px', - backgroundColor: theme.palette.figma.green[500], - transition: 'background-color 0.3s', - position: 'relative', - overflow: 'visible', - '&:hover': { - cursor: 'pointer', - }, - '&::before': { - content: '""', - position: 'absolute', - right: -4, - top: 0, - bottom: 0, - width: 10, - backgroundColor: theme.palette.figma.green[500], - transform: 'scaleX(0.6)', - transition: 'background-color 0.3s', - }, -})); - -const RestProgressBar = styled('div')<{ width: number; ended?: boolean }>(({ width, ended, theme }) => ({ - width: `${width}%`, - borderRadius: '0 4px 4px 0', - backgroundColor: ended ? 'transparent' : theme.palette.figma.green[50], - transition: 'background-color 0.3s', - position: 'relative', - '&:hover': { - cursor: 'pointer', - }, - ...(ended && { - backgroundImage: `repeating-linear-gradient( - -70deg, - red, - red 3px, - #ffffff 3px, - #ffffff 6px - )`, - }), - '&::before': { - content: '""', - position: 'absolute', - right: -4, - top: 0, - bottom: 0, - width: 10, - backgroundColor: ended ? 'transparent' : theme.palette.figma.green[50], - backgroundImage: ended - ? `repeating-linear-gradient( - -70deg, - #ffffff , - #ffffff 3px - red 3px, - red 6px, - )` - : 'none', - }, -})); - -const ClaimableProgressBar = styled('div')<{ width: number }>(({ width, theme }) => ({ - width: `${width}%`, - backgroundColor: theme.palette.figma.green[50], - transition: 'background-color 0.3s', - '&:hover': { - cursor: 'pointer', - }, - backgroundImage: `repeating-linear-gradient( - -70deg, - ${theme.palette.figma.green[500]}, - ${theme.palette.figma.green[500]} 3px, - #ffffff 3px, - #ffffff 6px - )`, -})); - -interface DualProgressBarProps { - claimed: bigint; - claimable: bigint; - total: bigint; - tooltip1?: ReactNode; - tooltip2?: ReactNode; - tooltip3?: ReactNode; - ended: boolean; -} - -const StakingProgressBar: FC = ({ - claimed = 0n, - claimable = 0n, - total = 0n, - tooltip1 = `$${formatNumber(formatEther(claimed), 'USD')}`, - tooltip2 = `$${formatNumber(formatEther(claimable), 'USD')}`, - tooltip3 = `$${formatNumber(formatEther(total - claimable - claimed), 'USD')}`, - ended = false, -}) => { - const { palette } = useTheme(); - const { t } = useTranslation(); - const { rewardsTokens, claimableTokens, claimedTokens, earnedTokens } = useStakeEXA(); - - const claimedPercentage = total > 0n ? Number((claimed * 100n) / total) : 0; - const claimablePercentage = total > 0n ? Number((claimable * 100n) / total) : 0; - const restValue = Math.max(0, 100 - claimedPercentage - claimablePercentage); - - const remainingTokens = Object.keys(claimableTokens).reduce( - (acc, symbol) => { - const claimableValue = claimableTokens[symbol] || 0n; - const claimedValue = claimedTokens[symbol] || 0n; - const totalValue = earnedTokens[symbol] || 0n; - - const remainingValue = totalValue - claimableValue - claimedValue; - - acc[symbol] = remainingValue; - - return acc; - }, - {} as Record, - ); - - return ( - - - - - - - - - - - - - - - - - - {t('Claimed')} - - - - ${formatNumber(formatEther(claimed), 'USD')} - } placement="top" arrow> - - {Object.entries(claimedTokens).map(([symbol]) => { - const isExaToken = symbol.length > 3 && symbol.startsWith('exa'); - const imagePath = isExaToken ? `/img/exaTokens/${symbol}.svg` : `/img/assets/${symbol}.svg`; - return ; - })} - - - - - - - - - Available to claim - - - - ${formatNumber(formatEther(claimable), 'USD')} - } placement="top" arrow> - - {Object.entries(claimableTokens).map(([symbol]) => { - const isExaToken = symbol.length > 3 && symbol.startsWith('exa'); - const imagePath = isExaToken ? `/img/exaTokens/${symbol}.svg` : `/img/assets/${symbol}.svg`; - return ; - })} - - - - - - - - - {ended ? t('Not available to claim') : t('Projected Remainder')} - - - - ${formatNumber(formatEther(total - claimable - claimed), 'USD')} - } placement="top" arrow> - - {rewardsTokens.map((symbol) => { - const isExaToken = symbol.length > 3 && symbol.startsWith('exa'); - const imagePath = isExaToken ? `/img/exaTokens/${symbol}.svg` : `/img/assets/${symbol}.svg`; - return ; - })} - - - - - - - ); -}; - -type TooltipContentProps = { - tokensData?: Record; -}; - -const TooltipContent: FC = ({ tokensData }) => { - if (!tokensData) return null; - - return ( - - {Object.entries(tokensData).map(([symbol, valueUSD]) => { - const isExaToken = symbol.length > 3 && symbol.startsWith('exa'); - const imagePath = isExaToken ? `/img/exaTokens/${symbol}.svg` : `/img/assets/${symbol}.svg`; - return ( - - - {symbol} - - {symbol} - - ${formatNumber(formatEther(valueUSD), 'USD')} - - - ); - })} - - ); -}; - -export default StakingProgressBar;