fix: voting during waiting for node vote (#1748)
* fix: voting during waiting for node vote allow voting during waiting for node vote, bug fix for vote cancelled, show correct status * fix: adjust vote information to be more correct * test: begin adding tests for current proposal status * chore: clean up render logic, add more tests for current proposal status * chore: add tests for failed proposals * test: add final tests for vote information * test: fix rebase issues
This commit is contained in:
parent
5e75e0ee21
commit
1bc41c8a9a
@ -505,7 +505,7 @@
|
|||||||
"voteFailedReason": "Vote closed. Failed due to: ",
|
"voteFailedReason": "Vote closed. Failed due to: ",
|
||||||
"Passed": "Passed",
|
"Passed": "Passed",
|
||||||
"votePassed": "Vote passed.",
|
"votePassed": "Vote passed.",
|
||||||
"subjectToFurtherActions": "Vote passed {{daysAgo}} subject to further actions.",
|
"WaitingForNodeVote": "Waiting for nodes to validate asset. ",
|
||||||
"transactionHashPrompt": "Transaction hash will appear here once the transaction is approved in your Ethereum wallet",
|
"transactionHashPrompt": "Transaction hash will appear here once the transaction is approved in your Ethereum wallet",
|
||||||
"newWalletVersionAvailable": "A new Vega wallet is available 🎉. ",
|
"newWalletVersionAvailable": "A new Vega wallet is available 🎉. ",
|
||||||
"downloadNewWallet": "Download {{newVersionAvailable}}",
|
"downloadNewWallet": "Download {{newVersionAvailable}}",
|
||||||
@ -564,7 +564,7 @@
|
|||||||
"yesPercentage": "Yes percentage",
|
"yesPercentage": "Yes percentage",
|
||||||
"noPercentage": "No percentage",
|
"noPercentage": "No percentage",
|
||||||
"proposalTerms": "Proposal terms",
|
"proposalTerms": "Proposal terms",
|
||||||
"currentlySetTo": "Currently set to ",
|
"currentlySetTo": "Vote currently set to ",
|
||||||
"rankingScore": "Ranking score",
|
"rankingScore": "Ranking score",
|
||||||
"stakeScore": "Stake score",
|
"stakeScore": "Stake score",
|
||||||
"performanceScore": "Performance",
|
"performanceScore": "Performance",
|
||||||
@ -691,5 +691,7 @@
|
|||||||
"MoreAssetsInfo": "To see Explorer data on existing assets visit",
|
"MoreAssetsInfo": "To see Explorer data on existing assets visit",
|
||||||
"ProposalNotFound": "Proposal not found",
|
"ProposalNotFound": "Proposal not found",
|
||||||
"ProposalNotFoundDetails": "The proposal you are looking for is not here, it may have been enacted before the last chain restore. You could check the Vega forums/discord instead for information about it.",
|
"ProposalNotFoundDetails": "The proposal you are looking for is not here, it may have been enacted before the last chain restore. You could check the Vega forums/discord instead for information about it.",
|
||||||
"FreeformProposal": "Freeform proposal"
|
"FreeformProposal": "Freeform proposal",
|
||||||
|
"unknownReason": "unknown reason",
|
||||||
|
"votingEnded": "Voting has ended."
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,298 @@
|
|||||||
|
import type { MockedResponse } from '@apollo/client/testing';
|
||||||
|
import { MockedProvider } from '@apollo/client/testing';
|
||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import { NETWORK_PARAMETERS_QUERY } from '@vegaprotocol/react-helpers';
|
||||||
|
import { ProposalRejectionReason, ProposalState } from '@vegaprotocol/types';
|
||||||
|
import type { NetworkParamsQuery } from '@vegaprotocol/web3';
|
||||||
|
import { AppStateProvider } from '../../../../contexts/app-state/app-state-provider';
|
||||||
|
import { generateProposal } from '../../test-helpers/generate-proposals';
|
||||||
|
import type { ProposalFields } from '../../__generated__/ProposalFields';
|
||||||
|
import { CurrentProposalStatus } from './current-proposal-status';
|
||||||
|
|
||||||
|
const networkParamsQueryMock: MockedResponse<NetworkParamsQuery> = {
|
||||||
|
request: {
|
||||||
|
query: NETWORK_PARAMETERS_QUERY,
|
||||||
|
},
|
||||||
|
result: {
|
||||||
|
data: {
|
||||||
|
networkParameters: [
|
||||||
|
{
|
||||||
|
__typename: 'NetworkParameter',
|
||||||
|
key: 'governance.proposal.updateNetParam.requiredMajority',
|
||||||
|
value: '0.00000001',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
__typename: 'NetworkParameter',
|
||||||
|
key: 'governance.proposal.updateNetParam.requiredParticipation',
|
||||||
|
value: '0.000000001',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderComponent = ({ proposal }: { proposal: ProposalFields }) => {
|
||||||
|
render(
|
||||||
|
<AppStateProvider>
|
||||||
|
<MockedProvider mocks={[networkParamsQueryMock]}>
|
||||||
|
<CurrentProposalStatus proposal={proposal} />
|
||||||
|
</MockedProvider>
|
||||||
|
</AppStateProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
jest.setSystemTime(60 * 60 * 1000);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.useRealTimers();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Proposal open - renders will fail state if the proposal will fail', async () => {
|
||||||
|
const proposal = generateProposal();
|
||||||
|
const failedProposal: ProposalFields = {
|
||||||
|
...proposal,
|
||||||
|
votes: {
|
||||||
|
__typename: 'ProposalVotes',
|
||||||
|
yes: {
|
||||||
|
__typename: 'ProposalVoteSide',
|
||||||
|
totalNumber: '0',
|
||||||
|
totalTokens: '0',
|
||||||
|
votes: null,
|
||||||
|
},
|
||||||
|
no: {
|
||||||
|
__typename: 'ProposalVoteSide',
|
||||||
|
totalNumber: '0',
|
||||||
|
totalTokens: '0',
|
||||||
|
votes: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
renderComponent({ proposal: failedProposal });
|
||||||
|
expect(await screen.findByText('Vote currently set to')).toBeInTheDocument();
|
||||||
|
expect(await screen.findByText('fail')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Proposal open - renders will pass state if the proposal will pass', async () => {
|
||||||
|
const proposal = generateProposal();
|
||||||
|
|
||||||
|
renderComponent({ proposal });
|
||||||
|
expect(await screen.findByText('Vote currently set to')).toBeInTheDocument();
|
||||||
|
expect(await screen.findByText('pass')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Proposal enacted - renders vote passed and time since enactment', async () => {
|
||||||
|
const proposal = generateProposal();
|
||||||
|
|
||||||
|
renderComponent({
|
||||||
|
proposal: {
|
||||||
|
...proposal,
|
||||||
|
state: ProposalState.STATE_ENACTED,
|
||||||
|
terms: {
|
||||||
|
...proposal.terms,
|
||||||
|
enactmentDatetime: new Date(0).toISOString(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(await screen.findByText('Vote passed.')).toBeInTheDocument();
|
||||||
|
expect(await screen.findByText('about 1 hour ago')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Proposal passed - renders vote passed and time since vote closed', async () => {
|
||||||
|
const proposal = generateProposal();
|
||||||
|
|
||||||
|
renderComponent({
|
||||||
|
proposal: {
|
||||||
|
...proposal,
|
||||||
|
state: ProposalState.STATE_PASSED,
|
||||||
|
terms: {
|
||||||
|
...proposal.terms,
|
||||||
|
closingDatetime: new Date(0).toISOString(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(await screen.findByText('Vote passed.')).toBeInTheDocument();
|
||||||
|
expect(await screen.findByText('about 1 hour ago')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Proposal waiting for node vote - will pass - renders if the vote will pass and status', async () => {
|
||||||
|
const proposal = generateProposal();
|
||||||
|
const failedProposal: ProposalFields = {
|
||||||
|
...proposal,
|
||||||
|
state: ProposalState.STATE_WAITING_FOR_NODE_VOTE,
|
||||||
|
votes: {
|
||||||
|
__typename: 'ProposalVotes',
|
||||||
|
yes: {
|
||||||
|
__typename: 'ProposalVoteSide',
|
||||||
|
totalNumber: '0',
|
||||||
|
totalTokens: '0',
|
||||||
|
votes: null,
|
||||||
|
},
|
||||||
|
no: {
|
||||||
|
__typename: 'ProposalVoteSide',
|
||||||
|
totalNumber: '0',
|
||||||
|
totalTokens: '0',
|
||||||
|
votes: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
renderComponent({ proposal: failedProposal });
|
||||||
|
expect(
|
||||||
|
await screen.findByText('Waiting for nodes to validate asset.')
|
||||||
|
).toBeInTheDocument();
|
||||||
|
expect(await screen.findByText('Vote currently set to')).toBeInTheDocument();
|
||||||
|
expect(await screen.findByText('fail')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Proposal waiting for node vote - will fail - renders if the vote will pass and status', async () => {
|
||||||
|
const proposal = generateProposal();
|
||||||
|
|
||||||
|
renderComponent({
|
||||||
|
proposal: {
|
||||||
|
...proposal,
|
||||||
|
state: ProposalState.STATE_WAITING_FOR_NODE_VOTE,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(
|
||||||
|
await screen.findByText('Waiting for nodes to validate asset.')
|
||||||
|
).toBeInTheDocument();
|
||||||
|
expect(await screen.findByText('Vote currently set to')).toBeInTheDocument();
|
||||||
|
expect(await screen.findByText('pass')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Proposal failed - renders vote failed reason and vote closed ago', async () => {
|
||||||
|
const proposal = generateProposal();
|
||||||
|
|
||||||
|
renderComponent({
|
||||||
|
proposal: {
|
||||||
|
...proposal,
|
||||||
|
state: ProposalState.STATE_FAILED,
|
||||||
|
errorDetails: 'foo',
|
||||||
|
terms: {
|
||||||
|
...proposal.terms,
|
||||||
|
closingDatetime: new Date(0).toISOString(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(
|
||||||
|
await screen.findByText('Vote closed. Failed due to:')
|
||||||
|
).toBeInTheDocument();
|
||||||
|
expect(await screen.findByText('foo')).toBeInTheDocument();
|
||||||
|
expect(await screen.findByText('about 1 hour ago')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Proposal failed - renders rejection reason there are no error details', async () => {
|
||||||
|
const proposal = generateProposal();
|
||||||
|
|
||||||
|
renderComponent({
|
||||||
|
proposal: {
|
||||||
|
...proposal,
|
||||||
|
state: ProposalState.STATE_FAILED,
|
||||||
|
rejectionReason:
|
||||||
|
ProposalRejectionReason.PROPOSAL_ERROR_CLOSE_TIME_TOO_LATE,
|
||||||
|
terms: {
|
||||||
|
...proposal.terms,
|
||||||
|
closingDatetime: new Date(0).toISOString(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(
|
||||||
|
await screen.findByText('Vote closed. Failed due to:')
|
||||||
|
).toBeInTheDocument();
|
||||||
|
expect(
|
||||||
|
await screen.findByText('PROPOSAL_ERROR_CLOSE_TIME_TOO_LATE')
|
||||||
|
).toBeInTheDocument();
|
||||||
|
expect(await screen.findByText('about 1 hour ago')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Proposal failed - renders unknown reason if there are no error details or rejection reason', async () => {
|
||||||
|
const proposal = generateProposal();
|
||||||
|
|
||||||
|
renderComponent({
|
||||||
|
proposal: {
|
||||||
|
...proposal,
|
||||||
|
state: ProposalState.STATE_FAILED,
|
||||||
|
terms: {
|
||||||
|
...proposal.terms,
|
||||||
|
closingDatetime: new Date(0).toISOString(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(
|
||||||
|
await screen.findByText('Vote closed. Failed due to:')
|
||||||
|
).toBeInTheDocument();
|
||||||
|
expect(await screen.findByText('unknown reason')).toBeInTheDocument();
|
||||||
|
expect(await screen.findByText('about 1 hour ago')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Proposal failed - renders participation not met if participation is not met', async () => {
|
||||||
|
const proposal = generateProposal();
|
||||||
|
|
||||||
|
renderComponent({
|
||||||
|
proposal: {
|
||||||
|
...proposal,
|
||||||
|
state: ProposalState.STATE_FAILED,
|
||||||
|
terms: {
|
||||||
|
...proposal.terms,
|
||||||
|
closingDatetime: new Date(0).toISOString(),
|
||||||
|
},
|
||||||
|
votes: {
|
||||||
|
__typename: 'ProposalVotes',
|
||||||
|
yes: {
|
||||||
|
__typename: 'ProposalVoteSide',
|
||||||
|
totalNumber: '0',
|
||||||
|
totalTokens: '0',
|
||||||
|
votes: null,
|
||||||
|
},
|
||||||
|
no: {
|
||||||
|
__typename: 'ProposalVoteSide',
|
||||||
|
totalNumber: '0',
|
||||||
|
totalTokens: '0',
|
||||||
|
votes: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(
|
||||||
|
await screen.findByText('Vote closed. Failed due to:')
|
||||||
|
).toBeInTheDocument();
|
||||||
|
expect(await screen.findByText('Participation not met')).toBeInTheDocument();
|
||||||
|
expect(await screen.findByText('about 1 hour ago')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Proposal failed - renders majority not met if majority is not met', async () => {
|
||||||
|
const proposal = generateProposal();
|
||||||
|
|
||||||
|
renderComponent({
|
||||||
|
proposal: {
|
||||||
|
...proposal,
|
||||||
|
state: ProposalState.STATE_FAILED,
|
||||||
|
terms: {
|
||||||
|
...proposal.terms,
|
||||||
|
closingDatetime: new Date(0).toISOString(),
|
||||||
|
},
|
||||||
|
votes: {
|
||||||
|
__typename: 'ProposalVotes',
|
||||||
|
yes: {
|
||||||
|
__typename: 'ProposalVoteSide',
|
||||||
|
totalNumber: '0',
|
||||||
|
totalTokens: '0',
|
||||||
|
votes: null,
|
||||||
|
},
|
||||||
|
no: {
|
||||||
|
__typename: 'ProposalVoteSide',
|
||||||
|
totalNumber: '1',
|
||||||
|
totalTokens: '25242474195500835440000',
|
||||||
|
votes: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(
|
||||||
|
await screen.findByText('Vote closed. Failed due to:')
|
||||||
|
).toBeInTheDocument();
|
||||||
|
expect(await screen.findByText('Majority not met')).toBeInTheDocument();
|
||||||
|
expect(await screen.findByText('about 1 hour ago')).toBeInTheDocument();
|
||||||
|
});
|
@ -1,4 +1,4 @@
|
|||||||
import React from 'react';
|
import type { ReactNode } from 'react';
|
||||||
import { formatDistanceToNow } from 'date-fns';
|
import { formatDistanceToNow } from 'date-fns';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
@ -6,14 +6,39 @@ import { ProposalState } from '@vegaprotocol/types';
|
|||||||
import { useVoteInformation } from '../../hooks';
|
import { useVoteInformation } from '../../hooks';
|
||||||
import type { ProposalFields } from '../../__generated__/ProposalFields';
|
import type { ProposalFields } from '../../__generated__/ProposalFields';
|
||||||
|
|
||||||
export const StatusPass = ({ children }: { children: React.ReactNode }) => (
|
export const StatusPass = ({ children }: { children: ReactNode }) => (
|
||||||
<span className="text-vega-green">{children}</span>
|
<span className="text-vega-green">{children}</span>
|
||||||
);
|
);
|
||||||
|
|
||||||
export const StatusFail = ({ children }: { children: React.ReactNode }) => (
|
export const StatusFail = ({ children }: { children: ReactNode }) => (
|
||||||
<span className="text-danger">{children}</span>
|
<span className="text-danger">{children}</span>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const WillPass = ({
|
||||||
|
willPass,
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
willPass: boolean;
|
||||||
|
children?: ReactNode;
|
||||||
|
}) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
if (willPass) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{children}
|
||||||
|
<StatusPass>{t('pass')}</StatusPass>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{children}
|
||||||
|
<StatusFail>{t('fail')}</StatusFail>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const CurrentProposalStatus = ({
|
export const CurrentProposalStatus = ({
|
||||||
proposal,
|
proposal,
|
||||||
}: {
|
}: {
|
||||||
@ -36,21 +61,7 @@ export const CurrentProposalStatus = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (proposal.state === ProposalState.STATE_OPEN) {
|
if (proposal.state === ProposalState.STATE_OPEN) {
|
||||||
if (willPass) {
|
return <WillPass willPass={willPass}>{t('currentlySetTo')}</WillPass>;
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{t('currentlySetTo')}
|
|
||||||
<StatusPass>{t('pass')}</StatusPass>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{t('currentlySetTo')}
|
|
||||||
<StatusFail>{t('fail')}</StatusFail>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@ -81,7 +92,11 @@ export const CurrentProposalStatus = ({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<span>{t('voteFailedReason')}</span>
|
<span>{t('voteFailedReason')}</span>
|
||||||
<StatusFail>{proposal.state}</StatusFail>
|
<StatusFail>
|
||||||
|
{proposal.errorDetails ||
|
||||||
|
proposal.rejectionReason ||
|
||||||
|
t('unknownReason')}
|
||||||
|
</StatusFail>
|
||||||
<span> {daysClosedAgo}</span>
|
<span> {daysClosedAgo}</span>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@ -106,7 +121,10 @@ export const CurrentProposalStatus = ({
|
|||||||
|
|
||||||
if (proposal.state === ProposalState.STATE_WAITING_FOR_NODE_VOTE) {
|
if (proposal.state === ProposalState.STATE_WAITING_FOR_NODE_VOTE) {
|
||||||
return (
|
return (
|
||||||
<span>{t('subjectToFurtherActions', { daysAgo: daysClosedAgo })}</span>
|
<WillPass willPass={willPass}>
|
||||||
|
<span>{t('WaitingForNodeVote')}</span>{' '}
|
||||||
|
<span>{t('currentlySetTo')}</span>
|
||||||
|
</WillPass>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,8 @@ import type { Proposals_proposalsConnection_edges_node as ProposalNode } from '.
|
|||||||
const renderComponent = (
|
const renderComponent = (
|
||||||
proposal: ProposalNode,
|
proposal: ProposalNode,
|
||||||
mock = networkParamsQueryMock
|
mock = networkParamsQueryMock
|
||||||
) => (
|
) =>
|
||||||
|
render(
|
||||||
<Router>
|
<Router>
|
||||||
<MockedProvider mocks={[mock]}>
|
<MockedProvider mocks={[mock]}>
|
||||||
<AppStateProvider>
|
<AppStateProvider>
|
||||||
@ -41,7 +42,7 @@ const renderComponent = (
|
|||||||
</AppStateProvider>
|
</AppStateProvider>
|
||||||
</MockedProvider>
|
</MockedProvider>
|
||||||
</Router>
|
</Router>
|
||||||
);
|
);
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
@ -53,7 +54,6 @@ afterAll(() => {
|
|||||||
|
|
||||||
describe('Proposals list item details', () => {
|
describe('Proposals list item details', () => {
|
||||||
it('Renders proposal state: Enacted', () => {
|
it('Renders proposal state: Enacted', () => {
|
||||||
render(
|
|
||||||
renderComponent(
|
renderComponent(
|
||||||
generateProposal({
|
generateProposal({
|
||||||
state: ProposalState.STATE_ENACTED,
|
state: ProposalState.STATE_ENACTED,
|
||||||
@ -61,7 +61,6 @@ describe('Proposals list item details', () => {
|
|||||||
enactmentDatetime: lastWeek.toString(),
|
enactmentDatetime: lastWeek.toString(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
)
|
|
||||||
);
|
);
|
||||||
expect(screen.getByTestId('proposal-status')).toHaveTextContent('Enacted');
|
expect(screen.getByTestId('proposal-status')).toHaveTextContent('Enacted');
|
||||||
expect(screen.getByTestId('vote-details')).toHaveTextContent(
|
expect(screen.getByTestId('vote-details')).toHaveTextContent(
|
||||||
@ -70,7 +69,6 @@ describe('Proposals list item details', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Renders proposal state: Passed', () => {
|
it('Renders proposal state: Passed', () => {
|
||||||
render(
|
|
||||||
renderComponent(
|
renderComponent(
|
||||||
generateProposal({
|
generateProposal({
|
||||||
state: ProposalState.STATE_PASSED,
|
state: ProposalState.STATE_PASSED,
|
||||||
@ -79,7 +77,6 @@ describe('Proposals list item details', () => {
|
|||||||
enactmentDatetime: nextWeek.toString(),
|
enactmentDatetime: nextWeek.toString(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
)
|
|
||||||
);
|
);
|
||||||
expect(screen.getByTestId('proposal-status')).toHaveTextContent('Passed');
|
expect(screen.getByTestId('proposal-status')).toHaveTextContent('Passed');
|
||||||
expect(screen.getByTestId('vote-details')).toHaveTextContent(
|
expect(screen.getByTestId('vote-details')).toHaveTextContent(
|
||||||
@ -88,7 +85,6 @@ describe('Proposals list item details', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Renders proposal state: Waiting for node vote', () => {
|
it('Renders proposal state: Waiting for node vote', () => {
|
||||||
render(
|
|
||||||
renderComponent(
|
renderComponent(
|
||||||
generateProposal({
|
generateProposal({
|
||||||
state: ProposalState.STATE_WAITING_FOR_NODE_VOTE,
|
state: ProposalState.STATE_WAITING_FOR_NODE_VOTE,
|
||||||
@ -96,7 +92,6 @@ describe('Proposals list item details', () => {
|
|||||||
enactmentDatetime: nextWeek.toString(),
|
enactmentDatetime: nextWeek.toString(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
)
|
|
||||||
);
|
);
|
||||||
expect(screen.getByTestId('proposal-status')).toHaveTextContent(
|
expect(screen.getByTestId('proposal-status')).toHaveTextContent(
|
||||||
'Waiting for node vote'
|
'Waiting for node vote'
|
||||||
@ -107,7 +102,6 @@ describe('Proposals list item details', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Renders proposal state: Open - 5 minutes left to vote', () => {
|
it('Renders proposal state: Open - 5 minutes left to vote', () => {
|
||||||
render(
|
|
||||||
renderComponent(
|
renderComponent(
|
||||||
generateProposal({
|
generateProposal({
|
||||||
state: ProposalState.STATE_OPEN,
|
state: ProposalState.STATE_OPEN,
|
||||||
@ -115,7 +109,6 @@ describe('Proposals list item details', () => {
|
|||||||
closingDatetime: fiveMinutes.toString(),
|
closingDatetime: fiveMinutes.toString(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
)
|
|
||||||
);
|
);
|
||||||
expect(screen.getByTestId('proposal-status')).toHaveTextContent('Open');
|
expect(screen.getByTestId('proposal-status')).toHaveTextContent('Open');
|
||||||
expect(screen.getByTestId('vote-details')).toHaveTextContent(
|
expect(screen.getByTestId('vote-details')).toHaveTextContent(
|
||||||
@ -124,7 +117,6 @@ describe('Proposals list item details', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Renders proposal state: Open - 5 hours left to vote', () => {
|
it('Renders proposal state: Open - 5 hours left to vote', () => {
|
||||||
render(
|
|
||||||
renderComponent(
|
renderComponent(
|
||||||
generateProposal({
|
generateProposal({
|
||||||
state: ProposalState.STATE_OPEN,
|
state: ProposalState.STATE_OPEN,
|
||||||
@ -132,7 +124,6 @@ describe('Proposals list item details', () => {
|
|||||||
closingDatetime: fiveHours.toString(),
|
closingDatetime: fiveHours.toString(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
)
|
|
||||||
);
|
);
|
||||||
expect(screen.getByTestId('proposal-status')).toHaveTextContent('Open');
|
expect(screen.getByTestId('proposal-status')).toHaveTextContent('Open');
|
||||||
expect(screen.getByTestId('vote-details')).toHaveTextContent(
|
expect(screen.getByTestId('vote-details')).toHaveTextContent(
|
||||||
@ -141,7 +132,6 @@ describe('Proposals list item details', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Renders proposal state: Open - 5 days left to vote', () => {
|
it('Renders proposal state: Open - 5 days left to vote', () => {
|
||||||
render(
|
|
||||||
renderComponent(
|
renderComponent(
|
||||||
generateProposal({
|
generateProposal({
|
||||||
state: ProposalState.STATE_OPEN,
|
state: ProposalState.STATE_OPEN,
|
||||||
@ -149,7 +139,6 @@ describe('Proposals list item details', () => {
|
|||||||
closingDatetime: fiveDays.toString(),
|
closingDatetime: fiveDays.toString(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
)
|
|
||||||
);
|
);
|
||||||
expect(screen.getByTestId('proposal-status')).toHaveTextContent('Open');
|
expect(screen.getByTestId('proposal-status')).toHaveTextContent('Open');
|
||||||
expect(screen.getByTestId('vote-details')).toHaveTextContent(
|
expect(screen.getByTestId('vote-details')).toHaveTextContent(
|
||||||
@ -158,7 +147,6 @@ describe('Proposals list item details', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Renders proposal state: Open - user voted for', () => {
|
it('Renders proposal state: Open - user voted for', () => {
|
||||||
render(
|
|
||||||
renderComponent(
|
renderComponent(
|
||||||
generateProposal({
|
generateProposal({
|
||||||
state: ProposalState.STATE_OPEN,
|
state: ProposalState.STATE_OPEN,
|
||||||
@ -187,7 +175,6 @@ describe('Proposals list item details', () => {
|
|||||||
closingDatetime: nextWeek.toString(),
|
closingDatetime: nextWeek.toString(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
)
|
|
||||||
);
|
);
|
||||||
expect(screen.getByTestId('proposal-status')).toHaveTextContent('Open');
|
expect(screen.getByTestId('proposal-status')).toHaveTextContent('Open');
|
||||||
expect(screen.getByTestId('vote-details')).toHaveTextContent(
|
expect(screen.getByTestId('vote-details')).toHaveTextContent(
|
||||||
@ -196,7 +183,6 @@ describe('Proposals list item details', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Renders proposal state: Open - user voted against', () => {
|
it('Renders proposal state: Open - user voted against', () => {
|
||||||
render(
|
|
||||||
renderComponent(
|
renderComponent(
|
||||||
generateProposal({
|
generateProposal({
|
||||||
state: ProposalState.STATE_OPEN,
|
state: ProposalState.STATE_OPEN,
|
||||||
@ -225,7 +211,6 @@ describe('Proposals list item details', () => {
|
|||||||
closingDatetime: nextWeek.toString(),
|
closingDatetime: nextWeek.toString(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
)
|
|
||||||
);
|
);
|
||||||
expect(screen.getByTestId('proposal-status')).toHaveTextContent('Open');
|
expect(screen.getByTestId('proposal-status')).toHaveTextContent('Open');
|
||||||
expect(screen.getByTestId('vote-details')).toHaveTextContent(
|
expect(screen.getByTestId('vote-details')).toHaveTextContent(
|
||||||
@ -234,7 +219,6 @@ describe('Proposals list item details', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Renders proposal state: Open - participation not reached', () => {
|
it('Renders proposal state: Open - participation not reached', () => {
|
||||||
render(
|
|
||||||
renderComponent(
|
renderComponent(
|
||||||
generateProposal({
|
generateProposal({
|
||||||
state: ProposalState.STATE_OPEN,
|
state: ProposalState.STATE_OPEN,
|
||||||
@ -246,7 +230,6 @@ describe('Proposals list item details', () => {
|
|||||||
yes: generateYesVotes(0),
|
yes: generateYesVotes(0),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
)
|
|
||||||
);
|
);
|
||||||
expect(screen.getByTestId('proposal-status')).toHaveTextContent('Open');
|
expect(screen.getByTestId('proposal-status')).toHaveTextContent('Open');
|
||||||
expect(screen.getByTestId('vote-status')).toHaveTextContent(
|
expect(screen.getByTestId('vote-status')).toHaveTextContent(
|
||||||
@ -255,7 +238,6 @@ describe('Proposals list item details', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Renders proposal state: Open - majority not reached', () => {
|
it('Renders proposal state: Open - majority not reached', () => {
|
||||||
render(
|
|
||||||
renderComponent(
|
renderComponent(
|
||||||
generateProposal({
|
generateProposal({
|
||||||
state: ProposalState.STATE_OPEN,
|
state: ProposalState.STATE_OPEN,
|
||||||
@ -267,7 +249,6 @@ describe('Proposals list item details', () => {
|
|||||||
yes: generateYesVotes(1, 1000000000000000000),
|
yes: generateYesVotes(1, 1000000000000000000),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
)
|
|
||||||
);
|
);
|
||||||
expect(screen.getByTestId('proposal-status')).toHaveTextContent('Open');
|
expect(screen.getByTestId('proposal-status')).toHaveTextContent('Open');
|
||||||
expect(screen.getByTestId('vote-status')).toHaveTextContent(
|
expect(screen.getByTestId('vote-status')).toHaveTextContent(
|
||||||
@ -276,7 +257,6 @@ describe('Proposals list item details', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Renders proposal state: Open - will pass', () => {
|
it('Renders proposal state: Open - will pass', () => {
|
||||||
render(
|
|
||||||
renderComponent(
|
renderComponent(
|
||||||
generateProposal({
|
generateProposal({
|
||||||
state: ProposalState.STATE_OPEN,
|
state: ProposalState.STATE_OPEN,
|
||||||
@ -289,34 +269,12 @@ describe('Proposals list item details', () => {
|
|||||||
closingDatetime: nextWeek.toString(),
|
closingDatetime: nextWeek.toString(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
)
|
|
||||||
);
|
);
|
||||||
expect(screen.getByTestId('proposal-status')).toHaveTextContent('Open');
|
expect(screen.getByTestId('proposal-status')).toHaveTextContent('Open');
|
||||||
expect(screen.getByTestId('vote-status')).toHaveTextContent('Set to pass');
|
expect(screen.getByTestId('vote-status')).toHaveTextContent('Set to pass');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Renders proposal state: Open - will fail', () => {
|
|
||||||
render(
|
|
||||||
renderComponent(
|
|
||||||
generateProposal({
|
|
||||||
state: ProposalState.STATE_OPEN,
|
|
||||||
votes: {
|
|
||||||
__typename: 'ProposalVotes',
|
|
||||||
yes: generateYesVotes(0),
|
|
||||||
no: generateNoVotes(3000, 1000000000000000000),
|
|
||||||
},
|
|
||||||
terms: {
|
|
||||||
closingDatetime: nextWeek.toString(),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
)
|
|
||||||
);
|
|
||||||
expect(screen.getByTestId('proposal-status')).toHaveTextContent('Open');
|
|
||||||
expect(screen.getByTestId('vote-status')).toHaveTextContent('Set to fail');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Renders proposal state: Declined - participation not reached', () => {
|
it('Renders proposal state: Declined - participation not reached', () => {
|
||||||
render(
|
|
||||||
renderComponent(
|
renderComponent(
|
||||||
generateProposal({
|
generateProposal({
|
||||||
state: ProposalState.STATE_DECLINED,
|
state: ProposalState.STATE_DECLINED,
|
||||||
@ -328,7 +286,6 @@ describe('Proposals list item details', () => {
|
|||||||
yes: generateYesVotes(0),
|
yes: generateYesVotes(0),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
)
|
|
||||||
);
|
);
|
||||||
expect(screen.getByTestId('proposal-status')).toHaveTextContent('Declined');
|
expect(screen.getByTestId('proposal-status')).toHaveTextContent('Declined');
|
||||||
expect(screen.getByTestId('vote-status')).toHaveTextContent(
|
expect(screen.getByTestId('vote-status')).toHaveTextContent(
|
||||||
@ -337,7 +294,6 @@ describe('Proposals list item details', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Renders proposal state: Declined - majority not reached', () => {
|
it('Renders proposal state: Declined - majority not reached', () => {
|
||||||
render(
|
|
||||||
renderComponent(
|
renderComponent(
|
||||||
generateProposal({
|
generateProposal({
|
||||||
state: ProposalState.STATE_DECLINED,
|
state: ProposalState.STATE_DECLINED,
|
||||||
@ -349,7 +305,6 @@ describe('Proposals list item details', () => {
|
|||||||
yes: generateYesVotes(1, 1000000000000000000),
|
yes: generateYesVotes(1, 1000000000000000000),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
)
|
|
||||||
);
|
);
|
||||||
expect(screen.getByTestId('proposal-status')).toHaveTextContent('Declined');
|
expect(screen.getByTestId('proposal-status')).toHaveTextContent('Declined');
|
||||||
expect(screen.getByTestId('vote-status')).toHaveTextContent(
|
expect(screen.getByTestId('vote-status')).toHaveTextContent(
|
||||||
@ -358,7 +313,6 @@ describe('Proposals list item details', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Renders proposal state: Rejected', () => {
|
it('Renders proposal state: Rejected', () => {
|
||||||
render(
|
|
||||||
renderComponent(
|
renderComponent(
|
||||||
generateProposal({
|
generateProposal({
|
||||||
state: ProposalState.STATE_REJECTED,
|
state: ProposalState.STATE_REJECTED,
|
||||||
@ -368,7 +322,6 @@ describe('Proposals list item details', () => {
|
|||||||
rejectionReason:
|
rejectionReason:
|
||||||
ProposalRejectionReason.PROPOSAL_ERROR_INVALID_FUTURE_PRODUCT,
|
ProposalRejectionReason.PROPOSAL_ERROR_INVALID_FUTURE_PRODUCT,
|
||||||
})
|
})
|
||||||
)
|
|
||||||
);
|
);
|
||||||
expect(screen.getByTestId('proposal-status')).toHaveTextContent('Rejected');
|
expect(screen.getByTestId('proposal-status')).toHaveTextContent('Rejected');
|
||||||
expect(screen.getByTestId('vote-status')).toHaveTextContent(
|
expect(screen.getByTestId('vote-status')).toHaveTextContent(
|
||||||
|
@ -133,12 +133,11 @@ export const ProposalsListItemDetails = ({
|
|||||||
voteStatus =
|
voteStatus =
|
||||||
(!participationMet && <ParticipationNotReached />) ||
|
(!participationMet && <ParticipationNotReached />) ||
|
||||||
(!majorityMet && <MajorityNotReached />) ||
|
(!majorityMet && <MajorityNotReached />) ||
|
||||||
(willPass && (
|
(willPass ? (
|
||||||
<>
|
<>
|
||||||
{t('Set to')} <StatusPass>{t('pass')}</StatusPass>
|
{t('Set to')} <StatusPass>{t('pass')}</StatusPass>
|
||||||
</>
|
</>
|
||||||
)) ||
|
) : (
|
||||||
(!willPass && (
|
|
||||||
<>
|
<>
|
||||||
{t('Set to')} <StatusFail>{t('fail')}</StatusFail>
|
{t('Set to')} <StatusFail>{t('fail')}</StatusFail>
|
||||||
</>
|
</>
|
||||||
|
@ -92,17 +92,21 @@ export function useUserVote(
|
|||||||
*/
|
*/
|
||||||
async function castVote(value: VoteValue) {
|
async function castVote(value: VoteValue) {
|
||||||
if (!proposalId || !pubKey) return;
|
if (!proposalId || !pubKey) return;
|
||||||
|
const previousVoteState = voteState;
|
||||||
setVoteState(VoteState.Requested);
|
setVoteState(VoteState.Requested);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await sendTx(pubKey, {
|
const res = await sendTx(pubKey, {
|
||||||
voteSubmission: {
|
voteSubmission: {
|
||||||
value: value,
|
value: value,
|
||||||
proposalId,
|
proposalId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
if (res === null) {
|
||||||
|
setVoteState(previousVoteState);
|
||||||
|
} else {
|
||||||
setVoteState(VoteState.Pending);
|
setVoteState(VoteState.Pending);
|
||||||
|
}
|
||||||
|
|
||||||
// Now await vote via poll in parent component
|
// Now await vote via poll in parent component
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -43,7 +43,7 @@ describe('Vote buttons', () => {
|
|||||||
</VegaWalletContext.Provider>
|
</VegaWalletContext.Provider>
|
||||||
</AppStateProvider>
|
</AppStateProvider>
|
||||||
);
|
);
|
||||||
expect(screen.getByText('Voting has ended. You did not vote')).toBeTruthy();
|
expect(screen.getByText('Voting has ended.')).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should provide a connect wallet prompt if no pubkey', () => {
|
it('should provide a connect wallet prompt if no pubkey', () => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { gql, useQuery } from '@apollo/client';
|
import { gql, useQuery } from '@apollo/client';
|
||||||
import { format } from 'date-fns';
|
import { format } from 'date-fns';
|
||||||
import * as React from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -88,10 +88,18 @@ export const VoteButtons = ({
|
|||||||
openVegaWalletDialog: store.openVegaWalletDialog,
|
openVegaWalletDialog: store.openVegaWalletDialog,
|
||||||
}));
|
}));
|
||||||
const [changeVote, setChangeVote] = React.useState(false);
|
const [changeVote, setChangeVote] = React.useState(false);
|
||||||
|
const proposalVotable = useMemo(
|
||||||
|
() =>
|
||||||
|
[
|
||||||
|
ProposalState.STATE_OPEN,
|
||||||
|
ProposalState.STATE_WAITING_FOR_NODE_VOTE,
|
||||||
|
].includes(proposalState),
|
||||||
|
[proposalState]
|
||||||
|
);
|
||||||
|
|
||||||
const cantVoteUI = React.useMemo(() => {
|
const cantVoteUI = React.useMemo(() => {
|
||||||
if (proposalState !== ProposalState.STATE_OPEN) {
|
if (!proposalVotable) {
|
||||||
return t('youDidNotVote');
|
return t('votingEnded');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pubKey) {
|
if (!pubKey) {
|
||||||
@ -141,13 +149,13 @@ export const VoteButtons = ({
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}, [
|
}, [
|
||||||
t,
|
proposalVotable,
|
||||||
pubKey,
|
pubKey,
|
||||||
currentStakeAvailable,
|
currentStakeAvailable,
|
||||||
proposalState,
|
|
||||||
appDispatch,
|
|
||||||
minVoterBalance,
|
minVoterBalance,
|
||||||
spamProtectionMinTokens,
|
spamProtectionMinTokens,
|
||||||
|
t,
|
||||||
|
appDispatch,
|
||||||
openVegaWalletDialog,
|
openVegaWalletDialog,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -188,7 +196,7 @@ export const VoteButtons = ({
|
|||||||
{voteDatetime ? (
|
{voteDatetime ? (
|
||||||
<span>{format(voteDatetime, DATE_FORMAT_LONG)}. </span>
|
<span>{format(voteDatetime, DATE_FORMAT_LONG)}. </span>
|
||||||
) : null}
|
) : null}
|
||||||
{proposalState === ProposalState.STATE_OPEN ? (
|
{proposalVotable ? (
|
||||||
<ButtonLink
|
<ButtonLink
|
||||||
data-testid="change-vote-button"
|
data-testid="change-vote-button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
@ -3,12 +3,7 @@ import React from 'react';
|
|||||||
|
|
||||||
import { useAppState } from '../../../contexts/app-state/app-state-context';
|
import { useAppState } from '../../../contexts/app-state/app-state-context';
|
||||||
import { BigNumber } from '../../../lib/bignumber';
|
import { BigNumber } from '../../../lib/bignumber';
|
||||||
import { addDecimal } from '../../../lib/decimals';
|
import type { ProposalFields } from '../__generated__/ProposalFields';
|
||||||
import type {
|
|
||||||
ProposalFields,
|
|
||||||
ProposalFields_votes_no_votes,
|
|
||||||
ProposalFields_votes_yes_votes,
|
|
||||||
} from '../__generated__/ProposalFields';
|
|
||||||
|
|
||||||
const useProposalNetworkParams = ({
|
const useProposalNetworkParams = ({
|
||||||
proposal,
|
proposal,
|
||||||
@ -100,34 +95,12 @@ export const useVoteInformation = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const noTokens = React.useMemo(() => {
|
const noTokens = React.useMemo(() => {
|
||||||
if (!proposal.votes.no.votes) {
|
return new BigNumber(proposal.votes.no.totalTokens);
|
||||||
return new BigNumber(0);
|
}, [proposal.votes.no.totalTokens]);
|
||||||
}
|
|
||||||
const totalNoVotes = proposal.votes.no.votes.reduce(
|
|
||||||
(prevValue: BigNumber, newValue: ProposalFields_votes_no_votes) => {
|
|
||||||
return new BigNumber(
|
|
||||||
newValue.party.stakingSummary.currentStakeAvailable
|
|
||||||
).plus(prevValue);
|
|
||||||
},
|
|
||||||
new BigNumber(0)
|
|
||||||
);
|
|
||||||
return new BigNumber(addDecimal(totalNoVotes, 18));
|
|
||||||
}, [proposal.votes.no.votes]);
|
|
||||||
|
|
||||||
const yesTokens = React.useMemo(() => {
|
const yesTokens = React.useMemo(() => {
|
||||||
if (!proposal.votes.yes.votes) {
|
return new BigNumber(proposal.votes.yes.totalTokens);
|
||||||
return new BigNumber(0);
|
}, [proposal.votes.yes.totalTokens]);
|
||||||
}
|
|
||||||
const totalYesVotes = proposal.votes.yes.votes.reduce(
|
|
||||||
(prevValue: BigNumber, newValue: ProposalFields_votes_yes_votes) => {
|
|
||||||
return new BigNumber(
|
|
||||||
newValue.party.stakingSummary.currentStakeAvailable
|
|
||||||
).plus(prevValue);
|
|
||||||
},
|
|
||||||
new BigNumber(0)
|
|
||||||
);
|
|
||||||
return new BigNumber(addDecimal(totalYesVotes, 18));
|
|
||||||
}, [proposal.votes.yes.votes]);
|
|
||||||
|
|
||||||
const totalTokensVoted = React.useMemo(
|
const totalTokensVoted = React.useMemo(
|
||||||
() => yesTokens.plus(noTokens),
|
() => yesTokens.plus(noTokens),
|
||||||
@ -153,11 +126,8 @@ export const useVoteInformation = ({
|
|||||||
}, [requiredParticipation, totalTokensVoted, totalSupply]);
|
}, [requiredParticipation, totalTokensVoted, totalSupply]);
|
||||||
|
|
||||||
const majorityMet = React.useMemo(() => {
|
const majorityMet = React.useMemo(() => {
|
||||||
return (
|
return yesPercentage.isGreaterThanOrEqualTo(requiredMajorityPercentage);
|
||||||
yesPercentage.isGreaterThanOrEqualTo(requiredMajorityPercentage) ||
|
}, [yesPercentage, requiredMajorityPercentage]);
|
||||||
noPercentage.isGreaterThanOrEqualTo(requiredMajorityPercentage)
|
|
||||||
);
|
|
||||||
}, [yesPercentage, noPercentage, requiredMajorityPercentage]);
|
|
||||||
|
|
||||||
const totalTokensPercentage = React.useMemo(() => {
|
const totalTokensPercentage = React.useMemo(() => {
|
||||||
return totalTokensVoted.multipliedBy(100).dividedBy(totalSupply);
|
return totalTokensVoted.multipliedBy(100).dividedBy(totalSupply);
|
||||||
@ -171,7 +141,6 @@ export const useVoteInformation = ({
|
|||||||
),
|
),
|
||||||
[participationMet, requiredMajorityPercentage, yesPercentage]
|
[participationMet, requiredMajorityPercentage, yesPercentage]
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
willPass,
|
willPass,
|
||||||
totalTokensPercentage,
|
totalTokensPercentage,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { ProposalState, VoteValue } from '@vegaprotocol/types';
|
import { ProposalState, VoteValue } from '@vegaprotocol/types';
|
||||||
|
import BigNumber from 'bignumber.js';
|
||||||
import * as faker from 'faker';
|
import * as faker from 'faker';
|
||||||
import isArray from 'lodash/isArray';
|
import isArray from 'lodash/isArray';
|
||||||
import mergeWith from 'lodash/mergeWith';
|
import mergeWith from 'lodash/mergeWith';
|
||||||
@ -7,7 +8,9 @@ import type { DeepPartial } from '../../../lib/type-helpers';
|
|||||||
import type {
|
import type {
|
||||||
ProposalFields,
|
ProposalFields,
|
||||||
ProposalFields_votes_no,
|
ProposalFields_votes_no,
|
||||||
|
ProposalFields_votes_no_votes,
|
||||||
ProposalFields_votes_yes,
|
ProposalFields_votes_yes,
|
||||||
|
ProposalFields_votes_yes_votes,
|
||||||
} from '../__generated__/ProposalFields';
|
} from '../__generated__/ProposalFields';
|
||||||
|
|
||||||
export function generateProposal(
|
export function generateProposal(
|
||||||
@ -76,19 +79,13 @@ export const generateYesVotes = (
|
|||||||
numberOfVotes = 5,
|
numberOfVotes = 5,
|
||||||
fixedTokenValue?: number
|
fixedTokenValue?: number
|
||||||
): ProposalFields_votes_yes => {
|
): ProposalFields_votes_yes => {
|
||||||
return {
|
const votes = Array.from(Array(numberOfVotes)).map(() => {
|
||||||
__typename: 'ProposalVoteSide',
|
const vote: ProposalFields_votes_yes_votes = {
|
||||||
totalNumber: faker.datatype.number({ min: 0, max: 100 }).toString(),
|
|
||||||
totalTokens: faker.datatype
|
|
||||||
.number({ min: 1, max: 10000000000000000000000 })
|
|
||||||
.toString(),
|
|
||||||
votes: Array.from(Array(numberOfVotes)).map(() => {
|
|
||||||
return {
|
|
||||||
__typename: 'Vote',
|
__typename: 'Vote',
|
||||||
value: VoteValue.VALUE_YES,
|
value: VoteValue.VALUE_YES,
|
||||||
party: {
|
party: {
|
||||||
id: faker.datatype.uuid(),
|
|
||||||
__typename: 'Party',
|
__typename: 'Party',
|
||||||
|
id: faker.datatype.uuid(),
|
||||||
stakingSummary: {
|
stakingSummary: {
|
||||||
__typename: 'StakingSummary',
|
__typename: 'StakingSummary',
|
||||||
currentStakeAvailable: fixedTokenValue
|
currentStakeAvailable: fixedTokenValue
|
||||||
@ -103,7 +100,18 @@ export const generateYesVotes = (
|
|||||||
},
|
},
|
||||||
datetime: faker.date.past().toISOString(),
|
datetime: faker.date.past().toISOString(),
|
||||||
};
|
};
|
||||||
}),
|
|
||||||
|
return vote;
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
__typename: 'ProposalVoteSide',
|
||||||
|
totalNumber: votes.length.toString(),
|
||||||
|
totalTokens: votes
|
||||||
|
.reduce((acc, cur) => {
|
||||||
|
return acc.plus(cur.party.stakingSummary.currentStakeAvailable);
|
||||||
|
}, new BigNumber(0))
|
||||||
|
.toString(),
|
||||||
|
votes,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -111,14 +119,8 @@ export const generateNoVotes = (
|
|||||||
numberOfVotes = 5,
|
numberOfVotes = 5,
|
||||||
fixedTokenValue?: number
|
fixedTokenValue?: number
|
||||||
): ProposalFields_votes_no => {
|
): ProposalFields_votes_no => {
|
||||||
return {
|
const votes = Array.from(Array(numberOfVotes)).map(() => {
|
||||||
__typename: 'ProposalVoteSide',
|
const vote: ProposalFields_votes_no_votes = {
|
||||||
totalNumber: faker.datatype.number({ min: 0, max: 100 }).toString(),
|
|
||||||
totalTokens: faker.datatype
|
|
||||||
.number({ min: 1000000000000000000, max: 10000000000000000000000 })
|
|
||||||
.toString(),
|
|
||||||
votes: Array.from(Array(numberOfVotes)).map(() => {
|
|
||||||
return {
|
|
||||||
__typename: 'Vote',
|
__typename: 'Vote',
|
||||||
value: VoteValue.VALUE_NO,
|
value: VoteValue.VALUE_NO,
|
||||||
party: {
|
party: {
|
||||||
@ -138,6 +140,16 @@ export const generateNoVotes = (
|
|||||||
},
|
},
|
||||||
datetime: faker.date.past().toISOString(),
|
datetime: faker.date.past().toISOString(),
|
||||||
};
|
};
|
||||||
}),
|
return vote;
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
__typename: 'ProposalVoteSide',
|
||||||
|
totalNumber: votes.length.toString(),
|
||||||
|
totalTokens: votes
|
||||||
|
.reduce((acc, cur) => {
|
||||||
|
return acc.plus(cur.party.stakingSummary.currentStakeAvailable);
|
||||||
|
}, new BigNumber(0))
|
||||||
|
.toString(),
|
||||||
|
votes,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user