diff --git a/apps/governance-e2e/src/integration/flow/proposal-enacted.cy.ts b/apps/governance-e2e/src/integration/flow/proposal-enacted.cy.ts index cef760963..f04a7ee52 100644 --- a/apps/governance-e2e/src/integration/flow/proposal-enacted.cy.ts +++ b/apps/governance-e2e/src/integration/flow/proposal-enacted.cy.ts @@ -89,8 +89,14 @@ context( }); cy.get(proposalStatus).should('have.text', 'Open'); voteForProposal('for'); - cy.get(proposalStatus, proposalTimeout).should('have.text', 'Passed'); - cy.get(proposalStatus, proposalTimeout).should('have.text', 'Enacted'); + cy.get(proposalStatus, proposalTimeout) + .should('have.text', 'Passed') + .then(() => { + cy.get(proposalStatus, proposalTimeout).should( + 'have.text', + 'Enacted' + ); + }); cy.get(votesTable).within(() => { cy.contains('Vote passed.').should('be.visible'); cy.contains('Voting has ended.').should('be.visible'); diff --git a/apps/governance-e2e/src/integration/flow/proposal-flow.cy.ts b/apps/governance-e2e/src/integration/flow/proposal-flow.cy.ts index 96fb285ed..57d205b2b 100644 --- a/apps/governance-e2e/src/integration/flow/proposal-flow.cy.ts +++ b/apps/governance-e2e/src/integration/flow/proposal-flow.cy.ts @@ -130,7 +130,7 @@ context( createRawProposal(); }); - it.skip('Creating a proposal - proposal rejected - when closing time sooner than system default', function () { + it('Creating a proposal - proposal rejected - when closing time sooner than system default', function () { goToMakeNewProposal(governanceProposalType.FREEFORM); enterUniqueFreeFormProposalBody('0.1', generateFreeFormProposalTitle()); cy.get('input:invalid') @@ -138,7 +138,7 @@ context( .should('equal', 'Value must be greater than or equal to 1.'); }); - it.skip('Creating a proposal - proposal rejected - when closing time later than system default', function () { + it('Creating a proposal - proposal rejected - when closing time later than system default', function () { goToMakeNewProposal(governanceProposalType.FREEFORM); enterUniqueFreeFormProposalBody( '100000', diff --git a/apps/governance-e2e/src/integration/flow/proposal-forms.cy.ts b/apps/governance-e2e/src/integration/flow/proposal-forms.cy.ts index c48ee0500..d6c7209b2 100644 --- a/apps/governance-e2e/src/integration/flow/proposal-forms.cy.ts +++ b/apps/governance-e2e/src/integration/flow/proposal-forms.cy.ts @@ -8,6 +8,7 @@ import { } from '../../support/common.functions'; import { getDownloadedProposalJsonPath, + getProposalFromTitle, submitUniqueRawProposal, } from '../../support/governance.functions'; import { @@ -55,7 +56,8 @@ const feedbackError = '[data-testid="Error"]'; const viewProposalBtn = 'view-proposal-btn'; const liquidityVoteStatus = 'liquidity-votes-status'; const tokenVoteStatus = 'token-votes-status'; -const proposalTermsSection = 'proposal'; +const proposalJsonToggle = 'proposal-json-toggle'; +const proposalJsonSection = 'proposal-json'; const vegaWalletPublicKey = Cypress.env('vegaWalletPublicKey'); const fUSDCId = '816af99af60d684502a40824758f6b5377e6af48e50a9ee8ef478ecb879ea8bc'; @@ -186,7 +188,7 @@ context( cy.get(maxVoteDeadline).click(); cy.get(enactmentDeadlineError).should( 'have.text', - 'Proposal will fail if enactment is earlier than the voting deadline' + 'The proposal will fail if enactment is earlier than the voting deadline' ); cy.get(proposalDownloadBtn) .should('be.visible') @@ -210,6 +212,7 @@ context( 'Able to submit valid new market proposal', { tags: '@smoke' }, function () { + const proposalTitle = 'Test new market proposal'; goToMakeNewProposal(governanceProposalType.NEW_MARKET); cy.get(newProposalTitle).type('Test new market proposal'); cy.get(newProposalDescription).type('E2E test for proposals'); @@ -231,6 +234,23 @@ context( submitUniqueRawProposal({ proposalBody: filePath }); // 3003-PMAN-003 }); }); + navigateTo(navigation.proposals); + getProposalFromTitle(proposalTitle).within(() => + cy.getByTestId('view-proposal-btn').click() + ); + cy.getByTestId('proposal-market-data').within(() => { + cy.getByTestId('proposal-market-data-toggle').click(); + cy.contains('Key details').click(); + getMarketProposalDetailsFromTable('Name').should( + 'have.text', + 'Token test market' + ); + cy.contains('Settlement asset').click(); + // Settlement asset symbol + cy.getByTestId('3_value').should('have.text', 'fBTC'); + cy.contains('Oracle').click(); + cy.getByTestId('oracle-spec-links').should('have.attr', 'href'); + }); } ); @@ -454,8 +474,8 @@ context( .within(() => { cy.getByTestId(viewProposalBtn).click(); }); - cy.getByTestId('proposal-terms-toggle').click(); - cy.getByTestId(proposalTermsSection).within(() => { + cy.getByTestId(proposalJsonToggle).click(); + cy.getByTestId(proposalJsonSection).within(() => { cy.contains('USDT Coin').should('be.visible'); cy.contains('USDT').should('be.visible'); }); @@ -501,13 +521,11 @@ context( .invoke('text') .should('not.be.empty'); // 3001-VOTE-030 3001-VOTE-031 - cy.getByTestId('proposal-terms-toggle').click(); - cy.getByTestId('proposal-terms').within(() => { - getProposalInformationFromTable('assetId').should('have.text', assetId); - getProposalInformationFromTable('lifetimeLimit').should( - 'have.text', - '10' - ); + cy.getByTestId(proposalJsonToggle).click(); + cy.getByTestId(proposalJsonSection).within(() => { + cy.contains(assetId).should('be.visible'); + cy.contains('lifetimeLimit').should('be.visible'); + cy.contains('10').should('be.visible'); }); }); @@ -605,5 +623,13 @@ context( }); }); } + + function getMarketProposalDetailsFromTable(heading: string) { + return cy + .getByTestId('key-value-table-row') + .contains(heading) + .parent() + .siblings(); + } } ); diff --git a/apps/governance-e2e/src/integration/view/validators.cy.ts b/apps/governance-e2e/src/integration/view/validators.cy.ts index 10d400bcc..25dcabd14 100644 --- a/apps/governance-e2e/src/integration/view/validators.cy.ts +++ b/apps/governance-e2e/src/integration/view/validators.cy.ts @@ -30,7 +30,6 @@ const normalisedVotingPowerToolTip = '[data-testid="normalised-voting-power-tooltip"]'; const performancePenaltyToolTip = '[data-testid="performance-penalty-tooltip"]'; const overstakedPenaltyToolTip = '[data-testid="overstaked-penalty-tooltip"]'; -const totalPenaltyToolTip = '[data-testid="total-penalty-tooltip"]'; const epochCountDown = '[data-testid="epoch-countdown"]'; const stakeNumberRegex = /^\d{1,3}(,\d{3})*(\.\d+)?$/; @@ -143,9 +142,6 @@ context('Validators Page - verify elements on page', function () { cy.get(overstakedPenaltyToolTip) .invoke('text') .should('contain', 'Overstaked penalty: 60.00%'); // value not asserted due to #2886 - cy.get(totalPenaltyToolTip) - .invoke('text') - .should('contain', 'Total penalties: 60.00%'); }); it('Should be able to see validator pending stake', function () { diff --git a/apps/governance-e2e/src/integration/view/wallet-vega.cy.ts b/apps/governance-e2e/src/integration/view/wallet-vega.cy.ts index d97e0e336..1a67a6472 100644 --- a/apps/governance-e2e/src/integration/view/wallet-vega.cy.ts +++ b/apps/governance-e2e/src/integration/view/wallet-vega.cy.ts @@ -282,13 +282,6 @@ context( // 2002-SINC-016 describe('Vega wallet with assets', function () { const assets = [ - { - id: '816af99af60d684502a40824758f6b5377e6af48e50a9ee8ef478ecb879ea8bc', - name: 'USDC (fake)', - symbol: 'fUSDC', - amount: '1000000', - expectedAmount: '10.00', - }, { id: '8566db7257222b5b7ef2886394ad28b938b28680a54a169bbc795027b89d6665', name: 'DAI (fake)', @@ -310,6 +303,13 @@ context( amount: '800000', expectedAmount: '8.00', }, + { + id: '816af99af60d684502a40824758f6b5377e6af48e50a9ee8ef478ecb879ea8bc', + name: 'USDC (fake)', + symbol: 'fUSDC', + amount: '1000000', + expectedAmount: '10.00', + }, ]; before('faucet assets to connected vega wallet', function () { diff --git a/apps/governance/src/i18n/translations/dev.json b/apps/governance/src/i18n/translations/dev.json index bea86da3a..35fde09f9 100644 --- a/apps/governance/src/i18n/translations/dev.json +++ b/apps/governance/src/i18n/translations/dev.json @@ -786,6 +786,7 @@ "performancePenalty": "Performance penalty", "overstaked": "Overstaked", "overstakedPenalty": "Overstaked penalty", + "multisigPenalty": "Multisig penalty", "homeProposalsIntro": "Decisions on the Vega network are on-chain, with tokenholders creating proposals that other tokenholders vote to approve or reject. Network upgrades are proposed and approved by validators.", "homeProposalsButtonText": "Browse, vote, and propose", "homeValidatorsIntro": "Vega runs on a delegated proof of stake blockchain, where validators earn fees for validating block transactions. Tokenholders can nominate validators by staking tokens to them.", diff --git a/apps/governance/src/routes/staking/home/validator-tables/consensus-validators-table.tsx b/apps/governance/src/routes/staking/home/validator-tables/consensus-validators-table.tsx index 36b031e9e..ef55dca05 100644 --- a/apps/governance/src/routes/staking/home/validator-tables/consensus-validators-table.tsx +++ b/apps/governance/src/routes/staking/home/validator-tables/consensus-validators-table.tsx @@ -36,6 +36,7 @@ import { toBigNum, } from '@vegaprotocol/utils'; import { VALIDATOR_LOGO_MAP } from './logo-map'; +import { getMultisigStatusInfo } from '../../../../lib/get-multisig-status-info'; interface CanonisedConsensusNodeProps { id: string; @@ -137,6 +138,10 @@ export const ConsensusValidatorsTable = ({ [totalStake] ); + const multisigStatus = previousEpochData + ? getMultisigStatusInfo(previousEpochData) + : undefined; + const allNodesInPreviousEpoch = removePaginationWrapper( previousEpochData?.epoch.validatorsConnection?.edges ); @@ -223,6 +228,8 @@ export const ConsensusValidatorsTable = ({ [ValidatorFields.USER_STAKE_SHARE]: userStakeShare ? formatNumberPercentage(new BigNumber(userStakeShare), 2) : undefined, + [ValidatorFields.MULTISIG_ERROR]: + multisigStatus?.showMultisigStatusError, }; } ); @@ -332,6 +339,7 @@ export const ConsensusValidatorsTable = ({ data, decimals, hideTopThird, + multisigStatus?.showMultisigStatusError, previousEpochData, thirdOfTotalStake, validatorsView, diff --git a/apps/governance/src/routes/staking/home/validator-tables/shared.tsx b/apps/governance/src/routes/staking/home/validator-tables/shared.tsx index c21ab8b6e..1abc3f8d3 100644 --- a/apps/governance/src/routes/staking/home/validator-tables/shared.tsx +++ b/apps/governance/src/routes/staking/home/validator-tables/shared.tsx @@ -39,6 +39,7 @@ export enum ValidatorFields { STAKED_BY_USER = 'stakedByUser', PENDING_USER_STAKE = 'pendingUserStake', USER_STAKE_SHARE = 'userStakeShare', + MULTISIG_ERROR = 'multisigError', } export const addUserDataToValidator = ( @@ -326,6 +327,7 @@ interface TotalPenaltiesRendererProps { overstakedAmount: string; overstakingPenalty: string; totalPenalties: string; + multisigError?: boolean; }; } @@ -344,10 +346,11 @@ export const TotalPenaltiesRenderer = ({
{t('overstakedPenalty')}: {data.overstakingPenalty}
-
- {t('totalPenalties')}:{' '} - {data.totalPenalties} -
+ {data.multisigError && ( +
+ {t('multisigPenalty')}: 100% +
+ )} } > diff --git a/libs/cypress/src/lib/capsule/submit-proposal.ts b/libs/cypress/src/lib/capsule/submit-proposal.ts new file mode 100644 index 000000000..e93324aef --- /dev/null +++ b/libs/cypress/src/lib/capsule/submit-proposal.ts @@ -0,0 +1,11 @@ +import type { ProposalSubmissionBody } from '@vegaprotocol/wallet'; +import { sendVegaTx } from './wallet-client'; +import { waitForProposal } from './propose-market'; +import { determineId } from '../utils'; +const vegaPubKey = Cypress.env('VEGA_PUBLIC_KEY'); + +export async function submitProposal(proposalTx: ProposalSubmissionBody) { + cy.highlight('Submitting proposal'); + const result = await sendVegaTx(vegaPubKey, proposalTx); + await waitForProposal(determineId(result.result.transaction.signature.value)); +} diff --git a/libs/cypress/src/lib/commands/vega-wallet-submit-proposal.ts b/libs/cypress/src/lib/commands/vega-wallet-submit-proposal.ts index 8ebf69a38..6fcf5e9a1 100644 --- a/libs/cypress/src/lib/commands/vega-wallet-submit-proposal.ts +++ b/libs/cypress/src/lib/commands/vega-wallet-submit-proposal.ts @@ -1,5 +1,6 @@ -import { createWalletClient, sendVegaTx } from '../capsule/wallet-client'; +import { createWalletClient } from '../capsule/wallet-client'; import type { ProposalSubmissionBody } from '@vegaprotocol/wallet'; +import { submitProposal } from '../capsule/submit-proposal'; declare global { // eslint-disable-next-line @typescript-eslint/no-namespace @@ -15,11 +16,8 @@ export const addVegaWalletSubmitProposal = () => { Cypress.Commands.add('VegaWalletSubmitProposal', (proposalTx) => { const vegaWalletUrl = Cypress.env('VEGA_WALLET_URL'); const token = Cypress.env('VEGA_WALLET_API_TOKEN'); - const vegaPubKey = Cypress.env('VEGA_PUBLIC_KEY'); createWalletClient(vegaWalletUrl, token); - - cy.highlight('Submitting proposal'); - sendVegaTx(vegaPubKey, proposalTx); + cy.wrap(submitProposal(proposalTx)); }); }; diff --git a/libs/ui-toolkit/package.json b/libs/ui-toolkit/package.json index c1ff2b802..c601eac1f 100644 --- a/libs/ui-toolkit/package.json +++ b/libs/ui-toolkit/package.json @@ -1,4 +1,4 @@ { "name": "@vegaprotocol/ui-toolkit", - "version": "0.12.4" + "version": "0.12.5" } diff --git a/libs/ui-toolkit/src/components/healthbar/healthbar.tsx b/libs/ui-toolkit/src/components/healthbar/healthbar.tsx index 2c1d17686..6ac590b35 100644 --- a/libs/ui-toolkit/src/components/healthbar/healthbar.tsx +++ b/libs/ui-toolkit/src/components/healthbar/healthbar.tsx @@ -82,12 +82,12 @@ const Level = ({ : '-'; const tooltipContent = ( - <> +
- {formattedFee}% {t('Fee')} + {formattedFee} {t('Fee')}
@@ -95,7 +95,7 @@ const Level = ({ {addDecimalsFormatNumber(commitmentAmount, decimals)}
- +
); return ( diff --git a/libs/ui-toolkit/src/components/tooltip/tooltip.tsx b/libs/ui-toolkit/src/components/tooltip/tooltip.tsx index f5c39bca5..7884b9d34 100644 --- a/libs/ui-toolkit/src/components/tooltip/tooltip.tsx +++ b/libs/ui-toolkit/src/components/tooltip/tooltip.tsx @@ -10,7 +10,7 @@ import { import type { ITooltipParams } from 'ag-grid-community'; const tooltipContentClasses = - 'max-w-sm bg-vega-light-100 dark:bg-vega-dark-100 border border-vega-light-200 dark:border-vega-dark-200 px-2 py-1 z-20 rounded text-xs break-word'; + 'max-w-sm bg-vega-light-100 dark:bg-vega-dark-100 border border-vega-light-200 dark:border-vega-dark-200 px-2 py-1 z-20 rounded text-xs text-black dark:text-white break-word'; export interface TooltipProps { children: React.ReactElement; description?: string | ReactNode;