Compare commits
25
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fbcb7fc996 | ||
|
|
bb77e95c85 | ||
|
|
b3b4ac36ab | ||
|
|
e4eedf5ccd | ||
|
|
20cbcb8302 | ||
|
|
cd3acf8ff9 | ||
|
|
30735388e8 | ||
|
|
652ff66a13 | ||
|
|
ccddfd3576 | ||
|
|
2efb6ab32f | ||
|
|
478c4f83bb | ||
|
|
67ce576bc8 | ||
|
|
431fab8824 | ||
|
|
83b6d3d295 | ||
|
|
98fd79bc35 | ||
|
|
39aa27f332 | ||
|
|
bf4fb29fe6 | ||
|
|
5ed1befc53 | ||
|
|
1b311a8b36 | ||
|
|
70c3bc8128 | ||
|
|
7e49836875 | ||
|
|
d624957e6d | ||
|
|
069b57d4ae | ||
|
|
ab1a2cb222 | ||
|
|
e1a1ae0fa1 |
@@ -137,7 +137,7 @@ jobs:
|
|||||||
secrets: inherit
|
secrets: inherit
|
||||||
with:
|
with:
|
||||||
projects: ${{ needs.lint-test-build.outputs.projects-e2e }}
|
projects: ${{ needs.lint-test-build.outputs.projects-e2e }}
|
||||||
tags: '@smoke @regression'
|
tags: '@smoke'
|
||||||
|
|
||||||
publish-dist:
|
publish-dist:
|
||||||
needs: lint-test-build
|
needs: lint-test-build
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ module.exports = defineConfig({
|
|||||||
viewportWidth: 1440,
|
viewportWidth: 1440,
|
||||||
viewportHeight: 900,
|
viewportHeight: 900,
|
||||||
testIsolation: false,
|
testIsolation: false,
|
||||||
|
experimentalMemoryManagement: true,
|
||||||
},
|
},
|
||||||
env: {
|
env: {
|
||||||
environment: 'CUSTOM',
|
environment: 'CUSTOM',
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
|
import { createSuccessorMarketProposal } from '../support/governance.functions';
|
||||||
|
|
||||||
context('Market page', { tags: '@regression' }, function () {
|
context('Market page', { tags: '@regression' }, function () {
|
||||||
describe('Verify elements on page', function () {
|
describe('Verify elements on page', function () {
|
||||||
const marketHeaders = 'markets-heading';
|
const marketHeaders = 'markets-heading';
|
||||||
const createdMarketId =
|
|
||||||
'2eab0e66545a789047561bc5a2e5cbc3b19eb708da41104e3cac2474ee36c4d4';
|
|
||||||
|
|
||||||
before('Create market', function () {
|
before('Create market', function () {
|
||||||
cy.visit('/');
|
cy.visit('/');
|
||||||
@@ -11,7 +11,7 @@ context('Market page', { tags: '@regression' }, function () {
|
|||||||
|
|
||||||
beforeEach('Get market id', function () {
|
beforeEach('Get market id', function () {
|
||||||
cy.navigate_to('markets');
|
cy.navigate_to('markets');
|
||||||
cy.get('[col-id="id"]').eq(1).invoke('text').as('createdMarketId');
|
cy.get('[col-id="id"]').last().invoke('text').as('createdMarketId');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Market displayed on market page', function () {
|
it('Market displayed on market page', function () {
|
||||||
@@ -106,6 +106,7 @@ context('Market page', { tags: '@regression' }, function () {
|
|||||||
// Able to view Json
|
// Able to view Json
|
||||||
cy.contains('View JSON').click();
|
cy.contains('View JSON').click();
|
||||||
cy.get('.language-json').should('exist');
|
cy.get('.language-json').should('exist');
|
||||||
|
cy.getByTestId('icon-cross').click();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Skipping due to resize observer loop limit error
|
// Skipping due to resize observer loop limit error
|
||||||
@@ -113,17 +114,60 @@ context('Market page', { tags: '@regression' }, function () {
|
|||||||
cy.common_switch_to_mobile_and_click_toggle();
|
cy.common_switch_to_mobile_and_click_toggle();
|
||||||
cy.navigate_to('markets', true);
|
cy.navigate_to('markets', true);
|
||||||
cy.getByTestId(marketHeaders).should('be.visible');
|
cy.getByTestId(marketHeaders).should('be.visible');
|
||||||
cy.get(`[row-id="${createdMarketId}"]`)
|
cy.get(`[row-id="${this.createdMarketId}"]`)
|
||||||
.should('be.visible')
|
.should('be.visible')
|
||||||
.within(() => {
|
.within(() => {
|
||||||
cy.get_element_by_col_id('code').should('have.text', 'TEST.24h');
|
cy.get_element_by_col_id('code').should('have.text', 'TEST.24h');
|
||||||
cy.get_element_by_col_id('name').should('have.text', 'Test market 1');
|
cy.get_element_by_col_id('name').should('have.text', 'Test market 1');
|
||||||
cy.get_element_by_col_id('state').should('have.text', 'Pending');
|
cy.get_element_by_col_id('state').should('have.text', 'Pending');
|
||||||
cy.get_element_by_col_id('asset').should('have.text', 'fUSDC');
|
cy.get_element_by_col_id('asset').should('have.text', 'fUSDC');
|
||||||
cy.get_element_by_col_id('id').should('have.text', createdMarketId);
|
cy.get_element_by_col_id('id').should(
|
||||||
|
'have.text',
|
||||||
|
this.createdMarketId
|
||||||
|
);
|
||||||
cy.get_element_by_col_id('actions')
|
cy.get_element_by_col_id('actions')
|
||||||
.find('a')
|
.find('a')
|
||||||
.should('have.attr', 'href', `/markets/${createdMarketId}`);
|
.should('have.attr', 'href', `/markets/${this.createdMarketId}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Able to go to market details page for successor market', function () {
|
||||||
|
const successionLineItem = 'succession-line-item';
|
||||||
|
const successionLineMarketId = 'succession-line-item-market-id';
|
||||||
|
|
||||||
|
createSuccessorMarketProposal(this.createdMarketId);
|
||||||
|
cy.navigate_to('markets');
|
||||||
|
cy.reload();
|
||||||
|
cy.contains('Token test market', { timeout: 8000 }).should('be.visible');
|
||||||
|
cy.get('[row-index="0"]')
|
||||||
|
.invoke('attr', 'row-id')
|
||||||
|
.as('successorMarketId');
|
||||||
|
cy.contains('Token test market').click();
|
||||||
|
cy.getByTestId(marketHeaders).should('have.text', 'Token test market');
|
||||||
|
cy.validate_proposal_change_type('Triggering Ratio', 'Added');
|
||||||
|
cy.validate_element_from_table('Triggering Ratio', '0.7');
|
||||||
|
cy.validate_proposal_change_type('Time Window', 'Added');
|
||||||
|
cy.validate_element_from_table('Time Window', '3,600');
|
||||||
|
cy.validate_proposal_change_type('Scaling Factor', 'Added');
|
||||||
|
cy.validate_element_from_table('Scaling Factor', '10');
|
||||||
|
|
||||||
|
cy.getByTestId(successionLineItem)
|
||||||
|
.first()
|
||||||
|
.within(() => {
|
||||||
|
cy.contains('Test market 1');
|
||||||
|
cy.getByTestId(successionLineMarketId).should(
|
||||||
|
'have.text',
|
||||||
|
this.createdMarketId
|
||||||
|
);
|
||||||
|
});
|
||||||
|
cy.getByTestId(successionLineItem)
|
||||||
|
.eq(1)
|
||||||
|
.within(() => {
|
||||||
|
cy.contains('Token test market');
|
||||||
|
cy.getByTestId(successionLineMarketId).should(
|
||||||
|
'have.text',
|
||||||
|
this.successorMarketId
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,28 +13,31 @@ context('Proposal page', { tags: '@smoke' }, function () {
|
|||||||
it('Able to view proposal', function () {
|
it('Able to view proposal', function () {
|
||||||
cy.navigate_to('governanceProposals');
|
cy.navigate_to('governanceProposals');
|
||||||
cy.getByTestId(proposalHeading).should('be.visible');
|
cy.getByTestId(proposalHeading).should('be.visible');
|
||||||
// get first proposal in list
|
cy.contains(proposalTitle)
|
||||||
cy.get('[row-index="0"]').within(() => {
|
.parent()
|
||||||
cy.get_element_by_col_id('title').should('have.text', proposalTitle);
|
.parent()
|
||||||
cy.get_element_by_col_id('type').should('have.text', 'NewMarket');
|
.parent()
|
||||||
cy.get_element_by_col_id('state').should('have.text', 'Enacted');
|
.within(() => {
|
||||||
cy.getByTestId('vote-progress').should('be.visible');
|
cy.get_element_by_col_id('title').should('have.text', proposalTitle);
|
||||||
cy.get('[col-id="cDate"]')
|
cy.get_element_by_col_id('type').should('have.text', 'NewMarket');
|
||||||
.invoke('text')
|
cy.get_element_by_col_id('state').should('have.text', 'Enacted');
|
||||||
.should('match', dateTimeRegex);
|
cy.getByTestId('vote-progress').should('be.visible');
|
||||||
cy.get('[col-id="eDate"]')
|
cy.get('[col-id="cDate"]')
|
||||||
.invoke('text')
|
.invoke('text')
|
||||||
.should('match', dateTimeRegex);
|
.should('match', dateTimeRegex);
|
||||||
cy.getByTestId('external-link')
|
cy.get('[col-id="eDate"]')
|
||||||
.should('have.attr', 'href')
|
.invoke('text')
|
||||||
.and('contains', 'https://governance.fairground.wtf/proposals/');
|
.should('match', dateTimeRegex);
|
||||||
cy.contains('View terms').should('exist').click();
|
cy.getByTestId('external-link')
|
||||||
});
|
.should('have.attr', 'href')
|
||||||
|
.and('contains', 'https://governance.fairground.wtf/proposals/');
|
||||||
|
cy.contains('View terms').should('exist').click();
|
||||||
|
});
|
||||||
cy.getByTestId('dialog-title').should('have.text', proposalTitle);
|
cy.getByTestId('dialog-title').should('have.text', proposalTitle);
|
||||||
cy.get('.language-json').should('exist');
|
cy.get('.language-json').should('exist');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Proposal page displayed on mobile', function () {
|
it.skip('Proposal page displayed on mobile', function () {
|
||||||
cy.common_switch_to_mobile_and_click_toggle();
|
cy.common_switch_to_mobile_and_click_toggle();
|
||||||
cy.navigate_to('governanceProposals', true);
|
cy.navigate_to('governanceProposals', true);
|
||||||
cy.getByTestId(proposalHeading).should('be.visible');
|
cy.getByTestId(proposalHeading).should('be.visible');
|
||||||
|
|||||||
@@ -127,3 +127,10 @@ Cypress.Commands.add(
|
|||||||
.should('have.text', tableRowValue);
|
.should('have.text', tableRowValue);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Cypress.Commands.add(
|
||||||
|
'validate_proposal_change_type',
|
||||||
|
(tableRowName, changeType) => {
|
||||||
|
cy.contains(tableRowName).siblings().should('have.text', changeType);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
export function createSuccessorMarketProposal(parentMarketId) {
|
||||||
|
cy.VegaWalletSubmitProposal(getSuccessorTxBody(parentMarketId));
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSuccessorTxBody(parentMarketId) {
|
||||||
|
return {
|
||||||
|
proposalSubmission: {
|
||||||
|
rationale: {
|
||||||
|
title: 'Test successor market proposal details',
|
||||||
|
description: 'E2E test for successor market',
|
||||||
|
},
|
||||||
|
terms: {
|
||||||
|
newMarket: {
|
||||||
|
changes: {
|
||||||
|
decimalPlaces: '5',
|
||||||
|
positionDecimalPlaces: '5',
|
||||||
|
linearSlippageFactor: '0.001',
|
||||||
|
quadraticSlippageFactor: '0',
|
||||||
|
lpPriceRange: '10',
|
||||||
|
instrument: {
|
||||||
|
name: 'Token test market',
|
||||||
|
code: 'TEST.24h',
|
||||||
|
future: {
|
||||||
|
settlementAsset:
|
||||||
|
'816af99af60d684502a40824758f6b5377e6af48e50a9ee8ef478ecb879ea8bc',
|
||||||
|
quoteName: 'fUSDC',
|
||||||
|
dataSourceSpecForSettlementData: {
|
||||||
|
external: {
|
||||||
|
oracle: {
|
||||||
|
signers: [
|
||||||
|
{
|
||||||
|
pubKey: {
|
||||||
|
key: '70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
key: {
|
||||||
|
name: 'prices.BTC.value',
|
||||||
|
type: 'TYPE_INTEGER',
|
||||||
|
numberDecimalPlaces: '0',
|
||||||
|
},
|
||||||
|
conditions: [
|
||||||
|
{
|
||||||
|
operator: 'OPERATOR_GREATER_THAN',
|
||||||
|
value: '0',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dataSourceSpecForTradingTermination: {
|
||||||
|
external: {
|
||||||
|
oracle: {
|
||||||
|
signers: [
|
||||||
|
{
|
||||||
|
pubKey: {
|
||||||
|
key: '70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
key: {
|
||||||
|
name: 'trading.terminated.ETH5',
|
||||||
|
type: 'TYPE_BOOLEAN',
|
||||||
|
},
|
||||||
|
conditions: [
|
||||||
|
{
|
||||||
|
operator: 'OPERATOR_EQUALS',
|
||||||
|
value: 'true',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dataSourceSpecBinding: {
|
||||||
|
settlementDataProperty: 'prices.BTC.value',
|
||||||
|
tradingTerminationProperty: 'trading.terminated.ETH5',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
metadata: [
|
||||||
|
'sector:food',
|
||||||
|
'sector:materials',
|
||||||
|
'source:docs.vega.xyz',
|
||||||
|
],
|
||||||
|
priceMonitoringParameters: {
|
||||||
|
triggers: [
|
||||||
|
{
|
||||||
|
horizon: '43200',
|
||||||
|
probability: '0.9999999',
|
||||||
|
auctionExtension: '600',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
liquidityMonitoringParameters: {
|
||||||
|
targetStakeParameters: {
|
||||||
|
timeWindow: '3600',
|
||||||
|
scalingFactor: 10,
|
||||||
|
},
|
||||||
|
triggeringRatio: '0.7',
|
||||||
|
auctionExtension: '1',
|
||||||
|
},
|
||||||
|
logNormal: {
|
||||||
|
tau: 0.0001140771161,
|
||||||
|
riskAversionParameter: 0.01,
|
||||||
|
params: {
|
||||||
|
mu: 0,
|
||||||
|
r: 0.016,
|
||||||
|
sigma: 0.5,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
successor: {
|
||||||
|
parentMarketId: parentMarketId,
|
||||||
|
insurancePoolFraction: '0.75',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
closingTimestamp: 1695666618,
|
||||||
|
enactmentTimestamp: 1695666618,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 547 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"short_name": "Mainnet Stats",
|
||||||
|
"name": "Vega Mainnet statistics",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "favicon.ico",
|
||||||
|
"sizes": "64x64 32x32 24x24 16x16",
|
||||||
|
"type": "image/x-icon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "logo192.png",
|
||||||
|
"type": "image/png",
|
||||||
|
"sizes": "192x192"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"start_url": ".",
|
||||||
|
"display": "standalone",
|
||||||
|
"theme_color": "#000000",
|
||||||
|
"background_color": "#ffffff"
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# https://www.robotstxt.org/robotstxt.html
|
||||||
|
User-agent: *
|
||||||
|
Disallow:
|
||||||
@@ -1,23 +1,39 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
|
||||||
<title>Explorer</title>
|
|
||||||
<base href="/" />
|
|
||||||
<link
|
|
||||||
rel="preload"
|
|
||||||
href="https://static.vega.xyz/AlphaLyrae-Medium.woff2"
|
|
||||||
as="font"
|
|
||||||
type="font/woff2"
|
|
||||||
crossorigin="anonymous"
|
|
||||||
/>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<meta charset="utf-8" />
|
||||||
<link
|
<link
|
||||||
rel="icon"
|
rel="icon"
|
||||||
type="image/x-icon"
|
type="image/x-icon"
|
||||||
href="https://static.vega.xyz/favicon.ico"
|
href="https://static.vega.xyz/favicon.ico"
|
||||||
/>
|
/>
|
||||||
<link rel="stylesheet" href="https://static.vega.xyz/fonts.css" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<meta name="theme-color" content="#000000" />
|
||||||
|
<meta name="description" content="Vega Protocol - VEGA Explorer" />
|
||||||
|
<meta name="og:type" content="website" />
|
||||||
|
<meta name="og:url" content="https://explorer.vega.xyz/" />
|
||||||
|
<meta name="og:title" content="Vega Protocol - Explorer" />
|
||||||
|
<meta name="og:site_name" content="Vega Protocol - Explorer" />
|
||||||
|
<meta name="og:image" content="https://static.vega.xyz/favicon.ico" />
|
||||||
|
|
||||||
|
<meta name="twitter:card" content="https://static.vega.xyz/favicon.ico" />
|
||||||
|
<meta name="twitter:title" content="Vega Protocol - Explorer" />
|
||||||
|
<meta name="twitter:description" content="Vega Protocol - Explorer" />
|
||||||
|
<meta name="twitter:image" content="https://static.vega.xyz/favicon.ico" />
|
||||||
|
<meta name="twitter:image:alt" content="VEGA logo" />
|
||||||
|
<meta name="twitter:site" content="@vegaprotocol" />
|
||||||
|
|
||||||
|
<meta name="description" content="Vega Protocol - Explorer" />
|
||||||
|
<link rel="apple-touch-icon" href="assets/apple-touch-icon.png" />
|
||||||
|
<link rel="manifest" href="assets/manifest.json" />
|
||||||
|
<link
|
||||||
|
rel="preload"
|
||||||
|
href="https://static.vega.xyz/AlphaLyrae-Medium.woff2"
|
||||||
|
as="font"
|
||||||
|
type="font/woff2"
|
||||||
|
/>
|
||||||
|
<title>VEGA Explorer</title>
|
||||||
<script src="./assets/env-config.js"></script>
|
<script src="./assets/env-config.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body class="dark:bg-black h-full w-full">
|
<body class="dark:bg-black h-full w-full">
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/annou
|
|||||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||||
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||||
NX_VEGA_REST_URL=http://localhost:3008/api/v2/
|
NX_VEGA_REST_URL=http://localhost:3008/api/v2/
|
||||||
|
NX_SUCCESSOR_MARKETS=true
|
||||||
|
|
||||||
#Test configuration variables
|
#Test configuration variables
|
||||||
CYPRESS_FAIRGROUND=false
|
CYPRESS_FAIRGROUND=false
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ module.exports = defineConfig({
|
|||||||
numTestsKeptInMemory: 5,
|
numTestsKeptInMemory: 5,
|
||||||
downloadsFolder: 'cypress/downloads',
|
downloadsFolder: 'cypress/downloads',
|
||||||
testIsolation: false,
|
testIsolation: false,
|
||||||
|
experimentalMemoryManagement: true,
|
||||||
},
|
},
|
||||||
env: {
|
env: {
|
||||||
ethProviderUrl: 'http://localhost:8545/',
|
ethProviderUrl: 'http://localhost:8545/',
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ import {
|
|||||||
getDateFormatForSpecifiedDays,
|
getDateFormatForSpecifiedDays,
|
||||||
getProposalFromTitle,
|
getProposalFromTitle,
|
||||||
getProposalInformationFromTable,
|
getProposalInformationFromTable,
|
||||||
|
proposalChangeType,
|
||||||
submitUniqueRawProposal,
|
submitUniqueRawProposal,
|
||||||
|
validateProposalDetailsDiff,
|
||||||
voteForProposal,
|
voteForProposal,
|
||||||
} from '../../../../governance-e2e/src/support/governance.functions';
|
} from '../../../../governance-e2e/src/support/governance.functions';
|
||||||
import {
|
import {
|
||||||
@@ -26,7 +28,9 @@ import {
|
|||||||
} from '../../support/wallet-functions';
|
} from '../../support/wallet-functions';
|
||||||
import type { testFreeformProposal } from '../../support/common-interfaces';
|
import type { testFreeformProposal } from '../../support/common-interfaces';
|
||||||
import { formatDateWithLocalTimezone } from '@vegaprotocol/utils';
|
import { formatDateWithLocalTimezone } from '@vegaprotocol/utils';
|
||||||
|
import { createSuccessorMarketProposalTxBody } from '../../support/proposal.functions';
|
||||||
|
|
||||||
|
const proposalListItem = '[data-testid="proposals-list-item"]';
|
||||||
const proposalVoteProgressForPercentage =
|
const proposalVoteProgressForPercentage =
|
||||||
'vote-progress-indicator-percentage-for';
|
'vote-progress-indicator-percentage-for';
|
||||||
const proposalVoteProgressAgainstPercentage =
|
const proposalVoteProgressAgainstPercentage =
|
||||||
@@ -42,6 +46,7 @@ const viewProposalButton = 'view-proposal-btn';
|
|||||||
const proposalDescriptionToggle = 'proposal-description-toggle';
|
const proposalDescriptionToggle = 'proposal-description-toggle';
|
||||||
const voteBreakdownToggle = 'vote-breakdown-toggle';
|
const voteBreakdownToggle = 'vote-breakdown-toggle';
|
||||||
const proposalTermsToggle = 'proposal-json-toggle';
|
const proposalTermsToggle = 'proposal-json-toggle';
|
||||||
|
const marketDataToggle = 'proposal-market-data-toggle';
|
||||||
|
|
||||||
describe(
|
describe(
|
||||||
'Governance flow for proposal details',
|
'Governance flow for proposal details',
|
||||||
@@ -50,12 +55,12 @@ describe(
|
|||||||
before('connect wallets and set approval limit', function () {
|
before('connect wallets and set approval limit', function () {
|
||||||
cy.visit('/');
|
cy.visit('/');
|
||||||
ethereumWalletConnect();
|
ethereumWalletConnect();
|
||||||
// cy.associateTokensToVegaWallet('1');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach('visit proposals tab', function () {
|
beforeEach('visit proposals tab', function () {
|
||||||
cy.clearLocalStorage();
|
cy.clearLocalStorage();
|
||||||
turnTelemetryOff();
|
turnTelemetryOff();
|
||||||
|
cy.mockChainId();
|
||||||
cy.reload();
|
cy.reload();
|
||||||
waitForSpinner();
|
waitForSpinner();
|
||||||
cy.connectVegaWallet();
|
cy.connectVegaWallet();
|
||||||
@@ -354,5 +359,98 @@ describe(
|
|||||||
switchVegaWalletPubKey();
|
switchVegaWalletPubKey();
|
||||||
stakingPageDisassociateAllTokens();
|
stakingPageDisassociateAllTokens();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Able to see successor market details with new and updated values', function () {
|
||||||
|
cy.createMarket();
|
||||||
|
cy.reload();
|
||||||
|
waitForSpinner();
|
||||||
|
cy.getByTestId('closed-proposals').within(() => {
|
||||||
|
cy.contains('Add Lorem Ipsum market')
|
||||||
|
.parentsUntil(proposalListItem)
|
||||||
|
.last()
|
||||||
|
.within(() => {
|
||||||
|
cy.getByTestId(viewProposalButton).click();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
getProposalInformationFromTable('ID')
|
||||||
|
.invoke('text')
|
||||||
|
.as('parentMarketId')
|
||||||
|
.then(() => {
|
||||||
|
cy.VegaWalletSubmitProposal(
|
||||||
|
createSuccessorMarketProposalTxBody(this.parentMarketId)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
navigateTo(navigation.proposals);
|
||||||
|
cy.reload();
|
||||||
|
getProposalFromTitle('Test successor market proposal details').within(
|
||||||
|
() => cy.getByTestId(viewProposalButton).click()
|
||||||
|
);
|
||||||
|
// #3003-PMAN-010
|
||||||
|
cy.getByTestId(proposalTermsToggle).click();
|
||||||
|
cy.get('.language-json').within(() => {
|
||||||
|
cy.get('.hljs-attr').should('contain.text', 'parentMarketId');
|
||||||
|
cy.get('.hljs-string').should('contain.text', this.parentMarketId);
|
||||||
|
cy.get('.hljs-attr').should('contain.text', 'insurancePoolFraction');
|
||||||
|
cy.get('.hljs-string').should('contain.text', '0.75');
|
||||||
|
});
|
||||||
|
// 3003-PMAN-011 3003-PMAN-012
|
||||||
|
cy.getByTestId(marketDataToggle).click();
|
||||||
|
cy.getByTestId('proposal-market-data').within(() => {
|
||||||
|
cy.contains('Key details').click();
|
||||||
|
validateProposalDetailsDiff(
|
||||||
|
'Name',
|
||||||
|
proposalChangeType.UPDATED,
|
||||||
|
'Token test market',
|
||||||
|
'Test market 1'
|
||||||
|
);
|
||||||
|
validateProposalDetailsDiff(
|
||||||
|
'Parent Market ID',
|
||||||
|
proposalChangeType.ADDED,
|
||||||
|
this.parentMarketId
|
||||||
|
);
|
||||||
|
validateProposalDetailsDiff(
|
||||||
|
'Insurance Pool Fraction',
|
||||||
|
proposalChangeType.ADDED,
|
||||||
|
'0.75'
|
||||||
|
);
|
||||||
|
validateProposalDetailsDiff(
|
||||||
|
'Trading Mode',
|
||||||
|
proposalChangeType.UPDATED,
|
||||||
|
'No trading',
|
||||||
|
'Opening auction'
|
||||||
|
);
|
||||||
|
|
||||||
|
cy.contains('Instrument').click();
|
||||||
|
validateProposalDetailsDiff(
|
||||||
|
'Market Name',
|
||||||
|
proposalChangeType.UPDATED,
|
||||||
|
'Token test market',
|
||||||
|
'Test market 1'
|
||||||
|
);
|
||||||
|
|
||||||
|
cy.contains('Metadata').click();
|
||||||
|
validateProposalDetailsDiff(
|
||||||
|
'Sector',
|
||||||
|
proposalChangeType.UPDATED,
|
||||||
|
'materials',
|
||||||
|
'tech'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 3003-PMAN-011
|
||||||
|
cy.get('.underline').contains('Parent Market ID').realHover();
|
||||||
|
cy.getByTestId('tooltip-content', { timeout: 8000 }).should(
|
||||||
|
'contain.text',
|
||||||
|
'The ID of the market this market succeeds.'
|
||||||
|
);
|
||||||
|
cy.get('.underline')
|
||||||
|
.contains('Insurance Pool Fraction')
|
||||||
|
.realMouseUp()
|
||||||
|
.realHover();
|
||||||
|
cy.getByTestId('tooltip-content', { timeout: 8000 }).should(
|
||||||
|
'contain.text',
|
||||||
|
'The fraction of the insurance pool balance that is carried over from the parent market to the successor.'
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ context(
|
|||||||
beforeEach('visit proposals', function () {
|
beforeEach('visit proposals', function () {
|
||||||
cy.clearLocalStorage();
|
cy.clearLocalStorage();
|
||||||
turnTelemetryOff();
|
turnTelemetryOff();
|
||||||
|
cy.mockChainId();
|
||||||
cy.reload();
|
cy.reload();
|
||||||
waitForSpinner();
|
waitForSpinner();
|
||||||
cy.connectVegaWallet();
|
cy.connectVegaWallet();
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ context(
|
|||||||
cy.clearLocalStorage();
|
cy.clearLocalStorage();
|
||||||
turnTelemetryOff();
|
turnTelemetryOff();
|
||||||
cy.reload();
|
cy.reload();
|
||||||
|
cy.mockChainId();
|
||||||
waitForSpinner();
|
waitForSpinner();
|
||||||
cy.connectVegaWallet();
|
cy.connectVegaWallet();
|
||||||
ethereumWalletConnect();
|
ethereumWalletConnect();
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ context(
|
|||||||
beforeEach('visit governance tab', function () {
|
beforeEach('visit governance tab', function () {
|
||||||
cy.clearLocalStorage();
|
cy.clearLocalStorage();
|
||||||
turnTelemetryOff();
|
turnTelemetryOff();
|
||||||
|
cy.mockChainId();
|
||||||
cy.reload();
|
cy.reload();
|
||||||
waitForSpinner();
|
waitForSpinner();
|
||||||
cy.connectVegaWallet();
|
cy.connectVegaWallet();
|
||||||
@@ -654,44 +655,7 @@ context(
|
|||||||
.find('a')
|
.find('a')
|
||||||
.should('have.attr', 'href')
|
.should('have.attr', 'href')
|
||||||
.and('contain', this.parentMarketId);
|
.and('contain', this.parentMarketId);
|
||||||
cy.getByTestId('view-proposal-btn').click();
|
|
||||||
});
|
});
|
||||||
// #3003-PMAN-010
|
|
||||||
cy.getByTestId(proposalJsonToggle).click();
|
|
||||||
cy.get('.language-json').within(() => {
|
|
||||||
cy.get('.hljs-attr').should('contain.text', 'parentMarketId');
|
|
||||||
cy.get('.hljs-string').should('contain.text', this.parentMarketId);
|
|
||||||
cy.get('.hljs-attr').should('contain.text', 'insurancePoolFraction');
|
|
||||||
cy.get('.hljs-string').should('contain.text', '0.75');
|
|
||||||
});
|
|
||||||
cy.getByTestId('proposal-market-data').within(() => {
|
|
||||||
cy.getByTestId('proposal-market-data-toggle').click();
|
|
||||||
cy.contains('Key details').click();
|
|
||||||
// 3003-PMAN-009
|
|
||||||
getMarketProposalDetailsFromTable('Parent Market ID').should(
|
|
||||||
'have.text',
|
|
||||||
this.parentMarketId
|
|
||||||
);
|
|
||||||
getMarketProposalDetailsFromTable('Insurance Pool Fraction').should(
|
|
||||||
'have.text',
|
|
||||||
'0.75'
|
|
||||||
);
|
|
||||||
getMarketProposalDetailsFromTable('Trading Mode').should(
|
|
||||||
'have.text',
|
|
||||||
'No trading'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
// 3003-PMAN-011
|
|
||||||
cy.contains('Parent Market ID').realHover();
|
|
||||||
cy.getByTestId('tooltip-content').should(
|
|
||||||
'contain.text',
|
|
||||||
'The ID of the market this market succeeds.'
|
|
||||||
);
|
|
||||||
cy.contains('Insurance Pool Fraction').realHover();
|
|
||||||
cy.getByTestId('tooltip-content').should(
|
|
||||||
'contain.text',
|
|
||||||
'The fraction of the insurance pool balance that is carried over from the parent market to the successor.'
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
after('Disassociate from second wallet key if present', function () {
|
after('Disassociate from second wallet key if present', function () {
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
|
|||||||
cy.clearLocalStorage();
|
cy.clearLocalStorage();
|
||||||
turnTelemetryOff();
|
turnTelemetryOff();
|
||||||
cy.reload();
|
cy.reload();
|
||||||
|
cy.mockChainId();
|
||||||
waitForSpinner();
|
waitForSpinner();
|
||||||
cy.connectVegaWallet();
|
cy.connectVegaWallet();
|
||||||
ethereumWalletConnect();
|
ethereumWalletConnect();
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ context('rewards - flow', { tags: '@slow' }, function () {
|
|||||||
before('set up environment to allow rewards', function () {
|
before('set up environment to allow rewards', function () {
|
||||||
cy.clearLocalStorage();
|
cy.clearLocalStorage();
|
||||||
turnTelemetryOff();
|
turnTelemetryOff();
|
||||||
|
cy.mockChainId();
|
||||||
cy.visit('/');
|
cy.visit('/');
|
||||||
waitForSpinner();
|
waitForSpinner();
|
||||||
ethereumWalletConnect();
|
ethereumWalletConnect();
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import {
|
|||||||
vegaWalletSetSpecifiedApprovalAmount,
|
vegaWalletSetSpecifiedApprovalAmount,
|
||||||
vegaWalletTeardown,
|
vegaWalletTeardown,
|
||||||
} from '../../support/wallet-functions';
|
} from '../../support/wallet-functions';
|
||||||
|
|
||||||
const stakeValidatorListTotalStake = 'total-stake';
|
const stakeValidatorListTotalStake = 'total-stake';
|
||||||
const stakeValidatorListTotalShare = 'total-stake-share';
|
const stakeValidatorListTotalShare = 'total-stake-share';
|
||||||
const stakeValidatorListStakePercentage = 'stake-percentage';
|
const stakeValidatorListStakePercentage = 'stake-percentage';
|
||||||
@@ -67,6 +68,7 @@ context(
|
|||||||
function () {
|
function () {
|
||||||
cy.clearLocalStorage();
|
cy.clearLocalStorage();
|
||||||
turnTelemetryOff();
|
turnTelemetryOff();
|
||||||
|
cy.mockChainId();
|
||||||
// Go to homepage to allow wallet teardown without epoch timer refreshing page
|
// Go to homepage to allow wallet teardown without epoch timer refreshing page
|
||||||
navigateTo(navigation.home);
|
navigateTo(navigation.home);
|
||||||
vegaWalletTeardown();
|
vegaWalletTeardown();
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ context(
|
|||||||
function () {
|
function () {
|
||||||
cy.clearLocalStorage();
|
cy.clearLocalStorage();
|
||||||
turnTelemetryOff();
|
turnTelemetryOff();
|
||||||
|
cy.mockChainId();
|
||||||
cy.reload();
|
cy.reload();
|
||||||
waitForSpinner();
|
waitForSpinner();
|
||||||
cy.connectVegaWallet();
|
cy.connectVegaWallet();
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ context(
|
|||||||
beforeEach('Navigate to withdrawal page', function () {
|
beforeEach('Navigate to withdrawal page', function () {
|
||||||
cy.clearLocalStorage();
|
cy.clearLocalStorage();
|
||||||
turnTelemetryOff();
|
turnTelemetryOff();
|
||||||
|
cy.mockChainId();
|
||||||
cy.reload();
|
cy.reload();
|
||||||
waitForSpinner();
|
waitForSpinner();
|
||||||
navigateTo(navigation.withdraw);
|
navigateTo(navigation.withdraw);
|
||||||
@@ -96,7 +97,8 @@ context(
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it(
|
// eslint-disable-next-line
|
||||||
|
it.skip(
|
||||||
'Able to withdraw asset: -eth wallet connected -withdraw funds button',
|
'Able to withdraw asset: -eth wallet connected -withdraw funds button',
|
||||||
{ tags: '@smoke' },
|
{ tags: '@smoke' },
|
||||||
function () {
|
function () {
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ context(
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 3009-NTWU-001 3009-NTWU-002 3009-NTWU-006 3009-NTWU-009
|
// 3009-NTWU-001 3009-NTWU-002 3009-NTWU-006 3009-NTWU-009
|
||||||
it('should display network upgrade banner with estimate', function () {
|
it.skip('should display network upgrade banner with estimate', function () {
|
||||||
mockNetworkUpgradeProposal();
|
mockNetworkUpgradeProposal();
|
||||||
cy.visit('/');
|
cy.visit('/');
|
||||||
cy.getByTestId('banners').within(() => {
|
cy.getByTestId('banners').within(() => {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
waitForBeginningOfEpoch,
|
waitForBeginningOfEpoch,
|
||||||
} from '../../support/staking.functions';
|
} from '../../support/staking.functions';
|
||||||
import { previousEpochData } from '../../fixtures/mocks/previous-epoch';
|
import { previousEpochData } from '../../fixtures/mocks/previous-epoch';
|
||||||
|
import { chainIdQuery, statisticsQuery } from '@vegaprotocol/mock';
|
||||||
|
|
||||||
const guideLink = 'staking-guide-link';
|
const guideLink = 'staking-guide-link';
|
||||||
const validatorTitle = 'validator-node-title';
|
const validatorTitle = 'validator-node-title';
|
||||||
@@ -33,11 +34,22 @@ const overstakedPenaltyToolTip = 'overstaked-penalty-tooltip';
|
|||||||
const multisigPenaltyToolTip = 'multisig-error-tooltip';
|
const multisigPenaltyToolTip = 'multisig-error-tooltip';
|
||||||
const epochCountDown = 'epoch-countdown';
|
const epochCountDown = 'epoch-countdown';
|
||||||
const stakeNumberRegex = /^\d{1,3}(,\d{3})*(\.\d+)?$/;
|
const stakeNumberRegex = /^\d{1,3}(,\d{3})*(\.\d+)?$/;
|
||||||
|
const txTimeout = Cypress.env('txTimeout');
|
||||||
|
|
||||||
context('Validators Page - verify elements on page', function () {
|
context('Validators Page - verify elements on page', function () {
|
||||||
before('navigate to validators page', function () {
|
before('navigate to validators page', () => {
|
||||||
|
cy.mockGQL((req) => {
|
||||||
|
aliasGQLQuery(req, 'ChainId', chainIdQuery());
|
||||||
|
aliasGQLQuery(req, 'Statistics', statisticsQuery());
|
||||||
|
});
|
||||||
cy.visit('/validators');
|
cy.visit('/validators');
|
||||||
});
|
});
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.mockGQL((req) => {
|
||||||
|
aliasGQLQuery(req, 'ChainId', chainIdQuery());
|
||||||
|
aliasGQLQuery(req, 'Statistics', statisticsQuery());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('with wallets disconnected', { tags: '@smoke' }, function () {
|
describe('with wallets disconnected', { tags: '@smoke' }, function () {
|
||||||
it('Should have validators tab highlighted', function () {
|
it('Should have validators tab highlighted', function () {
|
||||||
@@ -177,6 +189,11 @@ context('Validators Page - verify elements on page', function () {
|
|||||||
{ tags: '@smoke' },
|
{ tags: '@smoke' },
|
||||||
function () {
|
function () {
|
||||||
before('connect wallets and click on validator', function () {
|
before('connect wallets and click on validator', function () {
|
||||||
|
cy.mockGQL((req) => {
|
||||||
|
aliasGQLQuery(req, 'ChainId', chainIdQuery());
|
||||||
|
aliasGQLQuery(req, 'Statistics', statisticsQuery());
|
||||||
|
});
|
||||||
|
cy.visit('/validators');
|
||||||
cy.connectVegaWallet();
|
cy.connectVegaWallet();
|
||||||
clickOnValidatorFromList(0);
|
clickOnValidatorFromList(0);
|
||||||
});
|
});
|
||||||
@@ -263,7 +280,7 @@ context('Validators Page - verify elements on page', function () {
|
|||||||
|
|
||||||
cy.getByTestId(epochCountDown).within(() => {
|
cy.getByTestId(epochCountDown).within(() => {
|
||||||
cy.get(epochTitle).should('not.be.empty');
|
cy.get(epochTitle).should('not.be.empty');
|
||||||
cy.get(nextEpochInfo).should('contain.text', 'Next epoch');
|
cy.get(nextEpochInfo, txTimeout).should('contain.text', 'Next epoch');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import {
|
|||||||
vegaWalletFaucetAssetsWithoutCheck,
|
vegaWalletFaucetAssetsWithoutCheck,
|
||||||
vegaWalletTeardown,
|
vegaWalletTeardown,
|
||||||
} from '../../support/wallet-functions';
|
} from '../../support/wallet-functions';
|
||||||
|
import { aliasGQLQuery } from '@vegaprotocol/cypress';
|
||||||
|
import { chainIdQuery, statisticsQuery } from '@vegaprotocol/mock';
|
||||||
|
|
||||||
const walletContainer = 'aside [data-testid="vega-wallet"]';
|
const walletContainer = 'aside [data-testid="vega-wallet"]';
|
||||||
const walletHeader = '[data-testid="wallet-header"] h1';
|
const walletHeader = '[data-testid="wallet-header"] h1';
|
||||||
@@ -14,10 +16,6 @@ const dialogHeader = 'dialog-title';
|
|||||||
const walletDialogHeader = 'wallet-dialog-title';
|
const walletDialogHeader = 'wallet-dialog-title';
|
||||||
const connectorsList = 'connectors-list';
|
const connectorsList = 'connectors-list';
|
||||||
const dialogCloseBtn = 'dialog-close';
|
const dialogCloseBtn = 'dialog-close';
|
||||||
const restConnectorForm = 'rest-connector-form';
|
|
||||||
const restWallet = '#wallet';
|
|
||||||
const restPassphrase = '#passphrase';
|
|
||||||
const restConnectBtn = '[type="submit"]';
|
|
||||||
const accountNo = 'vega-account-truncated';
|
const accountNo = 'vega-account-truncated';
|
||||||
const currencyTitle = 'currency-title';
|
const currencyTitle = 'currency-title';
|
||||||
const currencyValue = 'currency-value';
|
const currencyValue = 'currency-value';
|
||||||
@@ -69,7 +67,7 @@ context(
|
|||||||
cy.get(dialog).within(() => {
|
cy.get(dialog).within(() => {
|
||||||
cy.getByTestId(walletDialogHeader)
|
cy.getByTestId(walletDialogHeader)
|
||||||
.should('be.visible')
|
.should('be.visible')
|
||||||
.and('have.text', 'Connect');
|
.and('have.text', 'Get a Vega wallet');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -77,10 +75,7 @@ context(
|
|||||||
cy.getByTestId(connectorsList).within(() => {
|
cy.getByTestId(connectorsList).within(() => {
|
||||||
cy.getByTestId('connector-jsonRpc')
|
cy.getByTestId('connector-jsonRpc')
|
||||||
.should('be.visible')
|
.should('be.visible')
|
||||||
.and('have.text', 'Connect Vega wallet');
|
.and('have.text', 'Use the Desktop App/CLI');
|
||||||
cy.getByTestId('connector-rest')
|
|
||||||
.should('be.visible')
|
|
||||||
.and('have.text', 'Hosted Fairground wallet');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -91,48 +86,14 @@ context(
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when rest connector form opened', function () {
|
|
||||||
before('click hosted wallet app button', function () {
|
|
||||||
cy.getByTestId(connectorsList).within(() => {
|
|
||||||
cy.getByTestId('connector-rest').click();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// 0002-WCON-002
|
|
||||||
it('should have wallet field visible', function () {
|
|
||||||
cy.getByTestId(restConnectorForm).within(() => {
|
|
||||||
cy.get(restWallet).should('be.visible');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have password field visible', function () {
|
|
||||||
cy.getByTestId(restConnectorForm).within(() => {
|
|
||||||
cy.get(restPassphrase).should('be.visible');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have connect button visible', function () {
|
|
||||||
cy.getByTestId(restConnectorForm).within(() => {
|
|
||||||
cy.get(restConnectBtn)
|
|
||||||
.should('be.visible')
|
|
||||||
.and('have.text', 'Connect');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have close button visible', function () {
|
|
||||||
cy.get(dialog).within(() => {
|
|
||||||
cy.getByTestId(dialogCloseBtn).should('be.visible');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
after('close dialog', function () {
|
|
||||||
cy.getByTestId(dialogCloseBtn).click().should('not.exist');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when vega wallet connected', function () {
|
describe('when vega wallet connected', function () {
|
||||||
before('connect vega wallet', function () {
|
before('connect vega wallet', function () {
|
||||||
|
cy.mockGQL((req) => {
|
||||||
|
aliasGQLQuery(req, 'ChainId', chainIdQuery());
|
||||||
|
aliasGQLQuery(req, 'Statistics', statisticsQuery());
|
||||||
|
});
|
||||||
cy.visit('/');
|
cy.visit('/');
|
||||||
|
cy.wait('@ChainId');
|
||||||
cy.connectVegaWallet();
|
cy.connectVegaWallet();
|
||||||
vegaWalletTeardown();
|
vegaWalletTeardown();
|
||||||
});
|
});
|
||||||
@@ -315,6 +276,10 @@ context(
|
|||||||
];
|
];
|
||||||
|
|
||||||
before('faucet assets to connected vega wallet', function () {
|
before('faucet assets to connected vega wallet', function () {
|
||||||
|
cy.mockGQL((req) => {
|
||||||
|
aliasGQLQuery(req, 'ChainId', chainIdQuery());
|
||||||
|
aliasGQLQuery(req, 'Statistics', statisticsQuery());
|
||||||
|
});
|
||||||
for (const { id, amount } of assets) {
|
for (const { id, amount } of assets) {
|
||||||
vegaWalletFaucetAssetsWithoutCheck(id, amount, vegaWalletPublicKey);
|
vegaWalletFaucetAssetsWithoutCheck(id, amount, vegaWalletPublicKey);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -232,6 +232,23 @@ export function getDownloadedProposalJsonPath(proposalType: string) {
|
|||||||
return filepath;
|
return filepath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function validateProposalDetailsDiff(
|
||||||
|
RowName: string,
|
||||||
|
changeType: proposalChangeType,
|
||||||
|
newValue: string,
|
||||||
|
oldValue?: string
|
||||||
|
) {
|
||||||
|
cy.contains(RowName)
|
||||||
|
.parentsUntil(proposalInformationTableRows)
|
||||||
|
.parent()
|
||||||
|
.first()
|
||||||
|
.within(() => {
|
||||||
|
cy.contains(changeType).should('be.visible');
|
||||||
|
cy.contains(newValue).should('be.visible');
|
||||||
|
if (oldValue) cy.contains(oldValue).should('have.class', 'line-through');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function getFormattedTime() {
|
function getFormattedTime() {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const day = now.getDate().toString().padStart(2, '0');
|
const day = now.getDate().toString().padStart(2, '0');
|
||||||
@@ -252,3 +269,8 @@ export enum governanceProposalType {
|
|||||||
FREEFORM = 'Freeform',
|
FREEFORM = 'Freeform',
|
||||||
RAW = 'raw proposal',
|
RAW = 'raw proposal',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum proposalChangeType {
|
||||||
|
UPDATED = 'Updated',
|
||||||
|
ADDED = 'Added',
|
||||||
|
}
|
||||||
|
|||||||
@@ -211,6 +211,143 @@ export function createNewMarketProposalTxBody(): ProposalSubmissionBody {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Requires cy.createMarket() to be run to set up parent market
|
||||||
|
export function createSuccessorMarketProposalTxBody(
|
||||||
|
parentMarketId: string
|
||||||
|
): ProposalSubmissionBody {
|
||||||
|
const MIN_CLOSE_SEC = 10000;
|
||||||
|
const MIN_ENACT_SEC = 10000;
|
||||||
|
|
||||||
|
const closingDate = addSeconds(new Date(), MIN_CLOSE_SEC);
|
||||||
|
const enactmentDate = addSeconds(closingDate, MIN_ENACT_SEC);
|
||||||
|
const closingTimestamp = millisecondsToSeconds(closingDate.getTime());
|
||||||
|
const enactmentTimestamp = millisecondsToSeconds(enactmentDate.getTime());
|
||||||
|
return {
|
||||||
|
proposalSubmission: {
|
||||||
|
rationale: {
|
||||||
|
title: 'Test successor market proposal details',
|
||||||
|
description: 'E2E test for successor market',
|
||||||
|
},
|
||||||
|
terms: {
|
||||||
|
newMarket: {
|
||||||
|
changes: {
|
||||||
|
decimalPlaces: '5',
|
||||||
|
positionDecimalPlaces: '5',
|
||||||
|
linearSlippageFactor: '0.001',
|
||||||
|
quadraticSlippageFactor: '0',
|
||||||
|
lpPriceRange: '10',
|
||||||
|
instrument: {
|
||||||
|
name: 'Token test market',
|
||||||
|
code: 'TEST.24h',
|
||||||
|
future: {
|
||||||
|
settlementAsset:
|
||||||
|
'816af99af60d684502a40824758f6b5377e6af48e50a9ee8ef478ecb879ea8bc',
|
||||||
|
quoteName: 'fUSDC',
|
||||||
|
dataSourceSpecForSettlementData: {
|
||||||
|
external: {
|
||||||
|
oracle: {
|
||||||
|
signers: [
|
||||||
|
{
|
||||||
|
pubKey: {
|
||||||
|
key: '70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
key: {
|
||||||
|
name: 'prices.BTC.value',
|
||||||
|
type: 'TYPE_INTEGER' as const,
|
||||||
|
numberDecimalPlaces: '0',
|
||||||
|
},
|
||||||
|
conditions: [
|
||||||
|
{
|
||||||
|
operator: 'OPERATOR_GREATER_THAN' as const,
|
||||||
|
value: '0',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dataSourceSpecForTradingTermination: {
|
||||||
|
external: {
|
||||||
|
oracle: {
|
||||||
|
signers: [
|
||||||
|
{
|
||||||
|
pubKey: {
|
||||||
|
key: '70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
key: {
|
||||||
|
name: 'trading.terminated.ETH5',
|
||||||
|
type: 'TYPE_BOOLEAN' as const,
|
||||||
|
},
|
||||||
|
conditions: [
|
||||||
|
{
|
||||||
|
operator: 'OPERATOR_EQUALS' as const,
|
||||||
|
value: 'true',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dataSourceSpecBinding: {
|
||||||
|
settlementDataProperty: 'prices.BTC.value',
|
||||||
|
tradingTerminationProperty: 'trading.terminated.ETH5',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
metadata: [
|
||||||
|
'sector:food',
|
||||||
|
'sector:materials',
|
||||||
|
'source:docs.vega.xyz',
|
||||||
|
],
|
||||||
|
priceMonitoringParameters: {
|
||||||
|
triggers: [
|
||||||
|
{
|
||||||
|
horizon: '43200',
|
||||||
|
probability: '0.9999999',
|
||||||
|
auctionExtension: '600',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
liquidityMonitoringParameters: {
|
||||||
|
targetStakeParameters: {
|
||||||
|
timeWindow: '3600',
|
||||||
|
scalingFactor: 10,
|
||||||
|
},
|
||||||
|
triggeringRatio: '0.7',
|
||||||
|
auctionExtension: '1',
|
||||||
|
},
|
||||||
|
logNormal: {
|
||||||
|
tau: 0.0001140771161,
|
||||||
|
riskAversionParameter: 0.01,
|
||||||
|
params: {
|
||||||
|
mu: 0,
|
||||||
|
r: 0.016,
|
||||||
|
sigma: 0.5,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
successor: {
|
||||||
|
parentMarketId: parentMarketId,
|
||||||
|
insurancePoolFraction: '0.75',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
closingTimestamp,
|
||||||
|
enactmentTimestamp,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function mockNetworkUpgradeProposal() {
|
export function mockNetworkUpgradeProposal() {
|
||||||
cy.mockGQL((req) => {
|
cy.mockGQL((req) => {
|
||||||
aliasGQLQuery(req, 'Nodes', nodeData);
|
aliasGQLQuery(req, 'Nodes', nodeData);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","STAGNET1":"https:
|
|||||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||||
NX_VEGA_WALLET_URL=http://localhost:1789
|
NX_VEGA_WALLET_URL=http://localhost:1789
|
||||||
NX_VEGA_EXPLORER_URL=https://explorer.stagnet1.vega.rocks
|
NX_VEGA_EXPLORER_URL=https://explorer.stagnet1.vega.rocks
|
||||||
|
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||||
|
|
||||||
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
||||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||||
@@ -21,6 +22,9 @@ NX_VEGA_REST_URL=https://api.n00.stagnet1.vega.xyz/api/v2/
|
|||||||
NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.rocks
|
NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.rocks
|
||||||
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
|
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
|
||||||
|
|
||||||
|
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||||
|
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/pl/firefox/addon/vega-wallet
|
||||||
|
|
||||||
#Test configuration variables
|
#Test configuration variables
|
||||||
CYPRESS_FAIRGROUND=false
|
CYPRESS_FAIRGROUND=false
|
||||||
LC_ALL="en_US.UTF-8"
|
LC_ALL="en_US.UTF-8"
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ export const VegaWalletPrompt = () => {
|
|||||||
</Link>
|
</Link>
|
||||||
<ButtonLink
|
<ButtonLink
|
||||||
className="text-neutral-500"
|
className="text-neutral-500"
|
||||||
|
data-testid="view-as-user"
|
||||||
onClick={() => setViewAsDialog(true)}
|
onClick={() => setViewAsDialog(true)}
|
||||||
>
|
>
|
||||||
{t('viewAsParty')}
|
{t('viewAsParty')}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="dark bg-black w-full h-full">
|
<html lang="en" class="dark bg-black w-full h-full">
|
||||||
<head>
|
<head>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="stylesheet" href="//static.vega.xyz/fonts.css" />
|
|
||||||
<link
|
<link
|
||||||
rel="icon"
|
rel="icon"
|
||||||
type="image/x-icon"
|
type="image/x-icon"
|
||||||
@@ -10,35 +10,42 @@
|
|||||||
/>
|
/>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta name="theme-color" content="#000000" />
|
<meta name="theme-color" content="#000000" />
|
||||||
<meta name="description" content="Vega Protocol - VEGA Token Vesting" />
|
<meta name="description" content="Vega Protocol - VEGA Governance" />
|
||||||
|
<meta name="og:type" content="website" />
|
||||||
|
<meta name="og:url" content="https://governance.vega.xyz/" />
|
||||||
|
<meta name="og:title" content="Vega Protocol - Governance" />
|
||||||
|
<meta name="og:site_name" content="Vega Protocol - Governance" />
|
||||||
|
<meta name="og:image" content="https://static.vega.xyz/favicon.ico" />
|
||||||
|
|
||||||
|
<meta name="twitter:card" content="https://static.vega.xyz/favicon.ico" />
|
||||||
|
<meta name="twitter:title" content="Vega Protocol - Governance" />
|
||||||
|
<meta name="twitter:description" content="Vega Protocol - Governance" />
|
||||||
|
<meta name="twitter:image" content="https://static.vega.xyz/favicon.ico" />
|
||||||
|
<meta name="twitter:image:alt" content="VEGA logo" />
|
||||||
|
<meta name="twitter:site" content="@vegaprotocol" />
|
||||||
|
|
||||||
|
<meta name="description" content="Vega Protocol - Governance" />
|
||||||
<link rel="apple-touch-icon" href="assets/apple-touch-icon.png" />
|
<link rel="apple-touch-icon" href="assets/apple-touch-icon.png" />
|
||||||
<!--
|
|
||||||
manifest.json provides metadata used when your web app is installed on a
|
|
||||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
|
||||||
-->
|
|
||||||
<link rel="manifest" href="assets/manifest.json" />
|
<link rel="manifest" href="assets/manifest.json" />
|
||||||
<link
|
<link
|
||||||
rel="preload"
|
rel="preload"
|
||||||
href="https://static.vega.xyz/AlphaLyrae-Medium.woff2"
|
href="https://static.vega.xyz/AlphaLyrae-Medium.woff2"
|
||||||
as="font"
|
as="font"
|
||||||
type="font/woff2"
|
type="font/woff2"
|
||||||
crossorigin="anonymous"
|
|
||||||
/>
|
/>
|
||||||
<title>Vega Governance dApp</title>
|
<title>VEGA Governance</title>
|
||||||
<script src="./assets/env-config.js"></script>
|
<script src="./assets/env-config.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body class="h-full">
|
<body class="h-full">
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript> You need to enable JavaScript to run this app. </noscript>
|
||||||
<div id="root" class="h-full"></div>
|
<div id="root" class="h-full"></div>
|
||||||
<!--
|
<!-- This HTML file is a template.
|
||||||
This HTML file is a template.
|
|
||||||
If you open it directly in the browser, you will see an empty page.
|
If you open it directly in the browser, you will see an empty page.
|
||||||
|
|
||||||
You can add webfonts, meta tags, or analytics to this file.
|
You can add webfonts, meta tags, or analytics to this file.
|
||||||
The build step will place the bundled scripts into the <body> tag.
|
The build step will place the bundled scripts into the <body> tag.
|
||||||
|
|
||||||
To begin the development, run `npm start` or `yarn start`.
|
To begin the development, run `npm start` or `yarn start`.
|
||||||
To create a production bundle, use `npm run build` or `yarn build`.
|
To create a production bundle, use `npm run build` or `yarn build`. -->
|
||||||
-->
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import {
|
import {
|
||||||
RestConnector,
|
|
||||||
JsonRpcConnector,
|
JsonRpcConnector,
|
||||||
ViewConnector,
|
ViewConnector,
|
||||||
InjectedConnector,
|
InjectedConnector,
|
||||||
@@ -8,13 +7,11 @@ import {
|
|||||||
const urlParams = new URLSearchParams(window.location.search);
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
|
||||||
export const injected = new InjectedConnector();
|
export const injected = new InjectedConnector();
|
||||||
export const rest = new RestConnector();
|
|
||||||
export const jsonRpc = new JsonRpcConnector();
|
export const jsonRpc = new JsonRpcConnector();
|
||||||
export const view = new ViewConnector(urlParams.get('address'));
|
export const view = new ViewConnector(urlParams.get('address'));
|
||||||
|
|
||||||
export const Connectors = {
|
export const Connectors = {
|
||||||
injected,
|
injected,
|
||||||
rest,
|
|
||||||
jsonRpc,
|
jsonRpc,
|
||||||
view,
|
view,
|
||||||
};
|
};
|
||||||
|
|||||||
+3
-3
@@ -25,7 +25,7 @@ import {
|
|||||||
} from '@vegaprotocol/ui-toolkit';
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
import { SubHeading } from '../../../../components/heading';
|
import { SubHeading } from '../../../../components/heading';
|
||||||
import { CollapsibleToggle } from '../../../../components/collapsible-toggle';
|
import { CollapsibleToggle } from '../../../../components/collapsible-toggle';
|
||||||
import type { MarketInfoWithData } from '@vegaprotocol/markets';
|
import type { MarketInfo } from '@vegaprotocol/markets';
|
||||||
import type { DataSourceDefinition } from '@vegaprotocol/types';
|
import type { DataSourceDefinition } from '@vegaprotocol/types';
|
||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
|
|
||||||
@@ -47,8 +47,8 @@ export const ProposalMarketData = ({
|
|||||||
marketData,
|
marketData,
|
||||||
parentMarketData,
|
parentMarketData,
|
||||||
}: {
|
}: {
|
||||||
marketData: MarketInfoWithData;
|
marketData: MarketInfo;
|
||||||
parentMarketData?: MarketInfoWithData;
|
parentMarketData?: MarketInfo;
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { isOpen, open, close } = useMarketDataDialogStore();
|
const { isOpen, open, close } = useMarketDataDialogStore();
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import Routes from '../../../routes';
|
|||||||
import { ProposalMarketData } from '../proposal-market-data';
|
import { ProposalMarketData } from '../proposal-market-data';
|
||||||
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
|
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
|
||||||
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
|
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
|
||||||
import type { MarketInfoWithData } from '@vegaprotocol/markets';
|
import type { MarketInfo } from '@vegaprotocol/markets';
|
||||||
import type { AssetQuery } from '@vegaprotocol/assets';
|
import type { AssetQuery } from '@vegaprotocol/assets';
|
||||||
import { removePaginationWrapper } from '@vegaprotocol/utils';
|
import { removePaginationWrapper } from '@vegaprotocol/utils';
|
||||||
import { ProposalState } from '@vegaprotocol/types';
|
import { ProposalState } from '@vegaprotocol/types';
|
||||||
@@ -31,8 +31,8 @@ export enum ProposalType {
|
|||||||
export interface ProposalProps {
|
export interface ProposalProps {
|
||||||
proposal: ProposalFieldsFragment | ProposalQuery['proposal'];
|
proposal: ProposalFieldsFragment | ProposalQuery['proposal'];
|
||||||
networkParams: Partial<NetworkParamsResult>;
|
networkParams: Partial<NetworkParamsResult>;
|
||||||
newMarketData?: MarketInfoWithData | null;
|
newMarketData?: MarketInfo | null;
|
||||||
parentMarketData?: MarketInfoWithData | null;
|
parentMarketData?: MarketInfo | null;
|
||||||
assetData?: AssetQuery | null;
|
assetData?: AssetQuery | null;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
restData: any;
|
restData: any;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { useProposalQuery } from './__generated__/Proposal';
|
|||||||
import { useFetch } from '@vegaprotocol/react-helpers';
|
import { useFetch } from '@vegaprotocol/react-helpers';
|
||||||
import { ENV } from '../../../config';
|
import { ENV } from '../../../config';
|
||||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||||
import { marketInfoWithDataProvider } from '@vegaprotocol/markets';
|
import { marketInfoProvider } from '@vegaprotocol/markets';
|
||||||
import { useAssetQuery } from '@vegaprotocol/assets';
|
import { useAssetQuery } from '@vegaprotocol/assets';
|
||||||
import {
|
import {
|
||||||
NetworkParams,
|
NetworkParams,
|
||||||
@@ -95,7 +95,7 @@ export const ProposalContainer = () => {
|
|||||||
loading: newMarketLoading,
|
loading: newMarketLoading,
|
||||||
error: newMarketError,
|
error: newMarketError,
|
||||||
} = useDataProvider({
|
} = useDataProvider({
|
||||||
dataProvider: marketInfoWithDataProvider,
|
dataProvider: marketInfoProvider,
|
||||||
skipUpdates: true,
|
skipUpdates: true,
|
||||||
variables: {
|
variables: {
|
||||||
marketId: data?.proposal?.id || '',
|
marketId: data?.proposal?.id || '',
|
||||||
@@ -109,12 +109,9 @@ export const ProposalContainer = () => {
|
|||||||
error: parentMarketIdError,
|
error: parentMarketIdError,
|
||||||
} = useParentMarketIdQuery({
|
} = useParentMarketIdQuery({
|
||||||
variables: {
|
variables: {
|
||||||
marketId: newMarketData?.data?.market?.id || '',
|
marketId: newMarketData?.id || '',
|
||||||
},
|
},
|
||||||
skip:
|
skip: !FLAGS.SUCCESSOR_MARKETS || !isSuccessor || !newMarketData?.id,
|
||||||
!FLAGS.SUCCESSOR_MARKETS ||
|
|
||||||
!isSuccessor ||
|
|
||||||
!newMarketData?.data?.market?.id,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -122,7 +119,7 @@ export const ProposalContainer = () => {
|
|||||||
loading: parentMarketLoading,
|
loading: parentMarketLoading,
|
||||||
error: parentMarketError,
|
error: parentMarketError,
|
||||||
} = useDataProvider({
|
} = useDataProvider({
|
||||||
dataProvider: marketInfoWithDataProvider,
|
dataProvider: marketInfoProvider,
|
||||||
skipUpdates: true,
|
skipUpdates: true,
|
||||||
variables: {
|
variables: {
|
||||||
marketId: parentMarketId?.market?.parentMarketID || '',
|
marketId: parentMarketId?.market?.parentMarketID || '',
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ module.exports = defineConfig({
|
|||||||
requestTimeout: 20000,
|
requestTimeout: 20000,
|
||||||
retries: 1,
|
retries: 1,
|
||||||
testIsolation: false,
|
testIsolation: false,
|
||||||
|
experimentalMemoryManagement: true,
|
||||||
},
|
},
|
||||||
env: {
|
env: {
|
||||||
ETHERSCAN_URL: 'https://sepolia.etherscan.io',
|
ETHERSCAN_URL: 'https://sepolia.etherscan.io',
|
||||||
|
|||||||
@@ -1,177 +0,0 @@
|
|||||||
// #region consts
|
|
||||||
const assetColId = '[col-id="asset.symbol"]';
|
|
||||||
const assetDetailsDialog = 'dialog-content';
|
|
||||||
const assetRow = 'key-value-table-row';
|
|
||||||
const contractAddress = '7_value';
|
|
||||||
const dialogCloseBtn = 'close-asset-details-dialog';
|
|
||||||
const dialogCloseX = 'dialog-close';
|
|
||||||
const dialogTitle = 'dialog-title';
|
|
||||||
|
|
||||||
const indicesWithLabelTooltips = [4, 5, 6, 7, 8, 9, 11, 12, 13, 14];
|
|
||||||
const indicesWithValueTooltips = [1, 6];
|
|
||||||
|
|
||||||
const labelValueToolTipPairs = [
|
|
||||||
{
|
|
||||||
label: 'ID',
|
|
||||||
value: 'asset-id',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Type',
|
|
||||||
value: 'ERC20',
|
|
||||||
valueToolTip: 'An asset originated from an Ethereum ERC20 Token',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Name',
|
|
||||||
value: 'Euro',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Symbol',
|
|
||||||
value: 'tEURO',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Decimals',
|
|
||||||
value: '5',
|
|
||||||
labelTooltip: 'Number of decimal / precision handled by this asset',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Quantum',
|
|
||||||
value: '0.00001',
|
|
||||||
labelTooltip: 'The minimum economically meaningful amount of the asset',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Status',
|
|
||||||
value: 'Enabled',
|
|
||||||
labelTooltip: 'The status of the asset in the Vega network',
|
|
||||||
valueToolTip: 'Asset can be used on the Vega network',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Contract address',
|
|
||||||
value: '0x0158031158Bb4dF2AD02eAA31e8963E84EA978a4 ',
|
|
||||||
labelTooltip:
|
|
||||||
'The address of the contract for the token, on the ethereum network',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Withdrawal threshold',
|
|
||||||
value: '0.0005',
|
|
||||||
labelTooltip:
|
|
||||||
"The maximum you can withdraw instantly. There's no limit on the size of a withdrawal, but all withdrawals over the threshold will have a delay time added to them",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Lifetime limit',
|
|
||||||
value: '1,230.00',
|
|
||||||
labelTooltip:
|
|
||||||
'The lifetime deposit limit per address. Note: this is a temporary measure that can be changed or removed through governance',
|
|
||||||
},
|
|
||||||
{ label: '', value: '' },
|
|
||||||
{
|
|
||||||
label: 'Infrastructure fee account balance',
|
|
||||||
value: '0.00001',
|
|
||||||
labelTooltip: 'The infrastructure fee account in this asset',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Global reward pool account balance',
|
|
||||||
value: '0.00002',
|
|
||||||
labelTooltip: 'The global rewards acquired in this asset',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Maker paid fees account balance',
|
|
||||||
value: '0.00003',
|
|
||||||
labelTooltip:
|
|
||||||
'The rewards acquired based on the fees paid to makers in this asset',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Maker received fees account balance',
|
|
||||||
value: '0.00004',
|
|
||||||
labelTooltip:
|
|
||||||
'The rewards acquired based on fees received for being a maker on trades',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Liquidity provision fee reward account balance',
|
|
||||||
value: '0.00005',
|
|
||||||
labelTooltip:
|
|
||||||
'The rewards acquired based on the liquidity provision fees in this asset',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Market proposer reward account balance',
|
|
||||||
value: '0.00006',
|
|
||||||
labelTooltip:
|
|
||||||
'The rewards acquired based on the market proposer reward in this asset',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
//endregion
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.mockTradingPage();
|
|
||||||
cy.mockSubscription();
|
|
||||||
cy.setVegaWallet();
|
|
||||||
});
|
|
||||||
|
|
||||||
const visitPortfolioAndClickAsset = (assetName: string) => {
|
|
||||||
cy.visit('/#/portfolio');
|
|
||||||
cy.get(assetColId).contains(assetName).click();
|
|
||||||
};
|
|
||||||
|
|
||||||
const testTooltip = (index: number, testId: string, tooltip: string) => {
|
|
||||||
cy.getByTestId(`${index}_${testId}`).realHover();
|
|
||||||
cy.get('[role="tooltip"]').find('div').should('have.text', tooltip);
|
|
||||||
cy.getByTestId(dialogTitle).click();
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('assets', { tags: '@smoke', testIsolation: true }, () => {
|
|
||||||
it('asset details', () => {
|
|
||||||
visitPortfolioAndClickAsset('tBTC');
|
|
||||||
|
|
||||||
cy.getByTestId(assetRow).each((element, index) => {
|
|
||||||
if (index === 10) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const { label, value, labelTooltip, valueToolTip } =
|
|
||||||
labelValueToolTipPairs[index];
|
|
||||||
// 6501-ASSE-001
|
|
||||||
// 6501-ASSE-002
|
|
||||||
// 6501-ASSE-003
|
|
||||||
// 6501-ASSE-004
|
|
||||||
// 6501-ASSE-005
|
|
||||||
// 6501-ASSE-006
|
|
||||||
// 6501-ASSE-007
|
|
||||||
// 6501-ASSE-008
|
|
||||||
// 6501-ASSE-009
|
|
||||||
// 6501-ASSE-010
|
|
||||||
// 6501-ASSE-011
|
|
||||||
cy.getByTestId(`${index}_label`).should('have.text', label);
|
|
||||||
cy.getByTestId(`${index}_value`).should('have.text', value);
|
|
||||||
|
|
||||||
// 6501-ASSE-012
|
|
||||||
if (indicesWithLabelTooltips.includes(index)) {
|
|
||||||
if (labelTooltip) {
|
|
||||||
testTooltip(index, 'label', labelTooltip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (indicesWithValueTooltips.includes(index)) {
|
|
||||||
if (valueToolTip) {
|
|
||||||
testTooltip(index, 'value', valueToolTip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// 6501-ASSE-013
|
|
||||||
cy.getByTestId(dialogCloseX).click();
|
|
||||||
cy.document().then((doc) => {
|
|
||||||
expect(doc.querySelector(assetDetailsDialog)).to.not.exist;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('ERC20 Contract address', () => {
|
|
||||||
visitPortfolioAndClickAsset('tBTC');
|
|
||||||
cy.getByTestId(contractAddress).within(() => {
|
|
||||||
// 6501-ASSE-014
|
|
||||||
cy.getByTestId('external-link')
|
|
||||||
.should('have.attr', 'target', '_blank')
|
|
||||||
.should('have.text', '0x0158031158Bb4dF2AD02eAA31e8963E84EA978a4');
|
|
||||||
});
|
|
||||||
// 6501-ASSE-013
|
|
||||||
cy.getByTestId(dialogCloseBtn).click();
|
|
||||||
cy.document().then((doc) => {
|
|
||||||
expect(doc.querySelector(assetDetailsDialog)).to.not.exist;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,208 +0,0 @@
|
|||||||
import { aliasGQLQuery } from '@vegaprotocol/cypress';
|
|
||||||
import type { ProposalListFieldsFragment } from '@vegaprotocol/proposals';
|
|
||||||
import * as Schema from '@vegaprotocol/types';
|
|
||||||
|
|
||||||
const dialogContent = 'welcome-dialog';
|
|
||||||
|
|
||||||
const generateProposal = (code: string): ProposalListFieldsFragment => ({
|
|
||||||
__typename: 'Proposal',
|
|
||||||
reference: '',
|
|
||||||
state: Schema.ProposalState.STATE_OPEN,
|
|
||||||
datetime: '',
|
|
||||||
votes: {
|
|
||||||
__typename: undefined,
|
|
||||||
yes: {
|
|
||||||
__typename: undefined,
|
|
||||||
totalTokens: '',
|
|
||||||
totalNumber: '',
|
|
||||||
totalWeight: '',
|
|
||||||
},
|
|
||||||
no: {
|
|
||||||
__typename: undefined,
|
|
||||||
totalTokens: '',
|
|
||||||
totalNumber: '',
|
|
||||||
totalWeight: '',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
requiredMajority: '',
|
|
||||||
party: {
|
|
||||||
__typename: 'Party',
|
|
||||||
id: '',
|
|
||||||
},
|
|
||||||
rationale: {
|
|
||||||
__typename: 'ProposalRationale',
|
|
||||||
description: '',
|
|
||||||
title: '',
|
|
||||||
},
|
|
||||||
requiredParticipation: '',
|
|
||||||
errorDetails: '',
|
|
||||||
rejectionReason: null,
|
|
||||||
requiredLpMajority: '',
|
|
||||||
requiredLpParticipation: '',
|
|
||||||
terms: {
|
|
||||||
__typename: 'ProposalTerms',
|
|
||||||
closingDatetime: '',
|
|
||||||
enactmentDatetime: undefined,
|
|
||||||
change: {
|
|
||||||
__typename: 'NewMarket',
|
|
||||||
decimalPlaces: 1,
|
|
||||||
lpPriceRange: '',
|
|
||||||
riskParameters: {
|
|
||||||
__typename: 'SimpleRiskModel',
|
|
||||||
params: {
|
|
||||||
__typename: 'SimpleRiskModelParams',
|
|
||||||
factorLong: 0,
|
|
||||||
factorShort: 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
metadata: [],
|
|
||||||
instrument: {
|
|
||||||
__typename: 'InstrumentConfiguration',
|
|
||||||
code: code,
|
|
||||||
name: code,
|
|
||||||
futureProduct: {
|
|
||||||
__typename: 'FutureProduct',
|
|
||||||
settlementAsset: {
|
|
||||||
__typename: 'Asset',
|
|
||||||
id: 'A',
|
|
||||||
name: 'A',
|
|
||||||
symbol: 'A',
|
|
||||||
decimals: 1,
|
|
||||||
quantum: '',
|
|
||||||
},
|
|
||||||
quoteName: '',
|
|
||||||
dataSourceSpecBinding: {
|
|
||||||
__typename: 'DataSourceSpecToFutureBinding',
|
|
||||||
settlementDataProperty: '',
|
|
||||||
tradingTerminationProperty: '',
|
|
||||||
},
|
|
||||||
dataSourceSpecForSettlementData: {
|
|
||||||
__typename: 'DataSourceDefinition',
|
|
||||||
sourceType: {
|
|
||||||
__typename: 'DataSourceDefinitionInternal',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
dataSourceSpecForTradingTermination: {
|
|
||||||
__typename: 'DataSourceDefinition',
|
|
||||||
sourceType: {
|
|
||||||
__typename: 'DataSourceDefinitionInternal',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('home', { tags: '@regression' }, () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.clearLocalStorage();
|
|
||||||
cy.mockTradingPage();
|
|
||||||
cy.mockSubscription();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('default market found', () => {
|
|
||||||
it('redirects to a default market with the landing dialog open', () => {
|
|
||||||
cy.visit('/');
|
|
||||||
cy.wait('@Markets');
|
|
||||||
|
|
||||||
cy.get('[data-testid^="pathname-/markets/"]');
|
|
||||||
|
|
||||||
// the choose market overlay is no longer showing
|
|
||||||
cy.contains('Loading...').should('not.exist');
|
|
||||||
cy.url().should('eq', Cypress.config().baseUrl + '/#/markets/market-0');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('no markets found', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.mockGQL((req) => {
|
|
||||||
const data = {
|
|
||||||
marketsConnection: {
|
|
||||||
__typename: 'MarketConnection',
|
|
||||||
edges: [],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const proposalA: ProposalListFieldsFragment =
|
|
||||||
generateProposal('AAAZZZ');
|
|
||||||
|
|
||||||
aliasGQLQuery(req, 'Markets', data);
|
|
||||||
aliasGQLQuery(req, 'MarketsData', data);
|
|
||||||
aliasGQLQuery(req, 'ProposalsList', {
|
|
||||||
proposalsConnection: {
|
|
||||||
__typename: 'ProposalsConnection',
|
|
||||||
edges: [{ __typename: 'ProposalEdge', node: proposalA }],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
cy.visit('/');
|
|
||||||
cy.wait('@Markets');
|
|
||||||
cy.wait('@MarketsData');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('close welcome dialog should redirect to market/all', () => {
|
|
||||||
cy.url().should('eq', Cypress.config().baseUrl + `/#/markets/all`);
|
|
||||||
cy.getByTestId('welcome-dialog').should('be.visible');
|
|
||||||
cy.getByTestId('welcome-title').should('contain.text', 'Console CUSTOM');
|
|
||||||
cy.getByTestId('browse-markets-button').should('not.be.disabled');
|
|
||||||
cy.getByTestId('get-started-banner').should('be.visible');
|
|
||||||
cy.getByTestId('get-started-button').should('not.be.disabled');
|
|
||||||
cy.getByTestId('dialog-close').click();
|
|
||||||
cy.url().should('eq', Cypress.config().baseUrl + `/#/markets/all`);
|
|
||||||
cy.window().then((window) => {
|
|
||||||
expect(window.localStorage.getItem('vega_onboarding_viewed')).to.equal(
|
|
||||||
'true'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('click browse markets button should redirect to market/all', () => {
|
|
||||||
cy.getByTestId('welcome-dialog').should('be.visible');
|
|
||||||
cy.getByTestId('browse-markets-button').click();
|
|
||||||
cy.url().should('eq', Cypress.config().baseUrl + `/#/markets/all`);
|
|
||||||
cy.window().then((window) => {
|
|
||||||
expect(window.localStorage.getItem('vega_onboarding_viewed')).to.equal(
|
|
||||||
'true'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('click get started button should open connect dialog', () => {
|
|
||||||
cy.getByTestId('welcome-dialog').should('be.visible');
|
|
||||||
cy.getByTestId('get-started-button').click();
|
|
||||||
cy.url().should('eq', Cypress.config().baseUrl + `/#/markets/all`);
|
|
||||||
cy.window().then((window) => {
|
|
||||||
expect(window.localStorage.getItem('vega_onboarding_viewed')).to.equal(
|
|
||||||
'true'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
cy.getByTestId('wallet-dialog-title').should('contain.text', 'Connect');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('redirect should take last visited market into consideration', () => {
|
|
||||||
it('marketId comes from existing market', () => {
|
|
||||||
cy.window().then((window) => {
|
|
||||||
window.localStorage.setItem('marketId', 'market-1');
|
|
||||||
cy.visit('/');
|
|
||||||
cy.getByTestId('dialog-close').click();
|
|
||||||
cy.location('hash').should('equal', '#/markets/market-1');
|
|
||||||
cy.getByTestId(dialogContent).should('not.exist');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('marketId comes from not-existing market', () => {
|
|
||||||
cy.window().then((window) => {
|
|
||||||
window.localStorage.setItem('marketId', 'market-not-existing');
|
|
||||||
cy.mockGQL((req) => {
|
|
||||||
aliasGQLQuery(req, 'Market', null);
|
|
||||||
});
|
|
||||||
cy.visit('/');
|
|
||||||
cy.wait('@Markets');
|
|
||||||
cy.getByTestId('dialog-close').click();
|
|
||||||
cy.location('hash').should('equal', '#/markets/market-not-existing');
|
|
||||||
cy.getByTestId(dialogContent).should('not.exist');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
import * as Schema from '@vegaprotocol/types';
|
|
||||||
import { aliasGQLQuery } from '@vegaprotocol/cypress';
|
|
||||||
import { marketsQuery } from '@vegaprotocol/mock';
|
|
||||||
import { getDateTimeFormat } from '@vegaprotocol/utils';
|
|
||||||
|
|
||||||
describe('markets table', { tags: '@smoke' }, () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.clearLocalStorage().then(() => {
|
|
||||||
cy.mockTradingPage(
|
|
||||||
Schema.MarketState.STATE_ACTIVE,
|
|
||||||
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
|
|
||||||
Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY_TARGET_NOT_MET
|
|
||||||
);
|
|
||||||
cy.mockSubscription();
|
|
||||||
cy.setOnBoardingViewed();
|
|
||||||
cy.visit('/#/markets/all');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('opening auction subsets should be properly displayed', () => {
|
|
||||||
cy.mockTradingPage(
|
|
||||||
Schema.MarketState.STATE_ACTIVE,
|
|
||||||
Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION
|
|
||||||
);
|
|
||||||
cy.mockGQL((req) => {
|
|
||||||
const override = {
|
|
||||||
marketsConnection: {
|
|
||||||
edges: [
|
|
||||||
{
|
|
||||||
node: {
|
|
||||||
tradableInstrument: {
|
|
||||||
instrument: {
|
|
||||||
name: `opening auction MARKET`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
state: Schema.MarketState.STATE_ACTIVE,
|
|
||||||
tradingMode:
|
|
||||||
Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
// @ts-ignore partial deep check failing
|
|
||||||
const market = marketsQuery(override);
|
|
||||||
aliasGQLQuery(req, 'Market', market);
|
|
||||||
aliasGQLQuery(req, 'ProposalOfMarket', {
|
|
||||||
proposal: { terms: { enactmentDatetime: '2023-01-31 12:00:01' } },
|
|
||||||
});
|
|
||||||
});
|
|
||||||
cy.visit('#/markets/market-0');
|
|
||||||
cy.url().should('contain', 'market-0');
|
|
||||||
cy.getByTestId('item-value').contains('Opening auction').realHover();
|
|
||||||
cy.getByTestId('opening-auction-sub-status').should(
|
|
||||||
'contain.text',
|
|
||||||
'Opening auction: Not enough liquidity to open'
|
|
||||||
);
|
|
||||||
|
|
||||||
const now = new Date(Date.parse('2023-01-30 12:00:01')).getTime();
|
|
||||||
cy.clock(now, ['Date']); // Set "now" to BEFORE reservation
|
|
||||||
cy.reload();
|
|
||||||
cy.getByTestId('item-value').contains('Opening auction').realHover();
|
|
||||||
cy.getByTestId('opening-auction-sub-status').should(
|
|
||||||
'contain.text',
|
|
||||||
`Opening auction: Closing on ${getDateTimeFormat().format(
|
|
||||||
new Date('2023-01-31 12:00:01')
|
|
||||||
)}`
|
|
||||||
);
|
|
||||||
cy.clock().then((clock) => {
|
|
||||||
clock.restore();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -27,7 +27,8 @@ describe('positions', { tags: '@smoke', testIsolation: true }, () => {
|
|||||||
validatePositionsDisplayed();
|
validatePositionsDisplayed();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders positions on portfolio page', () => {
|
// TODO: move this to sim, its flakey
|
||||||
|
it.skip('renders positions on portfolio page', () => {
|
||||||
cy.mockGQL((req) => {
|
cy.mockGQL((req) => {
|
||||||
const positions = positionsQuery();
|
const positions = positionsQuery();
|
||||||
if (positions.positions?.edges) {
|
if (positions.positions?.edges) {
|
||||||
@@ -230,7 +231,7 @@ describe('positions', { tags: '@regression', testIsolation: true }, () => {
|
|||||||
deltaX: 500,
|
deltaX: 500,
|
||||||
});
|
});
|
||||||
// 7004-POSI-004
|
// 7004-POSI-004
|
||||||
cy.get('[col-id="updatedAt"]').should('be.visible');
|
cy.get('[col-id="unrealisedPNL"]').should('be.visible');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Drag and drop columns', () => {
|
it('Drag and drop columns', () => {
|
||||||
|
|||||||
@@ -59,8 +59,7 @@ describe('trades', { tags: '@smoke' }, () => {
|
|||||||
cy.getByTestId(tradesTable) // order table shares identical col id
|
cy.getByTestId(tradesTable) // order table shares identical col id
|
||||||
.find(`${colIdCreatedAt} ${colHeader}`)
|
.find(`${colIdCreatedAt} ${colHeader}`)
|
||||||
.should('have.text', 'Created at');
|
.should('have.text', 'Created at');
|
||||||
const dateTimeRegex =
|
const dateTimeRegex = /(\d{1,2}):(\d{1,2}):(\d{1,2})/gm;
|
||||||
/(\d{1,2})\/(\d{1,2})\/(\d{4}), (\d{1,2}):(\d{1,2}):(\d{1,2})/gm;
|
|
||||||
cy.getByTestId(tradesTable)
|
cy.getByTestId(tradesTable)
|
||||||
.get(`.ag-center-cols-container ${colIdCreatedAt}`)
|
.get(`.ag-center-cols-container ${colIdCreatedAt}`)
|
||||||
.each(($tradeDateTime) => {
|
.each(($tradeDateTime) => {
|
||||||
@@ -87,6 +86,7 @@ describe('trades', { tags: '@smoke' }, () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('copy price to deal ticket form', () => {
|
it('copy price to deal ticket form', () => {
|
||||||
|
cy.getByTestId('Order').click();
|
||||||
// 6005-THIS-007
|
// 6005-THIS-007
|
||||||
cy.get(colIdPrice).last().should('be.visible').click();
|
cy.get(colIdPrice).last().should('be.visible').click();
|
||||||
cy.getByTestId('order-price').should('have.value', '171.16898');
|
cy.getByTestId('order-price').should('have.value', '171.16898');
|
||||||
|
|||||||
@@ -5,118 +5,8 @@ import {
|
|||||||
|
|
||||||
const connectVegaBtn = 'connect-vega-wallet';
|
const connectVegaBtn = 'connect-vega-wallet';
|
||||||
const manageVegaBtn = 'manage-vega-wallet';
|
const manageVegaBtn = 'manage-vega-wallet';
|
||||||
const form = 'rest-connector-form';
|
|
||||||
const dialogContent = 'dialog-content';
|
const dialogContent = 'dialog-content';
|
||||||
|
|
||||||
describe(
|
|
||||||
'connect hosted wallet',
|
|
||||||
{ tags: '@smoke', testIsolation: true },
|
|
||||||
() => {
|
|
||||||
beforeEach(() => {
|
|
||||||
// Using portfolio page as it requires vega wallet connection
|
|
||||||
cy.visit('/#/portfolio');
|
|
||||||
cy.mockTradingPage();
|
|
||||||
cy.mockSubscription();
|
|
||||||
cy.setOnBoardingViewed();
|
|
||||||
cy.get('[data-testid="pathname-/portfolio"]').should('exist');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can connect', () => {
|
|
||||||
// 0002-WCON-002
|
|
||||||
// 0002-WCON-003
|
|
||||||
// 0002-WCON-039
|
|
||||||
// 0002-WCON-017
|
|
||||||
// 0002-WCON-018
|
|
||||||
// 0002-WCON-019
|
|
||||||
|
|
||||||
// Mock authentication
|
|
||||||
cy.intercept(
|
|
||||||
'POST',
|
|
||||||
'https://wallet.testnet.vega.xyz/api/v1/auth/token',
|
|
||||||
{
|
|
||||||
body: {
|
|
||||||
token: 'test-token',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
// Mock getting keys from wallet
|
|
||||||
cy.intercept('GET', 'https://wallet.testnet.vega.xyz/api/v1/keys', {
|
|
||||||
body: {
|
|
||||||
keys: [
|
|
||||||
{
|
|
||||||
algorithm: {
|
|
||||||
name: 'algo',
|
|
||||||
version: 1,
|
|
||||||
},
|
|
||||||
index: 0,
|
|
||||||
meta: [],
|
|
||||||
pub: 'HOSTED_PUBKEY',
|
|
||||||
tainted: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
cy.getByTestId(connectVegaBtn).click();
|
|
||||||
cy.contains(
|
|
||||||
'Choose wallet app to connect, or to change port or server URL enter a custom wallet location first'
|
|
||||||
);
|
|
||||||
cy.contains('Connect Vega wallet');
|
|
||||||
cy.contains('Hosted Fairground wallet');
|
|
||||||
|
|
||||||
cy.getByTestId('connectors-list')
|
|
||||||
.find('[data-testid="connector-rest"]')
|
|
||||||
.click();
|
|
||||||
cy.getByTestId(form).find('#wallet').click().type('user');
|
|
||||||
cy.getByTestId(form).find('#passphrase').click().type('pass');
|
|
||||||
cy.getByTestId('rest-connector-form').find('button[type=submit]').click();
|
|
||||||
cy.getByTestId(manageVegaBtn).should('exist');
|
|
||||||
cy.getByTestId('manage-vega-wallet').click();
|
|
||||||
cy.getByTestId('keypair-list').should('exist');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('doesnt connect with invalid credentials', () => {
|
|
||||||
// 0002-WCON-020
|
|
||||||
|
|
||||||
// Mock incorrect username/password
|
|
||||||
cy.intercept(
|
|
||||||
'POST',
|
|
||||||
'https://wallet.testnet.vega.xyz/api/v1/auth/token',
|
|
||||||
{
|
|
||||||
body: {
|
|
||||||
error: 'No wallet',
|
|
||||||
},
|
|
||||||
statusCode: 403, // 403 forbidden invalid crednetials
|
|
||||||
}
|
|
||||||
);
|
|
||||||
cy.getByTestId(connectVegaBtn).click();
|
|
||||||
cy.getByTestId('connectors-list')
|
|
||||||
.find('[data-testid="connector-rest"]')
|
|
||||||
.click();
|
|
||||||
cy.getByTestId(form).find('#wallet').click().type('invalid name');
|
|
||||||
cy.getByTestId(form).find('#passphrase').click().type('invalid password');
|
|
||||||
cy.getByTestId('rest-connector-form').find('button[type=submit]').click();
|
|
||||||
cy.getByTestId('form-error').should('have.text', 'Invalid credentials');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('doesnt connect with empty fields', () => {
|
|
||||||
cy.getByTestId(connectVegaBtn).click();
|
|
||||||
cy.getByTestId('connectors-list')
|
|
||||||
.find('[data-testid="connector-rest"]')
|
|
||||||
.click();
|
|
||||||
|
|
||||||
cy.getByTestId('rest-connector-form').find('button[type=submit]').click();
|
|
||||||
cy.getByTestId(form)
|
|
||||||
.find('#wallet')
|
|
||||||
.next('[data-testid="input-error-text"]')
|
|
||||||
.should('have.text', 'Required');
|
|
||||||
cy.getByTestId(form)
|
|
||||||
.find('#passphrase')
|
|
||||||
.next('[data-testid="input-error-text"]')
|
|
||||||
.should('have.text', 'Required');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
describe('connect vega wallet', { tags: '@smoke', testIsolation: true }, () => {
|
describe('connect vega wallet', { tags: '@smoke', testIsolation: true }, () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
// Using portfolio page as it requires vega wallet connection
|
// Using portfolio page as it requires vega wallet connection
|
||||||
@@ -196,8 +86,6 @@ describe('connect vega wallet', { tags: '@smoke', testIsolation: true }, () => {
|
|||||||
cy.getByTestId('connect-vega-wallet').should('exist');
|
cy.getByTestId('connect-vega-wallet').should('exist');
|
||||||
cy.getByTestId('manage-vega-wallet').should('not.exist');
|
cy.getByTestId('manage-vega-wallet').should('not.exist');
|
||||||
cy.getByTestId('connect-vega-wallet').click();
|
cy.getByTestId('connect-vega-wallet').click();
|
||||||
cy.contains(
|
cy.contains('Enter a custom wallet location');
|
||||||
'Choose wallet app to connect, or to change port or server URL enter a custom wallet location first'
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
+2
-1
@@ -1,4 +1,3 @@
|
|||||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
|
||||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||||
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
||||||
@@ -13,6 +12,8 @@ NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
|||||||
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
|
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
|
||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/main/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/main/announcements.json
|
||||||
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||||
|
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||||
|
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/pl/firefox/addon/vega-wallet
|
||||||
|
|
||||||
# Cosmic elevator flags
|
# Cosmic elevator flags
|
||||||
NX_SUCCESSOR_MARKETS=true
|
NX_SUCCESSOR_MARKETS=true
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
@@ -0,0 +1 @@
|
|||||||
|
window._env_ = {};
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 547 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"short_name": "Mainnet Stats",
|
||||||
|
"name": "Vega Mainnet statistics",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "favicon.ico",
|
||||||
|
"sizes": "64x64 32x32 24x24 16x16",
|
||||||
|
"type": "image/x-icon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "logo192.png",
|
||||||
|
"type": "image/png",
|
||||||
|
"sizes": "192x192"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"start_url": ".",
|
||||||
|
"display": "standalone",
|
||||||
|
"theme_color": "#000000",
|
||||||
|
"background_color": "#ffffff"
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# https://www.robotstxt.org/robotstxt.html
|
||||||
|
User-agent: *
|
||||||
|
Disallow:
|
||||||
@@ -10,7 +10,6 @@ import { TradeGrid } from './trade-grid';
|
|||||||
import { TradePanels } from './trade-panels';
|
import { TradePanels } from './trade-panels';
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
import { Links, Routes } from '../../pages/client-router';
|
import { Links, Routes } from '../../pages/client-router';
|
||||||
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
|
|
||||||
import { ViewType, useSidebar } from '../../components/sidebar';
|
import { ViewType, useSidebar } from '../../components/sidebar';
|
||||||
|
|
||||||
const calculatePrice = (markPrice?: string, decimalPlaces?: number) => {
|
const calculatePrice = (markPrice?: string, decimalPlaces?: number) => {
|
||||||
@@ -65,8 +64,6 @@ export const MarketPage = () => {
|
|||||||
const update = useGlobalStore((store) => store.update);
|
const update = useGlobalStore((store) => store.update);
|
||||||
const lastMarketId = useGlobalStore((store) => store.marketId);
|
const lastMarketId = useGlobalStore((store) => store.marketId);
|
||||||
|
|
||||||
const onSelect = useMarketClickHandler();
|
|
||||||
|
|
||||||
const { data, error, loading } = useMarket(marketId);
|
const { data, error, loading } = useMarket(marketId);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -87,7 +84,6 @@ export const MarketPage = () => {
|
|||||||
return (
|
return (
|
||||||
<TradeGrid
|
<TradeGrid
|
||||||
market={data}
|
market={data}
|
||||||
onSelect={onSelect}
|
|
||||||
pinnedAsset={
|
pinnedAsset={
|
||||||
data?.tradableInstrument.instrument.product.settlementAsset
|
data?.tradableInstrument.instrument.product.settlementAsset
|
||||||
}
|
}
|
||||||
@@ -97,11 +93,12 @@ export const MarketPage = () => {
|
|||||||
return (
|
return (
|
||||||
<TradePanels
|
<TradePanels
|
||||||
market={data}
|
market={data}
|
||||||
onSelect={onSelect}
|
pinnedAsset={
|
||||||
onClickCollateral={() => navigate('/portfolio')}
|
data?.tradableInstrument.instrument.product.settlementAsset
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}, [largeScreen, data, onSelect, navigate]);
|
}, [largeScreen, data]);
|
||||||
|
|
||||||
if (!data && marketId) {
|
if (!data && marketId) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import { OracleBanner } from '@vegaprotocol/markets';
|
|||||||
import type { Market } from '@vegaprotocol/markets';
|
import type { Market } from '@vegaprotocol/markets';
|
||||||
import { Filter } from '@vegaprotocol/orders';
|
import { Filter } from '@vegaprotocol/orders';
|
||||||
import { Tab, LocalStoragePersistTabs as Tabs } from '@vegaprotocol/ui-toolkit';
|
import { Tab, LocalStoragePersistTabs as Tabs } from '@vegaprotocol/ui-toolkit';
|
||||||
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
|
|
||||||
import {
|
import {
|
||||||
ResizableGrid,
|
ResizableGrid,
|
||||||
ResizableGridPanel,
|
ResizableGridPanel,
|
||||||
@@ -24,7 +23,6 @@ import { FLAGS } from '@vegaprotocol/environment';
|
|||||||
|
|
||||||
interface TradeGridProps {
|
interface TradeGridProps {
|
||||||
market: Market | null;
|
market: Market | null;
|
||||||
onSelect: (marketId: string, metaKey?: boolean) => void;
|
|
||||||
pinnedAsset?: PinnedAsset;
|
pinnedAsset?: PinnedAsset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,7 +38,6 @@ const MainGrid = memo(
|
|||||||
const [sizesMiddle, handleOnMiddleLayoutChange] = usePaneLayout({
|
const [sizesMiddle, handleOnMiddleLayoutChange] = usePaneLayout({
|
||||||
id: 'middle-1',
|
id: 'middle-1',
|
||||||
});
|
});
|
||||||
const onMarketClick = useMarketClickHandler(true);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ResizableGrid vertical onChange={handleOnLayoutChange}>
|
<ResizableGrid vertical onChange={handleOnLayoutChange}>
|
||||||
@@ -98,30 +95,27 @@ const MainGrid = memo(
|
|||||||
<TradeGridChild>
|
<TradeGridChild>
|
||||||
<Tabs storageKey="console-trade-grid-bottom">
|
<Tabs storageKey="console-trade-grid-bottom">
|
||||||
<Tab id="positions" name={t('Positions')}>
|
<Tab id="positions" name={t('Positions')}>
|
||||||
<TradingViews.positions.component
|
<TradingViews.positions.component />
|
||||||
onMarketClick={onMarketClick}
|
|
||||||
/>
|
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab id="open-orders" name={t('Open')}>
|
<Tab
|
||||||
<TradingViews.orders.component
|
id="open-orders"
|
||||||
marketId={marketId}
|
name={t('Open')}
|
||||||
filter={Filter.Open}
|
menu={<TradingViews.activeOrders.menu marketId={marketId} />}
|
||||||
/>
|
>
|
||||||
|
<TradingViews.orders.component filter={Filter.Open} />
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab id="closed-orders" name={t('Closed')}>
|
<Tab id="closed-orders" name={t('Closed')}>
|
||||||
<TradingViews.orders.component
|
<TradingViews.orders.component filter={Filter.Closed} />
|
||||||
marketId={marketId}
|
|
||||||
filter={Filter.Closed}
|
|
||||||
/>
|
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab id="rejected-orders" name={t('Rejected')}>
|
<Tab id="rejected-orders" name={t('Rejected')}>
|
||||||
<TradingViews.orders.component
|
<TradingViews.orders.component filter={Filter.Rejected} />
|
||||||
marketId={marketId}
|
|
||||||
filter={Filter.Rejected}
|
|
||||||
/>
|
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab id="orders" name={t('All')}>
|
<Tab
|
||||||
<TradingViews.orders.component marketId={marketId} />
|
id="orders"
|
||||||
|
name={t('All')}
|
||||||
|
menu={<TradingViews.orders.menu marketId={marketId} />}
|
||||||
|
>
|
||||||
|
<TradingViews.orders.component />
|
||||||
</Tab>
|
</Tab>
|
||||||
{FLAGS.STOP_ORDERS ? (
|
{FLAGS.STOP_ORDERS ? (
|
||||||
<Tab id="stop-orders" name={t('Stop orders')}>
|
<Tab id="stop-orders" name={t('Stop orders')}>
|
||||||
@@ -129,17 +123,14 @@ const MainGrid = memo(
|
|||||||
</Tab>
|
</Tab>
|
||||||
) : null}
|
) : null}
|
||||||
<Tab id="fills" name={t('Fills')}>
|
<Tab id="fills" name={t('Fills')}>
|
||||||
<TradingViews.fills.component
|
<TradingViews.fills.component marketId={marketId} />
|
||||||
marketId={marketId}
|
|
||||||
onMarketClick={onMarketClick}
|
|
||||||
/>
|
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab id="accounts" name={t('Collateral')}>
|
<Tab
|
||||||
<TradingViews.collateral.component
|
id="accounts"
|
||||||
pinnedAsset={pinnedAsset}
|
name={t('Collateral')}
|
||||||
onMarketClick={onMarketClick}
|
menu={<TradingViews.collateral.menu />}
|
||||||
hideButtons
|
>
|
||||||
/>
|
<TradingViews.collateral.component pinnedAsset={pinnedAsset} />
|
||||||
</Tab>
|
</Tab>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</TradeGridChild>
|
</TradeGridChild>
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
import type { PinnedAsset } from '@vegaprotocol/accounts';
|
import type { PinnedAsset } from '@vegaprotocol/accounts';
|
||||||
import type { Market } from '@vegaprotocol/markets';
|
import type { Market } from '@vegaprotocol/markets';
|
||||||
import { OracleBanner } from '@vegaprotocol/markets';
|
import { OracleBanner } from '@vegaprotocol/markets';
|
||||||
import {
|
|
||||||
useMarketClickHandler,
|
|
||||||
useMarketLiquidityClickHandler,
|
|
||||||
} from '../../lib/hooks/use-market-click-handler';
|
|
||||||
import type { TradingView } from './trade-views';
|
import type { TradingView } from './trade-views';
|
||||||
import { TradingViews } from './trade-views';
|
import { TradingViews } from './trade-views';
|
||||||
import { memo, useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Splash } from '@vegaprotocol/ui-toolkit';
|
import { Splash } from '@vegaprotocol/ui-toolkit';
|
||||||
import { NO_MARKET } from './constants';
|
import { NO_MARKET } from './constants';
|
||||||
import AutoSizer from 'react-virtualized-auto-sizer';
|
import AutoSizer from 'react-virtualized-auto-sizer';
|
||||||
@@ -20,33 +16,14 @@ import { FLAGS } from '@vegaprotocol/environment';
|
|||||||
|
|
||||||
interface TradePanelsProps {
|
interface TradePanelsProps {
|
||||||
market: Market | null;
|
market: Market | null;
|
||||||
onSelect: (marketId: string, metaKey?: boolean) => void;
|
|
||||||
onMarketClick?: (marketId: string) => void;
|
|
||||||
onOrderTypeClick?: (marketId: string) => void;
|
|
||||||
onClickCollateral: () => void;
|
|
||||||
pinnedAsset?: PinnedAsset;
|
pinnedAsset?: PinnedAsset;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TradePanels = ({
|
export const TradePanels = ({ market, pinnedAsset }: TradePanelsProps) => {
|
||||||
market,
|
|
||||||
onSelect,
|
|
||||||
onClickCollateral,
|
|
||||||
pinnedAsset,
|
|
||||||
}: TradePanelsProps) => {
|
|
||||||
const onMarketClick = useMarketClickHandler(true);
|
|
||||||
const onOrderTypeClick = useMarketLiquidityClickHandler();
|
|
||||||
|
|
||||||
const [view, setView] = useState<TradingView>('candles');
|
const [view, setView] = useState<TradingView>('candles');
|
||||||
|
|
||||||
const renderView = () => {
|
const renderView = () => {
|
||||||
const Component = memo<{
|
const Component = TradingViews[view].component;
|
||||||
marketId: string;
|
|
||||||
onSelect: (marketId: string, metaKey?: boolean) => void;
|
|
||||||
onMarketClick?: (marketId: string) => void;
|
|
||||||
onOrderTypeClick?: (marketId: string) => void;
|
|
||||||
onClickCollateral: () => void;
|
|
||||||
pinnedAsset?: PinnedAsset;
|
|
||||||
}>(TradingViews[view].component);
|
|
||||||
|
|
||||||
if (!Component) {
|
if (!Component) {
|
||||||
throw new Error(`No component for view: ${view}`);
|
throw new Error(`No component for view: ${view}`);
|
||||||
@@ -54,16 +31,7 @@ export const TradePanels = ({
|
|||||||
|
|
||||||
if (!market) return <Splash>{NO_MARKET}</Splash>;
|
if (!market) return <Splash>{NO_MARKET}</Splash>;
|
||||||
|
|
||||||
return (
|
return <Component marketId={market?.id} pinnedAsset={pinnedAsset} />;
|
||||||
<Component
|
|
||||||
marketId={market?.id}
|
|
||||||
onSelect={onSelect}
|
|
||||||
onClickCollateral={onClickCollateral}
|
|
||||||
pinnedAsset={pinnedAsset}
|
|
||||||
onMarketClick={onMarketClick}
|
|
||||||
onOrderTypeClick={onOrderTypeClick}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderMenu = () => {
|
const renderMenu = () => {
|
||||||
@@ -71,9 +39,10 @@ export const TradePanels = ({
|
|||||||
|
|
||||||
if ('menu' in viewCfg) {
|
if ('menu' in viewCfg) {
|
||||||
const Menu = viewCfg.menu;
|
const Menu = viewCfg.menu;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex gap-1 p-1 bg-vega-clight-800 dark:bg-vega-cdark-800 border-b border-default">
|
<div className="flex gap-1 p-1 bg-vega-clight-800 dark:bg-vega-cdark-800 border-b border-default">
|
||||||
<Menu />
|
<Menu marketId={market?.id || ''} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import type { ComponentProps } from 'react';
|
import type { ComponentProps } from 'react';
|
||||||
import { Splash } from '@vegaprotocol/ui-toolkit';
|
import { Splash } from '@vegaprotocol/ui-toolkit';
|
||||||
import { TradesContainer } from '@vegaprotocol/trades';
|
|
||||||
import { DepthChartContainer } from '@vegaprotocol/market-depth';
|
import { DepthChartContainer } from '@vegaprotocol/market-depth';
|
||||||
import {
|
import {
|
||||||
CandlesChartContainer,
|
CandlesChartContainer,
|
||||||
CandlesMenu,
|
CandlesMenu,
|
||||||
} from '@vegaprotocol/candles-chart';
|
} from '@vegaprotocol/candles-chart';
|
||||||
import { Filter } from '@vegaprotocol/orders';
|
import { Filter, OpenOrdersMenu } from '@vegaprotocol/orders';
|
||||||
import { NO_MARKET } from './constants';
|
import { NO_MARKET } from './constants';
|
||||||
|
import { TradesContainer } from '../../components/trades-container';
|
||||||
import { OrderbookContainer } from '../../components/orderbook-container';
|
import { OrderbookContainer } from '../../components/orderbook-container';
|
||||||
import { FillsContainer } from '../../components/fills-container';
|
import { FillsContainer } from '../../components/fills-container';
|
||||||
import { PositionsContainer } from '../../components/positions-container';
|
import { PositionsContainer } from '../../components/positions-container';
|
||||||
@@ -16,6 +16,7 @@ import { LiquidityContainer } from '../../components/liquidity-container';
|
|||||||
import type { OrderContainerProps } from '../../components/orders-container';
|
import type { OrderContainerProps } from '../../components/orders-container';
|
||||||
import { OrdersContainer } from '../../components/orders-container';
|
import { OrdersContainer } from '../../components/orders-container';
|
||||||
import { StopOrdersContainer } from '../../components/stop-orders-container';
|
import { StopOrdersContainer } from '../../components/stop-orders-container';
|
||||||
|
import { AccountsMenu } from '../../components/accounts-menu';
|
||||||
|
|
||||||
type MarketDependantView =
|
type MarketDependantView =
|
||||||
| typeof CandlesChartContainer
|
| typeof CandlesChartContainer
|
||||||
@@ -62,6 +63,7 @@ export const TradingViews = {
|
|||||||
component: (props: OrderContainerProps) => (
|
component: (props: OrderContainerProps) => (
|
||||||
<OrdersContainer {...props} filter={Filter.Open} />
|
<OrdersContainer {...props} filter={Filter.Open} />
|
||||||
),
|
),
|
||||||
|
menu: OpenOrdersMenu,
|
||||||
},
|
},
|
||||||
closedOrders: {
|
closedOrders: {
|
||||||
label: 'Closed',
|
label: 'Closed',
|
||||||
@@ -78,11 +80,16 @@ export const TradingViews = {
|
|||||||
orders: {
|
orders: {
|
||||||
label: 'All',
|
label: 'All',
|
||||||
component: OrdersContainer,
|
component: OrdersContainer,
|
||||||
|
menu: OpenOrdersMenu,
|
||||||
},
|
},
|
||||||
stopOrders: {
|
stopOrders: {
|
||||||
label: 'Stop',
|
label: 'Stop',
|
||||||
component: StopOrdersContainer,
|
component: StopOrdersContainer,
|
||||||
},
|
},
|
||||||
collateral: { label: 'Collateral', component: AccountsContainer },
|
collateral: {
|
||||||
|
label: 'Collateral',
|
||||||
|
component: AccountsContainer,
|
||||||
|
menu: AccountsMenu,
|
||||||
|
},
|
||||||
fills: { label: 'Fills', component: FillsContainer },
|
fills: { label: 'Fills', component: FillsContainer },
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -411,24 +411,26 @@ describe('Closed', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
render(
|
await act(() => {
|
||||||
<MemoryRouter>
|
render(
|
||||||
<MockedProvider
|
<MemoryRouter>
|
||||||
mocks={[
|
<MockedProvider
|
||||||
mixedMarketsMock,
|
mocks={[
|
||||||
marketsDataMock,
|
mixedMarketsMock,
|
||||||
oracleDataMock,
|
marketsDataMock,
|
||||||
successorMarketsMock,
|
oracleDataMock,
|
||||||
]}
|
successorMarketsMock,
|
||||||
>
|
]}
|
||||||
<VegaWalletContext.Provider
|
|
||||||
value={{ pubKey } as VegaWalletContextShape}
|
|
||||||
>
|
>
|
||||||
<Closed />
|
<VegaWalletContext.Provider
|
||||||
</VegaWalletContext.Provider>
|
value={{ pubKey } as VegaWalletContextShape}
|
||||||
</MockedProvider>
|
>
|
||||||
</MemoryRouter>
|
<Closed />
|
||||||
);
|
</VegaWalletContext.Provider>
|
||||||
|
</MockedProvider>
|
||||||
|
</MemoryRouter>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(
|
expect(
|
||||||
|
|||||||
@@ -276,15 +276,9 @@ const ClosedMarketsDataGrid = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<AgGrid
|
<AgGrid
|
||||||
style={{ width: '100%', height: '100%' }}
|
|
||||||
rowData={rowData}
|
rowData={rowData}
|
||||||
columnDefs={colDefs}
|
columnDefs={colDefs}
|
||||||
getRowId={({ data }) => data.id}
|
getRowId={({ data }) => data.id}
|
||||||
defaultColDef={{
|
|
||||||
resizable: true,
|
|
||||||
minWidth: 100,
|
|
||||||
flex: 1,
|
|
||||||
}}
|
|
||||||
components={{ SuccessorMarketRenderer }}
|
components={{ SuccessorMarketRenderer }}
|
||||||
overlayNoRowsTemplate={error ? error.message : t('No markets')}
|
overlayNoRowsTemplate={error ? error.message : t('No markets')}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
import { Button, Splash } from '@vegaprotocol/ui-toolkit';
|
|
||||||
import { DepositsTable } from '@vegaprotocol/deposits';
|
|
||||||
import { depositsProvider } from '@vegaprotocol/deposits';
|
|
||||||
import { t } from '@vegaprotocol/i18n';
|
|
||||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
|
||||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
|
||||||
import { useSidebar, ViewType } from '../../components/sidebar';
|
|
||||||
|
|
||||||
export const DepositsContainer = () => {
|
|
||||||
const { pubKey, isReadOnly } = useVegaWallet();
|
|
||||||
const { data, error } = useDataProvider({
|
|
||||||
dataProvider: depositsProvider,
|
|
||||||
variables: { partyId: pubKey || '' },
|
|
||||||
skip: !pubKey,
|
|
||||||
});
|
|
||||||
const setView = useSidebar((store) => store.setView);
|
|
||||||
if (!pubKey) {
|
|
||||||
return <Splash>{t('Please connect Vega wallet')}</Splash>;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div className="h-full">
|
|
||||||
<DepositsTable
|
|
||||||
rowData={data}
|
|
||||||
overlayNoRowsTemplate={error ? error.message : t('No deposits')}
|
|
||||||
/>
|
|
||||||
{!isReadOnly && (
|
|
||||||
<div className="h-auto flex justify-end p-2 bottom-0 right-0 absolute dark:bg-black/75 bg-white/75 rounded">
|
|
||||||
<Button
|
|
||||||
variant="primary"
|
|
||||||
size="sm"
|
|
||||||
onClick={() => setView({ type: ViewType.Deposit })}
|
|
||||||
data-testid="deposit-button"
|
|
||||||
>
|
|
||||||
{t('Deposit')}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -6,12 +6,11 @@ import { t } from '@vegaprotocol/i18n';
|
|||||||
import { useIncompleteWithdrawals } from '@vegaprotocol/withdraws';
|
import { useIncompleteWithdrawals } from '@vegaprotocol/withdraws';
|
||||||
import { Tab, LocalStoragePersistTabs as Tabs } from '@vegaprotocol/ui-toolkit';
|
import { Tab, LocalStoragePersistTabs as Tabs } from '@vegaprotocol/ui-toolkit';
|
||||||
import { usePageTitleStore } from '../../stores';
|
import { usePageTitleStore } from '../../stores';
|
||||||
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
|
|
||||||
import { AccountsContainer } from '../../components/accounts-container';
|
import { AccountsContainer } from '../../components/accounts-container';
|
||||||
import { DepositsContainer } from './deposits-container';
|
import { DepositsContainer } from '../../components/deposits-container';
|
||||||
import { FillsContainer } from '../../components/fills-container';
|
import { FillsContainer } from '../../components/fills-container';
|
||||||
import { PositionsContainer } from '../../components/positions-container';
|
import { PositionsContainer } from '../../components/positions-container';
|
||||||
import { WithdrawalsContainer } from './withdrawals-container';
|
import { WithdrawalsContainer } from '../../components/withdrawals-container';
|
||||||
import { OrdersContainer } from '../../components/orders-container';
|
import { OrdersContainer } from '../../components/orders-container';
|
||||||
import { LedgerContainer } from '../../components/ledger-container';
|
import { LedgerContainer } from '../../components/ledger-container';
|
||||||
import { AccountHistoryContainer } from './account-history-container';
|
import { AccountHistoryContainer } from './account-history-container';
|
||||||
@@ -21,6 +20,9 @@ import {
|
|||||||
usePaneLayout,
|
usePaneLayout,
|
||||||
} from '../../components/resizable-grid';
|
} from '../../components/resizable-grid';
|
||||||
import { ViewType, useSidebar } from '../../components/sidebar';
|
import { ViewType, useSidebar } from '../../components/sidebar';
|
||||||
|
import { AccountsMenu } from '../../components/accounts-menu';
|
||||||
|
import { DepositsMenu } from '../../components/deposits-menu';
|
||||||
|
import { WithdrawalsMenu } from '../../components/withdrawals-menu';
|
||||||
|
|
||||||
const WithdrawalsIndicator = () => {
|
const WithdrawalsIndicator = () => {
|
||||||
const { ready } = useIncompleteWithdrawals();
|
const { ready } = useIncompleteWithdrawals();
|
||||||
@@ -51,7 +53,6 @@ export const Portfolio = () => {
|
|||||||
}
|
}
|
||||||
}, [init, view, setView]);
|
}, [init, view, setView]);
|
||||||
|
|
||||||
const onMarketClick = useMarketClickHandler(true);
|
|
||||||
const [sizes, handleOnLayoutChange] = usePaneLayout({ id: 'portfolio' });
|
const [sizes, handleOnLayoutChange] = usePaneLayout({ id: 'portfolio' });
|
||||||
const wrapperClasses = 'p-0.5 h-full max-h-full flex flex-col';
|
const wrapperClasses = 'p-0.5 h-full max-h-full flex flex-col';
|
||||||
return (
|
return (
|
||||||
@@ -64,13 +65,13 @@ export const Portfolio = () => {
|
|||||||
<AccountHistoryContainer />
|
<AccountHistoryContainer />
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab id="positions" name={t('Positions')}>
|
<Tab id="positions" name={t('Positions')}>
|
||||||
<PositionsContainer onMarketClick={onMarketClick} allKeys />
|
<PositionsContainer allKeys />
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab id="orders" name={t('Orders')}>
|
<Tab id="orders" name={t('Orders')}>
|
||||||
<OrdersContainer />
|
<OrdersContainer />
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab id="fills" name={t('Fills')}>
|
<Tab id="fills" name={t('Fills')}>
|
||||||
<FillsContainer onMarketClick={onMarketClick} />
|
<FillsContainer />
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab id="ledger-entries" name={t('Ledger entries')}>
|
<Tab id="ledger-entries" name={t('Ledger entries')}>
|
||||||
<LedgerContainer />
|
<LedgerContainer />
|
||||||
@@ -85,16 +86,21 @@ export const Portfolio = () => {
|
|||||||
>
|
>
|
||||||
<PortfolioGridChild>
|
<PortfolioGridChild>
|
||||||
<Tabs storageKey="console-portfolio-bottom">
|
<Tabs storageKey="console-portfolio-bottom">
|
||||||
<Tab id="collateral" name={t('Collateral')}>
|
<Tab
|
||||||
|
id="collateral"
|
||||||
|
name={t('Collateral')}
|
||||||
|
menu={<AccountsMenu />}
|
||||||
|
>
|
||||||
<AccountsContainer />
|
<AccountsContainer />
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab id="deposits" name={t('Deposits')}>
|
<Tab id="deposits" name={t('Deposits')} menu={<DepositsMenu />}>
|
||||||
<DepositsContainer />
|
<DepositsContainer />
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab
|
<Tab
|
||||||
id="withdrawals"
|
id="withdrawals"
|
||||||
name={t('Withdrawals')}
|
name={t('Withdrawals')}
|
||||||
indicator={<WithdrawalsIndicator />}
|
indicator={<WithdrawalsIndicator />}
|
||||||
|
menu={<WithdrawalsMenu />}
|
||||||
>
|
>
|
||||||
<WithdrawalsContainer />
|
<WithdrawalsContainer />
|
||||||
</Tab>
|
</Tab>
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
import { Button, Splash } from '@vegaprotocol/ui-toolkit';
|
|
||||||
import {
|
|
||||||
withdrawalProvider,
|
|
||||||
WithdrawalsTable,
|
|
||||||
useIncompleteWithdrawals,
|
|
||||||
} from '@vegaprotocol/withdraws';
|
|
||||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
|
||||||
import { t } from '@vegaprotocol/i18n';
|
|
||||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
|
||||||
import { ViewType, useSidebar } from '../../components/sidebar';
|
|
||||||
|
|
||||||
export const WithdrawalsContainer = () => {
|
|
||||||
const { pubKey, isReadOnly } = useVegaWallet();
|
|
||||||
const { data, error } = useDataProvider({
|
|
||||||
dataProvider: withdrawalProvider,
|
|
||||||
variables: { partyId: pubKey || '' },
|
|
||||||
skip: !pubKey,
|
|
||||||
});
|
|
||||||
const setView = useSidebar((store) => store.setView);
|
|
||||||
const { ready, delayed } = useIncompleteWithdrawals();
|
|
||||||
if (!pubKey) {
|
|
||||||
return <Splash>{t('Please connect Vega wallet')}</Splash>;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="h-full relative">
|
|
||||||
<WithdrawalsTable
|
|
||||||
data-testid="withdrawals-history"
|
|
||||||
rowData={data}
|
|
||||||
overlayNoRowsTemplate={error ? error.message : t('No withdrawals')}
|
|
||||||
ready={ready}
|
|
||||||
delayed={delayed}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{!isReadOnly && (
|
|
||||||
<div className="h-auto flex justify-end p-2 bottom-0 right-0 absolute dark:bg-black/75 bg-white/75 rounded">
|
|
||||||
<Button
|
|
||||||
variant="primary"
|
|
||||||
size="sm"
|
|
||||||
onClick={() => setView({ type: ViewType.Withdraw })}
|
|
||||||
data-testid="withdraw-dialog-button"
|
|
||||||
>
|
|
||||||
{t('Make withdrawal')}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { Button } from '@vegaprotocol/ui-toolkit';
|
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import { Splash } from '@vegaprotocol/ui-toolkit';
|
import { Splash } from '@vegaprotocol/ui-toolkit';
|
||||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||||
@@ -12,16 +11,14 @@ import { useDataGridEvents } from '@vegaprotocol/datagrid';
|
|||||||
import type { DataGridSlice } from '../../stores/datagrid-store-slice';
|
import type { DataGridSlice } from '../../stores/datagrid-store-slice';
|
||||||
import { createDataGridSlice } from '../../stores/datagrid-store-slice';
|
import { createDataGridSlice } from '../../stores/datagrid-store-slice';
|
||||||
import { ViewType, useSidebar } from '../sidebar';
|
import { ViewType, useSidebar } from '../sidebar';
|
||||||
|
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
|
||||||
|
|
||||||
export const AccountsContainer = ({
|
export const AccountsContainer = ({
|
||||||
pinnedAsset,
|
pinnedAsset,
|
||||||
hideButtons,
|
|
||||||
onMarketClick,
|
|
||||||
}: {
|
}: {
|
||||||
pinnedAsset?: PinnedAsset;
|
pinnedAsset?: PinnedAsset;
|
||||||
hideButtons?: boolean;
|
|
||||||
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
|
|
||||||
}) => {
|
}) => {
|
||||||
|
const onMarketClick = useMarketClickHandler(true);
|
||||||
const { pubKey, isReadOnly } = useVegaWallet();
|
const { pubKey, isReadOnly } = useVegaWallet();
|
||||||
const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore();
|
const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore();
|
||||||
const setView = useSidebar((store) => store.setView);
|
const setView = useSidebar((store) => store.setView);
|
||||||
@@ -48,44 +45,23 @@ export const AccountsContainer = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full relative">
|
<AccountManager
|
||||||
<AccountManager
|
partyId={pubKey}
|
||||||
partyId={pubKey}
|
onClickAsset={onClickAsset}
|
||||||
onClickAsset={onClickAsset}
|
onClickWithdraw={(assetId) => {
|
||||||
onClickWithdraw={(assetId) => {
|
setView({ type: ViewType.Withdraw, assetId });
|
||||||
setView({ type: ViewType.Withdraw, assetId });
|
}}
|
||||||
}}
|
onClickDeposit={(assetId) => {
|
||||||
onClickDeposit={(assetId) => {
|
setView({ type: ViewType.Deposit, assetId });
|
||||||
setView({ type: ViewType.Deposit, assetId });
|
}}
|
||||||
}}
|
onClickTransfer={(assetId) => {
|
||||||
onClickTransfer={(assetId) => {
|
setView({ type: ViewType.Transfer, assetId });
|
||||||
setView({ type: ViewType.Transfer, assetId });
|
}}
|
||||||
}}
|
onMarketClick={onMarketClick}
|
||||||
onMarketClick={onMarketClick}
|
isReadOnly={isReadOnly}
|
||||||
isReadOnly={isReadOnly}
|
pinnedAsset={pinnedAsset}
|
||||||
pinnedAsset={pinnedAsset}
|
gridProps={gridStoreCallbacks}
|
||||||
gridProps={gridStoreCallbacks}
|
/>
|
||||||
/>
|
|
||||||
{!isReadOnly && !hideButtons && (
|
|
||||||
<div className="flex gap-2 justify-end p-2 absolute bottom-0 right-0 dark:bg-black/75 bg-white/75 rounded">
|
|
||||||
<Button
|
|
||||||
variant="primary"
|
|
||||||
size="sm"
|
|
||||||
data-testid="open-transfer"
|
|
||||||
onClick={() => setView({ type: ViewType.Transfer })}
|
|
||||||
>
|
|
||||||
{t('Transfer')}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="primary"
|
|
||||||
size="sm"
|
|
||||||
onClick={() => setView({ type: ViewType.Deposit })}
|
|
||||||
>
|
|
||||||
{t('Deposit')}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { t } from '@vegaprotocol/i18n';
|
||||||
|
import { Intent, TradingButton } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { ViewType, useSidebar } from '../sidebar';
|
||||||
|
|
||||||
|
export const AccountsMenu = () => {
|
||||||
|
const setView = useSidebar((store) => store.setView);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<TradingButton
|
||||||
|
intent={Intent.Primary}
|
||||||
|
size="extra-small"
|
||||||
|
data-testid="open-transfer"
|
||||||
|
onClick={() => setView({ type: ViewType.Transfer })}
|
||||||
|
>
|
||||||
|
{t('Transfer')}
|
||||||
|
</TradingButton>
|
||||||
|
<TradingButton
|
||||||
|
intent={Intent.Primary}
|
||||||
|
size="extra-small"
|
||||||
|
onClick={() => setView({ type: ViewType.Deposit })}
|
||||||
|
>
|
||||||
|
{t('Deposit')}
|
||||||
|
</TradingButton>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './accounts-menu';
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import { Splash } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { DepositsTable } from '@vegaprotocol/deposits';
|
||||||
|
import { depositsProvider } from '@vegaprotocol/deposits';
|
||||||
|
import { t } from '@vegaprotocol/i18n';
|
||||||
|
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||||
|
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||||
|
|
||||||
|
export const DepositsContainer = () => {
|
||||||
|
const { pubKey } = useVegaWallet();
|
||||||
|
const { data, error } = useDataProvider({
|
||||||
|
dataProvider: depositsProvider,
|
||||||
|
variables: { partyId: pubKey || '' },
|
||||||
|
skip: !pubKey,
|
||||||
|
});
|
||||||
|
if (!pubKey) {
|
||||||
|
return <Splash>{t('Please connect Vega wallet')}</Splash>;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<DepositsTable
|
||||||
|
rowData={data}
|
||||||
|
overlayNoRowsTemplate={error ? error.message : t('No deposits')}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './deposits-container';
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { t } from '@vegaprotocol/i18n';
|
||||||
|
import { Intent, TradingButton } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { ViewType, useSidebar } from '../sidebar';
|
||||||
|
|
||||||
|
export const DepositsMenu = () => {
|
||||||
|
const setView = useSidebar((store) => store.setView);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TradingButton
|
||||||
|
intent={Intent.Primary}
|
||||||
|
size="extra-small"
|
||||||
|
onClick={() => setView({ type: ViewType.Deposit })}
|
||||||
|
data-testid="deposit-button"
|
||||||
|
>
|
||||||
|
{t('Deposit')}
|
||||||
|
</TradingButton>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './deposits-menu';
|
||||||
@@ -7,14 +7,10 @@ import { t } from '@vegaprotocol/i18n';
|
|||||||
import { Splash } from '@vegaprotocol/ui-toolkit';
|
import { Splash } from '@vegaprotocol/ui-toolkit';
|
||||||
import type { DataGridSlice } from '../../stores/datagrid-store-slice';
|
import type { DataGridSlice } from '../../stores/datagrid-store-slice';
|
||||||
import { createDataGridSlice } from '../../stores/datagrid-store-slice';
|
import { createDataGridSlice } from '../../stores/datagrid-store-slice';
|
||||||
|
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
|
||||||
|
|
||||||
export const FillsContainer = ({
|
export const FillsContainer = ({ marketId }: { marketId?: string }) => {
|
||||||
marketId,
|
const onMarketClick = useMarketClickHandler(true);
|
||||||
onMarketClick,
|
|
||||||
}: {
|
|
||||||
marketId?: string;
|
|
||||||
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
|
|
||||||
}) => {
|
|
||||||
const { pubKey } = useVegaWallet();
|
const { pubKey } = useVegaWallet();
|
||||||
|
|
||||||
const gridStore = useFillsStore((store) => store.gridStore);
|
const gridStore = useFillsStore((store) => store.gridStore);
|
||||||
|
|||||||
@@ -134,6 +134,20 @@ describe('MarketSelector', () => {
|
|||||||
error: undefined,
|
error: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Button "All" should be selected by default', () => {
|
||||||
|
const buttons = ['All', 'Futures', 'Spot', 'Perpetuals'];
|
||||||
|
render(
|
||||||
|
<MemoryRouter>
|
||||||
|
<MarketSelector currentMarketId="market-0" onSelect={jest.fn()} />
|
||||||
|
</MemoryRouter>
|
||||||
|
);
|
||||||
|
screen
|
||||||
|
.getAllByTestId(/^product-(All|Future|Spot|Perpetual)$/)
|
||||||
|
.forEach((elem, i) => {
|
||||||
|
expect(elem.textContent).toEqual(buttons[i]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('renders only active markets', () => {
|
it('renders only active markets', () => {
|
||||||
render(
|
render(
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
@@ -169,6 +183,12 @@ describe('MarketSelector', () => {
|
|||||||
activeMarkets.length
|
activeMarkets.length
|
||||||
);
|
);
|
||||||
expect(screen.queryByTestId('no-items')).not.toBeInTheDocument();
|
expect(screen.queryByTestId('no-items')).not.toBeInTheDocument();
|
||||||
|
|
||||||
|
await userEvent.click(screen.getByTestId('product-All'));
|
||||||
|
expect(screen.queryAllByTestId(/market-\d/)).toHaveLength(
|
||||||
|
activeMarkets.length
|
||||||
|
);
|
||||||
|
expect(screen.queryByTestId('no-items')).not.toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('filters by search term', async () => {
|
it('filters by search term', async () => {
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export const MarketSelector = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const [filter, setFilter] = useState<Filter>({
|
const [filter, setFilter] = useState<Filter>({
|
||||||
searchTerm: '',
|
searchTerm: '',
|
||||||
product: Product.Future,
|
product: Product.All,
|
||||||
sort: Sort.None,
|
sort: Sort.None,
|
||||||
assets: [],
|
assets: [],
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit';
|
|||||||
|
|
||||||
// Make sure these match the available __typename properties on product
|
// Make sure these match the available __typename properties on product
|
||||||
export const Product = {
|
export const Product = {
|
||||||
|
All: 'All',
|
||||||
Future: 'Future',
|
Future: 'Future',
|
||||||
Spot: 'Spot',
|
Spot: 'Spot',
|
||||||
Perpetual: 'Perpetual',
|
Perpetual: 'Perpetual',
|
||||||
@@ -16,6 +17,7 @@ export type ProductType = keyof typeof Product;
|
|||||||
const ProductTypeMapping: {
|
const ProductTypeMapping: {
|
||||||
[key in ProductType]: string;
|
[key in ProductType]: string;
|
||||||
} = {
|
} = {
|
||||||
|
[Product.All]: 'All',
|
||||||
[Product.Future]: 'Futures',
|
[Product.Future]: 'Futures',
|
||||||
[Product.Spot]: 'Spot',
|
[Product.Spot]: 'Spot',
|
||||||
[Product.Perpetual]: 'Perpetuals',
|
[Product.Perpetual]: 'Perpetuals',
|
||||||
@@ -49,8 +51,12 @@ export const ProductSelector = ({
|
|||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
<Link to={Routes.MARKETS} className="flex items-center gap-2 ml-auto">
|
<Link
|
||||||
<span className="underline underline-offset-4">{t('All markets')}</span>
|
to={Routes.MARKETS}
|
||||||
|
className="flex items-center gap-2 ml-auto"
|
||||||
|
title={t('See all markets')}
|
||||||
|
>
|
||||||
|
<span className="underline underline-offset-4">{t('Browse')}</span>
|
||||||
<VegaIcon name={VegaIconNames.ARROW_RIGHT} />
|
<VegaIcon name={VegaIconNames.ARROW_RIGHT} />
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -120,6 +120,13 @@ describe('useMarketSelectorList', () => {
|
|||||||
assets: [],
|
assets: [],
|
||||||
});
|
});
|
||||||
expect(result.current.markets).toEqual([markets[2]]);
|
expect(result.current.markets).toEqual([markets[2]]);
|
||||||
|
rerender({
|
||||||
|
searchTerm: '',
|
||||||
|
product: Product.All,
|
||||||
|
sort: Sort.None,
|
||||||
|
assets: [],
|
||||||
|
});
|
||||||
|
expect(result.current.markets).toEqual(markets);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('filters by asset', () => {
|
it('filters by asset', () => {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { calcCandleVolume, useMarketList } from '@vegaprotocol/markets';
|
|||||||
import { priceChangePercentage } from '@vegaprotocol/utils';
|
import { priceChangePercentage } from '@vegaprotocol/utils';
|
||||||
import type { Filter } from '../../components/market-selector/market-selector';
|
import type { Filter } from '../../components/market-selector/market-selector';
|
||||||
import { Sort } from './sort-dropdown';
|
import { Sort } from './sort-dropdown';
|
||||||
|
import { Product } from './product-selector';
|
||||||
|
|
||||||
// Used for sort order and filter
|
// Used for sort order and filter
|
||||||
const MARKET_TEMPLATE = [
|
const MARKET_TEMPLATE = [
|
||||||
@@ -28,7 +29,10 @@ export const useMarketSelectorList = ({
|
|||||||
.filter((m) => isMarketActive(m.state))
|
.filter((m) => isMarketActive(m.state))
|
||||||
// only selected product type
|
// only selected product type
|
||||||
.filter((m) => {
|
.filter((m) => {
|
||||||
if (m.tradableInstrument.instrument.product.__typename === product) {
|
if (
|
||||||
|
product === Product.All ||
|
||||||
|
m.tradableInstrument.instrument.product.__typename === product
|
||||||
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -25,11 +25,10 @@ export const FilterStatusValue = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export interface OrderContainerProps {
|
export interface OrderContainerProps {
|
||||||
marketId?: string;
|
|
||||||
filter?: Filter;
|
filter?: Filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const OrdersContainer = ({ marketId, filter }: OrderContainerProps) => {
|
export const OrdersContainer = ({ filter }: OrderContainerProps) => {
|
||||||
const { pubKey, isReadOnly } = useVegaWallet();
|
const { pubKey, isReadOnly } = useVegaWallet();
|
||||||
const onMarketClick = useMarketClickHandler(true);
|
const onMarketClick = useMarketClickHandler(true);
|
||||||
const onOrderTypeClick = useMarketLiquidityClickHandler();
|
const onOrderTypeClick = useMarketLiquidityClickHandler();
|
||||||
@@ -45,7 +44,6 @@ export const OrdersContainer = ({ marketId, filter }: OrderContainerProps) => {
|
|||||||
return (
|
return (
|
||||||
<OrderListManager
|
<OrderListManager
|
||||||
partyId={pubKey}
|
partyId={pubKey}
|
||||||
marketId={marketId}
|
|
||||||
filter={filter}
|
filter={filter}
|
||||||
onMarketClick={onMarketClick}
|
onMarketClick={onMarketClick}
|
||||||
onOrderTypeClick={onOrderTypeClick}
|
onOrderTypeClick={onOrderTypeClick}
|
||||||
|
|||||||
@@ -7,21 +7,15 @@ import type { DataGridSlice } from '../../stores/datagrid-store-slice';
|
|||||||
import { createDataGridSlice } from '../../stores/datagrid-store-slice';
|
import { createDataGridSlice } from '../../stores/datagrid-store-slice';
|
||||||
import { create } from 'zustand';
|
import { create } from 'zustand';
|
||||||
import { persist } from 'zustand/middleware';
|
import { persist } from 'zustand/middleware';
|
||||||
|
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
|
||||||
|
|
||||||
export const PositionsContainer = ({
|
export const PositionsContainer = ({ allKeys }: { allKeys?: boolean }) => {
|
||||||
onMarketClick,
|
const onMarketClick = useMarketClickHandler(true);
|
||||||
allKeys,
|
|
||||||
}: {
|
|
||||||
onMarketClick?: (marketId: string) => void;
|
|
||||||
allKeys?: boolean;
|
|
||||||
}) => {
|
|
||||||
const { pubKey, pubKeys, isReadOnly } = useVegaWallet();
|
const { pubKey, pubKeys, isReadOnly } = useVegaWallet();
|
||||||
|
|
||||||
const gridStore = usePositionsStore((store) => store.gridStore);
|
const gridStore = usePositionsStore((store) => store.gridStore);
|
||||||
const updateGridStore = usePositionsStore((store) => store.updateGridStore);
|
const updateGridStore = usePositionsStore((store) => store.updateGridStore);
|
||||||
const gridStoreCallbacks = useDataGridEvents(gridStore, (colState) => {
|
const gridStoreCallbacks = useDataGridEvents(gridStore, updateGridStore);
|
||||||
updateGridStore(colState);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!pubKey) {
|
if (!pubKey) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './trades-container';
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import { TradesManager } from '@vegaprotocol/trades';
|
||||||
|
import type { DataGridSlice } from '../../stores/datagrid-store-slice';
|
||||||
|
import { createDataGridSlice } from '../../stores/datagrid-store-slice';
|
||||||
|
import { create } from 'zustand';
|
||||||
|
import { persist } from 'zustand/middleware';
|
||||||
|
import { useDataGridEvents } from '@vegaprotocol/datagrid';
|
||||||
|
|
||||||
|
interface TradesContainerProps {
|
||||||
|
marketId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TradesContainer = ({ marketId }: TradesContainerProps) => {
|
||||||
|
const gridStore = useTradesStore((store) => store.gridStore);
|
||||||
|
const updateGridStore = useTradesStore((store) => store.updateGridStore);
|
||||||
|
const gridStoreCallbacks = useDataGridEvents(gridStore, updateGridStore);
|
||||||
|
|
||||||
|
return <TradesManager marketId={marketId} gridProps={gridStoreCallbacks} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
const useTradesStore = create<DataGridSlice>()(
|
||||||
|
persist(createDataGridSlice, {
|
||||||
|
name: 'vega_trades_store',
|
||||||
|
})
|
||||||
|
);
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './withdrawals-container';
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { Splash } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import {
|
||||||
|
withdrawalProvider,
|
||||||
|
WithdrawalsTable,
|
||||||
|
useIncompleteWithdrawals,
|
||||||
|
} from '@vegaprotocol/withdraws';
|
||||||
|
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||||
|
import { t } from '@vegaprotocol/i18n';
|
||||||
|
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||||
|
|
||||||
|
export const WithdrawalsContainer = () => {
|
||||||
|
const { pubKey } = useVegaWallet();
|
||||||
|
const { data, error } = useDataProvider({
|
||||||
|
dataProvider: withdrawalProvider,
|
||||||
|
variables: { partyId: pubKey || '' },
|
||||||
|
skip: !pubKey,
|
||||||
|
});
|
||||||
|
const { ready, delayed } = useIncompleteWithdrawals();
|
||||||
|
if (!pubKey) {
|
||||||
|
return <Splash>{t('Please connect Vega wallet')}</Splash>;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<WithdrawalsTable
|
||||||
|
data-testid="withdrawals-history"
|
||||||
|
rowData={data}
|
||||||
|
overlayNoRowsTemplate={error ? error.message : t('No withdrawals')}
|
||||||
|
ready={ready}
|
||||||
|
delayed={delayed}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './withdrawals-menu';
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { t } from '@vegaprotocol/i18n';
|
||||||
|
import { Intent, TradingButton } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { ViewType, useSidebar } from '../sidebar';
|
||||||
|
|
||||||
|
export const WithdrawalsMenu = () => {
|
||||||
|
const setView = useSidebar((store) => store.setView);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TradingButton
|
||||||
|
intent={Intent.Primary}
|
||||||
|
size="extra-small"
|
||||||
|
onClick={() => setView({ type: ViewType.Withdraw })}
|
||||||
|
data-testid="withdraw-dialog-button"
|
||||||
|
>
|
||||||
|
{t('Make withdrawal')}
|
||||||
|
</TradingButton>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -1,11 +1,9 @@
|
|||||||
import {
|
import {
|
||||||
RestConnector,
|
|
||||||
JsonRpcConnector,
|
JsonRpcConnector,
|
||||||
ViewConnector,
|
ViewConnector,
|
||||||
InjectedConnector,
|
InjectedConnector,
|
||||||
} from '@vegaprotocol/wallet';
|
} from '@vegaprotocol/wallet';
|
||||||
|
|
||||||
export const rest = new RestConnector();
|
|
||||||
export const jsonRpc = new JsonRpcConnector();
|
export const jsonRpc = new JsonRpcConnector();
|
||||||
export const injected = new InjectedConnector();
|
export const injected = new InjectedConnector();
|
||||||
|
|
||||||
@@ -19,7 +17,6 @@ if (typeof window !== 'undefined') {
|
|||||||
|
|
||||||
export const Connectors = {
|
export const Connectors = {
|
||||||
injected,
|
injected,
|
||||||
rest,
|
|
||||||
jsonRpc,
|
jsonRpc,
|
||||||
view,
|
view,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,12 +5,45 @@ export default function Document() {
|
|||||||
<Html>
|
<Html>
|
||||||
<Head>
|
<Head>
|
||||||
<link rel="stylesheet" href="https://static.vega.xyz/fonts.css" />
|
<link rel="stylesheet" href="https://static.vega.xyz/fonts.css" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<meta charSet="utf-8" />
|
||||||
|
<link
|
||||||
|
rel="icon"
|
||||||
|
type="image/x-icon"
|
||||||
|
href="https://static.vega.xyz/favicon.ico"
|
||||||
|
/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<meta name="theme-color" content="#000000" />
|
||||||
|
<meta name="description" content="Vega Protocol - VEGA Console" />
|
||||||
|
<meta name="og:type" content="website" />
|
||||||
|
<meta name="og:url" content="https://console.vega.xyz/" />
|
||||||
|
<meta name="og:title" content="Vega Protocol - Console" />
|
||||||
|
<meta name="og:site_name" content="Vega Protocol - Console" />
|
||||||
|
<meta name="og:image" content="https://static.vega.xyz/favicon.ico" />
|
||||||
|
|
||||||
|
<meta
|
||||||
|
name="twitter:card"
|
||||||
|
content="https://static.vega.xyz/favicon.ico"
|
||||||
|
/>
|
||||||
|
<meta name="twitter:title" content="Vega Protocol - Console" />
|
||||||
|
<meta name="twitter:description" content="Vega Protocol - Console" />
|
||||||
|
<meta
|
||||||
|
name="twitter:image"
|
||||||
|
content="https://static.vega.xyz/favicon.ico"
|
||||||
|
/>
|
||||||
|
<meta name="twitter:image:alt" content="VEGA logo" />
|
||||||
|
<meta name="twitter:site" content="@vegaprotocol" />
|
||||||
|
|
||||||
|
<meta name="description" content="Vega Protocol - Console" />
|
||||||
|
<link
|
||||||
|
rel="apple-touch-icon"
|
||||||
|
content="https://static.vega.xyz/favicon.ico"
|
||||||
|
/>
|
||||||
<link
|
<link
|
||||||
rel="preload"
|
rel="preload"
|
||||||
href="https://static.vega.xyz/AlphaLyrae-Medium.woff2"
|
href="https://static.vega.xyz/AlphaLyrae-Medium.woff2"
|
||||||
as="font"
|
as="font"
|
||||||
type="font/woff2"
|
type="font/woff2"
|
||||||
crossOrigin="anonymous"
|
|
||||||
/>
|
/>
|
||||||
{/* eslint-disable-next-line @next/next/no-css-tags */}
|
{/* eslint-disable-next-line @next/next/no-css-tags */}
|
||||||
<link rel="stylesheet" href="/preloader.css" media="all" />
|
<link rel="stylesheet" href="/preloader.css" media="all" />
|
||||||
|
|||||||
@@ -142,12 +142,19 @@ html [data-theme='dark'] {
|
|||||||
border-width: 0;
|
border-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vega-ag-grid .ag-cell .ag-cell-wrapper {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.vega-ag-grid .ag-header-row {
|
.vega-ag-grid .ag-header-row {
|
||||||
@apply font-alpha font-normal;
|
@apply font-alpha font-normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Light variables */
|
/* Light variables */
|
||||||
.ag-theme-balham {
|
.ag-theme-balham {
|
||||||
|
--ag-grid-size: 2px; /* Used for compactness */
|
||||||
|
--ag-row-height: 36px;
|
||||||
|
--ag-header-height: 36px;
|
||||||
--ag-background-color: theme(colors.white);
|
--ag-background-color: theme(colors.white);
|
||||||
--ag-border-color: theme(colors.vega.clight.600);
|
--ag-border-color: theme(colors.vega.clight.600);
|
||||||
--ag-header-background-color: theme(colors.vega.clight.700);
|
--ag-header-background-color: theme(colors.vega.clight.700);
|
||||||
@@ -160,6 +167,9 @@ html [data-theme='dark'] {
|
|||||||
|
|
||||||
/* Dark variables */
|
/* Dark variables */
|
||||||
.ag-theme-balham-dark {
|
.ag-theme-balham-dark {
|
||||||
|
--ag-grid-size: 2px; /* Used for compactness */
|
||||||
|
--ag-row-height: 36px;
|
||||||
|
--ag-header-height: 36px;
|
||||||
--ag-background-color: theme(colors.vega.cdark.900);
|
--ag-background-color: theme(colors.vega.cdark.900);
|
||||||
--ag-border-color: theme(colors.vega.cdark.600);
|
--ag-border-color: theme(colors.vega.cdark.600);
|
||||||
--ag-header-background-color: theme(colors.vega.cdark.700);
|
--ag-header-background-color: theme(colors.vega.cdark.700);
|
||||||
|
|||||||
@@ -58,6 +58,12 @@ export const accountValuesComparator = (
|
|||||||
return valueA > valueB ? 1 : -1;
|
return valueA > valueB ? 1 : -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const defaultColDef = {
|
||||||
|
resizable: true,
|
||||||
|
sortable: true,
|
||||||
|
tooltipComponent: TooltipCellComponent,
|
||||||
|
comparator: accountValuesComparator,
|
||||||
|
};
|
||||||
export interface GetRowsParams extends Omit<IGetRowsParams, 'successCallback'> {
|
export interface GetRowsParams extends Omit<IGetRowsParams, 'successCallback'> {
|
||||||
successCallback(rowsThisBlock: AccountFields[], lastRow?: number): void;
|
successCallback(rowsThisBlock: AccountFields[], lastRow?: number): void;
|
||||||
}
|
}
|
||||||
@@ -306,16 +312,10 @@ export const AccountTable = ({
|
|||||||
return (
|
return (
|
||||||
<AgGrid
|
<AgGrid
|
||||||
{...props}
|
{...props}
|
||||||
style={{ width: '100%', height: '100%' }}
|
|
||||||
getRowId={({ data }: { data: AccountFields }) => data.asset.id}
|
getRowId={({ data }: { data: AccountFields }) => data.asset.id}
|
||||||
tooltipShowDelay={500}
|
tooltipShowDelay={500}
|
||||||
rowData={data}
|
rowData={data}
|
||||||
defaultColDef={{
|
defaultColDef={defaultColDef}
|
||||||
resizable: true,
|
|
||||||
tooltipComponent: TooltipCellComponent,
|
|
||||||
sortable: true,
|
|
||||||
comparator: accountValuesComparator,
|
|
||||||
}}
|
|
||||||
columnDefs={colDefs}
|
columnDefs={colDefs}
|
||||||
getRowHeight={getPinnedAssetRowHeight}
|
getRowHeight={getPinnedAssetRowHeight}
|
||||||
pinnedTopRowData={pinnedRow ? [pinnedRow] : undefined}
|
pinnedTopRowData={pinnedRow ? [pinnedRow] : undefined}
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ import { MarginHealthChart } from './margin-health-chart';
|
|||||||
import { MarketNameCell } from '@vegaprotocol/datagrid';
|
import { MarketNameCell } from '@vegaprotocol/datagrid';
|
||||||
import { AccountType } from '@vegaprotocol/types';
|
import { AccountType } from '@vegaprotocol/types';
|
||||||
|
|
||||||
|
const defaultColDef = {
|
||||||
|
resizable: true,
|
||||||
|
sortable: true,
|
||||||
|
};
|
||||||
interface BreakdownTableProps extends AgGridReactProps {
|
interface BreakdownTableProps extends AgGridReactProps {
|
||||||
data: AccountFields[] | null;
|
data: AccountFields[] | null;
|
||||||
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
|
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
|
||||||
@@ -41,7 +45,6 @@ const BreakdownTable = forwardRef<AgGridReact, BreakdownTableProps>(
|
|||||||
if (!value) return 'None';
|
if (!value) return 'None';
|
||||||
return value;
|
return value;
|
||||||
},
|
},
|
||||||
minWidth: 200,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
headerName: t('Account type'),
|
headerName: t('Account type'),
|
||||||
@@ -58,7 +61,6 @@ const BreakdownTable = forwardRef<AgGridReact, BreakdownTableProps>(
|
|||||||
{
|
{
|
||||||
headerName: t('Balance'),
|
headerName: t('Balance'),
|
||||||
field: 'used',
|
field: 'used',
|
||||||
flex: 2,
|
|
||||||
maxWidth: 500,
|
maxWidth: 500,
|
||||||
type: 'rightAligned',
|
type: 'rightAligned',
|
||||||
tooltipComponent: TooltipCellComponent,
|
tooltipComponent: TooltipCellComponent,
|
||||||
@@ -97,7 +99,6 @@ const BreakdownTable = forwardRef<AgGridReact, BreakdownTableProps>(
|
|||||||
{
|
{
|
||||||
headerName: t('Margin health'),
|
headerName: t('Margin health'),
|
||||||
field: 'market.id',
|
field: 'market.id',
|
||||||
flex: 2,
|
|
||||||
maxWidth: 500,
|
maxWidth: 500,
|
||||||
sortable: false,
|
sortable: false,
|
||||||
cellRenderer: ({
|
cellRenderer: ({
|
||||||
@@ -118,7 +119,6 @@ const BreakdownTable = forwardRef<AgGridReact, BreakdownTableProps>(
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<AgGrid
|
<AgGrid
|
||||||
style={{ width: '100%', height: '100%' }}
|
|
||||||
overlayNoRowsTemplate={t('Collateral not used')}
|
overlayNoRowsTemplate={t('Collateral not used')}
|
||||||
rowData={data}
|
rowData={data}
|
||||||
getRowId={({ data }: { data: AccountFields }) =>
|
getRowId={({ data }: { data: AccountFields }) =>
|
||||||
@@ -128,11 +128,7 @@ const BreakdownTable = forwardRef<AgGridReact, BreakdownTableProps>(
|
|||||||
rowHeight={34}
|
rowHeight={34}
|
||||||
components={{ PriceCell, MarketNameCell, ProgressBarCell }}
|
components={{ PriceCell, MarketNameCell, ProgressBarCell }}
|
||||||
tooltipShowDelay={500}
|
tooltipShowDelay={500}
|
||||||
defaultColDef={{
|
defaultColDef={defaultColDef}
|
||||||
flex: 1,
|
|
||||||
resizable: true,
|
|
||||||
sortable: true,
|
|
||||||
}}
|
|
||||||
columnDefs={coldefs}
|
columnDefs={coldefs}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,21 +7,12 @@ import {
|
|||||||
} from '@vegaprotocol/network-parameters';
|
} from '@vegaprotocol/network-parameters';
|
||||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||||
import type { Transfer } from '@vegaprotocol/wallet';
|
import type { Transfer } from '@vegaprotocol/wallet';
|
||||||
import {
|
import { useVegaTransactionStore, useVegaWallet } from '@vegaprotocol/wallet';
|
||||||
useVegaTransactionStore,
|
|
||||||
useVegaWallet,
|
|
||||||
useVegaWalletDialogStore,
|
|
||||||
} from '@vegaprotocol/wallet';
|
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import { accountsDataProvider } from './accounts-data-provider';
|
import { accountsDataProvider } from './accounts-data-provider';
|
||||||
import { TransferForm } from './transfer-form';
|
import { TransferForm } from './transfer-form';
|
||||||
import sortBy from 'lodash/sortBy';
|
import sortBy from 'lodash/sortBy';
|
||||||
import {
|
import { Lozenge } from '@vegaprotocol/ui-toolkit';
|
||||||
ExternalLink,
|
|
||||||
Intent,
|
|
||||||
Lozenge,
|
|
||||||
Notification,
|
|
||||||
} from '@vegaprotocol/ui-toolkit';
|
|
||||||
|
|
||||||
export const TransferContainer = ({ assetId }: { assetId?: string }) => {
|
export const TransferContainer = ({ assetId }: { assetId?: string }) => {
|
||||||
const { pubKey, pubKeys } = useVegaWallet();
|
const { pubKey, pubKeys } = useVegaWallet();
|
||||||
@@ -32,10 +23,6 @@ export const TransferContainer = ({ assetId }: { assetId?: string }) => {
|
|||||||
skip: !pubKey,
|
skip: !pubKey,
|
||||||
});
|
});
|
||||||
|
|
||||||
const openVegaWalletDialog = useVegaWalletDialogStore(
|
|
||||||
(store) => store.openVegaWalletDialog
|
|
||||||
);
|
|
||||||
|
|
||||||
const create = useVegaTransactionStore((store) => store.create);
|
const create = useVegaTransactionStore((store) => store.create);
|
||||||
|
|
||||||
const transfer = useCallback(
|
const transfer = useCallback(
|
||||||
@@ -74,28 +61,6 @@ export const TransferContainer = ({ assetId }: { assetId?: string }) => {
|
|||||||
)}
|
)}
|
||||||
{t('. If you are at all unsure, stop and seek advice.')}
|
{t('. If you are at all unsure, stop and seek advice.')}
|
||||||
</p>
|
</p>
|
||||||
{!pubKey && (
|
|
||||||
<div className="mb-4">
|
|
||||||
<Notification
|
|
||||||
intent={Intent.Warning}
|
|
||||||
message={
|
|
||||||
<p className="text-sm pb-2">
|
|
||||||
You need a{' '}
|
|
||||||
<ExternalLink href="https://vega.xyz/wallet">
|
|
||||||
Vega wallet
|
|
||||||
</ExternalLink>{' '}
|
|
||||||
to make a transfer.
|
|
||||||
</p>
|
|
||||||
}
|
|
||||||
buttonProps={{
|
|
||||||
text: t('Connect wallet'),
|
|
||||||
action: openVegaWalletDialog,
|
|
||||||
dataTestId: 'order-connect-wallet',
|
|
||||||
size: 'small',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<TransferForm
|
<TransferForm
|
||||||
pubKey={pubKey}
|
pubKey={pubKey}
|
||||||
pubKeys={pubKeys ? pubKeys?.map((pk) => pk.publicKey) : null}
|
pubKeys={pubKeys ? pubKeys?.map((pk) => pk.publicKey) : null}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import { addVegaWalletSubmitLiquidityProvision } from './lib/commands/vega-walle
|
|||||||
import { addImportNodeWallets } from './lib/commands/import-node-wallets';
|
import { addImportNodeWallets } from './lib/commands/import-node-wallets';
|
||||||
import { addVegaWalletTopUpRewardsPool } from './lib/commands/vega-wallet-top-up-rewards-pool';
|
import { addVegaWalletTopUpRewardsPool } from './lib/commands/vega-wallet-top-up-rewards-pool';
|
||||||
import { addAssociateTokensToVegaWallet } from './lib/commands/associate-tokens-to-vega-wallet';
|
import { addAssociateTokensToVegaWallet } from './lib/commands/associate-tokens-to-vega-wallet';
|
||||||
|
import { addMockChainId } from './lib/commands/mock-chain-id';
|
||||||
|
|
||||||
addGetTestIdcommand();
|
addGetTestIdcommand();
|
||||||
addMockGQLCommand();
|
addMockGQLCommand();
|
||||||
@@ -49,6 +50,7 @@ addVegaWalletSubmitLiquidityProvision();
|
|||||||
addImportNodeWallets();
|
addImportNodeWallets();
|
||||||
addVegaWalletTopUpRewardsPool();
|
addVegaWalletTopUpRewardsPool();
|
||||||
addAssociateTokensToVegaWallet();
|
addAssociateTokensToVegaWallet();
|
||||||
|
addMockChainId();
|
||||||
|
|
||||||
export {
|
export {
|
||||||
mockConnectWallet,
|
mockConnectWallet,
|
||||||
|
|||||||
@@ -10,14 +10,11 @@ declare global {
|
|||||||
|
|
||||||
export const addConnectPublicKey = () => {
|
export const addConnectPublicKey = () => {
|
||||||
Cypress.Commands.add('connectPublicKey', (publicKey) => {
|
Cypress.Commands.add('connectPublicKey', (publicKey) => {
|
||||||
const connectVegaWaletBtn = Cypress.$(
|
const connectVegaWaletBtn = Cypress.$(`[data-testid="view-as-user"]`);
|
||||||
`[data-testid="connect-vega-wallet"]`
|
|
||||||
);
|
|
||||||
if (connectVegaWaletBtn.length > 0) {
|
if (connectVegaWaletBtn.length > 0) {
|
||||||
cy.get('aside [data-testid="connect-vega-wallet"]').click();
|
cy.get('aside button').contains('View as party').click();
|
||||||
cy.getByTestId('connector-view').should('be.visible').click();
|
cy.getByTestId('address').should('be.visible').focus();
|
||||||
cy.getByTestId('address').click();
|
cy.getByTestId('address').type(publicKey, { delay: 50 });
|
||||||
cy.getByTestId('address').type(publicKey);
|
|
||||||
cy.getByTestId('connect').click();
|
cy.getByTestId('connect').click();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { aliasGQLQuery } from '../mock-gql';
|
||||||
|
// eslint-disable-next-line @nx/enforce-module-boundaries
|
||||||
|
import { chainIdQuery, statisticsQuery } from '@vegaprotocol/mock';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||||
|
namespace Cypress {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
interface Chainable<Subject> {
|
||||||
|
mockChainId(): void;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addMockChainId() {
|
||||||
|
Cypress.Commands.add('mockChainId', () => {
|
||||||
|
cy.mockGQL((req) => {
|
||||||
|
aliasGQLQuery(req, 'ChainId', chainIdQuery());
|
||||||
|
aliasGQLQuery(req, 'Statistics', statisticsQuery());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -29,7 +29,7 @@ export const mockConnectWallet = () => {
|
|||||||
|
|
||||||
export const mockConnectWalletWithUserError = () => {
|
export const mockConnectWalletWithUserError = () => {
|
||||||
cy.mockWallet((req) => {
|
cy.mockWallet((req) => {
|
||||||
aliasWalletConnectWithUserError(req);
|
aliasWalletConnectWithUserError(req, Cypress.env('VEGA_WALLET_API_TOKEN'));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -62,10 +62,27 @@ export const aliasWalletConnectQuery = (
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (hasMethod(req, 'client.get_chain_id')) {
|
||||||
|
req.reply({
|
||||||
|
statusCode: 200,
|
||||||
|
headers: {
|
||||||
|
'Access-Control-Expose-Headers': 'Authorization',
|
||||||
|
Authorization: `VWT ${token}`,
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
result: {
|
||||||
|
chainID: 'test-id',
|
||||||
|
},
|
||||||
|
id: '1',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const aliasWalletConnectWithUserError = (
|
export const aliasWalletConnectWithUserError = (
|
||||||
req: CyHttpMessages.IncomingHttpRequest
|
req: CyHttpMessages.IncomingHttpRequest,
|
||||||
|
token: string
|
||||||
) => {
|
) => {
|
||||||
if (hasMethod(req, 'client.connect_wallet')) {
|
if (hasMethod(req, 'client.connect_wallet')) {
|
||||||
req.alias = 'client.connect_wallet';
|
req.alias = 'client.connect_wallet';
|
||||||
@@ -82,4 +99,20 @@ export const aliasWalletConnectWithUserError = (
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (hasMethod(req, 'client.get_chain_id')) {
|
||||||
|
req.reply({
|
||||||
|
statusCode: 200,
|
||||||
|
headers: {
|
||||||
|
'Access-Control-Expose-Headers': 'Authorization',
|
||||||
|
Authorization: `VWT ${token}`,
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
result: {
|
||||||
|
chainID: 'test-id',
|
||||||
|
},
|
||||||
|
id: '1',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,6 +3,20 @@ import { AgGridReact } from 'ag-grid-react';
|
|||||||
import { useThemeSwitcher } from '@vegaprotocol/react-helpers';
|
import { useThemeSwitcher } from '@vegaprotocol/react-helpers';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import type { ColDef } from 'ag-grid-community';
|
||||||
|
|
||||||
|
const defaultProps: AgGridReactProps = {
|
||||||
|
enableCellTextSelection: true,
|
||||||
|
overlayLoadingTemplate: t('Loading...'),
|
||||||
|
overlayNoRowsTemplate: t('No data'),
|
||||||
|
suppressCellFocus: true,
|
||||||
|
suppressColumnMoveAnimation: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaultColDef: ColDef = {
|
||||||
|
resizable: true,
|
||||||
|
sortable: true,
|
||||||
|
};
|
||||||
|
|
||||||
export const AgGridThemed = ({
|
export const AgGridThemed = ({
|
||||||
style,
|
style,
|
||||||
@@ -13,23 +27,20 @@ export const AgGridThemed = ({
|
|||||||
gridRef?: React.ForwardedRef<AgGridReact>;
|
gridRef?: React.ForwardedRef<AgGridReact>;
|
||||||
}) => {
|
}) => {
|
||||||
const { theme } = useThemeSwitcher();
|
const { theme } = useThemeSwitcher();
|
||||||
const defaultProps = {
|
|
||||||
rowHeight: 22,
|
|
||||||
headerHeight: 22,
|
|
||||||
enableCellTextSelection: true,
|
|
||||||
overlayLoadingTemplate: t('Loading...'),
|
|
||||||
overlayNoRowsTemplate: t('No data'),
|
|
||||||
suppressCellFocus: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
const wrapperClasses = classNames('vega-ag-grid', {
|
const wrapperClasses = classNames('vega-ag-grid', 'w-full h-full', {
|
||||||
'ag-theme-balham': theme === 'light',
|
'ag-theme-balham': theme === 'light',
|
||||||
'ag-theme-balham-dark': theme === 'dark',
|
'ag-theme-balham-dark': theme === 'dark',
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={wrapperClasses} style={style}>
|
<div className={wrapperClasses}>
|
||||||
<AgGridReact {...defaultProps} {...props} ref={gridRef} />
|
<AgGridReact
|
||||||
|
defaultColDef={defaultColDef}
|
||||||
|
ref={gridRef}
|
||||||
|
{...defaultProps}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -29,7 +29,11 @@ export const MarketNameCell = ({
|
|||||||
);
|
);
|
||||||
if (!value || !data) return null;
|
if (!value || !data) return null;
|
||||||
return onMarketClick ? (
|
return onMarketClick ? (
|
||||||
<button onClick={handleOnClick} tabIndex={0}>
|
<button
|
||||||
|
onClick={handleOnClick}
|
||||||
|
tabIndex={0}
|
||||||
|
className="block text-left text-ellipsis overflow-hidden whitespace-nowrap w-full"
|
||||||
|
>
|
||||||
{value}
|
{value}
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ export const COL_DEFS = {
|
|||||||
sortable: false,
|
sortable: false,
|
||||||
resizable: false,
|
resizable: false,
|
||||||
filter: false,
|
filter: false,
|
||||||
minWidth: 45,
|
minWidth: 30,
|
||||||
maxWidth: 45,
|
maxWidth: 30,
|
||||||
type: 'rightAligned',
|
type: 'rightAligned',
|
||||||
pinned: 'right' as const,
|
pinned: 'right' as const,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ const gridProps = {
|
|||||||
{
|
{
|
||||||
field: 'id',
|
field: 'id',
|
||||||
width: 100,
|
width: 100,
|
||||||
resizable: true,
|
|
||||||
filter: 'agNumberColumnFilter',
|
filter: 'agNumberColumnFilter',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -50,7 +49,7 @@ describe('useDataGridEvents', () => {
|
|||||||
console.warn = originalWarn;
|
console.warn = originalWarn;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('default state is set and callback is called on column or filter event', async () => {
|
it('default state is set and callback is called on filter event', async () => {
|
||||||
const callback = jest.fn();
|
const callback = jest.fn();
|
||||||
const initialState = {
|
const initialState = {
|
||||||
filterModel: undefined,
|
filterModel: undefined,
|
||||||
@@ -67,45 +66,6 @@ describe('useDataGridEvents', () => {
|
|||||||
// no filters set
|
// no filters set
|
||||||
expect(result.current.api.getFilterModel()).toEqual({});
|
expect(result.current.api.getFilterModel()).toEqual({});
|
||||||
|
|
||||||
const newWidth = 400;
|
|
||||||
|
|
||||||
// Set col width
|
|
||||||
await act(async () => {
|
|
||||||
result.current.columnApi.setColumnWidth('id', newWidth);
|
|
||||||
});
|
|
||||||
|
|
||||||
act(() => {
|
|
||||||
jest.advanceTimersByTime(GRID_EVENT_DEBOUNCE_TIME);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(callback).toHaveBeenCalledWith({
|
|
||||||
columnState: [expect.objectContaining({ colId: 'id', width: newWidth })],
|
|
||||||
filterModel: {},
|
|
||||||
});
|
|
||||||
callback.mockClear();
|
|
||||||
expect(result.current.columnApi.getColumnState()[0].width).toEqual(
|
|
||||||
newWidth
|
|
||||||
);
|
|
||||||
|
|
||||||
// Set filter
|
|
||||||
await act(async () => {
|
|
||||||
result.current.columnApi.applyColumnState({
|
|
||||||
state: [{ colId: 'id', sort: 'asc' }],
|
|
||||||
applyOrder: true,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
act(() => {
|
|
||||||
jest.advanceTimersByTime(GRID_EVENT_DEBOUNCE_TIME);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(callback).toHaveBeenCalledWith({
|
|
||||||
columnState: [expect.objectContaining({ colId: 'id', sort: 'asc' })],
|
|
||||||
filterModel: {},
|
|
||||||
});
|
|
||||||
callback.mockClear();
|
|
||||||
expect(result.current.columnApi.getColumnState()[0].sort).toEqual('asc');
|
|
||||||
|
|
||||||
// Set filter
|
// Set filter
|
||||||
const idFilter = {
|
const idFilter = {
|
||||||
filter: 1,
|
filter: 1,
|
||||||
@@ -123,7 +83,7 @@ describe('useDataGridEvents', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(callback).toHaveBeenCalledWith({
|
expect(callback).toHaveBeenCalledWith({
|
||||||
columnState: expect.any(Object),
|
columnState: undefined,
|
||||||
filterModel: {
|
filterModel: {
|
||||||
id: idFilter,
|
id: idFilter,
|
||||||
},
|
},
|
||||||
@@ -138,7 +98,7 @@ describe('useDataGridEvents', () => {
|
|||||||
filterType: 'number',
|
filterType: 'number',
|
||||||
type: 'equals',
|
type: 'equals',
|
||||||
};
|
};
|
||||||
const colState = { colId: 'id', width: 300, sort: 'desc' as const };
|
const colState = { colId: 'id', sort: 'desc' as const };
|
||||||
const initialState = {
|
const initialState = {
|
||||||
filterModel: {
|
filterModel: {
|
||||||
id: idFilter,
|
id: idFilter,
|
||||||
@@ -156,7 +116,7 @@ describe('useDataGridEvents', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('debounces events', async () => {
|
it('ignores events that were not made via the UI', async () => {
|
||||||
const callback = jest.fn();
|
const callback = jest.fn();
|
||||||
const initialState = {
|
const initialState = {
|
||||||
filterModel: undefined,
|
filterModel: undefined,
|
||||||
@@ -170,8 +130,6 @@ describe('useDataGridEvents', () => {
|
|||||||
// Set col width multiple times
|
// Set col width multiple times
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
result.current.columnApi.setColumnWidth('id', newWidth);
|
result.current.columnApi.setColumnWidth('id', newWidth);
|
||||||
result.current.columnApi.setColumnWidth('id', newWidth);
|
|
||||||
result.current.columnApi.setColumnWidth('id', newWidth);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(callback).not.toHaveBeenCalled();
|
expect(callback).not.toHaveBeenCalled();
|
||||||
@@ -180,6 +138,6 @@ describe('useDataGridEvents', () => {
|
|||||||
jest.advanceTimersByTime(GRID_EVENT_DEBOUNCE_TIME);
|
jest.advanceTimersByTime(GRID_EVENT_DEBOUNCE_TIME);
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(callback).toHaveBeenCalledTimes(1);
|
expect(callback).toHaveBeenCalledTimes(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import debounce from 'lodash/debounce';
|
|
||||||
import type {
|
import type {
|
||||||
|
ColumnMovedEvent,
|
||||||
ColumnResizedEvent,
|
ColumnResizedEvent,
|
||||||
ColumnState,
|
ColumnState,
|
||||||
|
ColumnVisibleEvent,
|
||||||
FilterChangedEvent,
|
FilterChangedEvent,
|
||||||
GridReadyEvent,
|
FirstDataRenderedEvent,
|
||||||
SortChangedEvent,
|
SortChangedEvent,
|
||||||
} from 'ag-grid-community';
|
} from 'ag-grid-community';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
@@ -14,30 +15,70 @@ type State = {
|
|||||||
columnState?: ColumnState[];
|
columnState?: ColumnState[];
|
||||||
};
|
};
|
||||||
|
|
||||||
type Event = ColumnResizedEvent | FilterChangedEvent | SortChangedEvent;
|
|
||||||
|
|
||||||
export const GRID_EVENT_DEBOUNCE_TIME = 300;
|
|
||||||
|
|
||||||
export const useDataGridEvents = (
|
export const useDataGridEvents = (
|
||||||
state: State,
|
state: State,
|
||||||
callback: (data: State) => void
|
callback: (data: State) => void
|
||||||
) => {
|
) => {
|
||||||
// This function can be called very frequently by the onColumnResized
|
/**
|
||||||
// grid callback, so its memoized to only update after resizing is finished
|
* Callback for filter events
|
||||||
const onGridChange = useMemo(
|
*/
|
||||||
() =>
|
const onFilterChanged = useCallback(
|
||||||
debounce(({ api, columnApi }: Event) => {
|
({ api }: FilterChangedEvent) => {
|
||||||
if (!api || !columnApi) return;
|
if (!api) return;
|
||||||
const columnState = columnApi.getColumnState();
|
const filterModel = api.getFilterModel();
|
||||||
const filterModel = api.getFilterModel();
|
callback({ filterModel });
|
||||||
callback({ columnState, filterModel });
|
},
|
||||||
}, GRID_EVENT_DEBOUNCE_TIME),
|
|
||||||
[callback]
|
[callback]
|
||||||
);
|
);
|
||||||
|
|
||||||
// check if we have stored column states or filter models and apply if we do
|
/**
|
||||||
|
* Callback for column resized and column moved events, which can be
|
||||||
|
* triggered in quick succession. Uses the finished flag to not call the
|
||||||
|
* store callback unnecessarily
|
||||||
|
*/
|
||||||
|
const onDebouncedColumnChange = useCallback(
|
||||||
|
({
|
||||||
|
columnApi,
|
||||||
|
source,
|
||||||
|
finished,
|
||||||
|
}: ColumnResizedEvent | ColumnMovedEvent) => {
|
||||||
|
if (!finished) return;
|
||||||
|
|
||||||
|
// only call back on user interactions, and not events triggered from the api
|
||||||
|
const permittedEvents = [
|
||||||
|
'uiColumnResized',
|
||||||
|
'uiColumnDragged',
|
||||||
|
'uiColumnMoved',
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!permittedEvents.includes(source)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const columnState = columnApi.getColumnState();
|
||||||
|
|
||||||
|
callback({ columnState });
|
||||||
|
},
|
||||||
|
[callback]
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for sort and visible events
|
||||||
|
*/
|
||||||
|
const onColumnChange = useCallback(
|
||||||
|
({ columnApi }: SortChangedEvent | ColumnVisibleEvent) => {
|
||||||
|
const columnState = columnApi.getColumnState();
|
||||||
|
callback({ columnState });
|
||||||
|
},
|
||||||
|
[callback]
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for grid startup to apply stored column and filter states.
|
||||||
|
* State only applied if found, otherwise columns sized to fit available space
|
||||||
|
*/
|
||||||
const onGridReady = useCallback(
|
const onGridReady = useCallback(
|
||||||
({ api, columnApi }: GridReadyEvent) => {
|
({ api, columnApi }: FirstDataRenderedEvent) => {
|
||||||
if (!api || !columnApi) return;
|
if (!api || !columnApi) return;
|
||||||
|
|
||||||
if (state.columnState) {
|
if (state.columnState) {
|
||||||
@@ -46,7 +87,6 @@ export const useDataGridEvents = (
|
|||||||
applyOrder: true,
|
applyOrder: true,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// ensure columns fit available space if no widths are set
|
|
||||||
api.sizeColumnsToFit();
|
api.sizeColumnsToFit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,8 +99,12 @@ export const useDataGridEvents = (
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
onGridReady,
|
onGridReady,
|
||||||
onColumnResized: onGridChange,
|
// these events don't use the 'finished' flag
|
||||||
onFilterChanged: onGridChange,
|
onFilterChanged,
|
||||||
onSortChanged: onGridChange,
|
onSortChanged: onColumnChange,
|
||||||
|
onColumnVisible: onColumnChange,
|
||||||
|
// these trigger a lot so this callback uses the 'finished' flag
|
||||||
|
onColumnMoved: onDebouncedColumnChange,
|
||||||
|
onColumnResized: onDebouncedColumnChange,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Intent, Notification, Link } from '@vegaprotocol/ui-toolkit';
|
import { Intent, Notification } from '@vegaprotocol/ui-toolkit';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
|
|
||||||
interface ZeroBalanceErrorProps {
|
interface ZeroBalanceErrorProps {
|
||||||
@@ -6,13 +6,11 @@ interface ZeroBalanceErrorProps {
|
|||||||
id: string;
|
id: string;
|
||||||
symbol: string;
|
symbol: string;
|
||||||
};
|
};
|
||||||
onClickCollateral?: () => void;
|
|
||||||
onDeposit: (assetId: string) => void;
|
onDeposit: (assetId: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ZeroBalanceError = ({
|
export const ZeroBalanceError = ({
|
||||||
asset,
|
asset,
|
||||||
onClickCollateral,
|
|
||||||
onDeposit,
|
onDeposit,
|
||||||
}: ZeroBalanceErrorProps) => {
|
}: ZeroBalanceErrorProps) => {
|
||||||
return (
|
return (
|
||||||
@@ -25,12 +23,6 @@ export const ZeroBalanceError = ({
|
|||||||
'You need %s in your wallet to trade in this market. ',
|
'You need %s in your wallet to trade in this market. ',
|
||||||
asset.symbol
|
asset.symbol
|
||||||
)}
|
)}
|
||||||
{onClickCollateral && (
|
|
||||||
<>
|
|
||||||
{t('See all your')}{' '}
|
|
||||||
<Link onClick={onClickCollateral}>collateral</Link>.
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
buttonProps={{
|
buttonProps={{
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
useMarket,
|
useMarket,
|
||||||
useMarketPrice,
|
useMarketPrice,
|
||||||
} from '@vegaprotocol/markets';
|
} from '@vegaprotocol/markets';
|
||||||
import { AsyncRenderer, Splash } from '@vegaprotocol/ui-toolkit';
|
import { AsyncRendererInline } from '@vegaprotocol/ui-toolkit';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import { DealTicket } from './deal-ticket';
|
import { DealTicket } from './deal-ticket';
|
||||||
import { FLAGS } from '@vegaprotocol/environment';
|
import { FLAGS } from '@vegaprotocol/environment';
|
||||||
@@ -17,7 +17,6 @@ import { FLAGS } from '@vegaprotocol/environment';
|
|||||||
interface DealTicketContainerProps {
|
interface DealTicketContainerProps {
|
||||||
marketId: string;
|
marketId: string;
|
||||||
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
|
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
|
||||||
onClickCollateral?: () => void;
|
|
||||||
onDeposit: (assetId: string) => void;
|
onDeposit: (assetId: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +42,7 @@ export const DealTicketContainer = ({
|
|||||||
const { data: marketPrice } = useMarketPrice(market?.id);
|
const { data: marketPrice } = useMarketPrice(market?.id);
|
||||||
const create = useVegaTransactionStore((state) => state.create);
|
const create = useVegaTransactionStore((state) => state.create);
|
||||||
return (
|
return (
|
||||||
<AsyncRenderer
|
<AsyncRendererInline
|
||||||
data={market && marketData}
|
data={market && marketData}
|
||||||
loading={marketLoading || marketDataLoading}
|
loading={marketLoading || marketDataLoading}
|
||||||
error={marketError || marketDataError}
|
error={marketError || marketDataError}
|
||||||
@@ -66,10 +65,8 @@ export const DealTicketContainer = ({
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
) : (
|
) : (
|
||||||
<Splash>
|
<p>{t('Could not load market')}</p>
|
||||||
<p>{t('Could not load market')}</p>
|
|
||||||
</Splash>
|
|
||||||
)}
|
)}
|
||||||
</AsyncRenderer>
|
</AsyncRendererInline>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -74,7 +74,6 @@ export interface DealTicketProps {
|
|||||||
marketPrice?: string | null;
|
marketPrice?: string | null;
|
||||||
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
|
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
|
||||||
submit: (order: OrderSubmission) => void;
|
submit: (order: OrderSubmission) => void;
|
||||||
onClickCollateral?: () => void;
|
|
||||||
onDeposit: (assetId: string) => void;
|
onDeposit: (assetId: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +120,6 @@ export const DealTicket = ({
|
|||||||
marketData,
|
marketData,
|
||||||
marketPrice,
|
marketPrice,
|
||||||
submit,
|
submit,
|
||||||
onClickCollateral,
|
|
||||||
onDeposit,
|
onDeposit,
|
||||||
}: DealTicketProps) => {
|
}: DealTicketProps) => {
|
||||||
const { pubKey, isReadOnly } = useVegaWallet();
|
const { pubKey, isReadOnly } = useVegaWallet();
|
||||||
@@ -530,7 +528,6 @@ export const DealTicket = ({
|
|||||||
}
|
}
|
||||||
isReadOnly={isReadOnly}
|
isReadOnly={isReadOnly}
|
||||||
pubKey={pubKey}
|
pubKey={pubKey}
|
||||||
onClickCollateral={onClickCollateral}
|
|
||||||
onDeposit={onDeposit}
|
onDeposit={onDeposit}
|
||||||
/>
|
/>
|
||||||
<DealTicketButton side={side} />
|
<DealTicketButton side={side} />
|
||||||
@@ -566,7 +563,6 @@ interface SummaryMessageProps {
|
|||||||
margin: string;
|
margin: string;
|
||||||
isReadOnly: boolean;
|
isReadOnly: boolean;
|
||||||
pubKey: string | null;
|
pubKey: string | null;
|
||||||
onClickCollateral?: () => void;
|
|
||||||
onDeposit: (assetId: string) => void;
|
onDeposit: (assetId: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -596,7 +592,6 @@ const SummaryMessage = memo(
|
|||||||
margin,
|
margin,
|
||||||
isReadOnly,
|
isReadOnly,
|
||||||
pubKey,
|
pubKey,
|
||||||
onClickCollateral,
|
|
||||||
onDeposit,
|
onDeposit,
|
||||||
}: SummaryMessageProps) => {
|
}: SummaryMessageProps) => {
|
||||||
// Specific error UI for if balance is so we can
|
// Specific error UI for if balance is so we can
|
||||||
@@ -608,11 +603,7 @@ const SummaryMessage = memo(
|
|||||||
if (error?.type === SummaryValidationType.NoCollateral) {
|
if (error?.type === SummaryValidationType.NoCollateral) {
|
||||||
return (
|
return (
|
||||||
<div className="mb-2">
|
<div className="mb-2">
|
||||||
<ZeroBalanceError
|
<ZeroBalanceError asset={asset} onDeposit={onDeposit} />
|
||||||
asset={asset}
|
|
||||||
onClickCollateral={onClickCollateral}
|
|
||||||
onDeposit={onDeposit}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,17 +70,9 @@ export const DepositsTable = (
|
|||||||
</EtherscanLink>
|
</EtherscanLink>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
flex: 1,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
return (
|
return <AgGrid columnDefs={columnDefs} {...props} />;
|
||||||
<AgGrid
|
|
||||||
defaultColDef={{ flex: 1 }}
|
|
||||||
columnDefs={columnDefs}
|
|
||||||
style={{ width: '100%', height: '100%' }}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -371,6 +371,14 @@ function compileEnvVars() {
|
|||||||
'NX_TENDERMINT_WEBSOCKET_URL',
|
'NX_TENDERMINT_WEBSOCKET_URL',
|
||||||
process.env['NX_TENDERMINT_WEBSOCKET_URL']
|
process.env['NX_TENDERMINT_WEBSOCKET_URL']
|
||||||
),
|
),
|
||||||
|
CHROME_EXTENSION_URL: windowOrDefault(
|
||||||
|
'NX_CHROME_EXTENSION_URL',
|
||||||
|
process.env['NX_CHROME_EXTENSION_URL']
|
||||||
|
),
|
||||||
|
MOZILLA_EXTENSION_URL: windowOrDefault(
|
||||||
|
'NX_MOZILLA_EXTENSION_URL',
|
||||||
|
process.env['NX_MOZILLA_EXTENSION_URL']
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
return env;
|
return env;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user