add redeem page for when token sale is closed

This commit is contained in:
Maximilian Schneider 2021-07-08 21:13:11 +02:00
parent 006db8f8e7
commit 05f3417265
6 changed files with 239 additions and 14 deletions

128
components/RedeemModal.tsx Normal file
View File

@ -0,0 +1,128 @@
import { useEffect, useState } from 'react'
import { LinkIcon } from '@heroicons/react/solid'
import useWalletStore from '../stores/useWalletStore'
import Button from './Button'
import { ConnectWalletButtonSmall } from './ConnectWalletButton'
import Loading from './Loading'
import useLargestAccounts from '../hooks/useLargestAccounts'
import useVaults from '../hooks/useVaults'
const RedeemModal = () => {
const actions = useWalletStore((s) => s.actions)
const connected = useWalletStore((s) => s.connected)
const wallet = useWalletStore((s) => s.current)
const largestAccounts = useLargestAccounts()
const vaults = useVaults()
const redeemableBalance = largestAccounts.redeemable?.balance || 0
const mangoAvailable = vaults.usdc
? (redeemableBalance * vaults.mango.balance) / vaults.usdc.balance
: 0
console.log('balance', redeemableBalance, mangoAvailable)
const [submitting, setSubmitting] = useState(false)
const [loading, setLoading] = useState(true)
const handleConnectDisconnect = () => {
if (connected) {
wallet.disconnect()
} else {
wallet.connect()
}
}
const handleRedeem = () => {
setSubmitting(true)
}
useEffect(() => {
setLoading(true)
if (largestAccounts.redeemable) {
setLoading(false)
}
}, [largestAccounts])
useEffect(() => {
if (submitting) {
const handleSubmit = async () => {
await actions.redeem()
setSubmitting(false)
}
handleSubmit()
}
}, [submitting])
const disableFormInputs = !connected || loading
const disableSubmit = disableFormInputs || redeemableBalance <= 0
return (
<>
<div className="bg-bkg-2 border border-bkg-3 col-span-7 p-7 rounded-lg shadow-lg">
<div className="pb-4 text-center">
{!submitting ? (
<>
<h2>Redeem your MNGO</h2>
<p>Welcome to the DAO, let&apos;s build together.</p>
</>
) : null}
{submitting ? (
<>
<h2>Approve the transaction</h2>
<p>Almost there...</p>
</>
) : null}
</div>
{submitting ? (
<div className="flex h-64 items-center justify-center">
<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>
<Button
onClick={() => handleRedeem()}
className="w-full py-2.5"
disabled={disableSubmit}
>
<div className={`flex items-center justify-center`}>
Redeem 🥭
</div>
</Button>
</div>
</div>
<div className="flex justify-center">
{connected ? (
<Button
className="rounded-full bg-bkg-4 text-fgd-3 font-normal"
onClick={() => handleConnectDisconnect()}
secondary
>
<div className="flex items-center text-sm">
<LinkIcon className="h-4 w-4 mr-1" />
Disconnect
</div>
</Button>
) : (
<ConnectWalletButtonSmall onClick={handleConnectDisconnect}>
<div className="flex items-center justify-center text-sm">
<LinkIcon className="h-4 w-4 mr-1" />
Connect Wallet
</div>
</ConnectWalletButtonSmall>
)}
</div>
</>
)}
</div>
</>
)
}
export default RedeemModal

13
pages/RedeemPage.tsx Normal file
View File

@ -0,0 +1,13 @@
import RedeemModal from '../components/RedeemModal'
const RedeemPage = () => {
return (
<div className="flex justify-center">
<div className="max-w-screen-md grid grid-cols-12 gap-4 w-full">
<RedeemModal />
</div>
</div>
)
}
export default RedeemPage

21
pages/SalePage.tsx Normal file
View File

@ -0,0 +1,21 @@
import ContributionModal from '../components/ContributionModal'
import PoolInfoCards from '../components/PoolInfoCards'
import HeroSection from '../components/HeroSection'
import LandingContent from '../components/LandingContent'
const SalePage = () => {
return (
<>
<HeroSection />
<PoolInfoCards />
<LandingContent />
<div className="flex justify-center">
<div className="max-w-screen-md grid grid-cols-12 gap-4 w-full">
<ContributionModal />
</div>
</div>
</>
)
}
export default SalePage

View File

@ -33,7 +33,7 @@ function App({ Component, pageProps }) {
<meta name="twitter:description" content={description} />
<meta name="twitter:image" content="/twitter-image.png" />
<link rel="manifest" href="/manifest.json"></link>
{/* <link rel="manifest" href="/manifest.json"></link> */}
</Head>
<ThemeProvider defaultTheme="Mango">
<Component {...pageProps} />

View File

@ -1,24 +1,19 @@
import SalePage from './SalePage'
import RedeemPage from './RedeemPage'
import Notifications from '../components/Notification'
import TopBar from '../components/TopBar'
import ContributionModal from '../components/ContributionModal'
import PoolInfoCards from '../components/PoolInfoCards'
import HeroSection from '../components/HeroSection'
import LandingContent from '../components/LandingContent'
import usePool from '../hooks/usePool'
const Index = () => {
const { endIdo } = usePool()
return (
<div className={`bg-bkg-1 text-fgd-1 transition-all`}>
<TopBar />
<Notifications />
<HeroSection />
<PoolInfoCards />
<LandingContent />
<div className="flex justify-center">
<div className="max-w-screen-md grid grid-cols-12 gap-4 w-full">
<ContributionModal />
</div>
</div>
{endIdo?.isAfter() && <SalePage />}
{endIdo?.isBefore() && <RedeemPage />}
</div>
)
}

View File

@ -291,6 +291,74 @@ const useWalletStore = create<WalletStore>((set, get) => ({
await actions.fetchWalletTokenAccounts()
actions.fetchUsdcVault()
},
async redeem() {
console.log('redeem')
const actions = get().actions
await actions.fetchWalletTokenAccounts()
const {
program,
pool,
tokenAccounts,
mints,
current: wallet,
connection: { current: connection },
} = get()
const redeemable = findLargestBalanceAccountForMint(
mints,
tokenAccounts,
pool.redeemableMint
)
const watermelon = findLargestBalanceAccountForMint(
mints,
tokenAccounts,
pool.watermelonMint
)
console.log(redeemable, watermelon, 'exchangeRedeemableForMango')
const [poolSigner] = await anchor.web3.PublicKey.findProgramAddress(
[pool.watermelonMint.toBuffer()],
program.programId
)
const transaction = new Transaction()
let watermelonAccount = watermelon?.account?.publicKey
if (!watermelonAccount) {
const [ins, pk] = await createAssociatedTokenAccount(
wallet.publicKey,
wallet.publicKey,
pool.watermelonMint
)
transaction.add(ins)
watermelonAccount = pk
}
transaction.add(
program.instruction.exchangeRedeemableForWatermelon(
redeemable.account.account.amount,
{
accounts: {
poolAccount: POOL_PK,
poolSigner,
redeemableMint: pool.redeemableMint,
poolWatermelon: pool.poolWatermelon,
userAuthority: wallet.publicKey,
userWatermelon: watermelonAccount,
userRedeemable: redeemable.account.publicKey,
tokenProgram: TOKEN_PROGRAM_ID,
clock: anchor.web3.SYSVAR_CLOCK_PUBKEY,
},
}
)
)
await sendTransaction({ transaction, wallet, connection })
await actions.fetchPool()
},
},
set: (fn) => set(produce(fn)),
}))