mango-token-sale/components/ContributionModal.tsx

344 lines
12 KiB
TypeScript
Raw Normal View History

import { useEffect, useState } from 'react'
import {
ExclamationCircleIcon,
LockClosedIcon,
LockOpenIcon,
} from '@heroicons/react/outline'
import useWalletStore from '../stores/useWalletStore'
import Input from './Input'
import Button from './Button'
2021-07-16 03:18:21 -07:00
import ConnectWalletButton from './ConnectWalletButton'
2021-07-07 04:16:54 -07:00
import PoolCountdown from './PoolCountdown'
import Slider from './Slider'
import Loading from './Loading'
import WalletIcon from './WalletIcon'
2021-07-04 16:17:40 -07:00
import useLargestAccounts from '../hooks/useLargestAccounts'
import useVaults from '../hooks/useVaults'
2021-07-07 04:16:54 -07:00
import usePool from '../hooks/usePool'
import styled from '@emotion/styled'
import 'twin.macro'
const SmallButton = styled.button``
const ContributionModal = () => {
2021-07-04 16:17:40 -07:00
const actions = useWalletStore((s) => s.actions)
const connected = useWalletStore((s) => s.connected)
const wallet = useWalletStore((s) => s.current)
2021-07-04 16:17:40 -07:00
const largestAccounts = useLargestAccounts()
const vaults = useVaults()
2021-07-07 04:16:54 -07:00
const { endIdo, endDeposits } = usePool()
2021-07-04 16:17:40 -07:00
const usdcBalance = largestAccounts.usdc?.balance || 0
const redeemableBalance = largestAccounts.redeemable?.balance || 0
2021-07-05 05:34:53 -07:00
const totalBalance = usdcBalance + redeemableBalance
2021-07-06 15:35:53 -07:00
// const mangoRedeemable = vaults.usdc
// ? (redeemableBalance * vaults.mango.balance) / vaults.usdc.balance
// : 0
2021-07-04 16:17:40 -07:00
const [walletAmount, setWalletAmount] = useState(0)
2021-04-29 18:40:11 -07:00
const [contributionAmount, setContributionAmount] = useState(0)
const [submitting, setSubmitting] = useState(false)
const [submitted, setSubmitted] = useState(false)
const [editContribution, setEditContribution] = useState(false)
const [loading, setLoading] = useState(true)
2021-04-29 18:40:11 -07:00
const [maxButtonTransition, setMaxButtonTransition] = useState(false)
const [errorMessage, setErrorMessage] = useState(null)
2021-07-16 09:07:37 -07:00
const priceFormat = new Intl.NumberFormat('en-US', {
maximumSignificantDigits: 4,
})
2021-07-04 16:17:40 -07:00
useEffect(() => {
console.log('refresh modal on balance change')
setWalletAmount(usdcBalance)
2021-07-04 16:17:40 -07:00
setContributionAmount(redeemableBalance)
2021-07-05 05:52:49 -07:00
if (redeemableBalance > 0) {
setSubmitted(true)
}
}, [totalBalance])
2021-07-04 16:17:40 -07:00
const handleConnectDisconnect = () => {
if (connected) {
setSubmitted(false)
setEditContribution(false)
wallet.disconnect()
} else {
wallet.connect()
}
}
const handleSetContribution = () => {
setSubmitting(true)
setEditContribution(false)
}
const handleEditContribution = () => {
setEditContribution(true)
setSubmitted(false)
}
const onChangeAmountInput = (amount) => {
setWalletAmount(totalBalance - amount)
setContributionAmount(amount)
2021-07-07 04:16:54 -07:00
if (endDeposits?.isBefore() && amount > redeemableBalance) {
2021-07-06 15:03:58 -07:00
setErrorMessage('Deposits ended, contribution can not increase')
2021-07-06 15:35:53 -07:00
setTimeout(() => setErrorMessage(null), 4000)
2021-07-06 15:03:58 -07:00
}
}
const onChangeSlider = (percentage) => {
let newContribution = Math.round(percentage * totalBalance) / 100
2021-07-07 04:16:54 -07:00
if (endDeposits?.isBefore() && newContribution > redeemableBalance) {
2021-07-06 15:35:53 -07:00
newContribution = redeemableBalance
setErrorMessage('Deposits ended, contribution can not increase')
2021-07-06 15:35:53 -07:00
setTimeout(() => setErrorMessage(null), 4000)
}
setWalletAmount(totalBalance - newContribution)
setContributionAmount(newContribution)
}
const handleMax = () => {
2021-07-07 04:16:54 -07:00
if (endDeposits?.isAfter()) {
setWalletAmount(0)
setContributionAmount(totalBalance)
} else {
setWalletAmount(usdcBalance)
setContributionAmount(redeemableBalance)
}
2021-04-29 18:40:11 -07:00
setMaxButtonTransition(true)
}
2021-04-29 18:40:11 -07:00
useEffect(() => {
if (maxButtonTransition) {
setMaxButtonTransition(false)
}
}, [maxButtonTransition])
useEffect(() => {
setLoading(true)
2021-07-05 05:34:53 -07:00
if (largestAccounts.usdc) {
setLoading(false)
}
2021-07-05 05:34:53 -07:00
}, [largestAccounts])
useEffect(() => {
if (submitting) {
2021-07-05 08:32:33 -07:00
const handleSubmit = async () => {
2021-07-05 06:28:01 -07:00
await actions.submitContribution(contributionAmount)
setSubmitted(true)
setSubmitting(false)
2021-07-05 08:32:33 -07:00
}
handleSubmit()
}
}, [submitting])
2021-04-29 18:40:11 -07:00
const disableFormInputs = submitted || !connected || loading
2021-07-06 15:35:53 -07:00
const dontAddMore =
2021-07-07 04:16:54 -07:00
endDeposits?.isBefore() && contributionAmount > redeemableBalance
2021-07-06 15:35:53 -07:00
const disableSubmit = disableFormInputs || walletAmount < 0 || dontAddMore
return (
2021-07-06 06:25:55 -07:00
<>
<div className="bg-bkg-2 border border-bkg-3 col-span-7 p-7 rounded-lg shadow-lg">
2021-04-29 23:16:02 -07:00
<div className="pb-4 text-center">
{!submitted && !submitting && !editContribution ? (
<>
2021-07-06 06:25:55 -07:00
<h2>Plant Your Seed</h2>
2021-04-29 23:16:02 -07:00
<p>This is the start of something big.</p>
</>
) : null}
2021-04-29 23:16:02 -07:00
{!submitted && submitting ? (
<>
<h2>Approve the transaction</h2>
<p>Almost there...</p>
</>
) : null}
2021-04-29 23:16:02 -07:00
{submitted && !submitting ? (
<>
<h2>Your contribution amount</h2>
<p>A new seed planted...</p>
</>
) : null}
2021-04-29 23:16:02 -07:00
{editContribution && !submitting ? (
<>
<h2>Funds unlocked</h2>
<p>Increase or reduce your contribution...</p>
</>
) : null}
</div>
2021-04-29 23:16:02 -07:00
{submitting ? (
2021-07-06 06:25:55 -07:00
<div className="flex h-64 items-center justify-center">
2021-04-29 23:16:02 -07:00
<Loading className="h-6 w-6 mb-3 text-primary-light" />
</div>
) : (
<>
<div
className={`${
connected ? 'opacity-100' : 'opacity-30'
} pb-6 transiton-all duration-1000 w-full`}
>
<div className="flex justify-between pb-2">
<div className="flex items-center text-xs text-fgd-4">
<WalletIcon className="w-4 h-4 mr-1 text-fgd-3 fill-current" />
{connected ? (
loading ? (
<div className="bg-bkg-4 rounded w-10 h-4 animate-pulse" />
) : (
<span className="font-display text-fgd-1 ml-1">
{walletAmount}
2021-04-29 23:16:02 -07:00
</span>
)
) : (
2021-04-29 23:16:02 -07:00
'----'
)}
<img
alt=""
width="16"
height="16"
src="/icons/usdc.svg"
className={`ml-1`}
/>
</div>
<div className="flex">
{submitted ? (
<SmallButton
2021-04-29 23:16:02 -07:00
className="ring-1 ring-secondary-1-light ring-inset hover:ring-secondary-1-dark hover:bg-transparent hover:text-secondary-1-dark font-normal rounded text-secondary-1-light text-xs py-0.5 px-1.5 mr-2"
disabled={!connected}
onClick={() => handleEditContribution()}
>
Unlock
</SmallButton>
2021-04-29 23:16:02 -07:00
) : null}
<SmallButton
2021-04-29 23:16:02 -07:00
className={`${
disableFormInputs && 'opacity-30'
} bg-bkg-4 hover:bg-bkg-3 font-normal rounded text-fgd-3 text-xs py-0.5 px-1.5`}
2021-04-29 23:16:02 -07:00
disabled={disableFormInputs}
onClick={() => handleMax()}
>
2021-04-29 23:16:02 -07:00
Max
</SmallButton>
2021-04-29 23:16:02 -07:00
</div>
</div>
<div className="flex items-center pb-4 relative">
{submitted ? (
<LockClosedIcon className="absolute text-secondary-2-light h-4 w-4 mb-0.5 left-2 z-10" />
) : null}
{editContribution ? (
<LockOpenIcon className="absolute text-secondary-1-light h-4 w-4 mb-0.5 left-2 z-10" />
) : null}
2021-04-29 23:16:02 -07:00
<Input
className={(submitted || editContribution) && 'pl-7'}
disabled={disableFormInputs}
type="text"
onChange={(e) => onChangeAmountInput(e.target.value)}
value={loading ? '' : contributionAmount}
suffix="USDC"
/>
</div>
<div
className={`${
!submitted ? 'opacity-100' : 'opacity-30'
} transiton-all duration-1000`}
>
2021-07-06 15:35:53 -07:00
<div className="pb-12">
2021-04-29 23:16:02 -07:00
<Slider
disabled={disableFormInputs}
2021-07-05 05:34:53 -07:00
value={(100 * contributionAmount) / totalBalance}
2021-04-29 23:16:02 -07:00
onChange={(v) => onChangeSlider(v)}
step={1}
maxButtonTransition={maxButtonTransition}
/>
</div>
2021-07-06 15:35:53 -07:00
<div className="h-12 pb-4">
{errorMessage && (
2021-07-06 15:03:58 -07:00
<div className="flex items-center pt-1.5 text-secondary-2-light">
<ExclamationCircleIcon className="h-4 w-4 mr-1.5" />
{errorMessage}
</div>
)}
</div>
<Button
2021-04-29 23:16:02 -07:00
onClick={() => handleSetContribution()}
className="w-full py-2.5"
2021-07-06 15:35:53 -07:00
disabled={disableSubmit}
>
2021-04-29 23:16:02 -07:00
<div className={`flex items-center justify-center`}>
2021-07-06 15:35:53 -07:00
{dontAddMore
? 'Sorry you cant add anymore 🥲'
: 'Set Contribution'}
2021-04-29 23:16:02 -07:00
</div>
</Button>
</div>
</div>
2021-07-16 03:18:21 -07:00
<div className="flex items-center justify-center">
<ConnectWalletButton onClick={handleConnectDisconnect} />
2021-07-06 06:25:55 -07:00
</div>
2021-04-29 23:16:02 -07:00
</>
)}
2021-07-06 06:25:55 -07:00
</div>
<div className="bg-gradient-to-br from-secondary-4-dark to-secondary-4-light border border-bkg-3 col-span-5 p-7 rounded-lg shadow-lg">
<div className="border-b border-bkg-4 pb-4 text-center">
<p className="text-fgd-3">Estimated Token Price</p>
<div className="flex items-center justify-center pt-0.5">
<img
alt=""
width="20"
height="20"
src="/icons/usdc.svg"
className={`mr-2`}
/>
<div className="font-bold text-fgd-1 text-xl">
2021-07-16 09:07:37 -07:00
{priceFormat.format(vaults.estimatedPrice)}
2021-07-06 06:25:55 -07:00
</div>
</div>
</div>
<div className="border-b border-bkg-4 py-4 text-center">
<p className="text-fgd-3">Total USDC Deposited</p>
<div className="flex items-center justify-center pt-0.5">
<div className="font-bold text-fgd-1 text-base">
2021-07-07 04:16:54 -07:00
{vaults.usdcBalance}
2021-07-06 06:25:55 -07:00
</div>
</div>
</div>
<div className="border-b border-bkg-4 py-4 text-center">
<p className="text-fgd-3">Locked MNGO in Pool</p>
<div className="flex items-center justify-center pt-0.5">
<img className="h-5 mr-2 w-auto" src="/logo.svg" alt="mango" />
<div className="font-bold text-fgd-1 text-base">
2021-07-07 04:16:54 -07:00
{vaults.mangoBalance}
2021-07-06 06:25:55 -07:00
</div>
</div>
</div>
<div className="border-b border-bkg-4 py-4 text-center">
<p className="text-fgd-3">Deposits Close</p>
2021-07-07 04:37:12 -07:00
<PoolCountdown date={endDeposits} className="justify-center pt-1" />
2021-07-06 06:25:55 -07:00
</div>
<div className="pt-4 text-center">
<p className="text-fgd-3">Withdrawals Close</p>
2021-07-07 04:37:12 -07:00
<PoolCountdown date={endIdo} className="justify-center pt-1" />
2021-07-06 06:25:55 -07:00
</div>
{/* <p>
Start: {startIdo?.fromNow()} ({startIdo?.format()})
</p>
<p>
End Deposits: {endDeposits?.fromNow()} ({endDeposits?.format()})
</p>
<p>
End Withdraws: {endIdo?.fromNow()} ({endIdo?.format()})
</p>
<p>Current USDC in Pool: {vaults.usdc?.balance || 'N/A'}</p>
<p>Locked MNGO in Pool: {vaults.mango?.balance || 'N/A'}</p> */}
</div>
</>
)
}
export default ContributionModal