From d87adfd7d564553043cc6b82c85a2ca95e3be161 Mon Sep 17 00:00:00 2001 From: Sam Keen Date: Tue, 28 Feb 2023 12:43:20 +0000 Subject: [PATCH] fix(governance): vote state update fix (#3023) --- .../components/vote-details/use-user-vote.tsx | 43 +++++++++++-------- .../vote-details/vote-buttons.spec.tsx | 14 ++++++ .../components/vote-details/vote-buttons.tsx | 7 ++- .../components/vote-details/vote-details.tsx | 7 ++- .../src/lib/voting-hooks/use-vote-submit.ts | 2 + 5 files changed, 51 insertions(+), 22 deletions(-) diff --git a/apps/token/src/routes/proposals/components/vote-details/use-user-vote.tsx b/apps/token/src/routes/proposals/components/vote-details/use-user-vote.tsx index da720b1c6..610c2cd27 100644 --- a/apps/token/src/routes/proposals/components/vote-details/use-user-vote.tsx +++ b/apps/token/src/routes/proposals/components/vote-details/use-user-vote.tsx @@ -5,6 +5,7 @@ import { VoteValue } from '@vegaprotocol/types'; import { useEffect, useState } from 'react'; import { useUserVoteQuery } from './__generated__/Vote'; import { removePaginationWrapper } from '@vegaprotocol/react-helpers'; +import type { FinalizedVote } from '@vegaprotocol/governance'; export enum VoteState { NotCast = 'NotCast', @@ -21,25 +22,14 @@ export type Vote = { party: { id: string }; }; -export type Votes = Array; - -export function getUserVote(pubkey: string, yesVotes?: Votes, noVotes?: Votes) { - const yesVote = yesVotes?.find((v) => v && v.party.id === pubkey); - const noVote = noVotes?.find((v) => v && v.party.id === pubkey); - if (yesVote) { - return yesVote; - } else if (noVote) { - return noVote; - } else { - return null; - } -} - /** * Finds the status of a users given vote in a given proposal and provides * a function to send a vote transaction to your wallet */ -export function useUserVote(proposalId: string | null | undefined) { +export function useUserVote( + proposalId: string | null | undefined, + finalizedVote?: FinalizedVote | null +) { const { pubKey } = useVegaWallet(); // eslint-disable-next-line @typescript-eslint/no-explicit-any const [timeout, setTimeoutValue] = useState(null); @@ -50,10 +40,27 @@ export function useUserVote(proposalId: string | null | undefined) { variables: { partyId: pubKey || '' }, skip: !pubKey || !proposalId, }); + const [userVote, setUserVote] = useState( + undefined + ); - const userVote = removePaginationWrapper( - data?.party?.votesConnection?.edges - ).find(({ proposalId: pId }) => proposalId === pId); + useEffect(() => { + if (finalizedVote?.vote.value) { + setUserVote(finalizedVote); + } else if (data?.party?.votesConnection?.edges) { + // This sets the vote (if any) when the user first loads the page + setUserVote( + removePaginationWrapper(data?.party?.votesConnection?.edges).find( + ({ proposalId: pId }) => proposalId === pId + ) + ); + } + }, [ + finalizedVote?.vote.value, + data?.party?.votesConnection?.edges, + finalizedVote, + proposalId, + ]); // If user vote changes update the vote state useEffect(() => { diff --git a/apps/token/src/routes/proposals/components/vote-details/vote-buttons.spec.tsx b/apps/token/src/routes/proposals/components/vote-details/vote-buttons.spec.tsx index 6cba28229..d4aa90279 100644 --- a/apps/token/src/routes/proposals/components/vote-details/vote-buttons.spec.tsx +++ b/apps/token/src/routes/proposals/components/vote-details/vote-buttons.spec.tsx @@ -22,6 +22,8 @@ describe('Vote buttons', () => { minVoterBalance={null} spamProtectionMinTokens={null} currentStakeAvailable={new BigNumber(1)} + dialog={() =>
Blah
} + submit={() => Promise.resolve()} /> @@ -43,6 +45,8 @@ describe('Vote buttons', () => { minVoterBalance={null} spamProtectionMinTokens={null} currentStakeAvailable={new BigNumber(1)} + dialog={() =>
Blah
} + submit={() => Promise.resolve()} /> @@ -75,6 +79,8 @@ describe('Vote buttons', () => { minVoterBalance={null} spamProtectionMinTokens={null} currentStakeAvailable={new BigNumber(1)} + dialog={() =>
Blah
} + submit={() => Promise.resolve()} /> @@ -97,6 +103,8 @@ describe('Vote buttons', () => { minVoterBalance={null} spamProtectionMinTokens={null} currentStakeAvailable={new BigNumber(0)} + dialog={() =>
Blah
} + submit={() => Promise.resolve()} /> @@ -120,6 +128,8 @@ describe('Vote buttons', () => { minVoterBalance="2000000000000000000" spamProtectionMinTokens="1000000000000000000" currentStakeAvailable={new BigNumber(1)} + dialog={() =>
Blah
} + submit={() => Promise.resolve()} /> @@ -145,6 +155,8 @@ describe('Vote buttons', () => { minVoterBalance="2000000000000000000" spamProtectionMinTokens="1000000000000000000" currentStakeAvailable={new BigNumber(10)} + dialog={() =>
Blah
} + submit={() => Promise.resolve()} /> @@ -167,6 +179,8 @@ describe('Vote buttons', () => { minVoterBalance="2000000000000000000" spamProtectionMinTokens="1000000000000000000" currentStakeAvailable={new BigNumber(10)} + dialog={() =>
Blah
} + submit={() => Promise.resolve()} /> diff --git a/apps/token/src/routes/proposals/components/vote-details/vote-buttons.tsx b/apps/token/src/routes/proposals/components/vote-details/vote-buttons.tsx index 9ff2554d8..bf6ec86ec 100644 --- a/apps/token/src/routes/proposals/components/vote-details/vote-buttons.tsx +++ b/apps/token/src/routes/proposals/components/vote-details/vote-buttons.tsx @@ -4,7 +4,6 @@ import { useTranslation } from 'react-i18next'; import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet'; import { AsyncRenderer, Button, ButtonLink } from '@vegaprotocol/ui-toolkit'; import { addDecimal, toBigNum } from '@vegaprotocol/react-helpers'; -import { useVoteSubmit } from '@vegaprotocol/governance'; import { ProposalState, VoteValue } from '@vegaprotocol/types'; import { AppStateActionType, @@ -16,6 +15,7 @@ import { VoteState } from './use-user-vote'; import { ProposalMinRequirements, ProposalUserAction } from '../shared'; import { VoteTransactionDialog } from './vote-transaction-dialog'; import { useVoteButtonsQuery } from './__generated__/Stake'; +import type { DialogProps } from '@vegaprotocol/wallet'; interface VoteButtonsContainerProps { voteState: VoteState | null; @@ -24,6 +24,8 @@ interface VoteButtonsContainerProps { proposalState: ProposalState; minVoterBalance: string | null; spamProtectionMinTokens: string | null; + submit: (voteValue: VoteValue, proposalId: string | null) => Promise; + dialog: (props: DialogProps) => JSX.Element; className?: string; } @@ -62,11 +64,12 @@ export const VoteButtons = ({ currentStakeAvailable, minVoterBalance, spamProtectionMinTokens, + submit, + dialog: Dialog, }: VoteButtonsProps) => { const { t } = useTranslation(); const { appDispatch } = useAppState(); const { pubKey } = useVegaWallet(); - const { submit, Dialog } = useVoteSubmit(); const { openVegaWalletDialog } = useVegaWalletDialogStore((store) => ({ openVegaWalletDialog: store.openVegaWalletDialog, })); diff --git a/apps/token/src/routes/proposals/components/vote-details/vote-details.tsx b/apps/token/src/routes/proposals/components/vote-details/vote-details.tsx index 9d3a79bc2..fa307b8eb 100644 --- a/apps/token/src/routes/proposals/components/vote-details/vote-details.tsx +++ b/apps/token/src/routes/proposals/components/vote-details/vote-details.tsx @@ -2,7 +2,7 @@ import { useTranslation } from 'react-i18next'; import { formatDistanceToNow } from 'date-fns'; import { useVegaWallet } from '@vegaprotocol/wallet'; import { ProposalState } from '@vegaprotocol/types'; -import { VoteProgress } from '@vegaprotocol/governance'; +import { useVoteSubmit, VoteProgress } from '@vegaprotocol/governance'; import { formatNumber } from '../../../../lib/format-number'; import { ConnectToVega } from '../../../../components/connect-to-vega'; import { useVoteInformation } from '../../hooks'; @@ -44,7 +44,8 @@ export const VoteDetails = ({ } = useVoteInformation({ proposal }); const { t } = useTranslation(); - const { voteState, voteDatetime } = useUserVote(proposal?.id); + const { submit, Dialog, finalizedVote } = useVoteSubmit(); + const { voteState, voteDatetime } = useUserVote(proposal?.id, finalizedVote); const defaultDecimals = 2; const daysLeft = t('daysLeft', { daysLeft: formatDistanceToNow(new Date(proposal?.terms.closingDatetime)), @@ -188,6 +189,8 @@ export const VoteDetails = ({ minVoterBalance={minVoterBalance} spamProtectionMinTokens={spamProtectionMinTokens} className="flex" + submit={submit} + dialog={Dialog} /> )} diff --git a/libs/governance/src/lib/voting-hooks/use-vote-submit.ts b/libs/governance/src/lib/voting-hooks/use-vote-submit.ts index a900d825d..08ccfa89f 100644 --- a/libs/governance/src/lib/voting-hooks/use-vote-submit.ts +++ b/libs/governance/src/lib/voting-hooks/use-vote-submit.ts @@ -5,6 +5,8 @@ import { useVoteEvent } from './use-vote-event'; import type { VoteValue } from '@vegaprotocol/types'; import type { VoteEventFieldsFragment } from './__generated__/VoteSubsciption'; +export type FinalizedVote = VoteEventFieldsFragment; + export const useVoteSubmit = () => { const { pubKey } = useVegaWallet(); const { send, transaction, setComplete, Dialog } = useVegaTransaction();