Test/757 tfe add e2e tests for governance (#1236)

* test: initial commit

* test: lint

* chore: set different environement variable for rest url

* test: enable commented out steps

* chore: set base correctly

* chore: correct env var

* test: update to function

* test: lint

* test: governance flow

* test: lint

* test: extra tests

* fix: set fetchPolicy to not cache results so new proposals are updated

* test: update

* test: lint

* test: extra tests

* test: lint

* test: add wait and select proposal

* test: lint

* test: extra checks

* test: lint

* Revert "chore: use custom vega capsule file (#1055)"

This reverts commit 6b4b896bbc.

* test: final commit of initial tests

* test: removal of unused file

* test: before all change to reset before each test

* test: speed enhancement

* test: lint

* test: lint check fix

* test: extra tests and checks

* test: lint

* test: extra tests and checks

* test: lint

* test: extra checks & error handling

* test: lint

* test: lint

* test: wallet update

* test: lint

* test: lint

* test: begining of test refactor due to ui revamp

* test: lint

* test: extra test

* test: lint

* test: extra test enable prev skipped

* test: lint

* test: small changes

* test: update ahead of merge

* test: in house vegcapsule config changes

* test: lint

* chore: add vegacapsule config for newer repo

* chore: remove dead config files

* test: genesis and tweaks

* test: lint

* test: added wait to avoid flake

* test: enhancements

* test: lint

* chore: fix lint

Co-authored-by: Dexter <dexter.edwards93@gmail.com>
Co-authored-by: Dexter <dexter@vega.xyz>
Co-authored-by: Joe <joe@vega.xyz>
This commit is contained in:
AndyWhiteVega 2022-09-05 09:57:02 +01:00 committed by GitHub
parent 0f87c68437
commit cb4cbdc2ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 1301 additions and 129 deletions

View File

@ -38,6 +38,14 @@ jobs:
## Checkout capsule ## 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 # Checkout capsule to build local network
- name: Checkout capsule - name: Checkout capsule
uses: actions/checkout@v2 uses: actions/checkout@v2
@ -87,7 +95,7 @@ jobs:
run: vegacapsule nomad & run: vegacapsule nomad &
- name: Bootstrap network - 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 working-directory: capsule
###### ######
@ -111,23 +119,19 @@ jobs:
## Run some tests ## 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 - name: Derive appropriate SHAs for base and head for `nx affected` commands
uses: nrwl/nx-set-shas@v2 uses: nrwl/nx-set-shas@v2
with: with:
working-directory: frontend-monorepo
main-branch-name: master main-branch-name: master
- name: Install root dependencies - name: Install root dependencies
run: yarn install run: yarn install
working-directory: frontend-monorepo
- name: Run Cypress tests - name: Run Cypress tests
run: npx nx affected:e2e --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome run: npx nx affected:e2e --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome
working-directory: frontend-monorepo
env: env:
CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }} CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }} CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}

View File

@ -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
}
}

View File

@ -1,11 +1,10 @@
{ {
"rationale": { "rationale": {
"url": "https://dweb.link/ipfs/bafybeigwwctpv37xdcwacqxvekr6e4kaemqsrv34em6glkbiceo3fcy4si", "title": "An example freeform proposal",
"hash": "bafybeigwwctpv37xdcwacqxvekr6e4kaemqsrv34em6glkbiceo3fcy4si", "description": "I propose that everyone evaluate the following IPFS document and vote Yes if they agree. [bafybeigwwctpv37xdcwacqxvekr6e4kaemqsrv34em6glkbiceo3fcy4si](https://dweb.link/ipfs/bafybeigwwctpv37xdcwacqxvekr6e4kaemqsrv34em6glkbiceo3fcy4si)"
"description": "Freeform Proposal with unique id of: "
}, },
"terms": { "terms": {
"newFreeform": {}, "newFreeform": {},
"closingTimestamp": 1657721401 "closingTimestamp": 1662374250
} }
} }

View File

@ -1,4 +1,9 @@
/// <reference types="cypress" /> /// <reference types="cypress" />
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 newProposalButton = '[data-testid="new-proposal-link"]';
const newProposalDatabox = '[data-testid="proposal-data"]'; const newProposalDatabox = '[data-testid="proposal-data"]';
const newProposalSubmitButton = '[data-testid="proposal-submit"]'; 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 proposalInformationTableRows = '[data-testid="key-value-table-row"]';
const openProposals = '[data-testid="open-proposals"]'; const openProposals = '[data-testid="open-proposals"]';
const vegaWalletAssociatedBalance = '[data-testid="currency-value"]'; 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 txTimeout = Cypress.env('txTimeout');
const epochTimeout = Cypress.env('epochTimeout');
context('Governance flow - with eth and vega wallets connected', function () { context('Governance flow - with eth and vega wallets connected', function () {
before('connect wallets and set approval limit', 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( cy.wrap(
network_parameters['governance.proposal.freeform.minProposerBalance'] network_parameters['governance.proposal.freeform.minProposerBalance']
).as('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( cy.wrap(
network_parameters['governance.proposal.freeform.minClose'].split( network_parameters['governance.proposal.freeform.minClose'].split(
'h' 'h'
@ -33,11 +64,43 @@ context('Governance flow - with eth and vega wallets connected', function () {
cy.vega_wallet_connect(); cy.vega_wallet_connect();
cy.vega_wallet_set_specified_approval_amount('1000'); cy.vega_wallet_set_specified_approval_amount('1000');
cy.reload(); cy.reload();
cy.wait_for_spinner();
cy.verify_page_header('The $VEGA token'); cy.verify_page_header('The $VEGA token');
cy.ethereum_wallet_connect(); cy.ethereum_wallet_connect();
}); });
describe('Eth wallet - contains VEGA tokens', function () { 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 () { beforeEach('visit staking tab', function () {
cy.navigate_to('staking'); cy.navigate_to('staking');
cy.wait_for_spinner(); 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( cy.ensure_specified_unstaked_tokens_are_associated(
this.minProposerBalance this.minProposerBalance
); );
cy.navigate_to('governance'); cy.navigate_to('governance');
cy.wait_for_spinner(); cy.wait_for_spinner();
cy.get(newProposalButton).should('be.visible').click(); cy.get(newProposalButton).should('be.visible').click();
cy.get(newProposalDatabox).click();
cy.create_ten_digit_unix_timestamp_for_specified_days('7').then( cy.create_ten_digit_unix_timestamp_for_specified_days('7').then(
(closingDateTimestamp) => { (closingDateTimestamp) => {
cy.enter_unique_freeform_proposal_body(closingDateTimestamp); cy.enter_unique_freeform_proposal_body(closingDateTimestamp);
} }
); );
cy.get(newProposalSubmitButton).should('be.visible').click(); 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(); 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 () { it('Newly created freeform proposal - shows in an open state', function () {
cy.ensure_specified_unstaked_tokens_are_associated( cy.ensure_specified_unstaked_tokens_are_associated(
this.minProposerBalance this.minProposerBalance
@ -73,43 +245,41 @@ context('Governance flow - with eth and vega wallets connected', function () {
cy.navigate_to('governance'); cy.navigate_to('governance');
cy.wait_for_spinner(); cy.wait_for_spinner();
cy.get(newProposalButton).should('be.visible').click(); cy.get(newProposalButton).should('be.visible').click();
cy.get(newProposalDatabox).click();
cy.create_ten_digit_unix_timestamp_for_specified_days('8').then( cy.create_ten_digit_unix_timestamp_for_specified_days('8').then(
(closingDateTimestamp) => { (closingDateTimestamp) => {
cy.enter_unique_freeform_proposal_body(closingDateTimestamp); cy.enter_unique_freeform_proposal_body(closingDateTimestamp);
} }
); );
cy.get(newProposalSubmitButton).should('be.visible').click(); 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.get(dialogCloseButton).click();
cy.wait('@proposalSubmissionCompletion') cy.wait_for_proposal_sync();
.its(proposalResponseIdPath)
.then((proposalId) => {
cy.navigate_to('governance'); cy.navigate_to('governance');
cy.wait_for_spinner(); cy.wait_for_spinner();
cy.wait('@proposalSubmissionCompletion')
.its(proposalResponseProposalIdPath)
.then((proposalId) => {
cy.get(openProposals).within(() => { cy.get(openProposals).within(() => {
cy.get(`#${proposalId}`) cy.get(`#${proposalId}`)
.should('contain', `Freeform proposal: ${proposalId}`) .should('contain', `Freeform proposal: ${proposalId}`, txTimeout)
.and('contain', 'Open') .and('contain', 'Open')
.and('be.visible') .and('be.visible')
.within(() => { .within(() => {
cy.get(viewProposalButton).should('be.visible').click(); cy.get(viewProposalButton).should('be.visible').click();
}); });
}); });
cy.get(proposalInformationTableRows) cy.get_proposal_information_from_table('ID')
.contains('ID')
.siblings()
.contains(proposalId) .contains(proposalId)
.should('be.visible'); .and('be.visible');
cy.get(proposalInformationTableRows) cy.get_proposal_information_from_table('State')
.contains('State') .contains('STATE_OPEN')
.siblings() .and('be.visible');
.contains('Open') cy.get_proposal_information_from_table('Type')
.should('be.visible'); .contains('NewFreeform')
cy.get(proposalInformationTableRows) .and('be.visible');
.contains('Type')
.siblings()
.contains('NewFreeform');
}); });
}); });
@ -120,43 +290,39 @@ context('Governance flow - with eth and vega wallets connected', function () {
cy.navigate_to('governance'); cy.navigate_to('governance');
cy.wait_for_spinner(); cy.wait_for_spinner();
cy.get(newProposalButton).should('be.visible').click(); cy.get(newProposalButton).should('be.visible').click();
cy.get(newProposalDatabox).click();
cy.create_ten_digit_unix_timestamp_for_specified_days('9').then( cy.create_ten_digit_unix_timestamp_for_specified_days('9').then(
(closingDateTimestamp) => { (closingDateTimestamp) => {
cy.enter_unique_freeform_proposal_body(closingDateTimestamp); cy.enter_unique_freeform_proposal_body(closingDateTimestamp);
cy.get(newProposalSubmitButton).should('be.visible').click(); 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.get(dialogCloseButton).click();
cy.wait_for_proposal_sync();
cy.navigate_to('governance'); cy.navigate_to('governance');
cy.wait_for_spinner(); cy.wait_for_spinner();
cy.get_submitted_proposal().within(() => cy.get_submitted_proposal_from_proposal_list().within(() =>
cy.get(viewProposalButton).click() cy.get(viewProposalButton).click()
); );
cy.convert_unix_timestamp_to_governance_data_table_date_format( cy.convert_unix_timestamp_to_governance_data_table_date_format(
closingDateTimestamp closingDateTimestamp
).then((closingDate) => { ).then((closingDate) => {
cy.get(proposalInformationTableRows) cy.get_proposal_information_from_table('Closes on')
.contains('Closes on')
.siblings()
.contains(closingDate) .contains(closingDate)
.should('be.visible'); .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( cy.get_governance_proposal_date_format_for_specified_days('0').then(
now (proposalDate) => {
).then((proposalDate) => { cy.get_proposal_information_from_table('Proposed on')
cy.get(proposalInformationTableRows)
.contains('Proposed on')
.siblings()
.contains(proposalDate) .contains(proposalDate)
.should('be.visible'); .should('be.visible');
});
} }
); );
cy.contains('9 days left to vote').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 () { 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.navigate_to('governance');
cy.wait_for_spinner(); cy.wait_for_spinner();
cy.get(newProposalButton).should('be.visible').click(); cy.get(newProposalButton).should('be.visible').click();
cy.get(newProposalDatabox).click();
cy.create_ten_digit_unix_timestamp_for_specified_days('7').then( cy.create_ten_digit_unix_timestamp_for_specified_days('7').then(
(closingDateTimestamp) => { (closingDateTimestamp) => {
cy.enter_unique_freeform_proposal_body(closingDateTimestamp); cy.enter_unique_freeform_proposal_body(closingDateTimestamp);
} }
); );
cy.get(newProposalSubmitButton).should('be.visible').click(); 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.get(dialogCloseButton).click();
cy.wait_for_proposal_sync();
cy.navigate_to('governance'); cy.navigate_to('governance');
cy.wait_for_spinner(); cy.wait_for_spinner();
cy.get_submitted_proposal().within(() => cy.get_submitted_proposal_from_proposal_list().within(() =>
cy.get(viewProposalButton).click() cy.get(viewProposalButton).click()
); );
cy.contains('Currently set to fail').should('be.visible'); cy.contains('Currently set to fail').should('be.visible');
cy.contains('Participation: Not Met 0.00 0.00%(0.00% Required)').should( cy.contains('Participation: Not Met 0.00 0.00%(0.00% Required)').should(
'be.visible' 'be.visible'
); );
cy.get(proposalInformationTableRows) cy.get_proposal_information_from_table('Will pass')
.contains('Will pass')
.siblings()
.contains('👎') .contains('👎')
.should('be.visible'); .should('be.visible');
cy.get(proposalInformationTableRows) cy.get_proposal_information_from_table('Majority met')
.contains('Majority met')
.siblings()
.contains('👎') .contains('👎')
.should('be.visible'); .should('be.visible');
cy.get(proposalInformationTableRows) cy.get_proposal_information_from_table('Participation met')
.contains('Participation met')
.siblings()
.contains('👎') .contains('👎')
.should('be.visible'); .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 () { it('Creating a proposal - proposal rejected - when closing time sooner than system default', function () {
cy.ensure_specified_unstaked_tokens_are_associated( cy.ensure_specified_unstaked_tokens_are_associated(
this.minProposerBalance this.minProposerBalance
@ -208,37 +670,25 @@ context('Governance flow - with eth and vega wallets connected', function () {
cy.navigate_to('governance'); cy.navigate_to('governance');
cy.wait_for_spinner(); cy.wait_for_spinner();
cy.get(newProposalButton).should('be.visible').click(); cy.get(newProposalButton).should('be.visible').click();
cy.get(newProposalDatabox).click();
cy.create_ten_digit_unix_timestamp_for_specified_days( cy.create_ten_digit_unix_timestamp_for_specified_days(
this.minCloseDays - 1 this.minCloseDays - 1
).then((closingDateTimestamp) => { ).then((closingDateTimestamp) => {
cy.enter_unique_freeform_proposal_body(closingDateTimestamp); cy.enter_unique_freeform_proposal_body(closingDateTimestamp);
}); });
cy.get(newProposalSubmitButton).should('be.visible').click(); 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.get(dialogCloseButton).click();
cy.wait_for_proposal_sync();
cy.navigate_to('governance'); cy.navigate_to('governance');
cy.wait_for_spinner(); 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('Rejected').should('be.visible');
cy.contains('Close time too soon').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 () { 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.navigate_to('governance');
cy.wait_for_spinner(); cy.wait_for_spinner();
cy.get(newProposalButton).should('be.visible').click(); cy.get(newProposalButton).should('be.visible').click();
cy.get(newProposalDatabox).click();
cy.create_ten_digit_unix_timestamp_for_specified_days( cy.create_ten_digit_unix_timestamp_for_specified_days(
this.maxCloseDays + 1 this.maxCloseDays + 1
).then((closingDateTimestamp) => { ).then((closingDateTimestamp) => {
cy.enter_unique_freeform_proposal_body(closingDateTimestamp); cy.enter_unique_freeform_proposal_body(closingDateTimestamp);
}); });
cy.get(newProposalSubmitButton).should('be.visible').click(); 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.get(dialogCloseButton).click();
cy.wait_for_proposal_sync();
cy.navigate_to('governance'); cy.navigate_to('governance');
cy.wait_for_spinner(); 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('Rejected').should('be.visible');
cy.contains('Close time too late').should('be.visible'); cy.contains('Close time too late').should('be.visible');
cy.get(viewProposalButton).click(); cy.get(viewProposalButton).click();
}); });
cy.get(proposalInformationTableRows) cy.get_proposal_information_from_table('State')
.contains('State') .contains('STATE_REJECTED')
.siblings() .and('be.visible');
.contains('Rejected') cy.get_proposal_information_from_table('Rejection reason')
.should('be.visible'); .contains('PROPOSAL_ERROR_CLOSE_TIME_TOO_LATE')
cy.get(proposalInformationTableRows) .and('be.visible');
.contains('Rejection reason') cy.get_proposal_information_from_table('Error details')
.siblings()
.contains('CloseTimeTooLate')
.should('be.visible');
cy.get(proposalInformationTableRows)
.contains('Error details')
.siblings()
.contains('proposal closing time too late') .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 () { 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.navigate_to('governance');
cy.wait_for_spinner(); cy.wait_for_spinner();
cy.get(newProposalButton).should('be.visible').click(); cy.get(newProposalButton).should('be.visible').click();
cy.get(newProposalDatabox).click();
cy.create_ten_digit_unix_timestamp_for_specified_days('1').then( cy.create_ten_digit_unix_timestamp_for_specified_days('1').then(
(closingDateTimestamp) => { (closingDateTimestamp) => {
cy.enter_unique_freeform_proposal_body(closingDateTimestamp); cy.enter_unique_freeform_proposal_body(closingDateTimestamp);
} }
); );
cy.get(newProposalSubmitButton).should('be.visible').click(); cy.get(newProposalSubmitButton).should('be.visible').click();
cy.wait('@proposalSubmissionCompletion');
cy.contains( cy.contains('Transaction failed', epochTimeout).should('be.visible');
'party has insufficient tokens to submit proposal request in this epoch' cy.get(feedbackError)
).should('be.visible'); .contains(
cy.get(dialogCloseButton).click(); '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 () { it('Unable to create a freeform proposal - when some but not enough tokens are associated', function () {
cy.ensure_specified_unstaked_tokens_are_associated( cy.ensure_specified_unstaked_tokens_are_associated(
this.minProposerBalance - 0.1 this.minProposerBalance - 0.000001
); );
cy.navigate_to('governance'); cy.navigate_to('governance');
cy.wait_for_spinner(); cy.wait_for_spinner();
cy.get(newProposalButton).should('be.visible').click(); cy.get(newProposalButton).should('be.visible').click();
cy.get(newProposalDatabox).click();
cy.create_ten_digit_unix_timestamp_for_specified_days('1').then( cy.create_ten_digit_unix_timestamp_for_specified_days('1').then(
(closingDateTimestamp) => { (closingDateTimestamp) => {
cy.enter_unique_freeform_proposal_body(closingDateTimestamp); cy.enter_unique_freeform_proposal_body(closingDateTimestamp);
} }
); );
cy.get(newProposalSubmitButton).should('be.visible').click(); cy.get(newProposalSubmitButton).should('be.visible').click();
cy.wait('@proposalSubmissionCompletion');
cy.contains( cy.contains('Transaction failed', epochTimeout).should('be.visible');
'party has insufficient tokens to submit proposal request in this epoch' cy.get(feedbackError)
).should('be.visible'); .contains(
cy.get(dialogCloseButton).click(); 'Party has insufficient associated governance tokens in their staking account to submit proposal request'
)
.should('be.visible');
}); });
Cypress.Commands.add( Cypress.Commands.add(
'convert_unix_timestamp_to_governance_data_table_date_format', 'convert_unix_timestamp_to_governance_data_table_date_format',
(unixTimestamp) => { (unixTimestamp, monthTextLength = 'longMonth') => {
let dateSupplied = new Date(unixTimestamp * 1000), let dateSupplied = new Date(unixTimestamp * 1000),
year = dateSupplied.getFullYear(), year = dateSupplied.getFullYear(),
months = [ months = [
@ -345,9 +823,11 @@ context('Governance flow - with eth and vega wallets connected', function () {
'December', 'December',
], ],
month = months[dateSupplied.getMonth()], month = months[dateSupplied.getMonth()],
shortMonth = months[dateSupplied.getMonth()].substring(0, 3),
date = dateSupplied.getDate(); 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) => { Cypress.Commands.add('enter_unique_freeform_proposal_body', (timestamp) => {
cy.fixture('/proposals/freeform.json').then((freeformProposal) => { cy.fixture('/proposals/freeform.json').then((freeformProposal) => {
freeformProposal.terms.closingTimestamp = timestamp; freeformProposal.terms.closingTimestamp = timestamp;
freeformProposal.rationale.description += timestamp; freeformProposal.rationale.title += timestamp;
let proposalPayload = JSON.stringify(freeformProposal); let proposalPayload = JSON.stringify(freeformProposal);
cy.get(newProposalDatabox).type(proposalPayload, { cy.get(newProposalDatabox).type(proposalPayload, {
@ -385,7 +865,7 @@ context('Governance flow - with eth and vega wallets connected', function () {
}, },
headers: { 'content-type': 'application/json' }, headers: { 'content-type': 'application/json' },
}) })
.its('body.data.networkParameters') .its(`body.data.networkParameters`)
.then(function (response) { .then(function (response) {
let object = response.reduce(function (r, e) { let object = response.reduce(function (r, e) {
r[e.key] = e.value; r[e.key] = e.value;
@ -396,11 +876,73 @@ 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') cy.wait('@proposalSubmissionCompletion')
.its(proposalResponseIdPath) .its(proposalResponseProposalIdPath)
.then((proposalId) => { .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();
}
}); });
}); });
}); });

View File

@ -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 () { it('Able to stake against a validator - using vega from wallet', function () {
cy.staking_page_associate_tokens('3'); 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 () { 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.staking_page_associate_tokens('3');
cy.get(vegaWalletUnstakedBalance, txTimeout).should( 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 () { 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.staking_page_associate_tokens('3', { type: 'contract' });
cy.get(vegaWalletUnstakedBalance, txTimeout).should( 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 () { 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.staking_page_associate_tokens('3', { type: 'wallet' });
cy.get(vegaWalletUnstakedBalance, txTimeout).should( 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 () { 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.staking_page_associate_tokens('6');
cy.get(vegaWalletUnstakedBalance, txTimeout).should( cy.get(vegaWalletUnstakedBalance, txTimeout).should(

View File

@ -145,6 +145,7 @@ export const VoteButtons = ({
) : null} ) : null}
{proposalState === ProposalState.STATE_OPEN ? ( {proposalState === ProposalState.STATE_OPEN ? (
<ButtonLink <ButtonLink
data-testid="change-vote-button"
onClick={() => { onClick={() => {
setChangeVote(true); setChangeVote(true);
}} }}
@ -161,7 +162,7 @@ export const VoteButtons = ({
} }
return ( return (
<div className="flex gap-4"> <div className="flex gap-4" data-testid="vote-buttons">
<div className="flex-1"> <div className="flex-1">
<Button onClick={() => submitVote(VoteValue.VALUE_YES)}> <Button onClick={() => submitVote(VoteValue.VALUE_YES)}>
{t('voteFor')} {t('voteFor')}

View File

@ -67,21 +67,33 @@ export const VoteDetails = ({ proposal }: VoteDetailsProps) => {
</thead> </thead>
<tbody> <tbody>
<tr> <tr>
<td className="text-left"> <td
className="text-left"
data-testid="vote-progress-indicator-percentage-for"
>
{yesPercentage.toFixed(defaultDecimals)}% {yesPercentage.toFixed(defaultDecimals)}%
</td> </td>
<td className="text-center text-white"> <td className="text-center text-white">
{t('majorityRequired')}{' '} {t('majorityRequired')}{' '}
{requiredMajorityPercentage.toFixed(defaultDecimals)}% {requiredMajorityPercentage.toFixed(defaultDecimals)}%
</td> </td>
<td className="text-right"> <td
className="text-right"
data-testid="vote-progress-indicator-percentage-against"
>
{noPercentage.toFixed(defaultDecimals)}% {noPercentage.toFixed(defaultDecimals)}%
</td> </td>
</tr> </tr>
<tr> <tr>
<td> {formatNumber(yesTokens, defaultDecimals)}</td> <td data-testid="vote-progress-indicator-tokens-for">
{' '}
{formatNumber(yesTokens, defaultDecimals)}{' '}
</td>
<td></td> <td></td>
<td className="text-right"> <td
data-testid="vote-progress-indicator-tokens-against"
className="text-right"
>
{formatNumber(noTokens, defaultDecimals)} {formatNumber(noTokens, defaultDecimals)}
</td> </td>
</tr> </tr>

101
vegacapsule/config.hcl Normal file
View File

@ -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"
}
}
}

231
vegacapsule/genesis.tmpl Normal file
View File

@ -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"
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"
}
}

View File

@ -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"
}
}