diff --git a/apps/explorer-e2e/cypress.config.js b/apps/explorer-e2e/cypress.config.js index 19f3a841a..bb5505737 100644 --- a/apps/explorer-e2e/cypress.config.js +++ b/apps/explorer-e2e/cypress.config.js @@ -1,16 +1,13 @@ const { defineConfig } = require('cypress'); -const setupNodeEvents = require('./src/plugins/index.js'); module.exports = defineConfig({ projectId: 'et4snf', e2e: { - setupNodeEvents, baseUrl: 'http://localhost:3000', fileServerFolder: '.', fixturesFolder: false, - specPattern: '**/*.feature', - excludeSpecPattern: '**/*.js', + specPattern: '**/*.cy.{js,jsx,ts,tsx}', modifyObstructiveCode: false, supportFile: './src/support/index.ts', video: true, diff --git a/apps/explorer-e2e/src/integration/asset-page.feature b/apps/explorer-e2e/src/integration/asset-page.feature deleted file mode 100644 index addbbffc3..000000000 --- a/apps/explorer-e2e/src/integration/asset-page.feature +++ /dev/null @@ -1,11 +0,0 @@ -Feature: Asset Page - - Scenario: Navigate to Asset Page - Given I am on the homepage - When I navigate to the asset page - Then asset page is correctly displayed - - Scenario: Navigate to Asset Page using mobile - Given I am on mobile and open the toggle menu - When I navigate to the asset page - Then asset page is correctly displayed diff --git a/apps/explorer-e2e/src/integration/asset.cy.js b/apps/explorer-e2e/src/integration/asset.cy.js new file mode 100644 index 000000000..4838c1699 --- /dev/null +++ b/apps/explorer-e2e/src/integration/asset.cy.js @@ -0,0 +1,20 @@ +import '../support/common.functions'; + +context('Asset page', function () { + describe('Verify elements on page', function () { + const assetsNavigation = 'a[href="/assets"]'; + const assetHeader = '[data-testid="asset-header"]'; + + it('Assets page is displayed', function () { + cy.visit('/'); + cy.get(assetsNavigation).click(); + cy.common_validate_blocks_data_displayed(assetHeader); + }); + + it('Assets page displayed in mobile', function () { + cy.common_switch_to_mobile_and_click_toggle(); + cy.get(assetsNavigation).click(); + cy.common_validate_blocks_data_displayed(assetHeader); + }); + }); +}); diff --git a/apps/explorer-e2e/src/integration/blocks-page.feature b/apps/explorer-e2e/src/integration/blocks-page.feature deleted file mode 100644 index c655b7d00..000000000 --- a/apps/explorer-e2e/src/integration/blocks-page.feature +++ /dev/null @@ -1,38 +0,0 @@ -Feature: Blocks Page - - Scenario: Navigate to blocks page - Given I am on the homepage - When I navigate to the blocks page - Then blocks page is correctly displayed - - Scenario: Navigate to blocks page using mobile - Given I am on mobile and open the toggle menu - When I navigate to the blocks page - Then blocks page is correctly displayed - - Scenario: Navigate to block validator page - Given I am on the homepage - When I navigate to the blocks page - And I click on top block - Then validator block page is correctly displayed - - Scenario: Navigate to previous block - Given I am on the homepage - When I navigate to the blocks page - And I click on top block - Then I am on the previous block when I click previous - - Scenario: Previous button disabled on first block - Given I am on the homepage - When I navigate to the blocks page - And jump to first block - Then previous button is disabled - And I am on the second block when I click next - -# Skipping these tests for time being - since blockchain in capsule -# is now too small to show historical data - re-enable once addressed - # Scenario: Infinite scroll shows at least 300 new blocks - # Given I am on the homepage - # When I navigate to the blocks page - # And I scroll down to the last block on the page - # Then I can expect to see at least 100 blocks if i scroll 7 times \ No newline at end of file diff --git a/apps/explorer-e2e/src/integration/blocks.cy.js b/apps/explorer-e2e/src/integration/blocks.cy.js new file mode 100644 index 000000000..97dddef67 --- /dev/null +++ b/apps/explorer-e2e/src/integration/blocks.cy.js @@ -0,0 +1,132 @@ +import '../support/common.functions'; + +context('Blocks page', function () { + before('visit token home page', function () { + cy.visit('/'); + }); + + describe('Verify elements on page', function () { + const blockNavigation = 'a[href="/blocks"]'; + const blockHeight = '[data-testid="block-height"]'; + const blockTime = '[data-testid="block-time"]'; + const blockHeader = '[data-testid="block-header"]'; + const previousBlockBtn = '[data-testid="previous-block"]'; + const infiniteScrollWrapper = '[data-testid="infinite-scroll-wrapper"]'; + + beforeEach('navigate to blocks page', function () { + cy.get(blockNavigation).click(); + }); + + it('Blocks page is displayed', function () { + validateBlocksDisplayed(); + }); + + it('Blocks page is displayed on mobile', function () { + cy.common_switch_to_mobile_and_click_toggle(); + cy.get(blockNavigation).click(); + validateBlocksDisplayed(); + }); + + it('Block validator page is displayed', function () { + waitForBlocksResponse(); + cy.get(blockHeight).eq(0).click(); + cy.get('[data-testid="block-validator"]').should('not.be.empty'); + cy.get(blockTime).should('not.be.empty'); + //TODO: Add assertion for transactions when txs are added + }); + + it('Navigate to previous block', function () { + waitForBlocksResponse(); + cy.get(blockHeight).eq(0).click(); + cy.get(blockHeader) + .invoke('text') + .then(($blockHeaderTxt) => { + const blockHeight = parseInt($blockHeaderTxt.replace('BLOCK ', '')); + cy.get(previousBlockBtn).click(); + cy.get(blockHeader) + .invoke('text') + .then(($newBlockHeaderTxt) => { + const newBlockHeight = parseInt( + $newBlockHeaderTxt.replace('BLOCK ', '') + ); + expect(newBlockHeight).to.be.lessThan(blockHeight); + }); + }); + }); + + it('Previous button disabled on first block', function () { + cy.get('[data-testid="block-input"]').type('1'); + cy.get('[data-testid="go-submit"]').click(); + cy.get(previousBlockBtn).find('button').should('be.disabled'); + cy.get(blockHeader) + .invoke('text') + .then(($blockHeaderTxt) => { + const blockHeight = parseInt($blockHeaderTxt.replace('BLOCK ', '')); + cy.get('[data-testid="next-block"]').click(); + cy.get(blockHeader) + .invoke('text') + .then(($newBlockHeaderTxt) => { + const newBlockHeight = parseInt( + $newBlockHeaderTxt.replace('BLOCK ', '') + ); + expect(newBlockHeight).to.be.greaterThan(blockHeight); + }); + }); + }); + + // Skipping these tests for time being - since blockchain in capsule is now too small to show historical data - re-enable once addressed + it.skip('Infinite scroll shows at least 100 new blocks', function () { + const expectedBlocks = 100; + const scrollAttempts = 7; + + waitForBlocksResponse(); + cy.get(infiniteScrollWrapper).children().scrollTo('bottom'); + + cy.intercept('*blockchain?maxHeight*').as('blockchain_load'); + cy.get(blockHeight) + .last() + .invoke('text') + .then(($initialLastBlockHeight) => { + for (let index = 0; index < scrollAttempts; index++) { + cy.get(infiniteScrollWrapper) + .children() + .children() + .invoke('css', 'height') + .then((scrollTarget) => { + cy.get(infiniteScrollWrapper) + .children() + .scrollTo(0, scrollTarget.toString(), { easing: 'linear' }) + .wait('@blockchain_load'); + + // eslint-disable-next-line cypress/no-unnecessary-waiting + cy.wait(50); // Need this as although network response has arrived it takes a few millisecs for the css height to expand + }); + } + + cy.get(blockHeight) + .last() + .invoke('text') + .then(($lastBlockHeight) => { + const totalBlocksLoadedSinceScrollBegan = + parseInt($initialLastBlockHeight) - parseInt($lastBlockHeight); + expect(totalBlocksLoadedSinceScrollBegan).to.be.at.least( + expectedBlocks + ); + }); + }); + }); + + function waitForBlocksResponse() { + cy.contains('Loading...').should('not.exist', { timeout: 18000 }); + } + + function validateBlocksDisplayed() { + waitForBlocksResponse(); + cy.get('[data-testid="block-row"]').should('have.length.above', 1); + cy.get(blockHeight).first().should('not.be.empty'); + cy.get('[data-testid="num-txs"]').first().should('not.be.empty'); + cy.get('[data-testid="validator-link"]').first().should('not.be.empty'); + cy.get(blockTime).first().should('not.be.empty'); + } + }); +}); diff --git a/apps/explorer-e2e/src/integration/home-page.feature b/apps/explorer-e2e/src/integration/home-page.feature deleted file mode 100644 index 983e52508..000000000 --- a/apps/explorer-e2e/src/integration/home-page.feature +++ /dev/null @@ -1,27 +0,0 @@ -Feature: Home page - - Scenario: Stats page displayed correctly - Given I am on the homepage - Then the stats for deployed environment are correctly displayed - - Scenario Outline: Succesfful search for specific id by - Given I am on the homepage - When I search for '' - Then I am redirected to page containing id '' - - Examples: - | IdType | Id | - | Block Id | 973624 | - | Tx Hash | 9ED3718AA8308E7E08EC588EE7AADAF49711D2138860D8914B4D81A2054D9FB8 | - | Tx Id | 0x61DCCEBB955087F50D0B85382DAE138EDA9631BF1A4F92E563D528904AA38898 | - - Scenario Outline: Error message displayed when invalid search by - Given I am on the homepage - When I search for '' - Then search error message "" is displayed - - Examples: - | invalidType | Id | errorMessage | - | wrong string length | 9ED3718AA8308E7E08EC588EE7AADAF497D2138860D8914B4D81A2054D9FB8 | Something doesn't look right | - | invalid hash | 9ED3718AA8308E7E08ECht8EE753DAF49711D2138860D8914B4D81A2054D9FB8 | Transaction is not hexadecimal | - | empty search | | Search required | diff --git a/apps/explorer-e2e/src/integration/home.cy.js b/apps/explorer-e2e/src/integration/home.cy.js new file mode 100644 index 000000000..2598c423a --- /dev/null +++ b/apps/explorer-e2e/src/integration/home.cy.js @@ -0,0 +1,141 @@ +context('Home Page', function () { + before('visit home page', function () { + cy.visit('/'); + }); + + describe('Stats page', function () { + const statsValue = '[data-testid="stats-value"]'; + + it('Should show connected environment', function () { + const deployedEnv = Cypress.env('environment').toUpperCase(); + cy.get('[data-testid="stats-environment"]').should( + 'have.text', + `/ ${deployedEnv}` + ); + }); + + it('should show connected environment stats', function () { + const statTitles = { + 0: 'Status', + 1: 'Height', + 2: 'Validating nodes', + 3: 'Uptime', + 4: 'Total nodes', + 5: 'Inactive nodes', + 6: 'Total staked', + 7: 'Backlog', + 8: 'Trades / second', + 9: 'Orders / block', + 10: 'Orders / second', + 11: 'Transactions / block', + 12: 'Block time', + 13: 'Time', + 14: 'App', + 15: 'Tendermint', + 16: 'Up since', + 17: 'Chain ID', + }; + + cy.get('[data-testid="stats-title"]') + .each(($list, index) => { + cy.wrap($list).should('have.text', statTitles[index]); + }) + .then(($list) => { + cy.wrap($list).should('have.length', 18); + }); + + cy.get(statsValue).eq(0).should('have.text', 'CONNECTED'); + cy.get(statsValue).eq(1).should('not.be.empty'); + cy.get(statsValue).eq(2).should('have.text', '2'); + cy.get(statsValue) + .eq(3) + .invoke('text') + .should('match', /\d+d \d+h \d+m \d+s/i); + cy.get(statsValue).eq(4).should('have.text', '2'); + cy.get(statsValue).eq(5).should('have.text', '0'); + cy.get(statsValue).eq(6).should('have.text', '0.00'); + cy.get(statsValue).eq(7).should('have.text', '0'); + cy.get(statsValue).eq(8).should('have.text', '0'); + cy.get(statsValue).eq(9).should('have.text', '0'); + cy.get(statsValue).eq(10).should('have.text', '0'); + cy.get(statsValue).eq(11).should('not.be.empty'); + cy.get(statsValue).eq(12).should('not.be.empty'); + cy.get(statsValue).eq(13).should('not.be.empty'); + if (Cypress.env('NIGHTLY_RUN') != true) { + cy.get(statsValue) + .eq(14) + .invoke('text') + .should('match', /v\d+\.\d+\.\d+/i); + } + cy.get(statsValue) + .eq(15) + .invoke('text') + .should('match', /\d+\.\d+\.\d+/i); + cy.get(statsValue).eq(16).should('not.be.empty'); + cy.get(statsValue).eq(17).should('not.be.empty'); + }); + + it('Block height should be updating', function () { + cy.get(statsValue) + .eq(1) + .invoke('text') + .then((blockHeightTxt) => { + cy.get(statsValue) + .eq(1) + .invoke('text') + .should((newBlockHeightTxt) => { + expect(blockHeightTxt).not.to.eq(newBlockHeightTxt); + }); + }); + }); + }); + + describe('Search bar', function () { + it('Successful search for specific id by block id', function () { + const blockId = '973624'; + search(blockId); + cy.url().should('include', blockId); + }); + + it('Successful search for specific id by tx hash', function () { + const txHash = + '9ED3718AA8308E7E08EC588EE7AADAF49711D2138860D8914B4D81A2054D9FB8'; + search(txHash); + cy.url().should('include', txHash); + }); + + it('Successful search for specific id by tx id', function () { + const txId = + '0x61DCCEBB955087F50D0B85382DAE138EDA9631BF1A4F92E563D528904AA38898'; + search(txId); + cy.url().should('include', txId); + }); + + it('Error message displayed when invalid search by wrong string length', function () { + search('9ED3718AA8308E7E08EC588EE7AADAF497D2138860D8914B4D81A2054D9FB8'); + validateSearchError("Something doesn't look right"); + }); + + it('Error message displayed when invalid search by invalid hash', function () { + search( + '9ED3718AA8308E7E08ECht8EE753DAF49711D2138860D8914B4D81A2054D9FB8' + ); + validateSearchError('Transaction is not hexadecimal'); + }); + + it('Error message displayed when searching empty field', function () { + cy.get('[data-testid="search"]').clear(); + cy.get('[data-testid="search-button"]').click(); + validateSearchError('Search required'); + }); + + function search(searchTxt) { + cy.get('[data-testid="search"]').clear().type(searchTxt); + cy.get('[data-testid="search-button"]').click(); + } + + function validateSearchError(expectedError) { + cy.get('[data-testid="search-error"]').should('have.text', expectedError); + } + }); +}); diff --git a/apps/explorer-e2e/src/integration/market.cy.js b/apps/explorer-e2e/src/integration/market.cy.js new file mode 100644 index 000000000..d63cab4da --- /dev/null +++ b/apps/explorer-e2e/src/integration/market.cy.js @@ -0,0 +1,21 @@ +import '../support/common.functions'; + +//Tests set to skip until market bug for capsule checkpoint is fixed +context.skip('Market page', function () { + describe('Verify elements on page', function () { + const marketHeaders = '[data-testid="markets-header"]'; + const marketNavigation = 'a[href="/markets"]'; + + it('Markets page is displayed', function () { + cy.visit('/'); + cy.get(marketNavigation).click(); + cy.common_validate_blocks_data_displayed(marketHeaders); + }); + + it('Markets page displayed on mobile', function () { + cy.common_switch_to_mobile_and_click_toggle(); + cy.get(marketNavigation).click(); + cy.common_validate_blocks_data_displayed(marketHeaders); + }); + }); +}); diff --git a/apps/explorer-e2e/src/integration/markets-page.feature b/apps/explorer-e2e/src/integration/markets-page.feature deleted file mode 100644 index 29fa18b7c..000000000 --- a/apps/explorer-e2e/src/integration/markets-page.feature +++ /dev/null @@ -1,14 +0,0 @@ -@todo -Feature: Markets Page - - @todo - Needs markets in capsule state - Scenario: Navigate to markets page - Given I am on the homepage - When I navigate to the markets page - Then markets page is correctly displayed - - @todo - Scenario: Navigate to markets page using mobile - Given I am on mobile and open the toggle menu - When I navigate to the markets page - Then markets page is correctly displayed diff --git a/apps/explorer-e2e/src/integration/network-page.feature b/apps/explorer-e2e/src/integration/network-page.feature deleted file mode 100644 index 466d9a568..000000000 --- a/apps/explorer-e2e/src/integration/network-page.feature +++ /dev/null @@ -1,11 +0,0 @@ -Feature: Network parameters Page - - Scenario: Navigate to network parameters page - Given I am on the homepage - When I navigate to network parameters page - Then network parameters page is correctly displayed - - Scenario: Navigate to network parameters page using mobile - Given I am on mobile and open the toggle menu - When I navigate to network parameters page - Then network parameters page is correctly displayed diff --git a/apps/explorer-e2e/src/integration/network.cy.js b/apps/explorer-e2e/src/integration/network.cy.js new file mode 100644 index 000000000..4898bc6bb --- /dev/null +++ b/apps/explorer-e2e/src/integration/network.cy.js @@ -0,0 +1,35 @@ +import '../support/common.functions'; + +context('Network parameters page', function () { + before('visit token home page', function () { + cy.visit('/'); + }); + + describe('Verify elements on page', function () { + const networkParametersNavigation = 'a[href="/network-parameters"]'; + + beforeEach('Navigate to network parameter page', function () { + cy.get(networkParametersNavigation).click(); + }); + + it('Network paremeter page is displayed', function () { + verifyNetworkParametersPageDisplayed(); + }); + + it('Network parameter page displayed on mobile', function () { + cy.common_switch_to_mobile_and_click_toggle(); + cy.get(networkParametersNavigation).click(); + verifyNetworkParametersPageDisplayed(); + }); + }); + + function verifyNetworkParametersPageDisplayed() { + cy.get('[data-testid="network-param-header"]').should( + 'have.text', + 'Network Parameters' + ); + cy.common_verify_json_parameters(18); + cy.common_verify_json_string_values(6); + cy.common_verify_json_int_values(7); + } +}); diff --git a/apps/explorer-e2e/src/integration/transactions-page.feature b/apps/explorer-e2e/src/integration/transactions-page.feature deleted file mode 100644 index edd8709ac..000000000 --- a/apps/explorer-e2e/src/integration/transactions-page.feature +++ /dev/null @@ -1,21 +0,0 @@ -@ignore -# tendermint times out getting txs on testnet atm -Feature: Transactions Page - - Scenario: Navigate to transactions page - Given I am on the homepage - When I navigate to the transactions page - Then transactions page is correctly displayed - - Scenario: Navigate to transaction details page - Given I am on the homepage - When I navigate to the transactions page - And I click on the top transaction - Then transaction details are displayed - - Scenario: Navigate to transactions page using mobile - Given I am on mobile and open the toggle menu - When I navigate to the transactions page - Then transactions page is correctly displayed - When I click on the top transaction - Then transaction details are displayed diff --git a/apps/explorer-e2e/src/integration/transactions.cy.js b/apps/explorer-e2e/src/integration/transactions.cy.js new file mode 100644 index 000000000..dfc9135fc --- /dev/null +++ b/apps/explorer-e2e/src/integration/transactions.cy.js @@ -0,0 +1,87 @@ +//Tests set to skip until transactions are generated after capsule start up +context.skip('Transactions page', function () { + before('visit token home page', function () { + cy.visit('/'); + }); + + describe('Verify elements on page', function () { + const transactionNavigation = 'a[href="/txs"]'; + const transactionRow = 'transaction-row'; + const txHash = 'hash'; + + beforeEach('Navigate to transactions page', function () { + cy.get(transactionNavigation).click(); + }); + + it('transactions are displayed', function () { + cy.get(transactionRow).should('have.length.above', 1); + }); + + it('transactions details page is displayed', function () { + clickTopTransaction(); + validateTxDetailsAreDisplayed(); + }); + + it('transactions details page is displayed in mobile', function () { + cy.common_switch_to_mobile_and_click_toggle(); + cy.get(transactionNavigation).click(); + clickTopTransaction(); + validateTxDetailsAreDisplayed(); + }); + + function clickTopTransaction() { + // eslint-disable-next-line cypress/no-unnecessary-waiting + cy.wait(1000); // Wait for transactions to load if there are any + cy.get('body').then(($body) => { + if ($body.find(transactionRow).length) { + cy.get(transactionRow) + .first() + .find('a') + .first() + .click({ force: true }); + } else { + cy.slack('Unable to find any transactions on page'); + cy.screenshot(); + } + }); + } + + function validateTxDetailsAreDisplayed() { + // eslint-disable-next-line cypress/no-unnecessary-waiting + cy.wait(1000); // Wait for transactions to load if there are any + cy.get('body').then(($body) => { + if ($body.find(txHash).length) { + cy.get(txHash).invoke('text').should('have.length', 64); + cy.get('submitted-by') + .find('a') + .then(($address) => { + cy.wrap($address).should('have.attr', 'href'); + cy.wrap($address).invoke('text').should('have.length', 66); + }); + cy.get('block').should('not.be.empty'); + cy.get('encoded-tnx').should('not.be.empty'); + cy.get('tx-type') + .should('not.be.empty') + .invoke('text') + .then((txTypeTxt) => { + if (txTypeTxt == 'Order Submission') { + cy.get('.hljs-attr') + .should('have.length.at.least', 8) + .each(($propertyName) => { + cy.wrap($propertyName).should('not.be.empty'); + }); + cy.get('.hljs-string') + .should('have.length.at.least', 8) + .each(($propertyValue) => { + cy.wrap($propertyValue).should('not.be.empty'); + }); + } + }); + } else { + cy.slack('Unable to find any transactions on page'); + cy.screenshot(); + } + }); + } + }); +}); diff --git a/apps/explorer-e2e/src/integration/validator.cy.js b/apps/explorer-e2e/src/integration/validator.cy.js new file mode 100644 index 000000000..a97bb7a62 --- /dev/null +++ b/apps/explorer-e2e/src/integration/validator.cy.js @@ -0,0 +1,28 @@ +import '../support/common.functions'; + +context('Validator page', function () { + describe('Verify elements on page', function () { + const validatorNavigation = 'a[href="/validators"]'; + + it('Validator page is displayed', function () { + cy.visit('/'); + cy.get(validatorNavigation).click(); + validateValidatorsDisplayed(); + }); + + it('Validator page is displayed on mobile', function () { + cy.common_switch_to_mobile_and_click_toggle(); + cy.get(validatorNavigation).click(); + validateValidatorsDisplayed(); + }); + + function validateValidatorsDisplayed() { + cy.get('[data-testid="tendermint-header"]').should( + 'have.text', + 'Tendermint data' + ); + cy.get('[data-testid="vega-header"]').should('have.text', 'Vega data'); + cy.get('[data-testid="vega-data"]').should('not.be.empty'); + } + }); +}); diff --git a/apps/explorer-e2e/src/integration/validators-page.feature b/apps/explorer-e2e/src/integration/validators-page.feature deleted file mode 100644 index 47b9a0eff..000000000 --- a/apps/explorer-e2e/src/integration/validators-page.feature +++ /dev/null @@ -1,11 +0,0 @@ -Feature: Validators Page - - Scenario: Navigate to validators page - Given I am on the homepage - When I navigate to the validators page - Then validators page is correctly displayed - - Scenario: Navigate to validators page using mobile - Given I am on mobile and open the toggle menu - When I navigate to the validators page - Then validators page is correctly displayed diff --git a/apps/explorer-e2e/src/plugins/index.js b/apps/explorer-e2e/src/plugins/index.js deleted file mode 100644 index 97abe0be2..000000000 --- a/apps/explorer-e2e/src/plugins/index.js +++ /dev/null @@ -1,75 +0,0 @@ -/// - -const webpackPreprocessor = require('@cypress/webpack-preprocessor'); -const webpack = require('webpack'); -const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); -const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); -const nodeExternals = require('webpack-node-externals'); - -/** - * @type {Cypress.PluginConfig} - */ -module.exports = (on, config) => { - on( - 'file:preprocessor', - webpackPreprocessor({ - webpackOptions: { - resolve: { - extensions: ['.ts', '.tsx', '.mjs', '.js', '.jsx'], - plugins: [ - new TsconfigPathsPlugin({ - configFile: config.env.tsConfig, - extensions: ['.ts', '.tsx', '.mjs', '.js', '.jsx'], - }), - ], - fallback: { - path: require.resolve('path-browserify'), - }, - }, - module: { - rules: [ - { - test: /\.([jt])sx?$/, - loader: 'ts-loader', - exclude: [/node_modules/], - options: { - configFile: config.env.tsConfig, - // https://github.com/TypeStrong/ts-loader/pull/685 - experimentalWatchApi: true, - transpileOnly: true, - }, - }, - { - test: /\.feature$/, - use: [ - { - loader: 'cypress-cucumber-preprocessor/loader', - }, - ], - }, - { - test: /\.features$/, - use: [ - { - loader: 'cypress-cucumber-preprocessor/lib/featuresLoader', - }, - ], - }, - ], - }, - plugins: [ - new ForkTsCheckerWebpackPlugin({ - typescript: { - enabled: true, - configFile: config.env.tsConfig, - }, - }), - new webpack.ProvidePlugin({ - process: 'process/browser', - }), - ], - externals: [nodeExternals()], - }, - }) - ); -}; diff --git a/apps/explorer-e2e/src/support/common.functions.js b/apps/explorer-e2e/src/support/common.functions.js new file mode 100644 index 000000000..c7759d726 --- /dev/null +++ b/apps/explorer-e2e/src/support/common.functions.js @@ -0,0 +1,53 @@ +Cypress.Commands.add( + 'common_validate_blocks_data_displayed', + function (headerTestId) { + cy.get(headerTestId).then(($assetHeaders) => { + const headersLength = Number($assetHeaders.length); + + cy.wrap($assetHeaders).each(($header) => { + expect($header).to.not.be.empty; + }); + + cy.get('.language-json') + .each(($asset) => { + expect($asset).to.not.be.empty; + }) + .then(($list) => { + expect($list).to.have.length(headersLength); + }); + }); + } +); + +Cypress.Commands.add('common_switch_to_mobile_and_click_toggle', function () { + cy.viewport('iphone-x'); + cy.visit('/'); + cy.get('[data-testid="open-menu"]').click(); +}); + +Cypress.Commands.add('common_verify_json_parameters', function (expectedNum) { + cy.get('.hljs-attr') + .should('have.length.at.least', expectedNum) + .each(($paramName) => { + cy.wrap($paramName).should('not.be.empty'); + }); +}); + +Cypress.Commands.add( + 'common_verify_json_string_values', + function (expectedNum) { + cy.get('.hljs-string') + .should('have.length.at.least', expectedNum) + .each(($paramValue) => { + cy.wrap($paramValue).should('not.be.empty'); + }); + } +); + +Cypress.Commands.add('common_verify_json_int_values', function (expectedNum) { + cy.get('.hljs-number') + .should('have.length.at.least', expectedNum) + .each(($paramValue) => { + cy.wrap($paramValue).should('not.be.empty'); + }); +}); diff --git a/apps/explorer-e2e/src/support/index.d.ts b/apps/explorer-e2e/src/support/index.d.ts new file mode 100644 index 000000000..2a7657dcd --- /dev/null +++ b/apps/explorer-e2e/src/support/index.d.ts @@ -0,0 +1,2 @@ +// type definitions for Cypress object "cy" +/// diff --git a/apps/explorer-e2e/src/support/pages/assets-page.ts b/apps/explorer-e2e/src/support/pages/assets-page.ts deleted file mode 100644 index 663b4b6b3..000000000 --- a/apps/explorer-e2e/src/support/pages/assets-page.ts +++ /dev/null @@ -1,9 +0,0 @@ -import BasePage from './base-page'; - -export default class AssetsPage extends BasePage { - assetHeader = 'asset-header'; - - validateAssetsDisplayed() { - this.validateBlockDataDisplayed(this.assetHeader); - } -} diff --git a/apps/explorer-e2e/src/support/pages/base-page.ts b/apps/explorer-e2e/src/support/pages/base-page.ts deleted file mode 100644 index 7c63641e6..000000000 --- a/apps/explorer-e2e/src/support/pages/base-page.ts +++ /dev/null @@ -1,100 +0,0 @@ -export default class BasePage { - transactionsUrl = '/txs'; - blocksUrl = '/blocks'; - partiesUrl = '/parties'; - assetsUrl = '/assets'; - genesisUrl = '/genesis'; - governanceUrl = '/governance'; - marketsUrl = '/markets'; - networkParametersUrl = '/network-parameters'; - validatorsUrl = '/validators'; - blockExplorerHeader = 'explorer-header'; - searchField = 'search'; - searchButton = 'search-button'; - searchError = 'search-error'; - openMobileMenuBtn = 'open-menu'; - - navigateToTxs() { - cy.get(`a[href='${this.transactionsUrl}']`).click(); - } - - navigateToBlocks() { - cy.get(`a[href='${this.blocksUrl}']`).click(); - } - - navigateToParties() { - cy.get(`a[href='${this.partiesUrl}']`).click(); - } - - navigateToAssets() { - cy.get(`a[href*='${this.assetsUrl}']`).click(); - } - - navigateToGenesis() { - cy.get(`a[href='${this.genesisUrl}']`).click(); - } - - navigateToGovernance() { - cy.get(`a[href='${this.governanceUrl}']`).click(); - } - - navigateToMarkets() { - cy.get(`a[href='${this.marketsUrl}']`).click(); - } - - navigateToNetworkParameters() { - cy.get(`a[href='${this.networkParametersUrl}']`).click(); - } - - navigateToValidators() { - cy.get(`a[href='${this.validatorsUrl}']`).click(); - } - - search(searchText: string) { - if (searchText) { - cy.getByTestId(this.searchField).type(searchText); - } - } - - clickSearch() { - cy.getByTestId(this.searchButton).click(); - } - - clickOnToggle() { - cy.getByTestId(this.openMobileMenuBtn).click({ force: true }); - } - - validateUrl(expectedUrl: string) { - cy.url().should('include', expectedUrl); - } - - validateSearchDisplayed() { - cy.getByTestId(this.blockExplorerHeader).should( - 'have.text', - 'Vega Explorer' - ); - cy.getByTestId(this.searchField).should('be.visible'); - } - - validateSearchErrorDisplayed(errorMessage: string) { - cy.getByTestId(this.searchError).should('have.text', errorMessage); - } - - validateBlockDataDisplayed(headerTestId: string) { - cy.getByTestId(headerTestId).then(($assetHeaders) => { - const headersAmount = Number($assetHeaders.length); - - cy.wrap($assetHeaders).each(($header) => { - expect($header).to.not.be.empty; - }); - - cy.get('.language-json') - .each(($asset) => { - expect($asset).to.not.be.empty; - }) - .then(($list) => { - expect($list).to.have.length(headersAmount); - }); - }); - } -} diff --git a/apps/explorer-e2e/src/support/pages/blocks-page.ts b/apps/explorer-e2e/src/support/pages/blocks-page.ts deleted file mode 100644 index 301299de5..000000000 --- a/apps/explorer-e2e/src/support/pages/blocks-page.ts +++ /dev/null @@ -1,146 +0,0 @@ -import BasePage from './base-page'; - -export default class BlocksPage extends BasePage { - blockRow = 'block-row'; - transactionsRow = 'transaction-row'; - blockHeight = 'block-height'; - numberOfTransactions = 'num-txs'; - validatorLink = 'validator-link'; - blockTime = 'block-time'; - refreshBtn = 'refresh'; - blockHeader = 'block-header'; - minedByValidator = 'block-validator'; - previousBlockBtn = 'previous-block'; - nextBlockBtn = 'next-block'; - jumpToBlockInput = 'block-input'; - jumpToBlockSubmit = 'go-submit'; - infiniteScrollWrapper = 'infinite-scroll-wrapper'; - - private waitForBlocksResponse() { - cy.contains('Loading...').should('not.exist', { timeout: 18000 }); - } - - validateBlocksPageDisplayed() { - this.waitForBlocksResponse(); - cy.getByTestId(this.blockRow).should('have.length.above', 1); - cy.getByTestId(this.blockHeight).first().should('not.be.empty'); - cy.getByTestId(this.numberOfTransactions).first().should('not.be.empty'); - cy.getByTestId(this.validatorLink).first().should('not.be.empty'); - cy.getByTestId(this.blockTime).first().should('not.be.empty'); - } - - clickOnTopBlockHeight() { - this.waitForBlocksResponse(); - cy.getByTestId(this.blockHeight).first().click(); - } - - validateBlockValidatorPage() { - cy.getByTestId(this.minedByValidator).should('not.be.empty'); - cy.getByTestId(this.blockTime).should('not.be.empty'); - cy.get('body').then(($body) => { - if ($body.find(`[data-testid=${this.transactionsRow}] > td`).length) { - cy.get(`[data-testid=${this.transactionsRow}] > td`).each(($cell) => { - cy.wrap($cell).should('not.be.empty'); - }); - } else { - cy.slack('Unable to find any transactions on page'); - cy.screenshot(); - } - }); - } - - navigateToPreviousBlock() { - cy.getByTestId(this.blockHeader) - .invoke('text') - .then(($blockHeaderTxt) => { - const blockHeight = parseInt($blockHeaderTxt.replace('BLOCK ', '')); - this.clickPreviousBlock(); - cy.getByTestId(this.blockHeader) - .invoke('text') - .then(($newBlockHeaderTxt) => { - const newBlockHeight = parseInt( - $newBlockHeaderTxt.replace('BLOCK ', '') - ); - expect(newBlockHeight).to.be.lessThan(blockHeight); - }); - }); - } - - navigateToNextBlock() { - cy.getByTestId(this.blockHeader) - .invoke('text') - .then(($blockHeaderTxt) => { - const blockHeight = parseInt($blockHeaderTxt.replace('BLOCK ', '')); - this.clickNextBlock(); - cy.getByTestId(this.blockHeader) - .invoke('text') - .then(($newBlockHeaderTxt) => { - const newBlockHeight = parseInt( - $newBlockHeaderTxt.replace('BLOCK ', '') - ); - expect(newBlockHeight).to.be.greaterThan(blockHeight); - }); - }); - } - - navigateToLastBlockOnPage() { - this.waitForBlocksResponse(); - cy.getByTestId(this.infiniteScrollWrapper).children().scrollTo('bottom'); - } - - navigateToOlderBlocksWithInfiniteScroll( - expectedBlocks: number, - scrollAttempts: number - ) { - cy.intercept('*blockchain?maxHeight*').as('blockchain_load'); - - cy.getByTestId(this.blockHeight) - .last() - .invoke('text') - .then(($initialLastBlockHeight) => { - for (let index = 0; index < scrollAttempts; index++) { - cy.getByTestId(this.infiniteScrollWrapper) - .children() - .children() - .invoke('css', 'height') - .then((scrollTarget) => { - cy.getByTestId(this.infiniteScrollWrapper) - .children() - .scrollTo(0, scrollTarget.toString(), { easing: 'linear' }) - .wait('@blockchain_load'); - - // eslint-disable-next-line cypress/no-unnecessary-waiting - cy.wait(50); // Need this as although network response has arrived it takes a few millisecs for the css height to expand - }); - } - - cy.getByTestId(this.blockHeight) - .last() - .invoke('text') - .then(($lastBlockHeight) => { - const totalBlocksLoadedSinceScrollBegan = - parseInt($initialLastBlockHeight) - parseInt($lastBlockHeight); - expect(totalBlocksLoadedSinceScrollBegan).to.be.at.least( - expectedBlocks - ); - }); - }); - } - - clickPreviousBlock() { - cy.getByTestId(this.previousBlockBtn).click(); - } - - clickNextBlock() { - cy.getByTestId(this.nextBlockBtn).click(); - } - - jumpToBlock(blockNumber: string) { - cy.getByTestId(this.jumpToBlockInput).type(blockNumber); - cy.getByTestId(this.jumpToBlockSubmit).click(); - } - - verifyPreviousBtnDisabled() { - cy.getByTestId(this.previousBlockBtn).find('button').should('be.disabled'); - } -} diff --git a/apps/explorer-e2e/src/support/pages/genesis-page.ts b/apps/explorer-e2e/src/support/pages/genesis-page.ts deleted file mode 100644 index 249f3a919..000000000 --- a/apps/explorer-e2e/src/support/pages/genesis-page.ts +++ /dev/null @@ -1,9 +0,0 @@ -import BasePage from './base-page'; - -export default class GenesisPage extends BasePage { - genesisHeader = 'genesis-header'; - - genesisFieldsDisplayed() { - this.validateBlockDataDisplayed(this.genesisHeader); - } -} diff --git a/apps/explorer-e2e/src/support/pages/home-page.ts b/apps/explorer-e2e/src/support/pages/home-page.ts deleted file mode 100644 index cc388b0e3..000000000 --- a/apps/explorer-e2e/src/support/pages/home-page.ts +++ /dev/null @@ -1,95 +0,0 @@ -import BasePage from './base-page'; -export default class HomePage extends BasePage { - statsEnvironmentTitle = 'stats-environment'; - statsTitle = 'stats-title'; - statsValue = 'stats-value'; - - verifyStatsEnvironment() { - const deployedEnv = Cypress.env('environment').toUpperCase(); - cy.getByTestId(this.statsEnvironmentTitle).should( - 'have.text', - `/ ${deployedEnv}` - ); - } - - verifyStatsTitlesDisplayed() { - const statTitles = [ - 'Status', - 'Height', - 'Validating nodes', - 'Uptime', - 'Total nodes', - 'Inactive nodes', - 'Total staked', - 'Backlog', - 'Trades / second', - 'Orders / block', - 'Orders / second', - 'Transactions / block', - 'Block time', - 'Time', - 'App', - 'Tendermint', - 'Up since', - 'Chain ID', - ]; - - cy.getByTestId(this.statsTitle).then(($list) => { - cy.wrap($list).should('have.length', 18); - }); - - cy.getByTestId(this.statsTitle) - .each(($title, index) => { - cy.wrap($title).should('have.text', statTitles[index]); - }) - .then(($list) => { - cy.wrap($list).should('have.length', 18); - }); - } - - verifyStatsValuesDisplayed() { - cy.getByTestId(this.statsValue).eq(0).should('have.text', 'CONNECTED'); - cy.getByTestId(this.statsValue).eq(1).should('not.be.empty'); - cy.getByTestId(this.statsValue).eq(2).should('have.text', '2'); - cy.getByTestId(this.statsValue) - .eq(3) - .invoke('text') - .should('match', /\d+d \d+h \d+m \d+s/i); - cy.getByTestId(this.statsValue).eq(4).should('have.text', '2'); - cy.getByTestId(this.statsValue).eq(5).should('have.text', '0'); - cy.getByTestId(this.statsValue).eq(6).should('not.be.empty'); - cy.getByTestId(this.statsValue).eq(7).should('have.text', '0'); - cy.getByTestId(this.statsValue).eq(8).should('have.text', '0'); - cy.getByTestId(this.statsValue).eq(9).should('have.text', '0'); - cy.getByTestId(this.statsValue).eq(10).should('have.text', '0'); - cy.getByTestId(this.statsValue).eq(11).should('not.be.empty'); - cy.getByTestId(this.statsValue).eq(12).should('not.be.empty'); - cy.getByTestId(this.statsValue).eq(13).should('not.be.empty'); - if (Cypress.env('NIGHTLY_RUN') != true) { - cy.getByTestId(this.statsValue) - .eq(14) - .invoke('text') - .should('match', /v\d+\.\d+\.\d+/i); - } - cy.getByTestId(this.statsValue) - .eq(15) - .invoke('text') - .should('match', /\d+\.\d+\.\d+/i); - cy.getByTestId(this.statsValue).eq(16).should('not.be.empty'); - cy.getByTestId(this.statsValue).eq(17).should('not.be.empty'); - } - - verifyStatsBlockHeightUpdating() { - cy.getByTestId(this.statsValue) - .eq(1) - .invoke('text') - .then((blockHeightTxt) => { - cy.getByTestId(this.statsValue) - .eq(1) - .invoke('text') - .should((newBlockHeightTxt) => { - expect(blockHeightTxt).not.to.eq(newBlockHeightTxt); - }); - }); - } -} diff --git a/apps/explorer-e2e/src/support/pages/markets-page.ts b/apps/explorer-e2e/src/support/pages/markets-page.ts deleted file mode 100644 index cf3680c68..000000000 --- a/apps/explorer-e2e/src/support/pages/markets-page.ts +++ /dev/null @@ -1,9 +0,0 @@ -import BasePage from './base-page'; - -export default class MarketsPage extends BasePage { - marketHeaders = 'markets-header'; - - validateMarketDataDisplayed() { - this.validateBlockDataDisplayed(this.marketHeaders); - } -} diff --git a/apps/explorer-e2e/src/support/pages/network-page.ts b/apps/explorer-e2e/src/support/pages/network-page.ts deleted file mode 100644 index 8c10c9a96..000000000 --- a/apps/explorer-e2e/src/support/pages/network-page.ts +++ /dev/null @@ -1,39 +0,0 @@ -import BasePage from './base-page'; - -export default class NetworkParametersPage extends BasePage { - networkParametersHeader = 'network-param-header'; - parameters = 'parameters'; - jsonParamNameClassName = '.hljs-attr'; - jsonParamValueStringClassName = '.hljs-string'; - jsonParamValueNumberClassName = '.hljs-number'; - parameterKeyValueRow = 'key-value-table-row'; - - verifyNetworkParametersDisplayed() { - cy.getByTestId(this.networkParametersHeader).should( - 'have.text', - 'Network Parameters' - ); - - cy.get(this.jsonParamNameClassName) - .should('have.length.at.least', 18) - .each(($paramName) => { - cy.wrap($paramName).should('not.be.empty'); - }); - cy.get(this.jsonParamValueStringClassName) - .should('have.length.at.least', 6) - .each(($paramValue) => { - cy.wrap($paramValue).should('not.be.empty'); - }); - - cy.get(this.jsonParamValueNumberClassName) - .should('have.length.at.least', 7) - .each(($paramValue) => { - cy.wrap($paramValue).should('not.be.empty'); - }); - - cy.getByTestId(this.parameterKeyValueRow).each(($row) => { - cy.wrap($row).find('dt').should('not.be.empty'); - cy.wrap($row).find('dd').should('not.be.empty'); - }); - } -} diff --git a/apps/explorer-e2e/src/support/pages/transactions-page.ts b/apps/explorer-e2e/src/support/pages/transactions-page.ts deleted file mode 100644 index ab072e208..000000000 --- a/apps/explorer-e2e/src/support/pages/transactions-page.ts +++ /dev/null @@ -1,85 +0,0 @@ -import BasePage from './base-page'; - -export default class TransactionsPage extends BasePage { - transactionsList = 'transactions-list'; - transactionRow = 'transaction-row'; - blockHeight = 'block-height'; - numberOfTransactions = 'num-txs'; - validatorLink = 'validator-link'; - blockTime = 'block-time'; - refreshBtn = 'refresh'; - txHash = 'hash'; - txSubmittedBy = 'submitted-by'; - txBlock = 'block'; - txEncodedTnx = 'encoded-tnx'; - txType = 'tx-type'; - - validateTransactionsPagedisplayed() { - // eslint-disable-next-line cypress/no-unnecessary-waiting - cy.wait(5000); // Wait for transactions to load if there are any - cy.getByTestId(this.transactionRow).should('have.length.above', 1); - } - - validateRefreshBtn() { - cy.intercept('GET', '**/blockchain').as('get-blockchain'); - cy.getByTestId(this.refreshBtn).click(); - cy.wait('@get-blockchain').its('response.statusCode').should('eq', 200); - } - - validateTxDetailsAreDisplayed() { - // TODO fail test when there are no txs once running with Capsule - // eslint-disable-next-line cypress/no-unnecessary-waiting - cy.wait(1000); // Wait for transactions to load if there are any - cy.get('body').then(($body) => { - if ($body.find(`[data-testid=${this.txHash}]`).length) { - cy.getByTestId(this.txHash).invoke('text').should('have.length', 64); - cy.getByTestId(this.txSubmittedBy) - .find('a') - .then(($address) => { - cy.wrap($address).should('have.attr', 'href'); - cy.wrap($address).invoke('text').should('have.length', 66); - }); - cy.getByTestId(this.txBlock).should('not.be.empty'); - cy.getByTestId(this.txEncodedTnx).should('not.be.empty'); - cy.getByTestId(this.txType) - .should('not.be.empty') - .invoke('text') - .then((txTypeTxt) => { - if (txTypeTxt == 'Order Submission') { - cy.get('.hljs-attr') - .should('have.length.at.least', 8) - .each(($propertyName) => { - cy.wrap($propertyName).should('not.be.empty'); - }); - cy.get('.hljs-string') - .should('have.length.at.least', 8) - .each(($propertyValue) => { - cy.wrap($propertyValue).should('not.be.empty'); - }); - } - }); - } else { - cy.slack('Unable to find any transactions on page'); - cy.screenshot(); - } - }); - } - - clickOnTopTransaction() { - // TODO fail test when there are no txs once running with Capsule - // eslint-disable-next-line cypress/no-unnecessary-waiting - cy.wait(1000); // Wait for transactions to load if there are any - cy.get('body').then(($body) => { - if ($body.find(`[data-testid=${this.transactionRow}]`).length) { - cy.getByTestId(this.transactionRow) - .first() - .find('a') - .first() - .click({ force: true }); - } else { - cy.slack('Unable to find any transactions on page'); - cy.screenshot(); - } - }); - } -} diff --git a/apps/explorer-e2e/src/support/pages/validators-page.ts b/apps/explorer-e2e/src/support/pages/validators-page.ts deleted file mode 100644 index 47129b2a0..000000000 --- a/apps/explorer-e2e/src/support/pages/validators-page.ts +++ /dev/null @@ -1,18 +0,0 @@ -import BasePage from './base-page'; - -export default class ValidatorPage extends BasePage { - tendermintHeader = 'tendermint-header'; - vegaHeader = 'vega-header'; - tendermintData = 'tendermint-data'; - vegaData = 'vega-data'; - - validateValidatorsDisplayed() { - cy.getByTestId(this.tendermintHeader).should( - 'have.text', - 'Tendermint data' - ); - cy.getByTestId(this.tendermintData).should('not.be.empty'); - cy.getByTestId(this.vegaHeader).should('have.text', 'Vega data'); - cy.getByTestId(this.vegaData).should('not.be.empty'); - } -} diff --git a/apps/explorer-e2e/src/support/step_definitions/asset-page-step.ts b/apps/explorer-e2e/src/support/step_definitions/asset-page-step.ts deleted file mode 100644 index ab9f14b8d..000000000 --- a/apps/explorer-e2e/src/support/step_definitions/asset-page-step.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Then, When } from 'cypress-cucumber-preprocessor/steps'; - -import AssetsPage from '../pages/assets-page'; -const assetPage = new AssetsPage(); - -When('I navigate to the asset page', () => { - assetPage.navigateToAssets(); -}); - -Then('asset page is correctly displayed', () => { - assetPage.validateAssetsDisplayed(); -}); diff --git a/apps/explorer-e2e/src/support/step_definitions/blocks-page.step.ts b/apps/explorer-e2e/src/support/step_definitions/blocks-page.step.ts deleted file mode 100644 index 99c4f25ce..000000000 --- a/apps/explorer-e2e/src/support/step_definitions/blocks-page.step.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { Then, When } from 'cypress-cucumber-preprocessor/steps'; - -import BlocksPage from '../pages/blocks-page'; -const blocksPage = new BlocksPage(); - -When('I navigate to the blocks page', () => { - blocksPage.navigateToBlocks(); -}); - -When('I click on top block', () => { - blocksPage.clickOnTopBlockHeight(); -}); - -When('jump to first block', () => { - blocksPage.jumpToBlock('1'); -}); - -Then('blocks page is correctly displayed', () => { - blocksPage.validateBlocksPageDisplayed(); -}); - -Then('validator block page is correctly displayed', () => { - blocksPage.validateBlockValidatorPage(); -}); - -Then('I am on the previous block when I click previous', () => { - blocksPage.navigateToPreviousBlock(); -}); - -Then('previous button is disabled', () => { - blocksPage.verifyPreviousBtnDisabled(); -}); - -Then('I am on the second block when I click next', () => { - blocksPage.navigateToNextBlock(); -}); - -Then('I scroll down to the last block on the page', () => { - blocksPage.navigateToLastBlockOnPage(); -}); - -Then( - 'I can expect to see at least {int} blocks if i scroll {int} times', - (expectedBlocks, scrollAttempts) => { - blocksPage.navigateToOlderBlocksWithInfiniteScroll( - expectedBlocks, - scrollAttempts - ); - } -); diff --git a/apps/explorer-e2e/src/support/step_definitions/common.step.ts b/apps/explorer-e2e/src/support/step_definitions/common.step.ts deleted file mode 100644 index 64973f249..000000000 --- a/apps/explorer-e2e/src/support/step_definitions/common.step.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Given, Then, When } from 'cypress-cucumber-preprocessor/steps'; -import BasePage from '../pages/base-page'; -const basePage = new BasePage(); - -Given('I am on mobile and open the toggle menu', () => { - cy.viewport('iphone-x'); - cy.visit('/'); - basePage.clickOnToggle(); -}); - -Given('I am on the homepage', () => { - cy.visit('/'); -}); - -When('I search for {string}', (searchText) => { - basePage.search(searchText); - basePage.clickSearch(); -}); - -Then('I am redirected to page containing id {string}', (expectedUrl) => { - basePage.validateUrl(expectedUrl); -}); - -Then('search error message {string} is displayed', (expectedErrorMsg) => { - basePage.validateSearchErrorDisplayed(expectedErrorMsg); -}); diff --git a/apps/explorer-e2e/src/support/step_definitions/home-page.step.ts b/apps/explorer-e2e/src/support/step_definitions/home-page.step.ts deleted file mode 100644 index 8258444cd..000000000 --- a/apps/explorer-e2e/src/support/step_definitions/home-page.step.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Then } from 'cypress-cucumber-preprocessor/steps'; - -import HomePage from '../pages/home-page'; -const homePage = new HomePage(); - -Then('the stats for deployed environment are correctly displayed', () => { - homePage.verifyStatsEnvironment(); - homePage.verifyStatsTitlesDisplayed(); - homePage.verifyStatsValuesDisplayed(); - homePage.verifyStatsBlockHeightUpdating(); -}); diff --git a/apps/explorer-e2e/src/support/step_definitions/markets-page-step.ts b/apps/explorer-e2e/src/support/step_definitions/markets-page-step.ts deleted file mode 100644 index 04961f51e..000000000 --- a/apps/explorer-e2e/src/support/step_definitions/markets-page-step.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Then, When } from 'cypress-cucumber-preprocessor/steps'; - -import MarketsPage from '../pages/markets-page'; -const marketsPage = new MarketsPage(); - -When('I navigate to the markets page', () => { - marketsPage.navigateToMarkets(); -}); - -Then('markets page is correctly displayed', () => { - marketsPage.validateMarketDataDisplayed(); -}); diff --git a/apps/explorer-e2e/src/support/step_definitions/network-page.step.ts b/apps/explorer-e2e/src/support/step_definitions/network-page.step.ts deleted file mode 100644 index 8cfda1d37..000000000 --- a/apps/explorer-e2e/src/support/step_definitions/network-page.step.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Then, When } from 'cypress-cucumber-preprocessor/steps'; -import NetworkPage from '../pages/network-page'; -const networkPage = new NetworkPage(); - -When('I navigate to network parameters page', () => { - networkPage.navigateToNetworkParameters(); -}); - -Then('network parameters page is correctly displayed', () => { - networkPage.verifyNetworkParametersDisplayed(); -}); diff --git a/apps/explorer-e2e/src/support/step_definitions/transaction-page.step.ts b/apps/explorer-e2e/src/support/step_definitions/transaction-page.step.ts deleted file mode 100644 index c4df608c9..000000000 --- a/apps/explorer-e2e/src/support/step_definitions/transaction-page.step.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Then, When } from 'cypress-cucumber-preprocessor/steps'; - -import TransactionsPage from '../pages/transactions-page'; -const transactionsPage = new TransactionsPage(); - -When('I navigate to the transactions page', () => { - transactionsPage.navigateToTxs(); -}); - -When('I navigate to the blocks page', () => { - transactionsPage.navigateToBlocks(); -}); - -When('I click on the top transaction', () => { - transactionsPage.clickOnTopTransaction(); -}); - -Then('transactions page is correctly displayed', () => { - transactionsPage.validateTransactionsPagedisplayed(); - transactionsPage.validateRefreshBtn(); -}); - -Then('blocks page is correctly displayed', () => { - transactionsPage.validateTransactionsPagedisplayed(); - transactionsPage.validateRefreshBtn(); -}); - -Then('transaction details are displayed', () => { - transactionsPage.validateTxDetailsAreDisplayed(); -}); diff --git a/apps/explorer-e2e/src/support/step_definitions/validators-page-step.ts b/apps/explorer-e2e/src/support/step_definitions/validators-page-step.ts deleted file mode 100644 index 40b325157..000000000 --- a/apps/explorer-e2e/src/support/step_definitions/validators-page-step.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Then, When } from 'cypress-cucumber-preprocessor/steps'; - -import ValidatorPage from '../pages/validators-page'; -const validatorsPage = new ValidatorPage(); - -When('I navigate to the validators page', () => { - validatorsPage.navigateToValidators(); -}); - -Then('validators page is correctly displayed', () => { - validatorsPage.validateValidatorsDisplayed(); -}); diff --git a/apps/simple-trading-app-e2e/src/integration/market-selector.test.ts b/apps/simple-trading-app-e2e/src/integration/market-selector.test.ts new file mode 100644 index 000000000..1b9dc07f9 --- /dev/null +++ b/apps/simple-trading-app-e2e/src/integration/market-selector.test.ts @@ -0,0 +1,87 @@ +describe('market selector', () => { + let markets; + before(() => { + cy.intercept('POST', '/query', (req) => { + const { body } = req; + if (body.operationName === 'SimpleMarkets') { + req.alias = `gqlSimpleMarketsQuery`; + } + }); + cy.visit('/markets'); + cy.wait('@gqlSimpleMarketsQuery').then((response) => { + if (response.response?.body?.data?.markets?.length) { + markets = response.response?.body?.data?.markets; + } + }); + }); + + it('should be properly rendered', () => { + if (markets) { + cy.visit(`/trading/${markets[0].id}`); + cy.get('input[placeholder="Search"]').should( + 'have.value', + markets[0].name + ); + cy.getByTestId('arrow-button').click(); + cy.getByTestId('market-pane').should('be.visible'); + cy.getByTestId('market-pane') + .children() + .find('[role="button"]') + .should('contain.text', markets[0].name); + cy.getByTestId('market-pane').children().find('[role="button"]').click(); + cy.getByTestId('market-pane').should('not.be.visible'); + } + }); + + it('typing should change list', () => { + if (markets) { + cy.visit(`/trading/${markets[0].id}`); + cy.get('input[placeholder="Search"]').type('{backspace}'); + cy.getByTestId('market-pane') + .children() + .find('[role="button"]') + .should('have.length', 1); + cy.get('input[placeholder="Search"]').clear(); + cy.get('input[placeholder="Search"]').type('a'); + const filtered = markets.filter((market) => market.name.match(/a/i)); + cy.getByTestId('market-pane') + .children() + .find('[role="button"]') + .should('have.length', filtered.length); + cy.getByTestId('market-pane') + .children() + .find('[role="button"]') + .last() + .click(); + cy.location('pathname').should( + 'eq', + `/trading/${filtered[filtered.length - 1].id}` + ); + cy.get('input[placeholder="Search"]').should( + 'have.value', + filtered[filtered.length - 1].name + ); + } + }); + + it('mobile view', () => { + if (markets) { + cy.viewport('iphone-xr'); + cy.visit(`/trading/${markets[0].id}`); + cy.get('[role="dialog"]').should('not.exist'); + cy.getByTestId('arrow-button').click(); + cy.get('[role="dialog"]').should('be.visible'); + cy.get('input[placeholder="Search"]').clear(); + cy.getByTestId('market-pane') + .children() + .find('[role="button"]') + .should('have.length', markets.length); + cy.pause(); + cy.getByTestId('dialog-close').click(); + cy.get('input[placeholder="Search"]').should( + 'have.value', + markets[0].name + ); + } + }); +}); diff --git a/apps/simple-trading-app/src/app/components/deal-ticket/deal-ticket-steps.tsx b/apps/simple-trading-app/src/app/components/deal-ticket/deal-ticket-steps.tsx index 7a00b91dd..db2ae968d 100644 --- a/apps/simple-trading-app/src/app/components/deal-ticket/deal-ticket-steps.tsx +++ b/apps/simple-trading-app/src/app/components/deal-ticket/deal-ticket-steps.tsx @@ -2,30 +2,45 @@ import * as React from 'react'; import { useForm, Controller } from 'react-hook-form'; import Box from '@mui/material/Box'; import { Stepper } from '../stepper'; -import type { DealTicketQuery_market, Order } from '@vegaprotocol/deal-ticket'; +import type { DealTicketQuery_market } from '@vegaprotocol/deal-ticket'; import { Button, InputError } from '@vegaprotocol/ui-toolkit'; import { ExpirySelector, SideSelector, TimeInForceSelector, TypeSelector, - getDefaultOrder, - useOrderValidation, - useOrderSubmit, DealTicketAmount, + MarketSelector, } from '@vegaprotocol/deal-ticket'; +import type { Order } from '@vegaprotocol/orders'; import { - OrderTimeInForce, - OrderType, + VegaWalletOrderTimeInForce as OrderTimeInForce, + VegaWalletOrderType as OrderType, VegaTxStatus, } from '@vegaprotocol/wallet'; import { t, addDecimal, toDecimal } from '@vegaprotocol/react-helpers'; +import { + getDefaultOrder, + useOrderValidation, + useOrderSubmit, +} from '@vegaprotocol/orders'; +import { useCallback } from 'react'; +import { useNavigate } from 'react-router-dom'; +import MarketNameRenderer from '../simple-market-list/simple-market-renderer'; interface DealTicketMarketProps { market: DealTicketQuery_market; } export const DealTicketSteps = ({ market }: DealTicketMarketProps) => { + const navigate = useNavigate(); + const setMarket = useCallback( + (marketId) => { + navigate(`/trading/${marketId}`); + }, + [navigate] + ); + const { register, control, @@ -70,7 +85,13 @@ export const DealTicketSteps = ({ market }: DealTicketMarketProps) => { { label: 'Select Asset', description: `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.`, - component:

{market.name}

, + component: ( + + ), }, { label: 'Select Order Type', diff --git a/apps/simple-trading-app/src/app/components/simple-market-list/simple-market-renderer.tsx b/apps/simple-trading-app/src/app/components/simple-market-list/simple-market-renderer.tsx index 5d26e330d..269cbe635 100644 --- a/apps/simple-trading-app/src/app/components/simple-market-list/simple-market-renderer.tsx +++ b/apps/simple-trading-app/src/app/components/simple-market-list/simple-market-renderer.tsx @@ -1,23 +1,23 @@ import React from 'react'; -import type { SimpleMarkets_markets } from './__generated__/SimpleMarkets'; +import type { MarketNames_markets } from '@vegaprotocol/deal-ticket'; import SimpleMarketExpires from './simple-market-expires'; interface Props { - data: SimpleMarkets_markets; + market: MarketNames_markets; } -const MarketNameRenderer = ({ data }: Props) => { +const MarketNameRenderer = ({ market }: Props) => { return (
- {data.name}{' '} + {market.name}{' '}
-
- {data.tradableInstrument.instrument.product.quoteName} +
+ {market.tradableInstrument.instrument.product.quoteName}
); diff --git a/apps/simple-trading-app/src/app/hooks/use-column-definitions.tsx b/apps/simple-trading-app/src/app/hooks/use-column-definitions.tsx index a3882fc93..b0f4b4457 100644 --- a/apps/simple-trading-app/src/app/hooks/use-column-definitions.tsx +++ b/apps/simple-trading-app/src/app/hooks/use-column-definitions.tsx @@ -21,7 +21,7 @@ const useColumnDefinitions = ({ onClick }: Props) => { minWidth: 300, field: 'name', cellRenderer: ({ data }: { data: SimpleMarketsType }) => ( - + ), }, { diff --git a/apps/simple-trading-app/tailwind.config.js b/apps/simple-trading-app/tailwind.config.js index d2fb3eb3d..e127aabb4 100644 --- a/apps/simple-trading-app/tailwind.config.js +++ b/apps/simple-trading-app/tailwind.config.js @@ -2,6 +2,7 @@ const { join } = require('path'); const { createGlobPatternsForDependencies } = require('@nrwl/next/tailwind'); const theme = require('../../libs/tailwindcss-config/src/theme-lite'); const vegaCustomClasses = require('../../libs/tailwindcss-config/src/vega-custom-classes'); +const vegaCustomClassesLite = require('../../libs/tailwindcss-config/src/vega-custom-classes-lite'); module.exports = { content: [ @@ -11,5 +12,5 @@ module.exports = { ], darkMode: 'class', theme, - plugins: [vegaCustomClasses], + plugins: [vegaCustomClasses, vegaCustomClassesLite], }; diff --git a/apps/static/src/assets/mainnet-tranches.json b/apps/static/src/assets/mainnet-tranches.json index 89906dd3b..827845f24 100644 --- a/apps/static/src/assets/mainnet-tranches.json +++ b/apps/static/src/assets/mainnet-tranches.json @@ -71,7 +71,7 @@ "tranche_end": "2023-12-05T00:00:00.000Z", "total_added": "129999.45", "total_removed": "0", - "locked_amount": "121814.203346243275662375", + "locked_amount": "120687.60294909203186805", "deposits": [ { "amount": "129999.45", @@ -521,7 +521,7 @@ "tranche_end": "2023-04-05T00:00:00.000Z", "total_added": "97499.58", "total_removed": "0", - "locked_amount": "62710.587599252519550582", + "locked_amount": "61605.4975572212290407", "deposits": [ { "amount": "97499.58", @@ -554,7 +554,7 @@ "tranche_end": "2023-04-05T00:00:00.000Z", "total_added": "135173.4239508", "total_removed": "0", - "locked_amount": "85714.54671688684878975345576", + "locked_amount": "84204.0794152667057160273426", "deposits": [ { "amount": "135173.4239508", @@ -587,7 +587,7 @@ "tranche_end": "2023-04-05T00:00:00.000Z", "total_added": "32499.86", "total_removed": "0", - "locked_amount": "26381.26124908313794121", + "locked_amount": "25916.368952284834442322", "deposits": [ { "amount": "32499.86", @@ -620,7 +620,7 @@ "tranche_end": "2023-04-05T00:00:00.000Z", "total_added": "10833.29", "total_removed": "0", - "locked_amount": "8586.844538876974346587", + "locked_amount": "8435.52660747719195897", "deposits": [ { "amount": "10833.29", @@ -708,7 +708,7 @@ "tranche_end": "2022-11-01T00:00:00.000Z", "total_added": "22500", "total_removed": "0", - "locked_amount": "14000.856261322464", + "locked_amount": "13420.127094655797", "deposits": [ { "amount": "15000", @@ -794,7 +794,7 @@ "tranche_end": "2023-06-02T00:00:00.000Z", "total_added": "1939928.38", "total_removed": "179856.049568108351", - "locked_amount": "1740598.83199851280435843", + "locked_amount": "1715358.109875174368620276", "deposits": [ { "amount": "1852091.69", @@ -1845,8 +1845,8 @@ "tranche_start": "2021-09-05T00:00:00.000Z", "tranche_end": "2022-09-30T00:00:00.000Z", "total_added": "60916.66666633337", - "total_removed": "19065.935569279679372649", - "locked_amount": "12885.5761687131318989695117159034", + "total_removed": "19238.601152747179372649", + "locked_amount": "12143.787034497502163478850106205", "deposits": [ { "amount": "2833.333333", @@ -1950,6 +1950,11 @@ "user": "0x1887D97F9C875108Aa6bE109B282f87A666472f2", "tx": "0xe828dbf343aeedc654737740783f3bd27ad5b932c6c468475db99025815974ed" }, + { + "amount": "172.6655834675", + "user": "0x9fd50776F133751E8Ae6abE1Be124638Bb917E05", + "tx": "0x38dcb1d6480ceb1b106d11bcf18fde600d00e3d7aa2221070f29c801583489ec" + }, { "amount": "381.5558078025", "user": "0x9fd50776F133751E8Ae6abE1Be124638Bb917E05", @@ -2676,6 +2681,12 @@ } ], "withdrawals": [ + { + "amount": "172.6655834675", + "user": "0x9fd50776F133751E8Ae6abE1Be124638Bb917E05", + "tranche_id": 13, + "tx": "0x38dcb1d6480ceb1b106d11bcf18fde600d00e3d7aa2221070f29c801583489ec" + }, { "amount": "381.5558078025", "user": "0x9fd50776F133751E8Ae6abE1Be124638Bb917E05", @@ -2726,8 +2737,8 @@ } ], "total_tokens": "4250", - "withdrawn_tokens": "3219.6582828575", - "remaining_tokens": "1030.3417171425" + "withdrawn_tokens": "3392.323866325", + "remaining_tokens": "857.676133675" }, { "address": "0xDFaF6D0a0102ea5e4688F95Eb22Dc353751a7563", @@ -3319,10 +3330,15 @@ "tranche_id": 10, "tranche_start": "2021-07-15T23:37:11.000Z", "tranche_end": "2021-07-15T23:37:11.000Z", - "total_added": "3790968.150000000000000001", - "total_removed": "3782778.640000000000000001", + "total_added": "3904968.150000000000000001", + "total_removed": "3896778.640000000000000001", "locked_amount": "0", "deposits": [ + { + "amount": "114000", + "user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f", + "tx": "0x167fe6c654897398dcfdab9305133b4410b15bac8f5a30bb1260a94a14a65aad" + }, { "amount": "30000", "user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f", @@ -3765,6 +3781,11 @@ } ], "withdrawals": [ + { + "amount": "114000", + "user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f", + "tx": "0x873061bbe5702251e087833b87033296fef9c6fb4f6c2be7586e1e74e20a4f52" + }, { "amount": "30000", "user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f", @@ -4150,6 +4171,12 @@ { "address": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f", "deposits": [ + { + "amount": "114000", + "user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f", + "tranche_id": 10, + "tx": "0x167fe6c654897398dcfdab9305133b4410b15bac8f5a30bb1260a94a14a65aad" + }, { "amount": "30000", "user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f", @@ -4248,6 +4275,12 @@ } ], "withdrawals": [ + { + "amount": "114000", + "user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f", + "tranche_id": 10, + "tx": "0x873061bbe5702251e087833b87033296fef9c6fb4f6c2be7586e1e74e20a4f52" + }, { "amount": "30000", "user": "0xb2d6DEC77558Cf8EdB7c428d23E70Eab0688544f", @@ -4339,8 +4372,8 @@ "tx": "0xac16a4ce688d40a482a59914d68c3a676592f8804ee8f0781b66a4ba5ccfbdfc" } ], - "total_tokens": "631651", - "withdrawn_tokens": "631651", + "total_tokens": "745651", + "withdrawn_tokens": "745651", "remaining_tokens": "0" }, { @@ -5360,9 +5393,9 @@ "tranche_id": 11, "tranche_start": "2021-09-03T00:00:00.000Z", "tranche_end": "2022-09-03T00:00:00.000Z", - "total_added": "22675.000000000000000003", - "total_removed": "6310.21478833278", - "locked_amount": "3447.5872138191271475004561306126331811", + "total_added": "24284.000000000000000003", + "total_removed": "6875.88980798578", + "locked_amount": "3376.2614414003058740004170970319634705", "deposits": [ { "amount": "25", @@ -5654,6 +5687,181 @@ "user": "0x7Eae1E0D58a8B1EAd803e2857Cc71262790BEF31", "tx": "0x9c4b31c46ccf46a8f5adf804c29b70bee174a52efa5551c2937527f276694120" }, + { + "amount": "25", + "user": "0x2f28F3Be9315cD7F2475F6500020262bd8505fA1", + "tx": "0xd4cd7cc10ebbfe143ff40dc3ef93a4832d23e9e6785b4bc33f5039ba1fd76946" + }, + { + "amount": "20", + "user": "0x2f28F3Be9315cD7F2475F6500020262bd8505fA1", + "tx": "0xe370ba99033dc4079338923b67da8e84d4ca5723b508fd46162f6e072b11cbb3" + }, + { + "amount": "20", + "user": "0x2f28F3Be9315cD7F2475F6500020262bd8505fA1", + "tx": "0x77437394f59f6eb88258449ae21c1dd447166779eed4b565fdefcf64686b9a8b" + }, + { + "amount": "20", + "user": "0x2f28F3Be9315cD7F2475F6500020262bd8505fA1", + "tx": "0xe88bf3aa7c87adfa65148183592f30bfe6d17e1ed31fdb7758604f6784f70be4" + }, + { + "amount": "25", + "user": "0x2f28F3Be9315cD7F2475F6500020262bd8505fA1", + "tx": "0xde28a1d3aa51121b8398580cfb7f09d03c7ff0a13d0e5bf12f088414a4ab49f4" + }, + { + "amount": "5", + "user": "0x2f28F3Be9315cD7F2475F6500020262bd8505fA1", + "tx": "0x13a798a6ae5a4b971e87864fa2fb3073879a09dd625bb4b621048684c278e7d7" + }, + { + "amount": "50", + "user": "0xf450648448be1117A854ab39FA30B398bAC88AEf", + "tx": "0x0ad493b8ba584c36fc6b74d67ae1836cc0359900cddc1a99e140ef1b19d551be" + }, + { + "amount": "30", + "user": "0xf450648448be1117A854ab39FA30B398bAC88AEf", + "tx": "0x79f2dfaa597a63643a3cdd74a6c4d7bbb3d762f61065efcc2dfe8360e0c77869" + }, + { + "amount": "60", + "user": "0xf450648448be1117A854ab39FA30B398bAC88AEf", + "tx": "0x443e4d4dbf20b1f57381ad5820bcb30fc6997d0ad24c5b893c14f5c2e2c1c8ff" + }, + { + "amount": "35", + "user": "0xf450648448be1117A854ab39FA30B398bAC88AEf", + "tx": "0xd35b23d198f2fb974a9d54410a594586ead6bb73be6e03f39e1c2d985d139318" + }, + { + "amount": "35", + "user": "0xf450648448be1117A854ab39FA30B398bAC88AEf", + "tx": "0x7acbd6411084bb539a023d5f026dc830220e958957953673a75f108e1d09617f" + }, + { + "amount": "200", + "user": "0xf450648448be1117A854ab39FA30B398bAC88AEf", + "tx": "0xbb38bbc96d8ea8cbd61cec953346a1e0329a0fcd34dbe494b3a88a5236b380de" + }, + { + "amount": "100", + "user": "0xf450648448be1117A854ab39FA30B398bAC88AEf", + "tx": "0xc6e187cdfb25f8f5c01fc699d0759cf482e9df697dd44cdc98a953072a25d034" + }, + { + "amount": "25", + "user": "0xf450648448be1117A854ab39FA30B398bAC88AEf", + "tx": "0x7922f20988fd31e30e772696891a11ed4b244654f1084535e02c97bcb3146364" + }, + { + "amount": "10", + "user": "0xf450648448be1117A854ab39FA30B398bAC88AEf", + "tx": "0x9c37f4918ecc76ab41a2ea159caa921d433393aaa1b7e0323c30b6a009e770b2" + }, + { + "amount": "20", + "user": "0xf450648448be1117A854ab39FA30B398bAC88AEf", + "tx": "0x0e7754b18eab077fc5c144a1a50358e2549baaf2981b53e583a8ad99061fa03c" + }, + { + "amount": "15", + "user": "0xf450648448be1117A854ab39FA30B398bAC88AEf", + "tx": "0x5e26adc0060f0cc3a5a8507be33b703e9d00ab6a794fe2621b2d512bcec109a6" + }, + { + "amount": "25", + "user": "0xf144fcebdb84fD3Bc070108673D6290940AAD756", + "tx": "0xebadbc1f72b4dde201bb069be7dadba684cf6931a7cc8e37114d375b40567728" + }, + { + "amount": "20", + "user": "0xf144fcebdb84fD3Bc070108673D6290940AAD756", + "tx": "0xedf869f1b26b121bec11919818f4810bd0e0418ebb2b5aeb2282e668f9849314" + }, + { + "amount": "10", + "user": "0xf144fcebdb84fD3Bc070108673D6290940AAD756", + "tx": "0xe1f87658af57653bd74b9142930c2ebd5e4315210919240c567e8682bf128837" + }, + { + "amount": "15", + "user": "0xf144fcebdb84fD3Bc070108673D6290940AAD756", + "tx": "0xe5bfa8b23591735541e37a8b9520cf2246e6d38b4f3253e5df1bb543460337c4" + }, + { + "amount": "25", + "user": "0xf144fcebdb84fD3Bc070108673D6290940AAD756", + "tx": "0xf6ad63410fc6de02497fb025bf90274bc187bac9dfe8d1f58bd637460ffa4bea" + }, + { + "amount": "5", + "user": "0xf144fcebdb84fD3Bc070108673D6290940AAD756", + "tx": "0x5735e2acfa821261700d8635c2f90510627cb41b709ed8d9b3562eab01d7d0fc" + }, + { + "amount": "2", + "user": "0xEeFF517294d2aa759274703a1B1C5ac81f9a754B", + "tx": "0x4626fe9fb39350c366f423b1e3e56234f635f1de462aa6d4246e88167d6bf451" + }, + { + "amount": "25", + "user": "0xf144fcebdb84fD3Bc070108673D6290940AAD756", + "tx": "0x20f42a87a88b4a26a757d421c2441639c25d1930090f4fc9b9e05664521c7b7e" + }, + { + "amount": "30", + "user": "0xf144fcebdb84fD3Bc070108673D6290940AAD756", + "tx": "0x0b28570bb5ca732c7f9c78d1b99036692bd53312a4dc8aee9bcd5a3f98b095b3" + }, + { + "amount": "20", + "user": "0xf144fcebdb84fD3Bc070108673D6290940AAD756", + "tx": "0x628b0fa1dd10c38fb2df1555794fc48aa3355d8fbcef5861ec085c18d8cd1f98" + }, + { + "amount": "10", + "user": "0xf144fcebdb84fD3Bc070108673D6290940AAD756", + "tx": "0x7cc81c556e905eff3433d9e87cddc7d36655b5c525fd3e763623ce5362b737df" + }, + { + "amount": "50", + "user": "0xf144fcebdb84fD3Bc070108673D6290940AAD756", + "tx": "0x30b7a49c36dc037021ec26013dd1ace6335985557b6e2a1f46463a31a7a814cf" + }, + { + "amount": "75", + "user": "0xf144fcebdb84fD3Bc070108673D6290940AAD756", + "tx": "0x6a812385fe8e104cedcb81615bcf2f65aa4ca4400a94524774878047b505d5cc" + }, + { + "amount": "25", + "user": "0x2f28F3Be9315cD7F2475F6500020262bd8505fA1", + "tx": "0xaf417ee6513450b1c5e4dee7b96442fe2d4fd64da94c7f1c75bcf8c302e02f89" + }, + { + "amount": "2", + "user": "0x0F71cA78EFa7bc202EcB5d2BB10125F41c7a1911", + "tx": "0xe0c40d5c2812ccbb87d17074a4b90c07a3ce5c9905de9bd446711fc4cbb43569" + }, + { + "amount": "300", + "user": "0x44d145E145B7811ad309032D4c5CdeB1bf044719", + "tx": "0xbec609feaff6762d61bc4cb06a3ccd5a97624b5dccf2cfcc4048ecad5e121f96" + }, + { + "amount": "175", + "user": "0x44d145E145B7811ad309032D4c5CdeB1bf044719", + "tx": "0xf5fcde86bf9cf88dd5e2d50803cc001eab3c05b185ed16151c4e93191507ed57" + }, + { + "amount": "100", + "user": "0x44d145E145B7811ad309032D4c5CdeB1bf044719", + "tx": "0x8e664532cfa2031eb5f6ce7c99cd673fa767599654a35b73d76407ed46763ad4" + }, { "amount": "75", "user": "0x3a380f7CFdEeb723228cA57d2795EA215094000d", @@ -8866,6 +9074,16 @@ "user": "0xC6D7208DaDEe4F431bd0f3f11E7d4c91fF51bfb2", "tx": "0xfeb269c626db43a4d16a117e47a21a148c9f911d708d97d9dfd0caf08e1c09e7" }, + { + "amount": "5.695719178", + "user": "0xc5467213593778E528f0eB8117cc7AFBC5b7491b", + "tx": "0xfaa7bf324021a5af466824d62ed9e9ebf691d52c9546e3bf12f6093a5990ba89" + }, + { + "amount": "559.979300475", + "user": "0x3a380f7CFdEeb723228cA57d2795EA215094000d", + "tx": "0x4c4e0fd7a8adbad24d6cc6e8fdf4f832ac9a39b2a04b954ec0d77e36a79c0e90" + }, { "amount": "4.429693048", "user": "0xc5467213593778E528f0eB8117cc7AFBC5b7491b", @@ -9611,6 +9829,270 @@ "withdrawn_tokens": "0", "remaining_tokens": "140" }, + { + "address": "0x2f28F3Be9315cD7F2475F6500020262bd8505fA1", + "deposits": [ + { + "amount": "25", + "user": "0x2f28F3Be9315cD7F2475F6500020262bd8505fA1", + "tranche_id": 11, + "tx": "0xd4cd7cc10ebbfe143ff40dc3ef93a4832d23e9e6785b4bc33f5039ba1fd76946" + }, + { + "amount": "20", + "user": "0x2f28F3Be9315cD7F2475F6500020262bd8505fA1", + "tranche_id": 11, + "tx": "0xe370ba99033dc4079338923b67da8e84d4ca5723b508fd46162f6e072b11cbb3" + }, + { + "amount": "20", + "user": "0x2f28F3Be9315cD7F2475F6500020262bd8505fA1", + "tranche_id": 11, + "tx": "0x77437394f59f6eb88258449ae21c1dd447166779eed4b565fdefcf64686b9a8b" + }, + { + "amount": "20", + "user": "0x2f28F3Be9315cD7F2475F6500020262bd8505fA1", + "tranche_id": 11, + "tx": "0xe88bf3aa7c87adfa65148183592f30bfe6d17e1ed31fdb7758604f6784f70be4" + }, + { + "amount": "25", + "user": "0x2f28F3Be9315cD7F2475F6500020262bd8505fA1", + "tranche_id": 11, + "tx": "0xde28a1d3aa51121b8398580cfb7f09d03c7ff0a13d0e5bf12f088414a4ab49f4" + }, + { + "amount": "5", + "user": "0x2f28F3Be9315cD7F2475F6500020262bd8505fA1", + "tranche_id": 11, + "tx": "0x13a798a6ae5a4b971e87864fa2fb3073879a09dd625bb4b621048684c278e7d7" + }, + { + "amount": "25", + "user": "0x2f28F3Be9315cD7F2475F6500020262bd8505fA1", + "tranche_id": 11, + "tx": "0xaf417ee6513450b1c5e4dee7b96442fe2d4fd64da94c7f1c75bcf8c302e02f89" + } + ], + "withdrawals": [], + "total_tokens": "140", + "withdrawn_tokens": "0", + "remaining_tokens": "140" + }, + { + "address": "0xf450648448be1117A854ab39FA30B398bAC88AEf", + "deposits": [ + { + "amount": "50", + "user": "0xf450648448be1117A854ab39FA30B398bAC88AEf", + "tranche_id": 11, + "tx": "0x0ad493b8ba584c36fc6b74d67ae1836cc0359900cddc1a99e140ef1b19d551be" + }, + { + "amount": "30", + "user": "0xf450648448be1117A854ab39FA30B398bAC88AEf", + "tranche_id": 11, + "tx": "0x79f2dfaa597a63643a3cdd74a6c4d7bbb3d762f61065efcc2dfe8360e0c77869" + }, + { + "amount": "60", + "user": "0xf450648448be1117A854ab39FA30B398bAC88AEf", + "tranche_id": 11, + "tx": "0x443e4d4dbf20b1f57381ad5820bcb30fc6997d0ad24c5b893c14f5c2e2c1c8ff" + }, + { + "amount": "35", + "user": "0xf450648448be1117A854ab39FA30B398bAC88AEf", + "tranche_id": 11, + "tx": "0xd35b23d198f2fb974a9d54410a594586ead6bb73be6e03f39e1c2d985d139318" + }, + { + "amount": "35", + "user": "0xf450648448be1117A854ab39FA30B398bAC88AEf", + "tranche_id": 11, + "tx": "0x7acbd6411084bb539a023d5f026dc830220e958957953673a75f108e1d09617f" + }, + { + "amount": "200", + "user": "0xf450648448be1117A854ab39FA30B398bAC88AEf", + "tranche_id": 11, + "tx": "0xbb38bbc96d8ea8cbd61cec953346a1e0329a0fcd34dbe494b3a88a5236b380de" + }, + { + "amount": "100", + "user": "0xf450648448be1117A854ab39FA30B398bAC88AEf", + "tranche_id": 11, + "tx": "0xc6e187cdfb25f8f5c01fc699d0759cf482e9df697dd44cdc98a953072a25d034" + }, + { + "amount": "25", + "user": "0xf450648448be1117A854ab39FA30B398bAC88AEf", + "tranche_id": 11, + "tx": "0x7922f20988fd31e30e772696891a11ed4b244654f1084535e02c97bcb3146364" + }, + { + "amount": "10", + "user": "0xf450648448be1117A854ab39FA30B398bAC88AEf", + "tranche_id": 11, + "tx": "0x9c37f4918ecc76ab41a2ea159caa921d433393aaa1b7e0323c30b6a009e770b2" + }, + { + "amount": "20", + "user": "0xf450648448be1117A854ab39FA30B398bAC88AEf", + "tranche_id": 11, + "tx": "0x0e7754b18eab077fc5c144a1a50358e2549baaf2981b53e583a8ad99061fa03c" + }, + { + "amount": "15", + "user": "0xf450648448be1117A854ab39FA30B398bAC88AEf", + "tranche_id": 11, + "tx": "0x5e26adc0060f0cc3a5a8507be33b703e9d00ab6a794fe2621b2d512bcec109a6" + } + ], + "withdrawals": [], + "total_tokens": "580", + "withdrawn_tokens": "0", + "remaining_tokens": "580" + }, + { + "address": "0xf144fcebdb84fD3Bc070108673D6290940AAD756", + "deposits": [ + { + "amount": "25", + "user": "0xf144fcebdb84fD3Bc070108673D6290940AAD756", + "tranche_id": 11, + "tx": "0xebadbc1f72b4dde201bb069be7dadba684cf6931a7cc8e37114d375b40567728" + }, + { + "amount": "20", + "user": "0xf144fcebdb84fD3Bc070108673D6290940AAD756", + "tranche_id": 11, + "tx": "0xedf869f1b26b121bec11919818f4810bd0e0418ebb2b5aeb2282e668f9849314" + }, + { + "amount": "10", + "user": "0xf144fcebdb84fD3Bc070108673D6290940AAD756", + "tranche_id": 11, + "tx": "0xe1f87658af57653bd74b9142930c2ebd5e4315210919240c567e8682bf128837" + }, + { + "amount": "15", + "user": "0xf144fcebdb84fD3Bc070108673D6290940AAD756", + "tranche_id": 11, + "tx": "0xe5bfa8b23591735541e37a8b9520cf2246e6d38b4f3253e5df1bb543460337c4" + }, + { + "amount": "25", + "user": "0xf144fcebdb84fD3Bc070108673D6290940AAD756", + "tranche_id": 11, + "tx": "0xf6ad63410fc6de02497fb025bf90274bc187bac9dfe8d1f58bd637460ffa4bea" + }, + { + "amount": "5", + "user": "0xf144fcebdb84fD3Bc070108673D6290940AAD756", + "tranche_id": 11, + "tx": "0x5735e2acfa821261700d8635c2f90510627cb41b709ed8d9b3562eab01d7d0fc" + }, + { + "amount": "25", + "user": "0xf144fcebdb84fD3Bc070108673D6290940AAD756", + "tranche_id": 11, + "tx": "0x20f42a87a88b4a26a757d421c2441639c25d1930090f4fc9b9e05664521c7b7e" + }, + { + "amount": "30", + "user": "0xf144fcebdb84fD3Bc070108673D6290940AAD756", + "tranche_id": 11, + "tx": "0x0b28570bb5ca732c7f9c78d1b99036692bd53312a4dc8aee9bcd5a3f98b095b3" + }, + { + "amount": "20", + "user": "0xf144fcebdb84fD3Bc070108673D6290940AAD756", + "tranche_id": 11, + "tx": "0x628b0fa1dd10c38fb2df1555794fc48aa3355d8fbcef5861ec085c18d8cd1f98" + }, + { + "amount": "10", + "user": "0xf144fcebdb84fD3Bc070108673D6290940AAD756", + "tranche_id": 11, + "tx": "0x7cc81c556e905eff3433d9e87cddc7d36655b5c525fd3e763623ce5362b737df" + }, + { + "amount": "50", + "user": "0xf144fcebdb84fD3Bc070108673D6290940AAD756", + "tranche_id": 11, + "tx": "0x30b7a49c36dc037021ec26013dd1ace6335985557b6e2a1f46463a31a7a814cf" + }, + { + "amount": "75", + "user": "0xf144fcebdb84fD3Bc070108673D6290940AAD756", + "tranche_id": 11, + "tx": "0x6a812385fe8e104cedcb81615bcf2f65aa4ca4400a94524774878047b505d5cc" + } + ], + "withdrawals": [], + "total_tokens": "310", + "withdrawn_tokens": "0", + "remaining_tokens": "310" + }, + { + "address": "0xEeFF517294d2aa759274703a1B1C5ac81f9a754B", + "deposits": [ + { + "amount": "2", + "user": "0xEeFF517294d2aa759274703a1B1C5ac81f9a754B", + "tranche_id": 11, + "tx": "0x4626fe9fb39350c366f423b1e3e56234f635f1de462aa6d4246e88167d6bf451" + } + ], + "withdrawals": [], + "total_tokens": "2", + "withdrawn_tokens": "0", + "remaining_tokens": "2" + }, + { + "address": "0x0F71cA78EFa7bc202EcB5d2BB10125F41c7a1911", + "deposits": [ + { + "amount": "2", + "user": "0x0F71cA78EFa7bc202EcB5d2BB10125F41c7a1911", + "tranche_id": 11, + "tx": "0xe0c40d5c2812ccbb87d17074a4b90c07a3ce5c9905de9bd446711fc4cbb43569" + } + ], + "withdrawals": [], + "total_tokens": "2", + "withdrawn_tokens": "0", + "remaining_tokens": "2" + }, + { + "address": "0x44d145E145B7811ad309032D4c5CdeB1bf044719", + "deposits": [ + { + "amount": "300", + "user": "0x44d145E145B7811ad309032D4c5CdeB1bf044719", + "tranche_id": 11, + "tx": "0xbec609feaff6762d61bc4cb06a3ccd5a97624b5dccf2cfcc4048ecad5e121f96" + }, + { + "amount": "175", + "user": "0x44d145E145B7811ad309032D4c5CdeB1bf044719", + "tranche_id": 11, + "tx": "0xf5fcde86bf9cf88dd5e2d50803cc001eab3c05b185ed16151c4e93191507ed57" + }, + { + "amount": "100", + "user": "0x44d145E145B7811ad309032D4c5CdeB1bf044719", + "tranche_id": 11, + "tx": "0x8e664532cfa2031eb5f6ce7c99cd673fa767599654a35b73d76407ed46763ad4" + } + ], + "withdrawals": [], + "total_tokens": "575", + "withdrawn_tokens": "0", + "remaining_tokens": "575" + }, { "address": "0x3a380f7CFdEeb723228cA57d2795EA215094000d", "deposits": [ @@ -9712,6 +10194,12 @@ } ], "withdrawals": [ + { + "amount": "559.979300475", + "user": "0x3a380f7CFdEeb723228cA57d2795EA215094000d", + "tranche_id": 11, + "tx": "0x4c4e0fd7a8adbad24d6cc6e8fdf4f832ac9a39b2a04b954ec0d77e36a79c0e90" + }, { "amount": "940.30940496195", "user": "0x3a380f7CFdEeb723228cA57d2795EA215094000d", @@ -9720,8 +10208,8 @@ } ], "total_tokens": "1745", - "withdrawn_tokens": "940.30940496195", - "remaining_tokens": "804.69059503805" + "withdrawn_tokens": "1500.28870543695", + "remaining_tokens": "244.71129456305" }, { "address": "0xB2BddeEb907797F9be51E3f9f75824f83cD71B67", @@ -15337,6 +15825,12 @@ } ], "withdrawals": [ + { + "amount": "5.695719178", + "user": "0xc5467213593778E528f0eB8117cc7AFBC5b7491b", + "tranche_id": 11, + "tx": "0xfaa7bf324021a5af466824d62ed9e9ebf691d52c9546e3bf12f6093a5990ba89" + }, { "amount": "4.429693048", "user": "0xc5467213593778E528f0eB8117cc7AFBC5b7491b", @@ -15405,8 +15899,8 @@ } ], "total_tokens": "200", - "withdrawn_tokens": "166.066761796", - "remaining_tokens": "33.933238204" + "withdrawn_tokens": "171.762480974", + "remaining_tokens": "28.237519026" }, { "address": "0x1775cc97E5c05Fde8b571ef75CA52d0A9ff19025", @@ -15430,8 +15924,8 @@ "tranche_start": "2022-03-05T00:00:00.000Z", "tranche_end": "2023-06-05T00:00:00.000Z", "total_added": "3732368.4671", - "total_removed": "74162.9780761646031", - "locked_amount": "2699195.71736283573760081335", + "total_removed": "106452.6400159857469", + "locked_amount": "2660409.42081862296035011689", "deposits": [ { "amount": "1998.95815", @@ -15600,6 +16094,16 @@ } ], "withdrawals": [ + { + "amount": "20676.42232", + "user": "0x93b478148FF792B00076B7EdC89Db1FdE7772079", + "tx": "0x5f6d3898764817a641875455e6506e8e93c5d9228ebccd69cf1452507279010e" + }, + { + "amount": "11613.2396198211438", + "user": "0x1A71e3ED1996CAbB91bB043f880CE963D601707e", + "tx": "0xd079047194931c11582a1eee4e8f50f1b7aa7a8c89681f61e649e9d280a2367e" + }, { "amount": "35594.05138", "user": "0x93b478148FF792B00076B7EdC89Db1FdE7772079", @@ -15706,6 +16210,12 @@ } ], "withdrawals": [ + { + "amount": "11613.2396198211438", + "user": "0x1A71e3ED1996CAbB91bB043f880CE963D601707e", + "tranche_id": 1, + "tx": "0xd079047194931c11582a1eee4e8f50f1b7aa7a8c89681f61e649e9d280a2367e" + }, { "amount": "19991.6435667249571", "user": "0x1A71e3ED1996CAbB91bB043f880CE963D601707e", @@ -15714,8 +16224,8 @@ } ], "total_tokens": "112323.67", - "withdrawn_tokens": "19991.6435667249571", - "remaining_tokens": "92332.0264332750429" + "withdrawn_tokens": "31604.8831865461009", + "remaining_tokens": "80718.7868134538991" }, { "address": "0x3D7944C81794Bc621076958cA0dC0F0b31BDc3e2", @@ -16065,6 +16575,12 @@ } ], "withdrawals": [ + { + "amount": "20676.42232", + "user": "0x93b478148FF792B00076B7EdC89Db1FdE7772079", + "tranche_id": 1, + "tx": "0x5f6d3898764817a641875455e6506e8e93c5d9228ebccd69cf1452507279010e" + }, { "amount": "35594.05138", "user": "0x93b478148FF792B00076B7EdC89Db1FdE7772079", @@ -16073,8 +16589,8 @@ } ], "total_tokens": "200000", - "withdrawn_tokens": "35594.05138", - "remaining_tokens": "164405.94862" + "withdrawn_tokens": "56270.4737", + "remaining_tokens": "143729.5263" }, { "address": "0xB523235B6c7C74DDB26b10E78bFb2d0Cb63Ae289", @@ -16143,8 +16659,8 @@ "tranche_start": "2022-06-05T00:00:00.000Z", "tranche_end": "2023-12-05T00:00:00.000Z", "total_added": "15788853.065470999700000001", - "total_removed": "12175.7143774436229", - "locked_amount": "14794728.4232451818250719454944430478169775", + "total_removed": "62889.84066484668888", + "locked_amount": "14657898.8329277585456883041909973431305758", "deposits": [ { "amount": "16249.93", @@ -16648,6 +17164,51 @@ "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", "tx": "0x14590efea8cd53e0bc5e102f8b82d80370d3487b18aece11f3338a9fdca9afc0" }, + { + "amount": "384.41201054941005", + "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", + "tx": "0x0cf55e46d1acaa85666bd5153644bcb804370c46b9f7b45f79ab345f7e124f03" + }, + { + "amount": "351.464056162431225", + "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", + "tx": "0x6fe7c383d5b75c3a0fe9169a3d69217e604177711b37c01d2073002c2fd1c0aa" + }, + { + "amount": "13356.160448", + "user": "0x29f1856E73262fc4372BBF442EbB550919459308", + "tx": "0x4dc966d71824dc346ead6f88d059cf0d74198ce99bbafb519f4713fce2a83696" + }, + { + "amount": "13362.766964", + "user": "0x1b956E6c00E238194B331eddEFF72Cb5f28A8d01", + "tx": "0xd91eb691332437c003dfc5ca3d48307fe9bfc7255d8c117db2aa542467560e6f" + }, + { + "amount": "5858.6529132790638", + "user": "0x1A71e3ED1996CAbB91bB043f880CE963D601707e", + "tx": "0x589e397cd552542f80df85299023979505989ffbe37617d74c1ce67e5d2bee32" + }, + { + "amount": "13365.398586", + "user": "0x74b521F96c641FD59631Dc6a24c558ed39D64352", + "tx": "0x341f9033e7d5b39bd80eb73c31838d2b81889ef9828847afccde8ec434295dfe" + }, + { + "amount": "3294.60955363161788", + "user": "0x4d982Ab0823fD2f48e934a7be2bb0a5374a26148", + "tx": "0x43da238e1b1f28aa8063ca322a3c87d534fb03c52acd56af0193014bf301d775" + }, + { + "amount": "370.8045045432414", + "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", + "tx": "0x3f16131c69129bfd1a0a0bcd5f474ccf7612fdadc3abf4dc7de85f26fb37c2ae" + }, + { + "amount": "369.857251237301625", + "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", + "tx": "0x148f389a5771abdc96c5a51c1fc0e306d135763c60f6839db6763690022a1a36" + }, { "amount": "579.636872035866225", "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", @@ -16826,6 +17387,30 @@ "tranche_id": 2, "tx": "0x14590efea8cd53e0bc5e102f8b82d80370d3487b18aece11f3338a9fdca9afc0" }, + { + "amount": "384.41201054941005", + "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", + "tranche_id": 2, + "tx": "0x0cf55e46d1acaa85666bd5153644bcb804370c46b9f7b45f79ab345f7e124f03" + }, + { + "amount": "351.464056162431225", + "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", + "tranche_id": 2, + "tx": "0x6fe7c383d5b75c3a0fe9169a3d69217e604177711b37c01d2073002c2fd1c0aa" + }, + { + "amount": "370.8045045432414", + "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", + "tranche_id": 2, + "tx": "0x3f16131c69129bfd1a0a0bcd5f474ccf7612fdadc3abf4dc7de85f26fb37c2ae" + }, + { + "amount": "369.857251237301625", + "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", + "tranche_id": 2, + "tx": "0x148f389a5771abdc96c5a51c1fc0e306d135763c60f6839db6763690022a1a36" + }, { "amount": "579.636872035866225", "user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b", @@ -16966,8 +17551,8 @@ } ], "total_tokens": "194999.1675", - "withdrawn_tokens": "12175.7143774436229", - "remaining_tokens": "182823.4531225563771" + "withdrawn_tokens": "13652.2521999360072", + "remaining_tokens": "181346.9153000639928" }, { "address": "0x89051CAb67Bc7F8CC44F7e270c6EDaf1EC57676c", @@ -17189,10 +17774,17 @@ "tx": "0x12bc4fefc73449e06f98facf0020f5bedebbb211bce00c070a6d4fbef9ffc522" } ], - "withdrawals": [], + "withdrawals": [ + { + "amount": "3294.60955363161788", + "user": "0x4d982Ab0823fD2f48e934a7be2bb0a5374a26148", + "tranche_id": 2, + "tx": "0x43da238e1b1f28aa8063ca322a3c87d534fb03c52acd56af0193014bf301d775" + } + ], "total_tokens": "49294.676", - "withdrawn_tokens": "0", - "remaining_tokens": "49294.676" + "withdrawn_tokens": "3294.60955363161788", + "remaining_tokens": "46000.06644636838212" }, { "address": "0x4092E429B149b5495265b608FD6Fae69fa5bfBe6", @@ -17219,10 +17811,17 @@ "tx": "0x2f62f0ae1720018d9d429b0d3c83add3dc99dc8f27bdd5f1b54cf47399ed71c5" } ], - "withdrawals": [], + "withdrawals": [ + { + "amount": "13365.398586", + "user": "0x74b521F96c641FD59631Dc6a24c558ed39D64352", + "tranche_id": 2, + "tx": "0x341f9033e7d5b39bd80eb73c31838d2b81889ef9828847afccde8ec434295dfe" + } + ], "total_tokens": "200000", - "withdrawn_tokens": "0", - "remaining_tokens": "200000" + "withdrawn_tokens": "13365.398586", + "remaining_tokens": "186634.601414" }, { "address": "0x834b777E3aB758C84FeBbfb9d6BB675bc4B16915", @@ -17354,10 +17953,17 @@ "tx": "0x23696a5f86dad7c80a11e3a87f555f79d40c4868e85964454663d7708bc2645d" } ], - "withdrawals": [], + "withdrawals": [ + { + "amount": "13362.766964", + "user": "0x1b956E6c00E238194B331eddEFF72Cb5f28A8d01", + "tranche_id": 2, + "tx": "0xd91eb691332437c003dfc5ca3d48307fe9bfc7255d8c117db2aa542467560e6f" + } + ], "total_tokens": "200000", - "withdrawn_tokens": "0", - "remaining_tokens": "200000" + "withdrawn_tokens": "13362.766964", + "remaining_tokens": "186637.233036" }, { "address": "0xA5d8726fFaD226e65D136ef9C2185750863b4850", @@ -17489,10 +18095,17 @@ "tx": "0xfc702de647f91b141bc4a828192c745d0bf84fc505a5f275017d07e362736161" } ], - "withdrawals": [], + "withdrawals": [ + { + "amount": "5858.6529132790638", + "user": "0x1A71e3ED1996CAbB91bB043f880CE963D601707e", + "tranche_id": 2, + "tx": "0x589e397cd552542f80df85299023979505989ffbe37617d74c1ce67e5d2bee32" + } + ], "total_tokens": "87676.33", - "withdrawn_tokens": "0", - "remaining_tokens": "87676.33" + "withdrawn_tokens": "5858.6529132790638", + "remaining_tokens": "81817.6770867209362" }, { "address": "0x9cF9B305601154C85ff86014d10a8762C802db0B", @@ -17699,10 +18312,17 @@ "tx": "0x0be42ac80b2dc5b80024b0d6a441dcd670e6850f93e1d8df341e2bcc8ae4b2e6" } ], - "withdrawals": [], + "withdrawals": [ + { + "amount": "13356.160448", + "user": "0x29f1856E73262fc4372BBF442EbB550919459308", + "tranche_id": 2, + "tx": "0x4dc966d71824dc346ead6f88d059cf0d74198ce99bbafb519f4713fce2a83696" + } + ], "total_tokens": "200000", - "withdrawn_tokens": "0", - "remaining_tokens": "200000" + "withdrawn_tokens": "13356.160448", + "remaining_tokens": "186643.839552" }, { "address": "0x87D71adAbC11c35aF566eD51421eDA0c82828a3A", @@ -18371,8 +18991,8 @@ "tranche_start": "2021-11-05T00:00:00.000Z", "tranche_end": "2023-05-05T00:00:00.000Z", "total_added": "14597706.0446472999", - "total_removed": "2164650.583392610391208927", - "locked_amount": "8007239.89262149386383419935049434", + "total_removed": "2413723.131389663831937297", + "locked_amount": "7880269.64303812390931654596122858", "deposits": [ { "amount": "129284.449", @@ -18591,6 +19211,71 @@ "user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b", "tx": "0xe7805f58cd369847197451266a778115f73cf37e0db5ebcc9f709fcc3921a39c" }, + { + "amount": "710.14095861784501725", + "user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b", + "tx": "0x7a12a85592f9696bb45f1f73672440fc3c1b3fbf151f5a8df5cf7ad260fce17a" + }, + { + "amount": "652.11713543465295625", + "user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b", + "tx": "0x84bd672f790c5873c15d35e0cc0592ecc2041e1423e8b70a0f63e228c925847f" + }, + { + "amount": "3578.334540394068", + "user": "0xCe068b733CDB8D1455E72Ede39705E209251269f", + "tx": "0x5a5e339b1b28edef055de4af68c950621be3a148be529eabf29767c00d559ca9" + }, + { + "amount": "2752.406564582654", + "user": "0x97E5985117F47c8d110Be1c422DdCB9bE9b46e62", + "tx": "0x607657d39483078a5d5b3a48c93138f3753e58978e7b10487c251d8ecce70c5d" + }, + { + "amount": "4678.855033842795", + "user": "0xc01F2E57554Bb392384feCA6a54c8E3A3Ca94E42", + "tx": "0x0e63d6ddac024730c1e6840b0127f60f3e631bcb223a9ca1c508d664caddeec8" + }, + { + "amount": "5780.03710676496", + "user": "0xe2E6F37cb1f1980418012BF69f43910d6Bc73e73", + "tx": "0x5e5297ae7a6951f21cbea97c9871f0f14f8708ad200ffd7d4c801e38b40cda1c" + }, + { + "amount": "3853.3118498576", + "user": "0xd4632B682228Db5f38E2283869AEe8c29ee6Eec8", + "tx": "0xa39e8088492ff0a57c645d3b97393fa3e7cf668ada70506f73f6424f90c4318e" + }, + { + "amount": "4128.34689631801", + "user": "0x83BB032E371D7f18195037d85b3A1d459322C20c", + "tx": "0xe042f84dfed2f96f75d5ee7e2936d661b061f34c5dde77fa1723e35a0a753ee1" + }, + { + "amount": "10176.8802962853078536", + "user": "0x17d93ca9263fCaEADf29088b3aCa8C290d5423FB", + "tx": "0x8e879f16287074e3fb87f4047ad962db3de3f7345aed1cab88a63b6f305045d6" + }, + { + "amount": "683.45853014152479025", + "user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b", + "tx": "0x44168decc7619b10c602ccf2058513e929aa81b2618d01224f59830e45f6839e" + }, + { + "amount": "211088.59999144065897027", + "user": "0xC62BC272187e0Fd48ed126B99ABD6e7943707E64", + "tx": "0x19c02ba7470821fc03fa6fa6d807c88885375386a09d21cce9ad5f5416252e0c" + }, + { + "amount": "684.18173298455492525", + "user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b", + "tx": "0x2c79d73d2f298d377192f2e84da773e8d589caccb253d89dbfd9c9ede10588fa" + }, + { + "amount": "305.8773603888092155", + "user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b", + "tx": "0x5b2ba568e3f60b624456972f011948b6870274b94ddba2f11eb876b4e875be1a" + }, { "amount": "509.31853983395369725", "user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b", @@ -20289,6 +20974,36 @@ "tranche_id": 3, "tx": "0xe7805f58cd369847197451266a778115f73cf37e0db5ebcc9f709fcc3921a39c" }, + { + "amount": "710.14095861784501725", + "user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b", + "tranche_id": 3, + "tx": "0x7a12a85592f9696bb45f1f73672440fc3c1b3fbf151f5a8df5cf7ad260fce17a" + }, + { + "amount": "652.11713543465295625", + "user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b", + "tranche_id": 3, + "tx": "0x84bd672f790c5873c15d35e0cc0592ecc2041e1423e8b70a0f63e228c925847f" + }, + { + "amount": "683.45853014152479025", + "user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b", + "tranche_id": 3, + "tx": "0x44168decc7619b10c602ccf2058513e929aa81b2618d01224f59830e45f6839e" + }, + { + "amount": "684.18173298455492525", + "user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b", + "tranche_id": 3, + "tx": "0x2c79d73d2f298d377192f2e84da773e8d589caccb253d89dbfd9c9ede10588fa" + }, + { + "amount": "305.8773603888092155", + "user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b", + "tranche_id": 3, + "tx": "0x5b2ba568e3f60b624456972f011948b6870274b94ddba2f11eb876b4e875be1a" + }, { "amount": "509.31853983395369725", "user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b", @@ -21635,8 +22350,8 @@ } ], "total_tokens": "359123.469575", - "withdrawn_tokens": "161944.3787235179023365", - "remaining_tokens": "197179.0908514820976635" + "withdrawn_tokens": "164980.154441085289241", + "remaining_tokens": "194143.315133914710759" }, { "address": "0xBdd412797c1B78535Afc5F71503b91fAbD0160fB", @@ -22193,10 +22908,17 @@ "tx": "0x06b06f5f5534572c8e30230b57c460edb3c4d4d5133fb21f3f7861be0218a6e0" } ], - "withdrawals": [], + "withdrawals": [ + { + "amount": "211088.59999144065897027", + "user": "0xC62BC272187e0Fd48ed126B99ABD6e7943707E64", + "tranche_id": 3, + "tx": "0x19c02ba7470821fc03fa6fa6d807c88885375386a09d21cce9ad5f5416252e0c" + } + ], "total_tokens": "460783.036347", - "withdrawn_tokens": "0", - "remaining_tokens": "460783.036347" + "withdrawn_tokens": "211088.59999144065897027", + "remaining_tokens": "249694.43635555934102973" }, { "address": "0x37fBC48109c4D71Bb0FFD44Bef0FE493b9Ff582a", @@ -22413,6 +23135,12 @@ } ], "withdrawals": [ + { + "amount": "2752.406564582654", + "user": "0x97E5985117F47c8d110Be1c422DdCB9bE9b46e62", + "tranche_id": 3, + "tx": "0x607657d39483078a5d5b3a48c93138f3753e58978e7b10487c251d8ecce70c5d" + }, { "amount": "9236.914528065455", "user": "0x97E5985117F47c8d110Be1c422DdCB9bE9b46e62", @@ -22427,8 +23155,8 @@ } ], "total_tokens": "31784.9", - "withdrawn_tokens": "11721.292988015548", - "remaining_tokens": "20063.607011984452" + "withdrawn_tokens": "14473.699552598202", + "remaining_tokens": "17311.200447401798" }, { "address": "0x17d93ca9263fCaEADf29088b3aCa8C290d5423FB", @@ -22441,6 +23169,12 @@ } ], "withdrawals": [ + { + "amount": "10176.8802962853078536", + "user": "0x17d93ca9263fCaEADf29088b3aCa8C290d5423FB", + "tranche_id": 3, + "tx": "0x8e879f16287074e3fb87f4047ad962db3de3f7345aed1cab88a63b6f305045d6" + }, { "amount": "1809.0490389033853472", "user": "0x17d93ca9263fCaEADf29088b3aCa8C290d5423FB", @@ -22455,8 +23189,8 @@ } ], "total_tokens": "31786.09544", - "withdrawn_tokens": "4298.1923904720520544", - "remaining_tokens": "27487.9030495279479456" + "withdrawn_tokens": "14475.072686757359908", + "remaining_tokens": "17311.022753242640092" }, { "address": "0xbEb7f1B85626Fd9BdA69765d7abb3832C542A62E", @@ -22484,6 +23218,12 @@ } ], "withdrawals": [ + { + "amount": "3853.3118498576", + "user": "0xd4632B682228Db5f38E2283869AEe8c29ee6Eec8", + "tranche_id": 3, + "tx": "0xa39e8088492ff0a57c645d3b97393fa3e7cf668ada70506f73f6424f90c4318e" + }, { "amount": "8440.209063021632", "user": "0xd4632B682228Db5f38E2283869AEe8c29ee6Eec8", @@ -22510,8 +23250,8 @@ } ], "total_tokens": "44499.2", - "withdrawn_tokens": "16410.88640274976", - "remaining_tokens": "28088.31359725024" + "withdrawn_tokens": "20264.19825260736", + "remaining_tokens": "24235.00174739264" }, { "address": "0xe2E6F37cb1f1980418012BF69f43910d6Bc73e73", @@ -22524,6 +23264,12 @@ } ], "withdrawals": [ + { + "amount": "5780.03710676496", + "user": "0xe2E6F37cb1f1980418012BF69f43910d6Bc73e73", + "tranche_id": 3, + "tx": "0x5e5297ae7a6951f21cbea97c9871f0f14f8708ad200ffd7d4c801e38b40cda1c" + }, { "amount": "12661.530439173696", "user": "0xe2E6F37cb1f1980418012BF69f43910d6Bc73e73", @@ -22544,8 +23290,8 @@ } ], "total_tokens": "66748.8", - "withdrawn_tokens": "24615.953230336032", - "remaining_tokens": "42132.846769663968" + "withdrawn_tokens": "30395.990337100992", + "remaining_tokens": "36352.809662899008" }, { "address": "0x83BB032E371D7f18195037d85b3A1d459322C20c", @@ -22558,6 +23304,12 @@ } ], "withdrawals": [ + { + "amount": "4128.34689631801", + "user": "0x83BB032E371D7f18195037d85b3A1d459322C20c", + "tranche_id": 3, + "tx": "0xe042f84dfed2f96f75d5ee7e2936d661b061f34c5dde77fa1723e35a0a753ee1" + }, { "amount": "11068.756947018642", "user": "0x83BB032E371D7f18195037d85b3A1d459322C20c", @@ -22578,8 +23330,8 @@ } ], "total_tokens": "47678.2", - "withdrawn_tokens": "17583.656769925972", - "remaining_tokens": "30094.543230074028" + "withdrawn_tokens": "21712.003666243982", + "remaining_tokens": "25966.196333756018" }, { "address": "0xCe068b733CDB8D1455E72Ede39705E209251269f", @@ -22592,6 +23344,12 @@ } ], "withdrawals": [ + { + "amount": "3578.334540394068", + "user": "0xCe068b733CDB8D1455E72Ede39705E209251269f", + "tranche_id": 3, + "tx": "0x5a5e339b1b28edef055de4af68c950621be3a148be529eabf29767c00d559ca9" + }, { "amount": "12003.2446429164", "user": "0xCe068b733CDB8D1455E72Ede39705E209251269f", @@ -22606,8 +23364,8 @@ } ], "total_tokens": "41320.2", - "withdrawn_tokens": "15237.323014538964", - "remaining_tokens": "26082.876985461036" + "withdrawn_tokens": "18815.657554933032", + "remaining_tokens": "22504.542445066968" }, { "address": "0xc01F2E57554Bb392384feCA6a54c8E3A3Ca94E42", @@ -22620,6 +23378,12 @@ } ], "withdrawals": [ + { + "amount": "4678.855033842795", + "user": "0xc01F2E57554Bb392384feCA6a54c8E3A3Ca94E42", + "tranche_id": 3, + "tx": "0x0e63d6ddac024730c1e6840b0127f60f3e631bcb223a9ca1c508d664caddeec8" + }, { "amount": "10248.998002731345", "user": "0xc01F2E57554Bb392384feCA6a54c8E3A3Ca94E42", @@ -22640,8 +23404,8 @@ } ], "total_tokens": "54034.5", - "withdrawn_tokens": "19926.772773219", - "remaining_tokens": "34107.727226781" + "withdrawn_tokens": "24605.627807061795", + "remaining_tokens": "29428.872192938205" } ] }, @@ -22650,8 +23414,8 @@ "tranche_start": "2021-10-05T00:00:00.000Z", "tranche_end": "2023-04-05T00:00:00.000Z", "total_added": "5778205.3912159303", - "total_removed": "1539572.873831600560839727", - "locked_amount": "2846805.505418249434976609440786892", + "total_removed": "1543188.041113165491270727", + "locked_amount": "2796638.79189818404440572191528324", "deposits": [ { "amount": "552496.6455", @@ -22800,6 +23564,11 @@ "user": "0x1b4B2372462b391006FAc69f09066Ae8504D75eC", "tx": "0x157dbf1b28465a758596604a1ee5874977d3b527d63e430ba1a4e21bb702f7be" }, + { + "amount": "3615.167281564930431", + "user": "0xafa64cCa337eFEE0AD827F6C2684e69275226e90", + "tx": "0x9c4cfa505550e13a41c2eb84a767412539ccae45bb280b5235423aadce942f2e" + }, { "amount": "4089.266768653121589", "user": "0xafa64cCa337eFEE0AD827F6C2684e69275226e90", @@ -23676,6 +24445,12 @@ } ], "withdrawals": [ + { + "amount": "3615.167281564930431", + "user": "0xafa64cCa337eFEE0AD827F6C2684e69275226e90", + "tranche_id": 4, + "tx": "0x9c4cfa505550e13a41c2eb84a767412539ccae45bb280b5235423aadce942f2e" + }, { "amount": "4089.266768653121589", "user": "0xafa64cCa337eFEE0AD827F6C2684e69275226e90", @@ -23756,8 +24531,8 @@ } ], "total_tokens": "331498.5873", - "withdrawn_tokens": "165797.579674556372286", - "remaining_tokens": "165701.007625443627714" + "withdrawn_tokens": "169412.746956121302717", + "remaining_tokens": "162085.840343878697283" }, { "address": "0x16da609341ed67750A8BCC5AAa2005471006Cd77", @@ -23839,8 +24614,8 @@ "tranche_start": "2022-06-05T00:00:00.000Z", "tranche_end": "2023-06-05T00:00:00.000Z", "total_added": "472355.6199999996", - "total_removed": "193.97337645", - "locked_amount": "427702.99067665172547620796854388", + "total_removed": "279.2296426169", + "locked_amount": "421557.080277297961550599391172", "deposits": [ { "amount": "3000", @@ -30464,6 +31239,26 @@ "user": "0xfeF4b56A370135A17Eef5ba8f5c308451a64Cf86", "tx": "0x7582fbf498c102fe792c436d1eed81e62295780af552caee732b3043a791ec4d" }, + { + "amount": "19.490455352", + "user": "0x0F71cA78EFa7bc202EcB5d2BB10125F41c7a1911", + "tx": "0x855e70f6d8fcced11047c4a93eeaf116ba5e67c01c72d56c47306ca0518d1d1a" + }, + { + "amount": "20.067884322", + "user": "0x0ab986C2eEe9A631Dfd770250b0BF04A6Dba1B45", + "tx": "0xbe5b2b288555ca7d800cef1d044b229400b806051914c78ccbf2abc04c58fd98" + }, + { + "amount": "3.1716581049", + "user": "0xbd6aeC2cd1Cc9fE80b4154E1cCD29bBe15854E8d", + "tx": "0xe816ba918bfec7c75908aa8cb32b5cfecb27f234a42610e37ebfce1183f91c78" + }, + { + "amount": "42.526268388", + "user": "0xA17b91BdDcE741528fDDF8E5738A767B3053ac18", + "tx": "0x51ce8527126c66bef66c723c6c9242b21796b90da616216420f6bce90910c285" + }, { "amount": "11.163032724", "user": "0xF5037DDA4A660d67560200f45380FF8364e35540", @@ -37491,10 +38286,17 @@ "tx": "0x057f65938b1360b6d2c4ebf5e789c67897cf60cb6a13f947004def03891afbd8" } ], - "withdrawals": [], + "withdrawals": [ + { + "amount": "42.526268388", + "user": "0xA17b91BdDcE741528fDDF8E5738A767B3053ac18", + "tranche_id": 5, + "tx": "0x51ce8527126c66bef66c723c6c9242b21796b90da616216420f6bce90910c285" + } + ], "total_tokens": "400", - "withdrawn_tokens": "0", - "remaining_tokens": "400" + "withdrawn_tokens": "42.526268388", + "remaining_tokens": "357.473731612" }, { "address": "0x8CF85d1ecC6eDd70000c57E31ff8FC18633F7328", @@ -38601,10 +39403,17 @@ "tx": "0x96a22c369645e8945b4047374a05332f4054b50a492c43092e8bb8e974a006b9" } ], - "withdrawals": [], + "withdrawals": [ + { + "amount": "19.490455352", + "user": "0x0F71cA78EFa7bc202EcB5d2BB10125F41c7a1911", + "tranche_id": 5, + "tx": "0x855e70f6d8fcced11047c4a93eeaf116ba5e67c01c72d56c47306ca0518d1d1a" + } + ], "total_tokens": "200", - "withdrawn_tokens": "0", - "remaining_tokens": "200" + "withdrawn_tokens": "19.490455352", + "remaining_tokens": "180.509544648" }, { "address": "0x6CaAD0A05F6e1AD7590f7c32d65d6fda8090A6E2", @@ -38631,10 +39440,17 @@ "tx": "0x96a22c369645e8945b4047374a05332f4054b50a492c43092e8bb8e974a006b9" } ], - "withdrawals": [], + "withdrawals": [ + { + "amount": "20.067884322", + "user": "0x0ab986C2eEe9A631Dfd770250b0BF04A6Dba1B45", + "tranche_id": 5, + "tx": "0xbe5b2b288555ca7d800cef1d044b229400b806051914c78ccbf2abc04c58fd98" + } + ], "total_tokens": "200", - "withdrawn_tokens": "0", - "remaining_tokens": "200" + "withdrawn_tokens": "20.067884322", + "remaining_tokens": "179.932115678" }, { "address": "0x000566B53E028d21e104E4320dE61c2314ef4064", @@ -44174,10 +44990,17 @@ "tx": "0xb1425d9b0d5f10c5b06236d6f9d61ebddd21c4027e0f41deb5ec227a1753c715" } ], - "withdrawals": [], + "withdrawals": [ + { + "amount": "3.1716581049", + "user": "0xbd6aeC2cd1Cc9fE80b4154E1cCD29bBe15854E8d", + "tranche_id": 5, + "tx": "0xe816ba918bfec7c75908aa8cb32b5cfecb27f234a42610e37ebfce1183f91c78" + } + ], "total_tokens": "30", - "withdrawn_tokens": "0", - "remaining_tokens": "30" + "withdrawn_tokens": "3.1716581049", + "remaining_tokens": "26.8283418951" }, { "address": "0x8aA46D13A453baBECba17E177E84AeBB7E3d605D", @@ -49590,7 +50413,7 @@ "tranche_start": "2021-12-05T00:00:00.000Z", "tranche_end": "2022-06-05T00:00:00.000Z", "total_added": "171288.42", - "total_removed": "34930.0423647506377", + "total_removed": "36329.8823647506377", "locked_amount": "0", "deposits": [ { @@ -53825,6 +54648,36 @@ "user": "0xc2AB91ad356B39307E7331c8900Efc4dBdbaF31F", "tx": "0xe9903a9a7d4f08e6a28c5f47719a75b5795aa7bf0e066b9289bcff76c9f514a7" }, + { + "amount": "250", + "user": "0x63F7e57dAa24bE6f8089442Ad0480d8cb6EAC9A7", + "tx": "0xcf7265db4128aef1b7199a5538d3e11333900aa48921416d8979aec7466a1fb9" + }, + { + "amount": "250", + "user": "0x52BDbCDc2A36778e49F8927D4b3F4e8BB240545f", + "tx": "0xf064ea5aa2586a564a3f560ef3edaeabb1398416ace3bdf8a027d644f4010313" + }, + { + "amount": "250", + "user": "0xcbc12eC06Bf59597818E531b0b002bD041b013b2", + "tx": "0xe98dc022b49a6fb74ba0ed11a8ba7c9ddf97478b93c753dc513986fe88a1cc90" + }, + { + "amount": "250", + "user": "0xb14972279FEc1b0D6C82B0b97595C6E47C07c45a", + "tx": "0x92205b946a3ad80a5932f3cebeba7456373097b48bdec1201e3349bd71353292" + }, + { + "amount": "150", + "user": "0x36C1803bddbE4DDF1CaEE6A3Ba7F935F4bC04CFE", + "tx": "0x64faa1c40a458e900ee051160b4aace05319a2aba230993a971be489c03489d1" + }, + { + "amount": "249.84", + "user": "0x5cce57661D758497446B57592D31667aafd60465", + "tx": "0x8d9b31eaaecaa4f74f05f93d33e61d0691eba3a6f23a9033dbfcaeca1c9a00c4" + }, { "amount": "60.4448387275", "user": "0xEe3183EcE9ee7d73Fb7bA7F4eB262A2dE68C42B0", @@ -58871,10 +59724,17 @@ "tx": "0x5f6fbdcd43bd83bf0d7a4beb3a2c7d4aa493ef5e4c0c6eeb6a4eb6a0ae4df05e" } ], - "withdrawals": [], + "withdrawals": [ + { + "amount": "250", + "user": "0x52BDbCDc2A36778e49F8927D4b3F4e8BB240545f", + "tranche_id": 6, + "tx": "0xf064ea5aa2586a564a3f560ef3edaeabb1398416ace3bdf8a027d644f4010313" + } + ], "total_tokens": "250", - "withdrawn_tokens": "0", - "remaining_tokens": "250" + "withdrawn_tokens": "250", + "remaining_tokens": "0" }, { "address": "0xcbc12eC06Bf59597818E531b0b002bD041b013b2", @@ -58886,10 +59746,17 @@ "tx": "0x5f6fbdcd43bd83bf0d7a4beb3a2c7d4aa493ef5e4c0c6eeb6a4eb6a0ae4df05e" } ], - "withdrawals": [], + "withdrawals": [ + { + "amount": "250", + "user": "0xcbc12eC06Bf59597818E531b0b002bD041b013b2", + "tranche_id": 6, + "tx": "0xe98dc022b49a6fb74ba0ed11a8ba7c9ddf97478b93c753dc513986fe88a1cc90" + } + ], "total_tokens": "250", - "withdrawn_tokens": "0", - "remaining_tokens": "250" + "withdrawn_tokens": "250", + "remaining_tokens": "0" }, { "address": "0x94FB32e3D5b9DDc3DDcaf6F174CAEeF2BCc6a83d", @@ -58938,10 +59805,17 @@ "tx": "0x5f6fbdcd43bd83bf0d7a4beb3a2c7d4aa493ef5e4c0c6eeb6a4eb6a0ae4df05e" } ], - "withdrawals": [], + "withdrawals": [ + { + "amount": "250", + "user": "0xb14972279FEc1b0D6C82B0b97595C6E47C07c45a", + "tranche_id": 6, + "tx": "0x92205b946a3ad80a5932f3cebeba7456373097b48bdec1201e3349bd71353292" + } + ], "total_tokens": "250", - "withdrawn_tokens": "0", - "remaining_tokens": "250" + "withdrawn_tokens": "250", + "remaining_tokens": "0" }, { "address": "0x0DCC2304f67eE437bd2f7bdA841450cBd1d267E8", @@ -62114,10 +62988,17 @@ "tx": "0x96a22c369645e8945b4047374a05332f4054b50a492c43092e8bb8e974a006b9" } ], - "withdrawals": [], + "withdrawals": [ + { + "amount": "150", + "user": "0x36C1803bddbE4DDF1CaEE6A3Ba7F935F4bC04CFE", + "tranche_id": 6, + "tx": "0x64faa1c40a458e900ee051160b4aace05319a2aba230993a971be489c03489d1" + } + ], "total_tokens": "150", - "withdrawn_tokens": "0", - "remaining_tokens": "150" + "withdrawn_tokens": "150", + "remaining_tokens": "0" }, { "address": "0xfFBDcC50b8e897f9f38AC04F11bBB09Cc8306003", @@ -66598,10 +67479,17 @@ "tx": "0xd23813c30e93f3867eaa257b7aef7052a050b1ee1c1a90102a3f40c5d989fe82" } ], - "withdrawals": [], + "withdrawals": [ + { + "amount": "250", + "user": "0x63F7e57dAa24bE6f8089442Ad0480d8cb6EAC9A7", + "tranche_id": 6, + "tx": "0xcf7265db4128aef1b7199a5538d3e11333900aa48921416d8979aec7466a1fb9" + } + ], "total_tokens": "250", - "withdrawn_tokens": "0", - "remaining_tokens": "250" + "withdrawn_tokens": "250", + "remaining_tokens": "0" }, { "address": "0xAD19C8eef5022966c6E601E6A4f2103C73f6B980", @@ -68194,10 +69082,17 @@ "tx": "0xb59405747c8088945a412703637a7b422f3639439ec2ee15e180c0a2a0d71ee4" } ], - "withdrawals": [], + "withdrawals": [ + { + "amount": "249.84", + "user": "0x5cce57661D758497446B57592D31667aafd60465", + "tranche_id": 6, + "tx": "0x8d9b31eaaecaa4f74f05f93d33e61d0691eba3a6f23a9033dbfcaeca1c9a00c4" + } + ], "total_tokens": "249.84", - "withdrawn_tokens": "0", - "remaining_tokens": "249.84" + "withdrawn_tokens": "249.84", + "remaining_tokens": "0" }, { "address": "0x3E0a6071c887155fD43f9e66E48502063405ACf5", @@ -101584,7 +102479,7 @@ "tranche_start": "2021-11-05T00:00:00.000Z", "tranche_end": "2021-11-05T00:00:00.000Z", "total_added": "2576065.7689906998", - "total_removed": "1600042.522159331", + "total_removed": "1681357.175632331", "locked_amount": "0", "deposits": [ { @@ -101794,6 +102689,11 @@ } ], "withdrawals": [ + { + "amount": "81314.653473", + "user": "0xC62BC272187e0Fd48ed126B99ABD6e7943707E64", + "tx": "0x5d19397cec815c35463d18a5d00f90787f8d3d09f2cad7a421cc65c18a7e2371" + }, { "amount": "3168.73649625", "user": "0x7043Da7e9437b01075AdEd8ceaEC8595427895eB", @@ -102360,10 +103260,17 @@ "tx": "0x0466970ae676c330fbb29b2ed0e31d5e4fd297d19b3eff7f8a22ed1774932766" } ], - "withdrawals": [], + "withdrawals": [ + { + "amount": "81314.653473", + "user": "0xC62BC272187e0Fd48ed126B99ABD6e7943707E64", + "tranche_id": 8, + "tx": "0x5d19397cec815c35463d18a5d00f90787f8d3d09f2cad7a421cc65c18a7e2371" + } + ], "total_tokens": "81314.653473", - "withdrawn_tokens": "0", - "remaining_tokens": "81314.653473" + "withdrawn_tokens": "81314.653473", + "remaining_tokens": "0" }, { "address": "0xaAeD573103e3f981867C4cd31c6674DE1c8a13c3", diff --git a/apps/static/src/assets/stagnet1-tranches.json b/apps/static/src/assets/stagnet1-tranches.json index 34af86644..1d41d76ec 100644 --- a/apps/static/src/assets/stagnet1-tranches.json +++ b/apps/static/src/assets/stagnet1-tranches.json @@ -38,7 +38,7 @@ "tranche_end": "2022-11-26T13:48:10.000Z", "total_added": "100", "total_removed": "0", - "locked_amount": "38.375643708777274", + "locked_amount": "37.074508498224257", "deposits": [ { "amount": "100", @@ -242,7 +242,7 @@ "tranche_end": "2022-10-12T00:53:20.000Z", "total_added": "1100", "total_removed": "673.04388635", - "locked_amount": "284.894035388127847", + "locked_amount": "270.58154807204466", "deposits": [ { "amount": "1000", diff --git a/apps/static/src/assets/testnet-tranches.json b/apps/static/src/assets/testnet-tranches.json index cd9127b88..0a0b6b2d2 100644 --- a/apps/static/src/assets/testnet-tranches.json +++ b/apps/static/src/assets/testnet-tranches.json @@ -69,7 +69,7 @@ "tranche_end": "2022-10-12T00:53:20.000Z", "total_added": "1010.000000000000000001", "total_removed": "668.4622323651", - "locked_amount": "261.58452340182647770025899457762557077", + "locked_amount": "248.4430577752410060002459832255200406", "deposits": [ { "amount": "1000", diff --git a/apps/token-e2e/cypress.config.js b/apps/token-e2e/cypress.config.js index 6cd68facd..0a2bcad52 100644 --- a/apps/token-e2e/cypress.config.js +++ b/apps/token-e2e/cypress.config.js @@ -18,6 +18,7 @@ module.exports = defineConfig({ env: { ethProviderUrl: 'http://localhost:8545/', ethWalletPublicKey: '0xEe7D375bcB50C26d52E1A4a472D8822A2A22d94F', + ethWalletPublicKeyTruncated: '0xEe7D…d94F', ethStakingBridgeContractAddress: '0x9135f5afd6F055e731bca2348429482eE614CFfA', vegaWalletName: 'capsule_wallet', diff --git a/apps/token-e2e/src/integration/flow/staking-flow.cy.js b/apps/token-e2e/src/integration/flow/staking-flow.cy.js index 87e094505..46d5618db 100644 --- a/apps/token-e2e/src/integration/flow/staking-flow.cy.js +++ b/apps/token-e2e/src/integration/flow/staking-flow.cy.js @@ -1,31 +1,28 @@ -/// -import navigation from '../../locators/navigation.locators'; -import staking from '../../locators/staking.locators'; -import wallet from '../../locators/wallet.locators'; -import '../../support/staking.functions'; -import '../../support/vega-wallet.functions'; -import '../../support/eth-wallet.functions'; -import '../../support/wallet-teardown.functions'; +const pageSpinner = 'splash-loader'; +const menuBar = 'nav'; +const validatorList = '[data-testid="node-list-item-name"]'; +const removeStakeRadioButton = '[data-testid="remove-stake-radio"]'; +const tokenAmountInputBox = '[data-testid="token-amount-input"]'; +const tokenSubmitButton = '[data-testid="token-input-submit-button"]'; +const stakeNextEpochValue = '[data-testid="stake-next-epoch"]'; +const vegaWalletContainer = '[data-testid="vega-wallet"]'; const vegaWalletPublicKeyShort = Cypress.env('vegaWalletPublicKeyShort'); -context('Staking Tab - with eth and vega wallets connected', function () { +context('Staking Flow - with eth and vega wallets connected', function () { before('visit staking tab and connect vega wallet', function () { cy.vega_wallet_import(); cy.visit('/'); - cy.get(navigation.section, { timeout: 20000 }).should('be.visible'); + cy.get(menuBar, { timeout: 20000 }).should('be.visible'); cy.vega_wallet_connect(); cy.vega_wallet_set_specified_approval_amount('1000'); cy.reload(); - cy.get(navigation.section, { timeout: 20000 }).should('be.visible'); + cy.get(menuBar, { timeout: 20000 }).should('be.visible'); cy.ethereum_wallet_connect(); - cy.get(navigation.staking).first().click(); - cy.get(navigation.spinner, { timeout: 20000 }).should('not.exist'); - cy.get(staking.validatorNames).first().invoke('text').as('validatorName'); - cy.get(staking.validatorNames) - .last() - .invoke('text') - .as('otherValidatorName'); + cy.navigate_to('staking'); + cy.get(pageSpinner, { timeout: 20000 }).should('not.exist'); + cy.get(validatorList).first().invoke('text').as('validatorName'); + cy.get(validatorList).last().invoke('text').as('otherValidatorName'); }); describe('Eth wallet - contains VEGA tokens', function () { @@ -33,7 +30,7 @@ context('Staking Tab - with eth and vega wallets connected', function () { 'teardown wallet & drill into a specific validator', function () { cy.vega_wallet_teardown(); - cy.get(navigation.staking).first().click(); + cy.navigate_to('staking'); } ); @@ -47,37 +44,37 @@ context('Staking Tab - with eth and vega wallets connected', function () { ); cy.get('button').contains('Select a validator to nominate').click(); - cy.get(staking.validatorNames).contains(this.validatorName).click(); + cy.get(validatorList).contains(this.validatorName).click(); cy.staking_validator_page_add_stake('2'); - cy.vega_wallet_check_validator_stake_next_epoch_value_is( + vega_wallet_check_validator_stake_next_epoch_value_is( this.validatorName, '2.000000000000000000' ); cy.vega_wallet_check_unstaked_value_is('1.000000000000000000'); - cy.vega_wallet_check_validator_staked_value_is( + vega_wallet_check_validator_staked_value_is( this.validatorName, '2.000000000000000000' ); - cy.staking_validator_page_check_stake_next_epoch_value('2.0'); - cy.staking_validator_page_check_stake_this_epoch_value('2.0'); + staking_validator_page_check_stake_next_epoch_value('2.0'); + staking_validator_page_check_stake_this_epoch_value('2.0'); }); it('Able to stake against mulitple validators', function () { cy.staking_page_associate_tokens('5'); cy.vega_wallet_check_unstaked_value_is('5.000000000000000000'); cy.get('button').contains('Select a validator to nominate').click(); - cy.get(staking.validatorNames).contains(this.validatorName).click(); + cy.get(validatorList).contains(this.validatorName).click(); cy.staking_validator_page_add_stake('2'); - cy.vega_wallet_check_validator_staked_value_is( + vega_wallet_check_validator_staked_value_is( this.validatorName, '2.000000000000000000' ); - cy.get(navigation.staking).first().click(); - cy.get(staking.validatorNames).contains(this.otherValidatorName).click(); + cy.navigate_to('staking'); + cy.get(validatorList).contains(this.otherValidatorName).click(); cy.staking_validator_page_add_stake('1'); - cy.vega_wallet_check_validator_staked_value_is( + vega_wallet_check_validator_staked_value_is( this.otherValidatorName, '1.000000000000000000' ); @@ -89,37 +86,37 @@ context('Staking Tab - with eth and vega wallets connected', function () { cy.vega_wallet_check_unstaked_value_is('4.000000000000000000'); cy.get('button').contains('Select a validator to nominate').click(); - cy.get(staking.validatorNames).contains(this.validatorName).click(); + cy.get(validatorList).contains(this.validatorName).click(); cy.staking_validator_page_add_stake('3'); - cy.staking_validator_page_check_stake_next_epoch_value('3.0'); - cy.vega_wallet_check_validator_stake_next_epoch_value_is( + staking_validator_page_check_stake_next_epoch_value('3.0'); + vega_wallet_check_validator_stake_next_epoch_value_is( this.validatorName, '3.000000000000000000' ); cy.vega_wallet_check_unstaked_value_is('1.000000000000000000'); - cy.get(navigation.staking).first().click(); - cy.get(staking.validatorNames).contains(this.validatorName).click(); + cy.navigate_to('staking'); + cy.get(validatorList).contains(this.validatorName).click(); cy.staking_validator_page_removeStake('1'); - cy.staking_validator_page_check_stake_next_epoch_value('2.0'); - cy.staking_validator_page_check_stake_this_epoch_value('3.0'); - cy.vega_wallet_check_validator_stake_next_epoch_value_is( + staking_validator_page_check_stake_next_epoch_value('2.0'); + staking_validator_page_check_stake_this_epoch_value('3.0'); + vega_wallet_check_validator_stake_next_epoch_value_is( this.validatorName, '2.000000000000000000' ); - cy.vega_wallet_check_validator_stake_this_epoch_value_is( + vega_wallet_check_validator_stake_this_epoch_value_is( this.validatorName, '3.000000000000000000' ); cy.vega_wallet_check_unstaked_value_is('2.000000000000000000'); - cy.vega_wallet_check_validator_staked_value_is( + vega_wallet_check_validator_staked_value_is( this.validatorName, '2.000000000000000000' ); - cy.staking_validator_page_check_stake_next_epoch_value('2.0'); - cy.staking_validator_page_check_stake_this_epoch_value('2.0'); + staking_validator_page_check_stake_next_epoch_value('2.0'); + staking_validator_page_check_stake_this_epoch_value('2.0'); }); it('Able to remove a full stake against a validator', function () { @@ -127,33 +124,33 @@ context('Staking Tab - with eth and vega wallets connected', function () { cy.vega_wallet_check_unstaked_value_is('3.000000000000000000'); cy.get('button').contains('Select a validator to nominate').click(); - cy.get(staking.validatorNames).contains(this.validatorName).click(); + cy.get(validatorList).contains(this.validatorName).click(); cy.staking_validator_page_add_stake('1'); - cy.vega_wallet_check_validator_stake_next_epoch_value_is( + vega_wallet_check_validator_stake_next_epoch_value_is( this.validatorName, '1.000000000000000000' ); cy.vega_wallet_check_unstaked_value_is('2.000000000000000000'); - cy.get(navigation.staking).first().click(); - cy.get(staking.validatorNames).contains(this.validatorName).click(); + cy.navigate_to('staking'); + cy.get(validatorList).contains(this.validatorName).click(); cy.staking_validator_page_removeStake('1'); - cy.staking_validator_page_check_stake_next_epoch_value('0.0'); + staking_validator_page_check_stake_next_epoch_value('0.0'); - cy.vega_wallet_check_validator_stake_this_epoch_value_is( + vega_wallet_check_validator_stake_this_epoch_value_is( this.validatorName, '1.000000000000000000' ); - cy.vega_wallet_check_validator_stake_next_epoch_value_is( + vega_wallet_check_validator_stake_next_epoch_value_is( this.validatorName, '0.000000000000000000' ); cy.vega_wallet_check_unstaked_value_is('3.000000000000000000'); - cy.staking_validator_page_check_stake_next_epoch_value('0.0'); - cy.staking_validator_page_check_stake_this_epoch_value('0.0'); - cy.vega_wallet_check_validator_no_longer_showing(this.validatorName); + staking_validator_page_check_stake_next_epoch_value('0.0'); + staking_validator_page_check_stake_this_epoch_value('0.0'); + vega_wallet_check_validator_no_longer_showing(this.validatorName); }); it.skip('Unable to remove a stake with a negative value for a validator', function () { @@ -161,22 +158,22 @@ context('Staking Tab - with eth and vega wallets connected', function () { cy.vega_wallet_check_unstaked_value_is('3.000000000000000000'); cy.get('button').contains('Select a validator to nominate').click(); - cy.get(staking.validatorNames).contains(this.validatorName).click(); + cy.get(validatorList).contains(this.validatorName).click(); cy.staking_validator_page_add_stake('2'); - cy.staking_validator_page_check_stake_next_epoch_value('2.0'); - cy.vega_wallet_check_validator_stake_next_epoch_value_is( + staking_validator_page_check_stake_next_epoch_value('2.0'); + vega_wallet_check_validator_stake_next_epoch_value_is( this.validatorName, '2.000000000000000000' ); cy.vega_wallet_check_unstaked_value_is('1.000000000000000000'); - cy.get(navigation.staking).first().click(); - cy.get(staking.validatorNames).contains(this.validatorName).click(); - cy.get(staking.removeStakeRadioButton).click({ force: true }); - cy.get(staking.tokenAmountInput).type('-0.1'); + cy.navigate_to('staking'); + cy.get(validatorList).contains(this.validatorName).click(); + cy.get(removeStakeRadioButton).click({ force: true }); + cy.get(tokenAmountInputBox).type('-0.1'); cy.contains('Waiting for next epoch to start', { timeout: 10000 }); - cy.get(staking.tokenInputSubmit) + cy.get(tokenSubmitButton) .should('be.disabled', { timeout: 8000 }) .and('contain', `Remove -0.1 $VEGA tokens at the end of epoch`) .and('be.visible'); @@ -187,22 +184,22 @@ context('Staking Tab - with eth and vega wallets connected', function () { cy.vega_wallet_check_unstaked_value_is('3.000000000000000000'); cy.get('button').contains('Select a validator to nominate').click(); - cy.get(staking.validatorNames).contains(this.validatorName).click(); + cy.get(validatorList).contains(this.validatorName).click(); cy.staking_validator_page_add_stake('2'); - cy.staking_validator_page_check_stake_next_epoch_value('2.0'); - cy.vega_wallet_check_validator_stake_next_epoch_value_is( + staking_validator_page_check_stake_next_epoch_value('2.0'); + vega_wallet_check_validator_stake_next_epoch_value_is( this.validatorName, '2.000000000000000000' ); cy.vega_wallet_check_unstaked_value_is('1.000000000000000000'); - cy.get(navigation.staking).first().click(); - cy.get(staking.validatorNames).contains(this.validatorName).click(); - cy.get(staking.removeStakeRadioButton).click({ force: true }); - cy.get(staking.tokenAmountInput).type(4); + cy.navigate_to('staking'); + cy.get(validatorList).contains(this.validatorName).click(); + cy.get(removeStakeRadioButton).click({ force: true }); + cy.get(tokenAmountInputBox).type(4); cy.contains('Waiting for next epoch to start', { timeout: 10000 }); - cy.get(staking.tokenInputSubmit) + cy.get(tokenSubmitButton) .should('be.disabled', { timeout: 8000 }) .and('contain', `Remove 4 $VEGA tokens at the end of epoch`) .and('be.visible'); @@ -213,22 +210,22 @@ context('Staking Tab - with eth and vega wallets connected', function () { cy.vega_wallet_check_unstaked_value_is('3.000000000000000000'); cy.get('button').contains('Select a validator to nominate').click(); - cy.get(staking.validatorNames).contains(this.validatorName).click(); + cy.get(validatorList).contains(this.validatorName).click(); cy.staking_validator_page_add_stake('2'); cy.vega_wallet_check_unstaked_value_is('1.000000000000000000'); - cy.vega_wallet_check_validator_staked_value_is( + vega_wallet_check_validator_staked_value_is( this.validatorName, '2.000000000000000000' ); - cy.get(navigation.staking).first().click(); + cy.navigate_to('staking'); cy.staking_page_disassociate_all_tokens(); cy.ethereum_wallet_check_associated_vega_key_is_no_longer_showing( vegaWalletPublicKeyShort ); cy.ethereum_wallet_check_associated_value_is('0.0'); cy.vega_wallet_check_associated_value_is('0.000000000000000000'); - cy.vega_wallet_check_validator_no_longer_showing(this.validatorName); + vega_wallet_check_validator_no_longer_showing(this.validatorName); }); it('Disassociating some tokens - prioritizes unstaked tokens', function () { @@ -236,19 +233,19 @@ context('Staking Tab - with eth and vega wallets connected', function () { cy.vega_wallet_check_unstaked_value_is('3.000000000000000000'); cy.get('button').contains('Select a validator to nominate').click(); - cy.get(staking.validatorNames).contains(this.validatorName).click(); + cy.get(validatorList).contains(this.validatorName).click(); cy.staking_validator_page_add_stake('2'); cy.vega_wallet_check_unstaked_value_is('1.000000000000000000'); - cy.vega_wallet_check_validator_staked_value_is( + vega_wallet_check_validator_staked_value_is( this.validatorName, '2.000000000000000000' ); - cy.get(navigation.staking).first().click(); + cy.navigate_to('staking'); cy.staking_page_disassociate_tokens('1'); cy.ethereum_wallet_check_associated_value_is('2.0'); cy.vega_wallet_check_associated_value_is('2.000000000000000000'); - cy.vega_wallet_check_validator_staked_value_is( + vega_wallet_check_validator_staked_value_is( this.validatorName, '2.000000000000000000' ); @@ -261,78 +258,78 @@ context('Staking Tab - with eth and vega wallets connected', function () { } ); }); - - cy.staking_validator_page_check_stake_next_epoch_value = (expectedVal) => { - cy.highlight( - `Checking Staking Page - Validator Stake Next Epoch Value is ${expectedVal}` - ); - cy.get(staking.stakeNextEpochValue, { timeout: 10000 }) - .contains(expectedVal, { timeout: 10000 }) - .should('be.visible'); - }; - - cy.staking_validator_page_check_stake_this_epoch_value = (expectedVal) => { - cy.highlight( - `Checking Staking Page - Validator Stake This Epoch Value is ${expectedVal}` - ); - cy.get(staking.stakeThisEpochValue, { timeout: 10000 }) - .contains(expectedVal, { timeout: 10000 }) - .should('be.visible'); - }; - - cy.vega_wallet_check_validator_stake_next_epoch_value_is = ( - validatorName, - expectedVal - ) => { - cy.highlight( - `Checking vega wallet - Stake Next Epoch Value for ${validatorName} is ${expectedVal}` - ); - cy.get(wallet.vegawallet).within(() => { - cy.contains(`${validatorName} (Next epoch)`, { timeout: 40000 }) - .siblings() - .contains(expectedVal, { timeout: 40000 }) - .should('be.visible'); - }); - }; - - cy.vega_wallet_check_validator_stake_this_epoch_value_is = ( - validatorName, - expectedVal - ) => { - cy.highlight( - `Checking vega wallet - Stake This Epoch Value for ${validatorName} is ${expectedVal}` - ); - cy.get(wallet.vegawallet).within(() => { - cy.contains(`${validatorName} (This Epoch)`, { timeout: 40000 }) - .siblings() - .contains(expectedVal, { timeout: 40000 }) - .should('be.visible'); - }); - }; - - cy.vega_wallet_check_validator_no_longer_showing = (validatorName) => { - cy.highlight( - `Checking Validator and therefore stake removed for ${validatorName}` - ); - cy.get(wallet.vegawallet).within(() => { - cy.contains(`${validatorName}`, { timeout: 40000 }).should('not.exist', { - timeout: 40000, - }); - }); - }; - - cy.vega_wallet_check_validator_staked_value_is = ( - validatorName, - expectedVal - ) => { - cy.highlight( - `Checking Validator Stake Value for ${validatorName} is ${expectedVal}` - ); - cy.get(wallet.vegawallet).within(() => { - cy.contains(`${validatorName}`, { timeout: 40000 }) - .siblings() - .contains(expectedVal, { timeout: 40000 }) - .should('be.visible'); - }); - }; }); + +function staking_validator_page_check_stake_next_epoch_value(expectedVal) { + cy.highlight( + `Checking Staking Page - Validator Stake Next Epoch Value is ${expectedVal}` + ); + cy.get(stakeNextEpochValue, { timeout: 10000 }) + .contains(expectedVal, { timeout: 10000 }) + .should('be.visible'); +} + +function staking_validator_page_check_stake_this_epoch_value(expectedVal) { + cy.highlight( + `Checking Staking Page - Validator Stake This Epoch Value is ${expectedVal}` + ); + cy.get(stakeNextEpochValue, { timeout: 10000 }) + .contains(expectedVal, { timeout: 10000 }) + .should('be.visible'); +} + +function vega_wallet_check_validator_stake_next_epoch_value_is( + validatorName, + expectedVal +) { + cy.highlight( + `Checking vega wallet - Stake Next Epoch Value for ${validatorName} is ${expectedVal}` + ); + cy.get(vegaWalletContainer).within(() => { + cy.contains(`${validatorName} (Next epoch)`, { timeout: 40000 }) + .siblings() + .contains(expectedVal, { timeout: 40000 }) + .should('be.visible'); + }); +} + +function vega_wallet_check_validator_stake_this_epoch_value_is( + validatorName, + expectedVal +) { + cy.highlight( + `Checking vega wallet - Stake This Epoch Value for ${validatorName} is ${expectedVal}` + ); + cy.get(vegaWalletContainer).within(() => { + cy.contains(`${validatorName} (This Epoch)`, { timeout: 40000 }) + .siblings() + .contains(expectedVal, { timeout: 40000 }) + .should('be.visible'); + }); +} + +function vega_wallet_check_validator_no_longer_showing(validatorName) { + cy.highlight( + `Checking Validator and therefore stake removed for ${validatorName}` + ); + cy.get(vegaWalletContainer).within(() => { + cy.contains(`${validatorName}`, { timeout: 40000 }).should('not.exist', { + timeout: 40000, + }); + }); +} + +function vega_wallet_check_validator_staked_value_is( + validatorName, + expectedVal +) { + cy.highlight( + `Checking Validator Stake Value for ${validatorName} is ${expectedVal}` + ); + cy.get(vegaWalletContainer).within(() => { + cy.contains(`${validatorName}`, { timeout: 40000 }) + .siblings() + .contains(expectedVal, { timeout: 40000 }) + .should('be.visible'); + }); +} diff --git a/apps/token-e2e/src/integration/flow/token-association-flow.cy.js b/apps/token-e2e/src/integration/flow/token-association-flow.cy.js index ece1e8aa7..7d87be4b4 100644 --- a/apps/token-e2e/src/integration/flow/token-association-flow.cy.js +++ b/apps/token-e2e/src/integration/flow/token-association-flow.cy.js @@ -1,118 +1,98 @@ -/// -import navigation from '../../locators/navigation.locators'; -import staking from '../../locators/staking.locators'; -import wallet from '../../locators/wallet.locators'; -import '../../support/staking.functions'; -import '../../support/vega-wallet.functions'; -import '../../support/eth-wallet.functions'; -import '../../support/wallet-teardown.functions'; +const pageSpinner = 'splash-loader'; +const menuBar = 'nav'; +const validatorList = '[data-testid="node-list-item-name"]'; const vegaWalletPublicKeyShort = Cypress.env('vegaWalletPublicKeyShort'); -context('Staking Tab - with eth and vega wallets connected', function () { - before('visit staking tab and connect vega wallet', function () { - cy.vega_wallet_import(); - cy.visit('/'); - cy.get(navigation.section, { timeout: 20000 }).should('be.visible'); - cy.vega_wallet_connect(); - cy.vega_wallet_set_specified_approval_amount('1000'); - cy.reload(); - cy.get(navigation.section, { timeout: 20000 }).should('be.visible'); - cy.ethereum_wallet_connect(); - cy.get(navigation.staking).first().click(); - cy.get(navigation.spinner, { timeout: 20000 }).should('not.exist'); - cy.get(staking.validatorNames).first().invoke('text').as('validatorName'); - }); - - describe('Eth wallet - contains VEGA tokens', function () { - beforeEach( - 'teardown wallet & drill into a specific validator', - function () { - cy.vega_wallet_teardown(); - cy.get(navigation.staking).first().click(); - cy.get(navigation.spinner, { timeout: 20000 }).should('not.exist'); - } - ); - - it('Able to associate tokens - from staking page', function () { - cy.staking_page_associate_tokens('2'); - cy.ethereum_wallet_check_associated_vega_key_value_is( - vegaWalletPublicKeyShort, - '2.000000000000000000' - ); - cy.ethereum_wallet_check_associated_value_is('2.0'); - cy.vega_wallet_check_associated_value_is('2.000000000000000000'); - cy.vega_wallet_check_unstaked_value_is('2.000000000000000000'); +context( + 'Token association flow - with eth and vega wallets connected', + function () { + before('visit staking tab and connect vega wallet', function () { + cy.vega_wallet_import(); + cy.visit('/'); + cy.get(menuBar, { timeout: 20000 }).should('be.visible'); + cy.vega_wallet_connect(); + cy.vega_wallet_set_specified_approval_amount('1000'); + cy.reload(); + cy.get(menuBar, { timeout: 20000 }).should('be.visible'); + cy.ethereum_wallet_connect(); + cy.navigate_to('staking'); + cy.get(pageSpinner, { timeout: 20000 }).should('not.exist'); + cy.get(validatorList).first().invoke('text').as('validatorName'); }); - it('Able to disassociate tokens - from staking page', function () { - cy.staking_page_associate_tokens('2'); - cy.ethereum_wallet_check_associated_vega_key_value_is( - vegaWalletPublicKeyShort, - '2.000000000000000000' + describe('Eth wallet - contains VEGA tokens', function () { + beforeEach( + 'teardown wallet & drill into a specific validator', + function () { + cy.vega_wallet_teardown(); + cy.navigate_to('staking'); + cy.get(pageSpinner, { timeout: 20000 }).should('not.exist'); + } ); - cy.vega_wallet_check_associated_value_is('2.000000000000000000'); - cy.get('button').contains('Select a validator to nominate').click(); - cy.staking_page_disassociate_tokens('1'); - cy.ethereum_wallet_check_associated_vega_key_value_is( - vegaWalletPublicKeyShort, - '1.000000000000000000' - ); - cy.ethereum_wallet_check_associated_value_is('1.0'); - cy.vega_wallet_check_associated_value_is('1.000000000000000000'); - }); - it('Able to access associate token form - from eth wallet', function () { - cy.get(wallet.ethWallet).within(() => - cy.get(wallet.ethWalletAssociate).click() - ); - cy.get(staking.stakeAssociateWalletRadio, { timeout: 30000 }).should( - 'be.enabled' - ); - }); + it('Able to associate tokens', function () { + cy.staking_page_associate_tokens('2'); + cy.ethereum_wallet_check_associated_vega_key_value_is( + vegaWalletPublicKeyShort, + '2.000000000000000000' + ); + cy.ethereum_wallet_check_associated_value_is('2.0'); + cy.vega_wallet_check_associated_value_is('2.000000000000000000'); + cy.vega_wallet_check_unstaked_value_is('2.000000000000000000'); + }); - it('Able to access disassociate token form - from eth wallet', function () { - cy.get(wallet.ethWallet).within(() => - cy.get(wallet.ethWalletDisassociate).click() - ); - cy.get(staking.stakeAssociateWalletRadio, { timeout: 30000 }).should( - 'be.enabled' - ); - }); + it('Able to disassociate tokens', function () { + cy.staking_page_associate_tokens('2'); + cy.ethereum_wallet_check_associated_vega_key_value_is( + vegaWalletPublicKeyShort, + '2.000000000000000000' + ); + cy.vega_wallet_check_associated_value_is('2.000000000000000000'); + cy.get('button').contains('Select a validator to nominate').click(); + cy.staking_page_disassociate_tokens('1'); + cy.ethereum_wallet_check_associated_vega_key_value_is( + vegaWalletPublicKeyShort, + '1.000000000000000000' + ); + cy.ethereum_wallet_check_associated_value_is('1.0'); + cy.vega_wallet_check_associated_value_is('1.000000000000000000'); + }); - it('Able to associate more tokens than the approved amount of 1000 - requires re-approval', function () { - cy.staking_page_associate_tokens('1001', true); - cy.ethereum_wallet_check_associated_vega_key_value_is( - vegaWalletPublicKeyShort, - '1,001.000000000000000000' - ); - cy.ethereum_wallet_check_associated_value_is('1,001.00'); - cy.vega_wallet_check_associated_value_is('1,001.000000000000000000'); - }); + it('Able to associate more tokens than the approved amount of 1000 - requires re-approval', function () { + cy.staking_page_associate_tokens('1001', true); + cy.ethereum_wallet_check_associated_vega_key_value_is( + vegaWalletPublicKeyShort, + '1,001.000000000000000000' + ); + cy.ethereum_wallet_check_associated_value_is('1,001.00'); + cy.vega_wallet_check_associated_value_is('1,001.000000000000000000'); + }); - it('Able to disassociate a partial amount of tokens currently associated', function () { - cy.staking_page_associate_tokens('2'); - cy.vega_wallet_check_associated_value_is('2.000000000000000000'); - cy.get('button').contains('Select a validator to nominate').click(); - cy.staking_page_disassociate_tokens('1'); - cy.ethereum_wallet_check_associated_vega_key_value_is( - vegaWalletPublicKeyShort, - '1.000000000000000000' - ); - cy.ethereum_wallet_check_associated_value_is('1.0'); - cy.vega_wallet_check_associated_value_is('1.000000000000000000'); - }); + it('Able to disassociate a partial amount of tokens currently associated', function () { + cy.staking_page_associate_tokens('2'); + cy.vega_wallet_check_associated_value_is('2.000000000000000000'); + cy.get('button').contains('Select a validator to nominate').click(); + cy.staking_page_disassociate_tokens('1'); + cy.ethereum_wallet_check_associated_vega_key_value_is( + vegaWalletPublicKeyShort, + '1.000000000000000000' + ); + cy.ethereum_wallet_check_associated_value_is('1.0'); + cy.vega_wallet_check_associated_value_is('1.000000000000000000'); + }); - it('Able to disassociate all tokens', function () { - cy.staking_page_associate_tokens('2'); - cy.vega_wallet_check_associated_value_is('2.000000000000000000'); - cy.get('button').contains('Select a validator to nominate').click(); - cy.staking_page_disassociate_all_tokens(); - cy.ethereum_wallet_check_associated_vega_key_is_no_longer_showing( - vegaWalletPublicKeyShort - ); - cy.ethereum_wallet_check_associated_value_is('0.0'); - cy.vega_wallet_check_associated_value_is('0.000000000000000000'); + it('Able to disassociate all tokens', function () { + cy.staking_page_associate_tokens('2'); + cy.vega_wallet_check_associated_value_is('2.000000000000000000'); + cy.get('button').contains('Select a validator to nominate').click(); + cy.staking_page_disassociate_all_tokens(); + cy.ethereum_wallet_check_associated_vega_key_is_no_longer_showing( + vegaWalletPublicKeyShort + ); + cy.ethereum_wallet_check_associated_value_is('0.0'); + cy.vega_wallet_check_associated_value_is('0.000000000000000000'); + }); }); - }); -}); + } +); diff --git a/apps/token-e2e/src/integration/governance.cy.js b/apps/token-e2e/src/integration/governance.cy.js index 4e4aef0b4..2f5dff6e0 100644 --- a/apps/token-e2e/src/integration/governance.cy.js +++ b/apps/token-e2e/src/integration/governance.cy.js @@ -1,30 +1,21 @@ -import navigation from '../locators/navigation.locators'; -import governance from '../locators/governance.locators'; +const noProposals = '[data-testid="no-proposals"]'; context('Governance Page - verify elements on page', function () { before('navigate to governance page', function () { - cy.visit('/') - .get(navigation.section) - .within(() => { - cy.get(navigation.governance).click(); - }); + cy.visit('/').navigate_to('governance'); }); describe('with no network change proposals', function () { it('should have governance tab highlighted', function () { - cy.get(navigation.section).within(() => { - cy.get(navigation.governance).should('have.attr', 'aria-current'); - }); + cy.verify_tab_highlighted('governance'); }); it('should have GOVERNANCE header visible', function () { - cy.get(governance.pageHeader) - .should('be.visible') - .and('have.text', 'Governance'); + cy.verify_page_header('Governance'); }); it('should have information box visible', function () { - cy.get(governance.noProposals) + cy.get(noProposals) .should('be.visible') .and('have.text', 'There are no active network change proposals'); }); diff --git a/apps/token-e2e/src/integration/home.cy.js b/apps/token-e2e/src/integration/home.cy.js index eae3261a5..f13b3117b 100644 --- a/apps/token-e2e/src/integration/home.cy.js +++ b/apps/token-e2e/src/integration/home.cy.js @@ -1,5 +1,24 @@ -import navigation from '../locators/navigation.locators'; -import home from '../locators/home.locators'; +const navSection = 'nav'; +const navHome = '[href="/"]'; +const navVesting = '[href="/vesting"]'; +const navStaking = '[href="/staking"]'; +const navRewards = '[href="/rewards"]'; +const navWithdraw = '[href="/withdraw"]'; +const navGovernance = '[href="/governance"]'; + +const tokenDetailsTable = '.token-details'; +const address = '[data-testid="token-address"]'; +const contract = '[data-testid="token-contract"]'; +const totalSupply = '[data-testid="total-supply"]'; +const circulatingSupply = '[data-testid="circulating-supply"]'; +const staked = '[data-testid="staked"]'; +const tranchesLink = '[data-testid="tranches-link"]'; +const redeemBtn = '[data-testid="check-vesting-page-btn"]'; +const getVegaWalletLink = '[data-testid="get-vega-wallet-link"]'; +const associateVegaLink = + '[data-testid="associate-vega-tokens-link-on-homepage"]'; +const stakingBtn = '[data-testid="staking-button-on-homepage"]'; +const governanceBtn = '[data-testid="governance-button-on-homepage"]'; const vegaTokenAddress = Cypress.env('vegaTokenAddress'); const vegaTokenContractAddress = Cypress.env('vegaTokenContractAddress'); @@ -11,111 +30,111 @@ context('Home Page - verify elements on page', function () { describe('with wallets disconnected', function () { before('wait for page to load', function () { - cy.get(navigation.section, { timeout: 10000 }).should('be.visible'); + cy.get(navSection, { timeout: 10000 }).should('be.visible'); }); describe('Navigation tabs', function () { it('should have HOME tab', function () { - cy.get(navigation.section).within(() => { - cy.get(navigation.home).should('be.visible'); + cy.get(navSection).within(() => { + cy.get(navHome).should('be.visible'); }); }); it('should have VESTING tab', function () { - cy.get(navigation.section).within(() => { - cy.get(navigation.vesting).should('be.visible'); + cy.get(navSection).within(() => { + cy.get(navVesting).should('be.visible'); }); }); it('should have STAKING tab', function () { - cy.get(navigation.section).within(() => { - cy.get(navigation.staking).should('be.visible'); + cy.get(navSection).within(() => { + cy.get(navStaking).should('be.visible'); }); }); it('should have REWARDS tab', function () { - cy.get(navigation.section).within(() => { - cy.get(navigation.rewards).should('be.visible'); + cy.get(navSection).within(() => { + cy.get(navRewards).should('be.visible'); }); }); it('should have WITHDRAW tab', function () { - cy.get(navigation.section).within(() => { - cy.get(navigation.withdraw).should('be.visible'); + cy.get(navSection).within(() => { + cy.get(navWithdraw).should('be.visible'); }); }); it('should have GOVERNANCE tab', function () { - cy.get(navigation.section).within(() => { - cy.get(navigation.governance).should('be.visible'); + cy.get(navSection).within(() => { + cy.get(navGovernance).should('be.visible'); }); }); }); describe('THE $VEGA TOKEN table', function () { it('should have TOKEN ADDRESS', function () { - cy.get(home.tokenDetailsTable).within(() => { - cy.get(home.address) + cy.get(tokenDetailsTable).within(() => { + cy.get(address) .should('be.visible') .invoke('text') .should('be.equal', vegaTokenAddress); }); }); it('should have VESTING CONTRACT', function () { - cy.get(home.tokenDetailsTable).within(() => { - cy.get(home.contract) + cy.get(tokenDetailsTable).within(() => { + cy.get(contract) .should('be.visible') .invoke('text') .should('be.equal', vegaTokenContractAddress); }); }); it('should have TOTAL SUPPLY', function () { - cy.get(home.tokenDetailsTable).within(() => { - cy.get(home.totalSupply).should('be.visible'); + cy.get(tokenDetailsTable).within(() => { + cy.get(totalSupply).should('be.visible'); }); }); it('should have CIRCULATING SUPPLY', function () { - cy.get(home.tokenDetailsTable).within(() => { - cy.get(home.circulatingSupply).should('be.visible'); + cy.get(tokenDetailsTable).within(() => { + cy.get(circulatingSupply).should('be.visible'); }); }); it('should have STAKED $VEGA', function () { - cy.get(home.tokenDetailsTable).within(() => { - cy.get(home.staked).should('be.visible'); + cy.get(tokenDetailsTable).within(() => { + cy.get(staked).should('be.visible'); }); }); }); describe('links and buttons', function () { it('should have TRANCHES link', function () { - cy.get(home.tranchesLink) + cy.get(tranchesLink) .should('be.visible') .and('have.attr', 'href') .and('equal', '/tranches'); }); it('should have REDEEM button', function () { - cy.get(home.redeemBtn) + cy.get(redeemBtn) .should('be.visible') .parent() .should('have.attr', 'href') .and('equal', '/vesting'); }); it('should have GET VEGA WALLET link', function () { - cy.get(home.getVegaWalletLink) + cy.get(getVegaWalletLink) .should('be.visible') .and('have.attr', 'href') .and('equal', 'https://vega.xyz/wallet'); }); it('should have ASSOCIATE VEGA TOKENS link', function () { - cy.get(home.associateVegaLink) + cy.get(associateVegaLink) .should('be.visible') .and('have.attr', 'href') .and('equal', '/staking/associate'); }); it('should have STAKING button', function () { - cy.get(home.stakingBtn) + cy.get(stakingBtn) .should('be.visible') .parent() .should('have.attr', 'href') .and('equal', '/staking'); }); it('should have GOVERNANCE button', function () { - cy.get(home.governanceBtn) + cy.get(governanceBtn) .should('be.visible') .parent() .should('have.attr', 'href') diff --git a/apps/token-e2e/src/integration/rewards.cy.js b/apps/token-e2e/src/integration/rewards.cy.js index 5719d2972..a8aa88d03 100644 --- a/apps/token-e2e/src/integration/rewards.cy.js +++ b/apps/token-e2e/src/integration/rewards.cy.js @@ -1,30 +1,22 @@ -import navigation from '../locators/navigation.locators'; -import rewards from '../locators/rewards.locators'; +const connectToVegaBtn = '[data-testid="connect-to-vega-wallet-btn"]'; +const warning = '[data-testid="callout"]'; context('Rewards Page - verify elements on page', function () { before('navigate to rewards page', function () { - cy.visit('/') - .get(navigation.section) - .within(() => { - cy.get(navigation.rewards).click(); - }); + cy.visit('/').navigate_to('rewards'); }); describe('with wallets disconnected', function () { it('should have REWARDS tab highlighted', function () { - cy.get(navigation.section).within(() => { - cy.get(navigation.rewards).should('have.attr', 'aria-current'); - }); + cy.verify_tab_highlighted('rewards'); }); it('should have rewards header visible', function () { - cy.get(rewards.pageHeader) - .should('be.visible') - .and('have.text', 'Rewards'); + cy.verify_page_header('Rewards'); }); it('should have epoch warning', function () { - cy.get(rewards.warning) + cy.get(warning) .should('be.visible') .and( 'have.text', @@ -33,7 +25,7 @@ context('Rewards Page - verify elements on page', function () { }); it('should have connect Vega wallet button', function () { - cy.get(rewards.connectToVegaBtn) + cy.get(connectToVegaBtn) .should('be.visible') .and('have.text', 'Connect Vega wallet'); }); diff --git a/apps/token-e2e/src/integration/staking.cy.js b/apps/token-e2e/src/integration/staking.cy.js index 93d75143c..10914a338 100644 --- a/apps/token-e2e/src/integration/staking.cy.js +++ b/apps/token-e2e/src/integration/staking.cy.js @@ -1,31 +1,30 @@ -import navigation from '../locators/navigation.locators'; -import staking from '../locators/staking.locators'; +const guideLink = '[data-testid="staking-guide-link"]'; +const step1 = '[data-testid="staking-step-1"]'; +const step2 = '[data-testid="staking-step-2"]'; +const step3 = '[data-testid="staking-step-3"]'; +const sectionHeader = 'h2'; +const connectToEthBtn = '[data-testid="connect-to-eth-btn"]'; +const connectToVegaBtn = '[data-testid="connect-to-vega-wallet-btn"]'; +const link = '[data-testid="link"]'; +const warning = '[data-testid="callout"]'; context('Staking Page - verify elements on page', function () { before('navigate to staking page', function () { - cy.visit('/') - .get(navigation.section) - .within(() => { - cy.get(navigation.staking).click(); - }); + cy.visit('/').navigate_to('staking'); }); describe('with wallets disconnected', function () { describe('description section', function () { it('should have staking tab highlighted', function () { - cy.get(navigation.section).within(() => { - cy.get(navigation.staking).should('have.attr', 'aria-current'); - }); + cy.verify_tab_highlighted('staking'); }); it('should have STAKING ON VEGA header visible', function () { - cy.get(staking.pageHeader) - .should('be.visible') - .and('have.text', 'Staking on Vega'); + cy.verify_page_header('Staking on Vega'); }); it('should have Staking Guide link visible', function () { - cy.get(staking.guideLink) + cy.get(guideLink) .should('be.visible') .and('have.text', 'Read more about staking on Vega') .and( @@ -38,16 +37,16 @@ context('Staking Page - verify elements on page', function () { describe('step 1 section', function () { it('should have header visible', function () { - cy.get(staking.step1).within(() => { - cy.get(staking.sectionHeader) + cy.get(step1).within(() => { + cy.get(sectionHeader) .should('be.visible') .and('have.text', 'Step 1. Connect to a Vega Wallet'); }); }); it('should have text visible', function () { - cy.get(staking.step1).within(() => { - cy.get(staking.link) + cy.get(step1).within(() => { + cy.get(link) .should('be.visible') .and('have.text', 'Vega Wallet') .and('have.attr', 'href', 'https://vega.xyz/wallet'); @@ -55,16 +54,16 @@ context('Staking Page - verify elements on page', function () { }); it('should have connect to eth button visible', function () { - cy.get(staking.step1).within(() => { - cy.get(staking.connectToEthBtn) + cy.get(step1).within(() => { + cy.get(connectToEthBtn) .should('be.visible') .and('have.text', 'Connect Ethereum wallet'); }); }); it('should have connect to vega button visible', function () { - cy.get(staking.step1).within(() => { - cy.get(staking.connectToVegaBtn) + cy.get(step1).within(() => { + cy.get(connectToVegaBtn) .should('be.visible') .and('have.text', 'Connect Vega wallet'); }); @@ -73,16 +72,16 @@ context('Staking Page - verify elements on page', function () { describe('step 2 section', function () { it('should have header visible', function () { - cy.get(staking.step2).within(() => { - cy.get(staking.sectionHeader) + cy.get(step2).within(() => { + cy.get(sectionHeader) .should('be.visible') .and('have.text', 'Step 2. Associate tokens with a Vega Wallet'); }); }); it('should have warning visible', function () { - cy.get(staking.step2).within(() => { - cy.get(staking.warning) + cy.get(step2).within(() => { + cy.get(warning) .should('be.visible') .and( 'have.text', @@ -94,8 +93,8 @@ context('Staking Page - verify elements on page', function () { describe('step 3 section', function () { it('should have header visible', function () { - cy.get(staking.step3).within(() => { - cy.get(staking.sectionHeader) + cy.get(step3).within(() => { + cy.get(sectionHeader) .should('be.visible') .and( 'have.text', diff --git a/apps/token-e2e/src/integration/vesting.cy.js b/apps/token-e2e/src/integration/vesting.cy.js index 0534c230b..264cf63f9 100644 --- a/apps/token-e2e/src/integration/vesting.cy.js +++ b/apps/token-e2e/src/integration/vesting.cy.js @@ -1,34 +1,26 @@ -import navigation from '../locators/navigation.locators'; -import vesting from '../locators/vesting.locators'; +const connectPrompt = '[data-testid="eth-connect-prompt"]'; +const connectButton = '[data-testid="connect-to-eth-btn"]'; context('Vesting Page - verify elements on page', function () { before('navigate to vesting page', function () { - cy.visit('/') - .get(navigation.section) - .within(() => { - cy.get(navigation.vesting).click(); - }); + cy.visit('/').navigate_to('vesting'); }); describe('with wallets disconnected', function () { it('should have vesting tab highlighted', function () { - cy.get(navigation.section).within(() => { - cy.get(navigation.vesting).should('have.attr', 'aria-current'); - }); + cy.verify_tab_highlighted('vesting'); }); it('should have VESTING header visible', function () { - cy.get(vesting.pageHeader) - .should('be.visible') - .and('have.text', 'Vesting'); + cy.verify_page_header('Vesting'); }); it('should have connect Eth wallet info', function () { - cy.get(vesting.connectPrompt).should('be.visible'); + cy.get(connectPrompt).should('be.visible'); }); it('should have connect Eth wallet button', function () { - cy.get(vesting.connectButton) + cy.get(connectButton) .should('be.visible') .and('have.text', 'Connect Ethereum wallet'); }); diff --git a/apps/token-e2e/src/integration/wallet-eth.cy.js b/apps/token-e2e/src/integration/wallet-eth.cy.js new file mode 100644 index 000000000..d01a48fca --- /dev/null +++ b/apps/token-e2e/src/integration/wallet-eth.cy.js @@ -0,0 +1,251 @@ +const walletContainer = '[data-testid="ethereum-wallet"]'; +const walletHeader = '[data-testid="wallet-header"] h1'; +const connectToEthButton = '[data-testid="connect-to-eth-wallet-button"]'; +const connectorList = '[data-testid="web3-connector-list"]'; +const associate = '[href="/staking/associate"]'; +const disassociate = '[href="/staking/disassociate"]'; +const disconnect = '[data-testid="disconnect-from-eth-wallet-button"]'; +const accountNo = '[data-testid="ethereum-account-truncated"]'; +const currencyTitle = '[data-testid="currency-title"]'; +const currencyValue = '[data-testid="currency-value"]'; +const vegaInVesting = '[data-testid="vega-in-vesting-contract"]'; +const vegaInWallet = '[data-testid="vega-in-wallet"]'; +const progressBar = '[data-testid="progress-bar"]'; +const currencyLocked = '[data-testid="currency-locked"]'; +const currencyUnlocked = '[data-testid="currency-unlocked"]'; +const dialog = '[role="dialog"]'; +const dialogHeader = '[data-testid="dialog-title"]'; +const dialogCloseBtn = '[data-testid="dialog-close"]'; + +context('Ethereum Wallet - verify elements on widget', function () { + before('visit token home page', function () { + cy.visit('/'); + }); + + describe('with wallets disconnected', function () { + before('wait for widget to load', function () { + cy.get(walletContainer, { timeout: 10000 }).should('be.visible'); + }); + + it('should have ETHEREUM KEY header visible', function () { + cy.get(walletContainer).within(() => { + cy.get(walletHeader) + .should('be.visible') + .and('have.text', 'Ethereum key'); + }); + }); + + it('should have Connect Ethereum button visible', function () { + cy.get(walletContainer).within(() => { + cy.get(connectToEthButton) + .should('be.visible') + .and('have.text', 'Connect Ethereum wallet to associate $VEGA'); + }); + }); + }); + + describe('when Connect Ethereum clicked', function () { + before('', function () { + cy.get(connectToEthButton).click(); + }); + + it('should have Connect Ethereum header visible', function () { + cy.get(dialog).within(() => { + cy.get(dialogHeader) + .should('be.visible') + .and('have.text', 'Connect to your Ethereum wallet'); + }); + }); + + it('should have connector list visible', function () { + const connectList = [ + 'Unknown', + 'MetaMask, Brave or other injected web wallet', + 'WalletConnect', + ]; + cy.get(connectorList).within(() => { + cy.get('button').each(($btn, i) => { + cy.wrap($btn).should('be.visible').and('have.text', connectList[i]); + }); + }); + }); + + after('close popup', function () { + cy.get(dialog) + .within(() => { + cy.get(dialogCloseBtn).click(); + }) + .should('not.exist'); + }); + }); + + describe('when Ethereum wallet connected', function () { + before('connect to Ethereum wallet', function () { + cy.ethereum_wallet_connect(); + }); + + it('should have ETHEREUM KEY header visible', function () { + cy.get(walletContainer).within(() => { + cy.get(walletHeader) + .should('be.visible') + .and('have.text', 'Ethereum key'); + }); + }); + + it('should have account number visible', function () { + cy.get(walletContainer).within(() => { + cy.get(accountNo) + .should('be.visible') + .and('have.text', Cypress.env('ethWalletPublicKeyTruncated')); + }); + }); + + it('should have Associate button visible', function () { + cy.get(walletContainer).within(() => { + cy.get(associate).should('be.visible').and('have.text', 'Associate'); + }); + }); + + it('should have Disassociate button visible', function () { + cy.get(walletContainer).within(() => { + cy.get(disassociate) + .should('be.visible') + .and('have.text', 'Disassociate'); + }); + }); + + it('should have Disconnect button visible', function () { + cy.get(walletContainer).within(() => { + cy.get(disconnect).should('be.visible').and('have.text', 'Disconnect'); + }); + }); + + describe('VEGA IN VESTING CONTRACT', function () { + it('should have currency title visible', function () { + cy.get(vegaInVesting).within(() => { + cy.get(currencyTitle) + .should('be.visible') + .and('have.text', 'VEGAIn vesting contract'); + }); + }); + + it('should have currency value visible', function () { + cy.get(vegaInVesting).within(() => { + cy.get(currencyValue) + .should('be.visible') + .invoke('text') + .should('match', /\d{0,3}(,\d{3})*\.\d{18}$/); + }); + }); + + it('should have progress bar visible', function () { + cy.get(vegaInVesting).within(() => { + cy.get(progressBar).should('be.visible'); + }); + }); + + it('should have locked currency visible', function () { + cy.get(vegaInVesting).within(() => { + cy.get(currencyLocked) + .should('be.visible') + .invoke('text') + .should('match', /\d{0,3}(,\d{3})*\.\d{2}$/); + }); + }); + + it('should have unlocked currency visible', function () { + cy.get(vegaInVesting).within(() => { + cy.get(currencyUnlocked) + .should('be.visible') + .invoke('text') + .should('match', /\d{0,3}(,\d{3})*\.\d{2}$/); + }); + }); + + it('should match total & locked/unlocked currency value', function () { + cy.get(vegaInVesting) + .within(() => { + cy.get(currencyValue) + .invoke('text') + .convert_token_value_to_number() + .as('value'); + cy.get(currencyLocked) + .invoke('text') + .convert_token_value_to_number() + .as('locked'); + cy.get(currencyUnlocked) + .invoke('text') + .convert_token_value_to_number() + .as('unlocked'); + }) + .then(function () { + expect(this.value).to.equal(this.locked + this.unlocked); + }); + }); + }); + + describe('VEGA IN WALLET', function () { + it('should have currency title visible', function () { + cy.get(vegaInWallet).within(() => { + cy.get(currencyTitle) + .should('be.visible') + .and('have.text', 'VEGAIn Wallet'); + }); + }); + + it('should have currency value visible', function () { + cy.get(vegaInWallet).within(() => { + cy.get(currencyValue) + .should('be.visible') + .invoke('text') + .should('match', /\d{0,3}(,\d{3})*\.\d{18}$/); + }); + }); + + it('should have progress bar visible', function () { + cy.get(vegaInWallet).within(() => { + cy.get(progressBar).should('be.visible'); + }); + }); + + it('should have locked currency visible', function () { + cy.get(vegaInWallet).within(() => { + cy.get(currencyLocked) + .should('be.visible') + .invoke('text') + .should('match', /\d{0,3}(,\d{3})*\.\d{2}$/); + }); + }); + + it('should have unlocked currency visible', function () { + cy.get(vegaInWallet).within(() => { + cy.get(currencyUnlocked) + .should('be.visible') + .invoke('text') + .should('match', /\d{0,3}(,\d{3})*\.\d{2}$/); + }); + }); + + it('should match total & locked/unlocked currency value', function () { + cy.get(vegaInWallet) + .within(() => { + cy.get(currencyValue) + .invoke('text') + .convert_token_value_to_number() + .as('value'); + cy.get(currencyLocked) + .invoke('text') + .convert_token_value_to_number() + .as('locked'); + cy.get(currencyUnlocked) + .invoke('text') + .convert_token_value_to_number() + .as('unlocked'); + }) + .then(function () { + expect(this.value).to.equal(this.locked + this.unlocked); + }); + }); + }); + }); +}); diff --git a/apps/token-e2e/src/integration/withdraw.cy.js b/apps/token-e2e/src/integration/withdraw.cy.js index 0000ae619..9036b375a 100644 --- a/apps/token-e2e/src/integration/withdraw.cy.js +++ b/apps/token-e2e/src/integration/withdraw.cy.js @@ -1,36 +1,28 @@ -import navigation from '../locators/navigation.locators'; -import withdraw from '../locators/withdraw.locators'; +const connectToVegaBtn = '[data-testid="connect-to-vega-wallet-btn"]'; +const warning = '[data-testid="callout"]'; context('Withdraw Page - verify elements on page', function () { before('navigate to withdraw page', function () { - cy.visit('/') - .get(navigation.section) - .within(() => { - cy.get(navigation.withdraw).click(); - }); + cy.visit('/').navigate_to('withdraw'); }); describe('with wallets disconnected', function () { it('should have withdraw tab highlighted', function () { - cy.get(navigation.section).within(() => { - cy.get(navigation.withdraw).should('have.attr', 'aria-current'); - }); + cy.verify_tab_highlighted('withdraw'); }); it('should have WITHDRAW header visible', function () { - cy.get(withdraw.pageHeader) - .should('be.visible') - .and('have.text', 'Withdraw'); + cy.verify_page_header('Withdraw'); }); it('should have connect Vega wallet button', function () { - cy.get(withdraw.connectToVegaBtn) + cy.get(connectToVegaBtn) .should('be.visible') .and('have.text', 'Connect Vega wallet'); }); it('should have withdraw information box', function () { - cy.get(withdraw.warning).should('be.visible'); + cy.get(warning).should('be.visible'); }); }); }); diff --git a/apps/token-e2e/src/locators/common.locators.js b/apps/token-e2e/src/locators/common.locators.js deleted file mode 100644 index 11eee5f21..000000000 --- a/apps/token-e2e/src/locators/common.locators.js +++ /dev/null @@ -1,7 +0,0 @@ -export default { - pageHeader: 'header h1', - sectionHeader: 'h2', - link: '[data-testid="link"]', - warning: '[data-testid="callout"]', - connectToVegaBtn: '[data-testid="connect-to-vega-wallet-btn"]', -}; diff --git a/apps/token-e2e/src/locators/governance.locators.js b/apps/token-e2e/src/locators/governance.locators.js deleted file mode 100644 index ec3d43f05..000000000 --- a/apps/token-e2e/src/locators/governance.locators.js +++ /dev/null @@ -1,6 +0,0 @@ -import common from './common.locators'; - -export default { - ...common, - noProposals: '[data-testid="no-proposals"]', -}; diff --git a/apps/token-e2e/src/locators/home.locators.js b/apps/token-e2e/src/locators/home.locators.js deleted file mode 100644 index 240bc3415..000000000 --- a/apps/token-e2e/src/locators/home.locators.js +++ /dev/null @@ -1,15 +0,0 @@ -export default { - tokenDetailsTable: '.token-details', - address: '[data-testid="token-address"]', - contract: '[data-testid="token-contract"]', - totalSupply: '[data-testid="total-supply"]', - circulatingSupply: '[data-testid="circulating-supply"]', - staked: '[data-testid="staked"]', - - tranchesLink: '[data-testid="tranches-link"]', - redeemBtn: '[data-testid="check-vesting-page-btn"]', - getVegaWalletLink: '[data-testid="get-vega-wallet-link"]', - associateVegaLink: '[data-testid="associate-vega-tokens-link-on-homepage"]', - stakingBtn: '[data-testid="staking-button-on-homepage"]', - governanceBtn: '[data-testid="governance-button-on-homepage"]', -}; diff --git a/apps/token-e2e/src/locators/navigation.locators.js b/apps/token-e2e/src/locators/navigation.locators.js deleted file mode 100644 index 24d414dc5..000000000 --- a/apps/token-e2e/src/locators/navigation.locators.js +++ /dev/null @@ -1,13 +0,0 @@ -import common from './common.locators'; - -export default { - ...common, - section: 'nav', - home: '[href="/"]', - vesting: '[href="/vesting"]', - staking: '[href="/staking"]', - rewards: '[href="/rewards"]', - withdraw: '[href="/withdraw"]', - governance: '[href="/governance"]', - spinner: 'splash-loader', -}; diff --git a/apps/token-e2e/src/locators/rewards.locators.js b/apps/token-e2e/src/locators/rewards.locators.js deleted file mode 100644 index 343ef2607..000000000 --- a/apps/token-e2e/src/locators/rewards.locators.js +++ /dev/null @@ -1,5 +0,0 @@ -import common from './common.locators'; - -export default { - ...common, -}; diff --git a/apps/token-e2e/src/locators/staking.locators.js b/apps/token-e2e/src/locators/staking.locators.js deleted file mode 100644 index cfbbb3424..000000000 --- a/apps/token-e2e/src/locators/staking.locators.js +++ /dev/null @@ -1,26 +0,0 @@ -import common from './common.locators'; - -export default { - ...common, - guideLink: '[data-testid="staking-guide-link"]', - step1: '[data-testid="staking-step-1"]', - step2: '[data-testid="staking-step-2"]', - step3: '[data-testid="staking-step-3"]', - connectToEthBtn: '[data-testid="connect-to-eth-btn"]', - connectToVegaBtn: '[data-testid="connect-to-vega-wallet-btn"]', - validatorNames: '[data-testid="node-list-item-name"]', - epochEndingText: '[data-testid="epoch-countdown"]', - addStakeRadioButton: '[data-testid="add-stake-radio"]', - removeStakeRadioButton: '[data-testid="remove-stake-radio"]', - tokenAmountInput: '[data-testid="token-amount-input"]', - tokenInputApprove: '[data-testid="token-input-approve-button"]', - tokenInputSubmit: '[data-testid="token-input-submit-button"]', - stakedAmounts: '[data-testid="staked-validator-item"]', - stakeNextEpochValue: '[data-testid="stake-next-epoch"]', - stakeThisEpochValue: '[data-testid="stake-this-epoch"]', - stakeMaximumTokens: '[data-testid="token-amount-use-maximum"]', - stakeAssociateWalletRadio: '[data-testid="associate-radio-wallet"]', - disassociateButton: '[data-testid="disassociate-tokens-btn"]', - associateMoreTokensButton: '[data-testid="associate-more-tokens-btn"]', - associateButton: '[data-testid="associate-tokens-btn"]', -}; diff --git a/apps/token-e2e/src/locators/vesting.locators.js b/apps/token-e2e/src/locators/vesting.locators.js deleted file mode 100644 index 90eb929cb..000000000 --- a/apps/token-e2e/src/locators/vesting.locators.js +++ /dev/null @@ -1,7 +0,0 @@ -import common from './common.locators'; - -export default { - ...common, - connectPrompt: '[data-testid="eth-connect-prompt"]', - connectButton: '[data-testid="connect-to-eth-btn"]', -}; diff --git a/apps/token-e2e/src/locators/wallet.locators.js b/apps/token-e2e/src/locators/wallet.locators.js deleted file mode 100644 index 94371a8aa..000000000 --- a/apps/token-e2e/src/locators/wallet.locators.js +++ /dev/null @@ -1,14 +0,0 @@ -import common from './common.locators'; - -export default { - ...common, - connectRestForm: '[data-testid="rest-connector-form"]', - name: '#wallet', - passphrase: '#passphrase', - vegawallet: '[data-testid="vega-wallet"]', - ethWallet: '[data-testid="ethereum-wallet"]', - ethWalletConnectToEth: '[data-testid="connect-to-eth-wallet-button"]', - ethWalletConnect: '[data-testid="web3-connector-Unknown"]', - ethWalletAssociate: '[href="/staking/associate"]', - ethWalletDisassociate: '[href="/staking/disassociate"]', -}; diff --git a/apps/token-e2e/src/locators/withdraw.locators.js b/apps/token-e2e/src/locators/withdraw.locators.js deleted file mode 100644 index 343ef2607..000000000 --- a/apps/token-e2e/src/locators/withdraw.locators.js +++ /dev/null @@ -1,5 +0,0 @@ -import common from './common.locators'; - -export default { - ...common, -}; diff --git a/apps/token-e2e/src/support/common.functions.js b/apps/token-e2e/src/support/common.functions.js new file mode 100644 index 000000000..3f02096b0 --- /dev/null +++ b/apps/token-e2e/src/support/common.functions.js @@ -0,0 +1,33 @@ +Cypress.Commands.add( + 'convert_token_value_to_number', + { prevSubject: true }, + (subject) => { + return parseFloat(subject.replace(/,/g, '')); + } +); + +const navigation = { + section: 'nav', + home: '[href="/"]', + vesting: '[href="/vesting"]', + staking: '[href="/staking"]', + rewards: '[href="/rewards"]', + withdraw: '[href="/withdraw"]', + governance: '[href="/governance"]', +}; + +Cypress.Commands.add('navigate_to', (page) => { + return cy.get(navigation.section).within(() => { + cy.get(navigation[page]).click(); + }); +}); + +Cypress.Commands.add('verify_tab_highlighted', (page) => { + return cy.get(navigation.section).within(() => { + cy.get(navigation[page]).should('have.attr', 'aria-current'); + }); +}); + +Cypress.Commands.add('verify_page_header', (text) => { + return cy.get('header h1').should('be.visible').and('have.text', text); +}); diff --git a/apps/token-e2e/src/support/eth-wallet.functions.js b/apps/token-e2e/src/support/eth-wallet.functions.js deleted file mode 100644 index 451c39b1e..000000000 --- a/apps/token-e2e/src/support/eth-wallet.functions.js +++ /dev/null @@ -1,51 +0,0 @@ -import wallet from '../locators/wallet.locators'; - -cy.ethereum_wallet_connect = () => { - cy.highlight('Connecting Eth Wallet'); - cy.get(wallet.ethWalletConnectToEth).within(() => { - cy.contains('Connect Ethereum wallet to associate $VEGA') - .should('be.visible') - .click(); - }); - cy.get(wallet.ethWalletConnect).click(); - cy.get(wallet.ethWalletConnect, { timeout: 60000 }).should('not.exist'); - cy.get(wallet.ethWallet).within(() => { - // this check is required since it ensures the wallet is fully (not partially) loaded - cy.contains('Locked', { timeout: 15000 }).should('be.visible'); - }); -}; - -cy.ethereum_wallet_check_associated_value_is = (expectedVal) => { - cy.highlight(`Checking Eth Wallet - Associated Value is ${expectedVal}`); - cy.get(wallet.ethWallet).within(() => { - cy.contains('Associated', { timeout: 20000 }) - .parent() - .siblings() - .contains(expectedVal, { timeout: 40000 }) - .should('be.visible'); - }); -}; - -cy.ethereum_wallet_check_associated_vega_key_value_is = ( - vegaShortPublicKey, - expectedVal -) => { - cy.highlight( - `Checking Eth Wallet - Vega Key Associated Value is ${expectedVal} for key ${vegaShortPublicKey}` - ); - cy.get(wallet.ethWallet).within(() => { - cy.contains(vegaShortPublicKey, { timeout: 20000 }) - .parent() - .contains(expectedVal, { timeout: 40000 }) - .should('be.visible'); - }); -}; - -cy.ethereum_wallet_check_associated_vega_key_is_no_longer_showing = ( - vegaShortPublicKey -) => { - cy.highlight('Checking Eth Wallet - Vega Key Associated is not showing'); - cy.get(wallet.ethWallet).within(() => { - cy.contains(vegaShortPublicKey, { timeout: 20000 }).should('not.exist'); - }); -}; diff --git a/apps/token-e2e/src/support/index.ts b/apps/token-e2e/src/support/index.ts index ac0235f29..f5a484c0d 100644 --- a/apps/token-e2e/src/support/index.ts +++ b/apps/token-e2e/src/support/index.ts @@ -1,5 +1,11 @@ import '@vegaprotocol/cypress'; +import './common.functions.js'; +import './staking.functions.js'; +import './wallet-eth.functions.js'; +import './wallet-teardown.functions.js'; +import './wallet-vega.functions.js'; + // Hide fetch/XHR requests - They create a lot of noise in command log const app = window.top; if (!app.document.head.querySelector('[data-hide-command-log-request]')) { diff --git a/apps/token-e2e/src/support/staking.functions.js b/apps/token-e2e/src/support/staking.functions.js index 57eb9e916..42652b3fb 100644 --- a/apps/token-e2e/src/support/staking.functions.js +++ b/apps/token-e2e/src/support/staking.functions.js @@ -1,11 +1,27 @@ -import staking from '../locators/staking.locators'; +const tokenAmountInputBox = '[data-testid="token-amount-input"]'; +const tokenSubmitButton = '[data-testid="token-input-submit-button"]'; +const tokenInputApprove = '[data-testid="token-input-approve-button"]'; +const addStakeRadioButton = '[data-testid="add-stake-radio"]'; +const removeStakeRadioButton = '[data-testid="remove-stake-radio"]'; +const ethWalletAssociateButton = '[href="/staking/associate"]'; +const ethWalletDissociateButton = '[href="/staking/disassociate"]'; +const associateWalletRadioButton = '[data-testid="associate-radio-wallet"]'; +const stakeMaximumTokens = '[data-testid="token-amount-use-maximum"]'; -cy.staking_validator_page_add_stake = (stake) => { +Cypress.Commands.add('wait_for_begining_of_epoch', () => { + cy.highlight(`Waiting for next epoch to start`); + cy.contains('Waiting for next epoch to start', { timeout: 10000 }).should( + 'not.exist' + ); + cy.contains('Waiting for next epoch to start', { timeout: 20000 }); +}); + +Cypress.Commands.add('staking_validator_page_add_stake', (stake) => { cy.highlight(`Adding a stake of ${stake}`); - cy.get(staking.addStakeRadioButton).click({ force: true }); - cy.get(staking.tokenAmountInput).type(stake); - cy.contains('Waiting for next epoch to start', { timeout: 10000 }); - cy.get(staking.tokenInputSubmit, { timeout: 8000 }) + cy.get(addStakeRadioButton).click({ force: true }); + cy.get(tokenAmountInputBox).type(stake); + cy.wait_for_begining_of_epoch(); + cy.get(tokenSubmitButton, { timeout: 8000 }) .should('be.enabled') .and('contain', `Add ${stake} $VEGA tokens`) .and('be.visible') @@ -14,14 +30,14 @@ cy.staking_validator_page_add_stake = (stake) => { 'At the beginning of the next epoch your $VEGA will be nominated to the validator', { timeout: 20000 } ).should('be.visible'); -}; +}); -cy.staking_validator_page_removeStake = (stake) => { +Cypress.Commands.add('staking_validator_page_removeStake', (stake) => { cy.highlight(`Removing a stake of ${stake}`); - cy.get(staking.removeStakeRadioButton).click({ force: true }); - cy.get(staking.tokenAmountInput).type(stake); - cy.contains('Waiting for next epoch to start', { timeout: 10000 }); - cy.get(staking.tokenInputSubmit) + cy.get(removeStakeRadioButton).click({ force: true }); + cy.get(tokenAmountInputBox).type(stake); + cy.wait_for_begining_of_epoch(); + cy.get(tokenSubmitButton) .should('be.enabled', { timeout: 8000 }) .and('contain', `Remove ${stake} $VEGA tokens at the end of epoch`) .and('be.visible') @@ -29,53 +45,52 @@ cy.staking_validator_page_removeStake = (stake) => { cy.contains(`${stake} $VEGA has been removed from validator`).should( 'be.visible' ); -}; +}); -cy.staking_page_associate_tokens = (amount, approve = false) => { - cy.highlight(`Associating ${amount} tokens`); - cy.get(staking.associateButton).click(); - cy.get(staking.stakeAssociateWalletRadio, { timeout: 30000 }).click(); - cy.get(staking.tokenAmountInput, { timeout: 10000 }).type(amount); - if (approve) { - cy.get(staking.tokenInputApprove, { timeout: 40000 }) - .should('be.enabled') - .click(); - cy.contains('Approve $VEGA Tokens for staking on Vega').should( - 'be.visible' - ); - cy.contains('Approve $VEGA Tokens for staking on Vega', { - timeout: 40000, - }).should('not.exist'); +Cypress.Commands.add( + 'staking_page_associate_tokens', + (amount, approve = false) => { + cy.highlight(`Associating ${amount} tokens`); + cy.get(ethWalletAssociateButton).first().click(); + cy.get(associateWalletRadioButton, { timeout: 30000 }).click(); + cy.get(tokenAmountInputBox, { timeout: 10000 }).type(amount); + if (approve) { + cy.get(tokenInputApprove, { timeout: 40000 }) + .should('be.enabled') + .click(); + cy.contains('Approve $VEGA Tokens for staking on Vega').should( + 'be.visible' + ); + cy.contains('Approve $VEGA Tokens for staking on Vega', { + timeout: 40000, + }).should('not.exist'); + } + cy.get(tokenSubmitButton, { timeout: 40000 }).should('be.enabled').click(); + cy.contains('can now participate in governance and nominate a validator', { + timeout: 60000, + }).should('be.visible'); } - cy.get(staking.tokenInputSubmit, { timeout: 40000 }) - .should('be.enabled') - .click(); - cy.contains('can now participate in governance and nominate a validator', { - timeout: 60000, - }).should('be.visible'); -}; +); -cy.staking_page_disassociate_tokens = (amount) => { +Cypress.Commands.add('staking_page_disassociate_tokens', (amount) => { cy.highlight(`Disassociating ${amount} tokens via Staking Page`); - cy.get(staking.disassociateButton).click(); - cy.get(staking.stakeAssociateWalletRadio, { timeout: 30000 }).click(); - cy.get(staking.tokenAmountInput, { timeout: 10000 }).type(amount); + cy.get(ethWalletDissociateButton).first().click(); + cy.get(associateWalletRadioButton, { timeout: 30000 }).click(); + cy.get(tokenAmountInputBox, { timeout: 10000 }).type(amount); - cy.get(staking.tokenInputSubmit, { timeout: 40000 }) - .should('be.enabled') - .click(); + cy.get(tokenSubmitButton, { timeout: 40000 }).should('be.enabled').click(); cy.contains(`${amount} $VEGA tokens have been returned to Ethereum wallet`, { timeout: 60000, }).should('be.visible'); -}; +}); -cy.staking_page_disassociate_all_tokens = () => { +Cypress.Commands.add('staking_page_disassociate_all_tokens', () => { cy.highlight(`Disassociating all tokens via Staking Page`); - cy.get(staking.disassociateButton).click(); - cy.get(staking.stakeAssociateWalletRadio, { timeout: 20000 }).click(); - cy.get(staking.stakeMaximumTokens, { timeout: 60000 }).click(); - cy.get(staking.tokenInputSubmit, { timeout: 10000 }).click(); + cy.get(ethWalletDissociateButton).first().click(); + cy.get(associateWalletRadioButton, { timeout: 20000 }).click(); + cy.get(stakeMaximumTokens, { timeout: 60000 }).click(); + cy.get(tokenSubmitButton, { timeout: 10000 }).click(); cy.contains('$VEGA tokens have been returned to Ethereum wallet', { timeout: 60000, }).should('be.visible'); -}; +}); diff --git a/apps/token-e2e/src/support/wallet-eth.functions.js b/apps/token-e2e/src/support/wallet-eth.functions.js new file mode 100644 index 000000000..1a4bec47d --- /dev/null +++ b/apps/token-e2e/src/support/wallet-eth.functions.js @@ -0,0 +1,57 @@ +const ethWalletContainer = '[data-testid="ethereum-wallet"]'; +const connectToEthButton = '[data-testid="connect-to-eth-wallet-button"]'; +const capsuleWalletConnectButton = '[data-testid="web3-connector-Unknown"]'; + +Cypress.Commands.add('ethereum_wallet_connect', () => { + cy.highlight('Connecting Eth Wallet'); + cy.get(connectToEthButton).within(() => { + cy.contains('Connect Ethereum wallet to associate $VEGA') + .should('be.visible') + .click(); + }); + cy.get(capsuleWalletConnectButton).click(); + cy.get(capsuleWalletConnectButton, { timeout: 60000 }).should('not.exist'); + cy.get(ethWalletContainer).within(() => { + // this check is required since it ensures the wallet is fully (not partially) loaded + cy.contains('Locked', { timeout: 15000 }).should('be.visible'); + }); +}); + +Cypress.Commands.add( + 'ethereum_wallet_check_associated_value_is', + (expectedVal) => { + cy.highlight(`Checking Eth Wallet - Associated Value is ${expectedVal}`); + cy.get(ethWalletContainer).within(() => { + cy.contains('Associated', { timeout: 20000 }) + .parent() + .siblings() + .contains(expectedVal, { timeout: 40000 }) + .should('be.visible'); + }); + } +); + +Cypress.Commands.add( + 'ethereum_wallet_check_associated_vega_key_value_is', + (vegaShortPublicKey, expectedVal) => { + cy.highlight( + `Checking Eth Wallet - Vega Key Associated Value is ${expectedVal} for key ${vegaShortPublicKey}` + ); + cy.get(ethWalletContainer).within(() => { + cy.contains(vegaShortPublicKey, { timeout: 20000 }) + .parent() + .contains(expectedVal, { timeout: 40000 }) + .should('be.visible'); + }); + } +); + +Cypress.Commands.add( + 'ethereum_wallet_check_associated_vega_key_is_no_longer_showing', + (vegaShortPublicKey) => { + cy.highlight('Checking Eth Wallet - Vega Key Associated is not showing'); + cy.get(ethWalletContainer).within(() => { + cy.contains(vegaShortPublicKey, { timeout: 20000 }).should('not.exist'); + }); + } +); diff --git a/apps/token-e2e/src/support/wallet-teardown.functions.js b/apps/token-e2e/src/support/wallet-teardown.functions.js index aef6805af..5642c07e0 100644 --- a/apps/token-e2e/src/support/wallet-teardown.functions.js +++ b/apps/token-e2e/src/support/wallet-teardown.functions.js @@ -64,27 +64,30 @@ Cypress.Commands.add( } ); -cy.vega_wallet_teardown_staking = (stakingBridgeContract) => { - cy.highlight('Tearing down staking tokens from vega wallet if present'); - cy.wrap( - stakingBridgeContract.stakeBalance(ethWalletPubKey, vegaWalletPubKey), - { - timeout: transactionTimeout, - log: false, - } - ).then((stake_amount) => { - if (String(stake_amount) != '0') { - cy.wrap( - stakingBridgeContract.removeStake(stake_amount, vegaWalletPubKey), - { timeout: transactionTimeout, log: false } - ).then((tx) => { - cy.wait_for_transaction(tx); - }); - } - }); -}; +Cypress.Commands.add( + 'vega_wallet_teardown_staking', + (stakingBridgeContract) => { + cy.highlight('Tearing down staking tokens from vega wallet if present'); + cy.wrap( + stakingBridgeContract.stakeBalance(ethWalletPubKey, vegaWalletPubKey), + { + timeout: transactionTimeout, + log: false, + } + ).then((stake_amount) => { + if (String(stake_amount) != '0') { + cy.wrap( + stakingBridgeContract.removeStake(stake_amount, vegaWalletPubKey), + { timeout: transactionTimeout, log: false } + ).then((tx) => { + cy.wait_for_transaction(tx); + }); + } + }); + } +); -cy.vega_wallet_teardown_vesting = (vestingContract) => { +Cypress.Commands.add('vega_wallet_teardown_vesting', (vestingContract) => { cy.highlight('Tearing down vesting tokens from vega wallet if present'); cy.wrap(vestingContract.stakeBalance(ethWalletPubKey, vegaWalletPubKey), { timeout: transactionTimeout, @@ -99,8 +102,8 @@ cy.vega_wallet_teardown_vesting = (vestingContract) => { }); } }); -}; +}); -cy.wait_for_transaction = (tx) => { +Cypress.Commands.add('wait_for_transaction', (tx) => { cy.wrap(tx.wait(1).catch(cy.log), { timeout: transactionTimeout }); -}; +}); diff --git a/apps/token-e2e/src/support/vega-wallet.functions.js b/apps/token-e2e/src/support/wallet-vega.functions.js similarity index 68% rename from apps/token-e2e/src/support/vega-wallet.functions.js rename to apps/token-e2e/src/support/wallet-vega.functions.js index ef350181e..3ab43139d 100644 --- a/apps/token-e2e/src/support/vega-wallet.functions.js +++ b/apps/token-e2e/src/support/wallet-vega.functions.js @@ -1,10 +1,10 @@ -import wallet from '../locators/wallet.locators'; - +const vegaWalletContainer = '[data-testid="vega-wallet"]'; +const restConnectorForm = '[data-testid="rest-connector-form"]'; const vegaWalletName = Cypress.env('vegaWalletName'); const vegaWalletLocation = Cypress.env('vegaWalletLocation'); const vegaWalletPassphrase = Cypress.env('vegaWalletPassphrase'); -cy.vega_wallet_import = () => { +Cypress.Commands.add('vega_wallet_import', () => { cy.highlight(`Importing Vega Wallet ${vegaWalletName}`); cy.exec(`vegawallet init -f --home ${vegaWalletLocation}`); cy.exec( @@ -14,11 +14,11 @@ cy.vega_wallet_import = () => { cy.exec( `vegawallet service run --network DV --automatic-consent --home ${vegaWalletLocation}` ); -}; +}); -cy.vega_wallet_connect = () => { +Cypress.Commands.add('vega_wallet_connect', () => { cy.highlight('Connecting Vega Wallet'); - cy.get(wallet.vegawallet).within(() => { + cy.get(vegaWalletContainer).within(() => { cy.get('button') .contains('Connect Vega wallet to use associated $VEGA') .should('be.enabled') @@ -26,31 +26,31 @@ cy.vega_wallet_connect = () => { .click({ force: true }); }); cy.get('button').contains('rest provider').click(); - cy.get(wallet.connectRestForm).within(() => { - cy.get(wallet.name).click().type(vegaWalletName); - cy.get(wallet.passphrase).click().type(vegaWalletPassphrase); + cy.get(restConnectorForm).within(() => { + cy.get('#wallet').click().type(vegaWalletName); + cy.get('#passphrase').click().type(vegaWalletPassphrase); cy.get('button').contains('Connect').click(); }); cy.contains(`${vegaWalletName} key`, { timeout: 20000 }).should('be.visible'); -}; +}); -cy.vega_wallet_check_unstaked_value_is = (expectedVal) => { +Cypress.Commands.add('vega_wallet_check_unstaked_value_is', (expectedVal) => { cy.highlight(`Checking vega wallet - Unstaked Value is ${expectedVal}`); - cy.get(wallet.vegawallet).within(() => { + cy.get(vegaWalletContainer).within(() => { cy.contains('Unstaked', { timeout: 40000 }) .siblings() .contains(expectedVal, { timeout: 40000 }) .should('be.visible'); }); -}; +}); -cy.vega_wallet_check_associated_value_is = (expectedVal) => { +Cypress.Commands.add('vega_wallet_check_associated_value_is', (expectedVal) => { cy.highlight(`Checking vega wallet - Associated Value is ${expectedVal}`); - cy.get(wallet.vegawallet).within(() => { + cy.get(vegaWalletContainer).within(() => { cy.contains('Associated', { timeout: 40000 }) .parent() .siblings() .contains(expectedVal, { timeout: 40000 }) .should('be.visible'); }); -}; +}); diff --git a/apps/token/src/components/eth-wallet/eth-wallet.tsx b/apps/token/src/components/eth-wallet/eth-wallet.tsx index 63e97b8af..509542acc 100644 --- a/apps/token/src/components/eth-wallet/eth-wallet.tsx +++ b/apps/token/src/components/eth-wallet/eth-wallet.tsx @@ -128,7 +128,7 @@ const ConnectedKey = () => { return ( <> {totalVestedBalance.plus(totalLockedBalance).isEqualTo(0) ? null : ( - <> +
{ rightLabel={t('Unlocked')} light={false} /> - +
)} {!Object.keys(appState.associationBreakdown.vestingAssociations) .length ? null : ( @@ -154,22 +154,24 @@ const ConnectedKey = () => { notAssociated={notAssociatedInContract} /> )} - - {!Object.keys( - appState.associationBreakdown.stakingAssociations - ) ? null : ( - + - )} + {!Object.keys( + appState.associationBreakdown.stakingAssociations + ) ? null : ( + + )} + {

{t('ethereumKey')}

{account && (
-
{truncateMiddle(account)}
+
+ {truncateMiddle(account)} +
{pendingTxs && (
diff --git a/apps/token/src/components/locked-progress/locked-progress.tsx b/apps/token/src/components/locked-progress/locked-progress.tsx index 2101e48ab..37fe0c5c2 100644 --- a/apps/token/src/components/locked-progress/locked-progress.tsx +++ b/apps/token/src/components/locked-progress/locked-progress.tsx @@ -99,6 +99,7 @@ export const LockedProgress = ({ 'border-black': light, 'border-white': !light, })} + data-testid="progress-bar" > @@ -119,8 +120,12 @@ export const LockedProgress = ({ - {formatNumber(locked, decimals)} - {formatNumber(unlocked, decimals)} + + {formatNumber(locked, decimals)} + + + {formatNumber(unlocked, decimals)} +
); diff --git a/apps/token/src/components/wallet-card/wallet-card.tsx b/apps/token/src/components/wallet-card/wallet-card.tsx index 0313decd3..9ea5b6c80 100644 --- a/apps/token/src/components/wallet-card/wallet-card.tsx +++ b/apps/token/src/components/wallet-card/wallet-card.tsx @@ -47,7 +47,10 @@ interface WalletCardHeaderProps { export const WalletCardHeader = ({ children }: WalletCardHeaderProps) => { return ( -
+
{children}
); @@ -151,7 +154,10 @@ export const WalletCardAsset = ({ }`} />
-
+

-
+
{integers}. {decimalsPlaces} diff --git a/apps/token/src/components/web3-connector/web3-connector.tsx b/apps/token/src/components/web3-connector/web3-connector.tsx index 954bad4df..4691e4e23 100644 --- a/apps/token/src/components/web3-connector/web3-connector.tsx +++ b/apps/token/src/components/web3-connector/web3-connector.tsx @@ -68,7 +68,7 @@ export const Web3Content = ({ children, appChainId }: Web3ContentProps) => { return (
-

Something went wrong: {error.message}

+

Something went wrong: {error.message}

@@ -79,7 +79,9 @@ export const Web3Content = ({ children, appChainId }: Web3ContentProps) => { return (
-

This app only works on chain ID: {appChainId}

+

+ This app only works on chain ID: {appChainId} +

diff --git a/apps/trading-e2e/src/integration/trading-accounts.cy.ts b/apps/trading-e2e/src/integration/trading-accounts.cy.ts index afefabbed..388b8102a 100644 --- a/apps/trading-e2e/src/integration/trading-accounts.cy.ts +++ b/apps/trading-e2e/src/integration/trading-accounts.cy.ts @@ -18,21 +18,25 @@ describe('accounts', () => { cy.getByTestId('tab-accounts').should('be.visible'); cy.getByTestId('tab-accounts') + .should('be.visible') .get(`[row-id='General-tEURO-null']`) .find('[col-id="asset.symbol"]') .should('have.text', 'tEURO'); cy.getByTestId('tab-accounts') + .should('be.visible') .get(`[row-id='General-tEURO-null']`) .find('[col-id="type"]') .should('have.text', 'General'); cy.getByTestId('tab-accounts') + .should('be.visible') .get(`[row-id='General-tEURO-null']`) .find('[col-id="market.name"]') .should('have.text', '—'); cy.getByTestId('tab-accounts') + .should('be.visible') .get(`[row-id='General-tEURO-null']`) .find('[col-id="balance"]') .should('have.text', '1,000.00000'); diff --git a/apps/trading-e2e/src/integration/trading-deal-ticket.cy.ts b/apps/trading-e2e/src/integration/trading-deal-ticket.cy.ts index b1015fc6b..6f20e96ec 100644 --- a/apps/trading-e2e/src/integration/trading-deal-ticket.cy.ts +++ b/apps/trading-e2e/src/integration/trading-deal-ticket.cy.ts @@ -33,7 +33,7 @@ describe('deal ticket orders', () => { const orderTIFDropDown = 'order-tif'; const placeOrderBtn = 'place-order'; const orderStatusHeader = 'order-status-header'; - const orderTransactionHash = 'tx-hash'; + const orderTransactionHash = 'tx-block-explorer'; before(() => { cy.mockGQL((req) => { diff --git a/apps/trading-e2e/src/integration/trading-positions.cy.ts b/apps/trading-e2e/src/integration/trading-positions.cy.ts index 8b362e9db..e1c2d4e45 100644 --- a/apps/trading-e2e/src/integration/trading-positions.cy.ts +++ b/apps/trading-e2e/src/integration/trading-positions.cy.ts @@ -19,6 +19,7 @@ describe('positions', () => { cy.getByTestId('tab-positions').should('be.visible'); cy.getByTestId('tab-positions') .get('[col-id="market.tradableInstrument.instrument.code"]') + .should('be.visible') .each(($marketSymbol) => { cy.wrap($marketSymbol).invoke('text').should('not.be.empty'); }); diff --git a/apps/trading-e2e/src/support/mocks/generate-orders.ts b/apps/trading-e2e/src/support/mocks/generate-orders.ts index 6c7219f62..08ec6ea23 100644 --- a/apps/trading-e2e/src/support/mocks/generate-orders.ts +++ b/apps/trading-e2e/src/support/mocks/generate-orders.ts @@ -1,6 +1,6 @@ import merge from 'lodash/merge'; import type { PartialDeep } from 'type-fest'; -import type { Orders, Orders_party_orders } from '@vegaprotocol/order-list'; +import type { Orders, Orders_party_orders } from '@vegaprotocol/orders'; import { OrderStatus, OrderTimeInForce, diff --git a/apps/trading/pages/__generated__/MarketsLanding.ts b/apps/trading/pages/__generated__/MarketsLanding.ts index 266864354..edc7cb8fe 100644 --- a/apps/trading/pages/__generated__/MarketsLanding.ts +++ b/apps/trading/pages/__generated__/MarketsLanding.ts @@ -3,7 +3,7 @@ // @generated // This file was automatically generated and should not be edited. -import { MarketTradingMode } from "@vegaprotocol/types"; +import { MarketTradingMode, MarketState } from "@vegaprotocol/types"; // ==================================================== // GraphQL query operation: MarketsLanding @@ -27,6 +27,10 @@ export interface MarketsLanding_markets { * Current mode of execution of the market */ tradingMode: MarketTradingMode; + /** + * Current state of the market + */ + state: MarketState; /** * timestamps for state changes in the market */ diff --git a/apps/trading/pages/index.page.tsx b/apps/trading/pages/index.page.tsx index ee52b352b..d33792245 100644 --- a/apps/trading/pages/index.page.tsx +++ b/apps/trading/pages/index.page.tsx @@ -1,7 +1,7 @@ import { gql, useQuery } from '@apollo/client'; import { MarketTradingMode } from '@vegaprotocol/types'; import { AsyncRenderer } from '@vegaprotocol/ui-toolkit'; -import sortBy from 'lodash/sortBy'; +import orderBy from 'lodash/orderBy'; import { useRouter } from 'next/router'; import { useEffect } from 'react'; import { useGlobalStore } from '../stores'; @@ -12,6 +12,7 @@ const MARKETS_QUERY = gql` markets { id tradingMode + state marketTimestamps { open } @@ -20,13 +21,13 @@ const MARKETS_QUERY = gql` `; const marketList = ({ markets }: MarketsLanding) => - sortBy( + orderBy( markets?.filter( ({ marketTimestamps, tradingMode }) => marketTimestamps.open && tradingMode === MarketTradingMode.Continuous ) || [], - 'marketTimestamps.open', - 'id' + ['state', 'marketTimestamps.open', 'id'], + ['asc', 'asc', 'asc'] ); export function Index() { diff --git a/apps/trading/pages/markets/[marketId].page.tsx b/apps/trading/pages/markets/[marketId].page.tsx index a1cfc4844..463c3d16b 100644 --- a/apps/trading/pages/markets/[marketId].page.tsx +++ b/apps/trading/pages/markets/[marketId].page.tsx @@ -81,6 +81,7 @@ const MarketPage = ({ id }: { id?: string }) => { return ( query={MARKET_QUERY} + data-testid="market" options={{ variables: { marketId, diff --git a/apps/trading/pages/markets/trade-grid.tsx b/apps/trading/pages/markets/trade-grid.tsx index 2f150c99a..1aac09459 100644 --- a/apps/trading/pages/markets/trade-grid.tsx +++ b/apps/trading/pages/markets/trade-grid.tsx @@ -6,7 +6,7 @@ import { DealTicketContainer, MarketInfoContainer, } from '@vegaprotocol/deal-ticket'; -import { OrderListContainer } from '@vegaprotocol/order-list'; +import { OrderListContainer } from '@vegaprotocol/orders'; import { TradesContainer } from '@vegaprotocol/trades'; import { PositionsContainer } from '@vegaprotocol/positions'; import { OrderbookContainer } from '@vegaprotocol/market-depth'; diff --git a/apps/trading/pages/portfolio/index.page.tsx b/apps/trading/pages/portfolio/index.page.tsx index 43310c627..8deed921b 100644 --- a/apps/trading/pages/portfolio/index.page.tsx +++ b/apps/trading/pages/portfolio/index.page.tsx @@ -1,7 +1,7 @@ import { Web3Container } from '../../components/web3-container'; import { t } from '@vegaprotocol/react-helpers'; import { PositionsContainer } from '@vegaprotocol/positions'; -import { OrderListContainer } from '@vegaprotocol/order-list'; +import { OrderListContainer } from '@vegaprotocol/orders'; import { AccountsContainer } from '@vegaprotocol/accounts'; import { AnchorButton, Tab, Tabs } from '@vegaprotocol/ui-toolkit'; import { WithdrawalsContainer } from './withdrawals/withdrawals-container'; diff --git a/libs/deal-ticket/src/components/__generated__/MarketNames.ts b/libs/deal-ticket/src/components/__generated__/MarketNames.ts new file mode 100644 index 000000000..29335eed5 --- /dev/null +++ b/libs/deal-ticket/src/components/__generated__/MarketNames.ts @@ -0,0 +1,67 @@ +/* tslint:disable */ +/* eslint-disable */ +// @generated +// This file was automatically generated and should not be edited. + +// ==================================================== +// GraphQL query operation: MarketNames +// ==================================================== + +export interface MarketNames_markets_tradableInstrument_instrument_metadata { + __typename: "InstrumentMetadata"; + /** + * An arbitrary list of tags to associated to associate to the Instrument (string list) + */ + tags: string[] | null; +} + +export interface MarketNames_markets_tradableInstrument_instrument_product { + __typename: "Future"; + /** + * String representing the quote (e.g. BTCUSD -> USD is quote) + */ + quoteName: string; +} + +export interface MarketNames_markets_tradableInstrument_instrument { + __typename: "Instrument"; + /** + * Metadata for this instrument + */ + metadata: MarketNames_markets_tradableInstrument_instrument_metadata; + /** + * A reference to or instance of a fully specified product, including all required product parameters for that product (Product union) + */ + product: MarketNames_markets_tradableInstrument_instrument_product; +} + +export interface MarketNames_markets_tradableInstrument { + __typename: "TradableInstrument"; + /** + * An instance of or reference to a fully specified instrument. + */ + instrument: MarketNames_markets_tradableInstrument_instrument; +} + +export interface MarketNames_markets { + __typename: "Market"; + /** + * Market ID + */ + id: string; + /** + * Market full name + */ + name: string; + /** + * An instance of or reference to a tradable instrument. + */ + tradableInstrument: MarketNames_markets_tradableInstrument; +} + +export interface MarketNames { + /** + * One or more instruments that are trading on the VEGA network + */ + markets: MarketNames_markets[] | null; +} diff --git a/libs/deal-ticket/src/components/__generated__/index.ts b/libs/deal-ticket/src/components/__generated__/index.ts index b307559ae..b9d08aad0 100644 --- a/libs/deal-ticket/src/components/__generated__/index.ts +++ b/libs/deal-ticket/src/components/__generated__/index.ts @@ -1,2 +1,3 @@ export * from './DealTicketQuery'; export * from './MarketInfoQuery'; +export * from './MarketNames'; diff --git a/libs/deal-ticket/src/components/deal-ticket-amount.tsx b/libs/deal-ticket/src/components/deal-ticket-amount.tsx index b497d5554..000153aea 100644 --- a/libs/deal-ticket/src/components/deal-ticket-amount.tsx +++ b/libs/deal-ticket/src/components/deal-ticket-amount.tsx @@ -1,11 +1,11 @@ import type { UseFormRegister } from 'react-hook-form'; -import { OrderType } from '@vegaprotocol/wallet'; -import type { Order } from '../utils/get-default-order'; +import { VegaWalletOrderType } from '@vegaprotocol/wallet'; +import type { Order } from '@vegaprotocol/orders'; import { DealTicketMarketAmount } from './deal-ticket-market-amount'; import { DealTicketLimitAmount } from './deal-ticket-limit-amount'; export interface DealTicketAmountProps { - orderType: OrderType; + orderType: VegaWalletOrderType; step: number; register: UseFormRegister; quoteName: string; @@ -17,9 +17,9 @@ export const DealTicketAmount = ({ ...props }: DealTicketAmountProps) => { switch (orderType) { - case OrderType.Market: + case VegaWalletOrderType.Market: return ; - case OrderType.Limit: + case VegaWalletOrderType.Limit: return ; default: { throw new Error('Invalid ticket type'); diff --git a/libs/deal-ticket/src/components/deal-ticket-limit-amount.tsx b/libs/deal-ticket/src/components/deal-ticket-limit-amount.tsx index ffd16b738..87622b3f4 100644 --- a/libs/deal-ticket/src/components/deal-ticket-limit-amount.tsx +++ b/libs/deal-ticket/src/components/deal-ticket-limit-amount.tsx @@ -1,6 +1,6 @@ import { FormGroup, Input } from '@vegaprotocol/ui-toolkit'; import { t } from '@vegaprotocol/react-helpers'; -import { validateSize } from '../utils/validate-size'; +import { validateSize } from '@vegaprotocol/orders'; import type { DealTicketAmountProps } from './deal-ticket-amount'; export type DealTicketLimitAmountProps = Omit< diff --git a/libs/deal-ticket/src/components/deal-ticket-manager.tsx b/libs/deal-ticket/src/components/deal-ticket-manager.tsx index f23ec326b..b202f6c6f 100644 --- a/libs/deal-ticket/src/components/deal-ticket-manager.tsx +++ b/libs/deal-ticket/src/components/deal-ticket-manager.tsx @@ -1,11 +1,10 @@ import type { ReactNode } from 'react'; -import { useEffect, useState } from 'react'; -import { Dialog, Intent } from '@vegaprotocol/ui-toolkit'; -import { OrderStatus } from '@vegaprotocol/types'; -import { VegaOrderTransactionDialog, VegaTxStatus } from '@vegaprotocol/wallet'; +import { useState } from 'react'; +import { VegaTransactionDialog, VegaTxStatus } from '@vegaprotocol/wallet'; import { DealTicket } from './deal-ticket'; -import { useOrderSubmit } from '../hooks/use-order-submit'; import type { DealTicketQuery_market } from './__generated__/DealTicketQuery'; +import { useOrderSubmit } from '@vegaprotocol/orders'; +import { OrderStatus } from '@vegaprotocol/types'; export interface DealTicketManagerProps { market: DealTicketQuery_market; @@ -18,43 +17,20 @@ export const DealTicketManager = ({ }: DealTicketManagerProps) => { const [orderDialogOpen, setOrderDialogOpen] = useState(false); const { submit, transaction, finalizedOrder, reset } = useOrderSubmit(market); - - const getDialogIntent = (status: VegaTxStatus) => { - if (finalizedOrder) { - if ( - finalizedOrder.status === OrderStatus.Active || - finalizedOrder.status === OrderStatus.Filled || - finalizedOrder.status === OrderStatus.PartiallyFilled - ) { - return Intent.Success; - } - - if (finalizedOrder.status === OrderStatus.Parked) { - return Intent.Warning; - } - - return Intent.Danger; + const getDialogTitle = (status?: string) => { + switch (status) { + case OrderStatus.Active: + return 'Order submitted'; + case OrderStatus.Filled: + return 'Order filled'; + case OrderStatus.PartiallyFilled: + return 'Order partially filled'; + case OrderStatus.Parked: + return 'Order parked'; + default: + return 'Submission failed'; } - - if (status === VegaTxStatus.Requested) { - return Intent.Warning; - } - - if (status === VegaTxStatus.Error) { - return Intent.Danger; - } - - return Intent.None; }; - - useEffect(() => { - if (transaction.status !== VegaTxStatus.Default || finalizedOrder) { - setOrderDialogOpen(true); - } else { - setOrderDialogOpen(false); - } - }, [finalizedOrder, transaction.status]); - return ( <> {children || ( @@ -69,23 +45,15 @@ export const DealTicketManager = ({ } /> )} - { - setOrderDialogOpen(isOpen); - - // If closing reset - if (!isOpen) { - reset(); - } - }} - intent={getDialogIntent(transaction.status)} - > - - + ); }; diff --git a/libs/deal-ticket/src/components/deal-ticket-market-amount.tsx b/libs/deal-ticket/src/components/deal-ticket-market-amount.tsx index 483e721cc..881f3c439 100644 --- a/libs/deal-ticket/src/components/deal-ticket-market-amount.tsx +++ b/libs/deal-ticket/src/components/deal-ticket-market-amount.tsx @@ -1,6 +1,6 @@ import { FormGroup, Input } from '@vegaprotocol/ui-toolkit'; import { t } from '@vegaprotocol/react-helpers'; -import { validateSize } from '../utils/validate-size'; +import { validateSize } from '@vegaprotocol/orders'; import type { DealTicketAmountProps } from './deal-ticket-amount'; export type DealTicketMarketAmountProps = Omit< diff --git a/libs/deal-ticket/src/components/deal-ticket.spec.tsx b/libs/deal-ticket/src/components/deal-ticket.spec.tsx index 50a8ee1fa..2b06c0c6e 100644 --- a/libs/deal-ticket/src/components/deal-ticket.spec.tsx +++ b/libs/deal-ticket/src/components/deal-ticket.spec.tsx @@ -1,7 +1,7 @@ import { VegaWalletContext, - OrderTimeInForce, - OrderType, + VegaWalletOrderTimeInForce, + VegaWalletOrderType, } from '@vegaprotocol/wallet'; import { addDecimal } from '@vegaprotocol/react-helpers'; import { fireEvent, render, screen, act } from '@testing-library/react'; @@ -64,7 +64,7 @@ it('Displays ticket defaults', () => { // Assert defaults are used expect( - screen.getByTestId(`order-type-${OrderType.Market}-selected`) + screen.getByTestId(`order-type-${VegaWalletOrderType.Market}-selected`) ).toBeInTheDocument(); expect( screen.queryByTestId('order-side-SIDE_BUY-selected') @@ -75,7 +75,9 @@ it('Displays ticket defaults', () => { expect(screen.getByTestId('order-size')).toHaveDisplayValue( String(1 / Math.pow(10, market.positionDecimalPlaces)) ); - expect(screen.getByTestId('order-tif')).toHaveValue(OrderTimeInForce.IOC); + expect(screen.getByTestId('order-tif')).toHaveValue( + VegaWalletOrderTimeInForce.IOC + ); // Assert last price is shown expect(screen.getByTestId('last-price')).toHaveTextContent( @@ -101,9 +103,11 @@ it('Can edit deal ticket', async () => { expect(screen.getByTestId('order-size')).toHaveDisplayValue('200'); fireEvent.change(screen.getByTestId('order-tif'), { - target: { value: OrderTimeInForce.IOC }, + target: { value: VegaWalletOrderTimeInForce.IOC }, }); - expect(screen.getByTestId('order-tif')).toHaveValue(OrderTimeInForce.IOC); + expect(screen.getByTestId('order-tif')).toHaveValue( + VegaWalletOrderTimeInForce.IOC + ); // Switch to limit order fireEvent.click(screen.getByTestId('order-type-TYPE_LIMIT')); @@ -113,7 +117,7 @@ it('Can edit deal ticket', async () => { // Check all TIF options shown expect(screen.getByTestId('order-tif').children).toHaveLength( - Object.keys(OrderTimeInForce).length + Object.keys(VegaWalletOrderTimeInForce).length ); }); @@ -130,26 +134,34 @@ it('Handles TIF select box dependent on order type', () => { // Switch to limit order and check all TIF options shown fireEvent.click(screen.getByTestId('order-type-TYPE_LIMIT')); expect(screen.getByTestId('order-tif').children).toHaveLength( - Object.keys(OrderTimeInForce).length + Object.keys(VegaWalletOrderTimeInForce).length ); // Change to GTC fireEvent.change(screen.getByTestId('order-tif'), { - target: { value: OrderTimeInForce.GTC }, + target: { value: VegaWalletOrderTimeInForce.GTC }, }); - expect(screen.getByTestId('order-tif')).toHaveValue(OrderTimeInForce.GTC); + expect(screen.getByTestId('order-tif')).toHaveValue( + VegaWalletOrderTimeInForce.GTC + ); // Switch back to market order and TIF should now be IOC fireEvent.click(screen.getByTestId('order-type-TYPE_MARKET')); - expect(screen.getByTestId('order-tif')).toHaveValue(OrderTimeInForce.IOC); + expect(screen.getByTestId('order-tif')).toHaveValue( + VegaWalletOrderTimeInForce.IOC + ); // Switch tif to FOK fireEvent.change(screen.getByTestId('order-tif'), { - target: { value: OrderTimeInForce.FOK }, + target: { value: VegaWalletOrderTimeInForce.FOK }, }); - expect(screen.getByTestId('order-tif')).toHaveValue(OrderTimeInForce.FOK); + expect(screen.getByTestId('order-tif')).toHaveValue( + VegaWalletOrderTimeInForce.FOK + ); // Change back to limit and check we are still on FOK fireEvent.click(screen.getByTestId('order-type-TYPE_LIMIT')); - expect(screen.getByTestId('order-tif')).toHaveValue(OrderTimeInForce.FOK); + expect(screen.getByTestId('order-tif')).toHaveValue( + VegaWalletOrderTimeInForce.FOK + ); }); diff --git a/libs/deal-ticket/src/components/deal-ticket.tsx b/libs/deal-ticket/src/components/deal-ticket.tsx index eb4a87724..8daf81b18 100644 --- a/libs/deal-ticket/src/components/deal-ticket.tsx +++ b/libs/deal-ticket/src/components/deal-ticket.tsx @@ -1,17 +1,19 @@ import { useCallback } from 'react'; import { useForm, Controller } from 'react-hook-form'; -import { OrderType, OrderTimeInForce } from '@vegaprotocol/wallet'; +import { + VegaWalletOrderType, + VegaWalletOrderTimeInForce, +} from '@vegaprotocol/wallet'; import { t, addDecimal, toDecimal } from '@vegaprotocol/react-helpers'; import { Button, InputError } from '@vegaprotocol/ui-toolkit'; import { TypeSelector } from './type-selector'; import { SideSelector } from './side-selector'; import { DealTicketAmount } from './deal-ticket-amount'; import { TimeInForceSelector } from './time-in-force-selector'; -import { useOrderValidation } from '../hooks/use-order-validation'; import type { DealTicketQuery_market } from './__generated__/DealTicketQuery'; -import type { Order } from '../utils/get-default-order'; -import { getDefaultOrder } from '../utils/get-default-order'; import { ExpirySelector } from './expiry-selector'; +import type { Order } from '@vegaprotocol/orders'; +import { getDefaultOrder, useOrderValidation } from '@vegaprotocol/orders'; export type TransactionStatus = 'default' | 'pending'; @@ -97,8 +99,8 @@ export const DealTicket = ({ /> )} /> - {orderType === OrderType.Limit && - orderTimeInForce === OrderTimeInForce.GTT && ( + {orderType === VegaWalletOrderType.Limit && + orderTimeInForce === VegaWalletOrderTimeInForce.GTT && ( void; + ItemRenderer?: React.FC<{ market: MarketNames_markets }>; +} + +function escapeRegExp(str: string) { + return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); +} + +export const MarketSelector = ({ market, setMarket, ItemRenderer }: Props) => { + const { isMobile } = useScreenDimensions(); + const contRef = useRef(null); + const inputRef = useRef(null); + const arrowButtonRef = useRef(null); + const [skip, setSkip] = useState(true); + const [results, setResults] = useState([]); + const [showPane, setShowPane] = useState(false); + const [lookup, setLookup] = useState(market.name || ''); + const [dialogContent, setDialogContent] = useState( + null + ); + + const { data, loading, error } = useQuery(MARKET_NAMES_QUERY, { + skip, + }); + + const outsideClickCb = useCallback(() => { + if (!isMobile) { + setShowPane(false); + } + }, [setShowPane, isMobile]); + + useOutsideClick({ refs: [contRef, arrowButtonRef], func: outsideClickCb }); + + const handleOnChange = useCallback( + (event: React.ChangeEvent) => { + const { + target: { value }, + } = event; + setLookup(value); + setShowPane(true); + if (value) { + setSkip(false); + } + }, + [setLookup, setShowPane, setSkip] + ); + + const handleMarketSelect = useCallback( + ({ id, name }) => { + setLookup(name); + setShowPane(false); + setMarket(id); + inputRef.current?.focus(); + }, + [setLookup, setShowPane, setMarket, inputRef] + ); + + const handleItemKeyDown = useCallback( + ( + event: React.KeyboardEvent, + market: MarketNames_markets, + index: number + ) => { + switch (event.key) { + case 'ArrowDown': + if (index < results.length - 1) { + (contRef.current?.children[index + 1] as HTMLDivElement).focus(); + } + break; + + case 'ArrowUp': + if (!index) { + inputRef.current?.focus(); + inputRef.current?.setSelectionRange( + inputRef.current?.value.length, + inputRef.current?.value.length + ); + return; + } + (contRef.current?.children[index - 1] as HTMLDivElement).focus(); + break; + + case 'Enter': + handleMarketSelect(market); + break; + } + }, + [results, handleMarketSelect] + ); + + const handleInputKeyDown = useCallback( + (event: React.KeyboardEvent) => { + if (event.key === 'ArrowDown') { + (contRef.current?.children[0] as HTMLDivElement).focus(); + } + }, + [contRef] + ); + + const handleOnBlur = useCallback(() => { + console.log('lookup, showPane', lookup, showPane); + if (!lookup && !showPane) { + console.log( + '2 lookup, showPane, market.name', + lookup, + showPane, + market.name + ); + setLookup(market.name); + } + }, [market, lookup, showPane, setLookup]); + + const openPane = useCallback(() => { + setShowPane(!showPane); + setSkip(false); + inputRef.current?.focus(); + }, [showPane, setShowPane, setSkip, inputRef]); + + const handleDialogOnchange = useCallback( + (isOpen) => { + setShowPane(isOpen); + if (!isOpen) { + setLookup(lookup || market.name); + inputRef.current?.focus(); + } + }, + [setShowPane, lookup, setLookup, market.name, inputRef] + ); + + const selectorContent = useMemo(() => { + return ( +
+
+ + +
+
+
+ {loading && } + {error && ( + {t(`Something went wrong: ${error.message}`)} + )} +
+ {results.map((market, i) => ( +
handleMarketSelect(market)} + onKeyDown={(e) => handleItemKeyDown(e, market, i)} + > + {ItemRenderer ? : market.name} +
+ ))} +
+
+
+ ); + }, [ + ItemRenderer, + error, + handleInputKeyDown, + handleItemKeyDown, + handleMarketSelect, + handleOnBlur, + handleOnChange, + loading, + lookup, + openPane, + results, + showPane, + ]); + + useEffect(() => { + setResults( + data?.markets?.filter((item: MarketNames_markets) => + item.name.match(new RegExp(escapeRegExp(lookup), 'i')) + ) || [] + ); + }, [data, lookup]); + + useEffect(() => { + inputRef.current?.focus(); + }, [inputRef]); + + useEffect(() => { + if (showPane && isMobile) { + setDialogContent(selectorContent); + inputRef.current?.focus(); + window.scrollTo(0, 0); + } else { + setDialogContent(null); + } + }, [selectorContent, showPane, isMobile, setDialogContent]); + + return ( + <> + {!dialogContent && selectorContent} + + {dialogContent} + + + ); +}; diff --git a/libs/deal-ticket/src/components/side-selector.tsx b/libs/deal-ticket/src/components/side-selector.tsx index a78180824..adc3c6081 100644 --- a/libs/deal-ticket/src/components/side-selector.tsx +++ b/libs/deal-ticket/src/components/side-selector.tsx @@ -1,16 +1,16 @@ import { FormGroup } from '@vegaprotocol/ui-toolkit'; -import { OrderSide } from '@vegaprotocol/wallet'; +import { VegaWalletOrderSide } from '@vegaprotocol/wallet'; import { Toggle } from '@vegaprotocol/ui-toolkit'; import { t } from '@vegaprotocol/react-helpers'; interface SideSelectorProps { - value: OrderSide; - onSelect: (side: OrderSide) => void; + value: VegaWalletOrderSide; + onSelect: (side: VegaWalletOrderSide) => void; } export const SideSelector = ({ value, onSelect }: SideSelectorProps) => { - const toggles = Object.entries(OrderSide).map(([label, value]) => ({ - label, + const toggles = Object.entries(VegaWalletOrderSide).map(([label, value]) => ({ + label: label === 'Buy' ? 'Long' : 'Short', value, })); @@ -21,7 +21,7 @@ export const SideSelector = ({ value, onSelect }: SideSelectorProps) => { name="order-side" toggles={toggles} checkedValue={value} - onChange={(e) => onSelect(e.target.value as OrderSide)} + onChange={(e) => onSelect(e.target.value as VegaWalletOrderSide)} /> ); diff --git a/libs/deal-ticket/src/components/time-in-force-selector.tsx b/libs/deal-ticket/src/components/time-in-force-selector.tsx index e6d9c3282..6f7dd17b7 100644 --- a/libs/deal-ticket/src/components/time-in-force-selector.tsx +++ b/libs/deal-ticket/src/components/time-in-force-selector.tsx @@ -1,11 +1,14 @@ import { FormGroup, Select } from '@vegaprotocol/ui-toolkit'; -import { OrderTimeInForce, OrderType } from '@vegaprotocol/wallet'; +import { + VegaWalletOrderTimeInForce, + VegaWalletOrderType, +} from '@vegaprotocol/wallet'; import { t } from '@vegaprotocol/react-helpers'; interface TimeInForceSelectorProps { - value: OrderTimeInForce; - orderType: OrderType; - onSelect: (tif: OrderTimeInForce) => void; + value: VegaWalletOrderTimeInForce; + orderType: VegaWalletOrderType; + onSelect: (tif: VegaWalletOrderTimeInForce) => void; } export const TimeInForceSelector = ({ @@ -14,12 +17,12 @@ export const TimeInForceSelector = ({ onSelect, }: TimeInForceSelectorProps) => { const options = - orderType === OrderType.Limit - ? Object.entries(OrderTimeInForce) - : Object.entries(OrderTimeInForce).filter( + orderType === VegaWalletOrderType.Limit + ? Object.entries(VegaWalletOrderTimeInForce) + : Object.entries(VegaWalletOrderTimeInForce).filter( ([_, timeInForce]) => - timeInForce === OrderTimeInForce.FOK || - timeInForce === OrderTimeInForce.IOC + timeInForce === VegaWalletOrderTimeInForce.FOK || + timeInForce === VegaWalletOrderTimeInForce.IOC ); return ( @@ -27,7 +30,7 @@ export const TimeInForceSelector = ({