feat(governance): update market proposal only available for enacted markets (#3542)

This commit is contained in:
Sam Keen 2023-05-02 11:10:03 +01:00 committed by GitHub
parent 00c5252aea
commit de48ffa563
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 122 additions and 108 deletions

View File

@ -9,6 +9,9 @@ query ProposalMarketsQuery {
code code
} }
} }
proposal {
state
}
} }
} }
} }

View File

@ -6,7 +6,7 @@ const defaultOptions = {} as const;
export type ProposalMarketsQueryQueryVariables = Types.Exact<{ [key: string]: never; }>; export type ProposalMarketsQueryQueryVariables = Types.Exact<{ [key: string]: never; }>;
export type ProposalMarketsQueryQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, code: string } } } }> } | null }; export type ProposalMarketsQueryQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, code: string } }, proposal?: { __typename?: 'Proposal', state: Types.ProposalState } | null } }> } | null };
export const ProposalMarketsQueryDocument = gql` export const ProposalMarketsQueryDocument = gql`
@ -21,6 +21,9 @@ export const ProposalMarketsQueryDocument = gql`
code code
} }
} }
proposal {
state
}
} }
} }
} }

View File

@ -1,94 +0,0 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type ProposalMarketsQueryQueryVariables = Types.Exact<{
[key: string]: never;
}>;
export type ProposalMarketsQueryQuery = {
__typename?: 'Query';
marketsConnection?: {
__typename?: 'MarketConnection';
edges: Array<{
__typename?: 'MarketEdge';
node: {
__typename?: 'Market';
id: string;
tradableInstrument: {
__typename?: 'TradableInstrument';
instrument: { __typename?: 'Instrument'; name: string; code: string };
};
};
}>;
} | null;
};
export const ProposalMarketsQueryDocument = gql`
query ProposalMarketsQuery {
marketsConnection {
edges {
node {
id
tradableInstrument {
instrument {
name
code
}
}
}
}
}
}
`;
/**
* __useProposalMarketsQueryQuery__
*
* To run a query within a React component, call `useProposalMarketsQueryQuery` and pass it any options that fit your needs.
* When your component renders, `useProposalMarketsQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useProposalMarketsQueryQuery({
* variables: {
* },
* });
*/
export function useProposalMarketsQueryQuery(
baseOptions?: Apollo.QueryHookOptions<
ProposalMarketsQueryQuery,
ProposalMarketsQueryQueryVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useQuery<
ProposalMarketsQueryQuery,
ProposalMarketsQueryQueryVariables
>(ProposalMarketsQueryDocument, options);
}
export function useProposalMarketsQueryLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions<
ProposalMarketsQueryQuery,
ProposalMarketsQueryQueryVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useLazyQuery<
ProposalMarketsQueryQuery,
ProposalMarketsQueryQueryVariables
>(ProposalMarketsQueryDocument, options);
}
export type ProposalMarketsQueryQueryHookResult = ReturnType<
typeof useProposalMarketsQueryQuery
>;
export type ProposalMarketsQueryLazyQueryHookResult = ReturnType<
typeof useProposalMarketsQueryLazyQuery
>;
export type ProposalMarketsQueryQueryResult = Apollo.QueryResult<
ProposalMarketsQueryQuery,
ProposalMarketsQueryQueryVariables
>;

View File

@ -1,15 +1,16 @@
import type { MockedResponse } from '@apollo/client/testing'; import type { MockedResponse } from '@apollo/client/testing';
import { MockedProvider } from '@apollo/client/testing'; import { MockedProvider } from '@apollo/client/testing';
import { MemoryRouter as Router } from 'react-router-dom'; import { MemoryRouter as Router } from 'react-router-dom';
import { render, screen, fireEvent, waitFor } from '@testing-library/react'; import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { VegaWalletContext } from '@vegaprotocol/wallet'; import { VegaWalletContext } from '@vegaprotocol/wallet';
import { AppStateProvider } from '../../../../contexts/app-state/app-state-provider'; import { AppStateProvider } from '../../../../contexts/app-state/app-state-provider';
import { mockWalletContext } from '../../test-helpers/mocks'; import { mockWalletContext } from '../../test-helpers/mocks';
import { ProposeUpdateMarket } from './propose-update-market'; import { ProposeUpdateMarket } from './propose-update-market';
import type { NetworkParamsQuery } from '@vegaprotocol/react-helpers'; import type { NetworkParamsQuery } from '@vegaprotocol/react-helpers';
import { NetworkParamsDocument } from '@vegaprotocol/react-helpers'; import { NetworkParamsDocument } from '@vegaprotocol/react-helpers';
import type { ProposalMarketsQueryQuery } from './__generated___/UpdateMarket'; import type { ProposalMarketsQueryQuery } from './__generated__/UpdateMarket';
import { ProposalMarketsQueryDocument } from './__generated___/UpdateMarket'; import { ProposalMarketsQueryDocument } from './__generated__/UpdateMarket';
import { ProposalState } from '@vegaprotocol/types';
const updateMarketNetworkParamsQueryMock: MockedResponse<NetworkParamsQuery> = { const updateMarketNetworkParamsQueryMock: MockedResponse<NetworkParamsQuery> = {
request: { request: {
@ -89,6 +90,10 @@ const marketQueryMock: MockedResponse<ProposalMarketsQueryQuery> = {
code: 'ETHiUSDT', code: 'ETHiUSDT',
}, },
}, },
proposal: {
__typename: 'Proposal',
state: ProposalState.STATE_ENACTED,
},
}, },
}, },
{ {
@ -101,11 +106,16 @@ const marketQueryMock: MockedResponse<ProposalMarketsQueryQuery> = {
instrument: { instrument: {
__typename: 'Instrument', __typename: 'Instrument',
name: 'Las Vegas nuggets', name: 'Las Vegas nuggets',
code: 'Nuggets2', code: 'Nuggets',
}, },
}, },
proposal: {
__typename: 'Proposal',
state: ProposalState.STATE_OPEN,
},
}, },
}, },
{ {
__typename: 'MarketEdge', __typename: 'MarketEdge',
node: { node: {
@ -115,10 +125,14 @@ const marketQueryMock: MockedResponse<ProposalMarketsQueryQuery> = {
__typename: 'TradableInstrument', __typename: 'TradableInstrument',
instrument: { instrument: {
__typename: 'Instrument', __typename: 'Instrument',
name: 'Nuggets', name: 'California Nuggets',
code: 'Nuggets', code: 'Nuggets2',
}, },
}, },
proposal: {
__typename: 'Proposal',
state: ProposalState.STATE_WAITING_FOR_NODE_VOTE,
},
}, },
}, },
{ {
@ -130,10 +144,71 @@ const marketQueryMock: MockedResponse<ProposalMarketsQueryQuery> = {
__typename: 'TradableInstrument', __typename: 'TradableInstrument',
instrument: { instrument: {
__typename: 'Instrument', __typename: 'Instrument',
name: 'CELUSD (June 2022)', name: 'Nevada Nuggets',
code: 'CELUSD', code: 'Nugetts3',
}, },
}, },
proposal: {
__typename: 'Proposal',
state: ProposalState.STATE_REJECTED,
},
},
},
{
__typename: 'MarketEdge',
node: {
__typename: 'Market',
id: 'asdfe1755208914b6f258a28babd19ae8dfbaf4084d8867d8a120c50dca1e17f',
tradableInstrument: {
__typename: 'TradableInstrument',
instrument: {
__typename: 'Instrument',
name: 'NZ Nuggets',
code: 'Nugetts4',
},
},
proposal: {
__typename: 'Proposal',
state: ProposalState.STATE_DECLINED,
},
},
},
{
__typename: 'MarketEdge',
node: {
__typename: 'Market',
id: 'asdfe1755208914b6f258a28babd19ae8dfbaf4084d8867d8a120c50dca1e17f',
tradableInstrument: {
__typename: 'TradableInstrument',
instrument: {
__typename: 'Instrument',
name: 'Aussie Nuggets',
code: 'Nugetts5',
},
},
proposal: {
__typename: 'Proposal',
state: ProposalState.STATE_PASSED,
},
},
},
{
__typename: 'MarketEdge',
node: {
__typename: 'Market',
id: 'xcvbe1755208914b6f258a28babd19ae8dfbaf4084d8867d8a120c50dca1e17f',
tradableInstrument: {
__typename: 'TradableInstrument',
instrument: {
__typename: 'Instrument',
name: 'Tasmanian Nuggets',
code: 'Nugetts6',
},
},
proposal: {
__typename: 'Proposal',
state: ProposalState.STATE_FAILED,
},
}, },
}, },
], ],
@ -199,6 +274,27 @@ describe('Propose Update Market', () => {
expect(screen.getByTestId('proposal-market-select')).toHaveValue(''); expect(screen.getByTestId('proposal-market-select')).toHaveValue('');
}); });
it('should only render enacted markets', async () => {
renderComponent();
expect(
await screen.findByText('Update market proposal')
).toBeInTheDocument();
// (state enacted)
expect(screen.getByText('ETHUSD (September Market)')).toBeInTheDocument();
// (state open)
expect(screen.queryByText('Las Vegas nuggets')).not.toBeInTheDocument();
// (state waiting for node vote)
expect(screen.queryByText('California nuggets')).not.toBeInTheDocument();
// (state rejected)
expect(screen.queryByText('Nevada nuggets')).not.toBeInTheDocument();
// (state declined)
expect(screen.queryByText('NZ nuggets')).not.toBeInTheDocument();
// (state passed)
expect(screen.queryByText('Aussie nuggets')).not.toBeInTheDocument();
// (state failed)
expect(screen.queryByText('Tasmanian nuggets')).not.toBeInTheDocument();
});
it('should render the correct market details when the market select is used', async () => { it('should render the correct market details when the market select is used', async () => {
renderComponent(); renderComponent();
expect( expect(

View File

@ -2,25 +2,28 @@ import { useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useForm } from 'react-hook-form'; import { useForm } from 'react-hook-form';
import { import {
doesValueEquateToParam,
getClosingTimestamp, getClosingTimestamp,
getEnactmentTimestamp, getEnactmentTimestamp,
useProposalSubmit, useProposalSubmit,
doesValueEquateToParam,
} from '@vegaprotocol/proposals'; } from '@vegaprotocol/proposals';
import { useEnvironment } from '@vegaprotocol/environment'; import { useEnvironment } from '@vegaprotocol/environment';
import { createDocsLinks, validateJson } from '@vegaprotocol/utils'; import { createDocsLinks, validateJson } from '@vegaprotocol/utils';
import { NetworkParams, useNetworkParams } from '@vegaprotocol/react-helpers'; import { NetworkParams, useNetworkParams } from '@vegaprotocol/react-helpers';
import { import {
ProposalFormDescription, ProposalFormDescription,
ProposalFormDownloadJson,
ProposalFormSubheader, ProposalFormSubheader,
ProposalFormSubmit, ProposalFormSubmit,
ProposalFormTerms, ProposalFormTerms,
ProposalFormTitle, ProposalFormTitle,
ProposalFormTransactionDialog, ProposalFormTransactionDialog,
ProposalFormDownloadJson,
ProposalFormVoteAndEnactmentDeadline, ProposalFormVoteAndEnactmentDeadline,
} from '../../components/propose'; } from '../../components/propose';
import { ProposalMinRequirements } from '../../components/shared'; import {
ProposalMinRequirements,
ProposalUserAction,
} from '../../components/shared';
import { import {
AsyncRenderer, AsyncRenderer,
ExternalLink, ExternalLink,
@ -31,9 +34,9 @@ import {
Select, Select,
} from '@vegaprotocol/ui-toolkit'; } from '@vegaprotocol/ui-toolkit';
import { Heading } from '../../../../components/heading'; import { Heading } from '../../../../components/heading';
import { ProposalUserAction } from '../../components/shared'; import { useProposalMarketsQueryQuery } from './__generated__/UpdateMarket';
import { useProposalMarketsQueryQuery } from './__generated___/UpdateMarket';
import { downloadJson } from '../../../../lib/download-json'; import { downloadJson } from '../../../../lib/download-json';
import { ProposalState } from '@vegaprotocol/types';
export interface UpdateMarketProposalFormFields { export interface UpdateMarketProposalFormFields {
proposalVoteDeadline: string; proposalVoteDeadline: string;
@ -73,6 +76,9 @@ export const ProposeUpdateMarket = () => {
return marketsData.marketsConnection.edges return marketsData.marketsConnection.edges
.map((edge) => edge.node) .map((edge) => edge.node)
.filter(
(market) => market.proposal?.state === ProposalState.STATE_ENACTED
)
.sort((a, b) => { .sort((a, b) => {
const aName = a.tradableInstrument.instrument.name; const aName = a.tradableInstrument.instrument.name;
const bName = b.tradableInstrument.instrument.name; const bName = b.tradableInstrument.instrument.name;