Feat/1666: Added min requirements for raw proposal form. Tests failing (#1884)
* Feat/1666: Added min requirements for raw proposal form. Tests failing * Feat/1666: Tests now passing
This commit is contained in:
parent
03e39e8323
commit
1f8469a97a
@ -702,5 +702,7 @@
|
||||
"FreeformProposal": "Freeform proposal",
|
||||
"unknownReason": "unknown reason",
|
||||
"votingEnded": "Voting has ended.",
|
||||
"STATUS": "STATUS"
|
||||
"STATUS": "STATUS",
|
||||
"ProposalMinimumAmounts": "Different proposal types can have different minimum token requirements. You must have the greater of the proposal minimum or spam protection minimum from the table below",
|
||||
"SpamProtectionMin": "Spam protection minimum"
|
||||
}
|
||||
|
@ -13,6 +13,9 @@ interface ProposalFormMinRequirementsProps {
|
||||
userAction: ProposalUserAction.CREATE | ProposalUserAction.VOTE;
|
||||
}
|
||||
|
||||
export const formatMinRequiredBalance = (balance: string) =>
|
||||
new BigNumber(addDecimal(balance, 18));
|
||||
|
||||
// Returns the larger, formatted value of the two token amounts
|
||||
export const ProposalMinRequirements = ({
|
||||
minProposalBalance,
|
||||
@ -20,12 +23,10 @@ export const ProposalMinRequirements = ({
|
||||
userAction,
|
||||
}: ProposalFormMinRequirementsProps) => {
|
||||
const { t } = useTranslation();
|
||||
const minProposalBalanceFormatted = new BigNumber(
|
||||
addDecimal(minProposalBalance, 18)
|
||||
);
|
||||
const spamProtectionMinFormatted = new BigNumber(
|
||||
addDecimal(spamProtectionMin, 18)
|
||||
);
|
||||
const minProposalBalanceFormatted =
|
||||
formatMinRequiredBalance(minProposalBalance);
|
||||
const spamProtectionMinFormatted =
|
||||
formatMinRequiredBalance(spamProtectionMin);
|
||||
|
||||
const larger =
|
||||
minProposalBalanceFormatted > spamProtectionMinFormatted
|
||||
|
@ -15,7 +15,7 @@ jest.mock('@vegaprotocol/environment', () => ({
|
||||
}),
|
||||
}));
|
||||
|
||||
const updateMarketNetworkParamsQueryMock: MockedResponse<NetworkParamsQuery> = {
|
||||
const newAssetNetworkParamsQueryMock: MockedResponse<NetworkParamsQuery> = {
|
||||
request: {
|
||||
query: NETWORK_PARAMETERS_QUERY,
|
||||
},
|
||||
@ -60,7 +60,7 @@ const updateMarketNetworkParamsQueryMock: MockedResponse<NetworkParamsQuery> = {
|
||||
const renderComponent = () =>
|
||||
render(
|
||||
<Router>
|
||||
<MockedProvider mocks={[updateMarketNetworkParamsQueryMock]}>
|
||||
<MockedProvider mocks={[newAssetNetworkParamsQueryMock]}>
|
||||
<AppStateProvider>
|
||||
<VegaWalletContext.Provider value={mockWalletContext}>
|
||||
<ProposeNewAsset />
|
||||
|
@ -0,0 +1,104 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { KeyValueTable, KeyValueTableRow } from '@vegaprotocol/ui-toolkit';
|
||||
import { formatMinRequiredBalance } from '../../components/shared';
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
export interface ProposalRawMinRequirementsProps {
|
||||
assetMin: string;
|
||||
updateAssetMin: string;
|
||||
marketMin: string;
|
||||
updateMarketMin: string;
|
||||
updateNetParamMin: string;
|
||||
freeformMin: string;
|
||||
spamProtectionMin: string;
|
||||
}
|
||||
|
||||
const Wrapper = ({ children }: { children: ReactNode }) => (
|
||||
<div className="mb-4" data-testid="proposal-raw-min-requirements">
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
||||
export const ProposalRawMinRequirements = ({
|
||||
assetMin,
|
||||
updateAssetMin,
|
||||
marketMin,
|
||||
updateMarketMin,
|
||||
updateNetParamMin,
|
||||
freeformMin,
|
||||
spamProtectionMin,
|
||||
}: ProposalRawMinRequirementsProps) => {
|
||||
const { t } = useTranslation();
|
||||
if (
|
||||
assetMin <= spamProtectionMin &&
|
||||
updateAssetMin <= spamProtectionMin &&
|
||||
marketMin <= spamProtectionMin &&
|
||||
updateMarketMin <= spamProtectionMin &&
|
||||
updateNetParamMin <= spamProtectionMin &&
|
||||
freeformMin <= spamProtectionMin
|
||||
) {
|
||||
return (
|
||||
<Wrapper>
|
||||
{t('MinProposalRequirements', {
|
||||
value: Number(formatMinRequiredBalance(spamProtectionMin)),
|
||||
})}
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
assetMin === updateAssetMin &&
|
||||
assetMin === marketMin &&
|
||||
assetMin === updateMarketMin &&
|
||||
assetMin === updateNetParamMin &&
|
||||
assetMin === freeformMin
|
||||
) {
|
||||
return (
|
||||
<Wrapper>
|
||||
{t('MinProposalRequirements', {
|
||||
value: Number(formatMinRequiredBalance(assetMin)),
|
||||
})}
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<div className="mb-4">
|
||||
{t(
|
||||
'Different proposal types can have different minimum token requirements. You must have the greater of the proposal minimum or spam protection minimum from the table below'
|
||||
)}
|
||||
</div>
|
||||
<KeyValueTable>
|
||||
<KeyValueTableRow>
|
||||
{t('NewAsset')}
|
||||
{`${formatMinRequiredBalance(assetMin).toString()} VEGA`}
|
||||
</KeyValueTableRow>
|
||||
<KeyValueTableRow>
|
||||
{t('UpdateAsset')}
|
||||
{`${formatMinRequiredBalance(updateAssetMin).toString()} VEGA`}
|
||||
</KeyValueTableRow>
|
||||
<KeyValueTableRow>
|
||||
{t('NewMarket')}
|
||||
{`${formatMinRequiredBalance(marketMin).toString()} VEGA`}
|
||||
</KeyValueTableRow>
|
||||
<KeyValueTableRow>
|
||||
{t('UpdateMarket')}
|
||||
{`${formatMinRequiredBalance(updateMarketMin).toString()} VEGA`}
|
||||
</KeyValueTableRow>
|
||||
<KeyValueTableRow>
|
||||
{t('NetworkParameter')}
|
||||
{`${formatMinRequiredBalance(updateNetParamMin).toString()} VEGA`}
|
||||
</KeyValueTableRow>
|
||||
<KeyValueTableRow>
|
||||
{t('Freeform')}
|
||||
{`${formatMinRequiredBalance(freeformMin).toString()} VEGA`}
|
||||
</KeyValueTableRow>
|
||||
<KeyValueTableRow>
|
||||
{t('SpamProtectionMin')}
|
||||
{`${formatMinRequiredBalance(spamProtectionMin).toString()} VEGA`}
|
||||
</KeyValueTableRow>
|
||||
</KeyValueTable>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
@ -13,6 +13,58 @@ import {
|
||||
import { ProposeRaw } from './propose-raw';
|
||||
import { ProposalEventDocument } from '@vegaprotocol/governance';
|
||||
import type { ProposalEventSubscription } from '@vegaprotocol/governance';
|
||||
import { NETWORK_PARAMETERS_QUERY } from '@vegaprotocol/react-helpers';
|
||||
import type { NetworkParamsQuery } from '@vegaprotocol/web3';
|
||||
|
||||
const paramsDelay = 20;
|
||||
|
||||
const rawProposalNetworkParamsQueryMock: MockedResponse<NetworkParamsQuery> = {
|
||||
request: {
|
||||
query: NETWORK_PARAMETERS_QUERY,
|
||||
},
|
||||
result: {
|
||||
data: {
|
||||
networkParameters: [
|
||||
{
|
||||
__typename: 'NetworkParameter',
|
||||
key: 'governance.proposal.asset.minProposerBalance',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
__typename: 'NetworkParameter',
|
||||
key: 'governance.proposal.updateAsset.minProposerBalance',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
__typename: 'NetworkParameter',
|
||||
key: 'governance.proposal.market.minProposerBalance',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
__typename: 'NetworkParameter',
|
||||
key: 'governance.proposal.updateMarket.minProposerBalance',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
__typename: 'NetworkParameter',
|
||||
key: 'governance.proposal.updateNetParam.minProposerBalance',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
__typename: 'NetworkParameter',
|
||||
key: 'governance.proposal.freeform.minProposerBalance',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
__typename: 'NetworkParameter',
|
||||
key: 'spam.protection.proposal.min.tokens',
|
||||
value: '1000000000000000000',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
delay: paramsDelay,
|
||||
};
|
||||
|
||||
describe('Raw proposal form', () => {
|
||||
const pubKey = '0x123';
|
||||
@ -47,7 +99,9 @@ describe('Raw proposal form', () => {
|
||||
const setup = (mockSendTx = jest.fn()) => {
|
||||
return render(
|
||||
<AppStateProvider>
|
||||
<MockedProvider mocks={[mockProposalEvent]}>
|
||||
<MockedProvider
|
||||
mocks={[rawProposalNetworkParamsQueryMock, mockProposalEvent]}
|
||||
>
|
||||
<VegaWalletContext.Provider
|
||||
value={
|
||||
{
|
||||
@ -74,6 +128,8 @@ describe('Raw proposal form', () => {
|
||||
it('handles validation', async () => {
|
||||
const mockSendTx = jest.fn().mockReturnValue(Promise.resolve());
|
||||
setup(mockSendTx);
|
||||
|
||||
expect(await screen.findByTestId('proposal-submit')).toBeTruthy();
|
||||
await act(async () => {
|
||||
fireEvent.click(screen.getByTestId('proposal-submit'));
|
||||
});
|
||||
@ -113,6 +169,10 @@ describe('Raw proposal form', () => {
|
||||
);
|
||||
setup(mockSendTx);
|
||||
|
||||
await act(async () => {
|
||||
jest.advanceTimersByTime(paramsDelay);
|
||||
});
|
||||
|
||||
const inputJSON = JSON.stringify({
|
||||
rationale: {
|
||||
description: 'Update governance.proposal.freeform.minVoterBalance',
|
||||
@ -129,6 +189,7 @@ describe('Raw proposal form', () => {
|
||||
enactmentTimestamp: Math.floor(getTime(addHours(new Date(), 3)) / 1000),
|
||||
},
|
||||
});
|
||||
|
||||
fireEvent.change(screen.getByTestId('proposal-data'), {
|
||||
target: { value: inputJSON },
|
||||
});
|
||||
@ -170,7 +231,14 @@ describe('Raw proposal form', () => {
|
||||
);
|
||||
setup(mockSendTx);
|
||||
|
||||
await act(async () => {
|
||||
jest.advanceTimersByTime(paramsDelay);
|
||||
});
|
||||
|
||||
const inputJSON = '{}';
|
||||
|
||||
expect(await screen.findByTestId('proposal-data')).toBeTruthy();
|
||||
|
||||
fireEvent.change(screen.getByTestId('proposal-data'), {
|
||||
target: { value: inputJSON },
|
||||
});
|
||||
|
@ -4,23 +4,43 @@ import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { Heading } from '../../../../components/heading';
|
||||
import { VegaWalletContainer } from '../../../../components/vega-wallet-container';
|
||||
import {
|
||||
AsyncRenderer,
|
||||
FormGroup,
|
||||
InputError,
|
||||
Link,
|
||||
TextArea,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { validateJson } from '@vegaprotocol/react-helpers';
|
||||
import {
|
||||
NetworkParams,
|
||||
useNetworkParams,
|
||||
validateJson,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import { useProposalSubmit } from '@vegaprotocol/governance';
|
||||
import {
|
||||
ProposalFormSubmit,
|
||||
ProposalFormTransactionDialog,
|
||||
} from '../../components/propose';
|
||||
import { ProposalRawMinRequirements } from './proposal-raw-min-requirements';
|
||||
|
||||
export interface RawProposalFormFields {
|
||||
rawProposalData: string;
|
||||
}
|
||||
|
||||
export const ProposeRaw = () => {
|
||||
const {
|
||||
params,
|
||||
loading: networkParamsLoading,
|
||||
error: networkParamsError,
|
||||
} = useNetworkParams([
|
||||
NetworkParams.governance_proposal_asset_minProposerBalance,
|
||||
NetworkParams.governance_proposal_updateAsset_minProposerBalance,
|
||||
NetworkParams.governance_proposal_market_minProposerBalance,
|
||||
NetworkParams.governance_proposal_updateMarket_minProposerBalance,
|
||||
NetworkParams.governance_proposal_updateNetParam_minProposerBalance,
|
||||
NetworkParams.governance_proposal_freeform_minProposerBalance,
|
||||
NetworkParams.spam_protection_proposal_min_tokens,
|
||||
]);
|
||||
|
||||
const { VEGA_EXPLORER_URL, VEGA_DOCS_URL } = useEnvironment();
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
@ -37,11 +57,33 @@ export const ProposeRaw = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<AsyncRenderer
|
||||
loading={networkParamsLoading}
|
||||
error={networkParamsError}
|
||||
data={params}
|
||||
>
|
||||
<Heading title={t('NewRawProposal')} />
|
||||
<VegaWalletContainer>
|
||||
{() => (
|
||||
<>
|
||||
<ProposalRawMinRequirements
|
||||
assetMin={params.governance_proposal_asset_minProposerBalance}
|
||||
updateAssetMin={
|
||||
params.governance_proposal_updateAsset_minProposerBalance
|
||||
}
|
||||
marketMin={params.governance_proposal_market_minProposerBalance}
|
||||
updateMarketMin={
|
||||
params.governance_proposal_updateMarket_minProposerBalance
|
||||
}
|
||||
updateNetParamMin={
|
||||
params.governance_proposal_updateNetParam_minProposerBalance
|
||||
}
|
||||
freeformMin={
|
||||
params.governance_proposal_freeform_minProposerBalance
|
||||
}
|
||||
spamProtectionMin={params.spam_protection_proposal_min_tokens}
|
||||
/>
|
||||
|
||||
{VEGA_DOCS_URL && (
|
||||
<p className="text-sm" data-testid="proposal-docs-link">
|
||||
<span className="mr-1">{t('ProposalTermsText')}</span>
|
||||
@ -94,6 +136,6 @@ export const ProposeRaw = () => {
|
||||
</>
|
||||
)}
|
||||
</VegaWalletContainer>
|
||||
</>
|
||||
</AsyncRenderer>
|
||||
);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user