Compare commits

..
Author SHA1 Message Date
Madalina Raicu fbcb7fc996 chore: update head 2023-08-16 12:14:43 +03:00
Madalina Raicu bb77e95c85 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into fix/metadata-console-try 2023-08-15 19:48:08 +03:00
Madalina Raicu b3b4ac36ab fix: remove manifest add title 2023-08-15 19:46:27 +03:00
Matthew Russell e4eedf5ccd feat(trading,datagrid): datagrid improvements (#4524) 2023-08-15 12:26:13 +01:00
Ben 20cbcb8302 chore(trading): remove home tests (#4551) 2023-08-14 18:06:36 +01:00
Joe Tsang cd3acf8ff9 test(explorer): successor market explorer (#4544) 2023-08-14 16:17:29 +01:00
Ben 30735388e8 chore(trading): remove asset tests (#4548) 2023-08-14 15:35:24 +01:00
Madalina Raicu 652ff66a13 fix: metadata console try 2023-08-14 14:34:36 +03:00
Madalina Raicu ccddfd3576 fix: metadata console try 2023-08-14 14:33:53 +03:00
Madalina Raicu 2efb6ab32f fix: metadata console try 2023-08-14 14:33:37 +03:00
Ben 478c4f83bb chore(trading): remove markets test (#4545) 2023-08-14 12:20:53 +01:00
Madalina Raicu 67ce576bc8 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2023-08-14 12:27:47 +03:00
JonRay15 431fab8824 chore(trading,governance): update feature-epic.md (#4528) 2023-08-14 09:43:00 +01:00
m.ray 83b6d3d295 feat(trading): metadata console (#4515) 2023-08-11 16:12:43 +00:00
Matthew Russell 98fd79bc35 fix(trading): prevent overflow in deal ticket if market fails to load (#4535) 2023-08-11 17:03:17 +01:00
Ben 39aa27f332 chore(trading): remove iceberg side order details (#4540) 2023-08-11 16:33:34 +01:00
Sam Keen bf4fb29fe6 fix(governance): fixes settlement oracle display in governance (#4534) 2023-08-11 10:08:31 +01:00
Maciek 5ed1befc53 fix(trading): remove redundant connect wallet button (#4538) 2023-08-11 10:34:32 +02:00
m.ray 1b311a8b36 fix(trading): order single view side (#4526) 2023-08-11 09:12:13 +01:00
Matthew Russell 70c3bc8128 chore(trading): remove floating buttons (#4512) 2023-08-10 16:02:46 +01:00
Joe Tsang 7e49836875 chore(governance): add e2e for successor market diff (#4519) 2023-08-10 15:03:23 +01:00
Maciek d624957e6d chore(trading): 4384 all markets in switcher (#4516) 2023-08-10 14:25:13 +01:00
Maciekandasiaznik 069b57d4ae feat(wallet): 4370 new connect wallet modal (#4492)
Co-authored-by: asiaznik <artur@vegaprotocol.io>
2023-08-10 13:03:53 +02:00
Madalina Raicu ab1a2cb222 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2023-08-07 16:22:11 +01:00
Madalina Raicu e1a1ae0fa1 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2023-08-07 10:16:03 +01:00
152 changed files with 2139 additions and 2121 deletions
+1 -1
View File
@@ -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
+1
View File
@@ -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',
+50 -6
View File
@@ -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

+20
View File
@@ -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"
}
+3
View File
@@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:
+27 -11
View File
@@ -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">
+1
View File
@@ -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
+1
View File
@@ -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);
+5 -1
View File
@@ -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,9 +22,12 @@ 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"
# Cosmic elevator flags # Cosmic elevator flags
NX_SUCCESSOR_MARKETS=true NX_SUCCESSOR_MARKETS=true
@@ -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')}
+20 -13
View File
@@ -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,
}; };
@@ -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 || '',
+1
View File
@@ -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;
});
});
});
-208
View File
@@ -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'
);
}); });
}); });
+3 -2
View File
@@ -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,9 +12,11 @@ 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
NX_STOP_ORDERS=true NX_STOP_ORDERS=true
# NX_ICEBERG_ORDERS # NX_ICEBERG_ORDERS
# NX_PRODUCT_PERPETUALS # NX_PRODUCT_PERPETUALS
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

+1
View File
@@ -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

+20
View File
@@ -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"
}
+3
View File
@@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:
+4 -7
View File
@@ -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 (
+22 -31
View File
@@ -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>
);
};
-3
View File
@@ -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,
}; };
+34 -1
View File
@@ -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" />
+10
View File
@@ -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);
+7 -7
View File
@@ -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}
+5 -9
View File
@@ -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}
/> />
); );
+2 -37
View File
@@ -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}
+2
View File
@@ -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'));
}); });
}; };
+34 -1
View File
@@ -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>
) : ( ) : (
+2 -2
View File
@@ -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);
}); });
}); });
+67 -23
View File
@@ -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>
); );
} }
+1 -9
View File
@@ -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