Skip to content

Commit

Permalink
We will now have the Execute button. (#108)
Browse files Browse the repository at this point in the history
  • Loading branch information
Freshenext authored Aug 13, 2024
1 parent dfb95d7 commit 3a44809
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 1 deletion.
71 changes: 71 additions & 0 deletions src/lib/useExecuteProposal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { GovernorAddress } from '@/lib/contracts'
import { GovernorAbi } from '@/lib/abis/Governor'
import { useReadContract, useWaitForTransactionReceipt, useWriteContract } from 'wagmi'

const DAO_DEFAULT_PARAMS = {
abi: GovernorAbi,
address: GovernorAddress,
}

const getCurrentTimeInMsAsBigInt = () => BigInt(Math.floor(Date.now() / 1000))

const getBigIntTimestampAsHuman = (proposalEta?: bigint) => {
if (!proposalEta) return ''
const proposalEtaMs = Number(proposalEta) * 1000
const proposalDate = new Date(proposalEtaMs)
return proposalDate.toLocaleString()
}

export const useExecuteProposal = (proposalId: string) => {
const { data: proposalEta } = useReadContract({
...DAO_DEFAULT_PARAMS,
functionName: 'proposalEta',
args: [BigInt(proposalId)],
query: {
refetchInterval: 5000,
},
})
const currentTime = getCurrentTimeInMsAsBigInt()

const { writeContractAsync, data } = useWriteContract()
const { isLoading: isTxHashFromExecuteLoading } = useWaitForTransactionReceipt({ hash: data })

const onExecuteProposal = async () => {
if (proposalEta && getCurrentTimeInMsAsBigInt() >= proposalEta) {
return writeContractAsync({
// abi: [
// {
// inputs: [
// {
// internalType: 'uint256',
// name: 'proposalId',
// type: 'uint256',
// },
// ],
// name: 'execute',
// outputs: [],
// stateMutability: 'payable',
// type: 'function',
// },
// ],
...DAO_DEFAULT_PARAMS,
functionName: 'execute',
args: [BigInt(proposalId)],
}).catch(error => {
// @TODO when there is an error, use decodeErrorResult to get the error
// What is recommended is to iterate over each ABI and then see if any return result
console.log(42, error)
throw new Error(error)
})
}
}

const proposalEtaHumanDate = getBigIntTimestampAsHuman(proposalEta)
return {
onExecuteProposal,
canProposalBeExecuted: proposalEta && currentTime >= proposalEta,
proposalEta,
proposalEtaHumanDate,
isTxHashFromExecuteLoading,
}
}
31 changes: 30 additions & 1 deletion src/pages/proposals/[id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { useAccount } from 'wagmi'
import { Vote, VoteProposalModal } from '../../components/Modal/VoteProposalModal'
import { VoteSubmittedModal } from '../../components/Modal/VoteSubmittedModal'
import { useVotingPowerAtSnapshot } from '@/app/proposals/hooks/useVotingPowerAtSnapshot'
import { useExecuteProposal } from '@/lib/useExecuteProposal'

export default function ProposalView() {
const {
Expand Down Expand Up @@ -61,7 +62,7 @@ const PageWithProposal = (proposal: PageWithProposal) => {

const { votingPowerAtSnapshot, doesUserHasEnoughThreshold } = useVotingPowerAtSnapshot(snapshot as bigint)

const { threshold, canCreateProposal } = useVotingPower()
const { threshold } = useVotingPower()
const {
onVote,
isProposalActive,
Expand All @@ -71,6 +72,9 @@ const PageWithProposal = (proposal: PageWithProposal) => {
onQueueProposal,
} = useVoteOnProposal(proposalId)

const { onExecuteProposal, canProposalBeExecuted, proposalEtaHumanDate, isTxHashFromExecuteLoading } =
useExecuteProposal(proposalId)

const cannotCastVote = !isProposalActive || didUserVoteAlready || !doesUserHasEnoughThreshold

const handleVoting = async (vote: Vote) => {
Expand Down Expand Up @@ -124,6 +128,31 @@ const PageWithProposal = (proposal: PageWithProposal) => {
Put on Queue
</Button>
)}
{proposalStateHuman === 'Queued' && (
<Popover
size="small"
trigger="hover"
content={
!canProposalBeExecuted ? (
<p className="text-[12px] font-bold mb-1">
The proposal is not ready to be executed yet. It should be ready on:{' '}
{proposalEtaHumanDate}
</p>
) : (
<p className="text-[12px] font-bold mb-1">The proposal can be executed.</p>
)
}
>
<Button
onClick={onExecuteProposal}
className="mt-2"
disabled={!canProposalBeExecuted || isTxHashFromExecuteLoading}
>
Execute
</Button>
</Popover>
)}
{isTxHashFromExecuteLoading && <p>Pending transaction confirmation to complete execution.</p>}
{votingModal.isModalOpened && address && (
<VoteProposalModal
onSubmit={handleVoting}
Expand Down

0 comments on commit 3a44809

Please sign in to comment.