Compare commits

..
Author SHA1 Message Date
Edd 3e2ed0a680 fix(explorer-e2e): remove details check 2023-08-14 14:10:22 +01:00
Edd 6d570679f8 test(explorer): remove looping through all assets 2023-08-14 13:48:40 +01:00
Edd c402ec3a6e chore(explorer): enable skipped test 2023-08-14 13:48:40 +01:00
136 changed files with 1896 additions and 2077 deletions
+1 -1
View File
@@ -137,7 +137,7 @@ jobs:
secrets: inherit
with:
projects: ${{ needs.lint-test-build.outputs.projects-e2e }}
tags: '@smoke'
tags: '@smoke @regression'
publish-dist:
needs: lint-test-build
+1 -1
View File
@@ -20,7 +20,7 @@ jobs:
project: ${{ fromJSON(inputs.projects) }}
name: ${{ matrix.project }}
runs-on: self-hosted-runner
timeout-minutes: 120
timeout-minutes: 100
steps:
# Checks if skip cache was requested
- name: Set skip-nx-cache flag
-1
View File
@@ -23,7 +23,6 @@ module.exports = defineConfig({
viewportWidth: 1440,
viewportHeight: 900,
testIsolation: false,
experimentalMemoryManagement: true,
},
env: {
environment: 'CUSTOM',
@@ -31,17 +31,15 @@ context('Asset page', { tags: '@regression' }, () => {
});
});
it.skip('should open details page when clicked on "View details"', () => {
it('should open details page when clicked on "View details"', () => {
cy.getAssets().then((assets) => {
assets.forEach((asset) => {
cy.get(`[row-id="${asset.id}"] [col-id="actions"] button`)
.eq(0)
.should('contain.text', 'View details');
// Set to only click through one asset as the navigation could be
// causing a 'ResizeLoopObserver' error to be thrown inappropriately
assets.slice(0, 1).forEach((asset) => {
cy.get(`[row-id="${asset.id}"] [col-id="actions"] button`)
.eq(0)
.click();
cy.getByTestId('asset-header').should('have.text', asset.name);
cy.go('back');
});
});
});
+6 -50
View File
@@ -1,8 +1,8 @@
import { createSuccessorMarketProposal } from '../support/governance.functions';
context('Market page', { tags: '@regression' }, function () {
describe('Verify elements on page', function () {
const marketHeaders = 'markets-heading';
const createdMarketId =
'2eab0e66545a789047561bc5a2e5cbc3b19eb708da41104e3cac2474ee36c4d4';
before('Create market', function () {
cy.visit('/');
@@ -11,7 +11,7 @@ context('Market page', { tags: '@regression' }, function () {
beforeEach('Get market id', function () {
cy.navigate_to('markets');
cy.get('[col-id="id"]').last().invoke('text').as('createdMarketId');
cy.get('[col-id="id"]').eq(1).invoke('text').as('createdMarketId');
});
it('Market displayed on market page', function () {
@@ -106,7 +106,6 @@ context('Market page', { tags: '@regression' }, function () {
// Able to view Json
cy.contains('View JSON').click();
cy.get('.language-json').should('exist');
cy.getByTestId('icon-cross').click();
});
// Skipping due to resize observer loop limit error
@@ -114,60 +113,17 @@ context('Market page', { tags: '@regression' }, function () {
cy.common_switch_to_mobile_and_click_toggle();
cy.navigate_to('markets', true);
cy.getByTestId(marketHeaders).should('be.visible');
cy.get(`[row-id="${this.createdMarketId}"]`)
cy.get(`[row-id="${createdMarketId}"]`)
.should('be.visible')
.within(() => {
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('state').should('have.text', 'Pending');
cy.get_element_by_col_id('asset').should('have.text', 'fUSDC');
cy.get_element_by_col_id('id').should(
'have.text',
this.createdMarketId
);
cy.get_element_by_col_id('id').should('have.text', createdMarketId);
cy.get_element_by_col_id('actions')
.find('a')
.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
);
.should('have.attr', 'href', `/markets/${createdMarketId}`);
});
});
});
@@ -13,31 +13,28 @@ context('Proposal page', { tags: '@smoke' }, function () {
it('Able to view proposal', function () {
cy.navigate_to('governanceProposals');
cy.getByTestId(proposalHeading).should('be.visible');
cy.contains(proposalTitle)
.parent()
.parent()
.parent()
.within(() => {
cy.get_element_by_col_id('title').should('have.text', proposalTitle);
cy.get_element_by_col_id('type').should('have.text', 'NewMarket');
cy.get_element_by_col_id('state').should('have.text', 'Enacted');
cy.getByTestId('vote-progress').should('be.visible');
cy.get('[col-id="cDate"]')
.invoke('text')
.should('match', dateTimeRegex);
cy.get('[col-id="eDate"]')
.invoke('text')
.should('match', dateTimeRegex);
cy.getByTestId('external-link')
.should('have.attr', 'href')
.and('contains', 'https://governance.fairground.wtf/proposals/');
cy.contains('View terms').should('exist').click();
});
// get first proposal in list
cy.get('[row-index="0"]').within(() => {
cy.get_element_by_col_id('title').should('have.text', proposalTitle);
cy.get_element_by_col_id('type').should('have.text', 'NewMarket');
cy.get_element_by_col_id('state').should('have.text', 'Enacted');
cy.getByTestId('vote-progress').should('be.visible');
cy.get('[col-id="cDate"]')
.invoke('text')
.should('match', dateTimeRegex);
cy.get('[col-id="eDate"]')
.invoke('text')
.should('match', dateTimeRegex);
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.get('.language-json').should('exist');
});
it.skip('Proposal page displayed on mobile', function () {
it('Proposal page displayed on mobile', function () {
cy.common_switch_to_mobile_and_click_toggle();
cy.navigate_to('governanceProposals', true);
cy.getByTestId(proposalHeading).should('be.visible');
@@ -127,10 +127,3 @@ Cypress.Commands.add(
.should('have.text', tableRowValue);
}
);
Cypress.Commands.add(
'validate_proposal_change_type',
(tableRowName, changeType) => {
cy.contains(tableRowName).siblings().should('have.text', changeType);
}
);
@@ -1,130 +0,0 @@
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,
},
},
};
}
+2 -3
View File
@@ -1,4 +1,6 @@
# App configuration variables
NX_TENDERMINT_URL=http://localhost:26617
NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
NX_VEGA_ENV=CUSTOM
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
@@ -6,6 +8,3 @@ NX_VEGA_EXPLORER_URL=/
# App flags
NX_EXPLORER_TXS_LIST=0
NX_TENDERMINT_URL=http://localhost:26617
NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
+2 -3
View File
@@ -1,4 +1,6 @@
# App configuration variables
NX_TENDERMINT_URL=https://tm.be.devnet1.vega.xyz/
NX_TENDERMINT_WEBSOCKET_URL=wss://be.devnet1.vega.xyz/websocket
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
NX_VEGA_ENV=DEVNET
NX_BLOCK_EXPLORER=https://be.devnet1.vega.xyz/rest
@@ -8,6 +10,3 @@ NX_VEGA_URL=https://api.devnet1.vega.xyz/graphql
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_VEGA_EXPLORER_URL=/
NX_TENDERMINT_URL=https://tm.be.devnet1.vega.xyz/
NX_TENDERMINT_WEBSOCKET_URL=wss://be.devnet1.vega.xyz/websocket
+2 -3
View File
@@ -1,4 +1,6 @@
# App configuration variables
NX_TENDERMINT_URL=https://be.vega.community
NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket
NX_SENTRY_DSN=https://b3a56b03eda842faad731f3ea9dfd1bc@o286262.ingest.sentry.io/6242427
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/mainnet1/mainnet1.toml
NX_VEGA_URL=https://api.vega.community/graphql
@@ -9,6 +11,3 @@ NX_VEGA_GOVERNANCE_URL=https://governance.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz/
NX_VEGA_CONSOLE_URL=https://console.vega.xyz
NX_TENDERMINT_URL=https://be.vega.community
NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket
+3 -4
View File
@@ -1,4 +1,6 @@
# App configuration variables
NX_TENDERMINT_URL=https://be.mainnet-mirror.vega.rocks
NX_TENDERMINT_WEBSOCKET_URL=wss://be.mainnet-mirror.vega.rocks/websocket
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/mainnet-mirror/vegawallet-mainnet-mirror.toml
NX_VEGA_URL=https://api.mainnet-mirror.vega.rocks/graphql
@@ -8,7 +10,4 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_GOVERNANCE_URL=https://governance.mainnet-mirror.vega.rocks
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
NX_VEGA_EXPLORER_URL=https://explorer.mainnet-mirror.vega.rocks/
NX_VEGA_CONSOLE_URL=https://console.mainnet-mirror.vega.rocks
NX_TENDERMINT_URL=https://be.mainnet-mirror.vega.rocks
NX_TENDERMINT_WEBSOCKET_URL=wss://be.mainnet-mirror.vega.rocks/websocket
NX_VEGA_CONSOLE_URL=https://console.mainnet-mirror.vega.rocks
+2 -3
View File
@@ -1,5 +1,7 @@
# App configuration variables
NX_TENDERMINT_URL=https://tm.be.testnet.vega.xyz
NX_BLOCK_EXPLORER=https://be.testnet.vega.xyz/rest
NX_TENDERMINT_WEBSOCKET_URL=wss://be.testnet.vega.xyz/websocket
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/fairground/vegawallet-fairground.toml
NX_VEGA_ENV=TESTNET
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
@@ -9,6 +11,3 @@ NX_VEGA_GOVERNANCE_URL=https://governance.fairground.wtf
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
NX_VEGA_CONSOLE_URL=https://console.fairground.wtf
NX_TENDERMINT_URL=https://tm.be.testnet.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://be.testnet.vega.xyz/websocket
+2 -3
View File
@@ -7,10 +7,9 @@ NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_TENDERMINT_URL=https://tm.be.validators-testnet.vega.rocks
NX_BLOCK_EXPLORER=https://be.validators-testnet.vega.rocks/rest
NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.xyz/websocket
NX_VEGA_GOVERNANCE_URL=https://governance.validators-testnet.vega.rocks
NX_VEGA_EXPLORER_URL=https://explorer.validators-testnet.vega.rocks/
NX_VEGA_CONSOLE_URL=https://trading.validators-testnet.vega.rocks/
NX_TENDERMINT_URL=https://tm.be.validators-testnet.vega.rocks
NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.xyz/websocket
@@ -11,7 +11,6 @@ import { TxDetailsBatch } from './tx-batch';
import { TxDetailsChainEvent } from './tx-chain-event';
import { TxDetailsNodeVote } from './tx-node-vote';
import { TxDetailsOrderCancel } from './tx-order-cancel';
import { TxDetailsStopOrderCancel } from './tx-stop-order-cancel';
import { TxDetailsOrderAmend } from './tx-order-amend';
import { TxDetailsWithdrawSubmission } from './tx-withdraw-submission';
import { TxDetailsDelegate } from './tx-delegation';
@@ -86,8 +85,6 @@ function getTransactionComponent(txData?: BlockExplorerTransactionResult) {
return TxDetailsProtocolUpgrade;
case 'Cancel Order':
return TxDetailsOrderCancel;
case 'Stop Orders Cancellation':
return TxDetailsStopOrderCancel;
case 'Amend Order':
return TxDetailsOrderAmend;
case 'Validator Heartbeat':
@@ -1,60 +0,0 @@
import { t } from '@vegaprotocol/i18n';
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
import { MarketLink } from '../../links/';
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
import { TxDetailsShared } from './shared/tx-details-shared';
import { TableCell, TableRow, TableWithTbody } from '../../table';
import { CancelSummary } from '../../order-summary/order-cancellation';
import Hash from '../../links/hash';
import type { components } from '../../../../types/explorer';
export type StopOrderCancellationTransaction =
components['schemas']['v1StopOrdersCancellation'];
interface TxDetailsStopOrderCancelProps {
txData: BlockExplorerTransactionResult | undefined;
pubKey: string | undefined;
blockData: TendermintBlocksResponse | undefined;
}
/**
* Someone cancelled a stop order
*/
export const TxDetailsStopOrderCancel = ({
txData,
pubKey,
blockData,
}: TxDetailsStopOrderCancelProps) => {
if (!txData || !txData.command) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
const command: StopOrderCancellationTransaction =
txData.command.stopOrdersCancellation;
const { marketId, stopOrderId } = command;
return (
<TableWithTbody className="mb-8" allowWrap={true}>
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
<TableRow modifier="bordered">
<TableCell>{t('Cancel stop order')}</TableCell>
<TableCell>
{stopOrderId ? (
<Hash text={stopOrderId} />
) : (
<CancelSummary orderId={stopOrderId} marketId={marketId} />
)}
</TableCell>
</TableRow>
{marketId ? (
<TableRow modifier="bordered">
<TableCell>{t('Market')}</TableCell>
<TableCell>
<MarketLink id={marketId} />
</TableCell>
</TableRow>
) : null}
</TableWithTbody>
);
};
@@ -34,7 +34,6 @@ export type FilterOption =
| 'Protocol Upgrade'
| 'Register new Node'
| 'State Variable Proposal'
| 'Stop Orders Cancellation'
| 'Submit Oracle Data'
| 'Submit Order'
| 'Transfer Funds'
@@ -54,7 +53,6 @@ export const PrimaryFilterOptions: FilterOption[] = [
'Delegate',
'Liquidity Provision Order',
'Proposal',
'Stop Orders Cancellation',
'Submit Oracle Data',
'Submit Order',
'Transfer Funds',
-9
View File
@@ -22,11 +22,6 @@ import { Footer } from '../components/footer/footer';
import { Header } from '../components/header';
import { Routes } from './route-names';
import { useExplorerNodeNamesLazyQuery } from './validators/__generated__/NodeNames';
import {
ProtocolUpgradeCountdownMode,
ProtocolUpgradeInProgressNotification,
ProtocolUpgradeProposalNotification,
} from '@vegaprotocol/proposals';
const DialogsContainer = () => {
const { isOpen, id, trigger, asJson, setOpen } = useAssetDetailsDialogStore();
@@ -67,10 +62,6 @@ export const Layout = () => {
/>
)}
<Header />
<ProtocolUpgradeProposalNotification
mode={ProtocolUpgradeCountdownMode.IN_ESTIMATED_TIME_REMAINING}
/>
<ProtocolUpgradeInProgressNotification />
</div>
<div className={fixedWidthClasses}>
<main className="p-4">
+1 -1
View File
@@ -17,7 +17,7 @@
<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:card" content="summary_large_image" />
<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" />
-1
View File
@@ -28,7 +28,6 @@ module.exports = defineConfig({
numTestsKeptInMemory: 5,
downloadsFolder: 'cypress/downloads',
testIsolation: false,
experimentalMemoryManagement: true,
},
env: {
ethProviderUrl: 'http://localhost:8545/',
@@ -55,12 +55,12 @@ describe(
before('connect wallets and set approval limit', function () {
cy.visit('/');
ethereumWalletConnect();
// cy.associateTokensToVegaWallet('1');
});
beforeEach('visit proposals tab', function () {
cy.clearLocalStorage();
turnTelemetryOff();
cy.mockChainId();
cy.reload();
waitForSpinner();
cy.connectVegaWallet();
@@ -42,7 +42,6 @@ context(
beforeEach('visit proposals', function () {
cy.clearLocalStorage();
turnTelemetryOff();
cy.mockChainId();
cy.reload();
waitForSpinner();
cy.connectVegaWallet();
@@ -82,7 +82,6 @@ context(
cy.clearLocalStorage();
turnTelemetryOff();
cy.reload();
cy.mockChainId();
waitForSpinner();
cy.connectVegaWallet();
ethereumWalletConnect();
@@ -74,7 +74,6 @@ context(
beforeEach('visit governance tab', function () {
cy.clearLocalStorage();
turnTelemetryOff();
cy.mockChainId();
cy.reload();
waitForSpinner();
cy.connectVegaWallet();
@@ -42,7 +42,6 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
cy.clearLocalStorage();
turnTelemetryOff();
cy.reload();
cy.mockChainId();
waitForSpinner();
cy.connectVegaWallet();
ethereumWalletConnect();
@@ -26,7 +26,6 @@ context('rewards - flow', { tags: '@slow' }, function () {
before('set up environment to allow rewards', function () {
cy.clearLocalStorage();
turnTelemetryOff();
cy.mockChainId();
cy.visit('/');
waitForSpinner();
ethereumWalletConnect();
@@ -25,6 +25,8 @@ import {
vegaWalletSetSpecifiedApprovalAmount,
vegaWalletTeardown,
} from '../../support/wallet-functions';
import { aliasGQLQuery } from '@vegaprotocol/cypress';
import { chainIdQuery, statisticsQuery } from '@vegaprotocol/mock';
const stakeValidatorListTotalStake = 'total-stake';
const stakeValidatorListTotalShare = 'total-stake-share';
@@ -56,6 +58,10 @@ context(
function () {
// 1002-STKE-002, 1002-STKE-032
before('visit staking tab and connect vega wallet', function () {
cy.mockGQL((req) => {
aliasGQLQuery(req, 'ChainId', chainIdQuery());
aliasGQLQuery(req, 'Statistics', statisticsQuery());
});
cy.visit('/');
ethereumWalletConnect();
cy.connectVegaWallet();
@@ -66,9 +72,12 @@ context(
beforeEach(
'teardown wallet & drill into a specific validator',
function () {
cy.mockGQL((req) => {
aliasGQLQuery(req, 'ChainId', chainIdQuery());
aliasGQLQuery(req, 'Statistics', statisticsQuery());
});
cy.clearLocalStorage();
turnTelemetryOff();
cy.mockChainId();
// Go to homepage to allow wallet teardown without epoch timer refreshing page
navigateTo(navigation.home);
vegaWalletTeardown();
@@ -56,7 +56,6 @@ context(
function () {
cy.clearLocalStorage();
turnTelemetryOff();
cy.mockChainId();
cy.reload();
waitForSpinner();
cy.connectVegaWallet();
@@ -6,6 +6,8 @@ import {
} from '../../support/common.functions';
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
import { depositAsset } from '../../support/wallet-functions';
import { aliasGQLQuery } from '@vegaprotocol/cypress';
import { chainIdQuery, statisticsQuery } from '@vegaprotocol/mock';
const withdraw = 'withdraw';
const withdrawalForm = 'withdraw-form';
@@ -29,7 +31,6 @@ const toastPanel = 'toast-panel';
const toastClose = 'toast-close';
const withdrawalDialogContent = 'dialog-content';
const toastCompleteWithdrawal = 'toast-complete-withdrawal';
const scrollBar = '.ag-body-horizontal-scroll-viewport';
const usdtName = 'USDC (local)';
const usdcEthAddress = '0x1b8a1B6CBE5c93609b46D1829Cc7f3Cb8eeE23a0';
const usdcSymbol = 'tUSDC';
@@ -43,15 +44,22 @@ context(
{ tags: '@slow' },
function () {
before('visit withdrawals and connect vega wallet', function () {
cy.mockGQL((req) => {
aliasGQLQuery(req, 'ChainId', chainIdQuery());
aliasGQLQuery(req, 'Statistics', statisticsQuery());
});
cy.visit('/');
ethereumWalletConnect();
depositAsset(usdcEthAddress, '1000', 5);
});
beforeEach('Navigate to withdrawal page', function () {
cy.mockGQL((req) => {
aliasGQLQuery(req, 'ChainId', chainIdQuery());
aliasGQLQuery(req, 'Statistics', statisticsQuery());
});
cy.clearLocalStorage();
turnTelemetryOff();
cy.mockChainId();
cy.reload();
waitForSpinner();
navigateTo(navigation.withdraw);
@@ -98,8 +106,7 @@ context(
});
});
// eslint-disable-next-line
it.skip(
it(
'Able to withdraw asset: -eth wallet connected -withdraw funds button',
{ tags: '@smoke' },
function () {
@@ -200,17 +207,20 @@ context(
);
cy.getByTestId(toastClose).click();
});
cy.get("[row-id='0']").within(() => {
cy.get(tableAssetSymbol).should('have.text', usdcSymbol);
cy.get(tableAmount).should('have.text', '110.00');
cy.get(tableReceiverAddress)
.find('a')
.should('have.attr', 'href')
.and('contain', 'https://sepolia.etherscan.io/address/');
cy.get(tableCreatedTimeStamp).should('not.be.empty');
});
cy.get(tableTxHash)
.eq(1)
.should('have.text', 'Complete withdrawal')
.parent()
.within(() => {
cy.get(tableAssetSymbol).should('have.text', usdcSymbol);
cy.get(tableAmount).should('have.text', '110.00');
cy.get(tableReceiverAddress)
.find('a')
.should('have.attr', 'href')
.and('contain', 'https://sepolia.etherscan.io/address/');
cy.get(tableCreatedTimeStamp).should('not.be.empty');
});
ethereumWalletConnect();
cy.get(scrollBar).scrollTo('right');
cy.getByTestId(completeWithdrawalButton).first().click();
cy.getByTestId(toast)
.last(txTimeout)
@@ -231,7 +231,7 @@ context(
});
// 3009-NTWU-001 3009-NTWU-002 3009-NTWU-006 3009-NTWU-009
it.skip('should display network upgrade banner with estimate', function () {
it('should display network upgrade banner with estimate', function () {
mockNetworkUpgradeProposal();
cy.visit('/');
cy.getByTestId('banners').within(() => {
@@ -84,10 +84,9 @@ export function stakingPageAssociateTokens(
.length
) {
cy.get(tokenInputApprove, txTimeout).should('be.enabled').click();
cy.contains(
'Approve $VEGA Tokens for staking on Vega',
txTimeout
).should('be.visible');
cy.contains('Approve $VEGA Tokens for staking on Vega').should(
'be.visible'
);
cy.contains(
'Approve $VEGA Tokens for staking on Vega',
txTimeout
@@ -6,7 +6,6 @@ import { Nav } from '../nav';
import { Networks, useEnvironment } from '@vegaprotocol/environment';
import {
ProtocolUpgradeCountdownMode,
ProtocolUpgradeInProgressNotification,
ProtocolUpgradeProposalNotification,
} from '@vegaprotocol/proposals';
import { ViewingAsBanner } from '@vegaprotocol/ui-toolkit';
@@ -50,7 +49,6 @@ const NotificationsContainer = () => {
<ProtocolUpgradeProposalNotification
mode={ProtocolUpgradeCountdownMode.IN_ESTIMATED_TIME_REMAINING}
/>
<ProtocolUpgradeInProgressNotification />
{isReadOnly ? (
<ViewingAsBanner pubKey={pubKey} disconnect={disconnect} />
) : null}
@@ -626,8 +626,7 @@
"status-tendermint": "Consensus",
"status-ersatz": "Standby",
"status-pending": "Candidate",
"ersatzDescription1": "To be promoted, a standby validator must have more than the lowest consensus stake, plus a bonus given to existing validators, and only one standby validator can be promoted per epoch. Currently this requires a minimum of",
"ersatzDescription2": "stake assuming no performance penalty incurred.",
"ersatzDescription": "To be promoted, a standby validator must have more than the lowest consensus stake, plus a bonus given to existing validators. This currently requires a minimum of {{stakeNeededForPromotion}} stake assuming no penalties. Only one validator per epoch can be promoted.",
"pendingDescription1": "Anyone can",
"pendingDescriptionLinkText": "set up and run a node on Vega",
"pendingDescription2": ". A node can move from being a candidate into standby based on how much nomination it attracts, assuming it has proven reliability by sending heartbeats to the network.",
@@ -785,7 +784,6 @@
"PerformancePenaltyDescription": "Performance score is a measure of how often a validator proposed blocks in the last epoch relative to how many they should be expected to propose based on their voting power. Performance penalty is applied for having a performance score of less than 1",
"UnnormalisedVotingPowerDescription": "The voting power of the validator based on their final validator score after all penalties have been applied",
"NormalisedVotingPowerDescription": "The voting power of the validator, adjusted to ensure all validator scores sum to 1, used for distribution of rewards",
"NonConsensusVotingPowerDescription": "The voting power of the validator. Only consensus validators have voting power",
"Score": "Score",
"performancePenalty": "Performance penalty",
"overstaked": "Overstaked",
+1 -1
View File
@@ -17,7 +17,7 @@
<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:card" content="summary_large_image" />
<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" />
@@ -24,7 +24,6 @@ import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
import type { MockedResponse } from '@apollo/client/testing';
import { FLAGS } from '@vegaprotocol/environment';
import { BrowserRouter } from 'react-router-dom';
import { VoteState } from '../vote-details/use-user-vote';
jest.mock('@vegaprotocol/proposals', () => ({
...jest.requireActual('@vegaprotocol/proposals'),
@@ -37,8 +36,7 @@ jest.mock('@vegaprotocol/proposals', () => ({
const renderComponent = (
proposal: ProposalQuery['proposal'],
isListItem = true,
mocks: MockedResponse[] = [],
voteState?: VoteState
mocks: MockedResponse[] = []
) =>
render(
<AppStateProvider>
@@ -49,7 +47,6 @@ const renderComponent = (
proposal={proposal}
isListItem={isListItem}
networkParams={mockNetworkParams}
voteState={voteState}
/>
</VegaWalletContext.Provider>
</MockedProvider>
@@ -389,15 +386,10 @@ describe('Proposal header', () => {
closingDatetime: nextWeek.toString(),
},
});
renderComponent(
proposal,
true,
[
// @ts-ignore generateProposal always creates an id
createUserVoteQueryMock(proposal.id, VoteValue.VALUE_NO),
],
VoteState.No
);
renderComponent(proposal, true, [
// @ts-ignore generateProposal always creates an id
createUserVoteQueryMock(proposal.id, VoteValue.VALUE_NO),
]);
expect(await screen.findByTestId('user-voted-no')).toBeInTheDocument();
});
@@ -408,15 +400,10 @@ describe('Proposal header', () => {
closingDatetime: nextWeek.toString(),
},
});
renderComponent(
proposal,
true,
[
// @ts-ignore generateProposal always creates an id
createUserVoteQueryMock(proposal.id, VoteValue.VALUE_YES),
],
VoteState.Yes
);
renderComponent(proposal, true, [
// @ts-ignore generateProposal always creates an id
createUserVoteQueryMock(proposal.id, VoteValue.VALUE_YES),
]);
expect(await screen.findByTestId('user-voted-yes')).toBeInTheDocument();
});
});
@@ -8,26 +8,25 @@ import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
import { truncateMiddle } from '../../../../lib/truncate-middle';
import { CurrentProposalState } from '../current-proposal-state';
import { ProposalInfoLabel } from '../proposal-info-label';
import { useUserVote } from '../vote-details/use-user-vote';
import { ProposalVotingStatus } from '../proposal-voting-status';
import type { NetworkParamsResult } from '@vegaprotocol/network-parameters';
import { useSuccessorMarketProposalDetails } from '@vegaprotocol/proposals';
import { FLAGS } from '@vegaprotocol/environment';
import Routes from '../../../routes';
import { Link } from 'react-router-dom';
import type { VoteState } from '../vote-details/use-user-vote';
export const ProposalHeader = ({
proposal,
networkParams,
isListItem = true,
voteState,
}: {
proposal: ProposalFieldsFragment | ProposalQuery['proposal'];
networkParams: Partial<NetworkParamsResult>;
isListItem?: boolean;
voteState?: VoteState | null;
}) => {
const { t } = useTranslation();
const { voteState } = useUserVote(proposal?.id);
const change = proposal?.terms.change;
let details: ReactNode;
@@ -1,6 +1,4 @@
import { MemoryRouter } from 'react-router-dom';
import { MockedProvider } from '@apollo/client/testing';
import { VegaWalletProvider } from '@vegaprotocol/wallet';
import { render, screen } from '@testing-library/react';
import { generateProposal } from '../../test-helpers/generate-proposals';
import { Proposal } from './proposal';
@@ -46,15 +44,11 @@ jest.mock('../list-asset', () => ({
const renderComponent = (proposal: ProposalQuery['proposal']) => {
render(
<MemoryRouter>
<MockedProvider>
<VegaWalletProvider>
<Proposal
restData={{}}
proposal={proposal as ProposalQuery['proposal']}
networkParams={mockNetworkParams}
/>
</VegaWalletProvider>
</MockedProvider>
<Proposal
restData={{}}
proposal={proposal as ProposalQuery['proposal']}
networkParams={mockNetworkParams}
/>
</MemoryRouter>
);
};
@@ -19,8 +19,6 @@ import { removePaginationWrapper } from '@vegaprotocol/utils';
import { ProposalState } from '@vegaprotocol/types';
import { ProposalMarketChanges } from '../proposal-market-changes';
import type { NetworkParamsResult } from '@vegaprotocol/network-parameters';
import { useVoteSubmit } from '@vegaprotocol/proposals';
import { useUserVote } from '../vote-details/use-user-vote';
export enum ProposalType {
PROPOSAL_NEW_MARKET = 'PROPOSAL_NEW_MARKET',
@@ -55,8 +53,6 @@ export const Proposal = ({
mostRecentlyEnactedAssociatedMarketProposal,
}: ProposalProps) => {
const { t } = useTranslation();
const { submit, Dialog, finalizedVote } = useVoteSubmit();
const { voteState, voteDatetime } = useUserVote(proposal?.id, finalizedVote);
if (!proposal) {
return null;
@@ -136,12 +132,10 @@ export const Proposal = ({
</div>
)}
</div>
<ProposalHeader
proposal={proposal}
isListItem={false}
networkParams={networkParams}
voteState={voteState}
/>
<div id="details">
@@ -213,10 +207,6 @@ export const Proposal = ({
spamProtectionMinTokens={
networkParams?.spam_protection_voting_min_tokens
}
submit={submit}
dialog={Dialog}
voteState={voteState}
voteDatetime={voteDatetime}
/>
</RoundedWrapper>
</div>
@@ -1,7 +1,6 @@
import { RoundedWrapper } from '@vegaprotocol/ui-toolkit';
import { ProposalHeader } from '../proposal-detail-header/proposal-header';
import { ProposalsListItemDetails } from './proposals-list-item-details';
import { useUserVote } from '../vote-details/use-user-vote';
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
import type { NetworkParamsResult } from '@vegaprotocol/network-parameters';
@@ -15,17 +14,12 @@ export const ProposalsListItem = ({
proposal,
networkParams,
}: ProposalsListItemProps) => {
const { voteState } = useUserVote(proposal?.id);
if (!proposal || !proposal.id || !networkParams) return null;
return (
<li id={proposal.id} data-testid="proposals-list-item">
<RoundedWrapper paddingBottom={true} heightFull={true}>
<ProposalHeader
proposal={proposal}
networkParams={networkParams}
voteState={voteState}
/>
<ProposalHeader proposal={proposal} networkParams={networkParams} />
<ProposalsListItemDetails proposal={proposal} />
</RoundedWrapper>
</li>
@@ -188,7 +188,11 @@ export const VoteButtons = ({
(voteState === VoteState.Yes || voteState === VoteState.No) && (
<p data-testid="you-voted">
<span>{t('youVoted')}:</span>{' '}
<span className="text-white font-bold">
<span
className={
voteState === VoteState.Yes ? 'text-success' : 'text-danger'
}
>
{t(`voteState_${voteState}`)}
</span>{' '}
{voteDatetime ? (
@@ -3,29 +3,23 @@ import { formatDistanceToNow } from 'date-fns';
import { RoundedWrapper, Icon, ExternalLink } from '@vegaprotocol/ui-toolkit';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { ProposalState } from '@vegaprotocol/types';
import { VoteProgress } from '@vegaprotocol/proposals';
import { useVoteSubmit, VoteProgress } from '@vegaprotocol/proposals';
import { formatNumber } from '../../../../lib/format-number';
import { ConnectToVega } from '../../../../components/connect-to-vega';
import { useVoteInformation } from '../../hooks';
import { useUserVote } from './use-user-vote';
import { CurrentProposalStatus } from '../current-proposal-status';
import { VoteButtonsContainer } from './vote-buttons';
import { SubHeading } from '../../../../components/heading';
import { ProposalType } from '../proposal/proposal';
import type { VoteValue } from '@vegaprotocol/types';
import type { DialogProps } from '@vegaprotocol/wallet';
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
import type { VoteState } from './use-user-vote';
interface VoteDetailsProps {
proposal: ProposalFieldsFragment | ProposalQuery['proposal'];
minVoterBalance: string | null | undefined;
spamProtectionMinTokens: string | null | undefined;
proposalType: ProposalType | null;
submit: (voteValue: VoteValue, proposalId: string | null) => Promise<void>;
dialog: (props: DialogProps) => JSX.Element;
voteState: VoteState | null;
voteDatetime: Date | null;
}
export const VoteDetails = ({
@@ -33,10 +27,6 @@ export const VoteDetails = ({
minVoterBalance,
spamProtectionMinTokens,
proposalType,
submit,
dialog,
voteState,
voteDatetime,
}: VoteDetailsProps) => {
const { pubKey } = useVegaWallet();
const {
@@ -58,7 +48,8 @@ export const VoteDetails = ({
} = useVoteInformation({ proposal });
const { t } = useTranslation();
const { submit, Dialog, finalizedVote } = useVoteSubmit();
const { voteState, voteDatetime } = useUserVote(proposal?.id, finalizedVote);
const defaultDecimals = 2;
const daysLeft = t('daysLeft', {
daysLeft: formatDistanceToNow(new Date(proposal?.terms.closingDatetime)),
@@ -228,7 +219,7 @@ export const VoteDetails = ({
spamProtectionMinTokens={spamProtectionMinTokens}
className="flex"
submit={submit}
dialog={dialog}
dialog={Dialog}
/>
)
) : (
@@ -389,10 +389,10 @@ export const ConsensusValidatorsTable = ({
},
{
field: ValidatorFields.NORMALISED_VOTING_POWER,
headerName: t('votingPower').toString(),
headerName: t(ValidatorFields.NORMALISED_VOTING_POWER).toString(),
headerTooltip: t('NormalisedVotingPowerDescription').toString(),
cellRenderer: VotingPowerRenderer,
width: 120,
width: 200,
},
{
field: ValidatorFields.TOTAL_PENALTIES,
@@ -20,7 +20,6 @@ import {
TotalStakeRenderer,
StakeShareRenderer,
PendingStakeRenderer,
VotingPowerRenderer,
} from './shared';
import type { AgGridReact } from 'ag-grid-react';
import type { ColDef } from 'ag-grid-community';
@@ -40,6 +39,7 @@ interface StandbyPendingValidatorsTableProps extends ValidatorsTableProps {
export const StandbyPendingValidatorsTable = ({
data,
previousEpochData,
totalStake,
stakeNeededForPromotion,
stakeNeededForPromotionDescription,
validatorsView,
@@ -132,8 +132,6 @@ export const StandbyPendingValidatorsTable = ({
name,
},
[ValidatorFields.STAKE]: stakedTotal,
[ValidatorFields.NORMALISED_VOTING_POWER]: '0%',
[ValidatorFields.UNNORMALISED_VOTING_POWER]: '0%',
[ValidatorFields.STAKE_NEEDED_FOR_PROMOTION]:
individualStakeNeededForPromotion || null,
[ValidatorFields.STAKE_NEEDED_FOR_PROMOTION_DESCRIPTION]:
@@ -225,14 +223,7 @@ export const StandbyPendingValidatorsTable = ({
headerName: t(ValidatorFields.STAKE_SHARE).toString(),
headerTooltip: t('StakeShareDescription').toString(),
cellRenderer: StakeShareRenderer,
width: 120,
},
{
field: ValidatorFields.NORMALISED_VOTING_POWER,
headerName: t('votingPower').toString(),
headerTooltip: t('NonConsensusVotingPowerDescription').toString(),
cellRenderer: VotingPowerRenderer,
width: 120,
width: 100,
},
// {
// field: ValidatorFields.STAKE_NEEDED_FOR_PROMOTION,
@@ -17,10 +17,6 @@ import type { PreviousEpochQuery } from '../../__generated__/PreviousEpoch';
import type { StakingQuery } from '../../__generated__/Staking';
import type { StakingDelegationFieldsFragment } from '../../__generated__/Staking';
import type { ValidatorWithUserData } from './shared';
import {
NetworkParams,
useNetworkParams,
} from '@vegaprotocol/network-parameters';
export interface ValidatorsTableProps {
nodesData: NodesQuery | undefined;
@@ -45,9 +41,6 @@ export const ValidatorTables = ({
const {
appState: { decimals },
} = useAppState();
const { params } = useNetworkParams([
NetworkParams.network_validators_incumbentBonus,
]);
const [validatorsView, setValidatorsView] = useState<ValidatorsView>('all');
const totalStake = useMemo(
@@ -59,10 +52,6 @@ export const ValidatorTables = ({
() => userStakingData?.party?.stakingSummary.currentStakeAvailable || '0',
[userStakingData?.party?.stakingSummary.currentStakeAvailable]
);
const incumbentBonus = useMemo(
() => new BigNumber(params?.network_validators_incumbentBonus),
[params?.network_validators_incumbentBonus]
);
let stakeNeededForPromotion = undefined;
let delegations: StakingDelegationFieldsFragment[] | undefined = undefined;
@@ -137,23 +126,28 @@ export const ValidatorTables = ({
consensusValidators.length &&
(standbyValidators.length || pendingValidators.length)
) {
const lowestConsensusStake = consensusValidators.reduce(
const lowestRankingConsensusScore = consensusValidators.reduce(
(lowest: ValidatorWithUserData, validator: ValidatorWithUserData) => {
if (Number(validator.stakedTotal) < Number(lowest.stakedTotal)) {
if (
Number(validator.rankingScore.rankingScore) <
Number(lowest.rankingScore.rankingScore)
) {
lowest = validator;
}
return lowest;
}
).stakedTotal;
).rankingScore.rankingScore;
const lowestRankingBigNum = toBigNum(lowestConsensusStake, decimals);
const lowestRankingBigNum = toBigNum(lowestRankingConsensusScore, 0);
const consensusStakedTotal = consensusValidators.reduce((acc, cur) => {
return acc.plus(toBigNum(cur.stakedTotal, decimals));
}, new BigNumber(0));
stakeNeededForPromotion = formatNumber(
lowestRankingBigNum.multipliedBy(incumbentBonus.plus(1)),
lowestRankingBigNum.times(consensusStakedTotal),
2
).toString();
}
return (
<section data-testid="validator-tables">
<div className="grid w-full justify-end">
@@ -193,18 +187,12 @@ export const ValidatorTables = ({
<div className="mb-10">
<SubHeading title={t('status-ersatz')} />
<p>
<span>
<Trans i18nKey="ersatzDescription1" />
</span>
<span className="text-white font-bold">
{' '}
{stakeNeededForPromotion}{' '}
</span>
<span>
<Trans i18nKey="ersatzDescription2" />
</span>
<Trans
i18nKey="ersatzDescription"
values={{
stakeNeededForPromotion,
}}
/>
</p>
<StandbyPendingValidatorsTable
data={standbyValidators}
+1 -1
View File
@@ -68,7 +68,7 @@ export const calculateOverstakedPenalty = (nodeId: string, nodes: Node[]) => {
}
const penalty = new BigNumber(1)
.minus(
new BigNumber(node.rewardScore?.rawValidatorScore || 1).dividedBy(tts)
new BigNumber(node.rewardScore?.rawValidatorScore || 0).dividedBy(tts)
)
.times(100);
return penalty.isLessThan(0) ? new BigNumber(0) : penalty;
-1
View File
@@ -26,7 +26,6 @@ module.exports = defineConfig({
requestTimeout: 20000,
retries: 1,
testIsolation: false,
experimentalMemoryManagement: true,
},
env: {
ETHERSCAN_URL: 'https://sepolia.etherscan.io',
@@ -0,0 +1,177 @@
// #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;
});
});
});
@@ -0,0 +1,15 @@
describe('charts', { tags: '@smoke' }, () => {
before(() => {
cy.mockTradingPage();
cy.mockSubscription();
cy.setOnBoardingViewed();
cy.visit('/#/markets/market-0');
cy.wait('@Markets');
});
it('can see market depth chart', () => {
// 6006-DEPC-001
cy.getByTestId('Depth').click();
cy.getByTestId('tab-depth').should('be.visible');
});
});
@@ -256,7 +256,6 @@ describe('Closed markets', { tags: '@smoke' }, () => {
cy.get(rowSelector)
.first()
.find('[col-id="code"]')
.find('[data-testid="market-code"]')
.should('have.text', settledMarket.tradableInstrument.instrument.code);
// 6001-MARK-002
+207
View File
@@ -0,0 +1,207 @@
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.url().should('eq', Cypress.config().baseUrl + `/#/markets/all`);
cy.window().then((window) => {
// @ts-ignore stub it out just for test case
window.vega = {};
cy.getByTestId('get-started-button').click();
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');
});
});
});
});
@@ -4,8 +4,7 @@ import * as Schema from '@vegaprotocol/types';
const rowSelector =
'[data-testid="tab-open-markets"] .ag-center-cols-container .ag-row';
const colInstrumentCode =
'[col-id="tradableInstrument.instrument.code"] [data-testid="market-code"]';
const colInstrumentCode = '[col-id="tradableInstrument.instrument.code"]';
describe('markets all table', { tags: '@smoke' }, () => {
beforeEach(() => {
@@ -40,25 +40,21 @@ describe('markets selector', { tags: '@smoke' }, () => {
code: 'SOLUSD',
markPrice: '84.41',
vol: '0.00',
productType: 'Futr',
},
{
code: 'ETHBTC.QM21',
markPrice: '46,126.90058',
vol: '0.00',
productType: 'Futr',
},
{
code: 'BTCUSD.MF21',
markPrice: '46,126.90058',
vol: '0.00',
productType: 'Futr',
},
{
code: 'AAPL.MF21',
markPrice: '46,126.90058',
vol: '0.00',
productType: 'Futr',
},
];
cy.getByTestId('header-title').should('be.visible').click();
@@ -68,9 +64,7 @@ describe('markets selector', { tags: '@smoke' }, () => {
const market = data[i];
// 6001-MARK-021
// 6001-MARK-022
expect(item.find('h3').text()).equals(
`${market.code} ${market.productType}`
);
expect(item.find('h3').text()).equals(market.code);
expect(
item.find('[data-testid="market-selector-volume"]').text()
).contains(market.vol);
@@ -3,7 +3,7 @@ import type { ProposalsListQuery } from '@vegaprotocol/proposals';
const rowSelector =
'[data-testid="tab-proposed-markets"] .ag-center-cols-container .ag-row';
const colMarketId = '[col-id="market"] [data-testid="market-code"]';
const colMarketId = '[col-id="market"]';
describe('markets proposed table', { tags: '@smoke' }, () => {
before(() => {
@@ -155,13 +155,7 @@ describe('markets proposed table', { tags: '@smoke' }, () => {
'AAVEDAI.MF21',
'AAPL.MF21',
];
checkSorting(
'market',
marketColDefault,
marketColAsc,
marketColDesc,
' [data-testid="market-code"]'
);
checkSorting('market', marketColDefault, marketColAsc, marketColDesc);
const stateColDefault = [
'Open',
@@ -223,7 +217,7 @@ describe('no markets proposed', { tags: '@smoke', testIsolation: true }, () => {
cy.setOnBoardingViewed();
});
it.skip('can see no markets message', () => {
it('can see no markets message', () => {
cy.visit('/#/markets/all');
cy.get('[data-testid="Proposed markets"]').click();
@@ -120,9 +120,7 @@ describe('orders list', { tags: '@smoke', testIsolation: true }, () => {
cy.getByTestId('All').click();
cy.getByTestId('tab-orders')
.get(
`.ag-center-cols-container [col-id='${orderSymbol}'] [data-testid="market-code"]`
)
.get(`.ag-center-cols-container [col-id='${orderSymbol}']`)
.should('have.length.at.least', expectedOrderList.length)
.then(($symbols) => {
const symbolNames: string[] = [];
@@ -447,7 +445,8 @@ describe('amend and cancel order', { tags: '@smoke' }, () => {
liquidityProvisionId: null,
});
cy.get(`[row-id=${orderId}]`)
.find('[data-testid="icon-edit"]')
.find('[data-testid="edit"]')
.should('have.text', 'Edit')
.then(($btn) => {
cy.wrap($btn).click();
cy.getByTestId('dialog-title').should('have.text', 'Edit order');
@@ -475,7 +474,8 @@ describe('amend and cancel order', { tags: '@smoke' }, () => {
liquidityProvisionId: null,
});
cy.get(`[row-id=${orderId}]`)
.find(`[data-testid="icon-cross"]`)
.find(`[data-testid="cancel"]`)
.should('have.text', 'Cancel')
.then(($btn) => {
cy.wrap($btn).click({ force: true });
const order: OrderCancellation = {
@@ -512,7 +512,8 @@ describe('amend and cancel order', { tags: '@smoke' }, () => {
liquidityProvisionId: null,
});
cy.get(`[row-id=${orderId}]`)
.find('[data-testid="icon-edit"]')
.find('[data-testid="edit"]')
.should('have.text', 'Edit')
.then(($btn) => {
cy.wrap($btn).click({ force: true });
cy.getByTestId('dialog-title').should('have.text', 'Edit order');
@@ -0,0 +1,370 @@
import { checkSorting, aliasGQLQuery } from '@vegaprotocol/cypress';
import { marketsDataQuery } from '@vegaprotocol/mock';
import { positionsQuery } from '@vegaprotocol/mock';
// #region consts
const closePosition = 'close-position';
const dialogCloseX = 'dialog-close';
const dialogContent = 'dialog-content';
const dropDownMenu = 'dropdown-menu';
const marketActionsContent = 'position-actions-content';
const positions = 'Positions';
const tabPositions = 'tab-positions';
const toastContent = 'toast-content';
const tooltipContent = 'tooltip-content';
// #endregion
describe('positions', { tags: '@smoke', testIsolation: true }, () => {
beforeEach(() => {
cy.mockTradingPage();
cy.mockSubscription();
cy.setVegaWallet();
});
it('renders positions on trading page', () => {
visitAndClickPositions();
// 7004-POSI-001
// 7004-POSI-002
validatePositionsDisplayed();
});
it('renders positions on portfolio page', () => {
cy.mockGQL((req) => {
const positions = positionsQuery();
if (positions.positions?.edges) {
positions.positions.edges.push(
...positions.positions.edges.map((edge) => ({
...edge,
node: {
...edge.node,
party: {
...edge.node.party,
id: 'vega-1',
},
},
}))
);
}
aliasGQLQuery(req, 'Positions', positions);
});
visitAndClickPositions();
// 7004-POSI-001
// 7004-POSI-002
validatePositionsDisplayed(true);
});
it('Close my position', () => {
visitAndClickPositions();
cy.getByTestId(closePosition).first().click();
// 7004-POSI-010
cy.getByTestId(toastContent).should(
'contain.text',
'Awaiting confirmation'
);
});
});
describe('positions', { tags: '@regression', testIsolation: true }, () => {
beforeEach(() => {
cy.mockTradingPage();
cy.mockSubscription();
cy.setVegaWallet();
});
it('rows should be displayed despite errors', () => {
const errors = [
{
message:
'no market data for market: 9c55fb644c6f7de5422d40d691a62bffd5898384c70135bab29ba1e3e2e5280a',
path: ['marketsConnection', 'edges'],
extensions: {
code: 13,
type: 'Internal',
},
},
];
const marketData = marketsDataQuery();
const edges = marketData.marketsConnection?.edges.map((market) => {
const replace =
market.node.data?.market.id === 'market-2' ? null : market.node.data;
return { ...market, node: { ...market.node, data: replace } };
});
const overrides = {
...marketData,
marketsConnection: { ...marketData.marketsConnection, edges },
};
cy.mockGQL((req) => {
aliasGQLQuery(req, 'MarketsData', overrides, errors);
});
cy.visit('/#/markets/market-0');
const emptyCells = [
'notional',
'markPrice',
'currentLeverage',
'averageEntryPrice',
];
cy.getByTestId(tabPositions)
.first()
.within(() => {
cy.get(
'[row-id="02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65-market-2"]'
)
.eq(0)
.within(() => {
emptyCells.forEach((cell) => {
cy.get(`[col-id="${cell}"]`).should('contain.text', '-');
});
});
});
});
it('error message should be displayed', () => {
const errors = [
{
message:
'no market data for asset: 9c55fb644c6f7de5422d40d691a62bffd5898384c70135bab29ba1e3e2e5280a',
path: ['assets', 'edges'],
extensions: {
code: 13,
type: 'Internal',
},
},
];
const overrides = {
marketsConnection: { edges: [] },
};
cy.mockGQL((req) => {
aliasGQLQuery(req, 'MarketsData', overrides, errors);
});
cy.visit('/#/markets/market-0');
cy.getByTestId(tabPositions).contains('no market data');
});
it('sorting by Market', () => {
visitAndClickPositions();
const marketsSortedDefault = [
'AAPL.MF21',
'BTCUSD.MF21',
'ETHBTC.QM21',
'SOLUSD',
];
const marketsSortedAsc = [
'AAPL.MF21',
'BTCUSD.MF21',
'ETHBTC.QM21',
'SOLUSD',
];
const marketsSortedDesc = [
'SOLUSD',
'ETHBTC.QM21',
'BTCUSD.MF21',
'AAPL.MF21',
];
cy.getByTestId(positions).click();
// 7004-POSI-003
checkSorting(
'marketName',
marketsSortedDefault,
marketsSortedAsc,
marketsSortedDesc
);
});
// let elementWidth: number;
it('Resize column', () => {
visitAndClickPositions();
cy.get('.ag-overlay-loading-wrapper').should('not.be.visible');
cy.get('.ag-header-container').within(() => {
cy.get(`[col-id="marketName"]`)
.find('.ag-header-cell-resize')
.realMouseDown()
.realMouseMove(250, 0)
.realMouseUp();
});
// 7004-POSI-006
cy.get(`[col-id="marketName"]`)
.invoke('width')
.should('be.greaterThan', 250);
});
// This test depends on the previous one
it('Has persisted column widths', () => {
const width = 400;
cy.window().then((win) => {
win.localStorage.setItem(
'vega_positions_store',
JSON.stringify({
state: {
gridStore: {
columnState: [{ colId: 'marketName', width }],
},
},
})
);
});
visitAndClickPositions();
// 7004-POSI-012
cy.get('.ag-center-cols-container .ag-row')
.first()
.find('[col-id="marketName"]')
.invoke('outerWidth')
.should('equal', width);
});
it('Scroll horizontally', () => {
visitAndClickPositions();
cy.get('.ag-header-container').within(() => {
cy.get(`[col-id="marketName"]`)
.find('.ag-header-cell-resize')
.realMouseDown()
.realMouseMove(400, 0)
.realMouseUp();
});
cy.get('[col-id="marketName"]').should('be.visible');
cy.get('.ag-body-horizontal-scroll-viewport').realMouseWheel({
deltaX: 500,
});
// 7004-POSI-004
cy.get('[col-id="updatedAt"]').should('be.visible');
});
it('Drag and drop columns', () => {
visitAndClickPositions();
cy.get('.ag-overlay-loading-wrapper').should('not.be.visible');
cy.get('[col-id="marketName"]')
.realMouseDown()
.realMouseMove(700, 15)
.realMouseUp();
// 7004-POSI-005
cy.get('[col-id="marketName"]').should(($element) => {
const attributeValue = $element.attr('aria-colindex');
expect(attributeValue).not.to.equal('1');
});
});
it('I can see warnings', () => {
visitAndClickPositions();
cy.get('[col-id="openVolume"]')
.eq(3)
.within(() => {
cy.get('[aria-label="warning-sign icon"]')
.should('be.visible')
.realHover();
});
// 7004-POSI-011
cy.getByTestId(tooltipContent).should('be.visible');
});
it('Positive and Negative color change', () => {
cy.visit('/#/markets/market-0');
cy.getByTestId(positions).click();
// 7004-POSI-007
cy.get('.ag-center-cols-container').within(() => {
assertPNLColor(
'[col-id="realisedPNL"]',
'text-market-green-600',
'text-market-red'
);
});
cy.get('.ag-center-cols-container').within(() => {
assertPNLColor(
'[col-id="unrealisedPNL"]',
'text-market-green-600',
'text-market-red'
);
});
cy.get('.ag-center-cols-container').within(() => {
assertPNLColor(
'[col-id="openVolume"]',
'text-market-green-600',
'text-market-red'
);
});
});
it('View settlement asset', () => {
visitAndClickPositions();
cy.get('[col-id="asset"]')
.eq(3)
.within(() => {
cy.get('button[type="button"]').click();
});
// 7004-POSI-008
cy.getByTestId(dialogContent).should('be.visible');
cy.getByTestId(dialogCloseX).click();
cy.getByTestId(dropDownMenu).first().click();
cy.getByTestId(marketActionsContent).click();
// 7004-POSI-009
cy.getByTestId(dialogContent).should('be.visible');
});
});
function validatePositionsDisplayed(multiKey = false) {
cy.getByTestId('tab-positions').should('be.visible');
cy.getByTestId('tab-positions')
.get('.ag-center-cols-container .ag-row')
.eq(multiKey ? 3 : 1)
.within(() => {
cy.get('[col-id="marketName"]')
.should('be.visible')
.invoke('text')
.should('not.be.empty');
cy.get('[col-id="openVolume"]').should('not.be.empty');
// includes average entry price, mark price, realised PNL & leverage
cy.getByTestId('flash-cell').should('not.be.empty');
if (!multiKey) {
cy.get('[col-id="currentLeverage"]').should('contain.text', '2,767.3');
cy.get('[col-id="marginAccountBalance"]') // margin allocated
.should('contain.text', '0.01');
}
cy.get('[col-id="unrealisedPNL"]').should('not.be.empty');
cy.get('[col-id="notional"]').should('contain.text', '276,761.40348'); // Total tDAI position
cy.get('[col-id="realisedPNL"]').should('contain.text', '2.30'); // Total Realised PNL
cy.get('[col-id="unrealisedPNL"]').should('contain.text', '8.95'); // Total Unrealised PNL
});
cy.get('.ag-header-row [col-id="notional"]')
.should('contain.text', 'Notional')
.realHover();
cy.get('.ag-popup').should('contain.text', 'Mark price x open volume');
cy.getByTestId('close-position').should('be.visible').and('have.length', 3);
}
function assertPNLColor(
pnlSelector: string,
positiveClass: string,
negativeClass: string
) {
cy.get(pnlSelector).each(($el) => {
const value = parseFloat($el.text());
if (value > 0) {
cy.wrap($el).invoke('attr', 'class').should('contain', positiveClass);
} else if (value < 0) {
cy.wrap($el).invoke('attr', 'class').should('contain', negativeClass);
} else if (value == 0) {
cy.wrap($el)
.invoke('attr', 'class')
.should('not.contain', negativeClass, positiveClass);
} else {
throw new Error('Unexpected value');
}
});
}
function visitAndClickPositions() {
cy.visit('/#/markets/market-0');
cy.getByTestId(positions).click();
}
@@ -59,7 +59,8 @@ describe('trades', { tags: '@smoke' }, () => {
cy.getByTestId(tradesTable) // order table shares identical col id
.find(`${colIdCreatedAt} ${colHeader}`)
.should('have.text', 'Created at');
const dateTimeRegex = /(\d{1,2}):(\d{1,2}):(\d{1,2})/gm;
const dateTimeRegex =
/(\d{1,2})\/(\d{1,2})\/(\d{4}), (\d{1,2}):(\d{1,2}):(\d{1,2})/gm;
cy.getByTestId(tradesTable)
.get(`.ag-center-cols-container ${colIdCreatedAt}`)
.each(($tradeDateTime) => {
@@ -86,7 +87,6 @@ describe('trades', { tags: '@smoke' }, () => {
});
it('copy price to deal ticket form', () => {
cy.getByTestId('Order').click();
// 6005-THIS-007
cy.get(colIdPrice).last().should('be.visible').click();
cy.getByTestId('order-price').should('have.value', '171.16898');
-3
View File
@@ -20,6 +20,3 @@ NX_SUCCESSOR_MARKETS=true
NX_STOP_ORDERS=true
# NX_ICEBERG_ORDERS
# NX_PRODUCT_PERPETUALS
NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.rocks
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
+1 -4
View File
@@ -20,7 +20,4 @@ NX_ETH_WALLET_MNEMONIC="ozone access unlock valid olympic save include omit supp
NX_SUCCESSOR_MARKETS=false
NX_STOP_ORDERS=false
# NX_ICEBERG_ORDERS
# NX_PRODUCT_PERPETUALS
NX_TENDERMINT_URL=http://localhost:26617
NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
# NX_PRODUCT_PERPETUALS
+1 -4
View File
@@ -18,7 +18,4 @@ NX_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports
NX_SUCCESSOR_MARKETS=true
NX_STOP_ORDERS=true
# NX_ICEBERG_ORDERS
# NX_PRODUCT_PERPETUALS
NX_TENDERMINT_URL=https://tm.be.devnet1.vega.xyz/
NX_TENDERMINT_WEBSOCKET_URL=wss://be.devnet1.vega.xyz/websocket
# NX_PRODUCT_PERPETUALS
-3
View File
@@ -21,6 +21,3 @@ NX_SUCCESSOR_MARKETS=false
NX_STOP_ORDERS=false
# NX_ICEBERG_ORDERS
# NX_PRODUCT_PERPETUALS
NX_TENDERMINT_URL=https://be.vega.community
NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket
+1 -4
View File
@@ -20,7 +20,4 @@ NX_APP_VERSION=v0.20.19-core-0.71.6
NX_SUCCESSOR_MARKETS=false
NX_STOP_ORDERS=false
# NX_ICEBERG_ORDERS
# NX_PRODUCT_PERPETUALS
NX_TENDERMINT_URL=https://be.mainnet-mirror.vega.rocks
NX_TENDERMINT_WEBSOCKET_URL=wss://be.mainnet-mirror.vega.rocks/websocket
# NX_PRODUCT_PERPETUALS
+1 -4
View File
@@ -19,7 +19,4 @@ NX_VEGA_CONSOLE_URL=https://console.fairground.wtf
NX_SUCCESSOR_MARKETS=true
NX_STOP_ORDERS=true
NX_ICEBERG_ORDERS=true
# NX_PRODUCT_PERPETUALS
NX_TENDERMINT_URL=https://tm.be.testnet.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://be.testnet.vega.xyz/websocket
# NX_PRODUCT_PERPETUALS
+1 -4
View File
@@ -19,7 +19,4 @@ NX_VEGA_CONSOLE_URL=https://trading.validators-testnet.vega.rocks
NX_SUCCESSOR_MARKETS=false
NX_STOP_ORDERS=false
# NX_ICEBERG_ORDERS
# NX_PRODUCT_PERPETUALS
NX_TENDERMINT_URL=https://tm.be.validators-testnet.vega.rocks
NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.xyz/websocket
# NX_PRODUCT_PERPETUALS
@@ -1,5 +1,6 @@
import type { ComponentProps } from 'react';
import { Splash } from '@vegaprotocol/ui-toolkit';
import { TradesContainer } from '@vegaprotocol/trades';
import { DepthChartContainer } from '@vegaprotocol/market-depth';
import {
CandlesChartContainer,
@@ -7,7 +8,6 @@ import {
} from '@vegaprotocol/candles-chart';
import { Filter, OpenOrdersMenu } from '@vegaprotocol/orders';
import { NO_MARKET } from './constants';
import { TradesContainer } from '../../components/trades-container';
import { OrderbookContainer } from '../../components/orderbook-container';
import { FillsContainer } from '../../components/fills-container';
import { PositionsContainer } from '../../components/positions-container';
@@ -214,6 +214,7 @@ describe('Closed', () => {
</MemoryRouter>
);
});
// screen.debug(document, Infinity);
const headers = screen.getAllByRole('columnheader');
const expectedHeaders = [
@@ -433,7 +434,7 @@ describe('Closed', () => {
await waitFor(() => {
expect(
screen.getByRole('button', { name: /^SuccessorCode/ })
screen.getByRole('button', { name: 'SuccessorCode' })
).toBeInTheDocument();
});
expect(
@@ -442,16 +443,6 @@ describe('Closed', () => {
element.getAttribute('col-id') === 'successorMarket',
})
).toBeInTheDocument();
screen
.getAllByRole('gridcell', {
name: (_name, element) =>
element.getAttribute('col-id') === 'successorMarket',
})
.forEach((element) => {
expect(element.querySelector('[title="Future"]')?.textContent).toEqual(
'Futr'
);
});
});
it('feature flag should hide successors', async () => {
+18 -9
View File
@@ -4,11 +4,7 @@ import type {
VegaICellRendererParams,
VegaValueFormatterParams,
} from '@vegaprotocol/datagrid';
import {
AgGridLazy as AgGrid,
COL_DEFS,
MarketNameCell,
} from '@vegaprotocol/datagrid';
import { AgGridLazy as AgGrid, COL_DEFS } from '@vegaprotocol/datagrid';
import { useMemo } from 'react';
import { t } from '@vegaprotocol/i18n';
import { MarketState, MarketStateMapping } from '@vegaprotocol/types';
@@ -51,7 +47,6 @@ interface Row {
setlementDataSourceFilter: DataSourceFilterFragment | undefined;
tradingTerminationOracleId: string;
settlementAsset: SettlementAsset;
productType: string;
}
export const Closed = () => {
@@ -95,7 +90,6 @@ export const Closed = () => {
tradingTerminationOracleId:
instrument.product.dataSourceSpecForTradingTermination.id,
settlementAsset: instrument.product.settlementAsset,
productType: instrument.product.__typename || '',
};
return row;
@@ -121,7 +115,16 @@ const ClosedMarketsDataGrid = ({
{
headerName: t('Market'),
field: 'code',
cellRenderer: 'MarketNameCell',
cellRenderer: ({
value,
data,
}: VegaICellRendererParams<Row, 'code'>) => {
return (
<span data-testid="market-code" data-market-id={data?.id}>
{value}
</span>
);
},
},
{
headerName: t('Description'),
@@ -273,10 +276,16 @@ const ClosedMarketsDataGrid = ({
return (
<AgGrid
style={{ width: '100%', height: '100%' }}
rowData={rowData}
columnDefs={colDefs}
getRowId={({ data }) => data.id}
components={{ SuccessorMarketRenderer, MarketNameCell }}
defaultColDef={{
resizable: true,
minWidth: 100,
flex: 1,
}}
components={{ SuccessorMarketRenderer }}
overlayNoRowsTemplate={error ? error.message : t('No markets')}
/>
);
@@ -1,190 +0,0 @@
import { render, screen, act, waitFor } from '@testing-library/react';
import { MockedProvider } from '@apollo/client/testing';
import userEvent from '@testing-library/user-event';
import type { Market } from '@vegaprotocol/markets';
import { SuccessorMarketRenderer } from './successor-market-cell';
import {
MarketsDocument,
SuccessorMarketIdsDocument,
} from '@vegaprotocol/markets';
import { createMarketFragment } from '@vegaprotocol/mock';
const mockSuccessorsQuery = [
{
id: 'market1',
parentMarketID: 'parentMarket1',
successorMarketID: 'successorMarket1',
},
{ id: 'market2', parentMarketID: 'parentMarket2' },
{ id: 'market3', successorMarketID: 'successorMarket3' },
];
const parentMarket1 = {
id: 'parentMarket1',
tradableInstrument: {
instrument: { code: 'code parent 1', id: '1' },
},
} as unknown as Market;
const successorMarket1 = {
id: 'successorMarket1',
tradableInstrument: {
instrument: { code: 'code successor 1', id: '2' },
},
} as unknown as Market;
const parentMarket2 = {
id: 'parentMarket2',
tradableInstrument: {
instrument: { code: 'code parent 2', id: '3' },
},
} as unknown as Market;
const successorMarket3 = {
id: 'successorMarket3',
tradableInstrument: {
instrument: { code: 'code successor 3', id: '4' },
},
} as unknown as Market;
const mockMarkets = [
parentMarket1,
successorMarket1,
parentMarket2,
successorMarket3,
];
const mockClickHandler = jest.fn();
jest.mock('../../lib/hooks/use-market-click-handler', () => ({
useMarketClickHandler: jest.fn().mockImplementation(() => mockClickHandler),
}));
const marketMock = {
request: {
query: MarketsDocument,
variables: undefined,
},
result: {
data: {
marketsConnection: {
edges: mockMarkets.map((item) => ({
node: {
...createMarketFragment(item),
},
})),
},
},
},
};
const successorMock = {
request: {
query: SuccessorMarketIdsDocument,
},
result: {
data: {
marketsConnection: {
edges: mockSuccessorsQuery.map((item) => ({
node: {
...item,
},
})),
},
},
},
};
const mocks = [marketMock, successorMock];
describe('SuccessorMarketRenderer', () => {
beforeEach(() => {
jest.clearAllMocks();
});
it('should properly rendered successor market', async () => {
const successorValue = 'market1';
render(
<MockedProvider mocks={[...mocks]}>
<SuccessorMarketRenderer value={successorValue} />
</MockedProvider>
);
await waitFor(() => {
expect(screen.getByTestId('market-code')).toBeInTheDocument();
});
expect(screen.getByText('code successor 1')).toBeInTheDocument();
expect(screen.getByText('Futr')).toBeInTheDocument();
await userEvent.click(screen.getByRole('button'));
await waitFor(() => {
expect(mockClickHandler).toHaveBeenCalledWith('successorMarket1', false);
});
});
it('should properly rendered parent market', async () => {
const successorValue = 'market1';
render(
<MockedProvider mocks={[...mocks]}>
<SuccessorMarketRenderer value={successorValue} parent />
</MockedProvider>
);
await waitFor(() => {
expect(screen.getByTestId('market-code')).toBeInTheDocument();
});
expect(screen.getByText('code parent 1')).toBeInTheDocument();
expect(screen.getByText('Futr')).toBeInTheDocument();
await userEvent.click(screen.getByRole('button'));
await waitFor(() => {
expect(mockClickHandler).toHaveBeenCalledWith('parentMarket1', false);
});
});
it('should properly rendered only parent market', async () => {
const successorValue = 'market2';
const { rerender } = render(
<MockedProvider mocks={[...mocks]}>
<SuccessorMarketRenderer value={successorValue} parent />
</MockedProvider>
);
await waitFor(() => {
expect(screen.getByTestId('market-code')).toBeInTheDocument();
});
expect(screen.getByText('code parent 2')).toBeInTheDocument();
expect(screen.getByText('Futr')).toBeInTheDocument();
await userEvent.click(screen.getByRole('button'));
await waitFor(() => {
expect(mockClickHandler).toHaveBeenCalledWith('parentMarket2', false);
});
rerender(
<MockedProvider mocks={[...mocks]}>
<SuccessorMarketRenderer value={successorValue} />
</MockedProvider>
);
expect(screen.getByText('-')).toBeInTheDocument();
});
it('should properly rendered only successor market', async () => {
const successorValue = 'market3';
const { rerender } = render(
<MockedProvider mocks={[...mocks]}>
<SuccessorMarketRenderer value={successorValue} />
</MockedProvider>
);
await waitFor(() => {
expect(screen.getByTestId('market-code')).toBeInTheDocument();
});
expect(screen.getByText('code successor 3')).toBeInTheDocument();
expect(screen.getByText('Futr')).toBeInTheDocument();
await userEvent.click(screen.getByRole('button'));
await waitFor(() => {
expect(mockClickHandler).toHaveBeenCalledWith('successorMarket3', false);
});
await act(() => {
rerender(
<MockedProvider mocks={[...mocks]}>
<SuccessorMarketRenderer value={successorValue} parent />
</MockedProvider>
);
});
expect(screen.getByText('-')).toBeInTheDocument();
});
});
@@ -1,8 +1,8 @@
import React from 'react';
import { MarketNameCell } from '@vegaprotocol/datagrid';
import { useDataProvider } from '@vegaprotocol/data-provider';
import { marketProvider, useSuccessorMarketIds } from '@vegaprotocol/markets';
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
import React from 'react';
export const SuccessorMarketRenderer = ({
value,
@@ -33,7 +33,6 @@ export const SuccessorMarketRenderer = ({
value={data.tradableInstrument.instrument.code}
data={data}
onMarketClick={onMarketClick}
productType={data.tradableInstrument.instrument?.product.__typename}
/>
) : (
'-'
@@ -99,7 +99,6 @@ describe('MarketSelectorItem', () => {
currentMarketId={market.id}
style={{}}
onSelect={jest.fn()}
allProducts
/>
</MockedProvider>
</MemoryRouter>
@@ -182,7 +181,5 @@ describe('MarketSelectorItem', () => {
addDecimalsFormatNumber(marketData.markPrice, market.decimalPlaces)
);
});
expect(screen.getByText('Futr')).toBeInTheDocument();
});
});
@@ -12,20 +12,17 @@ import {
MarketTradingModeMapping,
} from '@vegaprotocol/types';
import { t } from '@vegaprotocol/i18n';
import { MarketProductPill } from '@vegaprotocol/datagrid';
export const MarketSelectorItem = ({
market,
style,
currentMarketId,
onSelect,
allProducts,
}: {
market: MarketMaybeWithDataAndCandles;
style: CSSProperties;
currentMarketId?: string;
onSelect: (marketId: string) => void;
allProducts: boolean;
}) => {
return (
<div style={style} role="row">
@@ -39,19 +36,13 @@ export const MarketSelectorItem = ({
})}
onClick={() => onSelect(market.id)}
>
<MarketData market={market} allProducts={allProducts} />
<MarketData market={market} />
</Link>
</div>
);
};
const MarketData = ({
market,
allProducts,
}: {
market: MarketMaybeWithDataAndCandles;
allProducts: boolean;
}) => {
const MarketData = ({ market }: { market: MarketMaybeWithDataAndCandles }) => {
const { data } = useMarketDataUpdateSubscription({
variables: {
marketId: market.id,
@@ -89,16 +80,11 @@ const MarketData = ({
? addDecimalsFormatNumber(vol, market.positionDecimalPlaces)
: '0.00';
const productType = market.tradableInstrument.instrument.product.__typename;
return (
<>
<div className="w-2/5" role="gridcell">
<h3 className="text-ellipsis text-sm lg:text-base whitespace-nowrap overflow-hidden">
{market.tradableInstrument.instrument.code}{' '}
{allProducts && productType && (
<MarketProductPill productType={productType} />
)}
{market.tradableInstrument.instrument.code}
</h3>
{mode && (
<p className="text-xs text-vega-orange-500 dark:text-vega-orange-550 whitespace-nowrap">
@@ -43,7 +43,7 @@ export const MarketSelector = ({
sort: Sort.None,
assets: [],
});
const allProducts = filter.product === Product.All;
const { markets, data, loading, error } = useMarketSelectorList(filter);
return (
@@ -128,7 +128,6 @@ export const MarketSelector = ({
? t('Spot markets coming soon.')
: t('No markets')
}
allProducts={allProducts}
/>
</div>
</div>
@@ -142,7 +141,6 @@ const MarketList = ({
currentMarketId,
onSelect,
noItems,
allProducts,
}: {
data: MarketMaybeWithDataAndCandles[];
error: Error | undefined;
@@ -151,7 +149,6 @@ const MarketList = ({
currentMarketId?: string;
onSelect: (marketId: string) => void;
noItems: string;
allProducts: boolean;
}) => {
const itemSize = 45;
const listRef = useRef<HTMLDivElement | null>(null);
@@ -195,7 +192,6 @@ const MarketList = ({
currentMarketId={currentMarketId}
onSelect={onSelect}
noItems={noItems}
allProducts={allProducts}
/>
</div>
</TinyScroll>
@@ -206,7 +202,6 @@ interface ListItemData {
data: MarketMaybeWithDataAndCandles[];
onSelect: (marketId: string) => void;
currentMarketId?: string;
allProducts: boolean;
}
const ListItem = ({
@@ -223,7 +218,6 @@ const ListItem = ({
currentMarketId={data.currentMarketId}
style={style}
onSelect={data.onSelect}
allProducts={data.allProducts}
/>
);
@@ -235,21 +229,19 @@ const List = ({
onSelect,
noItems,
currentMarketId,
allProducts,
}: ListItemData & {
loading: boolean;
height: number;
itemSize: number;
noItems: string;
allProducts: boolean;
}) => {
const itemKey = useCallback(
(index: number, data: ListItemData) => data.data[index].id,
[]
);
const itemData = useMemo(
() => ({ data, onSelect, currentMarketId, allProducts }),
[data, onSelect, currentMarketId, allProducts]
() => ({ data, onSelect, currentMarketId }),
[data, onSelect, currentMarketId]
);
if (!data || loading) {
return (
@@ -15,7 +15,9 @@ export const PositionsContainer = ({ allKeys }: { allKeys?: boolean }) => {
const gridStore = usePositionsStore((store) => store.gridStore);
const updateGridStore = usePositionsStore((store) => store.updateGridStore);
const gridStoreCallbacks = useDataGridEvents(gridStore, updateGridStore);
const gridStoreCallbacks = useDataGridEvents(gridStore, (colState) => {
updateGridStore(colState);
});
if (!pubKey) {
return (
@@ -1 +0,0 @@
export * from './trades-container';
@@ -1,24 +0,0 @@
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',
})
);
-2
View File
@@ -43,7 +43,6 @@ import { Navbar } from '../components/navbar';
import classNames from 'classnames';
import {
ProtocolUpgradeCountdownMode,
ProtocolUpgradeInProgressNotification,
ProtocolUpgradeProposalNotification,
} from '@vegaprotocol/proposals';
import { ViewingBanner } from '../components/viewing-banner';
@@ -112,7 +111,6 @@ function AppBody({ Component }: AppProps) {
<ProtocolUpgradeProposalNotification
mode={ProtocolUpgradeCountdownMode.IN_ESTIMATED_TIME_REMAINING}
/>
<ProtocolUpgradeInProgressNotification />
<ViewingBanner />
<UpgradeBanner showVersionChange={true} />
</div>
+1 -34
View File
@@ -5,45 +5,12 @@ export default function Document() {
<Html>
<Head>
<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
rel="preload"
href="https://static.vega.xyz/AlphaLyrae-Medium.woff2"
as="font"
type="font/woff2"
crossOrigin="anonymous"
/>
{/* eslint-disable-next-line @next/next/no-css-tags */}
<link rel="stylesheet" href="/preloader.css" media="all" />
+27 -1
View File
@@ -1,3 +1,4 @@
import Head from 'next/head';
import { ClientRouter } from './client-router';
/**
@@ -6,5 +7,30 @@ import { ClientRouter } from './client-router';
* have to serve a static site via next export
*/
export default function Index() {
return <ClientRouter />;
return (
<>
<Head>
<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 - Console" />
<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 Console dApp</title>
</Head>
<ClientRouter />
</>
);
}
-10
View File
@@ -142,19 +142,12 @@ html [data-theme='dark'] {
border-width: 0;
}
.vega-ag-grid .ag-cell .ag-cell-wrapper {
height: 100%;
}
.vega-ag-grid .ag-header-row {
@apply font-alpha font-normal;
}
/* Light variables */
.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-border-color: theme(colors.vega.clight.600);
--ag-header-background-color: theme(colors.vega.clight.700);
@@ -167,9 +160,6 @@ html [data-theme='dark'] {
/* Dark variables */
.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-border-color: theme(colors.vega.cdark.600);
--ag-header-background-color: theme(colors.vega.cdark.700);
+7 -7
View File
@@ -58,12 +58,6 @@ export const accountValuesComparator = (
return valueA > valueB ? 1 : -1;
};
const defaultColDef = {
resizable: true,
sortable: true,
tooltipComponent: TooltipCellComponent,
comparator: accountValuesComparator,
};
export interface GetRowsParams extends Omit<IGetRowsParams, 'successCallback'> {
successCallback(rowsThisBlock: AccountFields[], lastRow?: number): void;
}
@@ -312,10 +306,16 @@ export const AccountTable = ({
return (
<AgGrid
{...props}
style={{ width: '100%', height: '100%' }}
getRowId={({ data }: { data: AccountFields }) => data.asset.id}
tooltipShowDelay={500}
rowData={data}
defaultColDef={defaultColDef}
defaultColDef={{
resizable: true,
tooltipComponent: TooltipCellComponent,
sortable: true,
comparator: accountValuesComparator,
}}
columnDefs={colDefs}
getRowHeight={getPinnedAssetRowHeight}
pinnedTopRowData={pinnedRow ? [pinnedRow] : undefined}
@@ -24,9 +24,6 @@ const singleRow = {
__typename: 'Instrument',
name: 'BTCUSD Monthly (30 Jun 2022)',
code: 'BTCUSD.MF21',
product: {
__typename: 'Future',
},
},
},
id: '10cd0a793ad2887b340940337fa6d97a212e0e517fe8e9eab2b5ef3a38633f35',
@@ -123,9 +120,6 @@ describe('BreakdownTable', () => {
__typename: 'Instrument',
name: 'BTCUSD Monthly (30 Jun 2022)',
code: 'BTCUSD.MF21',
product: {
__typename: 'Future',
},
},
},
},
+14 -20
View File
@@ -20,10 +20,6 @@ import { MarginHealthChart } from './margin-health-chart';
import { MarketNameCell } from '@vegaprotocol/datagrid';
import { AccountType } from '@vegaprotocol/types';
const defaultColDef = {
resizable: true,
sortable: true,
};
interface BreakdownTableProps extends AgGridReactProps {
data: AccountFields[] | null;
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
@@ -36,25 +32,16 @@ const BreakdownTable = forwardRef<AgGridReact, BreakdownTableProps>(
{
headerName: t('Market'),
field: 'market.tradableInstrument.instrument.code',
minWidth: 200,
cellRenderer: ({
valueFormatter: ({
value,
data,
}: VegaICellRendererParams<
}: VegaValueFormatterParams<
AccountFields,
'market.tradableInstrument.instrument.code'
>) => {
return value ? (
<MarketNameCell
value={value}
productType={
data?.market?.tradableInstrument.instrument.product.__typename
}
/>
) : (
'None'
);
if (!value) return 'None';
return value;
},
minWidth: 200,
},
{
headerName: t('Account type'),
@@ -71,6 +58,7 @@ const BreakdownTable = forwardRef<AgGridReact, BreakdownTableProps>(
{
headerName: t('Balance'),
field: 'used',
flex: 2,
maxWidth: 500,
type: 'rightAligned',
tooltipComponent: TooltipCellComponent,
@@ -109,6 +97,7 @@ const BreakdownTable = forwardRef<AgGridReact, BreakdownTableProps>(
{
headerName: t('Margin health'),
field: 'market.id',
flex: 2,
maxWidth: 500,
sortable: false,
cellRenderer: ({
@@ -129,6 +118,7 @@ const BreakdownTable = forwardRef<AgGridReact, BreakdownTableProps>(
return (
<AgGrid
style={{ width: '100%', height: '100%' }}
overlayNoRowsTemplate={t('Collateral not used')}
rowData={data}
getRowId={({ data }: { data: AccountFields }) =>
@@ -136,9 +126,13 @@ const BreakdownTable = forwardRef<AgGridReact, BreakdownTableProps>(
}
ref={ref}
rowHeight={34}
components={{ PriceCell, ProgressBarCell }}
components={{ PriceCell, MarketNameCell, ProgressBarCell }}
tooltipShowDelay={500}
defaultColDef={defaultColDef}
defaultColDef={{
flex: 1,
resizable: true,
sortable: true,
}}
columnDefs={coldefs}
/>
);
+3 -6
View File
@@ -121,12 +121,9 @@ export function createClient({
// called on startup, NodeCheck and NodeCheckTimeUpdate are called
// by the NodeSwitcher component and the useNodeHealth hook
if (
[
'NodeGuard',
'NodeCheck',
'NodeCheckTimeUpdate',
'BlockStatistics',
].includes(operation.operationName)
['NodeGuard', 'NodeCheck', 'NodeCheckTimeUpdate'].includes(
operation.operationName
)
) {
return;
}
-2
View File
@@ -24,7 +24,6 @@ import { addVegaWalletSubmitLiquidityProvision } from './lib/commands/vega-walle
import { addImportNodeWallets } from './lib/commands/import-node-wallets';
import { addVegaWalletTopUpRewardsPool } from './lib/commands/vega-wallet-top-up-rewards-pool';
import { addAssociateTokensToVegaWallet } from './lib/commands/associate-tokens-to-vega-wallet';
import { addMockChainId } from './lib/commands/mock-chain-id';
addGetTestIdcommand();
addMockGQLCommand();
@@ -50,7 +49,6 @@ addVegaWalletSubmitLiquidityProvision();
addImportNodeWallets();
addVegaWalletTopUpRewardsPool();
addAssociateTokensToVegaWallet();
addMockChainId();
export {
mockConnectWallet,
@@ -1,22 +0,0 @@
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());
});
});
}
+6 -14
View File
@@ -41,22 +41,21 @@ export const checkSorting = (
column: string,
orderTabDefault: string[],
orderTabAsc: string[],
orderTabDesc: string[],
additionalColumnSelector = ''
orderTabDesc: string[]
) => {
checkSortChange(orderTabDefault, column, additionalColumnSelector);
checkSortChange(orderTabDefault, column);
cy.get('.ag-header-container')
.last()
.within(() => {
cy.get(`[col-id="${column}"]`).last().click();
});
checkSortChange(orderTabAsc, column, additionalColumnSelector);
checkSortChange(orderTabAsc, column);
cy.get('.ag-header-container')
.last()
.within(() => {
cy.get(`[col-id="${column}"]`).click();
});
checkSortChange(orderTabDesc, column, additionalColumnSelector);
checkSortChange(orderTabDesc, column);
cy.get('.ag-header-container')
.last()
.within(() => {
@@ -64,20 +63,13 @@ export const checkSorting = (
});
};
const checkSortChange = (
tabsArr: string[],
column: string,
additionalColumnSelector = ''
) => {
const checkSortChange = (tabsArr: string[], column: string) => {
cy.get('.ag-center-cols-container')
.last()
.within(() => {
tabsArr.forEach((entry, i) => {
cy.get(`[row-index="${i}"]`).within(() => {
cy.get(`[col-id="${column}"]${additionalColumnSelector}`).should(
'have.text',
tabsArr[i]
);
cy.get(`[col-id="${column}"]`).should('have.text', tabsArr[i]);
});
});
});
@@ -3,20 +3,6 @@ import { AgGridReact } from 'ag-grid-react';
import { useThemeSwitcher } from '@vegaprotocol/react-helpers';
import { t } from '@vegaprotocol/i18n';
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 = ({
style,
@@ -27,20 +13,23 @@ export const AgGridThemed = ({
gridRef?: React.ForwardedRef<AgGridReact>;
}) => {
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', 'w-full h-full', {
const wrapperClasses = classNames('vega-ag-grid', {
'ag-theme-balham': theme === 'light',
'ag-theme-balham-dark': theme === 'dark',
});
return (
<div className={wrapperClasses}>
<AgGridReact
defaultColDef={defaultColDef}
ref={gridRef}
{...defaultProps}
{...props}
/>
<div className={wrapperClasses} style={style}>
<AgGridReact {...defaultProps} {...props} ref={gridRef} />
</div>
);
};
@@ -9,10 +9,7 @@ export const CenteredGridCellWrapper = ({
className?: string;
}) => (
<div
className={classNames(
'flex h-[20px] p-0 justify-items-center items-center',
className
)}
className={classNames('flex h-[20px] p-0 justify-items-center', className)}
>
<div className="w-full self-center">{children}</div>
</div>
@@ -1,38 +1,13 @@
import type { MouseEvent } from 'react';
import type { MouseEvent, ReactNode } from 'react';
import { useCallback } from 'react';
import get from 'lodash/get';
import { Pill } from '@vegaprotocol/ui-toolkit';
import {
ProductTypeShortName,
type Market,
type ProductType,
ProductTypeMapping,
} from '@vegaprotocol/types';
export const MarketProductPill = ({
productType,
}: {
productType: ProductType;
}) => {
return (
<Pill
size="xxs"
className="uppercase ml-0.5"
title={ProductTypeMapping[productType]}
>
{ProductTypeShortName[productType]}
</Pill>
);
};
interface MarketNameCellProps {
value?: string | null;
data?:
| { id?: string; marketId?: string; productType?: string; market?: Market }
| Market;
data?: { id?: string; marketId?: string; market?: { id: string } };
idPath?: string;
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
productType?: ProductType;
defaultValue?: ReactNode;
}
export const MarketNameCell = ({
@@ -40,43 +15,25 @@ export const MarketNameCell = ({
data,
idPath,
onMarketClick,
productType,
}: MarketNameCellProps) => {
const id = data ? get(data, idPath ?? 'id', 'all') : '';
const handleOnClick = useCallback(
(ev: MouseEvent<HTMLButtonElement>) => {
ev.preventDefault();
ev.stopPropagation();
id && onMarketClick?.(id, ev.metaKey || ev.ctrlKey);
if (onMarketClick) {
onMarketClick(id, ev.metaKey || ev.ctrlKey);
}
},
[id, onMarketClick]
);
productType =
productType ||
(data as { productType?: ProductType }).productType ||
(data as Market)?.tradableInstrument?.instrument.product.__typename ||
(data as { market: Market })?.market?.tradableInstrument.instrument.product
.__typename;
if (!value) return;
const content = (
<>
<span data-testid="market-code" data-market-id={id}>
{value}
</span>
{productType && <MarketProductPill productType={productType} />}
</>
);
return onMarketClick && id ? (
<button
onClick={handleOnClick}
tabIndex={0}
className="block text-left text-ellipsis overflow-hidden whitespace-nowrap w-full"
>
{content}
if (!value || !data) return null;
return onMarketClick ? (
<button onClick={handleOnClick} tabIndex={0}>
{value}
</button>
) : (
content
// eslint-disable-next-line react/jsx-no-useless-fragment
<>{value}</>
);
};
+2 -2
View File
@@ -4,8 +4,8 @@ export const COL_DEFS = {
sortable: false,
resizable: false,
filter: false,
minWidth: 30,
maxWidth: 30,
minWidth: 45,
maxWidth: 45,
type: 'rightAligned',
pinned: 'right' as const,
},
@@ -14,6 +14,7 @@ const gridProps = {
{
field: 'id',
width: 100,
resizable: true,
filter: 'agNumberColumnFilter',
},
],
@@ -49,7 +50,7 @@ describe('useDataGridEvents', () => {
console.warn = originalWarn;
});
it('default state is set and callback is called on filter event', async () => {
it('default state is set and callback is called on column or filter event', async () => {
const callback = jest.fn();
const initialState = {
filterModel: undefined,
@@ -66,6 +67,45 @@ describe('useDataGridEvents', () => {
// no filters set
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
const idFilter = {
filter: 1,
@@ -83,7 +123,7 @@ describe('useDataGridEvents', () => {
});
expect(callback).toHaveBeenCalledWith({
columnState: undefined,
columnState: expect.any(Object),
filterModel: {
id: idFilter,
},
@@ -98,7 +138,7 @@ describe('useDataGridEvents', () => {
filterType: 'number',
type: 'equals',
};
const colState = { colId: 'id', sort: 'desc' as const };
const colState = { colId: 'id', width: 300, sort: 'desc' as const };
const initialState = {
filterModel: {
id: idFilter,
@@ -116,7 +156,7 @@ describe('useDataGridEvents', () => {
});
});
it('ignores events that were not made via the UI', async () => {
it('debounces events', async () => {
const callback = jest.fn();
const initialState = {
filterModel: undefined,
@@ -130,6 +170,8 @@ describe('useDataGridEvents', () => {
// Set col width multiple times
await act(async () => {
result.current.columnApi.setColumnWidth('id', newWidth);
result.current.columnApi.setColumnWidth('id', newWidth);
result.current.columnApi.setColumnWidth('id', newWidth);
});
expect(callback).not.toHaveBeenCalled();
@@ -138,6 +180,6 @@ describe('useDataGridEvents', () => {
jest.advanceTimersByTime(GRID_EVENT_DEBOUNCE_TIME);
});
expect(callback).toHaveBeenCalledTimes(0);
expect(callback).toHaveBeenCalledTimes(1);
});
});
+23 -67
View File
@@ -1,13 +1,12 @@
import debounce from 'lodash/debounce';
import type {
ColumnMovedEvent,
ColumnResizedEvent,
ColumnState,
ColumnVisibleEvent,
FilterChangedEvent,
FirstDataRenderedEvent,
GridReadyEvent,
SortChangedEvent,
} from 'ag-grid-community';
import { useCallback } from 'react';
import { useCallback, useMemo } from 'react';
type State = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -15,70 +14,30 @@ type State = {
columnState?: ColumnState[];
};
type Event = ColumnResizedEvent | FilterChangedEvent | SortChangedEvent;
export const GRID_EVENT_DEBOUNCE_TIME = 300;
export const useDataGridEvents = (
state: State,
callback: (data: State) => void
) => {
/**
* Callback for filter events
*/
const onFilterChanged = useCallback(
({ api }: FilterChangedEvent) => {
if (!api) return;
const filterModel = api.getFilterModel();
callback({ filterModel });
},
// This function can be called very frequently by the onColumnResized
// grid callback, so its memoized to only update after resizing is finished
const onGridChange = useMemo(
() =>
debounce(({ api, columnApi }: Event) => {
if (!api || !columnApi) return;
const columnState = columnApi.getColumnState();
const filterModel = api.getFilterModel();
callback({ columnState, filterModel });
}, GRID_EVENT_DEBOUNCE_TIME),
[callback]
);
/**
* 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
*/
// check if we have stored column states or filter models and apply if we do
const onGridReady = useCallback(
({ api, columnApi }: FirstDataRenderedEvent) => {
({ api, columnApi }: GridReadyEvent) => {
if (!api || !columnApi) return;
if (state.columnState) {
@@ -87,6 +46,7 @@ export const useDataGridEvents = (
applyOrder: true,
});
} else {
// ensure columns fit available space if no widths are set
api.sizeColumnsToFit();
}
@@ -99,12 +59,8 @@ export const useDataGridEvents = (
return {
onGridReady,
// these events don't use the 'finished' flag
onFilterChanged,
onSortChanged: onColumnChange,
onColumnVisible: onColumnChange,
// these trigger a lot so this callback uses the 'finished' flag
onColumnMoved: onDebouncedColumnChange,
onColumnResized: onDebouncedColumnChange,
onColumnResized: onGridChange,
onFilterChanged: onGridChange,
onSortChanged: onGridChange,
};
};
+9 -1
View File
@@ -70,9 +70,17 @@ export const DepositsTable = (
</EtherscanLink>
);
},
flex: 1,
},
],
[]
);
return <AgGrid columnDefs={columnDefs} {...props} />;
return (
<AgGrid
defaultColDef={{ flex: 1 }}
columnDefs={columnDefs}
style={{ width: '100%', height: '100%' }}
{...props}
/>
);
};
+3 -5
View File
@@ -29,7 +29,6 @@ const EmptyLinks: DAppLinks = {
const ExplorerLinks = {
...EmptyLinks,
[Networks.STAGNET1]: 'https://explorer.stagnet1.vega.rocks',
[Networks.TESTNET]: 'https://explorer.fairground.wtf',
[Networks.VALIDATOR_TESTNET]:
'https://explorer.validators-testnet.vega.rocks',
@@ -41,18 +40,17 @@ const ConsoleLinks = {
...EmptyLinks,
[Networks.STAGNET1]: 'https://trading.stagnet1.vega.rocks',
[Networks.TESTNET]: 'https://console.fairground.wtf',
[Networks.MAINNET]: 'https://vega.trading',
[Networks.MAINNET_MIRROR]: 'https://console.mainnet-mirror.vega.rocks',
[Networks.MAINNET]: 'https://console.vega.xyz',
[Networks.MAINNET_MIRROR]: 'https://console.mainnet-mirror.vega.rocks/',
};
const TokenLinks = {
...EmptyLinks,
[Networks.DEVNET]: 'https://dev.governance.vega.xyz',
[Networks.STAGNET1]: 'https://governance.stagnet1.vega.rocks',
[Networks.TESTNET]: 'https://governance.fairground.wtf',
[Networks.VALIDATOR_TESTNET]:
'https://governance.validators-testnet.vega.rocks',
[Networks.MAINNET_MIRROR]: 'https://governance.mainnet-mirror.vega.rocks',
[Networks.MAINNET_MIRROR]: 'https://governance.mainnet-mirror.vega.rocks/',
[Networks.MAINNET]: 'https://governance.vega.xyz',
};
+2
View File
@@ -124,6 +124,8 @@ export const FillsTable = forwardRef<AgGridReact, Props>(
ref={ref}
columnDefs={columnDefs}
overlayNoRowsTemplate={t('No fills')}
defaultColDef={{ resizable: true }}
style={{ width: '100%', height: '100%' }}
getRowId={({ data }) => data?.id}
tooltipShowDelay={0}
tooltipHideDelay={2000}
@@ -60,7 +60,7 @@ export const ledgerEntriesProvider = makeDerivedDataProvider<
(partsData) => {
const entries = partsData[0] as ReturnType<typeof getData>;
const assets = partsData[1] as Record<string, Asset>;
const markets = partsData[2] as Record<string, Market>;
const markets = partsData[1] as Record<string, Market>;
return entries.map((entry) => {
const asset = entry.assetId
? (assets as Record<string, Asset>)[entry.assetId]
+13 -26
View File
@@ -12,12 +12,10 @@ import type {
import {
AgGridLazy as AgGrid,
DateRangeFilter,
MarketNameCell,
SetFilter,
} from '@vegaprotocol/datagrid';
import type * as Types from '@vegaprotocol/types';
import type { ColDef } from 'ag-grid-community';
import type { Market } from '@vegaprotocol/markets';
import {
AccountTypeMapping,
DescriptionTransferTypeMapping,
@@ -44,16 +42,6 @@ const dateRangeFilterParams = {
maxNextDays: 0,
defaultValue,
};
const defaultColDef = {
resizable: true,
sortable: true,
tooltipComponent: TransferTooltipCellComponent,
filterParams: {
...dateRangeFilterParams,
buttons: ['reset'],
},
};
type LedgerEntryProps = TypedDataAgGrid<LedgerEntry>;
export const LedgerTable = (props: LedgerEntryProps) => {
@@ -84,14 +72,10 @@ export const LedgerTable = (props: LedgerEntryProps) => {
field: 'marketSender.tradableInstrument.instrument.code',
cellRenderer: ({
value,
data,
}: VegaValueFormatterParams<
LedgerEntry,
'marketSender.tradableInstrument.instrument.code'
>) =>
value && (
<MarketNameCell value={value} data={data?.marketSender as Market} />
),
>) => value || '-',
},
{
headerName: t('Receiver'),
@@ -118,17 +102,10 @@ export const LedgerTable = (props: LedgerEntryProps) => {
field: 'marketReceiver.tradableInstrument.instrument.code',
cellRenderer: ({
value,
data,
}: VegaValueFormatterParams<
LedgerEntry,
'marketReceiver.tradableInstrument.instrument.code'
>) =>
value && (
<MarketNameCell
value={value}
data={data?.marketReceiver as Market}
/>
),
>) => value || '-',
},
{
headerName: t('Transfer type'),
@@ -200,14 +177,24 @@ export const LedgerTable = (props: LedgerEntryProps) => {
value ? getDateTimeFormat().format(fromNanoSeconds(value)) : '-',
filterParams: dateRangeFilterParams,
filter: DateRangeFilter,
flex: 1,
},
],
[]
);
return (
<AgGrid
style={{ width: '100%', height: '100%' }}
tooltipShowDelay={500}
defaultColDef={defaultColDef}
defaultColDef={{
resizable: true,
sortable: true,
tooltipComponent: TransferTooltipCellComponent,
filterParams: {
...dateRangeFilterParams,
buttons: ['reset'],
},
}}
columnDefs={columnDefs}
{...props}
/>
+8 -7
View File
@@ -31,12 +31,6 @@ const dateValueFormatter = ({ value }: { value?: string | null }) => {
return getDateTimeFormat().format(new Date(value));
};
const defaultColDef = {
resizable: true,
sortable: true,
tooltipComponent: TooltipCellComponent,
};
export interface LiquidityTableProps
extends TypedDataAgGrid<LiquidityProvisionData> {
symbol?: string;
@@ -130,6 +124,7 @@ export const LiquidityTable = ({
headerTooltip: t(
'The valuation of the market at the time the liquidity commitment was made. Commitments made at a lower valuation earlier in the lifetime of the market would be expected to have a higher equity-like share if the market has grown. If a commitment is amended, value will reflect the average of the market valuations across the lifetime of the commitment.'
),
minWidth: 160,
valueFormatter: assetDecimalsQuantumFormatter,
tooltipValueGetter: assetDecimalsFormatter,
},
@@ -188,10 +183,16 @@ export const LiquidityTable = ({
return (
<AgGrid
style={{ width: '100%', height: '100%' }}
overlayNoRowsTemplate={t('No liquidity provisions')}
getRowId={({ data }: { data: LiquidityProvisionData }) => data.id || ''}
tooltipShowDelay={500}
defaultColDef={defaultColDef}
defaultColDef={{
resizable: true,
minWidth: 100,
tooltipComponent: TooltipCellComponent,
sortable: true,
}}
{...props}
columnDefs={colDefs}
/>
@@ -35,9 +35,11 @@ const MarketName = (props: MarketNameCellProps) => (
);
const defaultColDef = {
resizable: true,
sortable: true,
filter: true,
filterParams: { buttons: ['reset'] },
minWidth: 100,
};
type Props = TypedDataAgGrid<MarketMaybeWithData> & {
onMarketClick: (marketId: string, metaKey?: boolean) => void;
@@ -56,6 +58,7 @@ export const MarketListTable = ({
};
return (
<AgGrid
style={{ width: '100%', height: '100%' }}
getRowId={getRowId}
defaultColDef={defaultColDef}
columnDefs={columnDefs}
@@ -40,6 +40,7 @@ export const useColumnDefs = ({ onMarketClick }: Props) => {
{
headerName: t('Trading mode'),
field: 'tradingMode',
minWidth: 170,
valueFormatter: ({
data,
}: VegaValueFormatterParams<MarketMaybeWithData, 'data'>) => {
@@ -107,7 +107,6 @@ export const NetworkParams = {
market_liquidity_targetstake_triggering_ratio:
'market_liquidity_targetstake_triggering_ratio',
transfer_fee_factor: 'transfer_fee_factor',
network_validators_incumbentBonus: 'network_validators_incumbentBonus',
} as const;
type Params = typeof NetworkParams;

Some files were not shown because too many files have changed in this diff Show More