mars-v2-frontend/src/components/RewardsCenter.tsx
2023-10-03 15:54:22 +02:00

129 lines
4.0 KiB
TypeScript

import { useCallback, useEffect, useMemo, useState } from 'react'
import AssetBalanceRow from 'components/Asset/AssetBalanceRow'
import Button from 'components/Button'
import DisplayCurrency from 'components/DisplayCurrency'
import Divider from 'components/Divider'
import { Logo } from 'components/Icons'
import Overlay from 'components/Overlay'
import Text from 'components/Text'
import { ASSETS } from 'constants/assets'
import { ORACLE_DENOM } from 'constants/oracle'
import useAccountId from 'hooks/useAccountId'
import usePrices from 'hooks/usePrices'
import useToggle from 'hooks/useToggle'
import useUnclaimedRewards from 'hooks/useUnclaimedRewards'
import useStore from 'store'
import { BNCoin } from 'types/classes/BNCoin'
import { byDenom } from 'utils/array'
import { defaultFee } from 'utils/constants'
import { formatAmountWithSymbol, getCoinValue } from 'utils/formatters'
const renderIncentives = (unclaimedRewards: BNCoin[]) => {
if (unclaimedRewards.length === 0)
return (
<Text className='w-full px-4 text-center' size='sm'>
You have no claimable rewards.
</Text>
)
return unclaimedRewards.map((reward, index) => {
const asset = ASSETS.find(byDenom(reward.denom))
if (!asset) return null
return (
<div className='w-full' key={index}>
{index !== 0 && <Divider />}
<AssetBalanceRow key={reward.denom} coin={reward} asset={asset} />
</div>
)
})
}
export default function RewardsCenter() {
const accountId = useAccountId()
const [isConfirming, setIsConfirming] = useState(false)
const [estimatedFee, setEstimatedFee] = useState(defaultFee)
const [showRewardsCenter, setShowRewardsCenter] = useToggle()
const claimRewards = useStore((s) => s.claimRewards)
const { data: prices } = usePrices()
const { data: unclaimedRewards } = useUnclaimedRewards()
const totalRewardsCoin = useMemo(() => {
let total = 0
unclaimedRewards.forEach((reward) => {
total = total + getCoinValue(reward, prices).toNumber()
})
return new BNCoin({
denom: ORACLE_DENOM,
amount: total.toString(),
})
}, [prices, unclaimedRewards])
const hasIncentives = unclaimedRewards.length > 0
const claimTx = useMemo(() => {
return claimRewards({
accountId: accountId || '',
})
}, [accountId, claimRewards])
useEffect(() => {
claimTx.estimateFee().then(setEstimatedFee)
}, [claimTx])
const handleClaim = useCallback(async () => {
if (accountId) {
setIsConfirming(true)
await claimTx.execute()
setIsConfirming(false)
}
}, [accountId, claimTx])
return (
<div className={'relative'}>
<Button
variant='solid'
color='tertiary'
leftIcon={<Logo />}
onClick={() => {
setShowRewardsCenter(!showRewardsCenter)
}}
hasFocus={showRewardsCenter}
>
<div className='relative flex items-center h-fullx'>
<DisplayCurrency coin={totalRewardsCoin} />
</div>
</Button>
<Overlay className={'mt-2 right-0'} show={showRewardsCenter} setShow={setShowRewardsCenter}>
<div className='flex w-[402px] flex-wrap'>
<Text size='lg' className='w-full px-4 py-5 rounded-t-base bg-white/10'>
Rewards Center
</Text>
<div className='w-full p-4'>
<div className='flex flex-wrap w-full gap-4 pb-4'>
{renderIncentives(unclaimedRewards)}
</div>
{hasIncentives && (
<>
<Button
variant='solid'
color='tertiary'
className='w-full py-2'
showProgressIndicator={isConfirming}
text={'Claim total account rewards'}
onClick={handleClaim}
/>
<Text className='w-full py-4 text-center text-white/50' size='sm'>
Tx Fee: {formatAmountWithSymbol(estimatedFee.amount[0])}
</Text>
</>
)}
</div>
</div>
</Overlay>
</div>
)
}