Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c8d7b24f4 | ||
|
|
0b33639cf1 | ||
|
|
73d5a34c34 | ||
|
|
f3d4082b45 | ||
|
|
620c8f9809 | ||
|
|
06c347cc34 | ||
|
|
70bf495ddc | ||
|
|
08e204fe31 | ||
|
|
81f7b0595e | ||
|
|
4ed0e3a056 | ||
|
|
47a84b4dac |
@@ -10,7 +10,7 @@ on:
|
||||
jobs:
|
||||
run-tests:
|
||||
name: run-tests
|
||||
runs-on: 8-cores
|
||||
runs-on: console-test
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
#----------------------------------------------
|
||||
@@ -33,15 +33,6 @@ jobs:
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cache-node-modules-
|
||||
#----------------------------------------------
|
||||
# setup node
|
||||
#----------------------------------------------
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
|
||||
cache: yarn
|
||||
#----------------------------------------------
|
||||
# install deps if cache missing
|
||||
#----------------------------------------------
|
||||
- name: yarn install
|
||||
@@ -76,32 +67,6 @@ jobs:
|
||||
repository: vegaprotocol/console-test
|
||||
path: './console-test'
|
||||
#----------------------------------------------
|
||||
# set-up python
|
||||
#----------------------------------------------
|
||||
- name: Set up python
|
||||
id: setup-python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.10.11'
|
||||
#----------------------------------------------
|
||||
# ----- install & configure poetry -----
|
||||
#----------------------------------------------
|
||||
- name: Install Poetry
|
||||
uses: snok/install-poetry@v1
|
||||
with:
|
||||
virtualenvs-create: true
|
||||
virtualenvs-in-project: true
|
||||
virtualenvs-path: console-test/.venv
|
||||
#----------------------------------------------
|
||||
# load cached venv if cache exists
|
||||
#----------------------------------------------
|
||||
- name: Load cached venv
|
||||
id: cached-poetry-dependencies
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: console-test/.venv
|
||||
key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }}
|
||||
#----------------------------------------------
|
||||
# install dependencies if cache does not exist
|
||||
#----------------------------------------------
|
||||
- name: Install dependencies
|
||||
@@ -125,7 +90,7 @@ jobs:
|
||||
#----------------------------------------------
|
||||
- name: Run tests
|
||||
working-directory: ./console-test
|
||||
run: poetry run pytest -v -s --numprocesses auto --dist loadfile --durations=20
|
||||
run: poetry run pytest -v -s --numprocesses 2 --dist loadfile --durations=20
|
||||
- name: Check files
|
||||
run: |
|
||||
ls -al .
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
context('Network parameters page', { tags: '@smoke' }, function () {
|
||||
before('navigate to network parameter page', function () {
|
||||
cy.fixture('net_parameter_format_lookup').as('networkParameterFormat');
|
||||
cy.visit('/network-parameters');
|
||||
});
|
||||
describe('Verify elements on page', function () {
|
||||
beforeEach(() => {
|
||||
cy.visit('/network-parameters');
|
||||
});
|
||||
|
||||
const networkParametersHeader = '[data-testid="network-param-header"]';
|
||||
const tableRows = '[data-testid="key-value-table-row"]';
|
||||
|
||||
@@ -16,6 +13,7 @@ context('Network parameters page', { tags: '@smoke' }, function () {
|
||||
.and('be.visible');
|
||||
});
|
||||
|
||||
// 0006-NETW-021
|
||||
it('should list each of the network parameters available', function () {
|
||||
cy.get_network_parameters().then((network_parameters) => {
|
||||
const numberOfNetworkParametersInSystem =
|
||||
@@ -198,6 +196,19 @@ context('Network parameters page', { tags: '@smoke' }, function () {
|
||||
});
|
||||
});
|
||||
|
||||
// 0006-NETW-022 0006-NETW-023
|
||||
it('governance assets should be correctly grouped', function () {
|
||||
cy.getByTestId('governance')
|
||||
.should('exist')
|
||||
.parent()
|
||||
.should('have.attr', 'href', '/network-parameters#governance');
|
||||
cy.get('[id="governance-proposal-asset"]')
|
||||
.parent()
|
||||
.within(() => {
|
||||
cy.getByTestId('key-value-table-row').should('have.length', 8);
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to see network parameters - on mobile', function () {
|
||||
cy.switchToMobile();
|
||||
cy.get_network_parameters().then((network_parameters) => {
|
||||
|
||||
@@ -34,19 +34,20 @@ import { formatDateWithLocalTimezone } from '@vegaprotocol/utils';
|
||||
import { createSuccessorMarketProposalTxBody } from '../../support/proposal.functions';
|
||||
|
||||
const proposalListItem = '[data-testid="proposals-list-item"]';
|
||||
const proposalVoteProgressForPercentage =
|
||||
'vote-progress-indicator-percentage-for';
|
||||
const proposalVoteProgressAgainstPercentage =
|
||||
'vote-progress-indicator-percentage-against';
|
||||
const proposalVoteProgressForTokens = 'vote-progress-indicator-tokens-for';
|
||||
const proposalVoteProgressAgainstTokens =
|
||||
'vote-progress-indicator-tokens-against';
|
||||
const participationNotMet = 'token-participation-not-met';
|
||||
const voteStatus = 'vote-status';
|
||||
const voteMajorityNotMet = 'token-majority-not-met';
|
||||
const numberOfVotesFor = 'num-votes-for';
|
||||
const votesForPercentage = 'votes-for-percentage';
|
||||
const numberOfVotesAgainst = 'num-votes-against';
|
||||
const votesAgainstPercentage = 'votes-against-percentage';
|
||||
const totalVotedNumber = 'total-voted';
|
||||
const totalVotedPercentage = 'total-voted-percentage';
|
||||
const changeVoteButton = 'change-vote-button';
|
||||
const proposalDetailsTitle = 'proposal-title';
|
||||
const proposalDetailsDescription = 'proposal-description';
|
||||
const openProposals = 'open-proposals';
|
||||
const viewProposalButton = 'view-proposal-btn';
|
||||
const voteBreakdownToggle = 'vote-breakdown-toggle';
|
||||
const proposalTermsToggle = 'proposal-json-toggle';
|
||||
const marketDataToggle = 'proposal-market-data-toggle';
|
||||
|
||||
@@ -150,29 +151,32 @@ describe(
|
||||
// 3001-VOTE-037
|
||||
// 3001-VOTE-040
|
||||
// 3001-VOTE-067
|
||||
// 3001-VOTE-023
|
||||
createRawProposal();
|
||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||
getProposalFromTitle(rawProposal.rationale.title).within(() =>
|
||||
cy.getByTestId(viewProposalButton).click()
|
||||
);
|
||||
});
|
||||
cy.contains('Participation: Not Met 0.00 0.00%(0.00% Required)').should(
|
||||
'be.visible'
|
||||
cy.getByTestId(participationNotMet).should(
|
||||
'have.text',
|
||||
'0.000000000000000000000015% participation threshold not met'
|
||||
);
|
||||
cy.getByTestId(voteMajorityNotMet).should(
|
||||
'have.text',
|
||||
'66% majority threshold not met'
|
||||
);
|
||||
cy.getByTestId(voteStatus).should(
|
||||
'have.text',
|
||||
'Currently expected to fail'
|
||||
);
|
||||
cy.getByTestId(voteBreakdownToggle).click();
|
||||
getProposalInformationFromTable('Expected to pass')
|
||||
.contains('👎')
|
||||
.should('be.visible');
|
||||
// 3001-VOTE-062
|
||||
// 3001-VOTE-040
|
||||
// 3001-VOTE-070
|
||||
getProposalInformationFromTable('Token majority met')
|
||||
.contains('👎')
|
||||
.should('be.visible');
|
||||
// 3001-VOTE-068
|
||||
getProposalInformationFromTable('Token participation met')
|
||||
.contains('👎')
|
||||
.should('be.visible');
|
||||
cy.getByTestId(numberOfVotesFor).should('have.text', '0.0M');
|
||||
cy.getByTestId(numberOfVotesAgainst).should('have.text', '0.0M');
|
||||
cy.getByTestId(totalVotedNumber).should('have.text', '0.0M');
|
||||
});
|
||||
|
||||
// 3001-VOTE-080 3001-VOTE-090 3001-VOTE-069 3001-VOTE-072 3001-VOTE-073
|
||||
@@ -197,43 +201,16 @@ describe(
|
||||
.contains(votedDate)
|
||||
.should('be.visible');
|
||||
});
|
||||
cy.getByTestId(proposalVoteProgressForPercentage) // 3001-VOTE-072
|
||||
.contains('100.00%')
|
||||
.and('be.visible');
|
||||
cy.getByTestId(proposalVoteProgressAgainstPercentage)
|
||||
.contains('0.00%')
|
||||
.and('be.visible');
|
||||
cy.getByTestId(proposalVoteProgressForTokens)
|
||||
.contains('1.00')
|
||||
.and('be.visible');
|
||||
cy.getByTestId(proposalVoteProgressAgainstTokens)
|
||||
.contains('0.00')
|
||||
.and('be.visible');
|
||||
cy.getByTestId(voteBreakdownToggle).click();
|
||||
getProposalInformationFromTable('Tokens for proposal')
|
||||
.should('have.text', (1).toFixed(2))
|
||||
.and('be.visible');
|
||||
getProposalInformationFromTable('Tokens against proposal')
|
||||
.should('have.text', '0.00')
|
||||
.and('be.visible');
|
||||
// 3001-VOTE-061
|
||||
getProposalInformationFromTable('Participation required')
|
||||
.contains('0.00%')
|
||||
.should('be.visible');
|
||||
// 3001-VOTE-066
|
||||
getProposalInformationFromTable('Majority Required') // 3001-VOTE-073
|
||||
.contains(`${(66).toFixed(2)}%`)
|
||||
.should('be.visible');
|
||||
getProposalInformationFromTable('Number of voting parties')
|
||||
.should('have.text', '1')
|
||||
.and('be.visible');
|
||||
cy.getByTestId(votesForPercentage) // 3001-VOTE-072
|
||||
.should('have.text', '100%');
|
||||
cy.getByTestId(votesAgainstPercentage).should('have.text', '0%');
|
||||
cy.getByTestId('token-majority-progress')
|
||||
.should('have.attr', 'style')
|
||||
.and('eq', 'width: 100%;'); // 3001-VOTE-024
|
||||
cy.getByTestId(changeVoteButton).should('be.visible').click();
|
||||
voteForProposal('for');
|
||||
// 3001-VOTE-064
|
||||
cy.getByTestId('user-voted-yes').should('exist');
|
||||
getProposalInformationFromTable('Tokens for proposal')
|
||||
.should('have.text', (1).toFixed(2))
|
||||
.and('be.visible');
|
||||
navigateTo(navigation.proposals);
|
||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||
getProposalFromTitle(rawProposal.rationale.title).within(() => {
|
||||
@@ -244,16 +221,7 @@ describe(
|
||||
});
|
||||
cy.getByTestId(changeVoteButton).should('be.visible').click();
|
||||
voteForProposal('against');
|
||||
cy.getByTestId(proposalVoteProgressAgainstPercentage)
|
||||
.contains('100.00%')
|
||||
.and('be.visible');
|
||||
cy.getByTestId(voteBreakdownToggle).click();
|
||||
getProposalInformationFromTable('Tokens against proposal')
|
||||
.should('have.text', (1).toFixed(2))
|
||||
.and('be.visible');
|
||||
getProposalInformationFromTable('Number of voting parties')
|
||||
.should('have.text', '1')
|
||||
.and('be.visible');
|
||||
cy.getByTestId(votesAgainstPercentage).should('have.text', '100%');
|
||||
navigateTo(navigation.proposals);
|
||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||
getProposalFromTitle(rawProposal.rationale.title).within(() => {
|
||||
@@ -265,6 +233,7 @@ describe(
|
||||
|
||||
// 3001-VOTE-042, 3001-VOTE-057, 3001-VOTE-058, 3001-VOTE-059, 3001-VOTE-060
|
||||
it('Newly created proposal details - ability to increase associated tokens - by voting again after association', function () {
|
||||
ensureSpecifiedUnstakedTokensAreAssociated('1');
|
||||
vegaWalletSetSpecifiedApprovalAmount('1000');
|
||||
createRawProposal();
|
||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||
@@ -275,69 +244,28 @@ describe(
|
||||
voteForProposal('for');
|
||||
// 3001-VOTE-079
|
||||
cy.contains('You voted: For').should('be.visible');
|
||||
cy.getByTestId(proposalVoteProgressForTokens)
|
||||
.contains('1')
|
||||
.and('be.visible');
|
||||
cy.getByTestId(voteBreakdownToggle).click();
|
||||
getProposalInformationFromTable('Total Supply')
|
||||
.invoke('text')
|
||||
.then((totalSupply) => {
|
||||
const tokensRequiredToAchieveResult = (
|
||||
(Number(totalSupply.replace(/,/g, '')) * 0.001) /
|
||||
100
|
||||
).toFixed(2);
|
||||
ethereumWalletConnect();
|
||||
ensureSpecifiedUnstakedTokensAreAssociated(
|
||||
tokensRequiredToAchieveResult
|
||||
);
|
||||
navigateTo(navigation.proposals);
|
||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||
getProposalFromTitle(rawProposal.rationale.title).within(() =>
|
||||
cy.getByTestId(viewProposalButton).click()
|
||||
);
|
||||
});
|
||||
cy.getByTestId(proposalVoteProgressForPercentage)
|
||||
.contains('100.00%')
|
||||
.and('be.visible');
|
||||
cy.getByTestId(proposalVoteProgressAgainstPercentage)
|
||||
.contains('0.00%')
|
||||
.and('be.visible');
|
||||
// 3001-VOTE-065
|
||||
cy.getByTestId(changeVoteButton).should('be.visible').click();
|
||||
voteForProposal('for');
|
||||
cy.getByTestId(proposalVoteProgressForTokens)
|
||||
.contains(tokensRequiredToAchieveResult)
|
||||
.and('be.visible');
|
||||
cy.getByTestId(proposalVoteProgressAgainstTokens)
|
||||
.contains('0.00')
|
||||
.and('be.visible');
|
||||
cy.getByTestId(voteBreakdownToggle).click();
|
||||
getProposalInformationFromTable('Total tokens voted percentage')
|
||||
.should('have.text', '0.00%')
|
||||
.and('be.visible');
|
||||
getProposalInformationFromTable('Tokens for proposal')
|
||||
.should('have.text', tokensRequiredToAchieveResult)
|
||||
.and('be.visible');
|
||||
getProposalInformationFromTable('Tokens against proposal')
|
||||
.should('have.text', '0.00')
|
||||
.and('be.visible');
|
||||
getProposalInformationFromTable('Number of voting parties')
|
||||
.should('have.text', '1')
|
||||
.and('be.visible');
|
||||
getProposalInformationFromTable('Expected to pass')
|
||||
.contains('👍')
|
||||
.should('be.visible');
|
||||
// 3001-VOTE-062
|
||||
getProposalInformationFromTable('Token majority met')
|
||||
.contains('👍')
|
||||
.should('be.visible');
|
||||
getProposalInformationFromTable('Token participation met')
|
||||
.contains('👍')
|
||||
.should('be.visible');
|
||||
getProposalInformationFromTable('Tokens for proposal')
|
||||
.contains(tokensRequiredToAchieveResult)
|
||||
.and('be.visible');
|
||||
});
|
||||
cy.getByTestId(numberOfVotesFor).should('have.text', '0.0M');
|
||||
cy.getByTestId(votesForPercentage).should('have.text', '100%');
|
||||
cy.getByTestId(totalVotedNumber).should('have.text', '0.0M');
|
||||
cy.getByTestId(totalVotedPercentage).should('have.text', '(0.00%)');
|
||||
ethereumWalletConnect();
|
||||
stakingPageAssociateTokens('1000000', { approve: true });
|
||||
navigateTo(navigation.proposals);
|
||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||
getProposalFromTitle(rawProposal.rationale.title).within(() =>
|
||||
cy.getByTestId(viewProposalButton).click()
|
||||
);
|
||||
});
|
||||
cy.getByTestId(votesForPercentage).should('have.text', '100%');
|
||||
cy.getByTestId(numberOfVotesFor).should('have.text', '0.0M');
|
||||
cy.getByTestId(totalVotedNumber).should('have.text', '0.0M');
|
||||
cy.getByTestId(totalVotedPercentage).should('have.text', '(0.00%)');
|
||||
// 3001-VOTE-065
|
||||
cy.getByTestId(changeVoteButton).should('be.visible').click();
|
||||
voteForProposal('for');
|
||||
cy.getByTestId(numberOfVotesFor).should('have.text', '1.0M');
|
||||
cy.getByTestId(totalVotedNumber).should('have.text', '1.0M');
|
||||
cy.getByTestId(totalVotedPercentage).should('have.text', '(1.54%)');
|
||||
});
|
||||
|
||||
it('Able to vote for proposal twice by switching public key', function () {
|
||||
@@ -360,10 +288,6 @@ describe(
|
||||
voteForProposal('against');
|
||||
cy.contains('You voted: Against').should('be.visible');
|
||||
switchVegaWalletPubKey();
|
||||
cy.getByTestId(proposalVoteProgressForTokens).should(
|
||||
'contain.text',
|
||||
'1.00'
|
||||
);
|
||||
// Checking vote status for different public keys is displayed correctly
|
||||
cy.contains('You voted: For').should('be.visible');
|
||||
});
|
||||
|
||||
@@ -22,12 +22,10 @@ const proposalListItem = '[data-testid="proposals-list-item"]';
|
||||
const closedProposals = 'closed-proposals';
|
||||
const proposalStatus = 'proposal-status';
|
||||
const viewProposalButton = 'view-proposal-btn';
|
||||
const votesTable = 'votes-table';
|
||||
const votesTable = 'user-vote';
|
||||
const openProposals = 'open-proposals';
|
||||
const proposalVoteProgressForPercentage =
|
||||
'vote-progress-indicator-percentage-for';
|
||||
const majorityVoteReached = 'majority-reached';
|
||||
const minParticipationReached = 'participation-reached';
|
||||
const majorityVoteReached = 'token-majority-met';
|
||||
const minParticipationReached = 'token-participation-met';
|
||||
const proposalTimeout = { timeout: 8000 };
|
||||
|
||||
context(
|
||||
@@ -70,7 +68,6 @@ context(
|
||||
cy.getByTestId('proposal-type').should('have.text', 'New market');
|
||||
cy.getByTestId(proposalStatus).should('have.text', 'Enacted');
|
||||
cy.getByTestId(votesTable).within(() => {
|
||||
cy.contains('Vote passed.').should('be.visible');
|
||||
cy.contains('Voting has ended.').should('be.visible');
|
||||
});
|
||||
});
|
||||
@@ -92,7 +89,7 @@ context(
|
||||
// 3001-VOTE-019 time to vote is highlighted red
|
||||
cy.getByTestId('vote-details')
|
||||
.find('span')
|
||||
.should('have.class', 'text-vega-pink');
|
||||
.should('have.class', 'text-vega-orange');
|
||||
cy.getByTestId(viewProposalButton).click();
|
||||
});
|
||||
});
|
||||
@@ -109,12 +106,9 @@ context(
|
||||
);
|
||||
});
|
||||
cy.getByTestId(votesTable).within(() => {
|
||||
cy.contains('Vote passed.').should('be.visible');
|
||||
cy.contains('Voting has ended.').should('be.visible');
|
||||
});
|
||||
cy.getByTestId(proposalVoteProgressForPercentage)
|
||||
.contains('100.00%')
|
||||
.and('be.visible');
|
||||
cy.getByTestId('votes-for-percentage').should('have.text', '100%');
|
||||
navigateTo(navigation.proposals);
|
||||
cy.contains(proposalTitle)
|
||||
.parentsUntil(proposalListItem)
|
||||
|
||||
@@ -298,9 +298,6 @@ context(
|
||||
getProposalFromTitle(proposalTitle).within(() =>
|
||||
cy.getByTestId(viewProposalButton).click()
|
||||
);
|
||||
cy.contains('Vote breakdown').should('be.visible', {
|
||||
timeout: 10000,
|
||||
});
|
||||
cy.getByTestId(voteButtons).should('not.exist');
|
||||
cy.getByTestId('min-proposal-requirements').should(
|
||||
'have.text',
|
||||
|
||||
@@ -52,8 +52,6 @@ const enactmentDeadlineError = 'enactment-before-voting-deadline';
|
||||
const proposalDownloadBtn = 'proposal-download-json';
|
||||
const feedbackError = '[data-testid="Error"]';
|
||||
const viewProposalBtn = 'view-proposal-btn';
|
||||
const liquidityVoteStatus = 'liquidity-votes-status';
|
||||
const tokenVoteStatus = 'token-votes-status';
|
||||
const proposalJsonToggle = 'proposal-json-toggle';
|
||||
const proposalJsonSection = 'proposal-json';
|
||||
const vegaWalletPublicKey = Cypress.env('vegaWalletPublicKey');
|
||||
@@ -421,27 +419,28 @@ context(
|
||||
cy.getByTestId(viewProposalBtn).click();
|
||||
});
|
||||
});
|
||||
cy.getByTestId(liquidityVoteStatus).should(
|
||||
'contain.text',
|
||||
'Currently expected to fail'
|
||||
cy.getByTestId('lp-majority-not-met').should(
|
||||
'have.text',
|
||||
'66% majority threshold not met'
|
||||
);
|
||||
cy.getByTestId(tokenVoteStatus).should(
|
||||
'contain.text',
|
||||
'Currently expected to fail'
|
||||
|
||||
cy.getByTestId('token-majority-not-met').should(
|
||||
'have.text',
|
||||
'66% majority threshold not met'
|
||||
);
|
||||
voteForProposal('for');
|
||||
cy.getByTestId(liquidityVoteStatus).should(
|
||||
'contain.text',
|
||||
'Currently expected to pass'
|
||||
cy.getByTestId('lp-majority-met').should(
|
||||
'have.text',
|
||||
'66% majority threshold met'
|
||||
);
|
||||
cy.getByTestId(tokenVoteStatus).should(
|
||||
'contain.text',
|
||||
'Currently expected to pass'
|
||||
cy.getByTestId('token-majority-met').should(
|
||||
'have.text',
|
||||
'66% majority threshold met'
|
||||
);
|
||||
cy.getByTestId('vote-status').should(
|
||||
'have.text',
|
||||
'Currently expected to pass by token vote'
|
||||
);
|
||||
cy.getByTestId('vote-breakdown-toggle').click();
|
||||
getProposalInformationFromTable('Expected to pass')
|
||||
.contains('👍 by token vote')
|
||||
.should('be.visible');
|
||||
});
|
||||
|
||||
// 3001-VOTE-026 3001-VOTE-027 3001-VOTE-028 3001-VOTE-095 3001-VOTE-096 3005-PASN-001
|
||||
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
enterRawProposalBody,
|
||||
generateFreeFormProposalTitle,
|
||||
getProposalFromTitle,
|
||||
getProposalInformationFromTable,
|
||||
goToMakeNewProposal,
|
||||
governanceProposalType,
|
||||
submitUniqueRawProposal,
|
||||
@@ -30,7 +29,9 @@ const proposalType = 'proposal-type';
|
||||
const proposalStatus = 'proposal-status';
|
||||
const proposalClosingDate = 'vote-details';
|
||||
const viewProposalButton = 'view-proposal-btn';
|
||||
const voteBreakDownToggle = 'vote-breakdown-toggle';
|
||||
const voteMajorityNotMet = 'token-majority-not-met';
|
||||
const voteMajorityMet = 'token-majority-met';
|
||||
const votesForPercentage = 'votes-for-percentage';
|
||||
|
||||
describe('Governance flow for proposal list', { tags: '@slow' }, function () {
|
||||
before('connect wallets and set approval limit', function () {
|
||||
@@ -121,10 +122,15 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
|
||||
submitUniqueRawProposal({ proposalTitle: proposalTitle });
|
||||
getProposalFromTitle(proposalTitle).within(() => {
|
||||
// 3001-VOTE-039
|
||||
cy.getByTestId('participation-not-reached').should(
|
||||
cy.getByTestId(voteMajorityNotMet).should(
|
||||
'have.text',
|
||||
'Min. participation not reached'
|
||||
'66% majority threshold not met'
|
||||
);
|
||||
cy.getByTestId('token-participation-not-met').should(
|
||||
'have.text',
|
||||
'0.000000000000000000000015% participation threshold not met'
|
||||
);
|
||||
cy.getByTestId(votesForPercentage).should('have.text', '0%');
|
||||
cy.getByTestId(viewProposalButton).click();
|
||||
});
|
||||
voteForProposal('for');
|
||||
@@ -134,16 +140,15 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
|
||||
'have.text',
|
||||
'Currently expected to pass'
|
||||
);
|
||||
cy.getByTestId('user-voted-yes').should('exist');
|
||||
cy.getByTestId('participation-reached').should(
|
||||
cy.getByTestId(voteMajorityMet).should(
|
||||
'have.text',
|
||||
'Min. participation reached'
|
||||
'66% majority threshold met'
|
||||
);
|
||||
cy.getByTestId(votesForPercentage).should('have.text', '100%');
|
||||
cy.getByTestId('token-participation-met').should(
|
||||
'have.text',
|
||||
'0.000000000000000000000015% participation threshold met'
|
||||
);
|
||||
cy.getByTestId(viewProposalButton).click();
|
||||
});
|
||||
cy.getByTestId(voteBreakDownToggle).click();
|
||||
getProposalInformationFromTable('Token participation met')
|
||||
.contains('👍')
|
||||
.should('be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -146,7 +146,7 @@ export function getProposalInformationFromTable(heading: string) {
|
||||
}
|
||||
|
||||
export function voteForProposal(vote: string) {
|
||||
cy.contains('Vote breakdown').should('be.visible', { timeout: 10000 });
|
||||
cy.get(voteButtons).should('be.visible', { timeout: 10000 });
|
||||
cy.get(voteButtons).contains(vote).click();
|
||||
cy.get(dialogTitle, proposalTimeout).should(
|
||||
'have.text',
|
||||
|
||||
@@ -219,7 +219,9 @@ export function ensureSpecifiedUnstakedTokensAreAssociated(
|
||||
.eq(1)
|
||||
.invoke('text')
|
||||
.then((unstakedBalance) => {
|
||||
if (parseFloat(unstakedBalance) != parseFloat(tokenAmount)) {
|
||||
const tokenFloat = parseFloat(tokenAmount);
|
||||
const unstakedFloat = parseFloat(unstakedBalance.replace(/,/g, ''));
|
||||
if (tokenFloat != unstakedFloat) {
|
||||
vegaWalletTeardown();
|
||||
cy.get(vegaWalletAssociatedBalance, txTimeout).contains(
|
||||
'0.00',
|
||||
|
||||
@@ -308,7 +308,7 @@ export const VoteBreakdown = ({ proposal }: VoteBreakdownProps) => {
|
||||
<div className="flex items-center gap-1">
|
||||
<span>{t('tokenVotesFor')}:</span>
|
||||
<Tooltip description={formatNumber(yesTokens, defaultDP)}>
|
||||
<button>
|
||||
<button data-testid="num-votes-for">
|
||||
{yesTokens.dividedBy(toBigNum(10 ** 6, 0)).toFixed(1)}M
|
||||
</button>
|
||||
</Tooltip>
|
||||
@@ -317,7 +317,9 @@ export const VoteBreakdown = ({ proposal }: VoteBreakdownProps) => {
|
||||
<Tooltip
|
||||
description={<span>{yesPercentage.toFixed(defaultDP)}%</span>}
|
||||
>
|
||||
<button>{yesPercentage.toFixed(0)}%</button>
|
||||
<button data-testid="votes-for-percentage">
|
||||
{yesPercentage.toFixed(0)}%
|
||||
</button>
|
||||
</Tooltip>
|
||||
)
|
||||
</span>
|
||||
@@ -326,7 +328,7 @@ export const VoteBreakdown = ({ proposal }: VoteBreakdownProps) => {
|
||||
<div className="flex items-center gap-1">
|
||||
<span>{t('tokenVotesAgainst')}:</span>
|
||||
<Tooltip description={formatNumber(noTokens, defaultDP)}>
|
||||
<button>
|
||||
<button data-testid="num-votes-against">
|
||||
{noTokens.dividedBy(toBigNum(10 ** 6, 0)).toFixed(1)}M
|
||||
</button>
|
||||
</Tooltip>
|
||||
@@ -335,7 +337,9 @@ export const VoteBreakdown = ({ proposal }: VoteBreakdownProps) => {
|
||||
<Tooltip
|
||||
description={<span>{noPercentage.toFixed(defaultDP)}%</span>}
|
||||
>
|
||||
<button>{noPercentage.toFixed(0)}%</button>
|
||||
<button data-testid="votes-against-percentage">
|
||||
{noPercentage.toFixed(0)}%
|
||||
</button>
|
||||
</Tooltip>
|
||||
)
|
||||
</span>
|
||||
@@ -364,11 +368,13 @@ export const VoteBreakdown = ({ proposal }: VoteBreakdownProps) => {
|
||||
<div className="flex items-center gap-1">
|
||||
<span>{t('totalTokensVoted')}:</span>
|
||||
<Tooltip description={formatNumber(totalTokensVoted, defaultDP)}>
|
||||
<button>
|
||||
<button data-testid="total-voted">
|
||||
{totalTokensVoted.dividedBy(toBigNum(10 ** 6, 0)).toFixed(1)}M
|
||||
</button>
|
||||
</Tooltip>
|
||||
<span>({totalTokensPercentage.toFixed(defaultDP)}%)</span>
|
||||
<span data-testid="total-voted-percentage">
|
||||
({totalTokensPercentage.toFixed(defaultDP)}%)
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -39,7 +39,11 @@ export const MarketsPage = () => {
|
||||
id="proposed-markets"
|
||||
name={t('Proposed markets')}
|
||||
menu={
|
||||
<TradingAnchorButton size="extra-small" href={externalLink}>
|
||||
<TradingAnchorButton
|
||||
size="extra-small"
|
||||
data-testid="propose-new-market"
|
||||
href={externalLink}
|
||||
>
|
||||
{t('Propose a new market')}
|
||||
</TradingAnchorButton>
|
||||
}
|
||||
|
||||
@@ -78,8 +78,18 @@ const triggerPriceWarningMessage = 'stop-order-warning-message-trigger-price';
|
||||
const triggerTrailingPercentOffsetErrorMessage =
|
||||
'stop-order-error-message-trigger-trailing-percent-offset';
|
||||
|
||||
const numberOfActiveOrdersLimit = 'stop-order-warning-limit';
|
||||
|
||||
const ocoPostfix = (id: string, postfix = true) => (postfix ? `${id}-oco` : id);
|
||||
|
||||
const mockDataProvider = jest.fn((...args) => ({
|
||||
data: Array(0),
|
||||
}));
|
||||
jest.mock('@vegaprotocol/data-provider', () => ({
|
||||
...jest.requireActual('@vegaprotocol/data-provider'),
|
||||
useDataProvider: jest.fn((...args) => mockDataProvider(...args)),
|
||||
}));
|
||||
|
||||
describe('StopOrder', () => {
|
||||
beforeEach(() => {
|
||||
localStorage.clear();
|
||||
@@ -460,4 +470,26 @@ describe('StopOrder', () => {
|
||||
new Date(screen.getByTestId<HTMLInputElement>(datePicker).value).getTime()
|
||||
).toEqual(now);
|
||||
});
|
||||
|
||||
it('shows limit of active stop orders number', async () => {
|
||||
mockDataProvider.mockReturnValue({
|
||||
data: Array(4),
|
||||
});
|
||||
render(generateJsx());
|
||||
expect(mockDataProvider.mock.lastCall?.[0].skip).toBe(true);
|
||||
await userEvent.type(screen.getByTestId(sizeInput), '0.01');
|
||||
expect(mockDataProvider.mock.lastCall?.[0].skip).toBe(false);
|
||||
expect(screen.getByTestId(numberOfActiveOrdersLimit)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('counts oco as two orders', async () => {
|
||||
mockDataProvider.mockReturnValue({
|
||||
data: Array(3),
|
||||
});
|
||||
render(generateJsx());
|
||||
await userEvent.type(screen.getByTestId(sizeInput), '0.01');
|
||||
expect(screen.queryByTestId(numberOfActiveOrdersLimit)).toBeNull();
|
||||
await userEvent.click(screen.getByTestId(oco));
|
||||
expect(screen.getByTestId(numberOfActiveOrdersLimit)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
TradingButton as Button,
|
||||
Pill,
|
||||
Intent,
|
||||
Notification,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { getDerivedPrice } from '@vegaprotocol/markets';
|
||||
import type { Market } from '@vegaprotocol/markets';
|
||||
@@ -53,6 +54,8 @@ import { DealTicketFeeDetails } from './deal-ticket-fee-details';
|
||||
import { validateExpiration } from '../../utils';
|
||||
import { NOTIONAL_SIZE_TOOLTIP_TEXT } from '../../constants';
|
||||
import { KeyValue } from './key-value';
|
||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||
import { stopOrdersProvider } from '@vegaprotocol/orders';
|
||||
|
||||
export interface StopOrderProps {
|
||||
market: Market;
|
||||
@@ -60,6 +63,8 @@ export interface StopOrderProps {
|
||||
submit: (order: StopOrdersSubmission) => void;
|
||||
}
|
||||
|
||||
const MAX_NUMBER_OF_ACTIVE_STOP_ORDERS = 4;
|
||||
const POLLING_TIME = 2000;
|
||||
const trailingPercentOffsetStep = '0.1';
|
||||
|
||||
const getDefaultValues = (
|
||||
@@ -802,6 +807,27 @@ export const StopOrder = ({ market, marketPrice, submit }: StopOrderProps) => {
|
||||
const triggerTrailingPercentOffset = watch('triggerTrailingPercentOffset');
|
||||
const triggerType = watch('triggerType');
|
||||
|
||||
const { data: activeStopOrders, reload } = useDataProvider({
|
||||
dataProvider: stopOrdersProvider,
|
||||
variables: {
|
||||
filter: {
|
||||
parties: pubKey ? [pubKey] : [],
|
||||
markets: [market.id],
|
||||
liveOnly: true,
|
||||
},
|
||||
},
|
||||
skip: !(pubKey && (formState.isDirty || formState.submitCount)),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
reload();
|
||||
}, POLLING_TIME);
|
||||
return () => {
|
||||
clearInterval(interval);
|
||||
};
|
||||
}, [reload]);
|
||||
|
||||
useEffect(() => {
|
||||
const storedSize = storedFormValues?.[dealTicketType]?.size;
|
||||
if (storedSize && size !== storedSize) {
|
||||
@@ -864,7 +890,6 @@ export const StopOrder = ({ market, marketPrice, submit }: StopOrderProps) => {
|
||||
{errors.type.message}
|
||||
</InputError>
|
||||
)}
|
||||
|
||||
<Controller
|
||||
name="side"
|
||||
control={control}
|
||||
@@ -1095,6 +1120,20 @@ export const StopOrder = ({ market, marketPrice, submit }: StopOrderProps) => {
|
||||
</>
|
||||
)}
|
||||
<NoWalletWarning isReadOnly={isReadOnly} />
|
||||
{(activeStopOrders?.length ?? 0) + (oco ? 2 : 1) >
|
||||
MAX_NUMBER_OF_ACTIVE_STOP_ORDERS ? (
|
||||
<div className="mb-2">
|
||||
<Notification
|
||||
intent={Intent.Warning}
|
||||
testId={'stop-order-warning-limit'}
|
||||
message={t(
|
||||
'There is a limit of %s active stop orders per market. Orders submitted above the limit will be immediately rejected.',
|
||||
[MAX_NUMBER_OF_ACTIVE_STOP_ORDERS.toString()]
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<SubmitButton
|
||||
assetUnit={assetUnit}
|
||||
market={market}
|
||||
|
||||
@@ -144,8 +144,8 @@ fragment StopOrderFields on StopOrder {
|
||||
}
|
||||
}
|
||||
|
||||
query StopOrders($partyId: ID!) {
|
||||
stopOrders(filter: { parties: [$partyId] }) {
|
||||
query StopOrders($filter: StopOrderFilter) {
|
||||
stopOrders(filter: $filter) {
|
||||
edges {
|
||||
node {
|
||||
...StopOrderFields
|
||||
|
||||
+5
-5
@@ -37,7 +37,7 @@ export type OrderSubmissionFieldsFragment = { __typename?: 'OrderSubmission', ma
|
||||
export type StopOrderFieldsFragment = { __typename?: 'StopOrder', id: string, ocoLinkId?: string | null, expiresAt?: any | null, expiryStrategy?: Types.StopOrderExpiryStrategy | null, triggerDirection: Types.StopOrderTriggerDirection, status: Types.StopOrderStatus, createdAt: any, updatedAt?: any | null, partyId: string, marketId: string, order?: { __typename?: 'Order', id: string, type?: Types.OrderType | null, side: Types.Side, size: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, price: string, timeInForce: Types.OrderTimeInForce, remaining: string, expiresAt?: any | null, createdAt: any, updatedAt?: any | null, postOnly?: boolean | null, reduceOnly?: boolean | null, market: { __typename?: 'Market', id: string }, liquidityProvision?: { __typename: 'LiquidityProvision' } | null, peggedOrder?: { __typename: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null, icebergOrder?: { __typename: 'IcebergOrder', peakSize: string, minimumVisibleSize: string, reservedRemaining: string } | null } | null, trigger: { __typename?: 'StopOrderPrice', price: string } | { __typename?: 'StopOrderTrailingPercentOffset', trailingPercentOffset: string }, submission: { __typename?: 'OrderSubmission', marketId: string, price: string, size: string, side: Types.Side, timeInForce: Types.OrderTimeInForce, expiresAt: any, type: Types.OrderType, reference?: string | null, postOnly?: boolean | null, reduceOnly?: boolean | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null } };
|
||||
|
||||
export type StopOrdersQueryVariables = Types.Exact<{
|
||||
partyId: Types.Scalars['ID'];
|
||||
filter?: Types.InputMaybe<Types.StopOrderFilter>;
|
||||
}>;
|
||||
|
||||
|
||||
@@ -283,8 +283,8 @@ export function useOrdersUpdateSubscription(baseOptions: Apollo.SubscriptionHook
|
||||
export type OrdersUpdateSubscriptionHookResult = ReturnType<typeof useOrdersUpdateSubscription>;
|
||||
export type OrdersUpdateSubscriptionResult = Apollo.SubscriptionResult<OrdersUpdateSubscription>;
|
||||
export const StopOrdersDocument = gql`
|
||||
query StopOrders($partyId: ID!) {
|
||||
stopOrders(filter: {parties: [$partyId]}) {
|
||||
query StopOrders($filter: StopOrderFilter) {
|
||||
stopOrders(filter: $filter) {
|
||||
edges {
|
||||
node {
|
||||
...StopOrderFields
|
||||
@@ -306,11 +306,11 @@ export const StopOrdersDocument = gql`
|
||||
* @example
|
||||
* const { data, loading, error } = useStopOrdersQuery({
|
||||
* variables: {
|
||||
* partyId: // value for 'partyId'
|
||||
* filter: // value for 'filter'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useStopOrdersQuery(baseOptions: Apollo.QueryHookOptions<StopOrdersQuery, StopOrdersQueryVariables>) {
|
||||
export function useStopOrdersQuery(baseOptions?: Apollo.QueryHookOptions<StopOrdersQuery, StopOrdersQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<StopOrdersQuery, StopOrdersQueryVariables>(StopOrdersDocument, options);
|
||||
}
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
export * from './__generated__/Orders';
|
||||
export * from './order-data-provider';
|
||||
export * from './stop-orders-data-provider';
|
||||
|
||||
@@ -7,7 +7,7 @@ import type { StopOrder } from '../order-data-provider/stop-orders-data-provider
|
||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||
import { stopOrdersWithMarketProvider } from '../order-data-provider/stop-orders-data-provider';
|
||||
import { OrderViewDialog } from '../order-list/order-view-dialog';
|
||||
import type { Order } from '../order-data-provider';
|
||||
import type { Order, StopOrdersQueryVariables } from '../order-data-provider';
|
||||
|
||||
export interface StopOrdersManagerProps {
|
||||
partyId: string;
|
||||
@@ -26,7 +26,11 @@ export const StopOrdersManager = ({
|
||||
}: StopOrdersManagerProps) => {
|
||||
const create = useVegaTransactionStore((state) => state.create);
|
||||
const [viewOrder, setViewOrder] = useState<Order | null>(null);
|
||||
const variables = { partyId };
|
||||
const variables: StopOrdersQueryVariables = {
|
||||
filter: {
|
||||
parties: [partyId],
|
||||
},
|
||||
};
|
||||
|
||||
const { data, error, reload } = useDataProvider({
|
||||
dataProvider: stopOrdersWithMarketProvider,
|
||||
|
||||
@@ -132,6 +132,7 @@ export const TradingAnchorButton = forwardRef<
|
||||
children,
|
||||
className,
|
||||
subLabel,
|
||||
...props
|
||||
},
|
||||
ref
|
||||
) => (
|
||||
@@ -139,6 +140,7 @@ export const TradingAnchorButton = forwardRef<
|
||||
ref={ref}
|
||||
href={href}
|
||||
className={getClassName({ size, subLabel, intent }, className)}
|
||||
{...props}
|
||||
>
|
||||
<Content icon={icon} subLabel={subLabel} children={children} />
|
||||
</a>
|
||||
|
||||
@@ -12,10 +12,7 @@ import { useVegaWallet } from '../use-vega-wallet';
|
||||
|
||||
export const ConnectDialogTitle = ({ children }: { children: ReactNode }) => {
|
||||
return (
|
||||
<h1
|
||||
data-testid="wallet-dialog-title"
|
||||
className="mb-6 text-2xl uppercase font-alpha calt"
|
||||
>
|
||||
<h1 data-testid="wallet-dialog-title" className="mb-6 text-2xl font-alpha">
|
||||
{children}
|
||||
</h1>
|
||||
);
|
||||
|
||||
@@ -111,7 +111,7 @@ describe('VegaConnectDialog', () => {
|
||||
rerender(generateJSX());
|
||||
const list = await screen.findByTestId('connectors-list');
|
||||
expect(list).toBeInTheDocument();
|
||||
expect(list.children).toHaveLength(3);
|
||||
expect(list.children).toHaveLength(2);
|
||||
expect(screen.getByTestId('connector-jsonRpc')).toHaveTextContent(
|
||||
'Use the Desktop App/CLI'
|
||||
);
|
||||
@@ -122,7 +122,7 @@ describe('VegaConnectDialog', () => {
|
||||
mockBrowserWallet();
|
||||
render(generateJSX());
|
||||
const list = await screen.findByTestId('connectors-list');
|
||||
expect(list.children).toHaveLength(3);
|
||||
expect(list.children).toHaveLength(2);
|
||||
expect(screen.getByTestId('connector-injected')).toHaveTextContent(
|
||||
'Connect'
|
||||
);
|
||||
|
||||
@@ -224,28 +224,66 @@ const ConnectorList = ({
|
||||
/>
|
||||
</>
|
||||
);
|
||||
const isItChrome = window.navigator.userAgent.includes('Chrome');
|
||||
const isItMozilla =
|
||||
window.navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
||||
const browserName = isItChrome
|
||||
? 'Chrome'
|
||||
: isItMozilla
|
||||
? 'Firefox'
|
||||
: 'your browser';
|
||||
|
||||
return (
|
||||
<>
|
||||
<ConnectDialogTitle>{title}</ConnectDialogTitle>
|
||||
<p>
|
||||
<p className="text-md">
|
||||
{t(
|
||||
'Connect securely, deposit funds and approve or reject transactions with the Vega wallet'
|
||||
)}
|
||||
</p>
|
||||
<div data-testid="connectors-list" className="flex flex-col mt-6 gap-2">
|
||||
<div className="last:mb-0">
|
||||
<div data-testid="connectors-list" className="flex flex-col mt-4 gap-4">
|
||||
<div>
|
||||
{isBrowserWalletInstalled() ? (
|
||||
<ConnectionOption
|
||||
<ConnectionOptionWithDescription
|
||||
type="injected"
|
||||
text={extendedText}
|
||||
onClick={() => onSelect('injected')}
|
||||
title={
|
||||
<>
|
||||
<span>{t('Vega Wallet')}</span>
|
||||
{' '}
|
||||
<span className="text-xs">{t('full featured')}</span>
|
||||
</>
|
||||
}
|
||||
description={t(
|
||||
`Connect Vega Wallet extension
|
||||
for %s to access all features including key
|
||||
management and detailed transaction views from your
|
||||
browser.`,
|
||||
[browserName]
|
||||
)}
|
||||
/>
|
||||
) : (
|
||||
<GetWalletButton
|
||||
chromeExtensionUrl={links.chromeExtensionUrl}
|
||||
mozillaExtensionUrl={links.mozillaExtensionUrl}
|
||||
/>
|
||||
<div className="py-2">
|
||||
<h1 className="px-2 text-lg">
|
||||
<span>{t('Vega Wallet')}</span>
|
||||
{' '}
|
||||
<span className="text-xs"> {t('full featured')}</span>
|
||||
</h1>
|
||||
<p className="p-2 text-sm">
|
||||
{t(
|
||||
`Install Vega Wallet extension
|
||||
for %s to access all features including key
|
||||
management and detailed transaction views from your
|
||||
browser.`,
|
||||
[browserName]
|
||||
)}
|
||||
</p>
|
||||
<GetWalletButton
|
||||
chromeExtensionUrl={links.chromeExtensionUrl}
|
||||
mozillaExtensionUrl={links.mozillaExtensionUrl}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{connectors['snap'] !== undefined ? (
|
||||
@@ -269,9 +307,19 @@ const ConnectorList = ({
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<ConnectionOption
|
||||
<ConnectionOptionWithDescription
|
||||
type="snap"
|
||||
disabled={snapStatus === SnapStatus.NOT_SUPPORTED}
|
||||
title={
|
||||
<>
|
||||
<span>{t('Metamask Snap')}</span>
|
||||
{' '}
|
||||
<span className="text-xs"> {t('quick start')}</span>
|
||||
</>
|
||||
}
|
||||
description={t(
|
||||
`Connect directly via Metamask with the Vega Snap for single key support without advanced features.`
|
||||
)}
|
||||
text={
|
||||
<>
|
||||
<div className="flex items-center justify-center w-full h-full text-base gap-1">
|
||||
@@ -287,7 +335,7 @@ const ConnectorList = ({
|
||||
}}
|
||||
/>
|
||||
{snapStatus === SnapStatus.NOT_SUPPORTED ? (
|
||||
<p className="pt-2 text-sm text-default">
|
||||
<p className="pt-1 text-xs leading-tight text-default">
|
||||
{t('No MetaMask version that supports snaps detected.')}{' '}
|
||||
{t('Learn more about')}{' '}
|
||||
<ExternalLink href="https://metamask.io/snaps/">
|
||||
@@ -300,20 +348,21 @@ const ConnectorList = ({
|
||||
</div>
|
||||
) : null}
|
||||
<div>
|
||||
<h1 className="my-1 text-md">{t('Advanced / Other options...')}</h1>
|
||||
<ConnectionOption
|
||||
type="view"
|
||||
text={t('View as party')}
|
||||
onClick={() => onSelect('view')}
|
||||
disabled={Boolean(pubKey)}
|
||||
/>
|
||||
</div>
|
||||
<div className="last:mb-0">
|
||||
<CustomUrlInput
|
||||
walletUrl={walletUrl}
|
||||
setWalletUrl={setWalletUrl}
|
||||
isDesktopWalletRunning={isDesktopWalletRunning}
|
||||
onSelect={() => onSelect('jsonRpc')}
|
||||
/>
|
||||
<div className="mt-2">
|
||||
<CustomUrlInput
|
||||
walletUrl={walletUrl}
|
||||
setWalletUrl={setWalletUrl}
|
||||
isDesktopWalletRunning={isDesktopWalletRunning}
|
||||
onSelect={() => onSelect('jsonRpc')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
@@ -451,6 +500,38 @@ export const GetWalletButton = ({
|
||||
);
|
||||
};
|
||||
|
||||
const ConnectionOptionWithDescription = ({
|
||||
disabled,
|
||||
type,
|
||||
text,
|
||||
onClick,
|
||||
icon,
|
||||
description,
|
||||
title,
|
||||
}: {
|
||||
type: WalletType;
|
||||
text: string | ReactNode;
|
||||
onClick: () => void;
|
||||
disabled?: boolean;
|
||||
icon?: ReactNode;
|
||||
description?: string | ReactNode;
|
||||
title?: string | ReactNode;
|
||||
}) => {
|
||||
return (
|
||||
<div>
|
||||
<h1 className="text-md">{title}</h1>
|
||||
<p className="pb-2 text-sm text-gray-60 text-muted">{description}</p>
|
||||
<ConnectionOption
|
||||
disabled={disabled}
|
||||
type={type}
|
||||
text={text}
|
||||
onClick={onClick}
|
||||
icon={icon}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const ConnectionOption = ({
|
||||
disabled,
|
||||
type,
|
||||
@@ -531,7 +612,7 @@ const CustomUrlInput = ({
|
||||
onClick={() => onSelect('jsonRpc')}
|
||||
/>
|
||||
{isDesktopWalletRunning !== null && (
|
||||
<p className="pt-2 mb-6 text-sm">
|
||||
<p className="pt-1 mb-2 text-sm leading-tight">
|
||||
{isDesktopWalletRunning ? (
|
||||
<button
|
||||
className="underline text-default"
|
||||
@@ -543,13 +624,13 @@ const CustomUrlInput = ({
|
||||
</button>
|
||||
) : (
|
||||
<>
|
||||
<span className="text-default">
|
||||
<span className="text-xs">
|
||||
{t(
|
||||
'No running Desktop App/CLI detected. Open your app now to connect or enter a'
|
||||
)}
|
||||
</span>{' '}
|
||||
<button
|
||||
className="underline"
|
||||
className="text-xs underline"
|
||||
onClick={() => setUrlInputExpanded(true)}
|
||||
disabled={Boolean(pubKey)}
|
||||
>
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
- **Must** be able to click on current node to open node switcher dialog (<a name="0006-NETW-012" href="#0006-NETW-012">0006-NETW-012</a>)
|
||||
- In the node dialog
|
||||
|
||||
- **Must** must see all nodes provided by the [network config](https://github.com/vegaprotocol/networks) (<a name="0006-NETW-013" href="#0006-NETW-013">0006-NETW-013</a>)
|
||||
- For each node
|
||||
- **Must** see the response time of the node (<a name="0006-NETW-014" href="#0006-NETW-014">0006-NETW-014</a>)
|
||||
@@ -34,3 +35,9 @@
|
||||
- **Must** be able to select 'other' to input a node address and connect to it (<a name="0006-NETW-018" href="#0006-NETW-018">0006-NETW-018</a>)
|
||||
- **Must** have disabled connect button if 'other' is selected but no url has been entered (<a name="0006-NETW-019" href="#0006-NETW-019">0006-NETW-019</a>)
|
||||
- **Must** have disabled connect button if selected node is the current node (<a name="0006-NETW-020" href="#0006-NETW-020">0006-NETW-020</a>)
|
||||
|
||||
## Block Explorer
|
||||
|
||||
- **Must** show all possible network parameters (<a name="0006-NETW-021" href="#0006-NETW-021">0006-NETW-021</a>)
|
||||
- **Must** I can see network parameters grouped by type (<a name="0006-NETW-022" href="#0006-NETW-022">0006-NETW-022</a>)
|
||||
- **Must** Network parameter headings act as linkable anchors i.e. a third party website can link directly to a "section" of the network parameter page (<a name="0006-NETW-023" href="#0006-NETW-023">0006-NETW-022</a>)
|
||||
|
||||
@@ -162,6 +162,8 @@ When looking to vote on the proposal, I...
|
||||
- **must** trigger a transaction that needs to be confirmed in users wallet (<a name="3001-VOTE-013" href="#3001-VOTE-013">3001-VOTE-013</a>)
|
||||
- **must** see that I need to confirm the transaction in my wallet to continue (<a name="3001-VOTE-014" href="#3001-VOTE-014">3001-VOTE-014</a>)
|
||||
- **must** see option to change my vote (vote again in same or different direction) (<a name="3001-VOTE-090" href="#3001-VOTE-090">3001-VOTE-090</a>)
|
||||
- **must** see two vote status bars, one showing majority voting yes/no, and the other showing participation progress. The maximum value for the progress bar should be the threshold for that proposal type. (<a name="3001-VOTE-023" href="#3001-VOTE-023">3001-VOTE-023</a>)
|
||||
- **must** see when the participation bar reaches 100% (i.e. the network param threshold is met) the indicator text on top of it reads "[network param]% participation threshold met". Otherwise it says "[network param]% participation threshold not met". (<a name="3001-VOTE-024" href="#3001-VOTE-024">3001-VOTE-024</a>)
|
||||
|
||||
For open market change proposals, all of the above and:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user