* 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:
parent
b96e6ee9ce
commit
2c3c685522
@ -1,6 +1,3 @@
|
||||
inputs:
|
||||
passphrase:
|
||||
description: 'Wallet password'
|
||||
outputs:
|
||||
token:
|
||||
description: 'api-token of wallet'
|
||||
|
12
.github/workflows/cypress-console-lite-e2e.yml
vendored
12
.github/workflows/cypress-console-lite-e2e.yml
vendored
@ -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 }}
|
||||
|
15
.github/workflows/cypress-explorer-e2e.yml
vendored
15
.github/workflows/cypress-explorer-e2e.yml
vendored
@ -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 }}
|
||||
|
15
.github/workflows/cypress-token-e2e.yml
vendored
15
.github/workflows/cypress-token-e2e.yml
vendored
@ -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 }}
|
||||
|
28
.github/workflows/cypress-trading-e2e.yml
vendored
28
.github/workflows/cypress-trading-e2e.yml
vendored
@ -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
|
||||
|
@ -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=
|
||||
|
11
apps/console-lite-e2e/.env.capsule
Normal file
11
apps/console-lite-e2e/.env.capsule
Normal 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=
|
11
apps/console-lite-e2e/.env.stagnet3
Normal file
11
apps/console-lite-e2e/.env.stagnet3
Normal 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=
|
@ -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,
|
||||
|
@ -18,3 +18,4 @@ NX_EXPLORER_PARTIES=1
|
||||
NX_EXPLORER_VALIDATORS=1
|
||||
|
||||
CYPRESS_VEGA_WALLET_API_TOKEN=
|
||||
CYPRESS_VEGA_URL=http://localhost:3028/query
|
||||
|
@ -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=
|
||||
|
@ -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=
|
||||
|
26
apps/trading-e2e/.env.capsule
Normal file
26
apps/trading-e2e/.env.capsule
Normal 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=
|
22
apps/trading-e2e/.env.stagnet3
Normal file
22
apps/trading-e2e/.env.stagnet3
Normal 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=
|
@ -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:
|
||||
|
152
apps/trading-e2e/src/integration/capsule.cy.ts
Normal file
152
apps/trading-e2e/src/integration/capsule.cy.ts
Normal 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
|
||||
);
|
||||
});
|
||||
}
|
@ -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();
|
||||
});
|
||||
|
||||
|
@ -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',
|
||||
|
@ -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`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -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`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -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();
|
||||
};
|
||||
|
@ -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');
|
||||
|
@ -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');
|
||||
|
26
apps/trading-e2e/src/support/create-order.ts
Normal file
26
apps/trading-e2e/src/support/create-order.ts
Normal 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();
|
||||
};
|
@ -2,5 +2,6 @@ import '@vegaprotocol/cypress';
|
||||
import 'cypress-real-events/support';
|
||||
import registerCypressGrep from '@cypress/grep';
|
||||
import { addMockTradingPage } from './trading';
|
||||
|
||||
registerCypressGrep();
|
||||
addMockTradingPage();
|
||||
|
@ -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
11
apps/trading/.env.capsule
Normal 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
|
@ -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',
|
||||
|
137
libs/cypress/src/lib/capsule/create-market.ts
Normal file
137
libs/cypress/src/lib/capsule/create-market.ts
Normal 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);
|
||||
}
|
191
libs/cypress/src/lib/capsule/ethereum-setup.ts
Normal file
191
libs/cypress/src/lib/capsule/ethereum-setup.ts
Normal 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}`;
|
23
libs/cypress/src/lib/capsule/faucet-asset.ts
Normal file
23
libs/cypress/src/lib/capsule/faucet-asset.ts
Normal 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;
|
||||
}
|
5
libs/cypress/src/lib/capsule/logging.ts
Normal file
5
libs/cypress/src/lib/capsule/logging.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export function createLog(name: string) {
|
||||
return (message: string) => {
|
||||
console.log(`[${name}]: ${message}`);
|
||||
};
|
||||
}
|
192
libs/cypress/src/lib/capsule/propose-market.ts
Normal file
192
libs/cypress/src/lib/capsule/propose-market.ts
Normal 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);
|
||||
});
|
||||
}
|
39
libs/cypress/src/lib/capsule/request.ts
Normal file
39
libs/cypress/src/lib/capsule/request.ts
Normal 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);
|
||||
}
|
33
libs/cypress/src/lib/capsule/vote.ts
Normal file
33
libs/cypress/src/lib/capsule/vote.ts
Normal 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,
|
||||
},
|
||||
};
|
||||
}
|
50
libs/cypress/src/lib/commands/create-market.ts
Normal file
50
libs/cypress/src/lib/commands/create-market.ts
Normal 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);
|
||||
});
|
||||
};
|
@ -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');
|
||||
});
|
||||
}
|
||||
|
||||
|
20
libs/cypress/src/lib/utils.ts
Normal file
20
libs/cypress/src/lib/utils.ts
Normal 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);
|
||||
}
|
@ -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')}
|
||||
|
@ -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
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user