Skip to content

Commit

Permalink
Merge pull request #2680 from decentdao/erc721-vote-button
Browse files Browse the repository at this point in the history
Erc721 vote button
  • Loading branch information
adamgall authored Jan 21, 2025
2 parents 13a84f2 + fe943f0 commit 0e9dcd7
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 64 deletions.
7 changes: 1 addition & 6 deletions src/components/Proposals/ProposalActions/CastVote.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,7 @@ export function CastVote({ proposal }: { proposal: FractalProposal }) {
snapshotWeightedChoice,
} = useCastSnapshotVote(extendedSnapshotProposal);

const { canVote, canVoteLoading, hasVoted, hasVotedLoading } = useVoteContext();

// if the user is not a signer or has no delegated tokens, don't show anything
if (!canVote) {
return null;
}
const { canVoteLoading, hasVoted, hasVotedLoading } = useVoteContext();

// If user is lucky enough - he could create a proposal and proceed to vote on it
// even before the block, in which proposal was created, was mined.
Expand Down
109 changes: 53 additions & 56 deletions src/components/Proposals/ProposalVotes/context/VoteContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
useRef,
useState,
} from 'react';
import { Address, erc721Abi, getContract } from 'viem';
import { erc721Abi, getContract, Hex, toHex } from 'viem';
import { useAccount, usePublicClient } from 'wagmi';
import useSnapshotProposal from '../../../../hooks/DAO/loaders/snapshot/useSnapshotProposal';
import useUserERC721VotingTokens from '../../../../hooks/DAO/proposal/useUserERC721VotingTokens';
Expand All @@ -30,17 +30,13 @@ interface IVoteContext {
canVoteLoading: boolean;
hasVoted: boolean;
hasVotedLoading: boolean;
getCanVote: () => Promise<void>;
getHasVoted: () => void;
}

const VoteContext = createContext<IVoteContext>({
canVote: false,
canVoteLoading: false,
hasVoted: false,
hasVotedLoading: false,
getCanVote: async () => {},
getHasVoted: () => {},
});

export const useVoteContext = () => {
Expand Down Expand Up @@ -120,60 +116,63 @@ export function VoteContextProvider({
return userVotingWeight;
}, [governance, publicClient, userAccount.address]);

const getCanVote = useCallback(async () => {
setCanVoteLoading(true);
let newCanVote = false;
if (userAccount.address && publicClient) {
if (snapshotProposal) {
const votingWeightData = await loadVotingWeight();
newCanVote = votingWeightData.votingWeight >= 1;
} else if (governance.type === GovernanceType.AZORIUS_ERC20) {
const azoriusProposal = proposal as AzoriusProposal;
const ozLinearVotingContract = getContract({
abi: abis.LinearERC20Voting,
address: azoriusProposal.votingStrategy,
client: publicClient,
});
newCanVote =
(await ozLinearVotingContract.read.getVotingWeight([
userAccount.address,
Number(proposal.proposalId),
])) > 0n;
} else if (governance.type === GovernanceType.AZORIUS_ERC721) {
const votingWeight = await erc721VotingWeight();
newCanVote = votingWeight > 0n && remainingTokenIds.length > 0;
} else if (governance.type === GovernanceType.MULTISIG) {
newCanVote = !!safe?.owners.includes(userAccount.address);
} else {
newCanVote = false;
const getCanVote = useCallback(
async (remainingTokenIdsLength: number) => {
setCanVoteLoading(true);
let newCanVote = false;
if (userAccount.address && publicClient) {
if (snapshotProposal) {
const votingWeightData = await loadVotingWeight();
newCanVote = votingWeightData.votingWeight >= 1;
} else if (governance.type === GovernanceType.AZORIUS_ERC20) {
const azoriusProposal = proposal as AzoriusProposal;
const ozLinearVotingContract = getContract({
abi: abis.LinearERC20Voting,
address: azoriusProposal.votingStrategy,
client: publicClient,
});
newCanVote =
(await ozLinearVotingContract.read.getVotingWeight([
userAccount.address,
Number(proposal.proposalId),
])) > 0n;
} else if (governance.type === GovernanceType.AZORIUS_ERC721) {
const votingWeight = await erc721VotingWeight();
newCanVote = votingWeight > 0n && remainingTokenIdsLength > 0;
} else if (governance.type === GovernanceType.MULTISIG) {
newCanVote = !!safe?.owners.includes(userAccount.address);
} else {
newCanVote = false;
}
}
}

if (canVote !== newCanVote) {
setCanVote(newCanVote);
}
setCanVoteLoading(false);
}, [
userAccount.address,
publicClient,
canVote,
snapshotProposal,
governance.type,
loadVotingWeight,
remainingTokenIds.length,
safe?.owners,
proposal,
erc721VotingWeight,
]);
if (canVote !== newCanVote) {
setCanVote(newCanVote);
}
setCanVoteLoading(false);
},
[
userAccount.address,
publicClient,
canVote,
snapshotProposal,
governance.type,
loadVotingWeight,
safe?.owners,
proposal,
erc721VotingWeight,
],
);

const connectedUserRef = useRef<Address>();
const connectedUserRef = useRef<Hex>();
useEffect(() => {
const isUserRefCurrent = connectedUserRef.current === userAccount.address;
const refValue = toHex(`${userAccount.address}-${remainingTokenIds.length}`);
const isUserRefCurrent = connectedUserRef.current === refValue;
if (!isUserRefCurrent) {
connectedUserRef.current = userAccount.address;
getCanVote();
connectedUserRef.current = refValue;
getCanVote(remainingTokenIds.length);
}
}, [getCanVote, userAccount.address]);
}, [getCanVote, userAccount.address, remainingTokenIds.length]);

const connectedUserVotingWeightRef = useRef<string>();
useEffect(() => {
Expand All @@ -191,10 +190,8 @@ export function VoteContextProvider({
canVoteLoading,
hasVoted,
hasVotedLoading,
getCanVote,
getHasVoted,
};
}, [canVote, canVoteLoading, getCanVote, getHasVoted, hasVoted, hasVotedLoading]);
}, [canVote, canVoteLoading, hasVoted, hasVotedLoading]);

return <VoteContext.Provider value={memoizedValue}>{children}</VoteContext.Provider>;
}
4 changes: 2 additions & 2 deletions src/hooks/DAO/proposal/useUserERC721VotingTokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,8 @@ export default function useUserERC721VotingTokens(

const ownedTokenIds = new Set<string>();
allTokenTransferEvents.forEach(({ args: { to, from, tokenId } }) => {
if (!to || !from || !tokenId) {
throw new Error('An ERC721 event has undefiend data');
if (!to || !from || tokenId === undefined) {
throw new Error('An ERC721 event has undefined data');
}
if (to.toLowerCase() === userAddress.toLowerCase()) {
ownedTokenIds.add(tokenId.toString());
Expand Down

0 comments on commit 0e9dcd7

Please sign in to comment.