mars-v2-frontend/components/Account/FundAccountModal.tsx

214 lines
7.6 KiB
TypeScript
Raw Normal View History

import { Switch } from '@headlessui/react'
import BigNumber from 'bignumber.js'
import { useEffect, useMemo, useState } from 'react'
import { toast } from 'react-toastify'
import useLocalStorageState from 'use-local-storage-state'
import Button from 'components/Button'
import CircularProgress from 'components/CircularProgress'
import MarsProtocolLogo from 'components/Icons/mars-protocol.svg'
import Modal from 'components/Modal'
import Slider from 'components/Slider'
import Text from 'components/Text'
import useDepositCreditAccount from 'hooks/mutations/useDepositCreditAccount'
import useAllBalances from 'hooks/useAllBalances'
import useAllowedCoins from 'hooks/useAllowedCoins'
import useCreditManagerStore from 'stores/useCreditManagerStore'
import { getTokenDecimals, getTokenSymbol } from 'utils/tokens'
interface Props {
open: boolean
setOpen: (open: boolean) => void
}
const FundAccountModal = ({ open, setOpen }: Props) => {
const [amount, setAmount] = useState(0)
const [selectedToken, setSelectedToken] = useState('')
const selectedAccount = useCreditManagerStore((s) => s.selectedAccount)
const [lendAssets, setLendAssets] = useLocalStorageState(`lendAssets_${selectedAccount}`, {
defaultValue: false,
})
const { data: balancesData } = useAllBalances()
const { data: allowedCoinsData, isLoading: isLoadingAllowedCoins } = useAllowedCoins()
const { mutate, isLoading } = useDepositCreditAccount(
selectedAccount || '',
selectedToken,
BigNumber(amount)
.times(10 ** getTokenDecimals(selectedToken))
.toNumber(),
{
onSuccess: () => {
setAmount(0)
toast.success(`${amount} ${getTokenSymbol(selectedToken)} successfully Deposited`)
setOpen(false)
},
},
)
useEffect(() => {
if (allowedCoinsData && allowedCoinsData.length > 0) {
// initialize selected token when allowedCoins fetch data is available
setSelectedToken(allowedCoinsData[0])
}
}, [allowedCoinsData])
const walletAmount = useMemo(() => {
if (!selectedToken) return 0
return BigNumber(balancesData?.find((balance) => balance.denom === selectedToken)?.amount ?? 0)
.div(10 ** getTokenDecimals(selectedToken))
.toNumber()
}, [balancesData, selectedToken])
const handleValueChange = (value: number) => {
if (value > walletAmount) {
setAmount(walletAmount)
return
}
setAmount(value)
}
const maxValue = walletAmount
const percentageValue = isNaN(amount) ? 0 : (amount * 100) / maxValue
return (
<Modal open={open} setOpen={setOpen}>
<div className='flex min-h-[520px] w-full'>
{isLoading && (
<div className='absolute inset-0 z-40 grid place-items-center bg-black/50'>
<CircularProgress />
</div>
)}
<div className='flex flex-1 flex-col items-start justify-between bg-fund-modal bg-cover p-6'>
<div>
<Text size='2xs' uppercase={true} className='mb-3 text-white'>
About
</Text>
<Text size='xl' className='mb-4 text-white'>
Bringing the next generation of video creation to the Metaverse.
<br />
Powered by deep-learning.
</Text>
</div>
<div className='w-[153px] text-white'>
<MarsProtocolLogo />
</div>
</div>
<div className='flex flex-1 flex-col p-6'>
<Text size='xl' uppercase={true} className='mb-4 text-white'>
Account {selectedAccount}
</Text>
<div className='p-3" mb-2'>
<Text size='sm' uppercase={true} className='mb-1 text-white'>
Fund Account
</Text>
<Text size='sm' className='mb-6 text-white/60'>
Transfer assets from your injective wallet to your Mars credit account. If you dont
have any assets in your injective wallet use the injective bridge to transfer funds to
your injective wallet.
</Text>
{isLoadingAllowedCoins ? (
<p>Loading...</p>
) : (
<>
<div className='mb-4 rounded-md border border-white/20'>
<div className='mb-1 flex justify-between border-b border-white/20 p-2'>
<Text size='sm' className='text-white'>
Asset:
</Text>
<select
className='bg-transparent text-white outline-0'
onChange={(e) => {
setSelectedToken(e.target.value)
if (e.target.value !== selectedToken) setAmount(0)
}}
value={selectedToken}
>
{allowedCoinsData?.map((entry) => (
<option key={entry} value={entry}>
{getTokenSymbol(entry)}
</option>
))}
</select>
</div>
<div className='flex justify-between p-2'>
<Text size='sm' className='text-white'>
Amount:
</Text>
<input
type='number'
className='appearance-none bg-transparent text-right text-white'
value={amount}
min='0'
onChange={(e) => handleValueChange(e.target.valueAsNumber)}
onBlur={(e) => {
if (e.target.value === '') setAmount(0)
}}
/>
</div>
</div>
<Text size='xs' uppercase={true} className='mb-2 text-white/60'>
{`In wallet: ${walletAmount.toLocaleString()} ${getTokenSymbol(selectedToken)}`}
</Text>
<Slider
className='mb-6'
value={percentageValue}
onChange={(value) => {
const decimal = value[0] / 100
const tokenDecimals = getTokenDecimals(selectedToken)
// limit decimal precision based on token contract decimals
const newAmount = Number((decimal * maxValue).toFixed(tokenDecimals))
setAmount(newAmount)
}}
onMaxClick={() => setAmount(maxValue)}
/>
</>
)}
</div>
<div className='mb-2 flex items-center justify-between'>
<div>
<Text size='sm' uppercase={true} className='mb-1 text-white'>
Lending Assets
</Text>
<Text size='sm' className='text-white/60'>
Lend assets from account to earn yield.
</Text>
</div>
<Switch
checked={lendAssets}
onChange={setLendAssets}
className={`${
lendAssets ? 'bg-blue-600' : 'bg-gray-400'
} relative inline-flex h-6 w-11 items-center rounded-full`}
>
<span
className={`${
lendAssets ? 'translate-x-6' : 'translate-x-1'
} inline-block h-4 w-4 transform rounded-full bg-white transition`}
/>
</Switch>
</div>
<Button
className='mt-auto w-full'
onClick={() => mutate()}
disabled={amount === 0 || !amount}
>
Fund Account
</Button>
</div>
</div>
</Modal>
)
}
export default FundAccountModal