diff --git a/.github/workflows/capsule-cypress.yml b/.github/workflows/capsule-cypress.yml index f60584ae9..0414d9258 100644 --- a/.github/workflows/capsule-cypress.yml +++ b/.github/workflows/capsule-cypress.yml @@ -38,6 +38,14 @@ jobs: ## Checkout capsule ####### + # Checkout front ends + - name: Checkout frontend mono repo + uses: actions/checkout@v2 + with: + ref: ${{ github.event.pull_request.head.ref }} + fetch-depth: 0 + path: './frontend-monorepo' + # Checkout capsule to build local network - name: Checkout capsule uses: actions/checkout@v2 @@ -87,7 +95,7 @@ jobs: run: vegacapsule nomad & - name: Bootstrap network - run: vegacapsule network bootstrap --config-path=./net_confs/config.hcl --force + run: vegacapsule network bootstrap --config-path=../frontend-monorepo/vegacapsule/config.hcl --force working-directory: capsule ###### @@ -111,23 +119,19 @@ jobs: ## Run some tests ###### - # Checkout front ends - - name: Checkout frontend mono repo - uses: actions/checkout@v2 - with: - ref: ${{ github.event.pull_request.head.ref }} - fetch-depth: 0 - - name: Derive appropriate SHAs for base and head for `nx affected` commands uses: nrwl/nx-set-shas@v2 with: + working-directory: frontend-monorepo main-branch-name: master - name: Install root dependencies run: yarn install + working-directory: frontend-monorepo - name: Run Cypress tests run: npx nx affected:e2e --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome + working-directory: frontend-monorepo env: CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }} CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }} diff --git a/apps/token-e2e/src/fixtures/proposals/asset.json b/apps/token-e2e/src/fixtures/proposals/asset.json new file mode 100644 index 000000000..6ea2d69b3 --- /dev/null +++ b/apps/token-e2e/src/fixtures/proposals/asset.json @@ -0,0 +1,21 @@ +{ + "rationale": { + "title": "Add USDT Coin (USDT)", + "description": "Proposal to add USDT Coin (USDT) as an asset" + }, + "terms": { + "newAsset": { + "changes": { + "name": "USDT Coin", + "symbol": "USDT", + "decimals": "18", + "quantum": "1", + "erc20": { + "contractAddress": "0xb404c51bbc10dcbe948077f18a4b8e553d160084" + } + } + }, + "closingTimestamp": 1662374250, + "enactmentTimestamp": 1662460650 + } +} diff --git a/apps/token-e2e/src/fixtures/proposals/freeform.json b/apps/token-e2e/src/fixtures/proposals/freeform.json index c3eddfe9b..e3726769f 100644 --- a/apps/token-e2e/src/fixtures/proposals/freeform.json +++ b/apps/token-e2e/src/fixtures/proposals/freeform.json @@ -1,11 +1,10 @@ { "rationale": { - "url": "https://dweb.link/ipfs/bafybeigwwctpv37xdcwacqxvekr6e4kaemqsrv34em6glkbiceo3fcy4si", - "hash": "bafybeigwwctpv37xdcwacqxvekr6e4kaemqsrv34em6glkbiceo3fcy4si", - "description": "Freeform Proposal with unique id of: " + "title": "An example freeform proposal", + "description": "I propose that everyone evaluate the following IPFS document and vote Yes if they agree. [bafybeigwwctpv37xdcwacqxvekr6e4kaemqsrv34em6glkbiceo3fcy4si](https://dweb.link/ipfs/bafybeigwwctpv37xdcwacqxvekr6e4kaemqsrv34em6glkbiceo3fcy4si)" }, "terms": { "newFreeform": {}, - "closingTimestamp": 1657721401 + "closingTimestamp": 1662374250 } } diff --git a/apps/token-e2e/src/integration/flow/governance-flow.cy.js b/apps/token-e2e/src/integration/flow/governance-flow.cy.js index 7fa17179a..37319f0ac 100644 --- a/apps/token-e2e/src/integration/flow/governance-flow.cy.js +++ b/apps/token-e2e/src/integration/flow/governance-flow.cy.js @@ -1,4 +1,9 @@ /// + +const vegaWalletUnstakedBalance = + '[data-testid="vega-wallet-balance-unstaked"]'; +const vegaWalletStakedBalances = + '[data-testid="vega-wallet-balance-staked-validators"]'; const newProposalButton = '[data-testid="new-proposal-link"]'; const newProposalDatabox = '[data-testid="proposal-data"]'; const newProposalSubmitButton = '[data-testid="proposal-submit"]'; @@ -7,8 +12,22 @@ const viewProposalButton = '[data-testid="view-proposal-btn"]'; const proposalInformationTableRows = '[data-testid="key-value-table-row"]'; const openProposals = '[data-testid="open-proposals"]'; const vegaWalletAssociatedBalance = '[data-testid="currency-value"]'; -const proposalResponseIdPath = 'response.body.data.busEvents.0.event.id'; +const proposalResponseProposalIdPath = + 'response.body.data.busEvents.0.event.id'; +const proposalVoteProgressForPercentage = + '[data-testid="vote-progress-indicator-percentage-for"]'; +const proposalVoteProgressAgainstPercentage = + '[data-testid="vote-progress-indicator-percentage-against"]'; +const proposalVoteProgressForTokens = + '[data-testid="vote-progress-indicator-tokens-for"]'; +const proposalVoteProgressAgainstTokens = + '[data-testid="vote-progress-indicator-tokens-against"]'; +const changeVoteButton = '[data-testid="change-vote-button"]'; +const voteButtons = '[data-testid="vote-buttons"]'; +const rejectProposalsLink = '[href="/governance/rejected"]'; +const feedbackError = '[data-testid="Error"]'; const txTimeout = Cypress.env('txTimeout'); +const epochTimeout = Cypress.env('epochTimeout'); context('Governance flow - with eth and vega wallets connected', function () { before('connect wallets and set approval limit', function () { @@ -19,6 +38,18 @@ context('Governance flow - with eth and vega wallets connected', function () { cy.wrap( network_parameters['governance.proposal.freeform.minProposerBalance'] ).as('minProposerBalance'); + cy.wrap( + network_parameters['governance.proposal.freeform.minVoterBalance'] + ).as('minVoterBalance'); + cy.wrap( + network_parameters['governance.proposal.freeform.requiredMajority'] * + 100 + ).as('requiredMajority'); + cy.wrap( + network_parameters[ + 'governance.proposal.freeform.requiredParticipation' + ] * 100 + ).as('requiredParticipation'); cy.wrap( network_parameters['governance.proposal.freeform.minClose'].split( 'h' @@ -33,11 +64,43 @@ context('Governance flow - with eth and vega wallets connected', function () { cy.vega_wallet_connect(); cy.vega_wallet_set_specified_approval_amount('1000'); cy.reload(); + cy.wait_for_spinner(); cy.verify_page_header('The $VEGA token'); cy.ethereum_wallet_connect(); }); describe('Eth wallet - contains VEGA tokens', function () { + before( + 'checking network parameters (therefore environment) is fit for test', + function () { + assert.isAtLeast( + parseInt(this.minProposerBalance), + 0.00001, + 'Asserting that value is at least 0.00001 for network parameter minProposerBalance' + ); + assert.isAtLeast( + parseInt(this.minVoterBalance), + 0.00001, + 'Asserting that value is at least 0.00001 for network parameter minVoterBalance' + ); + assert.isAtLeast( + parseFloat(this.requiredParticipation), + 0.00001, + 'Asserting that value is at least 0.00001 for network parameter requiredParticipation' + ); + assert.isAtLeast( + parseInt(this.minCloseDays), + 1, + 'Asserting that value is at least 1 for network parameter minCloseDays' + ); + assert.isAtLeast( + parseInt(this.maxCloseDays), + parseInt(this.minCloseDays + 1), + 'Asserting that network parameter maxCloseDays is at least 1 day higher than minCloseDays' + ); + } + ); + beforeEach('visit staking tab', function () { cy.navigate_to('staking'); cy.wait_for_spinner(); @@ -48,24 +111,133 @@ context('Governance flow - with eth and vega wallets connected', function () { }); }); - it('Able to submit a valid freeform proposal - with minimum tokens associated', function () { + it('Able to submit a valid freeform proposal - with minimum required tokens associated', function () { cy.ensure_specified_unstaked_tokens_are_associated( this.minProposerBalance ); cy.navigate_to('governance'); cy.wait_for_spinner(); cy.get(newProposalButton).should('be.visible').click(); - cy.get(newProposalDatabox).click(); cy.create_ten_digit_unix_timestamp_for_specified_days('7').then( (closingDateTimestamp) => { cy.enter_unique_freeform_proposal_body(closingDateTimestamp); } ); cy.get(newProposalSubmitButton).should('be.visible').click(); - cy.contains('Proposal submitted').should('be.visible'); + cy.contains('Confirm transaction in wallet', epochTimeout).should( + 'be.visible' + ); + cy.contains('Awaiting network confirmation', epochTimeout).should( + 'be.visible' + ); + cy.contains('Proposal submitted', epochTimeout).should('be.visible'); cy.get(dialogCloseButton).click(); }); + it('Able to submit a valid freeform proposal - with minimum required tokens associated - but also staked', function () { + cy.ensure_specified_unstaked_tokens_are_associated( + this.minProposerBalance + ); + cy.get(vegaWalletUnstakedBalance, txTimeout).should( + 'contain', + this.minProposerBalance, + txTimeout + ); + cy.navigate_to('staking'); + cy.wait_for_spinner(); + cy.click_on_validator_from_list(0); + cy.staking_validator_page_add_stake(this.minProposerBalance); + + cy.get(vegaWalletStakedBalances, txTimeout).should( + 'contain', + this.minProposerBalance, + txTimeout + ); + + cy.navigate_to('governance'); + cy.wait_for_spinner(); + cy.get(newProposalButton).should('be.visible').click(); + cy.create_ten_digit_unix_timestamp_for_specified_days('7').then( + (closingDateTimestamp) => { + cy.enter_unique_freeform_proposal_body(closingDateTimestamp); + } + ); + cy.get(newProposalSubmitButton).should('be.visible').click(); + cy.contains('Awaiting network confirmation', epochTimeout).should( + 'be.visible' + ); + cy.contains('Proposal submitted', epochTimeout).should('be.visible'); + cy.get(dialogCloseButton).click(); + }); + + it('Newly created freeform proposal - able to filter by proposalID to show it in list', function () { + cy.ensure_specified_unstaked_tokens_are_associated( + this.minProposerBalance + ); + cy.navigate_to('governance'); + cy.wait_for_spinner(); + cy.get(newProposalButton).should('be.visible').click(); + cy.create_ten_digit_unix_timestamp_for_specified_days('7').then( + (closingDateTimestamp) => { + cy.enter_unique_freeform_proposal_body(closingDateTimestamp); + } + ); + cy.get(newProposalSubmitButton).should('be.visible').click(); + cy.contains('Awaiting network confirmation', epochTimeout).should( + 'be.visible' + ); + cy.contains('Proposal submitted', epochTimeout).should('be.visible'); + cy.get(dialogCloseButton).click(); + cy.wait_for_proposal_sync(); + cy.navigate_to('governance'); + cy.wait_for_spinner(); + cy.wait('@proposalSubmissionCompletion') + .its(proposalResponseProposalIdPath) + .then((proposalId) => { + cy.get('[data-testid="set-proposals-filter-visible"]').click(); + cy.get('[data-testid="filter-input"]').type(proposalId); + cy.get(`#${proposalId}`).should( + 'contain', + `Freeform proposal: ${proposalId}`, + txTimeout + ); + }); + }); + + it('Newly created freeform proposal - able to filter by proposerID to show it in list', function () { + cy.ensure_specified_unstaked_tokens_are_associated( + this.minProposerBalance + ); + cy.navigate_to('governance'); + cy.wait_for_spinner(); + cy.get(newProposalButton).should('be.visible').click(); + cy.create_ten_digit_unix_timestamp_for_specified_days('7').then( + (closingDateTimestamp) => { + cy.enter_unique_freeform_proposal_body(closingDateTimestamp); + } + ); + cy.get(newProposalSubmitButton).should('be.visible').click(); + cy.contains('Awaiting network confirmation', epochTimeout).should( + 'be.visible' + ); + cy.contains('Proposal submitted', epochTimeout).should('be.visible'); + cy.get(dialogCloseButton).click(); + cy.wait_for_proposal_sync(); + cy.navigate_to('governance'); + cy.wait_for_spinner(); + cy.wait('@proposalSubmissionCompletion').then((proposal) => { + let proposerId = proposal.request.body.variables.partyId; + let proposalId = proposal.response.body.data.busEvents[0].event.id; + cy.get('[data-testid="set-proposals-filter-visible"]').click(); + cy.get('[data-testid="filter-input"]').type(proposerId); + cy.get(`#${proposalId}`).should( + 'contain', + `Freeform proposal: ${proposalId}`, + txTimeout + ); + }); + }); + it('Newly created freeform proposal - shows in an open state', function () { cy.ensure_specified_unstaked_tokens_are_associated( this.minProposerBalance @@ -73,43 +245,41 @@ context('Governance flow - with eth and vega wallets connected', function () { cy.navigate_to('governance'); cy.wait_for_spinner(); cy.get(newProposalButton).should('be.visible').click(); - cy.get(newProposalDatabox).click(); cy.create_ten_digit_unix_timestamp_for_specified_days('8').then( (closingDateTimestamp) => { cy.enter_unique_freeform_proposal_body(closingDateTimestamp); } ); cy.get(newProposalSubmitButton).should('be.visible').click(); - cy.contains('Proposal submitted').should('be.visible'); + cy.contains('Awaiting network confirmation', epochTimeout).should( + 'be.visible' + ); + cy.contains('Proposal submitted', epochTimeout).should('be.visible'); cy.get(dialogCloseButton).click(); + cy.wait_for_proposal_sync(); + cy.navigate_to('governance'); + cy.wait_for_spinner(); cy.wait('@proposalSubmissionCompletion') - .its(proposalResponseIdPath) + .its(proposalResponseProposalIdPath) .then((proposalId) => { - cy.navigate_to('governance'); - cy.wait_for_spinner(); cy.get(openProposals).within(() => { cy.get(`#${proposalId}`) - .should('contain', `Freeform proposal: ${proposalId}`) + .should('contain', `Freeform proposal: ${proposalId}`, txTimeout) .and('contain', 'Open') .and('be.visible') .within(() => { cy.get(viewProposalButton).should('be.visible').click(); }); }); - cy.get(proposalInformationTableRows) - .contains('ID') - .siblings() + cy.get_proposal_information_from_table('ID') .contains(proposalId) - .should('be.visible'); - cy.get(proposalInformationTableRows) - .contains('State') - .siblings() - .contains('Open') - .should('be.visible'); - cy.get(proposalInformationTableRows) - .contains('Type') - .siblings() - .contains('NewFreeform'); + .and('be.visible'); + cy.get_proposal_information_from_table('State') + .contains('STATE_OPEN') + .and('be.visible'); + cy.get_proposal_information_from_table('Type') + .contains('NewFreeform') + .and('be.visible'); }); }); @@ -120,43 +290,39 @@ context('Governance flow - with eth and vega wallets connected', function () { cy.navigate_to('governance'); cy.wait_for_spinner(); cy.get(newProposalButton).should('be.visible').click(); - cy.get(newProposalDatabox).click(); cy.create_ten_digit_unix_timestamp_for_specified_days('9').then( (closingDateTimestamp) => { cy.enter_unique_freeform_proposal_body(closingDateTimestamp); cy.get(newProposalSubmitButton).should('be.visible').click(); - cy.contains('Proposal submitted').should('be.visible'); + + cy.contains('Awaiting network confirmation', epochTimeout).should( + 'be.visible' + ); + cy.contains('Proposal submitted', epochTimeout).should('be.visible'); cy.get(dialogCloseButton).click(); + cy.wait_for_proposal_sync(); cy.navigate_to('governance'); cy.wait_for_spinner(); - cy.get_submitted_proposal().within(() => + cy.get_submitted_proposal_from_proposal_list().within(() => cy.get(viewProposalButton).click() ); cy.convert_unix_timestamp_to_governance_data_table_date_format( closingDateTimestamp ).then((closingDate) => { - cy.get(proposalInformationTableRows) - .contains('Closes on') - .siblings() + cy.get_proposal_information_from_table('Closes on') .contains(closingDate) .should('be.visible'); }); - cy.create_ten_digit_unix_timestamp_for_specified_days('0').then( - (now) => { - cy.convert_unix_timestamp_to_governance_data_table_date_format( - now - ).then((proposalDate) => { - cy.get(proposalInformationTableRows) - .contains('Proposed on') - .siblings() - .contains(proposalDate) - .should('be.visible'); - }); - } - ); - cy.contains('9 days left to vote').should('be.visible'); } ); + cy.get_governance_proposal_date_format_for_specified_days('0').then( + (proposalDate) => { + cy.get_proposal_information_from_table('Proposed on') + .contains(proposalDate) + .should('be.visible'); + } + ); + cy.contains('9 days left to vote').should('be.visible'); }); it('Newly created freeform proposal - shows default status set to fail', function () { @@ -166,41 +332,337 @@ context('Governance flow - with eth and vega wallets connected', function () { cy.navigate_to('governance'); cy.wait_for_spinner(); cy.get(newProposalButton).should('be.visible').click(); - cy.get(newProposalDatabox).click(); cy.create_ten_digit_unix_timestamp_for_specified_days('7').then( (closingDateTimestamp) => { cy.enter_unique_freeform_proposal_body(closingDateTimestamp); } ); cy.get(newProposalSubmitButton).should('be.visible').click(); - cy.contains('Proposal submitted').should('be.visible'); + cy.contains('Awaiting network confirmation', epochTimeout).should( + 'be.visible' + ); + cy.contains('Proposal submitted', epochTimeout).should('be.visible'); cy.get(dialogCloseButton).click(); + cy.wait_for_proposal_sync(); cy.navigate_to('governance'); cy.wait_for_spinner(); - cy.get_submitted_proposal().within(() => + cy.get_submitted_proposal_from_proposal_list().within(() => cy.get(viewProposalButton).click() ); cy.contains('Currently set to fail').should('be.visible'); cy.contains('Participation: Not Met 0.00 0.00%(0.00% Required)').should( 'be.visible' ); - cy.get(proposalInformationTableRows) - .contains('Will pass') - .siblings() + cy.get_proposal_information_from_table('Will pass') .contains('👎') .should('be.visible'); - cy.get(proposalInformationTableRows) - .contains('Majority met') - .siblings() + cy.get_proposal_information_from_table('Majority met') .contains('👎') .should('be.visible'); - cy.get(proposalInformationTableRows) - .contains('Participation met') - .siblings() + cy.get_proposal_information_from_table('Participation met') .contains('👎') .should('be.visible'); }); + it('Newly created freeform proposal - ability to vote for proposal - with minimum required tokens associated', function () { + cy.ensure_specified_unstaked_tokens_are_associated( + this.minProposerBalance + ); + cy.navigate_to('governance'); + cy.wait_for_spinner(); + cy.get(newProposalButton).should('be.visible').click(); + cy.create_ten_digit_unix_timestamp_for_specified_days('7').then( + (closingDateTimestamp) => { + cy.enter_unique_freeform_proposal_body(closingDateTimestamp); + } + ); + cy.get(newProposalSubmitButton).should('be.visible').click(); + cy.contains('Awaiting network confirmation', epochTimeout).should( + 'be.visible' + ); + cy.contains('Proposal submitted', epochTimeout).should('be.visible'); + cy.get(dialogCloseButton).click(); + cy.wait_for_proposal_sync(); + cy.navigate_to('governance'); + cy.wait_for_spinner(); + cy.get_submitted_proposal_from_proposal_list() + .as('submittedProposal') + .within(() => cy.get(viewProposalButton).click()); + cy.vote_for_proposal('for'); + cy.get_governance_proposal_date_format_for_specified_days( + '0', + 'shortMonth' + ).then((votedDate) => { + cy.contains('You voted:') + .siblings() + .contains('For') + .siblings() + .contains(votedDate) + .should('be.visible'); + }); + cy.get(proposalVoteProgressForPercentage) + .contains('100.00%') + .and('be.visible'); + cy.get(proposalVoteProgressAgainstPercentage) + .contains('0.00%') + .and('be.visible'); + cy.get(proposalVoteProgressForTokens).contains('1.00').and('be.visible'); + cy.get(proposalVoteProgressAgainstTokens) + .contains('0.00') + .and('be.visible'); + cy.get_proposal_information_from_table('Tokens for proposal') + .should('have.text', parseFloat(this.minProposerBalance).toFixed(2)) + .and('be.visible'); + cy.get_proposal_information_from_table('Tokens against proposal') + .should('have.text', '0.00') + .and('be.visible'); + cy.get_proposal_information_from_table('Participation required') + .contains(`${this.requiredParticipation}%`) + .should('be.visible'); + cy.get_proposal_information_from_table('Majority Required') + .contains(`${parseFloat(this.requiredMajority).toFixed(2)}%`) + .should('be.visible'); + cy.get_proposal_information_from_table('Number of voting parties') + .should('have.text', '1') + .and('be.visible'); + }); + + it('Newly created freeform proposal - ability to vote against proposal - with minimum required tokens associated', function () { + cy.ensure_specified_unstaked_tokens_are_associated( + this.minProposerBalance + ); + cy.navigate_to('governance'); + cy.wait_for_spinner(); + cy.get(newProposalButton).should('be.visible').click(); + cy.create_ten_digit_unix_timestamp_for_specified_days('7').then( + (closingDateTimestamp) => { + cy.enter_unique_freeform_proposal_body(closingDateTimestamp); + } + ); + cy.get(newProposalSubmitButton).should('be.visible').click(); + cy.contains('Awaiting network confirmation', epochTimeout).should( + 'be.visible' + ); + cy.contains('Proposal submitted', epochTimeout).should('be.visible'); + cy.get(dialogCloseButton).click(); + cy.wait_for_proposal_sync(); + cy.navigate_to('governance'); + cy.wait_for_spinner(); + cy.get_submitted_proposal_from_proposal_list() + .as('submittedProposal') + .within(() => cy.get(viewProposalButton).click()); + cy.vote_for_proposal('against'); + cy.get_governance_proposal_date_format_for_specified_days( + '0', + 'shortMonth' + ).then((votedDate) => { + cy.contains('You voted:') + .siblings() + .contains('Against') + .siblings() + .contains(votedDate) + .should('be.visible'); + }); + cy.get(proposalVoteProgressForPercentage) + .contains('0.00%') + .and('be.visible'); + cy.get(proposalVoteProgressAgainstPercentage) + .contains('100.00%') + .and('be.visible'); + cy.get(proposalVoteProgressForTokens).contains('0.00').and('be.visible'); + cy.get(proposalVoteProgressAgainstTokens) + .contains('1.00') + .and('be.visible'); + cy.get_proposal_information_from_table('Tokens for proposal') + .should('have.text', '0.00') + .and('be.visible'); + cy.get_proposal_information_from_table('Tokens against proposal') + .should('have.text', parseFloat(this.minProposerBalance).toFixed(2)) + .and('be.visible'); + cy.get_proposal_information_from_table('Participation required') + .contains(`${this.requiredParticipation}%`) + .should('be.visible'); + cy.get_proposal_information_from_table('Majority Required') + .contains(`${parseFloat(this.requiredMajority).toFixed(2)}%`) + .should('be.visible'); + cy.get_proposal_information_from_table('Number of voting parties') + .should('have.text', '1') + .and('be.visible'); + }); + + it('Newly created freeform proposal - ability to change vote from against to for - with minimum required tokens associated', function () { + cy.ensure_specified_unstaked_tokens_are_associated( + this.minProposerBalance + ); + cy.navigate_to('governance'); + cy.wait_for_spinner(); + cy.get(newProposalButton).should('be.visible').click(); + cy.create_ten_digit_unix_timestamp_for_specified_days('7').then( + (closingDateTimestamp) => { + cy.enter_unique_freeform_proposal_body(closingDateTimestamp); + } + ); + cy.get(newProposalSubmitButton).should('be.visible').click(); + cy.contains('Awaiting network confirmation', epochTimeout).should( + 'be.visible' + ); + cy.contains('Proposal submitted', epochTimeout).should('be.visible'); + cy.get(dialogCloseButton).click(); + cy.wait_for_proposal_sync(); + cy.navigate_to('governance'); + cy.wait_for_spinner(); + cy.get_submitted_proposal_from_proposal_list() + .as('submittedProposal') + .within(() => cy.get(viewProposalButton).click()); + cy.vote_for_proposal('against'); + cy.get(changeVoteButton).should('be.visible').click(); + cy.wait_for_spinner(); + cy.vote_for_proposal('for'); + cy.get(proposalVoteProgressForPercentage) + .contains('100.00%') + .and('be.visible'); + cy.get(proposalVoteProgressAgainstPercentage) + .contains('0.00%') + .and('be.visible'); + cy.get(proposalVoteProgressForTokens).contains('1.00').and('be.visible'); + cy.get(proposalVoteProgressAgainstTokens) + .contains('0.00') + .and('be.visible'); + cy.get_proposal_information_from_table('Tokens for proposal') + .should('have.text', parseFloat(this.minProposerBalance).toFixed(2)) + .and('be.visible'); + cy.get_proposal_information_from_table('Tokens against proposal') + .should('have.text', '0.00') + .and('be.visible'); + cy.get_proposal_information_from_table('Participation required') + .contains(`${this.requiredParticipation}%`) + .should('be.visible'); + cy.get_proposal_information_from_table('Majority Required') + .contains(`${parseFloat(this.requiredMajority).toFixed(2)}%`) + .should('be.visible'); + cy.get_proposal_information_from_table('Number of voting parties') + .should('have.text', '1') + .and('be.visible'); + }); + + it('Newly created freeform proposal - ability to change vote from for to against - with minimum required tokens associated', function () { + cy.ensure_specified_unstaked_tokens_are_associated( + this.minProposerBalance + ); + cy.navigate_to('governance'); + cy.wait_for_spinner(); + cy.get(newProposalButton).should('be.visible').click(); + cy.create_ten_digit_unix_timestamp_for_specified_days('7').then( + (closingDateTimestamp) => { + cy.enter_unique_freeform_proposal_body(closingDateTimestamp); + } + ); + cy.get(newProposalSubmitButton).should('be.visible').click(); + cy.contains('Awaiting network confirmation', epochTimeout).should( + 'be.visible' + ); + cy.contains('Proposal submitted', epochTimeout).should('be.visible'); + cy.get(dialogCloseButton).click(); + cy.wait_for_proposal_sync(); + cy.navigate_to('governance'); + cy.wait_for_spinner(); + cy.get_submitted_proposal_from_proposal_list() + .as('submittedProposal') + .within(() => cy.get(viewProposalButton).click()); + cy.vote_for_proposal('for'); + cy.get(changeVoteButton).should('be.visible').click(); + cy.wait_for_spinner(); + cy.vote_for_proposal('against'); + cy.get(proposalVoteProgressForPercentage) + .contains('0.00%') + .and('be.visible'); + cy.get(proposalVoteProgressAgainstPercentage) + .contains('100.00%') + .and('be.visible'); + cy.get(proposalVoteProgressForTokens).contains('0.00').and('be.visible'); + cy.get(proposalVoteProgressAgainstTokens) + .contains('1.00') + .and('be.visible'); + cy.get_proposal_information_from_table('Tokens for proposal') + .should('have.text', '0.00') + .and('be.visible'); + cy.get_proposal_information_from_table('Tokens against proposal') + .should('have.text', parseFloat(this.minProposerBalance).toFixed(2)) + .and('be.visible'); + cy.get_proposal_information_from_table('Participation required') + .contains(`${this.requiredParticipation}%`) + .should('be.visible'); + cy.get_proposal_information_from_table('Majority Required') + .contains(`${parseFloat(this.requiredMajority).toFixed(2)}%`) + .should('be.visible'); + cy.get_proposal_information_from_table('Number of voting parties') + .should('have.text', '1') + .and('be.visible'); + }); + + it('Newly created freeform proposal - ability to increase associated tokens - so that vote sways result', function () { + cy.ensure_specified_unstaked_tokens_are_associated( + this.minProposerBalance + ); + cy.navigate_to('governance'); + cy.wait_for_spinner(); + cy.get(newProposalButton).should('be.visible').click(); + cy.create_ten_digit_unix_timestamp_for_specified_days('7').then( + (closingDateTimestamp) => { + cy.enter_unique_freeform_proposal_body(closingDateTimestamp); + } + ); + cy.get(newProposalSubmitButton).should('be.visible').click(); + cy.contains('Awaiting network confirmation', epochTimeout).should( + 'be.visible' + ); + cy.contains('Proposal submitted', epochTimeout).should('be.visible'); + cy.get(dialogCloseButton).click(); + cy.wait_for_proposal_sync(); + cy.navigate_to('governance'); + cy.wait_for_spinner(); + cy.get_submitted_proposal_from_proposal_list() + .as('submittedProposal') + .within(() => cy.get(viewProposalButton).click()); + cy.vote_for_proposal('for'); + cy.get_proposal_information_from_table('Total Supply') + .invoke('text') + .then((totalSupply) => { + let tokensRequiredToAcheiveResult = parseFloat( + (totalSupply.replace(/,/g, '') * this.requiredParticipation) / 100 + ).toFixed(2); + cy.ensure_specified_unstaked_tokens_are_associated( + tokensRequiredToAcheiveResult + ); + cy.navigate_to('governance'); + cy.wait_for_spinner(); + cy.get('@submittedProposal').within(() => + cy.get(viewProposalButton).click() + ); + cy.get(proposalVoteProgressForPercentage) + .contains('100.00%') + .and('be.visible'); + cy.get(proposalVoteProgressAgainstPercentage) + .contains('0.00%') + .and('be.visible'); + cy.get(proposalVoteProgressForTokens) + .contains(tokensRequiredToAcheiveResult) + .and('be.visible'); + cy.get(proposalVoteProgressAgainstTokens) + .contains('0.00') + .and('be.visible'); + cy.get_proposal_information_from_table('Tokens for proposal') + .should('have.text', tokensRequiredToAcheiveResult) + .and('be.visible'); + cy.get_proposal_information_from_table('Tokens against proposal') + .should('have.text', '0.00') + .and('be.visible'); + cy.get_proposal_information_from_table('Number of voting parties') + .should('have.text', '1') + .and('be.visible'); + }); + }); + it('Creating a proposal - proposal rejected - when closing time sooner than system default', function () { cy.ensure_specified_unstaked_tokens_are_associated( this.minProposerBalance @@ -208,37 +670,25 @@ context('Governance flow - with eth and vega wallets connected', function () { cy.navigate_to('governance'); cy.wait_for_spinner(); cy.get(newProposalButton).should('be.visible').click(); - cy.get(newProposalDatabox).click(); cy.create_ten_digit_unix_timestamp_for_specified_days( this.minCloseDays - 1 ).then((closingDateTimestamp) => { cy.enter_unique_freeform_proposal_body(closingDateTimestamp); }); cy.get(newProposalSubmitButton).should('be.visible').click(); - cy.contains('Proposal rejected').should('be.visible'); + cy.contains('Awaiting network confirmation', epochTimeout).should( + 'be.visible' + ); + cy.contains('Proposal rejected', epochTimeout).should('be.visible'); cy.get(dialogCloseButton).click(); + cy.wait_for_proposal_sync(); cy.navigate_to('governance'); cy.wait_for_spinner(); - cy.get_submitted_proposal().within(() => { + cy.get(rejectProposalsLink).click().wait_for_spinner(); + cy.get_submitted_proposal_from_proposal_list().within(() => { cy.contains('Rejected').should('be.visible'); cy.contains('Close time too soon').should('be.visible'); - cy.get(viewProposalButton).click(); }); - cy.get(proposalInformationTableRows) - .contains('State') - .siblings() - .contains('Rejected') - .should('be.visible'); - cy.get(proposalInformationTableRows) - .contains('Rejection reason') - .siblings() - .contains('CloseTimeTooSoon') - .should('be.visible'); - cy.get(proposalInformationTableRows) - .contains('Error details') - .siblings() - .contains('proposal closing time too soon') - .should('be.visible'); }); it('Creating a proposal - proposal rejected - when closing time later than system default', function () { @@ -248,37 +698,63 @@ context('Governance flow - with eth and vega wallets connected', function () { cy.navigate_to('governance'); cy.wait_for_spinner(); cy.get(newProposalButton).should('be.visible').click(); - cy.get(newProposalDatabox).click(); cy.create_ten_digit_unix_timestamp_for_specified_days( this.maxCloseDays + 1 ).then((closingDateTimestamp) => { cy.enter_unique_freeform_proposal_body(closingDateTimestamp); }); cy.get(newProposalSubmitButton).should('be.visible').click(); - cy.contains('Proposal rejected').should('be.visible'); + cy.contains('Awaiting network confirmation', epochTimeout).should( + 'be.visible' + ); + cy.contains('Proposal rejected', epochTimeout).should('be.visible'); cy.get(dialogCloseButton).click(); + cy.wait_for_proposal_sync(); cy.navigate_to('governance'); cy.wait_for_spinner(); - cy.get_submitted_proposal().within(() => { + cy.get(rejectProposalsLink).click().wait_for_spinner(); + cy.get_submitted_proposal_from_proposal_list().within(() => { + cy.contains('Rejected').should('be.visible'); + cy.contains('Close time too late').should('be.visible'); + }); + }); + + it('Creating a proposal - proposal rejected - able to access rejected proposals', function () { + cy.ensure_specified_unstaked_tokens_are_associated( + this.minProposerBalance + ); + cy.navigate_to('governance'); + cy.wait_for_spinner(); + cy.get(newProposalButton).should('be.visible').click(); + cy.create_ten_digit_unix_timestamp_for_specified_days( + this.maxCloseDays + 1 + ).then((closingDateTimestamp) => { + cy.enter_unique_freeform_proposal_body(closingDateTimestamp); + }); + cy.get(newProposalSubmitButton).should('be.visible').click(); + cy.contains('Awaiting network confirmation', epochTimeout).should( + 'be.visible' + ); + cy.contains('Proposal rejected', epochTimeout).should('be.visible'); + cy.get(dialogCloseButton).click(); + cy.wait_for_proposal_sync(); + cy.navigate_to('governance'); + cy.wait_for_spinner(); + cy.get(rejectProposalsLink).click().wait_for_spinner(); + cy.get_submitted_proposal_from_proposal_list().within(() => { cy.contains('Rejected').should('be.visible'); cy.contains('Close time too late').should('be.visible'); cy.get(viewProposalButton).click(); }); - cy.get(proposalInformationTableRows) - .contains('State') - .siblings() - .contains('Rejected') - .should('be.visible'); - cy.get(proposalInformationTableRows) - .contains('Rejection reason') - .siblings() - .contains('CloseTimeTooLate') - .should('be.visible'); - cy.get(proposalInformationTableRows) - .contains('Error details') - .siblings() + cy.get_proposal_information_from_table('State') + .contains('STATE_REJECTED') + .and('be.visible'); + cy.get_proposal_information_from_table('Rejection reason') + .contains('PROPOSAL_ERROR_CLOSE_TIME_TOO_LATE') + .and('be.visible'); + cy.get_proposal_information_from_table('Error details') .contains('proposal closing time too late') - .should('be.visible'); + .and('be.visible'); }); it('Unable to create a freeform proposal - when no tokens are associated', function () { @@ -290,44 +766,46 @@ context('Governance flow - with eth and vega wallets connected', function () { cy.navigate_to('governance'); cy.wait_for_spinner(); cy.get(newProposalButton).should('be.visible').click(); - cy.get(newProposalDatabox).click(); cy.create_ten_digit_unix_timestamp_for_specified_days('1').then( (closingDateTimestamp) => { cy.enter_unique_freeform_proposal_body(closingDateTimestamp); } ); cy.get(newProposalSubmitButton).should('be.visible').click(); - cy.wait('@proposalSubmissionCompletion'); - cy.contains( - 'party has insufficient tokens to submit proposal request in this epoch' - ).should('be.visible'); - cy.get(dialogCloseButton).click(); + + cy.contains('Transaction failed', epochTimeout).should('be.visible'); + cy.get(feedbackError) + .contains( + 'Party has insufficient associated governance tokens in their staking account to submit proposal request' + ) + .should('be.visible'); }); it('Unable to create a freeform proposal - when some but not enough tokens are associated', function () { cy.ensure_specified_unstaked_tokens_are_associated( - this.minProposerBalance - 0.1 + this.minProposerBalance - 0.000001 ); cy.navigate_to('governance'); cy.wait_for_spinner(); cy.get(newProposalButton).should('be.visible').click(); - cy.get(newProposalDatabox).click(); cy.create_ten_digit_unix_timestamp_for_specified_days('1').then( (closingDateTimestamp) => { cy.enter_unique_freeform_proposal_body(closingDateTimestamp); } ); cy.get(newProposalSubmitButton).should('be.visible').click(); - cy.wait('@proposalSubmissionCompletion'); - cy.contains( - 'party has insufficient tokens to submit proposal request in this epoch' - ).should('be.visible'); - cy.get(dialogCloseButton).click(); + + cy.contains('Transaction failed', epochTimeout).should('be.visible'); + cy.get(feedbackError) + .contains( + 'Party has insufficient associated governance tokens in their staking account to submit proposal request' + ) + .should('be.visible'); }); Cypress.Commands.add( 'convert_unix_timestamp_to_governance_data_table_date_format', - (unixTimestamp) => { + (unixTimestamp, monthTextLength = 'longMonth') => { let dateSupplied = new Date(unixTimestamp * 1000), year = dateSupplied.getFullYear(), months = [ @@ -345,9 +823,11 @@ context('Governance flow - with eth and vega wallets connected', function () { 'December', ], month = months[dateSupplied.getMonth()], + shortMonth = months[dateSupplied.getMonth()].substring(0, 3), date = dateSupplied.getDate(); - return `${date} ${month} ${year}`; + if (monthTextLength === 'longMonth') return `${date} ${month} ${year}`; + else return `${date} ${shortMonth} ${year}`; } ); @@ -365,7 +845,7 @@ context('Governance flow - with eth and vega wallets connected', function () { Cypress.Commands.add('enter_unique_freeform_proposal_body', (timestamp) => { cy.fixture('/proposals/freeform.json').then((freeformProposal) => { freeformProposal.terms.closingTimestamp = timestamp; - freeformProposal.rationale.description += timestamp; + freeformProposal.rationale.title += timestamp; let proposalPayload = JSON.stringify(freeformProposal); cy.get(newProposalDatabox).type(proposalPayload, { @@ -385,7 +865,7 @@ context('Governance flow - with eth and vega wallets connected', function () { }, headers: { 'content-type': 'application/json' }, }) - .its('body.data.networkParameters') + .its(`body.data.networkParameters`) .then(function (response) { let object = response.reduce(function (r, e) { r[e.key] = e.value; @@ -396,12 +876,74 @@ context('Governance flow - with eth and vega wallets connected', function () { }); }); - Cypress.Commands.add('get_submitted_proposal', () => { + Cypress.Commands.add('get_submitted_proposal_from_proposal_list', () => { cy.wait('@proposalSubmissionCompletion') - .its(proposalResponseIdPath) + .its(proposalResponseProposalIdPath) .then((proposalId) => { - cy.get(`#${proposalId}`); + return cy.get(`#${proposalId}`); }); }); + + Cypress.Commands.add( + 'get_governance_proposal_date_format_for_specified_days', + (days, shortOrLong) => { + cy.create_ten_digit_unix_timestamp_for_specified_days(days).then( + (date) => { + cy.convert_unix_timestamp_to_governance_data_table_date_format( + date, + shortOrLong + ).then((convertedDate) => { + return convertedDate; + }); + } + ); + } + ); + + Cypress.Commands.add('get_proposal_information_from_table', (heading) => { + cy.get(proposalInformationTableRows).contains(heading).siblings(); + }); + + Cypress.Commands.add('vote_for_proposal', (vote) => { + cy.contains('Vote breakdown').should('be.visible', { timeout: 10000 }); + cy.get(voteButtons).contains(vote).click(); + cy.contains('Casting vote...').should('be.visible'); + cy.contains('Casting vote...', txTimeout).should('not.exist'); + + // below section temporary until #1090 fixed Casting vote in vegacapsule always says: + // Something went wrong, and your vote was not seen by the network - despite vote success + cy.navigate_to('governance'); + cy.wait_for_spinner(); + cy.get('@submittedProposal').within(() => + cy.get(viewProposalButton).click() + ); + cy.wait_for_spinner(); + }); + + Cypress.Commands.add('wait_for_proposal_sync', () => { + // This is a workaround function required because after posting a proposal + // and waiting for the ProposalEvent network call to respond there can still be a few seconds + // before proposal appears in the list - so rather than hard coded wait - we just wait on the + // delegation checks that are performed on the governance page. + + cy.intercept('POST', '/query', (req) => { + if (req.body.operationName === 'Delegations') { + req.alias = 'proposalDelegationsCompletion'; + } + }); + + // waiting for two network calls + cy.wait([ + '@proposalDelegationsCompletion', + '@proposalDelegationsCompletion', + ]); + + // Turn off this intercept from here on in + cy.intercept('POST', '/query', (req) => { + if (req.body.operationName === 'Delegations') { + req.continue(); + } + }); + }); }); }); diff --git a/apps/token-e2e/src/integration/flow/staking-flow.cy.js b/apps/token-e2e/src/integration/flow/staking-flow.cy.js index d6d42e372..3f3a4d938 100644 --- a/apps/token-e2e/src/integration/flow/staking-flow.cy.js +++ b/apps/token-e2e/src/integration/flow/staking-flow.cy.js @@ -55,7 +55,6 @@ context('Staking Tab - with eth and vega wallets connected', function () { } ); - // 1002-STKE-004 it('Able to stake against a validator - using vega from wallet', function () { cy.staking_page_associate_tokens('3'); @@ -670,6 +669,7 @@ context('Staking Tab - with eth and vega wallets connected', function () { }); it('Associating wallet tokens - when some already staked - auto stakes tokens to staked validator', function () { + // 1002-STKE-004 cy.staking_page_associate_tokens('3'); cy.get(vegaWalletUnstakedBalance, txTimeout).should( @@ -705,6 +705,7 @@ context('Staking Tab - with eth and vega wallets connected', function () { }); it('Associating vesting contract tokens - when some already staked - auto stakes tokens to staked validator', function () { + // 1002-STKE-004 cy.staking_page_associate_tokens('3', { type: 'contract' }); cy.get(vegaWalletUnstakedBalance, txTimeout).should( @@ -740,6 +741,7 @@ context('Staking Tab - with eth and vega wallets connected', function () { }); it('Associating vesting contract tokens - when wallet tokens already staked - auto stakes tokens to staked validator', function () { + // 1002-STKE-004 cy.staking_page_associate_tokens('3', { type: 'wallet' }); cy.get(vegaWalletUnstakedBalance, txTimeout).should( @@ -775,6 +777,7 @@ context('Staking Tab - with eth and vega wallets connected', function () { }); it('Associating tokens - with multiple validators already staked - auto stakes to staked validators - abiding by existing stake ratio', function () { + // 1002-STKE-004 cy.staking_page_associate_tokens('6'); cy.get(vegaWalletUnstakedBalance, txTimeout).should( diff --git a/apps/token/src/routes/governance/components/vote-details/vote-buttons.tsx b/apps/token/src/routes/governance/components/vote-details/vote-buttons.tsx index 7860d7763..fec5dfe8f 100644 --- a/apps/token/src/routes/governance/components/vote-details/vote-buttons.tsx +++ b/apps/token/src/routes/governance/components/vote-details/vote-buttons.tsx @@ -145,6 +145,7 @@ export const VoteButtons = ({ ) : null} {proposalState === ProposalState.STATE_OPEN ? ( { setChangeVote(true); }} @@ -161,7 +162,7 @@ export const VoteButtons = ({ } return ( - + submitVote(VoteValue.VALUE_YES)}> {t('voteFor')} diff --git a/apps/token/src/routes/governance/components/vote-details/vote-details.tsx b/apps/token/src/routes/governance/components/vote-details/vote-details.tsx index 777209ab1..13240db44 100644 --- a/apps/token/src/routes/governance/components/vote-details/vote-details.tsx +++ b/apps/token/src/routes/governance/components/vote-details/vote-details.tsx @@ -67,21 +67,33 @@ export const VoteDetails = ({ proposal }: VoteDetailsProps) => { - + {yesPercentage.toFixed(defaultDecimals)}% {t('majorityRequired')}{' '} {requiredMajorityPercentage.toFixed(defaultDecimals)}% - + {noPercentage.toFixed(defaultDecimals)}% - {formatNumber(yesTokens, defaultDecimals)} + + {' '} + {formatNumber(yesTokens, defaultDecimals)}{' '} + - + {formatNumber(noTokens, defaultDecimals)} diff --git a/vegacapsule/config.hcl b/vegacapsule/config.hcl new file mode 100644 index 000000000..34ae932cb --- /dev/null +++ b/vegacapsule/config.hcl @@ -0,0 +1,101 @@ +vega_binary_path = "vega" + +network "testnet" { + ethereum { + chain_id = "1440" + network_id = "1441" + endpoint = "http://127.0.0.1:8545/" + } + + faucet "faucet-1" { + wallet_pass = "f4uc3tw4ll3t-v3g4-p4ssphr4e3" + + template = <<-EOT +[Node] + Port = 3002 + IP = "127.0.0.1" +EOT + } + + wallet "wallet-1" { + binary = "vegawallet" + + template = <<-EOT +Name = "DV" +Level = "info" +TokenExpiry = "168h0m0s" +Port = 1789 +Host = "0.0.0.0" + +[API] + [API.GRPC] + Hosts = [{{range $i, $v := .Validators}}{{if ne $i 0}},{{end}}"127.0.0.1:30{{$i}}2"{{end}}] + Retries = 5 +EOT + } + + pre_start { + docker_service "ganache-1" { + image = "vegaprotocol/ganache:latest" + cmd = "ganache-cli" + args = [ + "--blockTime", "1", + "--chainId", "1440", + "--networkId", "1441", + "-h", "0.0.0.0", + "-p", "8545", + "-m", "ozone access unlock valid olympic save include omit supply green clown session", + "--db", "/app/ganache-db", + ] + static_port { + value = 8545 + to = 8545 + } + auth_soft_fail = true + } + docker_service "postgres-1" { + image = "vegaprotocol/timescaledb:2.7.1-pg14" + cmd = "postgres" + args = [] + env = { + POSTGRES_USER="vega" + POSTGRES_PASSWORD="vega" + POSTGRES_DBS="vega0,vega1,vega2,vega3,vega4,vega5,vega6" + } + static_port { + value = 5232 + to = 5432 + } + auth_soft_fail = true + } + } + + genesis_template_file = "./genesis.tmpl" + smart_contracts_addresses_file = "./public_smart_contracts_addresses.json" + + node_set "validators" { + count = 2 + mode = "validator" + + node_wallet_pass = "n0d3w4ll3t-p4ssphr4e3" + vega_wallet_pass = "w4ll3t-p4ssphr4e3" + ethereum_wallet_pass = "ch41nw4ll3t-3th3r3um-p4ssphr4e3" + + config_templates { + vega_file = "./node_set_templates/default/vega_validators.tmpl" + tendermint_file = "./node_set_templates/default/tendermint_validators.tmpl" + } + } + + node_set "full" { + count = 1 + mode = "full" + data_node_binary = "data-node" + + config_templates { + vega_file = "./node_set_templates/default/vega_full.tmpl" + tendermint_file = "./node_set_templates/default/tendermint_full.tmpl" + data_node_file = "./node_set_templates/default/data_node_full_external_postgres.tmpl" + } + } +} diff --git a/vegacapsule/genesis.tmpl b/vegacapsule/genesis.tmpl new file mode 100644 index 000000000..1db7246b9 --- /dev/null +++ b/vegacapsule/genesis.tmpl @@ -0,0 +1,231 @@ +{ + "app_state": { + "assets": { + "fBTC": { + "min_lp_stake": "1", + "decimals": 5, + "name": "BTC (fake)", + "symbol": "fBTC", + "total_supply": "21000000", + "source": { + "builtin_asset": { + "max_faucet_amount_mint": "1000000" + } + } + }, + "fDAI": { + "min_lp_stake": "1", + "decimals": 5, + "name": "DAI (fake)", + "symbol": "fDAI", + "total_supply": "1000000000", + "source": { + "builtin_asset": { + "max_faucet_amount_mint": "10000000000" + } + } + }, + "fEURO": { + "min_lp_stake": "1", + "decimals": 5, + "name": "EURO (fake)", + "symbol": "fEURO", + "total_supply": "1000000000", + "source": { + "builtin_asset": { + "max_faucet_amount_mint": "10000000000" + } + } + }, + "fUSDC": { + "min_lp_stake": "1", + "decimals": 5, + "name": "USDC (fake)", + "symbol": "fUSDC", + "total_supply": "1000000000", + "source": { + "builtin_asset": { + "max_faucet_amount_mint": "1000000000000" + } + } + }, + "XYZalpha": { + "min_lp_stake": "1", + "decimals": 5, + "name": "XYZ (α alpha)", + "symbol": "XYZalpha", + "total_supply": "1000000000", + "source": { + "builtin_asset": { + "max_faucet_amount_mint": "100000000000" + } + } + }, + "XYZbeta": { + "min_lp_stake": "1", + "decimals": 5, + "name": "XYZ (β beta)", + "symbol": "XYZbeta", + "total_supply": "1000000000", + "source": { + "builtin_asset": { + "max_faucet_amount_mint": "100000000000" + } + } + }, + "XYZgamma": { + "min_lp_stake": "1", + "decimals": 5, + "name": "XYZ (γ gamma)", + "symbol": "XYZgamma", + "total_supply": "1000000000", + "source": { + "builtin_asset": { + "max_faucet_amount_mint": "100000000000" + } + } + }, + "XYZdelta": { + "min_lp_stake": "1", + "decimals": 5, + "name": "XYZ (δ delta)", + "symbol": "XYZdelta", + "total_supply": "1000000000", + "source": { + "builtin_asset": { + "max_faucet_amount_mint": "100000000000" + } + } + }, + "XYZepsilon": { + "min_lp_stake": "1", + "decimals": 5, + "name": "XYZ (ε epsilon)", + "symbol": "XYZepsilon", + "total_supply": "1000000000", + "source": { + "builtin_asset": { + "max_faucet_amount_mint": "100000000000" + } + } + }, + "{{.GetVegaContractID "tBTC"}}": { + "min_lp_stake": "1", + "decimals": 5, + "name": "BTC (local)", + "symbol": "tBTC", + "total_supply": "0", + "source": { + "erc20": { + "contract_address": "{{.GetEthContractAddr "tBTC"}}" + } + } + }, + "{{.GetVegaContractID "tDAI"}}": { + "min_lp_stake": "1", + "decimals": 5, + "name": "DAI (local)", + "symbol": "tDAI", + "total_supply": "0", + "source": { + "erc20": { + "contract_address": "{{.GetEthContractAddr "tDAI"}}" + } + } + }, + "{{.GetVegaContractID "tEURO"}}": { + "min_lp_stake": "1", + "decimals": 5, + "name": "EURO (local)", + "symbol": "tEURO", + "total_supply": "0", + "source": { + "erc20": { + "contract_address": "{{.GetEthContractAddr "tEURO"}}" + } + } + }, + "{{.GetVegaContractID "tUSDC"}}": { + "min_lp_stake": "1", + "decimals": 5, + "name": "USDC (local)", + "symbol": "tUSDC", + "total_supply": "0", + "source": { + "erc20": { + "contract_address": "{{.GetEthContractAddr "tUSDC"}}" + } + } + }, + "{{.GetVegaContractID "VEGA"}}": { + "min_lp_stake": "1", + "decimals": 18, + "name": "Vega", + "symbol": "VEGA", + "total_supply": "64999723000000000000000000", + "source": { + "erc20": { + "contract_address": "{{.GetEthContractAddr "VEGA"}}" + } + } + } + }, + "network": { + "ReplayAttackThreshold": 30 + }, + "network_parameters": { + "blockchains.ethereumConfig": "{\"network_id\": \"{{ .NetworkID }}\", \"chain_id\": \"{{ .ChainID }}\", \"collateral_bridge_contract\": { \"address\": \"{{.GetEthContractAddr "erc20_bridge_1"}}\" }, \"confirmations\": 3, \"staking_bridge_contract\": { \"address\": \"{{.GetEthContractAddr "staking_bridge"}}\", \"deployment_block_height\": 0}, \"token_vesting_contract\": { \"address\": \"{{.GetEthContractAddr "erc20_vesting"}}\", \"deployment_block_height\": 0 }, \"multisig_control_contract\": { \"address\": \"{{.GetEthContractAddr "MultisigControl"}}\", \"deployment_block_height\": 0 }}", + "governance.proposal.asset.minClose": "2s", + "governance.proposal.asset.minEnact": "2s", + "governance.proposal.asset.requiredParticipation": "0.00000000000000000000000015", + "governance.proposal.freeform.minProposerBalance": "1", + "governance.proposal.freeform.minVoterBalance": "1", + "governance.proposal.freeform.requiredMajority": "0.66", + "governance.proposal.freeform.requiredParticipation": "0.00001", + "governance.proposal.freeform.maxClose": "8760h0m0s", + "governance.proposal.freeform.minClose": "48h0m0s", + "governance.proposal.market.minClose": "2s", + "governance.proposal.market.minEnact": "2s", + "governance.proposal.market.requiredParticipation": "0.00000000000000000000000015", + "governance.proposal.updateMarket.minClose": "2s", + "governance.proposal.updateMarket.minEnact": "2s", + "governance.proposal.updateMarket.requiredParticipation": "0.00000000000000000000000015", + "governance.proposal.updateNetParam.minClose": "2s", + "governance.proposal.updateNetParam.minEnact": "2s", + "governance.proposal.updateNetParam.requiredParticipation": "0.00000000000000000000000015", + "market.auction.minimumDuration": "3s", + "market.fee.factors.infrastructureFee": "0.001", + "market.fee.factors.makerFee": "0.004", + "market.liquidity.stakeToCcySiskas": "0.3", + "market.liquidity.targetstake.triggering.ratio": "0.7", + "network.checkpoint.timeElapsedBetweenCheckpoints": "10s", + "reward.asset": "{{.GetVegaContractID "VEGA"}}", + "reward.staking.delegation.competitionLevel": "3.1", + "reward.staking.delegation.delegatorShare": "0.883", + "reward.staking.delegation.maxPayoutPerParticipant": "700000000000000000000", + "reward.staking.delegation.minimumValidatorStake": "3000000000000000000000", + "reward.staking.delegation.payoutDelay": "5m", + "reward.staking.delegation.payoutFraction": "0.007", + "spam.protection.delegation.min.tokens": "1000000000000000000", + "spam.protection.max.delegations": "390", + "spam.protection.max.proposals": "100", + "spam.protection.max.votes": "100", + "spam.protection.proposal.min.tokens": "1000000000000000000", + "spam.protection.voting.min.tokens": "1000000000000000000", + "validators.delegation.minAmount": "100000000000000000", + "validators.epoch.length": "6s", + "validators.vote.required": "0.67" + }, + "network_limits": { + "propose_asset_enabled": true, + "propose_asset_enabled_from": "2021-09-01T00:00:00Z", + "propose_market_enabled": true, + "propose_market_enabled_from": "2021-09-01T00:00:00Z" + } + }, + "consensus_params": { + "block": { + "time_iota_ms": "1" + } + } +} \ No newline at end of file diff --git a/vegacapsule/node_set_templates/default/data_node_full_external_postgres.tmpl b/vegacapsule/node_set_templates/default/data_node_full_external_postgres.tmpl new file mode 100644 index 000000000..3e5a51626 --- /dev/null +++ b/vegacapsule/node_set_templates/default/data_node_full_external_postgres.tmpl @@ -0,0 +1,40 @@ +GatewayEnabled = true + +[SQLStore] + Enabled = true + [SQLStore.ConnectionConfig] + Port = 5232 + UseTransactions = true + Database = "vega{{.NodeNumber}}" + + +[API] + Level = "Info" + Port = 30{{.NodeNumber}}7 + CoreNodeGRPCPort = 30{{.NodeNumber}}2 + +[Pprof] + Level = "Info" + Enabled = false + Port = 6{{.NodeNumber}}60 + ProfilesDir = "{{.NodeHomeDir}}" + +[Gateway] + Level = "Info" + [Gateway.Node] + Port = 30{{.NodeNumber}}7 + [Gateway.GraphQL] + Port = 30{{.NodeNumber}}8 + [Gateway.REST] + Port = 30{{.NodeNumber}}9 + +[Metrics] + Level = "Info" + Timeout = "5s" + Port = 21{{.NodeNumber}}2 + Enabled = false +[Broker] + Level = "Info" + UseEventFile = false + [Broker.SocketConfig] + Port = 30{{.NodeNumber}}5 \ No newline at end of file diff --git a/vegacapsule/node_set_templates/default/tendermint_full.tmpl b/vegacapsule/node_set_templates/default/tendermint_full.tmpl new file mode 100644 index 000000000..71bdc56d3 --- /dev/null +++ b/vegacapsule/node_set_templates/default/tendermint_full.tmpl @@ -0,0 +1,29 @@ +log_level = "info" + +proxy_app = "tcp://127.0.0.1:266{{.NodeNumber}}8" +moniker = "{{.Prefix}}-{{.TendermintNodePrefix}}" + +[rpc] + laddr = "tcp://0.0.0.0:266{{.NodeNumber}}7" + unsafe = true + cors_allowed_origins = ["*"] + cors_allowed_methods = ["HEAD", "GET", "POST", ] + cors_allowed_headers = ["Origin", "Accept", "Content-Type", "X-Requested-With", "X-Server-Time", ] + +[p2p] + laddr = "tcp://0.0.0.0:266{{.NodeNumber}}6" + addr_book_strict = false + max_packet_msg_payload_size = 4096 + pex = false + allow_duplicate_ip = true + persistent_peers = "{{- range $i, $peer := .NodePeers -}} + {{- if ne $i 0 }},{{end -}} + {{- $peer.ID}}@127.0.0.1:266{{$peer.Index}}6 + {{- end -}}" + +[mempool] + size = 10000 + cache_size = 20000 + +[consensus] + skip_timeout_commit = true diff --git a/vegacapsule/node_set_templates/default/tendermint_validators.tmpl b/vegacapsule/node_set_templates/default/tendermint_validators.tmpl new file mode 100644 index 000000000..fa5e7b91b --- /dev/null +++ b/vegacapsule/node_set_templates/default/tendermint_validators.tmpl @@ -0,0 +1,31 @@ +log_level = "info" + +proxy_app = "tcp://127.0.0.1:266{{.NodeNumber}}8" +moniker = "{{.Prefix}}-{{.TendermintNodePrefix}}" + +[rpc] + laddr = "tcp://0.0.0.0:266{{.NodeNumber}}7" + unsafe = true + cors_allowed_origins = ["*"] + cors_allowed_methods = ["HEAD", "GET", "POST", ] + cors_allowed_headers = ["Origin", "Accept", "Content-Type", "X-Requested-With", "X-Server-Time", ] + +[p2p] + laddr = "tcp://0.0.0.0:266{{.NodeNumber}}6" + addr_book_strict = false + max_packet_msg_payload_size = 4096 + pex = false + allow_duplicate_ip = true + + persistent_peers = "{{- range $i, $peer := .NodePeers -}} + {{- if ne $i 0 }},{{end -}} + {{- $peer.ID}}@127.0.0.1:266{{$peer.Index}}6 + {{- end -}}" + + +[mempool] + size = 10000 + cache_size = 20000 + +[consensus] + skip_timeout_commit = true diff --git a/vegacapsule/node_set_templates/default/vega_full.tmpl b/vegacapsule/node_set_templates/default/vega_full.tmpl new file mode 100644 index 000000000..11f703f78 --- /dev/null +++ b/vegacapsule/node_set_templates/default/vega_full.tmpl @@ -0,0 +1,32 @@ +[Admin] + [Admin.Server] + SocketPath = "/tmp/vega-{{.NodeNumber}}.sock" + Enabled = true + +[API] + Port = 30{{.NodeNumber}}2 + [API.REST] + Port = 30{{.NodeNumber}}3 + +[Blockchain] + [Blockchain.Tendermint] + RPCAddr = "tcp://127.0.0.1:266{{.NodeNumber}}7" + [Blockchain.Null] + Port = 31{{.NodeNumber}}1 + +[EvtForward] + Level = "Info" + RetryRate = "1s" + +[Ethereum] + RPCEndpoint = "{{.ETHEndpoint}}" + +[Processor] + [Processor.Ratelimit] + Requests = 10000 + PerNBlocks = 1 + +[Broker] + [Broker.Socket] + Port = 30{{.NodeNumber}}5 + Enabled = true \ No newline at end of file diff --git a/vegacapsule/node_set_templates/default/vega_validators.tmpl b/vegacapsule/node_set_templates/default/vega_validators.tmpl new file mode 100644 index 000000000..e1fad7dff --- /dev/null +++ b/vegacapsule/node_set_templates/default/vega_validators.tmpl @@ -0,0 +1,30 @@ +[Admin] + [Admin.Server] + SocketPath = "/tmp/vega-{{.NodeNumber}}.sock" + Enabled = true + +[API] + Port = 30{{.NodeNumber}}2 + [API.REST] + Port = 30{{.NodeNumber}}3 + +[Blockchain] + [Blockchain.Tendermint] + RPCAddr = "tcp://127.0.0.1:266{{.NodeNumber}}7" + [Blockchain.Null] + Port = 31{{.NodeNumber}}1 + +[EvtForward] + Level = "Info" + RetryRate = "1s" + {{if .FaucetPublicKey}} + BlockchainQueueAllowlist = ["{{ .FaucetPublicKey }}"] + {{end}} + +[Ethereum] + RPCEndpoint = "{{.ETHEndpoint}}" + +[Processor] + [Processor.Ratelimit] + Requests = 10000 + PerNBlocks = 1 \ No newline at end of file diff --git a/vegacapsule/public_smart_contracts_addresses.json b/vegacapsule/public_smart_contracts_addresses.json new file mode 100644 index 000000000..412c75966 --- /dev/null +++ b/vegacapsule/public_smart_contracts_addresses.json @@ -0,0 +1,48 @@ +{ + "addr0": { + "priv": "a37f4c2a678aefb5037bf415a826df1540b330b7e471aa54184877ba901b9ef0", + "pub": "0xEe7D375bcB50C26d52E1A4a472D8822A2A22d94F" + }, + "MultisigControl": { + "Ethereum": "0xdEcdA30fd3449718304eA201A8f220eBdE25dd1E" + }, + "ERC20_Asset_Pool": { + "Ethereum": "0xAa1eDb6C25e6B5ff2c8EdAf68757Ae557178E6eE" + }, + "erc20_bridge_1": { + "Ethereum": "0x9708FF7510D4A7B9541e1699d15b53Ecb1AFDc54" + }, + "erc20_bridge_2": { + "Ethereum": "0x29e1eA1cfb78f7c34802C90198Cc24aDcBBE4AD0" + }, + "tBTC": { + "Ethereum": "0xb63D135B0a6854EEb765d69ca36210cC70BECAE0", + "Vega": "0x5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c" + }, + "tDAI": { + "Ethereum": "0x879B84eCA313D62CE4e5ED717939B42cBa9e53cb", + "Vega": "0x6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61" + }, + "tEURO": { + "Ethereum": "0x7ccE194dAEf2A4e5C23C78C9330D4c907eCA6980", + "Vega": "0x8b52d4a3a4b0ffe733cddbc2b67be273816cfeb6ca4c8b339bac03ffba08e4e4" + }, + "tUSDC": { + "Ethereum": "0x1b8a1B6CBE5c93609b46D1829Cc7f3Cb8eeE23a0", + "Vega": "0x993ed98f4f770d91a796faab1738551193ba45c62341d20597df70fea6704ede" + }, + "VEGA": { + "Ethereum": "0x67175Da1D5e966e40D11c4B2519392B2058373de", + "Vega": "0xb4f2726571fbe8e33b442dc92ed2d7f0d810e21835b7371a7915a365f07ccd9b" + }, + "VEGAv1": { + "Ethereum": "0x8fa21D653C1bF17741055f00dD55663Bc52a8362", + "Vega": "0xc1607f28ec1d0a0b36842c8327101b18de2c5f172585870912f5959145a9176c" + }, + "erc20_vesting": { + "Ethereum": "0xF41bD86d462D36b997C0bbb4D97a0a3382f205B7" + }, + "staking_bridge": { + "Ethereum": "0x9135f5afd6F055e731bca2348429482eE614CFfA" + } +} diff --git a/vegacapsule/smart_contracts_addresses.json b/vegacapsule/smart_contracts_addresses.json new file mode 100644 index 000000000..71d0012b9 --- /dev/null +++ b/vegacapsule/smart_contracts_addresses.json @@ -0,0 +1,48 @@ +{ + "addr0": { + "priv": "adef89153e4bd6b43876045efdd6818cec359340683edaec5e8588e635e8428b", + "pub": "0xb89A165EA8b619c14312dB316BaAa80D2a98B493" + }, + "MultisigControl": { + "Ethereum": "0xa956B5c58B4Ac8Dd1D44Ade3e8972A16e9C917E4" + }, + "ERC20_Asset_Pool": { + "Ethereum": "0x3EA59801698c6820328597F26d29fC3EaAa17AcA" + }, + "erc20_bridge_1": { + "Ethereum": "0x0858D9BD11A4F6Bae8b979402550CA6c6ddB8332" + }, + "erc20_bridge_2": { + "Ethereum": "0x846087f262859fe6604e2e9f787a9F3f39296Ff8" + }, + "tBTC": { + "Ethereum": "0xc6a6000d740707edc35f75f42447320B60450c04", + "Vega": "0x5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c" + }, + "tDAI": { + "Ethereum": "0xE25F12E386Cd7F84c41B5210504d9743A35Badda", + "Vega": "0x6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61" + }, + "tEURO": { + "Ethereum": "0x7c23d674fED4500103A0b7e05b4A0da17291FCE9", + "Vega": "0x8b52d4a3a4b0ffe733cddbc2b67be273816cfeb6ca4c8b339bac03ffba08e4e4" + }, + "tUSDC": { + "Ethereum": "0xD76Bd796e117D54044E616ae42A3577256B601D1", + "Vega": "0x993ed98f4f770d91a796faab1738551193ba45c62341d20597df70fea6704ede" + }, + "VEGA": { + "Ethereum": "0xBC944ba38753A6fCAdd634Be98379330dbaB3Eb8", + "Vega": "0xb4f2726571fbe8e33b442dc92ed2d7f0d810e21835b7371a7915a365f07ccd9b" + }, + "VEGAv1": { + "Ethereum": "0xB69a81EE133d8c4dC4AeCB30af93bC8698118ccE", + "Vega": "0xc1607f28ec1d0a0b36842c8327101b18de2c5f172585870912f5959145a9176c" + }, + "erc20_vesting": { + "Ethereum": "0xB9f84835F00C0E4f494C51C945863109cF80754A" + }, + "staking_bridge": { + "Ethereum": "0xE4c9fB5955bAa8a7965D000afdCEFF25cfe0E8a3" + } +}