-
Notifications
You must be signed in to change notification settings - Fork 7
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
Erc721 vote button #2680
Erc721 vote button #2680
Conversation
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; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cleanup 1.
getCanVote: () => Promise<void>; | ||
getHasVoted: () => void; | ||
} | ||
|
||
const VoteContext = createContext<IVoteContext>({ | ||
canVote: false, | ||
canVoteLoading: false, | ||
hasVoted: false, | ||
hasVotedLoading: false, | ||
getCanVote: async () => {}, | ||
getHasVoted: () => {}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cleanup 2.
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]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bugfix 2.
getCanVote, | ||
getHasVoted, | ||
}; | ||
}, [canVote, canVoteLoading, getCanVote, getHasVoted, hasVoted, hasVotedLoading]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cleanup 2
if (!to || !from || tokenId === undefined) { | ||
throw new Error('An ERC721 event has undefined data'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bugfix 1
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]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the important part here. We need to make sure getCanVote
is ran every time the remainingTokenIds.length
changes, which happens asynchronously and definitely is updated after the user's address ref was first being set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this need to hotfix to prod? |
Oh yeah good point. Let me confirm that it's safe to rebase and make it happen |
…user reference handling - Modified `getCanVote` function to accept `remainingTokenIdsLength` as a parameter for better clarity and efficiency. - Updated user reference management to use a hex representation of the user's address combined with the length of remaining token IDs. - Ensured that the voting eligibility logic remains intact while enhancing readability and maintainability.
5af9c96
to
fe943f0
Compare
Deploying decent-interface with Cloudflare Pages
|
@Da-Colon @DarksightKellar just to confirm, have you both successfully reproduced the bug and then confirmed that this PR fixes it? Just considering this is a hotfix into prod, I want to be sure every "approval" includes QA testing. See the "Testing" section in the top comment. |
Created ticket |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested complete flow with deployment, created proposal and voted successfully.
@johnqh specifically, did you load the app fresh, with the proposal already created? Like, if you just refresh the page/app, does the proposal still give you the Vote button? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested on Contango /proposals/5?dao=eth:0xB14AC30AA97057e2A934c47BDc45171335B91Bd8 with the wallet that has NFT for voting - works good.
One caveat, but I think I've seen this some time ago - see screenshot. Right after voting the voting option appears as empty box but after refresh it loads correctly. I'll add a ticket for that in Linear
Closes https://linear.app/decent-labs/issue/ENG-136/contango-couldnt-vote
Currently, users are unable to vote on ERC 721 Token proposals. The "Vote" button does not appear when loading the app with a wallet connected that DOES have voting power on a proposal that already exists is and open for voting.
This PR addresses that bug.
Fixed two bugs, and do some cleanup.
Bugs fixed:
tokenId
of an owned NFT by the connected address is0
, that was returning truthy in a place where we actually want to check if it'sundefined
.a. Modified getCanVote function to accept remainingTokenIdsLength as a parameter for better clarity and efficiency.
b. Updated user reference management to use a hex representation of the user's address combined with the length of remaining token IDs.
c. Ensured that the voting eligibility logic remains intact while enhancing readability and maintainability.
Cleanup:
Testing:
0xda38c543596b7E1b79ad0aC2C7797ADb914Ea3C5
eth:0xB14AC30AA97057e2A934c47BDc45171335B91Bd8
a. Before this PR: no Vote button
b. In this PR: Vote button