feat(#2255): capsule tests for trading (#2498)

* feat: improve proposal types, add faucet for trading asset

* chore: yarn lock update

* fix: capsule tests to avoid jsx import

* chore: throw error so that ethereum setup failure is caught

* chore: org files and add logging

* chore: revert current trading-e2e .env file

* chore: add .env.capsule for trading tests on capsule

* chore: remove unused nx command

* chore: remove try catchs and allow errors to be caught by cypress

* chore: add slow tag for capsule test

* feat: move create market setup to libs/cypress

* chore: clearly separate vars meant for capsule with vars meant for non-capsule

* feat: remove hardcoded urls and use config obj

* chore: fix missing comma in genesis.tmpl

* chore: added limit order edit price test

* chore: remove encoding of transaction, update proposal tx trigger ratio to string

* chore: fix date and add date verification for update order

* chore: formatting fix

* chore: adjust trading app tests and workflows to be run in capsule in ci (#2574)

* chore: adjust trading app tests and workflows to be run in capsule in ci

* chore: fix token tests

* chore: increase timeout as it fails in ci

* chore: move market check to before function

* chore: add capsule logs to trading

* chore: increase proposal close time, also break up script for better debugging

* chore: bump up ethereum account setup timeout

* chore: suppress fetch logs to help with debugging

* chore: revert cy wraps now with suppressed logging

* chore: decrease tick amount

* chore: promise with timeout for better debugging

* chore: bump individual timeouts

* chore: bump timeout for tx wait promises

* chore: minor fix

* fix: leave Promise<any>

* fix: leave Promise<any>

* chore: fix home fail

Co-authored-by: Joe <joe@vega.xyz>
Co-authored-by: Dariusz Majcherczyk <dariusz.majcherczyk@gmail.com>
Co-authored-by: Radosław Szpiech <szpiechrados@gmail.com>
Co-authored-by: Madalina Raicu <madalina@raygroup.uk>
This commit is contained in:
Matthew Russell 2023-01-17 09:33:43 -06:00 committed by GitHub
parent b96e6ee9ce
commit 2c3c685522
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 1060 additions and 107 deletions

View File

@ -1,6 +1,3 @@
inputs:
passphrase:
description: 'Wallet password'
outputs:
token:
description: 'api-token of wallet'

View File

@ -42,17 +42,16 @@ jobs:
- name: Install root dependencies
run: yarn install --frozen-lockfile
working-directory: frontend-monorepo
######
## Setup a Vega wallet for our user
######
- name: Set up Vegawallet
- name: Run Vegacapsule network
uses: ./frontend-monorepo/.github/actions/run-vegacapsule
- name: Set up Vegawallet for capsule
id: setup-vega
uses: ./frontend-monorepo/.github/actions/setup-vegawallet
with:
recovery: ${{ secrets.TRADING_TEST_VEGA_WALLET_RECOVERY }}
passphrase: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
uses: ./frontend-monorepo/.github/actions/setup-vegawallet-docker
# To make sure that all Cypress binaries are installed properly
- name: Install cypress bins
@ -63,7 +62,6 @@ jobs:
run: npx nx run console-lite-e2e:e2e ${{ inputs.skip-cache }} --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome ${{ inputs.tags }}
working-directory: frontend-monorepo
env:
CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
CYPRESS_ETH_WALLET_MNEMONIC: ${{ secrets.CYPRESS_ETH_WALLET_MNEMONIC }}
CYPRESS_VEGA_WALLET_API_TOKEN: ${{ steps.setup-vega.outputs.token }}

View File

@ -51,22 +51,16 @@ jobs:
run: yarn install --frozen-lockfile
working-directory: frontend-monorepo
#######
## Build and run Vegacapsule network
#######
- name: Build and run Vegacapsule network
uses: ./frontend-monorepo/.github/actions/run-vegacapsule
######
## Setup a Vega wallet for our user
######
- name: Set up Vegawallet for docker
- name: Run Vegacapsule network
uses: ./frontend-monorepo/.github/actions/run-vegacapsule
- name: Set up Vegawallet for capsule
id: setup-vega
uses: ./frontend-monorepo/.github/actions/setup-vegawallet-docker
with:
passphrase: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
######
## Run some tests
@ -81,7 +75,6 @@ jobs:
run: npx nx run explorer-e2e:e2e ${{ inputs.skip-cache }} --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome ${{ inputs.tags }}
working-directory: frontend-monorepo
env:
CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
CYPRESS_ETH_WALLET_MNEMONIC: ${{ secrets.CYPRESS_ETH_WALLET_MNEMONIC }}
CYPRESS_NIGHTLY_RUN: ${{ inputs.night-run }}

View File

@ -47,22 +47,16 @@ jobs:
run: yarn install --frozen-lockfile
working-directory: frontend-monorepo
#######
## Build and run Vegacapsule network
#######
- name: Build and run Vegacapsule network
uses: ./frontend-monorepo/.github/actions/run-vegacapsule
######
## Setup a Vega wallet for our user
######
- name: Set up Vegawallet for docker
- name: Run Vegacapsule network
uses: ./frontend-monorepo/.github/actions/run-vegacapsule
- name: Set up Vegawallet for capsule
id: setup-vega
uses: ./frontend-monorepo/.github/actions/setup-vegawallet-docker
with:
passphrase: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
######
## Run some tests
@ -77,7 +71,6 @@ jobs:
run: npx nx run token-e2e:e2e ${{ inputs.skip-cache }} --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome ${{ inputs.tags }}
working-directory: frontend-monorepo
env:
CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
CYPRESS_ETH_WALLET_MNEMONIC: ${{ secrets.CYPRESS_ETH_WALLET_MNEMONIC }}
CYPRESS_VEGA_WALLET_API_TOKEN: ${{ steps.setup-vega.outputs.token }}

View File

@ -48,12 +48,12 @@ jobs:
## Setup a Vega wallet for our user
######
- name: Set up Vegawallet
- name: Run Vegacapsule network
uses: ./frontend-monorepo/.github/actions/run-vegacapsule
- name: Set up Vegawallet for capsule
id: setup-vega
uses: ./frontend-monorepo/.github/actions/setup-vegawallet
with:
recovery: ${{ secrets.TRADING_TEST_VEGA_WALLET_RECOVERY }}
passphrase: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
uses: ./frontend-monorepo/.github/actions/setup-vegawallet-docker
# To make sure that all Cypress binaries are installed properly
- name: Install cypress bins
@ -64,7 +64,23 @@ jobs:
run: npx nx run trading-e2e:e2e ${{ inputs.skip-cache }} --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome ${{ inputs.tags }}
working-directory: frontend-monorepo
env:
CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
CYPRESS_ETH_WALLET_MNEMONIC: ${{ secrets.CYPRESS_ETH_WALLET_MNEMONIC }}
CYPRESS_VEGA_WALLET_API_TOKEN: ${{ steps.setup-vega.outputs.token }}
######
## Upload logs
######
- name: Rename files to allow archive
if: ${{ always() }}
run: |
while read -r file; do
mv "${file}" "$(echo ${file} | sed 's|:|-|g')"
done< <(find /home/runner/.vegacapsule/testnet/logs -type f)
- uses: actions/upload-artifact@v2
if: ${{ always() }}
with:
name: logs
path: /home/runner/.vegacapsule/testnet/logs

View File

@ -1,10 +1,11 @@
# App configuration variables
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_ENV=STAGNET3
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHEREUM_PROVIDER_URL=http://localhost:8545
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_CONFIG_URL=''
NX_VEGA_ENV=CUSTOM
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
NX_VEGA_URL=http://localhost:3028/query
NX_VEGA_WALLET_URL=http://localhost:1789
CYPRESS_VEGA_ENV=STAGNET3
CYPRESS_VEGA_ENV=CUSTOM
CYPRESS_VEGA_URL=http://localhost:3028/query
CYPRESS_VEGA_WALLET_API_TOKEN=

View File

@ -0,0 +1,11 @@
NX_ETHEREUM_PROVIDER_URL=http://localhost:8545
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_CONFIG_URL=''
NX_VEGA_ENV=CUSTOM
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
NX_VEGA_URL=http://localhost:3028/query
NX_VEGA_WALLET_URL=http://localhost:1789
CYPRESS_VEGA_ENV=CUSTOM
CYPRESS_VEGA_URL=http://localhost:3028/query
CYPRESS_VEGA_WALLET_API_TOKEN=

View File

@ -0,0 +1,11 @@
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_ENV=STAGNET3
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_WALLET_URL=http://localhost:1789
CYPRESS_VEGA_ENV=STAGNET3
CYPRESS_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
CYPRESS_VEGA_WALLET_API_TOKEN=

View File

@ -1,7 +1,6 @@
const { defineConfig } = require('cypress');
module.exports = defineConfig({
projectId: 'et4snf',
e2e: {
setupNodeEvents(on, config) {
require('@cypress/grep/src/plugin')(config);
@ -23,21 +22,6 @@ module.exports = defineConfig({
viewportHeight: 900,
},
env: {
ETHEREUM_PROVIDER_URL:
'https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8',
VEGA_PUBLIC_KEY:
'47836c253520d2661bf5bed6339c0de08fd02cf5d4db0efee3b4373f20c7d278',
VEGA_PUBLIC_KEY2:
'1a18cdcaaa4f44a57b35a4e9b77e0701c17a476f2b407620f8c17371740cf2e4',
TRUNCATED_VEGA_PUBLIC_KEY: '47836c…c7d278',
TRUNCATED_VEGA_PUBLIC_KEY2: '1a18cd…0cf2e4',
ETHEREUM_WALLET_ADDRESS: '0x265Cc6d39a1B53d0d92068443009eE7410807158',
ETHERSCAN_URL: 'https://sepolia.etherscan.io',
tsConfig: 'tsconfig.json',
TAGS: 'not @todo and not @ignore and not @manual',
TRADING_TEST_VEGA_WALLET_PASSPHRASE: '123',
ETH_WALLET_MNEMONIC:
'ugly gallery notice network true range brave clarify flat logic someone chunk',
grepTags: '@regression @smoke @slow',
grepFilterSpecs: true,
grepOmitFiltered: true,

View File

@ -18,3 +18,4 @@ NX_EXPLORER_PARTIES=1
NX_EXPLORER_VALIDATORS=1
CYPRESS_VEGA_WALLET_API_TOKEN=
CYPRESS_VEGA_URL=http://localhost:3028/query

View File

@ -15,4 +15,5 @@ NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
#Test configuration variables
CYPRESS_FAIRGROUND=false
CYPRESS_VEGA_URL=http://localhost:3028/query
CYPRESS_VEGA_WALLET_API_TOKEN=

View File

@ -1,16 +1,26 @@
NX_VEGA_WALLET_URL=http://localhost:1789
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHEREUM_PROVIDER_URL=http://localhost:8545
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_ENV=STAGNET3
NX_VEGA_CONFIG_URL=''
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_ENV=CUSTOM
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_URL=http://localhost:3028/query
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
CYPRESS_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
# Expose some env vars to cypress environment for market setup
CYPRESS_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit supply green clown session
CYPRESS_ETHEREUM_PROVIDER_URL=http://localhost:8545
CYPRESS_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
CYPRESS_VEGA_ENV=STAGNET3
CYPRESS_FAUCET_URL=http://localhost:1790/api/v1/mint
CYPRESS_TRUNCATED_VEGA_PUBLIC_KEY=02ecea…342f65
CYPRESS_TRUNCATED_VEGA_PUBLIC_KEY2=7f9cf0…c25535
CYPRESS_VEGA_ENV=CUSTOM
CYPRESS_VEGA_PUBLIC_KEY=02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65
CYPRESS_VEGA_PUBLIC_KEY2=7f9cf07d3a9905b1a61a1069f7a758855da428bc0f4a97de87f48644bfc25535
CYPRESS_VEGA_TOKEN_URL=https://token.fairground.wtf
CYPRESS_VEGA_URL=http://localhost:3028/query
CYPRESS_VEGA_WALLET_URL=http://localhost:1789
CYPRESS_VEGA_WALLET_API_TOKEN=

View File

@ -0,0 +1,26 @@
NX_ETHEREUM_PROVIDER_URL=http://localhost:8545
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_VEGA_CONFIG_URL=''
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_ENV=CUSTOM
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_URL=http://localhost:3028/query
NX_VEGA_WALLET_URL=http://localhost:1789
# Expose some env vars to cypress environment for market setup
CYPRESS_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit supply green clown session
CYPRESS_ETHEREUM_PROVIDER_URL=http://localhost:8545
CYPRESS_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
CYPRESS_FAUCET_URL=http://localhost:1790/api/v1/mint
CYPRESS_TRUNCATED_VEGA_PUBLIC_KEY=02ecea…342f65
CYPRESS_TRUNCATED_VEGA_PUBLIC_KEY2=7f9cf0…c25535
CYPRESS_VEGA_ENV=CUSTOM
CYPRESS_VEGA_PUBLIC_KEY=02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65
CYPRESS_VEGA_PUBLIC_KEY2=7f9cf07d3a9905b1a61a1069f7a758855da428bc0f4a97de87f48644bfc25535
CYPRESS_VEGA_TOKEN_URL=https://token.fairground.wtf
CYPRESS_VEGA_URL=http://localhost:3028/query
CYPRESS_VEGA_WALLET_URL=http://localhost:1789
CYPRESS_VEGA_WALLET_API_TOKEN=

View File

@ -0,0 +1,22 @@
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_ENV=STAGNET3
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_TOKEN_URL=https://stagnet3.token.vega.xyz
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_WALLET_URL=http://localhost:1789
CYPRESS_ETH_WALLET_MNEMONIC=ugly gallery notice network true range brave clarify flat logic someone chunk
CYPRESS_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
CYPRESS_TRUNCATED_VEGA_PUBLIC_KEY=1a18cd…0cf2e4
CYPRESS_TRUNCATED_VEGA_PUBLIC_KEY2=47836c…c7d278
CYPRESS_VEGA_ENV=STAGNET3
CYPRESS_VEGA_PUBLIC_KEY=1a18cdcaaa4f44a57b35a4e9b77e0701c17a476f2b407620f8c17371740cf2e4
CYPRESS_VEGA_PUBLIC_KEY2=47836c253520d2661bf5bed6339c0de08fd02cf5d4db0efee3b4373f20c7d278
CYPRESS_VEGA_TOKEN_URL=https://stagnet3.token.vega.xyz
CYPRESS_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
CYPRESS_VEGA_WALLET_API_TOKEN=

View File

@ -24,20 +24,17 @@ module.exports = defineConfig({
requestTimeout: 20000,
},
env: {
ETHEREUM_PROVIDER_URL:
'https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8',
VEGA_PUBLIC_KEY:
'47836c253520d2661bf5bed6339c0de08fd02cf5d4db0efee3b4373f20c7d278',
VEGA_PUBLIC_KEY2:
'1a18cdcaaa4f44a57b35a4e9b77e0701c17a476f2b407620f8c17371740cf2e4',
TRUNCATED_VEGA_PUBLIC_KEY: '47836c…c7d278',
TRUNCATED_VEGA_PUBLIC_KEY2: '1a18cd…0cf2e4',
ETHEREUM_PROVIDER_URL:
'https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8',
ETHEREUM_WALLET_ADDRESS: '0x265Cc6d39a1B53d0d92068443009eE7410807158',
ETHERSCAN_URL: 'https://sepolia.etherscan.io',
ETHEREUM_CHAIN_ID: 11155111,
tsConfig: 'tsconfig.json',
TAGS: 'not @todo and not @ignore and not @manual',
TRADING_TEST_VEGA_WALLET_PASSPHRASE: '123',
ETH_WALLET_MNEMONIC:
'ugly gallery notice network true range brave clarify flat logic someone chunk',
TRADING_MODE_LINK:

View File

@ -0,0 +1,152 @@
import { removeDecimal } from '@vegaprotocol/cypress';
import * as Schema from '@vegaprotocol/types';
import {
OrderStatusMapping,
OrderTimeInForceMapping,
OrderTypeMapping,
Side,
} from '@vegaprotocol/types';
import { isBefore, isAfter, addSeconds, subSeconds } from 'date-fns';
import { createOrder } from '../support/create-order';
const orderSize = 'size';
const orderType = 'type';
const orderStatus = 'status';
const orderRemaining = 'remaining';
const orderPrice = 'price';
const orderTimeInForce = 'timeInForce';
const orderCreatedAt = 'createdAt';
const orderUpdatedAt = 'updatedAt';
// TODO: ensure this test runs only if capsule is running via workflow
describe('capsule', { tags: '@slow' }, () => {
before(() => {
cy.createMarket();
cy.get('@markets').then((markets) => {
cy.wrap(markets[0]).as('market');
});
});
beforeEach(() => {
cy.setVegaWallet();
});
it('can place and receive an order', function () {
const market = this.market;
cy.visit(`/#/markets/${market.id}`);
const order = {
marketId: market.id,
type: Schema.OrderType.TYPE_LIMIT,
side: Schema.Side.SIDE_BUY,
size: '0.0005',
price: '390',
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
};
const rawPrice = removeDecimal(order.price, market.decimalPlaces);
const rawSize = removeDecimal(order.size, market.positionDecimalPlaces);
createOrder(order);
cy.getByTestId('dialog-title').should(
'contain.text',
'Awaiting network confirmation'
);
cy.getByTestId('dialog-title').should('contain.text', 'Order submitted');
cy.getByTestId('dialog-close').click();
// orderbook cells are keyed by price level
cy.getByTestId('tab-orderbook')
.get(`[data-testid="price-${rawPrice}"]`)
.should('contain.text', order.price)
.get(`[data-testid="bid-vol-${rawPrice}"]`)
.should('contain.text', rawSize);
cy.getByTestId('Orders').click();
cy.getByTestId('tab-orders').within(() => {
cy.get('.ag-center-cols-container')
.children()
.first()
.within(() => {
cy.get(`[col-id='${orderSize}']`).should(
'contain.text',
order.side === Side.SIDE_BUY ? '+' : '-' + order.size
);
cy.get(`[col-id='${orderType}']`).should(
'contain.text',
OrderTypeMapping[order.type]
);
cy.get(`[col-id='${orderStatus}']`).should(
'contain.text',
OrderStatusMapping.STATUS_ACTIVE
);
cy.get(`[col-id='${orderRemaining}']`).should(
'contain.text',
`0.00/${order.size}`
);
cy.get(`[col-id='${orderPrice}']`).then(($price) => {
expect(parseFloat($price.text())).to.equal(parseFloat(order.price));
});
cy.get(`[col-id='${orderTimeInForce}']`).should(
'contain.text',
OrderTimeInForceMapping[order.timeInForce]
);
checkIfDataAndTimeOfCreationAndUpdateIsEqual(orderCreatedAt);
});
});
cy.getByTestId('edit').first().click();
cy.getByTestId('dialog-title').should('contain.text', 'Edit order');
cy.get('#limitPrice').focus().clear().type('200');
cy.getByTestId('edit-order').find('[type="submit"]').click();
cy.getByTestId('dialog-title').should('contain.text', 'Order updated');
cy.getByTestId('dialog-close').click();
cy.get('.ag-center-cols-container')
.children()
.first()
.within(() => {
cy.get(`[col-id='${orderPrice}']`).then(($price) => {
expect(parseFloat($price.text())).to.equal(parseFloat('200'));
});
checkIfDataAndTimeOfCreationAndUpdateIsEqual(orderUpdatedAt);
});
cy.getByTestId('cancel').first().click();
cy.getByTestId('dialog-title').should(
'contain.text',
'Awaiting network confirmation'
);
cy.getByTestId('dialog-title').should('contain.text', 'Order cancelled');
cy.getByTestId('dialog-close').click();
cy.getByTestId('tab-orders')
.get('.ag-center-cols-container')
.children()
.first()
.get(`[col-id='${orderStatus}']`)
.should('contain.text', OrderStatusMapping.STATUS_CANCELLED);
});
});
function checkIfDataAndTimeOfCreationAndUpdateIsEqual(date: string) {
cy.get(`[col-id='${date}']`)
.children('span')
.invoke('data', 'value')
.then(($dateTime) => {
// allow a date 5 seconds either side to allow for
// unexpected latency
const minBefore = subSeconds(new Date(), 5);
const maxAfter = addSeconds(new Date(), 5);
console.log(maxAfter);
const date = new Date($dateTime.toString());
expect(isAfter(date, minBefore) && isBefore(date, maxAfter)).to.equal(
true
);
});
}

View File

@ -96,11 +96,11 @@ describe('ethereum wallet', { tags: '@smoke' }, () => {
beforeEach(() => {
cy.mockWeb3Provider();
// Using portfolio withdrawals tab is it requires Ethereum wallet connection
cy.visit('/#/portfolio');
cy.mockTradingPage();
cy.mockSubscription();
cy.setVegaWallet();
cy.visit('/#/portfolio');
cy.get('main[data-testid="/portfolio"]').should('exist');
cy.connectVegaWallet();
cy.getByTestId('Withdrawals').click();
});

View File

@ -136,7 +136,7 @@ describe('home', { tags: '@regression' }, () => {
});
describe('no markets found', () => {
it('redirects to a the empty market page and displays welcome notice', () => {
beforeEach(() => {
cy.mockGQL((req) => {
const data = {
marketsConnection: {
@ -159,6 +159,8 @@ describe('home', { tags: '@regression' }, () => {
cy.visit('/');
cy.wait('@Markets');
cy.wait('@MarketsData');
});
it('redirects to a the empty market page and displays welcome notice', () => {
cy.url().should('eq', Cypress.config().baseUrl + `/#/markets`);
cy.getByTestId('welcome-notice-title').should(
'contain.text',

View File

@ -49,7 +49,7 @@ describe('Market proposal notification', { tags: '@smoke' }, () => {
cy.getByTestId('external-link').should(
'have.attr',
'href',
'https://stagnet3.token.vega.xyz/proposals/123'
`${Cypress.env('VEGA_TOKEN_URL')}/proposals/123`
);
});
});

View File

@ -108,7 +108,7 @@ describe('markets table', { tags: '@smoke' }, () => {
.and(
'have.attr',
'href',
'https://stagnet3.token.vega.xyz/proposals/propose/new-market'
`${Cypress.env('VEGA_TOKEN_URL')}/proposals/propose/new-market`
);
});
});

View File

@ -3,6 +3,7 @@ import { aliasGQLQuery, mockConnectWallet } from '@vegaprotocol/cypress';
import { testOrderSubmission } from '../support/order-validation';
import type { OrderSubmission } from '@vegaprotocol/wallet';
import { accountsQuery, estimateOrderQuery } from '@vegaprotocol/mock';
import { createOrder } from '../support/create-order';
const orderSizeField = 'order-size';
const orderPriceField = 'order-price';
@ -717,22 +718,3 @@ describe('account validation', { tags: '@regression' }, () => {
});
});
});
const createOrder = (order: OrderSubmission): void => {
const { type, side, size, price, timeInForce, expiresAt } = order;
cy.getByTestId(`order-type-${type}`).click();
cy.getByTestId(`order-side-${side}`).click();
cy.getByTestId(orderSizeField).clear().type(size);
if (price) {
cy.getByTestId(orderPriceField).clear().type(price);
}
cy.getByTestId(orderTIFDropDown).select(timeInForce);
if (timeInForce === 'TIME_IN_FORCE_GTT') {
if (!expiresAt) {
throw new Error('Specify expiresAt if using GTT');
}
cy.getByTestId('date-picker-field').type(expiresAt);
}
cy.getByTestId(placeOrderBtn).click();
};

View File

@ -35,6 +35,7 @@ describe('orders list', { tags: '@smoke' }, () => {
});
cy.wait('@Markets');
});
it('renders orders', () => {
cy.getByTestId('tab-orders').should('be.visible');
cy.getByTestId(cancelAllOrdersBtn).should('be.visible');

View File

@ -66,6 +66,9 @@ describe('withdraw form validation', { tags: '@smoke' }, () => {
});
describe('withdraw actions', { tags: '@regression' }, () => {
// this is extremely ugly hack, but setting it properly in contract is too much effort for such simple validation
const withdrawalThreshold =
Cypress.env('VEGA_ENV') === 'CUSTOM' ? '0.00' : '100.00';
before(() => {
cy.mockWeb3Provider();
cy.mockTradingPage();
@ -96,7 +99,7 @@ describe('withdraw actions', { tags: '@regression' }, () => {
);
cy.getByTestId('WITHDRAWAL_THRESHOLD_value').should(
'contain.text',
'100.00'
withdrawalThreshold
);
cy.getByTestId('DELAY_TIME_label').should('contain.text', 'Delay time');
cy.getByTestId('DELAY_TIME_value').should('have.text', 'None');

View File

@ -0,0 +1,26 @@
import type { OrderSubmission } from '@vegaprotocol/wallet';
const orderSizeField = 'order-size';
const orderPriceField = 'order-price';
const orderTIFDropDown = 'order-tif';
const placeOrderBtn = 'place-order';
export const createOrder = (order: OrderSubmission): void => {
cy.log('Placing order', order);
const { type, side, size, price, timeInForce, expiresAt } = order;
cy.getByTestId(`order-type-${type}`).click();
cy.getByTestId(`order-side-${side}`).click();
cy.getByTestId(orderSizeField).clear().type(size);
if (price) {
cy.getByTestId(orderPriceField).clear().type(price);
}
cy.getByTestId(orderTIFDropDown).select(timeInForce);
if (timeInForce === 'TIME_IN_FORCE_GTT') {
if (!expiresAt) {
throw new Error('Specify expiresAt if using GTT');
}
cy.getByTestId('date-picker-field').type(expiresAt);
}
cy.getByTestId(placeOrderBtn).click();
};

View File

@ -2,5 +2,6 @@ import '@vegaprotocol/cypress';
import 'cypress-real-events/support';
import registerCypressGrep from '@cypress/grep';
import { addMockTradingPage } from './trading';
registerCypressGrep();
addMockTradingPage();

View File

@ -61,7 +61,7 @@ const vegaWalletTransaction = (transaction: Transaction) => {
.should('deep.equal', {
token: JSON.parse(localStorage.getItem('vega_wallet_config') || '{}')
?.token,
publicKey: Cypress.env('VEGA_PUBLIC_KEY2'),
publicKey: Cypress.env('VEGA_PUBLIC_KEY'),
sendingMode: 'TYPE_SYNC',
transaction,
});

11
apps/trading/.env.capsule Normal file
View File

@ -0,0 +1,11 @@
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_VEGA_CONFIG_URL=''
NX_VEGA_ENV=CUSTOM
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_URL=http://localhost:3028/query
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet

View File

@ -15,6 +15,7 @@ import {
addSetVegaWallet,
} from './lib/commands/vega-wallet-connect';
import { addMockTransactionResponse } from './lib/commands/mock-transaction-response';
import { addCreateMarket } from './lib/commands/create-market';
addGetTestIdcommand();
addSlackCommand();
@ -31,11 +32,13 @@ addUpdateCapsuleMultiSig();
addVegaWalletConnect();
addSetVegaWallet();
addMockTransactionResponse();
addCreateMarket();
export { mockConnectWallet } from './lib/commands/vega-wallet-connect';
export type { onMessage } from './lib/mock-ws';
export { aliasGQLQuery } from './lib/mock-gql';
export { aliasWalletQuery } from './lib/mock-rest';
export * from './lib/utils';
Cypress.on(
'uncaught:exception',

View File

@ -0,0 +1,137 @@
import * as Schema from '@vegaprotocol/types';
import { gql } from 'graphql-request';
import { determineId } from '../utils';
import { requestGQL, setEndpoints } from './request';
import { vote } from './vote';
import { setupEthereumAccount } from './ethereum-setup';
import { faucetAsset } from './faucet-asset';
import {
proposeMarket,
waitForEnactment,
waitForProposal,
} from './propose-market';
import { createLog } from './logging';
const log = createLog('create-market');
export async function createMarket(cfg: {
vegaPubKey: string;
token: string;
ethWalletMnemonic: string;
ethereumProviderUrl: string;
vegaWalletUrl: string;
vegaUrl: string;
faucetUrl: string;
}) {
// set and store request endpoints
setEndpoints(cfg.vegaWalletUrl, cfg.vegaUrl);
const markets = await getMarkets();
if (markets.length) {
log(
`${markets.length} market${
markets.length > 1 ? 's' : ''
} found, skipping market creation`
);
return markets;
}
await setupEthereumAccount(
cfg.vegaPubKey,
cfg.ethWalletMnemonic,
cfg.ethereumProviderUrl
);
const result = await faucetAsset(cfg.faucetUrl, 'fUSDC', cfg.vegaPubKey);
if (!result.success) {
throw new Error('faucet failed');
}
// propose and vote on a market
const proposalTxResult = await proposeMarket(cfg.vegaPubKey, cfg.token);
const proposalId = determineId(proposalTxResult.transaction.signature.value);
log(`proposal created (id: ${proposalId})`);
const proposal = await waitForProposal(proposalId);
await vote(
proposal.id,
Schema.VoteValue.VALUE_YES,
cfg.vegaPubKey,
cfg.token
);
await waitForEnactment();
// fetch and return created market
const newMarkets = await getMarkets();
return newMarkets;
}
async function getMarkets() {
const query = gql`
{
marketsConnection {
edges {
node {
id
decimalPlaces
positionDecimalPlaces
state
tradableInstrument {
instrument {
id
name
code
metadata {
tags
}
product {
... on Future {
settlementAsset {
id
symbol
decimals
}
quoteName
}
}
}
}
}
}
}
}
`;
const res = await requestGQL<{
marketsConnection: {
edges: Array<{
node: {
id: string;
decimalPlaces: number;
positionDecimalPlaces: number;
state: string;
tradableInstrument: {
instrument: {
id: string;
name: string;
code: string;
metadata: {
tags: string[];
};
product: {
settlementAssset: {
id: string;
symbol: string;
decimals: number;
};
quoteName: string;
};
};
};
};
}>;
};
}>(query);
return res.marketsConnection.edges.map((e) => e.node);
}

View File

@ -0,0 +1,191 @@
import { ethers, Wallet } from 'ethers';
import { StakingBridge, Token } from '@vegaprotocol/smart-contracts';
import { gql } from 'graphql-request';
import { requestGQL } from './request';
import { createLog } from './logging';
const log = createLog('ethereum-setup');
export async function setupEthereumAccount(
vegaPublicKey: string,
ethWalletMnemonic: string,
ethereumProviderUrl: string
) {
// create provider/wallet
const provider = new ethers.providers.JsonRpcProvider({
url: ethereumProviderUrl,
});
const privateKey = Wallet.fromMnemonic(
ethWalletMnemonic,
getAccount()
).privateKey;
// this wallet (ozone access etc) is already set up with 6 million vega (eth)
const wallet = new Wallet(privateKey, provider);
const vegaAsset = await getVegaAsset();
if (!vegaAsset) {
throw new Error('could not fetch asset');
}
const ethereumConfig = await getEthereumConfig();
if (!ethereumConfig) {
throw new Error('could not not fetch ethereum config');
}
const tokenContract = new Token(vegaAsset.source.contractAddress, wallet);
log('sending approve tx');
const approveTx = await promiseWithTimeout(
tokenContract.approve(
ethereumConfig.staking_bridge_contract.address,
'100000' + '0'.repeat(18)
),
1000,
'tokenContract.approve'
);
await promiseWithTimeout(
approveTx.wait(1),
10 * 60 * 1000,
'approveTx.wait(1)'
);
log('sending approve tx: success');
const stakingContract = new StakingBridge(
ethereumConfig.staking_bridge_contract.address,
wallet
);
const amount = '10000' + '0'.repeat(18);
log(`sending stake tx of ${amount} to ${vegaPublicKey}`);
const stakeTx = await promiseWithTimeout(
stakingContract.stake(amount, vegaPublicKey),
14000,
'stakingContract.stake(amount, vegaPublicKey)'
);
await promiseWithTimeout(stakeTx.wait(3), 10 * 60 * 1000, 'stakeTx.wait(3)');
await waitForStake(vegaPublicKey);
log(`sending stake tx: success`);
}
function timeout(time = 0, id: string) {
return new Promise((resolve, reject) => {
setTimeout(() => reject(new Error(`${id}: timeout triggered`)), time);
});
}
async function promiseWithTimeout(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
promise: Promise<any>,
time: number,
id: string
) {
return await Promise.race([promise, timeout(time, id)]);
}
async function getVegaAsset() {
const query = gql`
{
assetsConnection {
edges {
node {
id
symbol
source {
... on ERC20 {
contractAddress
}
}
}
}
}
}
`;
const res = await requestGQL<{
assetsConnection: {
edges: Array<{
node: {
id: string;
symbol: string;
source: {
contractAddress: string;
};
};
}>;
};
}>(query);
return res.assetsConnection.edges
.map((e) => e.node)
.find((a) => a.symbol === 'VEGA');
}
async function getEthereumConfig() {
const query = gql`
{
networkParameter(key: "blockchains.ethereumConfig") {
value
}
}
`;
const res = await requestGQL<{
networkParameter: {
key: string;
value: string;
};
}>(query);
return JSON.parse(res.networkParameter.value);
}
function waitForStake(vegaPublicKey: string) {
const query = gql`
{
party(id:"${vegaPublicKey}") {
stakingSummary {
currentStakeAvailable
}
}
}
`;
return new Promise((resolve, reject) => {
let tick = 1;
const interval = setInterval(async () => {
log(`confirming stake (attempt: ${tick})`);
if (tick >= 10) {
clearInterval(interval);
reject(new Error('stake link never seen'));
}
try {
const res = await requestGQL<{
party: {
stakingSummary: {
currentStakeAvailable: string;
};
};
}>(query);
if (
res.party?.stakingSummary?.currentStakeAvailable !== null &&
parseInt(res.party.stakingSummary.currentStakeAvailable) > 0
) {
log(
`stake confirmed (amount: ${res.party.stakingSummary.currentStakeAvailable})`
);
clearInterval(interval);
resolve(res.party.stakingSummary.currentStakeAvailable);
}
} catch (err) {
// no op, query will error until party is created
}
tick++;
}, 1000);
});
}
// derivation path
const getAccount = (number = 0) => `m/44'/60'/0'/0/${number}`;

View File

@ -0,0 +1,23 @@
import { createLog } from './logging';
const log = createLog('faucet-asset');
export async function faucetAsset(
url: string,
asset: string,
party: string,
amount = '10000'
) {
log(`sending ${amount} ${asset} to ${party}`);
const res = await fetch(url, {
method: 'post',
body: JSON.stringify({
amount,
asset,
party,
}),
});
const json = await res.json();
return json;
}

View File

@ -0,0 +1,5 @@
export function createLog(name: string) {
return (message: string) => {
console.log(`[${name}]: ${message}`);
};
}

View File

@ -0,0 +1,192 @@
import * as Schema from '@vegaprotocol/types';
import { addSeconds, millisecondsToSeconds } from 'date-fns';
import { gql } from 'graphql-request';
import { request, requestGQL } from './request';
import { createLog } from './logging';
import type { ProposalSubmissionBody } from '@vegaprotocol/wallet';
const log = createLog('propose-market');
const MIN_CLOSE_SEC = 5;
const MIN_ENACT_SEC = 3;
export async function proposeMarket(publicKey: string, token: string) {
log('sending proposal tx');
const proposalTx = createNewMarketProposal();
const result = await request('client.send_transaction', {
token,
publicKey,
sendingMode: 'TYPE_SYNC',
transaction: proposalTx,
});
return result.result;
}
function createNewMarketProposal(): ProposalSubmissionBody {
const closingDate = addSeconds(new Date(), MIN_CLOSE_SEC);
const enactmentDate = addSeconds(closingDate, MIN_ENACT_SEC);
const closingTimestamp = millisecondsToSeconds(closingDate.getTime());
const enactmentTimestamp = millisecondsToSeconds(enactmentDate.getTime());
return {
proposalSubmission: {
rationale: {
title: 'Add Lorem Ipsum market',
description: 'An example proposal to add Lorem Ipsum market',
},
terms: {
newMarket: {
changes: {
decimalPlaces: '5',
positionDecimalPlaces: '5',
lpPriceRange: '10',
instrument: {
name: 'Test market 1',
code: 'TEST.24h',
future: {
settlementAsset: 'fUSDC',
quoteName: 'fUSDC',
dataSourceSpecForSettlementData: {
external: {
oracle: {
signers: [
{
pubKey: {
key: '0xfCEAdAFab14d46e20144F48824d0C09B1a03F2BC',
},
},
],
filters: [
{
key: {
name: 'prices.ETH.value',
type: 'TYPE_INTEGER' as const,
numberDecimalPlaces: '0',
},
conditions: [
{
operator: 'OPERATOR_GREATER_THAN' as const,
value: '0',
},
],
},
],
},
},
},
dataSourceSpecForTradingTermination: {
external: {
oracle: {
signers: [
{
pubKey: {
key: '70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680',
},
},
],
filters: [
{
key: {
name: 'trading.terminated.ETH5',
type: 'TYPE_BOOLEAN' as const,
},
conditions: [
{
operator: 'OPERATOR_EQUALS' as const,
value: 'true',
},
],
},
],
},
},
},
dataSourceSpecBinding: {
settlementDataProperty: 'prices.ETH.value',
tradingTerminationProperty: 'trading.terminated.ETH5',
},
},
},
metadata: ['sector:energy', 'sector:tech', 'source:docs.vega.xyz'],
priceMonitoringParameters: {
triggers: [
{
horizon: '43200',
probability: '0.9999999',
auctionExtension: '600',
},
],
},
liquidityMonitoringParameters: {
targetStakeParameters: {
timeWindow: '3600',
scalingFactor: 10,
},
triggeringRatio: '0.7',
auctionExtension: '1',
},
logNormal: {
tau: 0.0001140771161,
riskAversionParameter: 0.01,
params: {
mu: 0,
r: 0.016,
sigma: 0.5,
},
},
},
},
closingTimestamp,
enactmentTimestamp,
},
},
};
}
export function waitForProposal(id: string): Promise<{ id: string }> {
const query = gql`
{
proposal(id: "${id}") {
id
state
}
}
`;
return new Promise((resolve, reject) => {
let tick = 0;
const interval = setInterval(async () => {
if (tick >= 60) {
clearInterval(interval);
reject(new Error('proposal never seen'));
}
try {
const res = await requestGQL<{
proposal: {
id: string;
state: string;
};
}>(query);
if (
res.proposal !== null &&
res.proposal.state === Schema.ProposalState.STATE_OPEN
) {
clearInterval(interval);
resolve(res.proposal);
}
} catch (err) {
console.log(err);
}
tick++;
}, 1000);
});
}
export function waitForEnactment() {
const timeout = MIN_CLOSE_SEC * 1000 + MIN_ENACT_SEC * 1000;
return new Promise((resolve) => {
setTimeout(resolve, timeout + 2000);
});
}

View File

@ -0,0 +1,39 @@
import { request as gqlRequest } from 'graphql-request';
let walletEndpoint = '';
let gqlEndpoint = '';
export function setEndpoints(walletUrl: string, gqlUrl: string) {
walletEndpoint = walletUrl + '/api/v2/requests';
gqlEndpoint = gqlUrl;
}
export function request(method: string, params: object) {
if (!walletEndpoint) {
throw new Error('gqlEndpoint not set');
}
const body = {
jsonrpc: '2.0',
method,
params,
id: Math.random().toString(),
};
return fetch(walletEndpoint, {
method: 'post',
body: JSON.stringify(body),
headers: {
'Content-Type': 'application/json',
Origin: 'market-setup',
Referer: 'market-setup',
},
}).then((res) => {
return res.json();
});
}
export function requestGQL<T>(query: string): Promise<T> {
if (!gqlEndpoint) {
throw new Error('gqlEndpoint not set');
}
return gqlRequest(gqlEndpoint, query);
}

View File

@ -0,0 +1,33 @@
import type * as Schema from '@vegaprotocol/types';
import { request } from './request';
import { createLog } from './logging';
const log = createLog('vote');
export async function vote(
proposalId: string,
voteValue: Schema.VoteValue,
publicKey: string,
token: string
) {
log(`voting ${voteValue} on ${proposalId}`);
const voteTx = createVote(proposalId, voteValue);
const voteResult = await request('client.send_transaction', {
token,
publicKey,
sendingMode: 'TYPE_SYNC',
transaction: voteTx,
});
return voteResult.result;
}
function createVote(proposalId: string, value: Schema.VoteValue) {
return {
voteSubmission: {
value,
proposalId,
},
};
}

View File

@ -0,0 +1,50 @@
import { createMarket } from '../capsule/create-market';
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace Cypress {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface Chainable<Subject> {
createMarket(): void;
}
}
}
// suppress fetch and xhr logs
const originalLog = Cypress.log;
// @ts-ignore fuck with log to help with debug
Cypress.log = function (options, ...rest) {
// @ts-ignore fuck with log to help with debug
const isRequest = ['fetch', 'xhr'].includes(options.displayName);
if (isRequest) {
return;
}
return originalLog(options, ...rest);
};
export const addCreateMarket = () => {
Cypress.Commands.add('createMarket', () => {
const config = {
vegaPubKey: Cypress.env('VEGA_PUBLIC_KEY'),
token: Cypress.env('VEGA_WALLET_API_TOKEN'),
ethWalletMnemonic: Cypress.env('ETH_WALLET_MNEMONIC'),
ethereumProviderUrl: Cypress.env('ETHEREUM_PROVIDER_URL'),
vegaWalletUrl: Cypress.env('VEGA_WALLET_URL'),
vegaUrl: Cypress.env('VEGA_URL'),
faucetUrl: Cypress.env('FAUCET_URL'),
};
cy.highlight('creating market on capsule environment');
cy.wrap(createMarket(config), {
timeout: 5 * 60 * 1000,
})
// register market list result so it can be retrieved in tests later
.as('markets');
// make sure we have a market to test against, createMarket will
// return an array of markets or false if setup failed
cy.get('@markets').should('not.equal', false);
});
};

View File

@ -21,7 +21,7 @@ const hasOperationName = (
export function addMockGQLCommand() {
Cypress.Commands.add('mockGQL', (handler: RouteHandler) => {
cy.intercept('POST', '**/graphql', handler).as('GQL');
cy.intercept('POST', Cypress.env('VEGA_URL'), handler).as('GQL');
});
}

View File

@ -0,0 +1,20 @@
import { ethers } from 'ethers';
import sha3 from 'js-sha3';
import BigNumber from 'bignumber.js';
/**
* copy of determineId in libs/wallet/src/utils.ts
* to avoid pulling in any jsx files which will cypress is not set up to compile
*/
export function determineId(sig: string) {
return sha3.sha3_256(ethers.utils.arrayify('0x' + sig));
}
/**
* copy of removeDecimal from libs/react-helpers/src/lib/format/number.tsx
* to avoid pulling in any jsx files which will cypress is not set up to compile
*/
export function removeDecimal(value: string, decimals: number): string {
if (!decimals) return value;
return new BigNumber(value || 0).times(Math.pow(10, decimals)).toFixed(0);
}

View File

@ -47,6 +47,16 @@ export const MarketListTable = forwardRef<
<AgGridColumn
headerName={t('Market')}
field="tradableInstrument.instrument.code"
cellRenderer={({
value,
data,
}: VegaICellRendererParams<
MarketWithData,
'tradableInstrument.instrument.code'
>) => {
if (!data) return null;
return <span data-testid={`market-${data.id}`}>{value}</span>;
}}
/>
<AgGridColumn
headerName={t('Description')}

View File

@ -209,20 +209,29 @@ export const OrderListTable = forwardRef<AgGridReact, OrderListTableProps>(
/>
<AgGridColumn
field="createdAt"
valueFormatter={({
cellRenderer={({
data,
value,
}: VegaValueFormatterParams<Order, 'createdAt'>) => {
return value ? getDateTimeFormat().format(new Date(value)) : value;
}: VegaICellRendererParams<Order, 'createdAt'>) => {
return (
<span data-value={value}>
{value ? getDateTimeFormat().format(new Date(value)) : value}
</span>
);
}}
/>
<AgGridColumn
field="updatedAt"
filter={DateRangeFilter}
valueFormatter={({
cellRenderer={({
data,
value,
node,
}: VegaValueFormatterParams<Order, 'updatedAt'>) => {
return value ? getDateTimeFormat().format(new Date(value)) : '-';
}: VegaICellRendererParams<Order, 'updatedAt'>) => {
return (
<span data-value={value}>
{value ? getDateTimeFormat().format(new Date(value)) : '-'}
</span>
);
}}
/>
<AgGridColumn

View File

@ -56,6 +56,7 @@
"env-cmd": "^10.1.0",
"ethers": "^5.6.0",
"graphql": "^15.7.2",
"graphql-request": "^5.0.0",
"graphql-ws": "^5.6.3",
"i18next": "^20.3.5",
"i18next-browser-languagedetector": "^6.1.2",

View File

@ -181,6 +181,7 @@
"governance.proposal.market.minClose": "2s",
"governance.proposal.market.minEnact": "2s",
"governance.proposal.market.requiredParticipation": "0.00000000000000000000000015",
"governance.proposal.market.requiredMajority": "0.00000000000000000000000015",
"governance.proposal.updateMarket.minClose": "2s",
"governance.proposal.updateMarket.minEnact": "2s",
"governance.proposal.updateMarket.requiredParticipation": "0.00000000000000000000000015",