Skip to content

Commit

Permalink
Merge branch 'hotfix/v0.4.2' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
adamgall committed Jan 14, 2025
2 parents 87dcb8e + 6a604bf commit 090527a
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 68 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "decent-interface",
"version": "0.4.1",
"version": "0.4.2",
"private": true,
"dependencies": {
"@amplitude/analytics-browser": "^2.11.1",
Expand Down
74 changes: 56 additions & 18 deletions src/components/Proposals/ProposalSummary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { Box, Button, Flex, Text } from '@chakra-ui/react';
import { abis } from '@fractal-framework/fractal-contracts';
import { format } from 'date-fns';
import { formatInTimeZone } from 'date-fns-tz';
import { useEffect, useMemo, useState } from 'react';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { getContract } from 'viem';
import { erc721Abi, getContract } from 'viem';
import { useAccount, usePublicClient } from 'wagmi';
import { TOOLTIP_MAXW } from '../../constants/common';
import useBlockTimestamp from '../../hooks/utils/useBlockTimestamp';
Expand Down Expand Up @@ -60,31 +60,69 @@ export function AzoriusProposalSummary({ proposal }: { proposal: AzoriusProposal

const publicClient = usePublicClient();

const getErc721VotingWeight = useCallback(async () => {
if (!address || !azoriusGovernance.erc721Tokens || !publicClient) {
return 0n;
}
const userVotingWeight = (
await Promise.all(
azoriusGovernance.erc721Tokens.map(async ({ address: tokenAddress, votingWeight }) => {
const tokenContract = getContract({
abi: erc721Abi,
address: tokenAddress,
client: publicClient,
});
// @todo We should be checking proposal state - if it's active, we should use the latest block, otherwise we should calculate the voting weight based on the startBlock and deadlineMs
const userBalance = await tokenContract.read.balanceOf([address], {
blockNumber: startBlock,
});
return userBalance * votingWeight;
}),
)
).reduce((prev, curr) => prev + curr, 0n);
return userVotingWeight;
}, [azoriusGovernance.erc721Tokens, publicClient, address, startBlock]);

const isERC20 = type === GovernanceType.AZORIUS_ERC20;
const isERC721 = type === GovernanceType.AZORIUS_ERC721;

useEffect(() => {
async function loadProposalVotingWeight() {
if (address && publicClient) {
const strategyContract = getContract({
abi: abis.LinearERC20Voting,
address: proposal.votingStrategy,
client: publicClient,
});
if (isERC20) {
const strategyContract = getContract({
abi: abis.LinearERC20Voting,
address: proposal.votingStrategy,
client: publicClient,
});

const pastVotingWeight = await strategyContract.read.getVotingWeight([
address,
Number(proposal.proposalId),
]);
const pastVotingWeight = await strategyContract.read.getVotingWeight([
address,
Number(proposal.proposalId),
]);

setProposalVotingWeight(
formatCoin(pastVotingWeight, true, votesToken?.decimals, undefined, false),
);
setProposalVotingWeight(
formatCoin(pastVotingWeight, true, votesToken?.decimals, undefined, false),
);
} else if (isERC721) {
const votingWeight = await getErc721VotingWeight();
setProposalVotingWeight(votingWeight.toString());
}
}
}

loadProposalVotingWeight();
}, [address, proposal.proposalId, proposal.votingStrategy, publicClient, votesToken?.decimals]);

const isERC20 = type === GovernanceType.AZORIUS_ERC20;
const isERC721 = type === GovernanceType.AZORIUS_ERC721;
}, [
address,
proposal.proposalId,
proposal.votingStrategy,
publicClient,
votesToken?.decimals,
isERC20,
isERC721,
getErc721VotingWeight,
startBlock,
]);

// @todo @dev (see below):
// Caching has introduced a new "problem" edge case -- a proposal can be loaded before `votingStrategy` is loaded.
Expand Down
84 changes: 40 additions & 44 deletions src/components/Proposals/ProposalVotes/context/VoteContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import {
useCallback,
useContext,
useEffect,
useRef,
useMemo,
useState,
} from 'react';
import { erc721Abi, getContract } from 'viem';
import { BlockTag, erc721Abi, getContract } from 'viem';
import { useAccount, usePublicClient } from 'wagmi';
import useSnapshotProposal from '../../../../hooks/DAO/loaders/snapshot/useSnapshotProposal';
import useUserERC721VotingTokens from '../../../../hooks/DAO/proposal/useUserERC721VotingTokens';
Expand Down Expand Up @@ -98,27 +98,30 @@ export function VoteContextProvider({
extendedSnapshotProposal,
]);

const erc721VotingWeight = useCallback(async () => {
const account = userAccount.address;
const azoriusGovernance = governance as AzoriusGovernance;
if (!account || !azoriusGovernance.erc721Tokens || !publicClient) {
return 0n;
}
const userVotingWeight = (
await Promise.all(
azoriusGovernance.erc721Tokens.map(async ({ address, votingWeight }) => {
const tokenContract = getContract({
abi: erc721Abi,
address: address,
client: publicClient,
});
const userBalance = await tokenContract.read.balanceOf([account]);
return userBalance * votingWeight;
}),
)
).reduce((prev, curr) => prev + curr, 0n);
return userVotingWeight;
}, [governance, publicClient, userAccount.address]);
const getErc721VotingWeight = useCallback(
async (blockTag?: BlockTag) => {
const account = userAccount.address;
const azoriusGovernance = governance as AzoriusGovernance;
if (!account || !azoriusGovernance.erc721Tokens || !publicClient) {
return 0n;
}
const userVotingWeight = (
await Promise.all(
azoriusGovernance.erc721Tokens.map(async ({ address, votingWeight }) => {
const tokenContract = getContract({
abi: erc721Abi,
address: address,
client: publicClient,
});
const userBalance = await tokenContract.read.balanceOf([account], { blockTag });
return userBalance * votingWeight;
}),
)
).reduce((prev, curr) => prev + curr, 0n);
return userVotingWeight;
},
[governance, publicClient, userAccount.address],
);

const getCanVote = useCallback(async () => {
setCanVoteLoading(true);
Expand All @@ -140,15 +143,14 @@ export function VoteContextProvider({
Number(proposal.proposalId),
])) > 0n && !hasVoted;
} else if (governance.type === GovernanceType.AZORIUS_ERC721) {
const votingWeight = await erc721VotingWeight();
const votingWeight = await getErc721VotingWeight();
newCanVote = votingWeight > 0n && remainingTokenIds.length > 0;
} else if (governance.type === GovernanceType.MULTISIG) {
newCanVote = !!safe?.owners.includes(userAccount.address);
} else {
newCanVote = false;
}
}

if (canVote !== newCanVote) {
setCanVote(newCanVote);
}
Expand All @@ -164,15 +166,10 @@ export function VoteContextProvider({
remainingTokenIds.length,
safe?.owners,
proposal,
erc721VotingWeight,
getErc721VotingWeight,
]);

const initialLoadRef = useRef(false);
useEffect(() => {
// Prevent running this effect multiple times
if (initialLoadRef.current) return;
initialLoadRef.current = true;

getCanVote();
getHasVoted();
}, [getCanVote, getHasVoted]);
Expand All @@ -184,18 +181,17 @@ export function VoteContextProvider({
}
}, [proposal, proposalVotesLength]);

return (
<VoteContext.Provider
value={{
canVote,
canVoteLoading,
hasVoted,
hasVotedLoading,
getHasVoted,
getCanVote,
}}
>
{children}
</VoteContext.Provider>
const voteContextValue = useMemo(
() => ({
canVote,
canVoteLoading,
hasVoted,
hasVotedLoading,
getHasVoted,
getCanVote,
}),
[canVote, canVoteLoading, hasVoted, hasVotedLoading, getHasVoted, getCanVote],
);

return <VoteContext.Provider value={voteContextValue}>{children}</VoteContext.Provider>;
}
3 changes: 0 additions & 3 deletions src/hooks/DAO/proposal/useUserERC721VotingTokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,6 @@ export default function useUserERC721VotingTokens(

const tokenIdsSets = [...userERC721Tokens.values()];
const tokenAddressesKeys = [...userERC721Tokens.keys()];

await Promise.all(
// Same here
tokenIdsSets.map(async (tokenIdsSet, setIndex) => {
Expand Down Expand Up @@ -204,7 +203,6 @@ export default function useUserERC721VotingTokens(
);
}),
);

return {
totalVotingTokenAddresses: totalTokenAddresses,
totalVotingTokenIds: totalTokenIds,
Expand All @@ -226,7 +224,6 @@ export default function useUserERC721VotingTokens(
const loadUserERC721VotingTokens = useCallback(async () => {
const proposalIdNum = proposalId === null ? null : Number(proposalId);
const tokensInfo = await getUserERC721VotingTokens(safeAddress, proposalIdNum);

if (tokensInfo) {
setTotalVotingTokenAddresses(tokensInfo.totalVotingTokenAddresses);
setTotalVotingTokenIds(tokensInfo.totalVotingTokenIds);
Expand Down

0 comments on commit 090527a

Please sign in to comment.