214 lines
7.6 KiB
TypeScript
214 lines
7.6 KiB
TypeScript
|
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 don’t
|
|||
|
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
|