diff --git a/apps/governance-e2e/.env.devnet b/apps/governance-e2e/.env.devnet index 124d10968..79be2dc4d 100644 --- a/apps/governance-e2e/.env.devnet +++ b/apps/governance-e2e/.env.devnet @@ -5,3 +5,4 @@ NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9 NX_ETHERSCAN_URL=https://sepolia.etherscan.io NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json NX_PRODUCT_PERPETUALS=true +NX_UPDATE_MARKET_STATE=true diff --git a/apps/governance-e2e/.env.mainnet b/apps/governance-e2e/.env.mainnet index f59b0939c..68cd829b6 100644 --- a/apps/governance-e2e/.env.mainnet +++ b/apps/governance-e2e/.env.mainnet @@ -5,3 +5,4 @@ NX_ETHEREUM_PROVIDER_URL=https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9 NX_ETHERSCAN_URL=https://etherscan.io NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json NX_PRODUCT_PERPETUALS=false +NX_UPDATE_MARKET_STATE=false diff --git a/apps/governance-e2e/.env.testnet b/apps/governance-e2e/.env.testnet index 2f39b6fbd..13182d002 100644 --- a/apps/governance-e2e/.env.testnet +++ b/apps/governance-e2e/.env.testnet @@ -5,3 +5,4 @@ NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9 NX_ETHERSCAN_URL=https://sepolia.etherscan.io NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json NX_PRODUCT_PERPETUALS=true +NX_UPDATE_MARKET_STATE=true diff --git a/apps/governance/.env b/apps/governance/.env index ee6d94009..2c6151228 100644 --- a/apps/governance/.env +++ b/apps/governance/.env @@ -33,3 +33,4 @@ LC_ALL="en_US.UTF-8" NX_SUCCESSOR_MARKETS=true NX_METAMASK_SNAPS=true NX_PRODUCT_PERPETUALS=false +NX_UPDATE_MARKET_STATE=false diff --git a/apps/governance/.env.capsule b/apps/governance/.env.capsule index 34bb656e2..13702cd57 100644 --- a/apps/governance/.env.capsule +++ b/apps/governance/.env.capsule @@ -34,3 +34,4 @@ CYPRESS_FAIRGROUND=false NX_SUCCESSOR_MARKETS=false NX_METAMASK_SNAPS=false NX_PRODUCT_PERPETUALS=true +NX_UPDATE_MARKET_STATE=true diff --git a/apps/governance/.env.devnet b/apps/governance/.env.devnet index a0a31c6dd..4687fb0cd 100644 --- a/apps/governance/.env.devnet +++ b/apps/governance/.env.devnet @@ -26,3 +26,4 @@ NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/m NX_SUCCESSOR_MARKETS=true NX_METAMASK_SNAPS=true NX_PRODUCT_PERPETUALS=true +NX_UPDATE_MARKET_STATE=true diff --git a/apps/governance/.env.mainnet b/apps/governance/.env.mainnet index 7b75bc106..55ee0376a 100644 --- a/apps/governance/.env.mainnet +++ b/apps/governance/.env.mainnet @@ -25,3 +25,4 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket NX_SUCCESSOR_MARKETS=false NX_METAMASK_SNAPS=false NX_PRODUCT_PERPETUALS=false +NX_UPDATE_MARKET_STATE=false diff --git a/apps/governance/.env.mainnet-mirror b/apps/governance/.env.mainnet-mirror index 3e20d16a3..094c84a0a 100644 --- a/apps/governance/.env.mainnet-mirror +++ b/apps/governance/.env.mainnet-mirror @@ -23,3 +23,5 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://be.mainnet-mirror.vega.rocks/websocket # Cosmic elevator flags NX_SUCCESSOR_MARKETS=false NX_METAMASK_SNAPS=false +NX_PRODUCT_PERPETUALS=false +NX_UPDATE_MARKET_STATE=false diff --git a/apps/governance/.env.stagnet1 b/apps/governance/.env.stagnet1 index 8664b009e..708b234db 100644 --- a/apps/governance/.env.stagnet1 +++ b/apps/governance/.env.stagnet1 @@ -21,3 +21,4 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket NX_SUCCESSOR_MARKETS=true NX_METAMASK_SNAPS=true NX_PRODUCT_PERPETUALS=true +NX_UPDATE_MARKET_STATE=true diff --git a/apps/governance/.env.testnet b/apps/governance/.env.testnet index b3973792b..86ff8e022 100644 --- a/apps/governance/.env.testnet +++ b/apps/governance/.env.testnet @@ -26,3 +26,4 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://be.testnet.vega.xyz/websocket NX_SUCCESSOR_MARKETS=true NX_METAMASK_SNAPS=true NX_PRODUCT_PERPETUALS=true +NX_UPDATE_MARKET_STATE=true diff --git a/apps/governance/.env.validators-testnet b/apps/governance/.env.validators-testnet index 8bfc69f68..4893c0ec3 100644 --- a/apps/governance/.env.validators-testnet +++ b/apps/governance/.env.validators-testnet @@ -23,3 +23,4 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega. NX_SUCCESSOR_MARKETS=false NX_METAMASK_SNAPS=false NX_PRODUCT_PERPETUALS=false +NX_UPDATE_MARKET_STATE=false diff --git a/apps/governance/src/app.tsx b/apps/governance/src/app.tsx index ddc85a2cf..c7c3850b2 100644 --- a/apps/governance/src/app.tsx +++ b/apps/governance/src/app.tsx @@ -308,7 +308,7 @@ const AppContainer = () => { -
+
{t('Loading')}
} failure={ diff --git a/apps/governance/src/i18n/translations/dev.json b/apps/governance/src/i18n/translations/dev.json index 8c796af5f..1d573d970 100644 --- a/apps/governance/src/i18n/translations/dev.json +++ b/apps/governance/src/i18n/translations/dev.json @@ -613,6 +613,9 @@ "proposalDetails": "Proposal details", "marketSpecification": "Market specification", "viewMarketJson": "View market JSON", + "marketId": "Market ID", + "marketName": "Market name", + "marketCode": "Market code", "proposalDescription": "Description", "currentlySetTo": "Currently expected to ", "currently": "currently", @@ -705,10 +708,17 @@ "parameter": "parameter", "NewMarketProposal": "New market proposal", "UpdateMarketProposal": "Update market proposal", + "UpdateMarketStateProposal": "Update market state proposal", + "MarketChange": "Market change", + "MarketStateChange": "Market state change", + "MarketDetails": "Market details", "NewAssetProposal": "New asset proposal", "UpdateAssetProposal": "Update asset proposal", "NewFreeformProposal": "New freeform proposal", "NewRawProposal": "New proposal", + "MARKET_STATE_UPDATE_TYPE_RESUME": "Resume market", + "MARKET_STATE_UPDATE_TYPE_SUSPEND": "Suspend market", + "MARKET_STATE_UPDATE_TYPE_TERMINATE": "Terminate market", "MinProposalRequirements": "You must have at least {{value}} VEGA associated to make a proposal", "MinProposalVoteRequirements": "You must have at least {{value}} VEGA associated to vote on this proposal", "totalSupply": "Total Supply", @@ -721,6 +731,7 @@ "NewMarketFutureProduct": "New market - future", "NewMarketSpotProduct": "New market - spot", "UpdateMarket": "Update market", + "UpdateMarketState": "Update market state", "NewAsset": "New asset", "UpdateAsset": "Update asset", "AssetID": "Asset ID", diff --git a/apps/governance/src/routes/home/index.tsx b/apps/governance/src/routes/home/index.tsx index 253182e85..98ddff74d 100644 --- a/apps/governance/src/routes/home/index.tsx +++ b/apps/governance/src/routes/home/index.tsx @@ -187,6 +187,7 @@ const GovernanceHome = ({ name }: RouteChildProps) => { errorPolicy: 'ignore', variables: { includeNewMarketProductFields: !!FLAGS.PRODUCT_PERPETUALS, + includeUpdateMarketStates: !!FLAGS.UPDATE_MARKET_STATE, }, }); diff --git a/apps/governance/src/routes/proposals/components/proposal-detail-header/proposal-header.tsx b/apps/governance/src/routes/proposals/components/proposal-detail-header/proposal-header.tsx index 017dcce5c..1fb61ccbf 100644 --- a/apps/governance/src/routes/proposals/components/proposal-detail-header/proposal-header.tsx +++ b/apps/governance/src/routes/proposals/components/proposal-detail-header/proposal-header.tsx @@ -63,12 +63,31 @@ export const ProposalHeader = ({ ); break; } + case 'UpdateMarketState': { + proposalType = + FLAGS.UPDATE_MARKET_STATE && change?.updateType + ? t(change.updateType) + : 'UpdateMarketState'; + fallbackTitle = t('UpdateMarketStateProposal'); + details = ( + + {FLAGS.UPDATE_MARKET_STATE && + change?.market?.id && + change.updateType ? ( + <> + {t(change.updateType)}: {truncateMiddle(change.market.id)} + + ) : null} + + ); + break; + } case 'UpdateMarket': { proposalType = 'UpdateMarket'; fallbackTitle = t('UpdateMarketProposal'); details = ( <> - {t('Market change')}:{' '} + {t('MarketChange')}:{' '} {truncateMiddle(change.marketId)} ); diff --git a/apps/governance/src/routes/proposals/components/proposal-update-market-state/index.tsx b/apps/governance/src/routes/proposals/components/proposal-update-market-state/index.tsx new file mode 100644 index 000000000..9e86ea033 --- /dev/null +++ b/apps/governance/src/routes/proposals/components/proposal-update-market-state/index.tsx @@ -0,0 +1 @@ +export * from './proposal-update-market-state'; diff --git a/apps/governance/src/routes/proposals/components/proposal-update-market-state/proposal-update-market-state.spec.tsx b/apps/governance/src/routes/proposals/components/proposal-update-market-state/proposal-update-market-state.spec.tsx new file mode 100644 index 000000000..1222ae9fe --- /dev/null +++ b/apps/governance/src/routes/proposals/components/proposal-update-market-state/proposal-update-market-state.spec.tsx @@ -0,0 +1,123 @@ +import { fireEvent, render, screen } from '@testing-library/react'; +import { ProposalUpdateMarketState } from './proposal-update-market-state'; +import { generateProposal } from '../../test-helpers/generate-proposals'; +import { MarketUpdateType } from '@vegaprotocol/types'; + +describe('', () => { + const suspendProposal = generateProposal({ + terms: { + change: { + __typename: 'UpdateMarketState', + market: { + id: '1', + decimalPlaces: 0, + tradableInstrument: { + instrument: { + name: 'suspendProposal Name', + code: 'suspendProposal Code', + product: { + __typename: 'Future', + quoteName: 'USD', + }, + }, + }, + }, + updateType: MarketUpdateType.MARKET_STATE_UPDATE_TYPE_SUSPEND, + }, + }, + }); + + const resumeProposal = generateProposal({ + terms: { + change: { + __typename: 'UpdateMarketState', + market: { + id: '1', + decimalPlaces: 0, + tradableInstrument: { + instrument: { + name: 'resumeProposal Name', + code: 'resumeProposal Code', + product: { + __typename: 'Future', + quoteName: 'USD', + }, + }, + }, + }, + updateType: MarketUpdateType.MARKET_STATE_UPDATE_TYPE_RESUME, + }, + }, + }); + + const terminateProposal = generateProposal({ + terms: { + change: { + __typename: 'UpdateMarketState', + market: { + id: '1', + decimalPlaces: 0, + tradableInstrument: { + instrument: { + name: 'terminateProposal Name', + code: 'terminateProposal Code', + product: { + __typename: 'Future', + quoteName: 'USD', + }, + }, + }, + }, + updateType: MarketUpdateType.MARKET_STATE_UPDATE_TYPE_TERMINATE, + price: '123', + }, + }, + }); + + it('should render nothing if proposal is null', () => { + render(); + expect(screen.queryByTestId('proposal-update-market-state')).toBeNull(); + }); + + it('should toggle details when CollapsibleToggle is clicked', () => { + render(); + + expect( + screen.queryByTestId('proposal-update-market-state-table') + ).toBeNull(); + + fireEvent.click(screen.getByTestId('proposal-market-data-toggle')); + + expect( + screen.getByTestId('proposal-update-market-state-table') + ).toBeInTheDocument(); + }); + + it('should display suspend market information when showDetails is true', () => { + render(); + + fireEvent.click(screen.getByTestId('proposal-market-data-toggle')); + + expect(screen.getByText('suspendProposal Name')).toBeInTheDocument(); + expect(screen.getByText('suspendProposal Code')).toBeInTheDocument(); + }); + + it('should display resume market information when showDetails is true', () => { + render(); + + fireEvent.click(screen.getByTestId('proposal-market-data-toggle')); + + expect(screen.getByText('resumeProposal Name')).toBeInTheDocument(); + expect(screen.getByText('resumeProposal Code')).toBeInTheDocument(); + }); + + it('should display terminate market information when showDetails is true', () => { + render(); + + fireEvent.click(screen.getByTestId('proposal-market-data-toggle')); + + expect(screen.getByText('terminateProposal Name')).toBeInTheDocument(); + expect(screen.getByText('terminateProposal Code')).toBeInTheDocument(); + expect(screen.getByText('123 USD')).toBeInTheDocument(); + }); +}); diff --git a/apps/governance/src/routes/proposals/components/proposal-update-market-state/proposal-update-market-state.tsx b/apps/governance/src/routes/proposals/components/proposal-update-market-state/proposal-update-market-state.tsx new file mode 100644 index 000000000..4c27ce3ae --- /dev/null +++ b/apps/governance/src/routes/proposals/components/proposal-update-market-state/proposal-update-market-state.tsx @@ -0,0 +1,84 @@ +import { useTranslation } from 'react-i18next'; +import { + KeyValueTable, + KeyValueTableRow, + RoundedWrapper, +} from '@vegaprotocol/ui-toolkit'; +import { Row } from '@vegaprotocol/markets'; +import type { ProposalQuery } from '../../proposal/__generated__/Proposal'; +import { useState } from 'react'; +import { CollapsibleToggle } from '../../../../components/collapsible-toggle'; +import { SubHeading } from '../../../../components/heading'; + +interface ProposalUpdateMarketStateProps { + proposal: ProposalQuery['proposal']; +} + +export const ProposalUpdateMarketState = ({ + proposal, +}: ProposalUpdateMarketStateProps) => { + const { t } = useTranslation(); + const [showDetails, setShowDetails] = useState(false); + let market; + let isTerminate = false; + + if (!proposal) { + return null; + } + + if (proposal?.terms.change.__typename === 'UpdateMarketState') { + market = proposal?.terms?.change?.market; + isTerminate = + proposal?.terms?.change?.updateType === + 'MARKET_STATE_UPDATE_TYPE_TERMINATE'; + } + + return ( +
+ + + + + {showDetails && ( + + {proposal?.terms.change.__typename === 'UpdateMarketState' && ( + + + {t('marketId')} + {market?.id} + + + {t('marketName')} + {market?.tradableInstrument?.instrument?.name} + + + {t('marketCode')} + {market?.tradableInstrument?.instrument?.code} + + {isTerminate && ( + + )} + + )} + + )} +
+ ); +}; diff --git a/apps/governance/src/routes/proposals/components/proposal/proposal.tsx b/apps/governance/src/routes/proposals/components/proposal/proposal.tsx index 9bf1800e7..32df596c5 100644 --- a/apps/governance/src/routes/proposals/components/proposal/proposal.tsx +++ b/apps/governance/src/routes/proposals/components/proposal/proposal.tsx @@ -16,6 +16,7 @@ import type { AssetQuery } from '@vegaprotocol/assets'; import { removePaginationWrapper } from '@vegaprotocol/utils'; import { ProposalState } from '@vegaprotocol/types'; import { ProposalMarketChanges } from '../proposal-market-changes'; +import { ProposalUpdateMarketState } from '../proposal-update-market-state'; import type { NetworkParamsResult } from '@vegaprotocol/network-parameters'; import { useVoteSubmit } from '@vegaprotocol/proposals'; import { useUserVote } from '../vote-details/use-user-vote'; @@ -23,7 +24,7 @@ import { useUserVote } from '../vote-details/use-user-vote'; export interface ProposalProps { proposal: ProposalQuery['proposal']; networkParams: Partial; - newMarketData?: MarketInfo | null; + marketData?: MarketInfo | null; parentMarketData?: MarketInfo | null; assetData?: AssetQuery | null; // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -38,7 +39,7 @@ export const Proposal = ({ proposal, networkParams, restData, - newMarketData, + marketData, parentMarketData, assetData, originalMarketProposalRestData, @@ -73,14 +74,15 @@ export const Proposal = ({ if (networkParams) { switch (proposal.terms.change.__typename) { + case 'UpdateMarket': + case 'UpdateMarketState': + minVoterBalance = + networkParams.governance_proposal_updateMarket_minVoterBalance; + break; case 'NewMarket': minVoterBalance = networkParams.governance_proposal_market_minVoterBalance; break; - case 'UpdateMarket': - minVoterBalance = - networkParams.governance_proposal_updateMarket_minVoterBalance; - break; case 'NewAsset': minVoterBalance = networkParams.governance_proposal_asset_minVoterBalance; @@ -144,15 +146,21 @@ export const Proposal = ({
- {newMarketData && ( + {marketData && (
)} + {proposal.terms.change.__typename === 'UpdateMarketState' && ( +
+ +
+ )} + {proposal.terms.change.__typename === 'UpdateMarket' && (
; -export type ProposalQuery = { __typename?: 'Query', proposal?: { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: any, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string }, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: any, enactmentDatetime?: any | null, change: { __typename?: 'CancelTransfer' } | { __typename?: 'NewAsset', name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string, lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', decimalPlaces: number, metadata?: Array | null, positionDecimalPlaces: number, linearSlippageFactor: string, quadraticSlippageFactor: string, riskParameters: { __typename?: 'LogNormalRiskModel', riskAversionParameter: number, tau: number, params: { __typename?: 'LogNormalModelParams', mu: number, r: number, sigma: number } } | { __typename?: 'SimpleRiskModel', params: { __typename?: 'SimpleRiskModelParams', factorLong: number, factorShort: number } }, instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, name: string, symbol: string, decimals: number, quantum: string }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null }> | null }> | null } | { __typename?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null } | null> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } | null, product?: { __typename: 'FutureProduct' } | { __typename: 'PerpetualProduct' } | { __typename: 'SpotProduct' } | null }, priceMonitoringParameters: { __typename?: 'PriceMonitoringParameters', triggers?: Array<{ __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number }> | null }, liquidityMonitoringParameters: { __typename?: 'LiquidityMonitoringParameters', triggeringRatio: string, targetStakeParameters: { __typename?: 'TargetStakeParameters', timeWindow: number, scalingFactor: number } } } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset', quantum: string, assetId: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string, updateMarketConfiguration: { __typename?: 'UpdateMarketConfiguration', metadata?: Array | null, instrument: { __typename?: 'UpdateInstrumentConfiguration', code: string, product: { __typename?: 'UpdateFutureProduct', quoteName: string, dataSourceSpecForSettlementData: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null }> | null }> | null } | { __typename?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null } | null> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } | { __typename?: 'UpdatePerpetualProduct', quoteName: string, dataSourceSpecForSettlementData: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null }> | null }> | null } | { __typename?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null } | null> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecPerpetualBinding', settlementDataProperty: string, settlementScheduleProperty: string } } }, priceMonitoringParameters: { __typename?: 'PriceMonitoringParameters', triggers?: Array<{ __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number }> | null }, liquidityMonitoringParameters: { __typename?: 'LiquidityMonitoringParameters', triggeringRatio: string, targetStakeParameters: { __typename?: 'TargetStakeParameters', timeWindow: number, scalingFactor: number } }, riskParameters: { __typename?: 'UpdateMarketLogNormalRiskModel', logNormal?: { __typename?: 'LogNormalRiskModel', riskAversionParameter: number, tau: number, params: { __typename?: 'LogNormalModelParams', r: number, sigma: number, mu: number } } | null } | { __typename?: 'UpdateMarketSimpleRiskModel', simple?: { __typename?: 'SimpleRiskModelParams', factorLong: number, factorShort: number } | null } } } | { __typename?: 'UpdateMarketState' } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } | { __typename?: 'UpdateReferralProgram' } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram' } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string } } } | null }; +export type ProposalQuery = { __typename?: 'Query', proposal?: { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: any, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string }, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: any, enactmentDatetime?: any | null, change: { __typename?: 'CancelTransfer' } | { __typename?: 'NewAsset', name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string, lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', decimalPlaces: number, metadata?: Array | null, positionDecimalPlaces: number, linearSlippageFactor: string, quadraticSlippageFactor: string, riskParameters: { __typename?: 'LogNormalRiskModel', riskAversionParameter: number, tau: number, params: { __typename?: 'LogNormalModelParams', mu: number, r: number, sigma: number } } | { __typename?: 'SimpleRiskModel', params: { __typename?: 'SimpleRiskModelParams', factorLong: number, factorShort: number } }, instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, name: string, symbol: string, decimals: number, quantum: string }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null }> | null }> | null } | { __typename?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null } | null> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } | null, product?: { __typename: 'FutureProduct' } | { __typename: 'PerpetualProduct' } | { __typename: 'SpotProduct' } | null }, priceMonitoringParameters: { __typename?: 'PriceMonitoringParameters', triggers?: Array<{ __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number }> | null }, liquidityMonitoringParameters: { __typename?: 'LiquidityMonitoringParameters', triggeringRatio: string, targetStakeParameters: { __typename?: 'TargetStakeParameters', timeWindow: number, scalingFactor: number } } } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset', quantum: string, assetId: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string, updateMarketConfiguration: { __typename?: 'UpdateMarketConfiguration', metadata?: Array | null, instrument: { __typename?: 'UpdateInstrumentConfiguration', code: string, product: { __typename?: 'UpdateFutureProduct', quoteName: string, dataSourceSpecForSettlementData: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null }> | null }> | null } | { __typename?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null } | null> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } | { __typename?: 'UpdatePerpetualProduct', quoteName: string, dataSourceSpecForSettlementData: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null }> | null }> | null } | { __typename?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null } | null> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecPerpetualBinding', settlementDataProperty: string, settlementScheduleProperty: string } } }, priceMonitoringParameters: { __typename?: 'PriceMonitoringParameters', triggers?: Array<{ __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number }> | null }, liquidityMonitoringParameters: { __typename?: 'LiquidityMonitoringParameters', triggeringRatio: string, targetStakeParameters: { __typename?: 'TargetStakeParameters', timeWindow: number, scalingFactor: number } }, riskParameters: { __typename?: 'UpdateMarketLogNormalRiskModel', logNormal?: { __typename?: 'LogNormalRiskModel', riskAversionParameter: number, tau: number, params: { __typename?: 'LogNormalModelParams', r: number, sigma: number, mu: number } } | null } | { __typename?: 'UpdateMarketSimpleRiskModel', simple?: { __typename?: 'SimpleRiskModelParams', factorLong: number, factorShort: number } | null } } } | { __typename?: 'UpdateMarketState', updateType: Types.MarketUpdateType, price?: string | null, market: { __typename?: 'Market', decimalPlaces: number, id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, code: string, product: { __typename: 'Future', quoteName: string } | { __typename: 'Perpetual', quoteName: string } | { __typename: 'Spot' } } } } } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } | { __typename?: 'UpdateReferralProgram' } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram' } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string } } } | null }; export const NewMarketProductFieldFragmentDoc = gql` fragment NewMarketProductField on Proposal { @@ -28,8 +31,40 @@ export const NewMarketProductFieldFragmentDoc = gql` } } `; +export const UpdateMarketStateFragmentDoc = gql` + fragment UpdateMarketState on Proposal { + terms { + change { + ... on UpdateMarketState { + updateType + market { + decimalPlaces + id + tradableInstrument { + instrument { + product { + __typename + ... on Future { + quoteName + } + ... on Perpetual { + quoteName + } + } + name + code + } + } + } + updateType + price + } + } + } +} + `; export const ProposalDocument = gql` - query Proposal($proposalId: ID!, $includeNewMarketProductField: Boolean!) { + query Proposal($proposalId: ID!, $includeNewMarketProductField: Boolean!, $includeUpdateMarketState: Boolean!) { proposal(id: $proposalId) { id rationale { @@ -45,6 +80,7 @@ export const ProposalDocument = gql` } errorDetails ...NewMarketProductField @include(if: $includeNewMarketProductField) + ...UpdateMarketState @include(if: $includeUpdateMarketState) terms { closingDatetime enactmentDatetime @@ -331,7 +367,8 @@ export const ProposalDocument = gql` } } } - ${NewMarketProductFieldFragmentDoc}`; + ${NewMarketProductFieldFragmentDoc} +${UpdateMarketStateFragmentDoc}`; /** * __useProposalQuery__ @@ -347,6 +384,7 @@ export const ProposalDocument = gql` * variables: { * proposalId: // value for 'proposalId' * includeNewMarketProductField: // value for 'includeNewMarketProductField' + * includeUpdateMarketState: // value for 'includeUpdateMarketState' * }, * }); */ diff --git a/apps/governance/src/routes/proposals/proposal/proposal-container.tsx b/apps/governance/src/routes/proposals/proposal/proposal-container.tsx index a097e9d54..214603871 100644 --- a/apps/governance/src/routes/proposals/proposal/proposal-container.tsx +++ b/apps/governance/src/routes/proposals/proposal/proposal-container.tsx @@ -56,6 +56,7 @@ export const ProposalContainer = () => { variables: { proposalId: params.proposalId || '', includeNewMarketProductField: !!FLAGS.PRODUCT_PERPETUALS, + includeUpdateMarketState: !!FLAGS.UPDATE_MARKET_STATE, }, skip: !params.proposalId, }); @@ -94,9 +95,9 @@ export const ProposalContainer = () => { ); const { - data: newMarketData, - loading: newMarketLoading, - error: newMarketError, + data: marketData, + loading: marketLoading, + error: marketError, } = useDataProvider({ dataProvider: marketInfoProvider, skipUpdates: true, @@ -112,9 +113,9 @@ export const ProposalContainer = () => { error: parentMarketIdError, } = useParentMarketIdQuery({ variables: { - marketId: newMarketData?.id || '', + marketId: marketData?.id || '', }, - skip: !FLAGS.SUCCESSOR_MARKETS || !isSuccessor || !newMarketData?.id, + skip: !FLAGS.SUCCESSOR_MARKETS || !isSuccessor || !marketData?.id, }); const { @@ -194,7 +195,7 @@ export const ProposalContainer = () => { { } error={ error || - newMarketError || + marketError || assetError || networkParamsError || parentMarketIdError || @@ -221,7 +222,7 @@ export const ProposalContainer = () => { data={{ ...data, ...networkParams, - ...(newMarketData ? { newMarketData } : {}), + ...(marketData ? { newMarketData: marketData } : {}), ...(parentMarketData ? { parentMarketData } : {}), ...(assetData ? { assetData } : {}), ...(restData ? { restData } : {}), @@ -238,7 +239,7 @@ export const ProposalContainer = () => { proposal={data.proposal} networkParams={networkParams} restData={restData} - newMarketData={newMarketData} + marketData={marketData} parentMarketData={parentMarketData} assetData={assetData} originalMarketProposalRestData={originalMarketProposalRestData} diff --git a/apps/governance/src/routes/proposals/proposals/Proposals.graphql b/apps/governance/src/routes/proposals/proposals/Proposals.graphql index 8b26532ee..3d21f3117 100644 --- a/apps/governance/src/routes/proposals/proposals/Proposals.graphql +++ b/apps/governance/src/routes/proposals/proposals/Proposals.graphql @@ -12,6 +12,37 @@ fragment NewMarketProductFields on Proposal { } } +fragment UpdateMarketStates on Proposal { + terms { + change { + ... on UpdateMarketState { + updateType + market { + decimalPlaces + id + tradableInstrument { + instrument { + product { + __typename + ... on Future { + quoteName + } + ... on Perpetual { + quoteName + } + } + name + code + } + } + } + updateType + price + } + } + } +} + fragment ProposalFields on Proposal { id rationale { @@ -93,12 +124,16 @@ fragment ProposalFields on Proposal { } } -query Proposals($includeNewMarketProductFields: Boolean!) { +query Proposals( + $includeNewMarketProductFields: Boolean! + $includeUpdateMarketStates: Boolean! +) { proposalsConnection { edges { node { ...ProposalFields ...NewMarketProductFields @include(if: $includeNewMarketProductFields) + ...UpdateMarketStates @include(if: $includeUpdateMarketStates) } } } diff --git a/apps/governance/src/routes/proposals/proposals/__generated__/Proposals.ts b/apps/governance/src/routes/proposals/proposals/__generated__/Proposals.ts index f60005df4..a7d13c794 100644 --- a/apps/governance/src/routes/proposals/proposals/__generated__/Proposals.ts +++ b/apps/governance/src/routes/proposals/proposals/__generated__/Proposals.ts @@ -5,14 +5,17 @@ import * as Apollo from '@apollo/client'; const defaultOptions = {} as const; export type NewMarketProductFieldsFragment = { __typename?: 'Proposal', terms: { __typename?: 'ProposalTerms', change: { __typename?: 'CancelTransfer' } | { __typename?: 'NewAsset' } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', product?: { __typename: 'FutureProduct' } | { __typename: 'PerpetualProduct' } | { __typename: 'SpotProduct' } | null } } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset' } | { __typename?: 'UpdateMarket' } | { __typename?: 'UpdateMarketState' } | { __typename?: 'UpdateNetworkParameter' } | { __typename?: 'UpdateReferralProgram' } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram' } } }; +export type UpdateMarketStatesFragment = { __typename?: 'Proposal', terms: { __typename?: 'ProposalTerms', change: { __typename?: 'CancelTransfer' } | { __typename?: 'NewAsset' } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket' } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset' } | { __typename?: 'UpdateMarket' } | { __typename?: 'UpdateMarketState', updateType: Types.MarketUpdateType, price?: string | null, market: { __typename?: 'Market', decimalPlaces: number, id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, code: string, product: { __typename: 'Future', quoteName: string } | { __typename: 'Perpetual', quoteName: string } | { __typename: 'Spot' } } } } } | { __typename?: 'UpdateNetworkParameter' } | { __typename?: 'UpdateReferralProgram' } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram' } } }; + export type ProposalFieldsFragment = { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: any, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string }, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: any, enactmentDatetime?: any | null, change: { __typename?: 'CancelTransfer' } | { __typename: 'NewAsset', name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string, withdrawThreshold: string, lifetimeLimit: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null } } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset', quantum: string, assetId: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateMarketState' } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } | { __typename?: 'UpdateReferralProgram' } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram' } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string } } }; export type ProposalsQueryVariables = Types.Exact<{ includeNewMarketProductFields: Types.Scalars['Boolean']; + includeUpdateMarketStates: Types.Scalars['Boolean']; }>; -export type ProposalsQuery = { __typename?: 'Query', proposalsConnection?: { __typename?: 'ProposalsConnection', edges?: Array<{ __typename?: 'ProposalEdge', node: { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: any, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string }, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: any, enactmentDatetime?: any | null, change: { __typename?: 'CancelTransfer' } | { __typename: 'NewAsset', name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string, withdrawThreshold: string, lifetimeLimit: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null, product?: { __typename: 'FutureProduct' } | { __typename: 'PerpetualProduct' } | { __typename: 'SpotProduct' } | null } } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset', quantum: string, assetId: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateMarketState' } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } | { __typename?: 'UpdateReferralProgram' } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram' } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string } } } } | null> | null } | null }; +export type ProposalsQuery = { __typename?: 'Query', proposalsConnection?: { __typename?: 'ProposalsConnection', edges?: Array<{ __typename?: 'ProposalEdge', node: { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: any, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string }, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: any, enactmentDatetime?: any | null, change: { __typename?: 'CancelTransfer' } | { __typename: 'NewAsset', name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string, withdrawThreshold: string, lifetimeLimit: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null, product?: { __typename: 'FutureProduct' } | { __typename: 'PerpetualProduct' } | { __typename: 'SpotProduct' } | null } } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset', quantum: string, assetId: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateMarketState', updateType: Types.MarketUpdateType, price?: string | null, market: { __typename?: 'Market', decimalPlaces: number, id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, code: string, product: { __typename: 'Future', quoteName: string } | { __typename: 'Perpetual', quoteName: string } | { __typename: 'Spot' } } } } } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } | { __typename?: 'UpdateReferralProgram' } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram' } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string } } } } | null> | null } | null }; export const NewMarketProductFieldsFragmentDoc = gql` fragment NewMarketProductFields on Proposal { @@ -29,6 +32,38 @@ export const NewMarketProductFieldsFragmentDoc = gql` } } `; +export const UpdateMarketStatesFragmentDoc = gql` + fragment UpdateMarketStates on Proposal { + terms { + change { + ... on UpdateMarketState { + updateType + market { + decimalPlaces + id + tradableInstrument { + instrument { + product { + __typename + ... on Future { + quoteName + } + ... on Perpetual { + quoteName + } + } + name + code + } + } + } + updateType + price + } + } + } +} + `; export const ProposalFieldsFragmentDoc = gql` fragment ProposalFields on Proposal { id @@ -112,18 +147,20 @@ export const ProposalFieldsFragmentDoc = gql` } `; export const ProposalsDocument = gql` - query Proposals($includeNewMarketProductFields: Boolean!) { + query Proposals($includeNewMarketProductFields: Boolean!, $includeUpdateMarketStates: Boolean!) { proposalsConnection { edges { node { ...ProposalFields ...NewMarketProductFields @include(if: $includeNewMarketProductFields) + ...UpdateMarketStates @include(if: $includeUpdateMarketStates) } } } } ${ProposalFieldsFragmentDoc} -${NewMarketProductFieldsFragmentDoc}`; +${NewMarketProductFieldsFragmentDoc} +${UpdateMarketStatesFragmentDoc}`; /** * __useProposalsQuery__ @@ -138,6 +175,7 @@ ${NewMarketProductFieldsFragmentDoc}`; * const { data, loading, error } = useProposalsQuery({ * variables: { * includeNewMarketProductFields: // value for 'includeNewMarketProductFields' + * includeUpdateMarketStates: // value for 'includeUpdateMarketStates' * }, * }); */ diff --git a/apps/governance/src/routes/proposals/proposals/proposals-container.tsx b/apps/governance/src/routes/proposals/proposals/proposals-container.tsx index fbc2293e1..8c1e87344 100644 --- a/apps/governance/src/routes/proposals/proposals/proposals-container.tsx +++ b/apps/governance/src/routes/proposals/proposals/proposals-container.tsx @@ -48,6 +48,7 @@ export const ProposalsContainer = () => { errorPolicy: 'ignore', variables: { includeNewMarketProductFields: !!FLAGS.PRODUCT_PERPETUALS, + includeUpdateMarketStates: !!FLAGS.UPDATE_MARKET_STATE, }, }); diff --git a/apps/governance/src/routes/proposals/rejected/rejected-proposals-container.tsx b/apps/governance/src/routes/proposals/rejected/rejected-proposals-container.tsx index 784131261..246c8cdf3 100644 --- a/apps/governance/src/routes/proposals/rejected/rejected-proposals-container.tsx +++ b/apps/governance/src/routes/proposals/rejected/rejected-proposals-container.tsx @@ -40,6 +40,7 @@ export const RejectedProposalsContainer = () => { errorPolicy: 'ignore', variables: { includeNewMarketProductFields: !!FLAGS.PRODUCT_PERPETUALS, + includeUpdateMarketStates: !!FLAGS.UPDATE_MARKET_STATE, }, }); diff --git a/libs/environment/src/hooks/use-environment.ts b/libs/environment/src/hooks/use-environment.ts index b7ad4b9ec..0c0b3689f 100644 --- a/libs/environment/src/hooks/use-environment.ts +++ b/libs/environment/src/hooks/use-environment.ts @@ -417,6 +417,12 @@ function compileFeatureFlags(): FeatureFlags { REFERRALS: TRUTHY.includes( windowOrDefault('NX_REFERRALS', process.env['NX_REFERRALS']) as string ), + UPDATE_MARKET_STATE: TRUTHY.includes( + windowOrDefault( + 'NX_UPDATE_MARKET_STATE', + process.env['NX_UPDATE_MARKET_STATE'] + ) as string + ), }; const EXPLORER_FLAGS = { EXPLORER_ASSETS: TRUTHY.includes( diff --git a/libs/environment/src/types.ts b/libs/environment/src/types.ts index 345871484..fa5219c4a 100644 --- a/libs/environment/src/types.ts +++ b/libs/environment/src/types.ts @@ -24,6 +24,7 @@ export type CosmicElevatorFlags = Pick< | 'PRODUCT_PERPETUALS' | 'METAMASK_SNAPS' | 'REFERRALS' + | 'UPDATE_MARKET_STATE' >; export type Configuration = z.infer; export const CUSTOM_NODE_KEY = 'custom' as const; diff --git a/libs/environment/src/utils/validate-environment.ts b/libs/environment/src/utils/validate-environment.ts index 5079869ad..059d66156 100644 --- a/libs/environment/src/utils/validate-environment.ts +++ b/libs/environment/src/utils/validate-environment.ts @@ -79,6 +79,7 @@ const COSMIC_ELEVATOR_FLAGS = { PRODUCT_PERPETUALS: z.optional(z.boolean()), METAMASK_SNAPS: z.optional(z.boolean()), REFERRALS: z.optional(z.boolean()), + UPDATE_MARKET_STATE: z.optional(z.boolean()), }; const EXPLORER_FLAGS = { diff --git a/libs/markets/src/lib/components/market-info/__generated__/MarketInfo.ts b/libs/markets/src/lib/components/market-info/__generated__/MarketInfo.ts index a8586bebb..120243f9b 100644 --- a/libs/markets/src/lib/components/market-info/__generated__/MarketInfo.ts +++ b/libs/markets/src/lib/components/market-info/__generated__/MarketInfo.ts @@ -261,4 +261,4 @@ export function useMarketInfoLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions } export type MarketInfoQueryHookResult = ReturnType; export type MarketInfoLazyQueryHookResult = ReturnType; -export type MarketInfoQueryResult = Apollo.QueryResult; +export type MarketInfoQueryResult = Apollo.QueryResult; \ No newline at end of file