Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Thirdweb V5 Migration : Withdraw #317

Merged
merged 6 commits into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion ui/components/privy/PrivyConnectWallet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,11 @@ export function PrivyConnectWallet({
const { login } = useLogin({
onComplete: async ({ user, isNewUser, wasAlreadyAuthenticated }) => {
//If the user signs in and wasn't already authenticated, check if they have a citizen NFT and redirect them to their profile or the guest page
if (!wasAlreadyAuthenticated && router.pathname !== '/submit') {
if (
!wasAlreadyAuthenticated &&
router.pathname !== '/submit' &&
router.pathname !== '/withdraw'
) {
let citizen
try {
const citizenContract = await sdk?.getContract(
Expand Down
12 changes: 7 additions & 5 deletions ui/lib/utils/hooks/useWithdrawAmount.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { BigNumber } from 'ethers'
import { useState, useEffect } from 'react'
import { readContract } from 'thirdweb'

export default function useWithdrawAmount(
votingEscrowDepositorContract: any,
Expand All @@ -12,11 +13,12 @@ export default function useWithdrawAmount(
useEffect(() => {
async function fetchWithdrawAmount() {
if (!votingEscrowDepositorContract || !userAddress) return
const theWithdrawAmount = await votingEscrowDepositorContract.call(
'availableToWithdraw',
[userAddress]
)
setWithdrawAmount(theWithdrawAmount)
const theWithdrawAmount: any = await readContract({
contract: votingEscrowDepositorContract,
method: 'availableToWithdraw' as string,
params: [userAddress],
})
setWithdrawAmount(BigNumber.from(theWithdrawAmount))
}

fetchWithdrawAmount()
Expand Down
135 changes: 90 additions & 45 deletions ui/pages/withdraw.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { Arbitrum, Sepolia } from '@thirdweb-dev/chains'
import { useAddress, useContract } from '@thirdweb-dev/react'
import ERC20 from 'const/abis/ERC20.json'
import VotingEscrow from 'const/abis/VotingEscrow.json'
import VotingEscrowDepositor from 'const/abis/VotingEscrowDepositor.json'
Expand All @@ -13,50 +11,71 @@ import { BigNumber } from 'ethers'
import { useRouter } from 'next/router'
import React, { useContext, useState, useEffect } from 'react'
import toast from 'react-hot-toast'
import { prepareContractCall, sendAndConfirmTransaction } from 'thirdweb'
import { useActiveAccount } from 'thirdweb/react'
import toastStyle from '../lib/marketplace/marketplace-utils/toastConfig'
import useWindowSize from '@/lib/team/use-window-size'
import ChainContext from '@/lib/thirdweb/chain-context'
import { getChainSlug } from '@/lib/thirdweb/chain'
import ChainContextV5 from '@/lib/thirdweb/chain-context-v5'
import { useChainDefault } from '@/lib/thirdweb/hooks/useChainDefault'
import { useVMOONEYLock } from '@/lib/tokens/ve-token'
import useContract from '@/lib/thirdweb/hooks/useContract'
import useRead from '@/lib/thirdweb/hooks/useRead'
import { approveToken } from '@/lib/tokens/approve'
import useWithdrawAmount from '@/lib/utils/hooks/useWithdrawAmount'
import Container from '../components/layout/Container'
import ContentLayout from '../components/layout/ContentLayout'
import WebsiteHead from '../components/layout/Head'
import StandardButton from '../components/layout/StandardButton'
import Asset from '@/components/dashboard/treasury/balance/Asset'
import { NoticeFooter } from '@/components/layout/NoticeFooter'
import { PrivyWeb3Button } from '@/components/privy/PrivyWeb3Button'
import NetworkSelector from '@/components/thirdweb/NetworkSelector'

export default function Withdraw() {
useChainDefault()
const userAddress = useAddress()
const router = useRouter()
const { selectedChain } = useContext(ChainContext)
const { contract: votingEscrowDepositorContract } = useContract(
VOTING_ESCROW_DEPOSITOR_ADDRESSES[selectedChain.slug],
VotingEscrowDepositor.abi
)
const { contract: vMooneyContract }: any = useContract(
VMOONEY_ADDRESSES[selectedChain?.slug],
VotingEscrow
)
const { contract: mooneyContract } = useContract(
MOONEY_ADDRESSES[selectedChain.slug],
ERC20
)
const withdrawable = useWithdrawAmount(
votingEscrowDepositorContract,
userAddress
)

const account = useActiveAccount()
const address = account?.address

const { selectedChain } = useContext(ChainContextV5)
const chainSlug = getChainSlug(selectedChain)

//Contracts
const votingEscrowDepositorContract = useContract({
address: VOTING_ESCROW_DEPOSITOR_ADDRESSES[chainSlug],
abi: VotingEscrowDepositor.abi,
chain: selectedChain,
})
const vMooneyContract = useContract({
address: VMOONEY_ADDRESSES[chainSlug],
abi: VotingEscrow,
chain: selectedChain,
})
const mooneyContract = useContract({
address: MOONEY_ADDRESSES[chainSlug],
abi: ERC20,
chain: selectedChain,
})

const withdrawable = useWithdrawAmount(votingEscrowDepositorContract, address)
const { isMobile } = useWindowSize()
const { data: VMOONEYLock, isLoading: VMOONEYLockLoading } = useVMOONEYLock(
vMooneyContract,
userAddress
)

const { data: VMOONEYLock, isLoading: VMOONEYLockLoading } = useRead({
contract: vMooneyContract,
method: 'locked' as string,
params: [address],
})

const { data: mooneyAllowance, isLoading: mooneyAllowanceLoading } = useRead({
contract: mooneyContract,
method: 'allowance' as string,
params: [address, VMOONEY_ADDRESSES[chainSlug]],
})
const [hasLock, setHasLock] = useState<boolean>()
useEffect(() => {
!VMOONEYLockLoading && setHasLock(VMOONEYLock && VMOONEYLock[0] != 0)
}, [VMOONEYLock, VMOONEYLockLoading, userAddress])
}, [VMOONEYLock, VMOONEYLockLoading, address])

const [hasMoreThanSixMonths, setHasMoreThanSixMonths] =
useState<boolean>(false)
Expand All @@ -66,23 +85,48 @@ export default function Withdraw() {
setHasMoreThanSixMonths(
VMOONEYLock &&
VMOONEYLock[1] != 0 &&
BigNumber.from(+new Date() + sixMonths).lte(VMOONEYLock[1] * 1000)
BigNumber.from(+new Date() + sixMonths).lte(
VMOONEYLock?.[1].toString() * 1000
)
)
}, [VMOONEYLock, VMOONEYLockLoading, userAddress])
}, [VMOONEYLock, VMOONEYLockLoading, address, sixMonths])

const handleWithdraw = async () => {
try {
await mooneyContract?.call('approve', [
VMOONEY_ADDRESSES[selectedChain.slug],
withdrawable.toString(),
])
await votingEscrowDepositorContract?.call('withdraw')
toast.success('Withdrawal successful!', {
style: toastStyle,
const mooneyAllowanceBigNum = BigNumber.from(mooneyAllowance)
const withdrawableBigNum = BigNumber.from(withdrawable.toString())
if (!account) throw new Error('No account found')
if (mooneyAllowanceLoading) throw new Error('Loading...')
if (
mooneyAllowanceBigNum &&
withdrawableBigNum &&
mooneyAllowanceBigNum.lt(withdrawableBigNum)
) {
const allowance = withdrawableBigNum.sub(mooneyAllowanceBigNum)
const approveReceipt = await approveToken({
account,
tokenContract: mooneyContract,
spender: VMOONEY_ADDRESSES[chainSlug],
allowance: allowance,
})
}
const withdrawTx = prepareContractCall({
contract: votingEscrowDepositorContract,
method: 'withdraw' as string,
params: [],
})
const withdrawReceipt = await sendAndConfirmTransaction({
transaction: withdrawTx,
account,
})
setTimeout(() => {
router.reload()
}, 5000)
if (withdrawReceipt) {
toast.success('Withdrawal successful!', {
style: toastStyle,
})
setTimeout(() => {
router.reload()
}, 5000)
}
} catch (error) {
console.error('Error withdrawing:', error)
toast.error('Error withdrawing. Please try again.', {
Expand Down Expand Up @@ -123,21 +167,22 @@ export default function Withdraw() {
usd=""
/>
</section>
{userAddress && hasLock && hasMoreThanSixMonths ? (
{address && hasLock && hasMoreThanSixMonths ? (
<StandardButton
className="gradient-2 rounded-full"
onClick={handleWithdraw}
disabled={Number(withdrawable) === 0}
data-tip="You dont have any vMOONEY to withdraw"
>
Withdraw Rewards
</StandardButton>
) : (
<StandardButton
<PrivyWeb3Button
v5
label={hasLock ? 'Extend Lock' : 'Lock MOONEY'}
className="gradient-2 rounded-full"
link={`/lock`}
>
{hasLock ? 'Extend Lock' : 'Lock MOONEY'}
</StandardButton>
action={() => router.push('/lock')}
/>
)}
</div>
</ContentLayout>
Expand Down
Loading