Compare commits

..
Author SHA1 Message Date
Madalina Raicu 970193fde9 chore: remove liquidation price (est) for now 2022-11-17 06:48:14 -05:00
Madalina Raicu 38439b2562 fix: add other dp to summary row data 2022-11-17 06:28:27 -05:00
Madalina Raicu 1bd8c65031 fix: fix positions unit tests 2022-11-17 05:41:21 -05:00
Madalina Raicu 805467d6fa fix: normalize values 2022-11-17 05:31:56 -05:00
Madalina Raicu de61f89fb9 fix: update decimals on position notional size 2022-11-17 05:10:56 -05:00
Madalina Raicu 1436e97434 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2022-11-16 16:48:09 -05:00
Madalina Raicu 3d793128e7 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2022-11-16 10:54:05 -05:00
Madalina Raicu 4fa3aac079 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2022-11-15 05:41:37 -05:00
Madalina Raicu 41ca079814 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2022-11-13 20:04:39 -05:00
Madalina Raicu 38c76f24a3 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2022-11-11 16:35:08 +00:00
Madalina Raicu ab1308316f Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2022-11-11 10:44:16 +00:00
Madalina Raicu 3f3c0e18ab Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2022-11-08 16:14:53 +00:00
Madalina Raicu 29e7a9de03 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2022-11-08 10:11:34 +00:00
Madalina Raicu 8b4d8895fc Merge branches 'develop' and 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2022-11-07 10:28:44 +00:00
Madalina Raicu 36b2f9a5a9 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2022-11-06 12:56:19 +00:00
Madalina Raicu 962f5041ec Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2022-11-04 11:56:17 +00:00
Madalina Raicu 2c881cf35e Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2022-11-02 16:25:45 +00:00
Madalina Raicu 94c6bdf234 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2022-11-01 11:26:55 +00:00
Madalina Raicu 0855d3bae6 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2022-10-28 11:03:07 +01:00
Madalina Raicu 2fcee815e5 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2022-10-27 15:01:57 +01:00
Madalina Raicu 3aab601180 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2022-10-26 15:35:12 +01:00
Madalina Raicu 8561c1d0bc Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2022-10-26 10:34:30 +01:00
Madalina Raicu e0f5f43777 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2022-10-25 08:00:09 +01:00
Madalina Raicu 81ff3ceff0 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2022-10-23 00:38:55 +01:00
Madalina Raicu 5f9287a220 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2022-10-21 16:20:36 +01:00
Madalina Raicu 76827b239a Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2022-10-18 13:25:22 +01:00
Madalina Raicu 464b964cba Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2022-10-12 15:42:39 +01:00
Madalina Raicu 2c0287be32 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2022-10-10 09:28:15 +01:00
Madalina Raicu 0f60018ab4 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2022-10-07 16:36:10 +01:00
Madalina Raicu 934d75643f Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2022-10-05 21:24:40 +01:00
Madalina Raicu 1eb8565739 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop 2022-10-05 17:36:48 +01:00
1289 changed files with 33848 additions and 52285 deletions
@@ -0,0 +1,28 @@
inputs:
all:
description: 'Install all binaries'
default: false
version:
description: 'Vega version'
gobin:
description: 'GOBIN path'
default: '/home/runner/go/bin'
runs:
using: 'composite'
steps:
- name: Install Vega binaries
shell: bash
run: |
wget 'https://github.com/vegaprotocol/vega/releases/download/${{ inputs.version }}/vega-linux-amd64.zip' -q
unzip vega-linux-amd64.zip -d ${{ inputs.gobin }}
- name: Checkout vegawallet-dummy
uses: actions/checkout@v3
with:
repository: 'vegaprotocol/vegawallet-dummy'
path: './dummy'
- name: Install vegawallet-dummy binaries
shell: bash
run: go install
working-directory: ./dummy
@@ -1,6 +1,26 @@
inputs:
github-token:
description: 'github token'
runs:
using: 'composite'
steps:
- name: Checkout capsule
uses: actions/checkout@v2
with:
repository: vegaprotocol/vegacapsule
ref: main
token: ${{ inputs.github-token }}
path: './capsule'
- name: Build capsule
run: go install
shell: bash
working-directory: capsule
- name: Login to docker
shell: bash
run: echo -n ${{ inputs.github-token }} | docker login https://ghcr.io -u vega-ci-bot --password-stdin
- name: Start nomad
shell: bash
run: vegacapsule nomad &
@@ -1,35 +1,25 @@
outputs:
token:
description: 'api-token of wallet'
value: ${{ steps.generate-api-token.outputs.api-token }}
inputs:
passphrase:
description: 'Wallet password'
runs:
using: 'composite'
steps:
- name: Create passphrase
shell: bash
run: echo "${{ inputs.passphrase }}" > ./passphrase
- name: Initialize wallet
shell: bash
run: vega wallet init -f --home ~/.vegacapsule/testnet/wallet
- name: Import wallet
shell: bash
run: vega wallet import -w capsule_wallet --recovery-phrase-file ./frontend-monorepo/vegacapsule/recovery -p ./frontend-monorepo/vegacapsule/passphrase --home ~/.vegacapsule/testnet/wallet
- name: Generate second public key
shell: bash
run: vega wallet key generate -w capsule_wallet -p ./frontend-monorepo/vegacapsule/passphrase --home ~/.vegacapsule/testnet/wallet
run: vega wallet import -w capsule_wallet --recovery-phrase-file ./frontend-monorepo/vegacapsule/recovery -p ./passphrase --home ~/.vegacapsule/testnet/wallet
- name: Import network
shell: bash
run: vega wallet network import --force --from-file ./frontend-monorepo/vegacapsule/wallet-config.toml --home ~/.vegacapsule/testnet/wallet
- name: Init api-token
shell: bash
run: vega wallet api-token init --home ~/.vegacapsule/testnet/wallet --passphrase-file ./frontend-monorepo/vegacapsule/passphrase
- name: Generate api-token
id: generate-api-token
shell: bash
run: echo api-token=$(vega wallet api-token generate --wallet-name capsule_wallet --tokens-passphrase-file ./frontend-monorepo/vegacapsule/passphrase --wallet-passphrase-file ./frontend-monorepo/vegacapsule/passphrase --home ~/.vegacapsule/testnet/wallet | grep -Eo '[a-zA-Z0-9]{64}') >> $GITHUB_OUTPUT
- name: Start service using capsule network
shell: bash
run: vega wallet service run -n DV --load-tokens --tokens-passphrase-file ./frontend-monorepo/vegacapsule/passphrase --no-version-check --automatic-consent --home ~/.vegacapsule/testnet/wallet &
run: vegawallet-dummy service run --network DV --wallet capsule_wallet --passphrase-file ./passphrase --home ~/.vegacapsule/testnet/wallet &
+2 -15
View File
@@ -3,10 +3,6 @@ inputs:
description: 'Recovery phrase'
passphrase:
description: 'Wallet password'
outputs:
token:
description: 'api-token of wallet'
value: ${{ steps.generate-api-token.outputs.api-token }}
runs:
using: 'composite'
steps:
@@ -32,17 +28,8 @@ runs:
- name: Import network
shell: bash
run: vega wallet network import --from-url="https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml" --force --home ~/.vegacapsule/testnet/wallet
- name: Init api-token
shell: bash
run: vega wallet api-token init --home ~/.vegacapsule/testnet/wallet --passphrase-file passphrase
- name: Generate api-token
id: generate-api-token
shell: bash
run: echo api-token=$(vega wallet api-token generate --wallet-name UI_Trading_Test --tokens-passphrase-file passphrase --wallet-passphrase-file passphrase --home ~/.vegacapsule/testnet/wallet | grep -Eo '[a-zA-Z0-9]{64}') >> $GITHUB_OUTPUT
run: vega wallet network import --from-url="https://raw.githubusercontent.com/vegaprotocol/networks-internal/master/stagnet3/stagnet3.toml" --force --home ~/.vegacapsule/testnet/wallet
- name: Start service using stagnet3 network
shell: bash
run: vega wallet service run -n stagnet3 --load-tokens --tokens-passphrase-file passphrase --no-version-check --automatic-consent --home ~/.vegacapsule/testnet/wallet &
run: vegawallet-dummy service run --network stagnet3 --wallet UI_Trading_Test --passphrase-file ./passphrase --home ~/.vegacapsule/testnet/wallet &
@@ -12,6 +12,8 @@ on:
options:
- console-lite-e2e
- explorer-e2e
- liquidity-provision-dashboard-e2e
- stats-e2e
- token-e2e
- trading-e2e
tags:
@@ -24,6 +26,10 @@ on:
required: false
type: boolean
default: false
env:
GOBIN: /home/runner/go/bin
VEGA_VERSION: 'v0.62.1'
jobs:
manual:
name: Run Cypress tests -- manual trigger
@@ -37,6 +43,8 @@ jobs:
run: echo SKIP_NX_CACHE="--skip-nx-cache" >> $GITHUB_ENV
outputs:
vega-version: ${{env.VEGA_VERSION}}
gobin: ${{env.GOBIN}}
skip-cache: ${{env.SKIP_NX_CACHE}}
tags: ${{env.TAGS}}
@@ -46,5 +54,8 @@ jobs:
secrets: inherit
with:
project: ${{ inputs.project }}
vega-version: ${{needs.manual.outputs.vega-version}}
gobin: ${{needs.manual.outputs.gobin}}
skip-cache: ${{needs.manual.outputs.skip-cache}}
tags: ${{needs.manual.outputs.tags}}
capsule-teardown: false
@@ -12,6 +12,9 @@ jobs:
uses: ./.github/workflows/tests-dispatcher.yml
secrets: inherit
with:
project: '[console-lite-e2e, explorer-e2e, token-e2e, trading-e2e]'
project: '[console-lite-e2e, explorer-e2e, liquidity-provision-dashboard-e2e, stats-e2e, token-e2e, trading-e2e]'
vega-version: 'v0.62.1'
gobin: /home/runner/go/bin
tags: --env.grepTags '[ @smoke, @regression, @slow ]'
night-run: true
capsule-teardown: false
+11 -2
View File
@@ -11,6 +11,11 @@ on:
- reopened
- synchronize
- ready_for_review
env:
GOBIN: /home/runner/go/bin
VEGA_VERSION: 'v0.62.1'
jobs:
pr:
runs-on: ubuntu-latest
@@ -29,7 +34,7 @@ jobs:
path: |
frontend-monorepo/node_modules
/home/runner/.cache/Cypress
key: node_modules_cypress-${{ hashFiles('frontend-monorepo/yarn.lock', 'frontend-monorepo/package.json') }}
key: node_modules_cypress-${{ hashFiles('frontend-monorepo/yarn.lock') }}
# Install frontend dependencies
- name: Install root dependencies
@@ -51,6 +56,8 @@ jobs:
outputs:
projects: ${{ env.AFFECTED }}
vega-version: ${{ env.VEGA_VERSION }}
gobin: ${{ env.GOBIN }}
dispatch:
needs: pr
@@ -58,4 +65,6 @@ jobs:
secrets: inherit
with:
project: ${{ needs.pr.outputs.projects }}
tags: "--env.grepTags='[ @smoke, @regression ]'"
vega-version: ${{needs.pr.outputs.vega-version}}
gobin: ${{needs.pr.outputs.gobin}}
tags: "--env.grepTags='@smoke'"
+28 -10
View File
@@ -7,6 +7,13 @@ on:
required: true
type: string
default: 'false'
vega-version:
required: true
type: string
gobin:
required: false
type: string
default: /home/runner/go/bin
skip-cache:
required: false
type: string
@@ -19,8 +26,9 @@ jobs:
if: ${{ inputs.trigger == 'true' }}
runs-on: self-hosted
steps:
- name: Vega version
run: vega version
# Add GOBIN to PATH
- name: Add GOBIN to PATH
run: echo ${{ inputs.gobin }} >> $GITHUB_PATH
# Checkout front ends
- name: Checkout frontend mono repo
@@ -36,22 +44,32 @@ jobs:
path: |
frontend-monorepo/node_modules
/home/runner/.cache/Cypress
key: node_modules_cypress-${{ hashFiles('frontend-monorepo/yarn.lock', 'frontend-monorepo/package.json') }}
key: node_modules_cypress-${{ hashFiles('frontend-monorepo/yarn.lock') }}
# Install frontend dependencies
- name: Install root dependencies
run: yarn install --frozen-lockfile
working-directory: frontend-monorepo
#######
## Build and run Vegacapsule network
#######
- name: Install Vega binaries
uses: ./frontend-monorepo/.github/actions/install-vega-binaries
with:
version: ${{ inputs.vega-version }}
gobin: ${{ inputs.gobin }}
######
## Setup a Vega wallet for our user
######
- 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
- name: Set up Vegawallet
uses: ./frontend-monorepo/.github/actions/setup-vegawallet
with:
recovery: ${{ secrets.TRADING_TEST_VEGA_WALLET_RECOVERY }}
passphrase: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
# To make sure that all Cypress binaries are installed properly
- name: Install cypress bins
@@ -62,6 +80,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 }}
+38 -21
View File
@@ -7,6 +7,13 @@ on:
required: true
type: string
default: 'false'
vega-version:
required: true
type: string
gobin:
required: false
type: string
default: /home/runner/go/bin
skip-cache:
required: false
type: string
@@ -17,6 +24,10 @@ on:
required: false
type: boolean
default: false
capsule-teardown:
required: false
type: boolean
default: false
jobs:
explorer-e2e:
@@ -24,11 +35,9 @@ jobs:
runs-on: self-hosted
timeout-minutes: 30
steps:
- name: Vega version
run: vega version
- name: Vegacapsule version
run: vegacapsule version
# Add GOBIN to PATH
- name: Add GOBIN to PATH
run: echo ${{ inputs.gobin }} >> $GITHUB_PATH
# Checkout front ends
- name: Checkout frontend mono repo
@@ -44,23 +53,36 @@ jobs:
path: |
frontend-monorepo/node_modules
/home/runner/.cache/Cypress
key: node_modules_cypress-${{ hashFiles('frontend-monorepo/yarn.lock', 'frontend-monorepo/package.json') }}
key: node_modules_cypress-${{ hashFiles('frontend-monorepo/yarn.lock') }}
# Install frontend dependencies
- name: Install root dependencies
run: yarn install --frozen-lockfile
working-directory: frontend-monorepo
#######
## Build and run Vegacapsule network
#######
- name: Install Vega binaries
uses: ./frontend-monorepo/.github/actions/install-vega-binaries
with:
version: ${{ inputs.vega-version }}
gobin: ${{ inputs.gobin }}
- name: Build and run Vegacapsule network
uses: ./frontend-monorepo/.github/actions/run-vegacapsule
with:
github-token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
######
## Setup a Vega wallet for our user
######
- name: Run Vegacapsule network
uses: ./frontend-monorepo/.github/actions/run-vegacapsule
- name: Set up Vegawallet for capsule
id: setup-vega
- name: Set up Vegawallet for docker
uses: ./frontend-monorepo/.github/actions/setup-vegawallet-docker
with:
passphrase: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
######
## Run some tests
@@ -75,25 +97,20 @@ 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_TEARDOWN_NETWORK_AFTER_FLOWS: ${{ inputs.capsule-teardown }}
CYPRESS_NIGHTLY_RUN: ${{ inputs.night-run }}
CYPRESS_VEGA_WALLET_API_TOKEN: ${{ steps.setup-vega.outputs.token }}
######
## Upload logs
######
# Artifact path is not valid: /ganache-1/capsule-logscolletor.stderr-2022-12-22T10:20:30Z.log. Contains the following character: Colon :
- 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)
- name: Logs
run: vegacapsule network logs > vega-capsule-logs.txt
- uses: actions/upload-artifact@v2
if: ${{ always() }}
with:
name: logs
path: /home/runner/.vegacapsule/testnet/logs
path: ./vega-capsule-logs.txt
@@ -0,0 +1,47 @@
name: Cypress - liquidity provision dashboard
on:
workflow_call:
inputs:
trigger:
required: true
type: string
default: 'false'
jobs:
liquidity-provision-dashboard-e2e:
timeout-minutes: 10
if: ${{ inputs.trigger == 'true' }}
runs-on: self-hosted
steps:
# Checkout front ends
- name: Checkout frontend mono repo
uses: actions/checkout@v3
with:
fetch-depth: 0
path: './frontend-monorepo'
# Restore node_modules from cache if possible
- name: Restore node_modules from cache
uses: actions/cache@v3
with:
path: |
frontend-monorepo/node_modules
/home/runner/.cache/Cypress
key: node_modules_cypress-${{ hashFiles('frontend-monorepo/yarn.lock') }}
# Install frontend dependencies
- name: Install root dependencies
run: yarn install --frozen-lockfile
working-directory: frontend-monorepo
# To make sure that all Cypress binaries are installed properly
- name: Install cypress bins
run: yarn cypress install
working-directory: frontend-monorepo
- name: Run Cypress tests
run: npx nx run liquidity-provision-dashboard-e2e:e2e --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome
working-directory: frontend-monorepo
env:
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
+47
View File
@@ -0,0 +1,47 @@
name: Cypress - stats
on:
workflow_call:
inputs:
trigger:
required: true
type: string
default: 'false'
jobs:
stats-e2e:
runs-on: self-hosted
if: ${{ inputs.trigger == 'true' }}
timeout-minutes: 10
steps:
# Checkout front ends
- name: Checkout frontend mono repo
uses: actions/checkout@v3
with:
fetch-depth: 0
path: './frontend-monorepo'
# Restore node_modules from cache if possible
- name: Restore node_modules from cache
uses: actions/cache@v3
with:
path: |
frontend-monorepo/node_modules
/home/runner/.cache/Cypress
key: node_modules_cypress-${{ hashFiles('frontend-monorepo/yarn.lock') }}
# Install frontend dependencies
- name: Install root dependencies
run: yarn install --frozen-lockfile
working-directory: frontend-monorepo
# To make sure that all Cypress binaries are installed properly
- name: Install cypress bins
run: yarn cypress install
working-directory: frontend-monorepo
- name: Run Cypress tests
run: npx nx run stats-e2e:e2e --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome
working-directory: frontend-monorepo
env:
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
+39 -22
View File
@@ -7,12 +7,23 @@ on:
required: true
type: string
default: 'false'
vega-version:
required: true
type: string
gobin:
required: false
type: string
default: /home/runner/go/bin
skip-cache:
required: false
type: string
tags:
required: false
type: string
capsule-teardown:
required: false
type: boolean
default: false
jobs:
token-e2e:
@@ -20,11 +31,9 @@ jobs:
runs-on: self-hosted
timeout-minutes: 60
steps:
- name: Vega version
run: vega version
- name: Vegacapsule version
run: vegacapsule version
# Add GOBIN to PATH
- name: Add GOBIN to PATH
run: echo ${{ inputs.gobin }} >> $GITHUB_PATH
# Checkout front ends
- name: Checkout frontend mono repo
@@ -40,23 +49,36 @@ jobs:
path: |
frontend-monorepo/node_modules
/home/runner/.cache/Cypress
key: node_modules_cypress-${{ hashFiles('frontend-monorepo/yarn.lock', 'frontend-monorepo/package.json') }}
key: node_modules_cypress-${{ hashFiles('frontend-monorepo/yarn.lock') }}
# Install frontend dependencies
- name: Install root dependencies
run: yarn install --frozen-lockfile
working-directory: frontend-monorepo
#######
## Build and run Vegacapsule network
#######
- name: Install Vega binaries
uses: ./frontend-monorepo/.github/actions/install-vega-binaries
with:
version: ${{ inputs.vega-version }}
gobin: ${{ inputs.gobin }}
- name: Build and run Vegacapsule network
uses: ./frontend-monorepo/.github/actions/run-vegacapsule
with:
github-token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
######
## Setup a Vega wallet for our user
######
- name: Run Vegacapsule network
uses: ./frontend-monorepo/.github/actions/run-vegacapsule
- name: Set up Vegawallet for capsule
id: setup-vega
- name: Set up Vegawallet for docker
uses: ./frontend-monorepo/.github/actions/setup-vegawallet-docker
with:
passphrase: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
######
## Run some tests
@@ -71,24 +93,19 @@ 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 }}
CYPRESS_TEARDOWN_NETWORK_AFTER_FLOWS: ${{ inputs.capsule-teardown }}
######
## Upload logs
######
# Artifact path is not valid: /ganache-1/capsule-logscolletor.stderr-2022-12-22T10:20:30Z.log. Contains the following character: Colon :
- 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)
- name: Logs
run: vegacapsule network logs > vega-capsule-logs.txt
- uses: actions/upload-artifact@v2
if: ${{ always() }}
with:
name: logs-token
path: /home/runner/.vegacapsule/testnet/logs
name: logs
path: ./vega-capsule-logs.txt
+27 -27
View File
@@ -7,6 +7,13 @@ on:
required: true
type: string
default: 'false'
vega-version:
required: true
type: string
gobin:
required: false
type: string
default: /home/runner/go/bin
skip-cache:
required: false
type: string
@@ -20,8 +27,9 @@ jobs:
timeout-minutes: 30
runs-on: self-hosted
steps:
- name: Vega version
run: vega version
# Add GOBIN to PATH
- name: Add GOBIN to PATH
run: echo ${{ inputs.gobin }} >> $GITHUB_PATH
# Checkout front ends
- name: Checkout frontend mono repo
@@ -37,23 +45,32 @@ jobs:
path: |
frontend-monorepo/node_modules
/home/runner/.cache/Cypress
key: node_modules_cypress-${{ hashFiles('frontend-monorepo/yarn.lock', 'frontend-monorepo/package.json') }}
key: node_modules_cypress-${{ hashFiles('frontend-monorepo/yarn.lock') }}
# Install frontend dependencies
- name: Install root dependencies
run: yarn install --frozen-lockfile
working-directory: frontend-monorepo
#######
## Build and run Vegacapsule network
#######
- name: Install Vega binaries
uses: ./frontend-monorepo/.github/actions/install-vega-binaries
with:
version: ${{ inputs.vega-version }}
gobin: ${{ inputs.gobin }}
######
## Setup a Vega wallet for our user
######
- 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
- name: Set up Vegawallet
uses: ./frontend-monorepo/.github/actions/setup-vegawallet
with:
recovery: ${{ secrets.TRADING_TEST_VEGA_WALLET_RECOVERY }}
passphrase: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
# To make sure that all Cypress binaries are installed properly
- name: Install cypress bins
@@ -64,23 +81,6 @@ 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-trading
path: /home/runner/.vegacapsule/testnet/logs
@@ -4,7 +4,7 @@ name: Publish docker containers
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+-*'
- 'v[0-9]+.[0-9]+.[0-9]+-pre[0-9]+'
workflow_dispatch:
inputs:
+32
View File
@@ -4,6 +4,13 @@ on:
project:
required: true
type: string
vega-version:
required: true
type: string
gobin:
required: false
type: string
default: /home/runner/go/bin
skip-cache:
required: false
type: string
@@ -13,6 +20,9 @@ on:
night-run:
required: false
type: boolean
capsule-teardown:
required: false
type: boolean
jobs:
run-console-lite-e2e:
@@ -20,6 +30,8 @@ jobs:
secrets: inherit
with:
trigger: ${{ contains(inputs.project, 'console-lite-e2e') || contains(inputs.project, 'console-lite') }}
vega-version: ${{ inputs.vega-version }}
gobin: ${{ inputs.gobin }}
skip-cache: ${{ inputs.skip-cache }}
tags: ${{ inputs.tags }}
@@ -28,22 +40,42 @@ jobs:
secrets: inherit
with:
trigger: ${{ contains(inputs.project, 'explorer-e2e') || contains(inputs.project, 'explorer') }}
vega-version: ${{ inputs.vega-version }}
gobin: ${{ inputs.gobin }}
skip-cache: ${{ inputs.skip-cache }}
tags: ${{ inputs.tags }}
night-run: ${{ inputs.night-run }}
capsule-teardown: ${{ inputs.capsule-teardown }}
run-liquidity-e2e:
uses: ./.github/workflows/cypress-liquidity-provision-dashboard-e2e.yml
secrets: inherit
with:
trigger: ${{ contains(inputs.project, 'liquidity-provision-dashboard-e2e') || contains(inputs.project, 'liquidity-provision-dashboard') }}
run-stats-e2e:
uses: ./.github/workflows/cypress-stats-e2e.yml
secrets: inherit
with:
trigger: ${{ contains(inputs.project, 'stats-e2e') || contains(inputs.project, 'stats') }}
run-token-e2e:
uses: ./.github/workflows/cypress-token-e2e.yml
secrets: inherit
with:
trigger: ${{ contains(inputs.project, 'token-e2e') || contains(inputs.project, 'token') }}
vega-version: ${{ inputs.vega-version }}
gobin: ${{ inputs.gobin }}
skip-cache: ${{ inputs.skip-cache }}
tags: ${{ inputs.tags }}
capsule-teardown: ${{ inputs.capsule-teardown }}
run-trading-e2e:
uses: ./.github/workflows/cypress-trading-e2e.yml
secrets: inherit
with:
trigger: ${{ contains(inputs.project, 'trading-e2e') || contains(inputs.project, 'trading') }}
vega-version: ${{ inputs.vega-version }}
gobin: ${{ inputs.gobin }}
skip-cache: ${{ inputs.skip-cache }}
tags: ${{ inputs.tags }}
-1
View File
@@ -1,2 +1 @@
* @vegaprotocol/frontend
*.graphql @vegaprotocol/core
+9 -22
View File
@@ -22,6 +22,10 @@ The utility dApp for interacting with the Vega token and using its' utility. Thi
The block explorer for the Vega network, showing details of raw chain states and the state of markets on the Vega network.
### [Stats](./apps/stats)
An application for the status of the Vega network. Showing block height and other network activity.
### [Static](./apps/static)
Hosting for static content being shared across apps, for example fonts.
@@ -84,12 +88,12 @@ Run `nx test my-app` to execute the unit tests with [Jest](https://jestjs.io), o
### Using wallet
To run tests locally using your own wallets make sure you have generated at least two public keys and update the following environment variables in `cypress.config.js` to match your wallet.
To run tests locally using your own wallets you can add the following environment variables to `cypress.json`
1. Set `VEGA_PUBLIC_KEY` and `TRUNCATED_VEGA_PUBLIC_KEY` to your first public key.
2. Set `VEGA_PUBLIC_KEY2` and `TRUNCATED_VEGA_PUBLIC_KEY2` to your second public key.
3. Set `TRADING_TEST_VEGA_WALLET_PASSPHRASE` as your wallet passphrase
4. Add `ETH_WALLET_MNEMONIC` as your Ethereum wallet mnemonic
1. Change `TRADING_TEST_VEGA_WALLET_NAME` to your Vega wallet name
2. Add `TRADING_TEST_VEGA_WALLET_PASSPHRASE` as your wallet passphrase
3. Add `ETH_WALLET_MNEMONIC` as your Ethereum wallet mnemonic
4. Use [vegawallet-dummy](https://github.com/vegaprotocol/vegawallet-dummy) to avoid being prompted in CLI during test execution.
### Formatting
@@ -152,23 +156,6 @@ In order to run the bootstrap command to generate and start a new network, we mu
vegacapsule network bootstrap --config-path=../frontend-monorepo/vegacapsule/config.hcl
```
In order to setup and run vegawallet for e2e capsule tests, in a separate terminal window:
1. cd into `./vegacapsule`
2. run:
```bash
bash setup-vegawallet.sh
```
3. copy generated `api-token` and paste the token into `CYPRESS_VEGA_WALLET_API_TOKEN` environment variable in either `apps/token-e2e/.env` or `apps/explorer-e2e/.env` depending on which project needs testing.
Note: The script is only needed if capsule was built for first time or fresh. To run existing wallet service for capsule:
```bash
vega wallet service run -n DV --load-tokens --tokens-passphrase-file passphrase --no-version-check --automatic-consent --home ~/.vegacapsule/testnet/wallet
```
# 📑 License
[MIT](./LICENSE)
+6 -8
View File
@@ -1,11 +1,9 @@
NX_ETHEREUM_PROVIDER_URL=http://localhost:8545
# App configuration variables
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_URL=https://api.n01.stagnet3.vega.xyz/graphql
NX_VEGA_ENV=STAGNET3
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
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=
CYPRESS_VEGA_ENV=STAGNET3
-11
View File
@@ -1,11 +0,0 @@
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
View File
@@ -1,11 +0,0 @@
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=
+18 -1
View File
@@ -1,9 +1,10 @@
const { defineConfig } = require('cypress');
module.exports = defineConfig({
projectId: 'et4snf',
e2e: {
setupNodeEvents(on, config) {
require('@cypress/grep/src/plugin')(config);
require('cypress-grep/src/plugin')(config);
return config;
},
baseUrl: 'http://localhost:4200',
@@ -22,6 +23,22 @@ module.exports = defineConfig({
viewportHeight: 900,
},
env: {
TRADING_TEST_VEGA_WALLET_NAME: 'UI_Trading_Test',
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,
-20
View File
@@ -1,20 +0,0 @@
/// <reference types="cypress" />
declare namespace Cypress {
// specify additional properties in the TestConfig object
// in our case we will add "tags" property
interface SuiteConfigOverrides {
/**
* List of tags for this test
* @example a single tag
* it('logs in', { tags: '@smoke' }, () => { ... })
* @example multiple tags
* it('works', { tags: ['@smoke', '@slow'] }, () => { ... })
*/
tags?: string | string[];
}
interface Cypress {
grep?: (grep?: string, tags?: string, burn?: string) => void;
}
}
@@ -1,6 +1,15 @@
import { aliasQuery } from '@vegaprotocol/cypress';
import {
generateSimpleMarkets,
generateMarketsCandles,
} from '../support/mocks/generate-markets';
describe('simple trading app', { tags: '@smoke' }, () => {
beforeEach(() => {
cy.mockConsole();
cy.mockGQL((req) => {
aliasQuery(req, 'Markets', generateSimpleMarkets());
aliasQuery(req, 'MarketsCandles', generateMarketsCandles());
});
cy.visit('/');
});
@@ -1,11 +1,18 @@
import { aliasGQLQuery } from '@vegaprotocol/cypress';
import { aliasQuery } from '@vegaprotocol/cypress';
import type { MarketsQuery } from '@vegaprotocol/market-list';
import { marketCandlesQuery, marketsQuery } from '@vegaprotocol/mock';
import {
generateLongListMarkets,
generateSimpleMarkets,
generateMarketsCandles,
} from '../support/mocks/generate-markets';
describe('market list', { tags: '@smoke' }, () => {
describe('simple url', () => {
beforeEach(() => {
cy.mockConsole();
cy.mockGQL((req) => {
aliasQuery(req, 'Markets', generateSimpleMarkets());
aliasQuery(req, 'MarketsCandles', generateMarketsCandles());
});
cy.visit('/markets');
});
@@ -57,7 +64,10 @@ describe('market list', { tags: '@smoke' }, () => {
describe('url params should select filters', () => {
beforeEach(() => {
cy.mockConsole();
cy.mockGQL((req) => {
aliasQuery(req, 'Markets', generateSimpleMarkets());
aliasQuery(req, 'MarketsCandles', generateMarketsCandles());
});
});
it('suspended status', () => {
@@ -90,26 +100,14 @@ describe('market list', { tags: '@smoke' }, () => {
});
describe('long list of results should be handled properly', () => {
beforeEach(() => {
cy.mockConsole();
it('handles 1000 markets', () => {
cy.viewport(1440, 900);
const market = marketsQuery().marketsConnection?.edges[0];
const edges = new Array(1000)
.fill('')
.map(() => Object.assign({}, market));
cy.mockGQL((req) => {
aliasGQLQuery(
req,
'Markets',
marketsQuery({ marketsConnection: { edges } })
);
aliasGQLQuery(req, 'MarketsCandles', marketCandlesQuery());
aliasQuery(req, 'Markets', generateLongListMarkets(1000));
aliasQuery(req, 'MarketsCandles', generateMarketsCandles());
});
performance.mark('start-1k');
cy.visit('/markets');
cy.wait('@Markets');
});
it('handles 1000 markets', () => {
cy.get('.ag-center-cols-container', { timeout: 50000 }).then(() => {
performance.mark('end-1k');
performance.measure('load-1k', 'start-1k', 'end-1k');
@@ -1,85 +1,154 @@
const marketId = 'market-0';
const marketName = 'ACTIVE MARKET';
import { connectVegaWallet } from '../support/vega-wallet';
import { aliasQuery } from '@vegaprotocol/cypress';
import {
generateMarketsCandles,
generateMarketsData,
generateSimpleMarkets,
} from '../support/mocks/generate-markets';
import { generateDealTicket } from '../support/mocks/generate-deal-ticket';
import { generateMarketTags } from '../support/mocks/generate-market-tags';
import { generateMarketPositions } from '../support/mocks/generate-market-positions';
import { generateEstimateOrder } from '../support/mocks/generate-estimate-order';
import { generatePartyBalance } from '../support/mocks/generate-party-balance';
import { generatePartyMarketData } from '../support/mocks/generate-party-market-data';
import { generateMarketMarkPrice } from '../support/mocks/generate-market-mark-price';
import { generateMarketNames } from '../support/mocks/generate-market-names';
import { generateMarketDepth } from '../support/mocks/generate-market-depth';
import type { Market, MarketsQuery } from '@vegaprotocol/market-list';
import { generateChainId } from '../support/mocks/generate-chain-id';
import { generateStatistics } from '../support/mocks/generate-statistics';
describe('market selector', { tags: '@smoke' }, () => {
let markets: Market[];
beforeEach(() => {
cy.mockConsole();
cy.setVegaWallet();
cy.visit(`/trading/${marketId}`);
cy.wait('@Markets');
cy.mockGQL((req) => {
aliasQuery(req, 'ChainId', generateChainId());
aliasQuery(req, 'Statistics', generateStatistics());
aliasQuery(req, 'Markets', generateSimpleMarkets());
aliasQuery(req, 'MarketsCandles', generateMarketsCandles());
aliasQuery(req, 'MarketsData', generateMarketsData());
aliasQuery(req, 'DealTicket', generateDealTicket());
aliasQuery(req, 'MarketTags', generateMarketTags());
aliasQuery(req, 'MarketPositions', generateMarketPositions());
aliasQuery(req, 'EstimateOrder', generateEstimateOrder());
aliasQuery(req, 'PartyBalance', generatePartyBalance());
aliasQuery(req, 'PartyMarketData', generatePartyMarketData());
aliasQuery(req, 'MarketMarkPrice', generateMarketMarkPrice());
aliasQuery(req, 'MarketNames', generateMarketNames());
aliasQuery(req, 'MarketDepth', generateMarketDepth());
});
cy.visit('/markets');
cy.wait('@Markets').then((response) => {
const data: MarketsQuery | undefined = response?.response?.body?.data;
if (data?.marketsConnection?.edges.length) {
markets = data?.marketsConnection?.edges.map((edge) => edge.node);
}
});
});
it('should be properly rendered', () => {
cy.get('input[placeholder="Search"]').should('have.value', marketName);
cy.getByTestId('arrow-button').click();
cy.getByTestId('market-pane').should('be.visible');
cy.getByTestId('market-pane')
.children()
.find('[role="button"]')
.first()
.should('contain.text', marketName);
cy.getByTestId('market-pane')
.children()
.find('[role="button"]')
.first()
.click();
cy.getByTestId('market-pane').should('not.be.visible');
if (markets?.length) {
cy.visit(`/trading/${markets[0].id}`);
connectVegaWallet();
cy.get('input[placeholder="Search"]').should(
'have.value',
markets[0].tradableInstrument.instrument.name
);
cy.getByTestId('arrow-button').click();
cy.getByTestId('market-pane').should('be.visible');
cy.getByTestId('market-pane')
.children()
.find('[role="button"]')
.first()
.should('contain.text', markets[0].tradableInstrument.instrument.name);
cy.getByTestId('market-pane')
.children()
.find('[role="button"]')
.first()
.click();
cy.getByTestId('market-pane').should('not.be.visible');
}
});
it('typing should change list', () => {
cy.get('input[placeholder="Search"]').type('{backspace}');
cy.getByTestId('market-pane')
.children()
.find('[role="button"]')
.should('have.length.at.least', 1);
cy.get('input[placeholder="Search"]').clear();
cy.get('input[placeholder="Search"]').type('ACTIVE');
cy.getByTestId('market-pane')
.children()
.find('[role="button"]')
.should('have.length', 1);
cy.getByTestId('market-pane')
.children()
.find('[role="button"]')
.last()
.click();
cy.location('pathname').should('eq', `/trading/${marketId}`);
cy.get('input[placeholder="Search"]').should('have.value', marketName);
if (markets?.length) {
cy.visit(`/trading/${markets[0].id}`);
connectVegaWallet();
cy.get('input[placeholder="Search"]').type('{backspace}');
cy.getByTestId('market-pane')
.children()
.find('[role="button"]')
.should('have.length.at.least', 1);
cy.get('input[placeholder="Search"]').clear();
cy.get('input[placeholder="Search"]').type('aa');
const filtered = markets.filter(
(market) =>
market.state === 'STATE_ACTIVE' &&
market.tradableInstrument.instrument.name.match(/aa/i)
);
cy.getByTestId('market-pane')
.children()
.find('[role="button"]')
.should('have.length', filtered.length);
cy.getByTestId('market-pane')
.children()
.find('[role="button"]')
.last()
.click();
cy.location('pathname').should(
'eq',
`/trading/${filtered[filtered.length - 1].id}`
);
cy.get('input[placeholder="Search"]').should(
'have.value',
filtered[filtered.length - 1].tradableInstrument.instrument.name
);
}
});
// constantly failing on ci
it.skip('keyboard navigation should work well', () => {
cy.get('input[placeholder="Search"]').type('{backspace}');
cy.get('input[placeholder="Search"]').clear();
cy.focused().realPress('ArrowDown');
cy.focused().should('contain.text', marketName);
cy.focused().realPress('ArrowDown');
cy.focused().should('contain.text', 'ETHBTC').realPress('Enter');
cy.location('pathname').should('eq', '/trading/ethbtc-quaterly');
if (markets?.length) {
cy.visit(`/trading/${markets[0].id}`);
connectVegaWallet();
cy.get('input[placeholder="Search"]').type('{backspace}');
cy.get('input[placeholder="Search"]').clear();
cy.focused().realPress('ArrowDown');
cy.focused().should('contain.text', 'AAVEDAI Monthly');
cy.focused().realPress('ArrowDown');
cy.focused().should('contain.text', 'ETHBTC').realPress('Enter');
cy.location('pathname').should('eq', '/trading/ethbtc-quaterly');
cy.get('input[placeholder="Search"]').type('{backspace}');
cy.get('input[placeholder="Search"]').clear();
cy.getByTestId('market-pane').should('be.visible');
cy.get('body').realPress('ArrowDown');
cy.get('body').realPress('Tab');
cy.getByTestId('market-pane').should('not.be.visible');
cy.get('input[placeholder="Search"]').type('{backspace}');
cy.get('input[placeholder="Search"]').clear();
cy.getByTestId('market-pane').should('be.visible');
cy.get('body').realPress('ArrowDown');
cy.get('body').realPress('Tab');
cy.getByTestId('market-pane').should('not.be.visible');
}
});
it('mobile view', () => {
cy.viewport('iphone-xr');
cy.visit(`/trading/${marketId}`);
cy.connectVegaWallet();
cy.get('[role="dialog"]').should('not.exist');
cy.getByTestId('arrow-button').click();
cy.get('[role="dialog"]').should('be.visible');
cy.get('input[placeholder="Search"]').then((search) => {
cy.wrap(search).clear();
});
cy.getByTestId('market-pane')
.children()
.find('[role="button"]')
.should('have.length', 3);
cy.get('div[role="dialog"]').should('have.class', 'w-screen');
cy.getByTestId('dialog-close').click();
cy.get('input[placeholder="Search"]').should('have.value', marketName);
if (markets?.length) {
cy.viewport('iphone-xr');
cy.visit(`/trading/${markets[0].id}`);
connectVegaWallet();
cy.get('[role="dialog"]').should('not.exist');
cy.getByTestId('arrow-button').click();
cy.get('[role="dialog"]').should('be.visible');
cy.get('input[placeholder="Search"]').then((search) => {
cy.wrap(search).clear();
});
cy.getByTestId('market-pane')
.children()
.find('[role="button"]')
.should('have.length', 9);
cy.get('div[role="dialog"]').should('have.class', 'w-screen');
cy.getByTestId('dialog-close').click();
cy.get('input[placeholder="Search"]').should(
'have.value',
markets[0].tradableInstrument.instrument.name
);
}
});
});
@@ -1,37 +1,54 @@
import { aliasGQLQuery } from '@vegaprotocol/cypress';
import { marketQuery, marketsQuery } from '@vegaprotocol/mock';
import { connectVegaWallet } from '../support/vega-wallet';
import { aliasQuery } from '@vegaprotocol/cypress';
import {
generateSimpleMarkets,
generateMarketsCandles,
generateMarketsData,
generateMarket,
} from '../support/mocks/generate-markets';
import { generateDealTicket } from '../support/mocks/generate-deal-ticket';
import { generateMarketTags } from '../support/mocks/generate-market-tags';
import { generateMarketPositions } from '../support/mocks/generate-market-positions';
import { generateEstimateOrder } from '../support/mocks/generate-estimate-order';
import { generatePartyBalance } from '../support/mocks/generate-party-balance';
import { generatePartyMarketData } from '../support/mocks/generate-party-market-data';
import { generateMarketMarkPrice } from '../support/mocks/generate-market-mark-price';
import { generateMarketDepth } from '../support/mocks/generate-market-depth';
import type { MarketsQuery, Market } from '@vegaprotocol/market-list';
import { generateChainId } from '../support/mocks/generate-chain-id';
import { generateStatistics } from '../support/mocks/generate-statistics';
const marketId =
marketsQuery().marketsConnection?.edges[1].node.id || 'market-1';
const marketOverride = {
market: {
depth: {
lastTrade: {
price: '9893006',
},
},
id: marketId,
tradableInstrument: {
instrument: {
product: {
settlementAsset: {
id: 'asset-id-2',
name: 'DAI Name',
symbol: 'tDAI',
},
},
},
},
},
};
describe('Market trade with wallet disconnected', { tags: '@smoke' }, () => {
before(() => {
cy.mockConsole();
cy.visit(`/trading/${marketId}`);
cy.wait('@Market');
describe('Market trade', { tags: '@smoke' }, () => {
let markets: Market[];
beforeEach(() => {
cy.mockGQL((req) => {
aliasQuery(req, 'ChainId', generateChainId());
aliasQuery(req, 'Statistics', generateStatistics());
aliasQuery(req, 'Markets', generateSimpleMarkets());
aliasQuery(req, 'MarketsCandles', generateMarketsCandles());
aliasQuery(req, 'MarketsData', generateMarketsData());
aliasQuery(req, 'SimpleMarkets', generateSimpleMarkets());
aliasQuery(req, 'DealTicket', generateDealTicket());
aliasQuery(req, 'MarketTags', generateMarketTags());
aliasQuery(req, 'MarketPositions', generateMarketPositions());
aliasQuery(req, 'EstimateOrder', generateEstimateOrder());
aliasQuery(req, 'PartyBalance', generatePartyBalance());
aliasQuery(req, 'PartyMarketData', generatePartyMarketData());
aliasQuery(req, 'MarketMarkPrice', generateMarketMarkPrice());
aliasQuery(req, 'MarketDepth', generateMarketDepth());
aliasQuery(req, 'Market', generateMarket());
});
cy.visit('/markets');
cy.wait('@Markets').then((response) => {
const data: MarketsQuery | undefined = response?.response?.body?.data;
if (data?.marketsConnection?.edges.length) {
markets = data?.marketsConnection?.edges.map((edge) => edge.node);
}
});
});
it('should not display steps', () => {
it('should not display steps if wallet is disconnected', () => {
cy.visit(`/trading/${markets[0].id}`);
cy.getByTestId('trading-connect-wallet')
.find('h3')
.should('have.text', 'Please connect your Vega wallet to make a trade');
@@ -42,236 +59,267 @@ describe('Market trade with wallet disconnected', { tags: '@smoke' }, () => {
.find('a')
.should('have.text', 'https://vega.xyz/wallet');
});
});
describe('Market trade', { tags: '@regression' }, () => {
beforeEach(() => {
cy.mockConsole();
cy.mockGQL((req) => {
aliasGQLQuery(req, 'Market', marketQuery(marketOverride));
});
cy.setVegaWallet();
cy.visit(`/trading/${marketId}`);
cy.wait('@Market');
});
it('side selector should work well', () => {
cy.get('#step-1-control [aria-label^="Selected value"]').should(
'have.text',
'Long'
);
cy.get('#step-1-control [aria-label^="Selected value"]').click();
cy.get('button[aria-label="Open short position"]').click();
cy.get('#step-2-control').click();
cy.get('#step-1-control [aria-label^="Selected value"]').should(
'have.text',
'Short'
);
if (markets?.length) {
cy.visit(`/trading/${markets[0].id}`);
connectVegaWallet();
cy.get('#step-1-control [aria-label^="Selected value"]').should(
'have.text',
'Long'
);
cy.get('#step-1-control [aria-label^="Selected value"]').click();
cy.get('button[aria-label="Open short position"]').click();
cy.get('#step-2-control').click();
cy.get('#step-1-control [aria-label^="Selected value"]').should(
'have.text',
'Short'
);
}
});
it('side selector mobile view should work well', () => {
cy.viewport('iphone-xr');
cy.getByTestId('next-button').scrollIntoView().click();
if (markets?.length) {
cy.viewport('iphone-xr');
cy.visit(`/trading/${markets[0].id}`);
connectVegaWallet();
cy.getByTestId('next-button').scrollIntoView().click();
cy.get('button[aria-label="Open long position"]').should(
'have.class',
'selected'
);
cy.get('button[aria-label="Open short position"]').should(
'not.have.class',
'selected'
);
cy.get('button[aria-label="Open long position"]').should(
'have.class',
'selected'
);
cy.get('button[aria-label="Open short position"]').should(
'not.have.class',
'selected'
);
cy.get('button[aria-label="Open short position"]').click();
cy.get('button[aria-label="Open long position"]').should(
'not.have.class',
'selected'
);
cy.get('button[aria-label="Open short position"]').should(
'have.class',
'selected'
);
cy.getByTestId('next-button').scrollIntoView().click();
cy.get('#step-1-control').should(
'contain.html',
'aria-label="Selected value Short"'
);
cy.get('button[aria-label="Open short position"]').click();
cy.get('button[aria-label="Open long position"]').should(
'not.have.class',
'selected'
);
cy.get('button[aria-label="Open short position"]').should(
'have.class',
'selected'
);
cy.getByTestId('next-button').scrollIntoView().click();
cy.get('#step-1-control').should(
'contain.html',
'aria-label="Selected value Short"'
);
}
});
it('size slider should work well', () => {
cy.get('#step-1-control [aria-label^="Selected value"]').click();
cy.get('button[aria-label="Open short position"]').click();
cy.get('#step-2-control').click();
cy.get('#step-2-panel')
.find('dd')
.eq(0)
.find('button')
.should('have.text', '1');
cy.get('#step-2-panel').find('[role="slider"]').type('{rightarrow}');
if (markets?.length) {
cy.visit(`/trading/${markets[1].id}`);
connectVegaWallet();
cy.get('#step-1-control [aria-label^="Selected value"]').click();
cy.get('button[aria-label="Open short position"]').click();
cy.get('#step-2-control').click();
cy.get('#step-2-panel')
.find('dd')
.eq(0)
.find('button')
.should('have.text', '1');
cy.get('#step-2-panel').find('[role="slider"]').type('{rightarrow}');
cy.get('#step-2-panel')
.find('dd')
.eq(0)
.find('button')
.should('have.text', '2');
cy.get('#step-2-panel')
.find('dd')
.eq(0)
.find('button')
.should('have.text', '2');
}
});
it('percentage selection should work well', () => {
cy.get('#step-1-control [aria-label^="Selected value"]').click();
cy.get('button[aria-label="Open short position"]').click();
cy.get('#step-2-control').click();
cy.get('#step-2-panel')
.find('dd')
.eq(0)
.find('button')
.should('have.text', '1');
if (markets?.length) {
cy.visit(`/trading/${markets[1].id}`);
connectVegaWallet();
cy.get('#step-1-control [aria-label^="Selected value"]').click();
cy.get('button[aria-label="Open short position"]').click();
cy.get('#step-2-control').click();
cy.get('#step-2-panel')
.find('dd')
.eq(0)
.find('button')
.should('have.text', '1');
cy.getByTestId('max-label').should('have.text', '10');
cy.getByTestId('max-label').should('have.text', '21');
cy.getByTestId('percentage-selector')
.find('button')
.contains('Max')
.click();
cy.get('#step-2-panel')
.find('dd')
.eq(0)
.find('button')
.should('have.text', '10');
cy.getByTestId('percentage-selector')
.find('button')
.contains('Max')
.click();
cy.get('#step-2-panel')
.find('dd')
.eq(0)
.find('button')
.should('have.text', '21');
}
});
it('size input should work well', () => {
cy.get('#step-1-control [aria-label^="Selected value"]').click();
cy.get('button[aria-label="Open short position"]').click();
cy.get('#step-2-control').click();
cy.get('#step-2-panel')
.find('dd')
.eq(0)
.find('button')
.should('have.text', '1');
cy.get('#step-2-panel').find('dd').eq(0).find('button').click();
cy.get('#step-2-panel').find('dd').eq(0).find('input').type('{backspace}2');
cy.get('#step-2-panel').find('dd').eq(0).find('button').click();
cy.get('#step-2-panel')
.find('dd')
.eq(0)
.find('button')
.should('have.text', '2');
cy.get('button').contains('Max').click();
if (markets?.length) {
cy.visit(`/trading/${markets[1].id}`);
connectVegaWallet();
cy.get('#step-1-control [aria-label^="Selected value"]').click();
cy.get('button[aria-label="Open short position"]').click();
cy.get('#step-2-control').click();
cy.get('#step-2-panel')
.find('dd')
.eq(0)
.find('button')
.should('have.text', '1');
cy.get('#step-2-panel').find('dd').eq(0).find('button').click();
cy.get('#step-2-panel')
.find('dd')
.eq(0)
.find('input')
.type('{backspace}2');
cy.get('#step-2-panel').find('dd').eq(0).find('button').click();
cy.get('#step-2-panel')
.find('dd')
.eq(0)
.find('button')
.should('have.text', '2');
cy.get('button').contains('Max').click();
}
});
it('slippage value should be displayed', () => {
cy.get('#step-1-control [aria-label^="Selected value"]').click();
cy.get('button[aria-label="Open short position"]').click();
cy.get('#step-2-control').click();
cy.get('button').contains('Max').click();
cy.get('#step-2-panel')
.find('dl')
.eq(2)
.find('dd')
.should('have.text', '0.01%');
if (markets?.length) {
cy.visit(`/trading/${markets[1].id}`);
connectVegaWallet();
cy.get('#step-1-control [aria-label^="Selected value"]').click();
cy.get('button[aria-label="Open short position"]').click();
cy.get('#step-2-control').click();
cy.get('button').contains('Max').click();
cy.get('#step-2-panel')
.find('dl')
.eq(2)
.find('dd')
.should('have.text', '0.02%');
}
});
it('allow slippage value to be adjusted', () => {
cy.get('#step-1-control [aria-label^="Selected value"]').click();
cy.get('button[aria-label="Open short position"]').click();
cy.get('#step-2-control').click();
cy.get('button').contains('Max').click();
cy.get('#step-2-panel')
.find('dl')
.eq(2)
.find('dd')
.should('have.text', '0.01%');
cy.get('#step-2-panel').find('dl').eq(2).find('button').click();
cy.get('#input-order-slippage')
.focus()
.type('{backspace}{backspace}{backspace}1');
if (markets?.length) {
cy.visit(`/trading/${markets[1].id}`);
connectVegaWallet();
cy.get('#step-1-control [aria-label^="Selected value"]').click();
cy.get('button[aria-label="Open short position"]').click();
cy.get('#step-2-control').click();
cy.get('button').contains('Max').click();
cy.get('#step-2-panel')
.find('dl')
.eq(2)
.find('dd')
.should('have.text', '0.02%');
cy.get('#step-2-panel').find('dl').eq(2).find('button').click();
cy.get('#input-order-slippage')
.focus()
.type('{backspace}{backspace}{backspace}1');
cy.getByTestId('slippage-dialog').find('button').click();
cy.getByTestId('slippage-dialog').find('button').click();
cy.get('#step-2-panel')
.find('dl')
.eq(2)
.find('dd')
.should('have.text', '1%');
cy.get('#step-2-panel')
.find('dl')
.eq(2)
.find('dd')
.should('have.text', '1%');
}
});
it('notional position size should be present', () => {
cy.get('#step-1-control [aria-label^="Selected value"]').click();
cy.get('button[aria-label="Open short position"]').click();
cy.get('#step-2-control').click();
cy.get('#step-2-panel')
.find('dd')
.eq(0)
.find('button')
.should('have.text', '1');
cy.get('#step-2-panel').find('dd').eq(0).find('button').click();
cy.get('#step-2-panel').find('dd').eq(0).find('input').type('{backspace}2');
cy.get('#step-2-panel').find('dd').eq(0).find('button').click();
cy.get('#step-2-panel')
.find('dt')
.eq(2)
.should('have.text', 'Est. Position Size (tDAI)');
cy.get('#step-2-panel').find('dd').eq(2).should('have.text', '197.86012');
if (markets?.length) {
cy.visit(`/trading/${markets[1].id}`);
connectVegaWallet();
cy.get('#step-1-control [aria-label^="Selected value"]').click();
cy.get('button[aria-label="Open short position"]').click();
cy.get('#step-2-control').click();
cy.get('#step-2-panel')
.find('dd')
.eq(0)
.find('button')
.should('have.text', '1');
cy.get('#step-2-panel').find('dd').eq(0).find('button').click();
cy.get('#step-2-panel')
.find('dd')
.eq(0)
.find('input')
.type('{backspace}2');
cy.get('#step-2-panel').find('dd').eq(0).find('button').click();
cy.get('#step-2-panel')
.find('dt')
.eq(2)
.should('have.text', 'Est. Position Size (tDAI)');
cy.get('#step-2-panel').find('dd').eq(2).should('have.text', '197.86012');
}
});
it('total fees should be displayed', () => {
cy.get('#step-1-control [aria-label^="Selected value"]').click();
cy.get('button[aria-label="Open short position"]').click();
cy.get('#step-2-control').click();
cy.get('#step-2-panel')
.find('dt')
.eq(3)
.should('have.text', 'Est. Fees (tDAI)');
cy.get('#step-2-panel')
.find('dd')
.eq(3)
.should('have.text', '3.00 (3.03%)');
if (markets?.length) {
cy.visit(`/trading/${markets[1].id}`);
connectVegaWallet();
cy.get('#step-1-control [aria-label^="Selected value"]').click();
cy.get('button[aria-label="Open short position"]').click();
cy.get('#step-2-control').click();
cy.get('#step-2-panel')
.find('dt')
.eq(3)
.should('have.text', 'Est. Fees (tDAI)');
cy.get('#step-2-panel').find('dd').eq(3).should('have.text', '3 (3.03%)');
}
});
it('order review should display proper calculations', () => {
cy.get('#step-3-control').click();
if (markets?.length) {
cy.visit(`/trading/${markets[0].id}`);
connectVegaWallet();
cy.get('#step-3-control').click();
cy.getByTestId('review-trade')
.get('#contracts_tooltip_trigger')
.trigger('click')
.realTouch();
cy.getByTestId('review-trade')
.get('#contracts_tooltip_trigger')
.trigger('click')
.realTouch();
cy.get('[data-radix-popper-content-wrapper]').contains(
'The number of contracts determines'
);
cy.get('#step-3-panel').find('dd').eq(1).should('have.text', '1');
cy.get('[data-radix-popper-content-wrapper]').contains(
'The number of contracts determines'
);
cy.get('#step-3-panel').find('dd').eq(1).should('have.text', '1');
cy.get('#step-3-panel').find('dd').eq(2).should('have.text', '98.93006');
cy.get('#step-3-panel').find('dd').eq(2).should('have.text', '98.93006');
cy.get('#step-3-panel')
.find('dd')
.eq(3)
.should('have.text', '3.00 (3.03%)');
cy.get('#step-3-panel').find('dd').eq(3).should('have.text', '3 (3.03%)');
cy.get('#step-3-panel')
.find('dd')
.eq(4)
.should('have.text', '45,126.90058');
cy.get('#step-3-panel').find('dd').eq(4).should('have.text', ' - ');
cy.getByTestId('place-order').should('be.enabled').click();
cy.getByTestId('place-order').should('be.enabled').click();
}
});
it('info tooltip on mobile view should work well', () => {
cy.viewport('iphone-xr');
cy.get('#step-3-control').click();
if (markets?.length) {
cy.viewport('iphone-xr');
cy.visit(`/trading/${markets[0].id}`);
connectVegaWallet();
cy.get('#step-3-control').click();
// Start from the bottom tooltip to ensure the tooltip above
// can be interacted with
cy.getByTestId('review-trade').get('div.cursor-help').eq(1).realTouch();
cy.get('[data-radix-popper-content-wrapper]').contains(
'The notional size represents the position size'
);
// Start from the bottom tooltip to ensure the tooltip above
// can be interacted with
cy.getByTestId('review-trade').get('div.cursor-help').eq(1).realTouch();
cy.get('[data-radix-popper-content-wrapper]').contains(
'The notional size represents the position size'
);
cy.getByTestId('review-trade')
.get('#contracts_tooltip_trigger')
.realTouch();
cy.get('[data-radix-popper-content-wrapper]').contains(
'The number of contracts determines'
);
cy.getByTestId('review-trade')
.get('#contracts_tooltip_trigger')
.realTouch();
cy.get('[data-radix-popper-content-wrapper]').contains(
'The number of contracts determines'
);
}
});
});
@@ -1,24 +1,28 @@
import { aliasGQLQuery } from '@vegaprotocol/cypress';
import { connectVegaWallet } from '../support/vega-wallet';
import { aliasQuery } from '@vegaprotocol/cypress';
import {
accountsQuery,
assetsQuery,
chainIdQuery,
fillsQuery,
marginsQuery,
marketsDataQuery,
marketsQuery,
ordersQuery,
positionsQuery,
statisticsQuery,
} from '@vegaprotocol/mock';
generatePositions,
emptyPositions,
generateMargins,
} from '../support/mocks/generate-positions';
import { generateAccounts } from '../support/mocks/generate-accounts';
import { generateAssets } from '../support/mocks/generate-assets';
import { generateOrders } from '../support/mocks/generate-orders';
import { generateFills } from '../support/mocks/generate-fills';
import {
generateFillsMarkets,
generateMarketsData,
generatePositionsMarkets,
} from '../support/mocks/generate-markets';
import { generateChainId } from '../support/mocks/generate-chain-id';
import { generateStatistics } from '../support/mocks/generate-statistics';
describe('Portfolio page - wallet', { tags: '@smoke' }, () => {
it('button for wallet connect should work', () => {
cy.mockConsole();
cy.visit('/');
cy.get('[href="/portfolio"]').eq(0).click();
cy.getByTestId('trading-connect-wallet').should('be.visible');
cy.connectVegaWallet();
connectVegaWallet();
cy.getByTestId('trading-connect-wallet').should('not.exist');
});
});
@@ -26,20 +30,20 @@ describe('Portfolio page - wallet', { tags: '@smoke' }, () => {
describe('Portfolio page tabs', { tags: '@smoke' }, () => {
before(() => {
cy.mockGQL((req) => {
aliasGQLQuery(req, 'ChainId', chainIdQuery());
aliasGQLQuery(req, 'Statistics', statisticsQuery());
aliasGQLQuery(req, 'Positions', positionsQuery());
aliasGQLQuery(req, 'Margins', marginsQuery());
aliasGQLQuery(req, 'Markets', marketsQuery());
aliasGQLQuery(req, 'MarketsData', marketsDataQuery());
aliasGQLQuery(req, 'Accounts', accountsQuery());
aliasGQLQuery(req, 'Assets', assetsQuery());
aliasQuery(req, 'ChainId', generateChainId());
aliasQuery(req, 'Statistics', generateStatistics());
aliasQuery(req, 'Positions', generatePositions());
aliasQuery(req, 'Margins', generateMargins());
aliasQuery(req, 'Markets', generatePositionsMarkets());
aliasQuery(req, 'MarketsData', generateMarketsData());
aliasQuery(req, 'Accounts', generateAccounts());
aliasQuery(req, 'Assets', generateAssets());
});
cy.setVegaWallet();
});
it('certain tabs should exist', () => {
cy.visit('/portfolio');
connectVegaWallet();
cy.getByTestId('assets').click();
cy.location('pathname').should('eq', '/portfolio/assets');
@@ -58,16 +62,27 @@ describe('Portfolio page tabs', { tags: '@smoke' }, () => {
});
describe('Assets view', () => {
beforeEach(() => {
cy.mockConsole();
cy.setVegaWallet();
before(() => {
cy.mockGQL((req) => {
aliasQuery(req, 'ChainId', generateChainId());
aliasQuery(req, 'Statistics', generateStatistics());
aliasQuery(req, 'Positions', generatePositions());
aliasQuery(req, 'Margins', generateMargins());
aliasQuery(req, 'Markets', generatePositionsMarkets());
aliasQuery(req, 'MarketsData', generateMarketsData());
aliasQuery(req, 'Accounts', generateAccounts());
aliasQuery(req, 'Assets', generateAssets());
});
cy.visit('/portfolio/assets');
connectVegaWallet();
});
it('data should be properly rendered', () => {
cy.get('.ag-center-cols-container .ag-row').should('have.length', 5);
cy.get('[role="gridcell"][col-id="account-asset"] button')
.contains('tEURO')
cy.get('.ag-center-cols-container .ag-row').should('have.length', 3);
cy.get(
'.ag-center-cols-container [row-id="ACCOUNT_TYPE_GENERAL-asset-id-null"]'
)
.find('button')
.click();
cy.getByTestId('dialog-title').should(
'have.text',
@@ -80,17 +95,17 @@ describe('Portfolio page tabs', { tags: '@smoke' }, () => {
describe('Positions view', () => {
beforeEach(() => {
cy.mockGQL((req) => {
aliasGQLQuery(req, 'ChainId', chainIdQuery());
aliasGQLQuery(req, 'Statistics', statisticsQuery());
aliasGQLQuery(req, 'Positions', positionsQuery());
aliasGQLQuery(req, 'Margins', marginsQuery());
aliasGQLQuery(req, 'Markets', marketsQuery());
aliasGQLQuery(req, 'MarketsData', marketsDataQuery());
aliasGQLQuery(req, 'Accounts', accountsQuery());
aliasGQLQuery(req, 'Assets', assetsQuery());
aliasQuery(req, 'ChainId', generateChainId());
aliasQuery(req, 'Statistics', generateStatistics());
aliasQuery(req, 'Positions', generatePositions());
aliasQuery(req, 'Accounts', generateAccounts());
aliasQuery(req, 'Margins', generateMargins());
aliasQuery(req, 'Markets', generatePositionsMarkets());
aliasQuery(req, 'MarketsData', generateMarketsData());
aliasQuery(req, 'Assets', generateAssets());
});
cy.setVegaWallet();
cy.visit('/portfolio/positions');
connectVegaWallet();
});
it('data should be properly rendered', () => {
@@ -101,13 +116,13 @@ describe('Portfolio page tabs', { tags: '@smoke' }, () => {
describe('Orders view', () => {
beforeEach(() => {
cy.mockGQL((req) => {
aliasGQLQuery(req, 'ChainId', chainIdQuery());
aliasGQLQuery(req, 'Statistics', statisticsQuery());
aliasGQLQuery(req, 'Orders', ordersQuery());
aliasGQLQuery(req, 'Markets', marketsQuery());
aliasQuery(req, 'ChainId', generateChainId());
aliasQuery(req, 'Statistics', generateStatistics());
aliasQuery(req, 'Orders', generateOrders());
aliasQuery(req, 'Markets', generateFillsMarkets());
});
cy.setVegaWallet();
cy.visit('/portfolio/orders');
connectVegaWallet();
});
it('data should be properly rendered', () => {
@@ -118,14 +133,13 @@ describe('Portfolio page tabs', { tags: '@smoke' }, () => {
describe('Fills view', () => {
beforeEach(() => {
cy.mockGQL((req) => {
aliasGQLQuery(req, 'ChainId', chainIdQuery());
aliasGQLQuery(req, 'Statistics', statisticsQuery());
aliasGQLQuery(req, 'Orders', ordersQuery());
aliasGQLQuery(req, 'Markets', marketsQuery());
aliasGQLQuery(req, 'Fills', fillsQuery());
aliasQuery(req, 'ChainId', generateChainId());
aliasQuery(req, 'Statistics', generateStatistics());
aliasQuery(req, 'Fills', generateFills());
aliasQuery(req, 'Markets', generateFillsMarkets());
});
cy.setVegaWallet();
cy.visit('/portfolio/fills');
connectVegaWallet();
});
it('data should be properly rendered', () => {
@@ -136,23 +150,23 @@ describe('Portfolio page tabs', { tags: '@smoke' }, () => {
describe('Empty views', () => {
beforeEach(() => {
cy.mockGQL((req) => {
aliasGQLQuery(req, 'ChainId', chainIdQuery());
aliasGQLQuery(req, 'Statistics', statisticsQuery());
aliasGQLQuery(req, 'Positions', { party: null });
aliasGQLQuery(req, 'Accounts', { party: null });
aliasGQLQuery(req, 'Orders', { party: null });
aliasGQLQuery(req, 'Fills', { party: null });
aliasGQLQuery(req, 'Markets', {
aliasQuery(req, 'ChainId', generateChainId());
aliasQuery(req, 'Statistics', generateStatistics());
aliasQuery(req, 'Positions', emptyPositions());
aliasQuery(req, 'Accounts', { party: null });
aliasQuery(req, 'Orders', { party: null });
aliasQuery(req, 'Fills', { party: null });
aliasQuery(req, 'Markets', {
marketsConnection: { edges: [], __typename: 'MarketConnection' },
});
aliasGQLQuery(req, 'Assets', {
aliasQuery(req, 'Assets', {
assetsConnection: { edges: null, __typename: 'AssetsConnection' },
});
aliasGQLQuery(req, 'Margins', marginsQuery());
aliasGQLQuery(req, 'MarketsData', marketsDataQuery());
aliasQuery(req, 'Margins', generateMargins());
aliasQuery(req, 'MarketsData', generateMarketsData());
});
cy.setVegaWallet();
cy.visit('/portfolio');
connectVegaWallet();
});
it('"No data to display" should be always displayed', () => {
@@ -0,0 +1,9 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
@@ -1,58 +0,0 @@
import { aliasGQLQuery } from '@vegaprotocol/cypress';
import type { CyHttpMessages } from 'cypress/types/net-stubbing';
import {
accountsQuery,
assetsQuery,
chainIdQuery,
estimateOrderQuery,
fillsQuery,
marginsQuery,
marketDataQuery,
marketDepthQuery,
marketQuery,
marketsCandlesQuery,
marketsDataQuery,
marketsQuery,
networkParamsQuery,
ordersQuery,
positionsQuery,
statisticsQuery,
} from '@vegaprotocol/mock';
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace Cypress {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface Chainable<Subject> {
mockConsole(): void;
}
}
}
const mockPage = (req: CyHttpMessages.IncomingHttpRequest) => {
aliasGQLQuery(req, 'ChainId', chainIdQuery());
aliasGQLQuery(req, 'Statistics', statisticsQuery());
aliasGQLQuery(req, 'Markets', marketsQuery());
aliasGQLQuery(req, 'MarketsCandles', marketsCandlesQuery());
aliasGQLQuery(req, 'MarketsData', marketsDataQuery());
aliasGQLQuery(req, 'MarketData', marketDataQuery());
aliasGQLQuery(req, 'Market', marketQuery());
aliasGQLQuery(req, 'MarketTags', {});
aliasGQLQuery(req, 'EstimateOrder', estimateOrderQuery());
aliasGQLQuery(req, 'MarketNames', {});
aliasGQLQuery(req, 'MarketDepth', marketDepthQuery());
aliasGQLQuery(req, 'Positions', positionsQuery());
aliasGQLQuery(req, 'Margins', marginsQuery());
aliasGQLQuery(req, 'Accounts', accountsQuery());
aliasGQLQuery(req, 'Assets', assetsQuery());
aliasGQLQuery(req, 'SimpleMarkets', marketsQuery());
aliasGQLQuery(req, 'Orders', ordersQuery());
aliasGQLQuery(req, 'Fills', fillsQuery());
aliasGQLQuery(req, 'NetworkParams', networkParamsQuery());
};
export const addMockConsole = () => {
Cypress.Commands.add('mockConsole', () => {
cy.mockGQL(mockPage);
});
};
+33 -4
View File
@@ -1,7 +1,36 @@
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
import '@vegaprotocol/cypress';
import 'cypress-real-events/support';
import registerCypressGrep from '@cypress/grep';
import { addMockConsole } from './console-mock';
// Import commands.js using ES2015 syntax:
import './commands';
import registerCypressGrep from 'cypress-grep';
import { aliasQuery } from '@vegaprotocol/cypress';
registerCypressGrep();
addMockConsole();
before(() => {
// Mock chainId fetch which happens on every page for wallet connection
cy.mockGQL((req) => {
aliasQuery(req, 'ChainId', {
statistics: {
__typename: 'Statistics',
chainId:
Cypress.env('VEGA_ENV').toLowerCase() ||
'vega-fairground-202210041151',
},
});
});
});
@@ -0,0 +1,147 @@
import type { Market } from '@vegaprotocol/market-list';
import { Schema } from '@vegaprotocol/types';
import type { SingleMarketFieldsFragment } from '@vegaprotocol/market-list';
export const protoCandles = [
{ open: '9556163', close: '9587028', __typename: 'Candle' },
{
open: '9587028',
close: '9769899',
__typename: 'Candle',
},
{ open: '9769899', close: '9586292', __typename: 'Candle' },
{
open: '9586292',
close: '9261774',
__typename: 'Candle',
},
{ open: '9261773', close: '9236369', __typename: 'Candle' },
{
open: '9236369',
close: '9226070',
__typename: 'Candle',
},
{ open: '9226077', close: '9233252', __typename: 'Candle' },
{
open: '9249854',
close: '9333038',
__typename: 'Candle',
},
{ open: '9333038', close: '9410371', __typename: 'Candle' },
{
open: '9410371',
close: '9626249',
__typename: 'Candle',
},
{ open: '9626247', close: '9493253', __typename: 'Candle' },
{
open: '9493253',
close: '9309054',
__typename: 'Candle',
},
{ open: '9309054', close: '9378428', __typename: 'Candle' },
{
open: '9378428',
close: '9352996',
__typename: 'Candle',
},
{ open: '9352996', close: '9451142', __typename: 'Candle' },
{
open: '9451142',
close: '9691070',
__typename: 'Candle',
},
{ open: '9691071', close: '9622031', __typename: 'Candle' },
{
open: '9622034',
close: '9519285',
__typename: 'Candle',
},
{ open: '9528904', close: '9671275', __typename: 'Candle' },
{
open: '9671275',
close: '9988454',
__typename: 'Candle',
},
{ open: '9982457', close: '10085537', __typename: 'Candle' },
{
open: '10085537',
close: '9967390',
__typename: 'Candle',
},
{ open: '9967390', close: '9974844', __typename: 'Candle' },
{
open: '9974844',
close: '9940706',
__typename: 'Candle',
},
];
export const protoMarket: Market = {
id: 'ca7768f6de84bf86a21bbb6b0109d9659c81917b0e0339b2c262566c9b581a15',
tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
state: Schema.MarketState.STATE_ACTIVE,
decimalPlaces: 5,
positionDecimalPlaces: 0,
marketTimestamps: {
__typename: 'MarketTimestamps',
close: '',
open: '',
},
fees: {
__typename: 'Fees',
factors: {
__typename: 'FeeFactors',
makerFee: '',
infrastructureFee: '',
liquidityFee: '',
},
},
tradableInstrument: {
instrument: {
id: '',
code: 'AAVEDAI.MF21',
name: 'AAVEDAI Monthly (30 Jun 2022)',
metadata: {
tags: [
'formerly:2839D9B2329C9E70',
'base:AAVE',
'quote:DAI',
'class:fx/crypto',
'monthly',
'sector:defi',
],
__typename: 'InstrumentMetadata',
},
product: {
__typename: 'Future',
quoteName: 'DAI',
settlementAsset: { symbol: 'tDAI', __typename: 'Asset', decimals: 5 },
},
__typename: 'Instrument',
},
__typename: 'TradableInstrument',
},
__typename: 'Market',
};
export const singleMarket: SingleMarketFieldsFragment = {
...protoMarket,
tradableInstrument: {
...protoMarket.tradableInstrument,
instrument: {
...protoMarket.tradableInstrument.instrument,
product: {
...protoMarket.tradableInstrument.instrument.product,
settlementAsset: {
...protoMarket.tradableInstrument.instrument.product.settlementAsset,
id: 'dai-id',
name: 'DAI Name',
},
dataSourceSpecForTradingTermination: {
id: 'oid',
},
},
},
},
};
@@ -0,0 +1,95 @@
import merge from 'lodash/merge';
import type { AccountsQuery } from '@vegaprotocol/accounts';
import { Schema as Types } from '@vegaprotocol/types';
import type { PartialDeep } from 'type-fest';
export const generateAccounts = (
override?: PartialDeep<AccountsQuery>
): AccountsQuery => {
const defaultAccounts: AccountsQuery = {
party: {
__typename: 'Party',
id: Cypress.env('VEGA_PUBLIC_KEY'),
accountsConnection: {
__typename: 'AccountsConnection',
edges: [
{
__typename: 'AccountEdge',
node: {
__typename: 'AccountBalance',
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
balance: '100000000',
market: null,
asset: {
__typename: 'Asset',
id: 'asset-id',
},
},
},
{
__typename: 'AccountEdge',
node: {
__typename: 'AccountBalance',
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
balance: '100000000',
market: {
id: '0604e8c918655474525e1a95367902266ade70d318c2c908f0cca6e3d11dcb13',
__typename: 'Market',
},
asset: {
__typename: 'Asset',
id: 'asset-id-2',
},
},
},
{
__typename: 'AccountEdge',
node: {
__typename: 'AccountBalance',
type: Types.AccountType.ACCOUNT_TYPE_MARGIN,
balance: '1000',
market: {
__typename: 'Market',
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
},
asset: {
__typename: 'Asset',
id: 'asset-id',
},
},
},
{
__typename: 'AccountEdge',
node: {
__typename: 'AccountBalance',
type: Types.AccountType.ACCOUNT_TYPE_MARGIN,
balance: '1000',
market: {
__typename: 'Market',
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
},
asset: {
__typename: 'Asset',
id: 'asset-id-2',
},
},
},
{
__typename: 'AccountEdge',
node: {
__typename: 'AccountBalance',
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
balance: '100000000',
market: null,
asset: {
__typename: 'Asset',
id: 'asset-0',
},
},
},
],
},
},
};
return merge(defaultAccounts, override);
};
@@ -0,0 +1,120 @@
import merge from 'lodash/merge';
import type { AssetsQuery } from '@vegaprotocol/assets';
import { Schema as Types } from '@vegaprotocol/types';
import type { PartialDeep } from 'type-fest';
export const generateAssets = (override?: PartialDeep<AssetsQuery>) => {
const defaultAssets: AssetsQuery = {
assetsConnection: {
edges: [
{
node: {
id: 'asset-id',
symbol: 'tEURO',
decimals: 5,
name: 'Euro',
source: {
__typename: 'ERC20',
contractAddress: '0x0158031158Bb4dF2AD02eAA31e8963E84EA978a4',
lifetimeLimit: '1',
withdrawThreshold: '2',
},
quantum: '',
status: Types.AssetStatus.STATUS_ENABLED,
infrastructureFeeAccount: {
balance: '1',
__typename: 'AccountBalance',
},
globalRewardPoolAccount: {
balance: '2',
__typename: 'AccountBalance',
},
takerFeeRewardAccount: {
balance: '3',
__typename: 'AccountBalance',
},
makerFeeRewardAccount: {
balance: '4',
__typename: 'AccountBalance',
},
lpFeeRewardAccount: {
balance: '5',
__typename: 'AccountBalance',
},
marketProposerRewardAccount: {
balance: '6',
__typename: 'AccountBalance',
},
__typename: 'Asset',
},
},
{
node: {
id: 'asset-id-2',
symbol: 'tDAI',
decimals: 5,
name: 'DAI',
source: {
__typename: 'ERC20',
contractAddress: '0x0158031158Bb4dF2AD02eAA31e8963E84EA978a4',
lifetimeLimit: '1',
withdrawThreshold: '2',
},
quantum: '',
status: Types.AssetStatus.STATUS_ENABLED,
infrastructureFeeAccount: {
balance: '1',
__typename: 'AccountBalance',
},
globalRewardPoolAccount: {
balance: '2',
__typename: 'AccountBalance',
},
takerFeeRewardAccount: {
balance: '3',
__typename: 'AccountBalance',
},
makerFeeRewardAccount: {
balance: '4',
__typename: 'AccountBalance',
},
lpFeeRewardAccount: {
balance: '5',
__typename: 'AccountBalance',
},
marketProposerRewardAccount: {
balance: '6',
__typename: 'AccountBalance',
},
__typename: 'Asset',
},
},
{
node: {
id: 'asset-0',
symbol: 'AST0',
decimals: 5,
name: 'Asto',
source: {
__typename: 'BuiltinAsset',
maxFaucetAmountMint: '3',
},
quantum: '',
status: Types.AssetStatus.STATUS_ENABLED,
infrastructureFeeAccount: {
balance: '0',
__typename: 'AccountBalance',
},
globalRewardPoolAccount: null,
takerFeeRewardAccount: null,
makerFeeRewardAccount: null,
lpFeeRewardAccount: null,
marketProposerRewardAccount: null,
__typename: 'Asset',
},
},
],
},
};
return merge(defaultAssets, override);
};
@@ -0,0 +1,16 @@
import type { ChainIdQuery } from '@vegaprotocol/react-helpers';
import merge from 'lodash/merge';
import type { PartialDeep } from 'type-fest';
export const generateChainId = (
override?: PartialDeep<ChainIdQuery>
): ChainIdQuery => {
const defaultResult = {
statistics: {
__typename: 'Statistics',
chainId: Cypress.env('VEGA_ENV').toLowerCase() || 'test-chain-id',
},
};
return merge(defaultResult, override);
};
@@ -0,0 +1,52 @@
import type { DealTicketQuery } from '@vegaprotocol/deal-ticket';
import { Schema } from '@vegaprotocol/types';
import merge from 'lodash/merge';
import type { PartialDeep } from 'type-fest';
export const generateDealTicket = (
override?: PartialDeep<DealTicketQuery>
): DealTicketQuery => {
const defaultResult: DealTicketQuery = {
market: {
id: 'ca7768f6de84bf86a21bbb6b0109d9659c81917b0e0339b2c262566c9b581a15',
decimalPlaces: 5,
positionDecimalPlaces: 0,
state: Schema.MarketState.STATE_ACTIVE,
tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
tradableInstrument: {
instrument: {
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
name: 'AAVEDAI Monthly (30 Jun 2022)',
product: {
quoteName: 'DAI',
settlementAsset: {
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
symbol: 'tDAI',
name: 'tDAI TEST',
decimals: 5,
__typename: 'Asset',
},
__typename: 'Future',
},
__typename: 'Instrument',
},
__typename: 'TradableInstrument',
},
depth: {
lastTrade: { price: '9893006', __typename: 'Trade' },
__typename: 'MarketDepth',
},
fees: {
factors: {
makerFee: '0.0002',
infrastructureFee: '0.0005',
liquidityFee: '0.001',
__typename: 'FeeFactors',
},
__typename: 'Fees',
},
__typename: 'Market',
},
};
return merge(defaultResult, override);
};
@@ -0,0 +1,17 @@
export const generateEstimateOrder = () => {
return {
estimateOrder: {
fee: {
__typename: 'TradeFee',
makerFee: '100000',
liquidityFee: '100000',
infrastructureFee: '100000',
},
marginLevels: {
initialLevel: '2844054.80937741220203',
__typename: 'MarginLevels',
},
__typename: 'OrderEstimate',
},
};
};
@@ -0,0 +1,111 @@
import type { FillsQuery, FillFieldsFragment } from '@vegaprotocol/fills';
import { Schema } from '@vegaprotocol/types';
import merge from 'lodash/merge';
import type { PartialDeep } from 'type-fest';
export const generateFills = (
override?: PartialDeep<FillsQuery>
): FillsQuery => {
const fills: FillFieldsFragment[] = [
generateFill({
buyer: {
id: Cypress.env('VEGA_PUBLIC_KEY'),
},
}),
generateFill({
id: '1',
seller: {
id: Cypress.env('VEGA_PUBLIC_KEY'),
},
aggressor: Schema.Side.SIDE_SELL,
buyerFee: {
infrastructureFee: '5000',
},
market: {
id: 'market-1',
},
}),
generateFill({
id: '2',
seller: {
id: Cypress.env('VEGA_PUBLIC_KEY'),
},
aggressor: Schema.Side.SIDE_BUY,
}),
generateFill({
id: '3',
aggressor: Schema.Side.SIDE_SELL,
market: {
id: 'market-2',
},
buyer: {
id: Cypress.env('VEGA_PUBLIC_KEY'),
},
}),
];
const defaultResult: FillsQuery = {
party: {
id: 'buyer-id',
tradesConnection: {
__typename: 'TradeConnection',
edges: fills.map((f) => {
return {
__typename: 'TradeEdge',
node: f,
cursor: '3',
};
}),
pageInfo: {
__typename: 'PageInfo',
startCursor: '1',
endCursor: '2',
hasNextPage: false,
hasPreviousPage: false,
},
},
__typename: 'Party',
},
};
return merge(defaultResult, override);
};
export const generateFill = (override?: PartialDeep<FillFieldsFragment>) => {
const defaultFill: FillFieldsFragment = {
__typename: 'Trade',
id: '0',
createdAt: new Date().toISOString(),
price: '10000000',
size: '50000',
buyOrder: 'buy-order',
sellOrder: 'sell-order',
aggressor: Schema.Side.SIDE_BUY,
buyer: {
__typename: 'Party',
id: 'buyer-id',
},
seller: {
__typename: 'Party',
id: 'seller-id',
},
buyerFee: {
__typename: 'TradeFee',
makerFee: '100',
infrastructureFee: '100',
liquidityFee: '100',
},
sellerFee: {
__typename: 'TradeFee',
makerFee: '200',
infrastructureFee: '200',
liquidityFee: '200',
},
market: {
__typename: 'Market',
id: 'market-0',
},
};
return merge(defaultFill, override);
};
@@ -0,0 +1,210 @@
import merge from 'lodash/merge';
import type { PartialDeep } from 'type-fest';
// eslint-disable-next-line @nrwl/nx/enforce-module-boundaries
import type { MarketDepthQuery } from '../../../../../libs/market-depth/src/lib/__generated___/MarketDepth';
export const generateMarketDepth = (
override?: PartialDeep<MarketDepthQuery>
): MarketDepthQuery => {
const defaultResult: MarketDepthQuery = {
market: {
id: 'a46bd7e5277087723b7ab835844dec3cef8b4445738101269624bf5537d5d423',
depth: {
sell: [
{
price: '9893007',
volume: '3',
numberOfOrders: '3',
__typename: 'PriceLevel',
},
{
price: '9893010',
volume: '4',
numberOfOrders: '4',
__typename: 'PriceLevel',
},
{
price: '9893012',
volume: '1',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9893015',
volume: '1',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9893017',
volume: '2',
numberOfOrders: '2',
__typename: 'PriceLevel',
},
{
price: '9893021',
volume: '4',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9893025',
volume: '5',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9893125',
volume: '4',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9893135',
volume: '2',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9893165',
volume: '5',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9893175',
volume: '3',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9893185',
volume: '3',
numberOfOrders: '3',
__typename: 'PriceLevel',
},
{
price: '9894185',
volume: '1',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9894585',
volume: '1',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9895585',
volume: '4',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9896585',
volume: '2',
numberOfOrders: '2',
__typename: 'PriceLevel',
},
],
buy: [
{
price: '9893005',
volume: '4',
numberOfOrders: '3',
__typename: 'PriceLevel',
},
{
price: '9893003',
volume: '2',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9893001',
volume: '1',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9892006',
volume: '3',
numberOfOrders: '2',
__typename: 'PriceLevel',
},
{
price: '9891006',
volume: '2',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9891001',
volume: '1',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9890101',
volume: '2',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9890091',
volume: '5',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9890081',
volume: '4',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9890050',
volume: '2',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9890040',
volume: '6',
numberOfOrders: '3',
__typename: 'PriceLevel',
},
{
price: '9890030',
volume: '6',
numberOfOrders: '2',
__typename: 'PriceLevel',
},
{
price: '9890021',
volume: '3',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9890011',
volume: '1',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
{
price: '9890001',
volume: '11',
numberOfOrders: '1',
__typename: 'PriceLevel',
},
],
sequenceNumber: '1661773865550746910',
__typename: 'MarketDepth',
},
__typename: 'Market',
},
};
return merge(defaultResult, override);
};
@@ -0,0 +1,9 @@
export const generateMarketMarkPrice = () => {
return {
market: {
decimalPlaces: 5,
data: { markPrice: '692748', __typename: 'MarketData' },
__typename: 'Market',
},
};
};
@@ -0,0 +1,136 @@
import { protoMarket } from './commons';
export const generateMarketNames = () => {
return {
markets: [
{ ...protoMarket },
{
id: '1d7ddf67dac4924db03f5bf58571a7bcb1908d70c66580467717aabc5345b68a',
state: 'STATE_SUSPENDED',
tradableInstrument: {
instrument: {
code: 'AAPL.MF21',
name: 'Apple Monthly (30 Jun 2022)',
metadata: {
tags: [
'formerly:4899E01009F1A721',
'quote:USD',
'ticker:AAPL',
'class:equities/single-stock-futures',
'sector:tech',
'listing_venue:NASDAQ',
'country:US',
],
__typename: 'InstrumentMetadata',
},
product: { quoteName: 'USD', __typename: 'Future' },
__typename: 'Instrument',
},
__typename: 'TradableInstrument',
},
__typename: 'Market',
},
{
id: '87ae87cd3244fc1fab4b0e2dad2437879864192bb969f3109b69293421644c8b',
state: 'STATE_SUSPENDED',
tradableInstrument: {
instrument: {
code: 'TSLA.QM21',
name: 'Tesla Quarterly (30 Jun 2022)',
metadata: {
tags: [
'formerly:5A86B190C384997F',
'quote:EURO',
'ticker:TSLA',
'class:equities/single-stock-futures',
'sector:tech',
'listing_venue:NASDAQ',
'country:US',
],
__typename: 'InstrumentMetadata',
},
product: { quoteName: 'EURO', __typename: 'Future' },
__typename: 'Instrument',
},
__typename: 'TradableInstrument',
},
__typename: 'Market',
},
{
id: '69205712a854f1bbfb69fa3d11b60e01a1e249bafb5ece88115e7451e8ef07b3',
state: 'STATE_SUSPENDED',
tradableInstrument: {
instrument: {
code: 'BTCUSD.MF21',
name: 'BTCUSD Monthly (30 Jun 2022)',
metadata: {
tags: [
'formerly:076BB86A5AA41E3E',
'base:BTC',
'quote:USD',
'class:fx/crypto',
'monthly',
'sector:crypto',
],
__typename: 'InstrumentMetadata',
},
product: { quoteName: 'USD', __typename: 'Future' },
__typename: 'Instrument',
},
__typename: 'TradableInstrument',
},
__typename: 'Market',
},
{
id: 'ethbtc-quaterly',
state: 'STATE_ACTIVE',
tradableInstrument: {
instrument: {
code: 'ETHBTC.QM21',
name: 'ETHBTC Quarterly (30 Jun 2022)',
metadata: {
tags: [
'formerly:1F0BB6EB5703B099',
'base:ETH',
'quote:BTC',
'class:fx/crypto',
'quarterly',
'sector:crypto',
],
__typename: 'InstrumentMetadata',
},
product: { quoteName: 'BTC', __typename: 'Future' },
__typename: 'Instrument',
},
__typename: 'TradableInstrument',
},
__typename: 'Market',
},
{
id: '3c62b2714c4332d1a689a5352bff090e6aabccfd6bd87ce018936b38372530c9',
state: 'STATE_ACTIVE',
tradableInstrument: {
instrument: {
code: 'UNIDAI.MF21',
name: 'UNIDAI Monthly (30 Jun 2022)',
metadata: {
tags: [
'formerly:3C58ED2A4A6C5D7E',
'base:UNI',
'quote:DAI',
'class:fx/crypto',
'monthly',
'sector:defi',
],
__typename: 'InstrumentMetadata',
},
product: { quoteName: 'DAI', __typename: 'Future' },
__typename: 'Instrument',
},
__typename: 'TradableInstrument',
},
__typename: 'Market',
},
],
};
};
@@ -0,0 +1,72 @@
import type { MarketPositionsQuery } from '@vegaprotocol/deal-ticket';
import { Schema } from '@vegaprotocol/types';
export const generateMarketPositions = (): MarketPositionsQuery => {
return {
party: {
id: '2e1ef32e5804e14232406aebaad719087d326afa5c648b7824d0823d8a46c8d1',
accountsConnection: {
__typename: 'AccountsConnection',
edges: [
{
__typename: 'AccountEdge',
node: {
__typename: 'AccountBalance',
type: Schema.AccountType.ACCOUNT_TYPE_GENERAL,
asset: {
decimals: 5,
},
balance: '400000000000000000000',
market: {
id: '2751c508f9759761f912890f37fb3f97a00300bf7685c02a56a86e05facfe221',
__typename: 'Market',
},
},
},
{
__typename: 'AccountEdge',
node: {
type: Schema.AccountType.ACCOUNT_TYPE_MARGIN,
asset: {
decimals: 5,
},
balance: '265329',
market: {
id: 'ca7768f6de84bf86a21bbb6b0109d9659c81917b0e0339b2c262566c9b581a15',
__typename: 'Market',
},
},
},
],
},
positionsConnection: {
edges: [
{
node: {
openVolume: '3',
market: {
id: '2751c508f9759761f912890f37fb3f97a00300bf7685c02a56a86e05facfe221',
__typename: 'Market',
},
__typename: 'Position',
},
__typename: 'PositionEdge',
},
{
node: {
openVolume: '12',
market: {
id: 'ca7768f6de84bf86a21bbb6b0109d9659c81917b0e0339b2c262566c9b581a15',
__typename: 'Market',
},
__typename: 'Position',
},
__typename: 'PositionEdge',
},
],
__typename: 'PositionConnection',
},
__typename: 'Party',
},
};
};
@@ -0,0 +1,25 @@
export const generateMarketTags = () => {
return {
market: {
tradableInstrument: {
instrument: {
metadata: {
tags: [
'formerly:2839D9B2329C9E70',
'base:AAVE',
'quote:DAI',
'class:fx/crypto',
'monthly',
'sector:defi',
'settlement:2022-08-01',
],
__typename: 'InstrumentMetadata',
},
__typename: 'Instrument',
},
__typename: 'TradableInstrument',
},
__typename: 'Market',
},
};
};
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,143 @@
import merge from 'lodash/merge';
import type { PartialDeep } from 'type-fest';
import type { OrdersQuery, OrderFieldsFragment } from '@vegaprotocol/orders';
import { Schema } from '@vegaprotocol/types';
export const generateOrders = (
override?: PartialDeep<OrdersQuery>
): OrdersQuery => {
const orders: OrderFieldsFragment[] = [
{
__typename: 'Order',
id: '066468C06549101DAF7BC51099E1412A0067DC08C246B7D8013C9D0CBF1E8EE7',
market: {
__typename: 'Market',
id: 'market-0',
},
size: '10',
type: Schema.OrderType.TYPE_LIMIT,
status: Schema.OrderStatus.STATUS_FILLED,
side: Schema.Side.SIDE_BUY,
remaining: '0',
price: '20000000',
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
createdAt: new Date(2020, 1, 30).toISOString(),
updatedAt: null,
expiresAt: null,
rejectionReason: null,
liquidityProvision: null,
peggedOrder: null,
},
{
__typename: 'Order',
id: '48DB6767E4E4E0F649C5A13ABFADE39F8451C27DA828DAF14B7A1E8E5EBDAD99',
market: {
__typename: 'Market',
id: 'market-1',
},
size: '1',
type: Schema.OrderType.TYPE_LIMIT,
status: Schema.OrderStatus.STATUS_FILLED,
side: Schema.Side.SIDE_BUY,
remaining: '0',
price: '100',
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
createdAt: new Date(2020, 1, 29).toISOString(),
updatedAt: null,
expiresAt: null,
rejectionReason: null,
liquidityProvision: null,
peggedOrder: null,
},
{
__typename: 'Order',
id: '4e93702990712c41f6995fcbbd94f60bb372ad12d64dfa7d96d205c49f790336',
market: {
__typename: 'Market',
id: 'market-2',
},
size: '1',
type: Schema.OrderType.TYPE_LIMIT,
status: Schema.OrderStatus.STATUS_FILLED,
side: Schema.Side.SIDE_BUY,
remaining: '0',
price: '20000',
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
createdAt: new Date(2020, 1, 28).toISOString(),
updatedAt: null,
expiresAt: null,
rejectionReason: null,
liquidityProvision: null,
peggedOrder: null,
},
{
__typename: 'Order',
id: '94737d2bafafa4bc3b80a56ef084ae52a983b91aa067c31e243c61a0f962a836',
market: {
__typename: 'Market',
id: 'market-3',
},
size: '1',
type: Schema.OrderType.TYPE_LIMIT,
status: Schema.OrderStatus.STATUS_ACTIVE,
side: Schema.Side.SIDE_BUY,
remaining: '0',
price: '100000',
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
createdAt: new Date(2020, 1, 27).toISOString(),
updatedAt: null,
expiresAt: null,
rejectionReason: null,
liquidityProvision: null,
peggedOrder: null,
},
{
__typename: 'Order',
id: '94aead3ca92dc932efcb503631b03a410e2a5d4606cae6083e2406dc38e52f78',
market: {
__typename: 'Market',
id: 'market-3',
},
size: '10',
type: Schema.OrderType.TYPE_LIMIT,
status: Schema.OrderStatus.STATUS_PARTIALLY_FILLED,
side: Schema.Side.SIDE_SELL,
remaining: '3',
price: '100000',
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
createdAt: new Date(2020, 1, 27).toISOString(),
updatedAt: null,
expiresAt: null,
liquidityProvision: null,
peggedOrder: null,
rejectionReason: null,
},
];
const defaultResult: OrdersQuery = {
party: {
id: Cypress.env('VEGA_PUBLIC_KEY'),
ordersConnection: {
__typename: 'OrderConnection',
edges: orders.map((f) => {
return {
__typename: 'OrderEdge',
node: f,
cursor: f.id,
};
}),
pageInfo: {
__typename: 'PageInfo',
startCursor:
'066468C06549101DAF7BC51099E1412A0067DC08C246B7D8013C9D0CBF1E8EE7',
endCursor:
'94737d2bafafa4bc3b80a56ef084ae52a983b91aa067c31e243c61a0f962a836',
hasNextPage: false,
hasPreviousPage: false,
},
},
__typename: 'Party',
},
};
return merge(defaultResult, override);
};
@@ -0,0 +1,81 @@
import merge from 'lodash/merge';
import type { PartyBalanceQuery } from '@vegaprotocol/deal-ticket';
import type { PartialDeep } from 'type-fest';
import { Schema as Types } from '@vegaprotocol/types';
export const generatePartyBalance = (
override?: PartialDeep<PartyBalanceQuery>
): PartyBalanceQuery => {
const defaultResult: PartyBalanceQuery = {
party: {
accountsConnection: {
__typename: 'AccountsConnection',
edges: [
{
__typename: 'AccountEdge',
node: {
balance: '88474051',
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
asset: {
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
symbol: 'tDAI',
name: 'tDAI TEST',
decimals: 5,
__typename: 'Asset',
},
__typename: 'AccountBalance',
},
},
{
__typename: 'AccountEdge',
node: {
balance: '100000000',
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
asset: {
id: '8b52d4a3a4b0ffe733cddbc2b67be273816cfeb6ca4c8b339bac03ffba08e4e4',
symbol: 'tEURO',
name: 'tEURO TEST',
decimals: 5,
__typename: 'Asset',
},
__typename: 'AccountBalance',
},
},
{
__typename: 'AccountEdge',
node: {
balance: '3412867',
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
asset: {
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
symbol: 'tDAI',
name: 'tDAI TEST',
decimals: 5,
__typename: 'Asset',
},
__typename: 'AccountBalance',
},
},
{
__typename: 'AccountEdge',
node: {
balance: '70007',
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
asset: {
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
symbol: 'tDAI',
name: 'tDAI TEST',
decimals: 5,
__typename: 'Asset',
},
__typename: 'AccountBalance',
},
},
],
},
__typename: 'Party',
},
};
return merge(defaultResult, override);
};
@@ -0,0 +1,40 @@
import type { PartyMarketDataQuery } from '@vegaprotocol/deal-ticket';
import { Schema as Types } from '@vegaprotocol/types';
export const generatePartyMarketData = (): PartyMarketDataQuery => {
return {
party: {
id: '2e1ef32e5804e14232406aebaad719087d326afa5c648b7824d0823d8a46c8d1',
accountsConnection: {
__typename: 'AccountsConnection',
edges: [
{
__typename: 'AccountEdge',
node: {
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
balance: '1200000',
asset: { id: 'fBTC', decimals: 5, __typename: 'Asset' },
market: null,
__typename: 'AccountBalance',
},
},
{
__typename: 'AccountEdge',
node: {
__typename: 'AccountBalance',
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
balance: '0.000000001',
asset: {
__typename: 'Asset',
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
decimals: 0,
},
},
},
],
},
marginsConnection: { edges: null, __typename: 'MarginConnection' },
__typename: 'Party',
},
};
};
@@ -0,0 +1,145 @@
import merge from 'lodash/merge';
import type { PartialDeep } from 'type-fest';
import type {
PositionsQuery,
PositionFieldsFragment,
MarginsQuery,
} from '@vegaprotocol/positions';
export const generatePositions = (
override?: PartialDeep<PositionsQuery>
): PositionsQuery => {
const nodes: PositionFieldsFragment[] = [
{
__typename: 'Position',
realisedPNL: '0',
openVolume: '6',
unrealisedPNL: '895000',
averageEntryPrice: '1129935',
updatedAt: '2022-07-28T15:09:34.441143Z',
market: {
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
__typename: 'Market',
},
},
{
__typename: 'Position',
realisedPNL: '100',
openVolume: '20',
unrealisedPNL: '895000',
averageEntryPrice: '8509338',
updatedAt: '2022-07-28T15:09:34.441143Z',
market: {
id: '0604e8c918655474525e1a95367902266ade70d318c2c908f0cca6e3d11dcb13',
__typename: 'Market',
},
},
{
realisedPNL: '0',
openVolume: '1',
unrealisedPNL: '-22519',
averageEntryPrice: '84400088',
updatedAt: '2022-07-28T14:53:54.725477Z',
market: {
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
__typename: 'Market',
},
__typename: 'Position',
},
];
const defaultResult: PositionsQuery = {
party: {
__typename: 'Party',
id: Cypress.env('VEGA_PUBLIC_KEY'),
positionsConnection: {
__typename: 'PositionConnection',
edges: nodes.map((node) => {
return {
__typename: 'PositionEdge',
node,
};
}),
},
},
};
return merge(defaultResult, override);
};
export const emptyPositions = (): PositionsQuery => {
return {
party: {
id: Cypress.env('VEGA_PUBLIC_KEY'),
positionsConnection: { edges: null, __typename: 'PositionConnection' },
__typename: 'Party',
},
};
};
export const generateMargins = (): MarginsQuery => {
return {
party: {
id: Cypress.env('VEGA_PUBLIC_KEY'),
marginsConnection: {
edges: [
{
node: {
__typename: 'MarginLevels',
maintenanceLevel: '0',
searchLevel: '0',
initialLevel: '0',
collateralReleaseLevel: '0',
market: {
__typename: 'Market',
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
},
asset: {
__typename: 'Asset',
id: 'tDAI-id',
},
},
},
{
node: {
__typename: 'MarginLevels',
maintenanceLevel: '0',
searchLevel: '0',
initialLevel: '0',
collateralReleaseLevel: '0',
market: {
__typename: 'Market',
id: '0604e8c918655474525e1a95367902266ade70d318c2c908f0cca6e3d11dcb13',
},
asset: {
__typename: 'Asset',
id: 'tDAI-id',
},
},
__typename: 'MarginEdge',
},
{
node: {
__typename: 'MarginLevels',
maintenanceLevel: '0',
searchLevel: '0',
initialLevel: '0',
collateralReleaseLevel: '0',
market: {
__typename: 'Market',
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
},
asset: {
__typename: 'Asset',
id: 'tEURO-id',
},
},
__typename: 'MarginEdge',
},
],
__typename: 'MarginConnection',
},
__typename: 'Party',
},
};
};
@@ -0,0 +1,17 @@
import type { StatisticsQuery } from '@vegaprotocol/environment';
import merge from 'lodash/merge';
import type { PartialDeep } from 'type-fest';
export const generateStatistics = (
override?: PartialDeep<StatisticsQuery>
): StatisticsQuery => {
const defaultResult = {
statistics: {
__typename: 'Statistics',
chainId: Cypress.env('VEGA_ENV').toLowerCase() || 'test-chain-id',
blockHeight: '11',
},
};
return merge(defaultResult, override);
};
@@ -0,0 +1,12 @@
export const connectVegaWallet = () => {
const form = 'rest-connector-form';
const walletName = Cypress.env('TRADING_TEST_VEGA_WALLET_NAME');
const walletPassphrase = Cypress.env('TRADING_TEST_VEGA_WALLET_PASSPHRASE');
cy.getByTestId('connect-vega-wallet').click();
cy.getByTestId('connectors-list')
.find('[data-testid="connector-gui"]')
.click();
cy.getByTestId(form).find('#wallet').click().type(walletName);
cy.getByTestId(form).find('#passphrase').click().type(walletPassphrase);
cy.getByTestId('rest-connector-form').find('button[type=submit]').click();
};
+2 -2
View File
@@ -7,7 +7,7 @@
"allowSyntheticDefaultImports": true,
"outDir": "../../dist/out-tsc",
"allowJs": true,
"types": ["cypress", "node", "cypress-real-events", "@cypress/grep"]
"types": ["cypress", "node", "cypress-real-events", "cypress-grep"]
},
"include": ["src/**/*.ts", "src/**/*.js", "./declaration.d.ts", "index.d.ts"]
"include": ["src/**/*.ts", "src/**/*.js", "./declaration.d.ts"]
}
+1 -1
View File
@@ -19,7 +19,7 @@ NX_DEPLOY_URL=$DEPLOY_URL
NX_DEPLOY_PRIME_URL=$DEPLOY_PRIME_URL
NX_VEGA_CONFIG_URL="https://static.vega.xyz/assets/stagnet3-network.json"
NX_VEGA_ENV=STAGNET3
NX_VEGA_URL="https://api.stagnet3.vega.xyz/graphql"
NX_VEGA_URL="https://api.n01.stagnet3.vega.xyz/graphql"
NX_VEGA_WALLET_URL=http://localhost:1789
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
+1 -1
View File
@@ -1,6 +1,6 @@
# 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_URL=https://api.n01.stagnet3.vega.xyz/graphql
NX_VEGA_ENV=STAGNET3
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
+23 -18
View File
@@ -1,5 +1,7 @@
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import { ThemeContext } from '@vegaprotocol/react-helpers';
import { useThemeSwitcher } from '@vegaprotocol/react-helpers';
import { EnvironmentProvider, NetworkLoader } from '@vegaprotocol/environment';
import {
VegaConnectDialog,
@@ -16,7 +18,8 @@ import useLocalValues from './hooks/use-local-values';
import type { InMemoryCacheConfig } from '@apollo/client';
function App() {
const localValues = useLocalValues();
const [theme, toggleTheme] = useThemeSwitcher();
const localValues = useLocalValues(theme, toggleTheme);
const {
vegaWalletDialog,
menu: { setMenuOpen },
@@ -53,23 +56,25 @@ function App() {
return (
<EnvironmentProvider>
<NetworkLoader cache={cacheConfig}>
<VegaWalletProvider>
<LocalContext.Provider value={localValues}>
<AppLoader>
<div className="max-h-full min-h-full dark:bg-lite-black dark:text-neutral-200 bg-white text-neutral-800 grid grid-rows-[min-content,1fr]">
<Header />
<Main />
<VegaConnectDialog connectors={Connectors} />
<VegaManageDialog
dialogOpen={vegaWalletDialog.manage}
setDialogOpen={vegaWalletDialog.setManage}
/>
</div>
</AppLoader>
</LocalContext.Provider>
</VegaWalletProvider>
</NetworkLoader>
<ThemeContext.Provider value={theme}>
<NetworkLoader cache={cacheConfig}>
<VegaWalletProvider>
<LocalContext.Provider value={localValues}>
<AppLoader>
<div className="max-h-full min-h-full dark:bg-lite-black dark:text-neutral-200 bg-white text-neutral-800 grid grid-rows-[min-content,1fr]">
<Header />
<Main />
<VegaConnectDialog connectors={Connectors} />
<VegaManageDialog
dialogOpen={vegaWalletDialog.manage}
setDialogOpen={vegaWalletDialog.setManage}
/>
</div>
</AppLoader>
</LocalContext.Provider>
</VegaWalletProvider>
</NetworkLoader>
</ThemeContext.Provider>
</EnvironmentProvider>
);
}
@@ -1,11 +1,14 @@
import React, { forwardRef, useCallback, useMemo, useRef } from 'react';
import React, {
forwardRef,
useCallback,
useContext,
useMemo,
useRef,
} from 'react';
import classNames from 'classnames';
import type { AgGridReact } from 'ag-grid-react';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
import {
useScreenDimensions,
useThemeSwitcher,
} from '@vegaprotocol/react-helpers';
import { ThemeContext, useScreenDimensions } from '@vegaprotocol/react-helpers';
import type {
GridOptions,
GetRowIdParams,
@@ -40,7 +43,7 @@ const ConsoleLiteGrid = <T extends { id?: string }>(
) => {
const { isMobile, screenSize } = useScreenDimensions();
const gridRef = useRef<AgGridReact | null>(null);
const { theme } = useThemeSwitcher();
const theme = useContext(ThemeContext);
const handleOnGridReady = useCallback(() => {
(
(ref as React.RefObject<AgGridReact>) || gridRef
@@ -0,0 +1,18 @@
query PartyBalanceQuery($partyId: ID!) {
party(id: $partyId) {
accountsConnection {
edges {
node {
type
balance
asset {
id
symbol
name
decimals
}
}
}
}
}
}
@@ -1,54 +1,51 @@
import * as Types from '@vegaprotocol/types';
/* tslint:disable */
/* eslint-disable */
// @generated
// This file was automatically generated and should not be edited.
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type MarketTagsQueryVariables = Types.Exact<{
marketId: Types.Scalars['ID'];
}>;
// ====================================================
// GraphQL query operation: MarketTags
// ====================================================
export type MarketTagsQuery = { __typename?: 'Query', market?: { __typename?: 'Market', tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', metadata: { __typename?: 'InstrumentMetadata', tags?: Array<string> | null } } } } | null };
export const MarketTagsDocument = gql`
query MarketTags($marketId: ID!) {
market(id: $marketId) {
tradableInstrument {
instrument {
metadata {
tags
}
}
}
}
export interface MarketTags_market_tradableInstrument_instrument_metadata {
__typename: "InstrumentMetadata";
/**
* An arbitrary list of tags to associated to associate to the Instrument (string list)
*/
tags: string[] | null;
}
`;
/**
* __useMarketTagsQuery__
*
* To run a query within a React component, call `useMarketTagsQuery` and pass it any options that fit your needs.
* When your component renders, `useMarketTagsQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useMarketTagsQuery({
* variables: {
* marketId: // value for 'marketId'
* },
* });
*/
export function useMarketTagsQuery(baseOptions: Apollo.QueryHookOptions<MarketTagsQuery, MarketTagsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<MarketTagsQuery, MarketTagsQueryVariables>(MarketTagsDocument, options);
}
export function useMarketTagsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<MarketTagsQuery, MarketTagsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<MarketTagsQuery, MarketTagsQueryVariables>(MarketTagsDocument, options);
}
export type MarketTagsQueryHookResult = ReturnType<typeof useMarketTagsQuery>;
export type MarketTagsLazyQueryHookResult = ReturnType<typeof useMarketTagsLazyQuery>;
export type MarketTagsQueryResult = Apollo.QueryResult<MarketTagsQuery, MarketTagsQueryVariables>;
export interface MarketTags_market_tradableInstrument_instrument {
__typename: "Instrument";
/**
* Metadata for this instrument
*/
metadata: MarketTags_market_tradableInstrument_instrument_metadata;
}
export interface MarketTags_market_tradableInstrument {
__typename: "TradableInstrument";
/**
* An instance of, or reference to, a fully specified instrument.
*/
instrument: MarketTags_market_tradableInstrument_instrument;
}
export interface MarketTags_market {
__typename: "Market";
/**
* An instance of, or reference to, a tradable instrument.
*/
tradableInstrument: MarketTags_market_tradableInstrument;
}
export interface MarketTags {
/**
* An instrument that is trading on the Vega network
*/
market: MarketTags_market | null;
}
export interface MarketTagsVariables {
marketId: string;
}
@@ -0,0 +1,54 @@
import { Schema as Types } from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type MarketTagsQueryVariables = Types.Exact<{
marketId: Types.Scalars['ID'];
}>;
export type MarketTagsQuery = { __typename?: 'Query', market?: { __typename?: 'Market', tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', metadata: { __typename?: 'InstrumentMetadata', tags?: Array<string> | null } } } } | null };
export const MarketTagsDocument = gql`
query MarketTags($marketId: ID!) {
market(id: $marketId) {
tradableInstrument {
instrument {
metadata {
tags
}
}
}
}
}
`;
/**
* __useMarketTagsQuery__
*
* To run a query within a React component, call `useMarketTagsQuery` and pass it any options that fit your needs.
* When your component renders, `useMarketTagsQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useMarketTagsQuery({
* variables: {
* marketId: // value for 'marketId'
* },
* });
*/
export function useMarketTagsQuery(baseOptions: Apollo.QueryHookOptions<MarketTagsQuery, MarketTagsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<MarketTagsQuery, MarketTagsQueryVariables>(MarketTagsDocument, options);
}
export function useMarketTagsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<MarketTagsQuery, MarketTagsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<MarketTagsQuery, MarketTagsQueryVariables>(MarketTagsDocument, options);
}
export type MarketTagsQueryHookResult = ReturnType<typeof useMarketTagsQuery>;
export type MarketTagsLazyQueryHookResult = ReturnType<typeof useMarketTagsLazyQuery>;
export type MarketTagsQueryResult = Apollo.QueryResult<MarketTagsQuery, MarketTagsQueryVariables>;
@@ -0,0 +1,61 @@
import { Schema as Types } from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type PartyBalanceQueryQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
}>;
export type PartyBalanceQueryQuery = { __typename?: 'Query', party?: { __typename?: 'Party', accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number } } } | null> | null } | null } | null };
export const PartyBalanceQueryDocument = gql`
query PartyBalanceQuery($partyId: ID!) {
party(id: $partyId) {
accountsConnection {
edges {
node {
type
balance
asset {
id
symbol
name
decimals
}
}
}
}
}
}
`;
/**
* __usePartyBalanceQueryQuery__
*
* To run a query within a React component, call `usePartyBalanceQueryQuery` and pass it any options that fit your needs.
* When your component renders, `usePartyBalanceQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = usePartyBalanceQueryQuery({
* variables: {
* partyId: // value for 'partyId'
* },
* });
*/
export function usePartyBalanceQueryQuery(baseOptions: Apollo.QueryHookOptions<PartyBalanceQueryQuery, PartyBalanceQueryQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<PartyBalanceQueryQuery, PartyBalanceQueryQueryVariables>(PartyBalanceQueryDocument, options);
}
export function usePartyBalanceQueryLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<PartyBalanceQueryQuery, PartyBalanceQueryQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<PartyBalanceQueryQuery, PartyBalanceQueryQueryVariables>(PartyBalanceQueryDocument, options);
}
export type PartyBalanceQueryQueryHookResult = ReturnType<typeof usePartyBalanceQueryQuery>;
export type PartyBalanceQueryLazyQueryHookResult = ReturnType<typeof usePartyBalanceQueryLazyQuery>;
export type PartyBalanceQueryQueryResult = Apollo.QueryResult<PartyBalanceQueryQuery, PartyBalanceQueryQueryVariables>;
@@ -1,36 +1,38 @@
import React from 'react';
import { render } from '@testing-library/react';
import { MockedProvider } from '@apollo/client/testing';
import type { MarketDealTicketAsset } from '@vegaprotocol/market-list';
import type {
AccountFragment,
DealTicketMarketFragment,
} from '@vegaprotocol/deal-ticket';
import { DealTicketBalance } from './deal-ticket-balance';
import { Schema } from '@vegaprotocol/types';
jest.mock('@vegaprotocol/wallet', () => ({
...jest.requireActual('@vegaprotocol/wallet'),
useVegaWallet: jest.fn().mockReturnValue('wallet-pub-key'),
}));
const tDAI: DealTicketMarketFragment['tradableInstrument']['instrument']['product']['settlementAsset'] =
{
__typename: 'Asset',
id: '1',
symbol: 'tDAI',
name: 'TDAI',
decimals: 2,
};
const tDAI: MarketDealTicketAsset = {
__typename: 'Asset',
id: '1',
symbol: 'tDAI',
name: 'TDAI',
decimals: 2,
};
let mockAccountBalance: {
accountBalance: string;
accountDecimals: number | null;
} = { accountBalance: '1000000', accountDecimals: 2 };
jest.mock('@vegaprotocol/accounts', () => ({
...jest.requireActual('@vegaprotocol/accounts'),
useAccountBalance: jest.fn(() => mockAccountBalance),
}));
const accounts: AccountFragment[] = [
{
__typename: 'AccountBalance',
type: Schema.AccountType.ACCOUNT_TYPE_GENERAL,
balance: '1000000',
asset: tDAI,
},
];
describe('DealTicketBalance', function () {
it('should render the balance', () => {
const { getByText, getByRole } = render(
<DealTicketBalance settlementAsset={tDAI} isWalletConnected />,
{ wrapper: MockedProvider }
<DealTicketBalance
settlementAsset={tDAI}
accounts={accounts}
isWalletConnected
/>
);
expect(getByRole('complementary')).toHaveAccessibleName('tDAI Balance');
@@ -40,8 +42,11 @@ describe('DealTicketBalance', function () {
it('should prompt to connect wallet', () => {
const { getByText } = render(
<DealTicketBalance settlementAsset={tDAI} isWalletConnected={false} />,
{ wrapper: MockedProvider }
<DealTicketBalance
settlementAsset={tDAI}
accounts={accounts}
isWalletConnected={false}
/>
);
expect(
@@ -50,10 +55,12 @@ describe('DealTicketBalance', function () {
});
it('should display zero balance', () => {
mockAccountBalance = { accountBalance: '', accountDecimals: null };
const { getByText } = render(
<DealTicketBalance settlementAsset={tDAI} isWalletConnected={true} />,
{ wrapper: MockedProvider }
<DealTicketBalance
settlementAsset={tDAI}
accounts={[]}
isWalletConnected={true}
/>
);
expect(getByText('No tDAI left to trade')).toBeInTheDocument();
@@ -1,38 +1,43 @@
import classNames from 'classnames';
import {
addDecimalsFormatNumber,
t,
toBigNum,
} from '@vegaprotocol/react-helpers';
import type { MarketDealTicket } from '@vegaprotocol/market-list';
import { useAccountBalance } from '@vegaprotocol/accounts';
import { addDecimalsFormatNumber, t } from '@vegaprotocol/react-helpers';
import { Schema } from '@vegaprotocol/types';
import type {
AccountFragment,
DealTicketMarketFragment,
} from '@vegaprotocol/deal-ticket';
import { useSettlementAccount } from '@vegaprotocol/deal-ticket';
interface DealTicketBalanceProps {
settlementAsset: MarketDealTicket['tradableInstrument']['instrument']['product']['settlementAsset'];
settlementAsset: DealTicketMarketFragment['tradableInstrument']['instrument']['product']['settlementAsset'];
accounts: AccountFragment[];
isWalletConnected: boolean;
className?: string;
}
export const DealTicketBalance = ({
settlementAsset,
accounts,
isWalletConnected,
className = '',
}: DealTicketBalanceProps) => {
const settlementAssetId = settlementAsset?.id;
const settlementAssetSymbol = settlementAsset?.symbol;
const { accountBalance, accountDecimals } =
useAccountBalance(settlementAssetId) || {};
const settlementBalance = toBigNum(accountBalance || 0, accountDecimals || 0);
const settlementAccount = useSettlementAccount(
settlementAssetId,
accounts,
Schema.AccountType.ACCOUNT_TYPE_GENERAL
);
const formattedNumber =
accountBalance &&
accountDecimals &&
addDecimalsFormatNumber(accountBalance, accountDecimals);
settlementAccount?.balance &&
settlementAccount.asset.decimals &&
addDecimalsFormatNumber(
settlementAccount.balance,
settlementAccount.asset.decimals
);
const balance = (
<p className="text-blue text-lg font-semibold">
{!settlementBalance.isZero()
{settlementAccount
? t(`${formattedNumber}`)
: `No ${settlementAssetSymbol} left to trade`}
</p>
@@ -1,17 +1,17 @@
import { useParams } from 'react-router-dom';
import { Loader, Splash } from '@vegaprotocol/ui-toolkit';
import { t, useDataProvider } from '@vegaprotocol/react-helpers';
import compact from 'lodash/compact';
import {
DealTicketManager,
DealTicketContainer as Container,
usePartyBalanceQuery,
} from '@vegaprotocol/deal-ticket';
import { Loader } from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/react-helpers';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { DealTicketSteps } from './deal-ticket-steps';
import { DealTicketBalance } from './deal-ticket-balance';
import Baubles from './baubles-decor';
import ConnectWallet from '../wallet-connector';
import { useMemo } from 'react';
import type {
MarketDataUpdateFieldsFragment,
MarketDealTicket,
} from '@vegaprotocol/market-list';
import { marketDealTicketProvider } from '@vegaprotocol/market-list';
const tempEmptyText = (
<p>{t('Please select a market from the markets page')}</p>
@@ -21,54 +21,52 @@ export const DealTicketContainer = () => {
const { marketId } = useParams<{ marketId: string }>();
const { pubKey } = useVegaWallet();
const variables = useMemo(
() => ({
marketId: marketId || '',
}),
[marketId]
);
const { data, loading } = useDataProvider<
MarketDealTicket,
MarketDataUpdateFieldsFragment
>({
dataProvider: marketDealTicketProvider,
variables,
skip: !marketId,
const { data: partyData, loading } = usePartyBalanceQuery({
variables: { partyId: pubKey || '' },
skip: !pubKey,
});
const loader = <Loader />;
if (marketId && data) {
const balance = (
<DealTicketBalance
className="mb-4"
settlementAsset={
data.tradableInstrument.instrument.product?.settlementAsset
const container = marketId ? (
<Container marketId={marketId}>
{(data) => {
if (!data.market) {
return null as unknown as JSX.Element;
}
isWalletConnected={!!pubKey}
/>
);
const container = (
<>
{loading ? loader : balance}
<DealTicketSteps market={data} />
</>
);
const accounts = compact(
partyData?.party?.accountsConnection?.edges
).map((e) => e.node);
const balance = (
<DealTicketBalance
className="mb-4"
settlementAsset={
data.market.tradableInstrument.instrument.product?.settlementAsset
}
accounts={accounts || []}
isWalletConnected={!!pubKey}
/>
);
return (
<section className="flex p-4 md:p-6">
<section className="w-full md:w-1/2 md:min-w-[500px]">
{pubKey ? container : <ConnectWallet />}
</section>
<Baubles />
</section>
);
}
return marketId ? (
<Splash>
<p>{t('Could not load market')}</p>
</Splash>
return (
<DealTicketManager market={data.market}>
{loading ? loader : balance}
<DealTicketSteps market={data.market} />
</DealTicketManager>
);
}}
</Container>
) : (
tempEmptyText
);
return (
<section className="flex p-4 md:p-6">
<section className="w-full md:w-1/2 md:min-w-[500px]">
{pubKey ? container : <ConnectWallet />}
</section>
<Baubles />
</section>
);
};
@@ -1,13 +1,17 @@
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useForm, Controller } from 'react-hook-form';
import compact from 'lodash/compact';
import { Stepper } from '../stepper';
import type { DealTicketMarketFragment } from '@vegaprotocol/deal-ticket';
import {
getDefaultOrder,
useOrderCloseOut,
useOrderMargin,
usePartyBalanceQuery,
useMaximumPositionSize,
useCalculateSlippage,
validateAmount,
} from '@vegaprotocol/deal-ticket';
import { InputError } from '@vegaprotocol/ui-toolkit';
import { BigNumber } from 'bignumber.js';
@@ -20,9 +24,9 @@ import {
toDecimal,
removeDecimal,
addDecimalsFormatNumber,
addDecimalsNormalizeNumber,
addDecimal,
formatNumber,
validateAmount,
} from '@vegaprotocol/react-helpers';
import {
useOrderSubmit,
@@ -35,13 +39,12 @@ import { DealTicketSize } from './deal-ticket-size';
import MarketNameRenderer from '../simple-market-list/simple-market-renderer';
import SideSelector, { SIDE_NAMES } from './side-selector';
import ReviewTrade from './review-trade';
import * as Schema from '@vegaprotocol/types';
import { Schema } from '@vegaprotocol/types';
import { DealTicketSlippage } from './deal-ticket-slippage';
import { useOrderValidation } from './use-order-validation';
import type { MarketDealTicket } from '@vegaprotocol/market-list';
interface DealTicketMarketProps {
market: MarketDealTicket;
market: DealTicketMarketFragment;
}
export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
@@ -68,14 +71,31 @@ export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
const step = toDecimal(market.positionDecimalPlaces);
const order = watch();
const { pubKey } = useVegaWallet();
const estMargin = useOrderMargin({
order,
market,
partyId: pubKey || '',
});
const { message: invalidText, isDisabled } = useOrderValidation({
market,
order,
orderType: order.type,
orderTimeInForce: order.timeInForce,
fieldErrors: errors,
estMargin,
});
const { submit, transaction, finalizedOrder, Dialog } = useOrderSubmit();
const { data: partyBalance } = usePartyBalanceQuery({
variables: { partyId: pubKey || '' },
skip: !pubKey,
});
const accounts = compact(partyBalance?.party?.accountsConnection?.edges).map(
(e) => e.node
);
const maxTrade = useMaximumPositionSize({
partyId: pubKey || '',
accounts: accounts,
marketId: market.id,
settlementAssetId:
market.tradableInstrument.instrument.product.settlementAsset.id,
@@ -83,11 +103,11 @@ export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
order,
});
const closeOut = useOrderCloseOut({
const estCloseOut = useOrderCloseOut({
order,
market,
partyData: partyBalance,
});
const estCloseOut = closeOut && formatNumber(closeOut, market.decimalPlaces);
const slippage = useCalculateSlippage({ marketId: market.id, order });
const [slippageValue, setSlippageValue] = useState(
slippage ? parseFloat(slippage) : 0
@@ -110,18 +130,11 @@ export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
);
return new BigNumber(market?.depth?.lastTrade?.price)
.multipliedBy(multiplier)
.toString();
.toNumber();
}
return undefined;
return null;
}, [market?.depth?.lastTrade?.price, order.side, slippage]);
const estMargin = useOrderMargin({
order,
market,
partyId: pubKey || '',
derivedPrice: price,
});
const formattedPrice =
price && addDecimalsFormatNumber(price, market.decimalPlaces);
@@ -145,7 +158,7 @@ export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
.decimalPlaces(2)
.toString();
return `${addDecimalsFormatNumber(
return `${addDecimalsNormalizeNumber(
estMargin.totalFees,
assetDecimals
)} (${formatNumber(addDecimal(percentage, assetDecimals), 2)}%)`;
@@ -5,16 +5,34 @@ import {
KeyValueTableRow,
} from '@vegaprotocol/ui-toolkit';
import classNames from 'classnames';
import type { DealTicketMarketFragment } from '@vegaprotocol/deal-ticket';
import { DealTicketEstimates } from '@vegaprotocol/deal-ticket';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import { SIDE_NAMES } from './side-selector';
import * as Schema from '@vegaprotocol/types';
import { gql, useQuery } from '@apollo/client';
import type {
MarketTags,
MarketTagsVariables,
} from './__generated__/MarketTags';
import { Schema } from '@vegaprotocol/types';
import { MarketExpires } from '@vegaprotocol/market-info';
import type { MarketDealTicket } from '@vegaprotocol/market-list';
import { useMarketTagsQuery } from './__generated__/MarketTags';
export const MARKET_TAGS_QUERY = gql`
query MarketTags($marketId: ID!) {
market(id: $marketId) {
tradableInstrument {
instrument {
metadata {
tags
}
}
}
}
}
`;
interface Props {
market: MarketDealTicket;
market: DealTicketMarketFragment;
isDisabled: boolean;
transactionStatus?: string;
order: OrderSubmissionBody['orderSubmission'];
@@ -39,9 +57,12 @@ export default ({
notionalSize,
slippage,
}: Props) => {
const { data: tagsData } = useMarketTagsQuery({
variables: { marketId: market.id },
});
const { data: tagsData } = useQuery<MarketTags, MarketTagsVariables>(
MARKET_TAGS_QUERY,
{
variables: { marketId: market.id },
}
);
return (
<div className="mb-8 text-black dark:text-white" data-testid="review-trade">
@@ -2,7 +2,7 @@ import React from 'react';
import classNames from 'classnames';
import { FormGroup } from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/react-helpers';
import * as Schema from '@vegaprotocol/types';
import { Schema } from '@vegaprotocol/types';
interface SideSelectorProps {
value: Schema.Side;
@@ -3,11 +3,12 @@ import { renderHook } from '@testing-library/react';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { MockedProvider } from '@apollo/client/testing';
import type { VegaWalletContextShape } from '@vegaprotocol/wallet';
import * as Schema from '@vegaprotocol/types';
import { MarketStateMapping, Schema } from '@vegaprotocol/types';
import type { ValidationProps } from './use-order-validation';
import { marketTranslations, useOrderValidation } from './use-order-validation';
import type { MarketDealTicket } from '@vegaprotocol/market-list';
import type { DealTicketMarketFragment } from '@vegaprotocol/deal-ticket';
import * as DealTicket from '@vegaprotocol/deal-ticket';
import BigNumber from 'bignumber.js';
jest.mock('@vegaprotocol/wallet');
jest.mock('@vegaprotocol/deal-ticket', () => {
@@ -18,7 +19,7 @@ jest.mock('@vegaprotocol/deal-ticket', () => {
});
type SettlementAsset =
MarketDealTicket['tradableInstrument']['instrument']['product']['settlementAsset'];
DealTicketMarketFragment['tradableInstrument']['instrument']['product']['settlementAsset'];
const asset: SettlementAsset = {
__typename: 'Asset',
id: 'asset-id',
@@ -27,7 +28,7 @@ const asset: SettlementAsset = {
decimals: 2,
};
const market: MarketDealTicket = {
const market: DealTicketMarketFragment = {
id: 'market-id',
decimalPlaces: 2,
positionDecimalPlaces: 1,
@@ -39,17 +40,10 @@ const market: MarketDealTicket = {
__typename: 'Instrument',
id: 'instrument-id',
name: 'instrument-name',
code: 'instriment-code',
metadata: {
tags: [],
},
product: {
__typename: 'Future',
quoteName: 'quote-name',
settlementAsset: asset,
dataSourceSpecForTradingTermination: {
id: 'dataSource-id',
},
},
},
},
@@ -69,30 +63,6 @@ const market: MarketDealTicket = {
liquidityFee: '3',
},
},
data: {
__typename: 'MarketData',
bestBidPrice: '1605489971',
bestOfferPrice: '1606823730',
markPrice: '1606823730',
trigger: Schema.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED,
staticMidPrice: '1606156850',
marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
marketState: Schema.MarketState.STATE_ACTIVE,
indicativeVolume: '0',
indicativePrice: '0',
bestStaticBidPrice: '1605489971',
bestStaticOfferPrice: '1606823730',
targetStake: '8561302732',
suppliedStake: '727654170336',
auctionStart: null,
auctionEnd: null,
market: { __typename: 'Market', id: 'market-id' },
},
marketTimestamps: {
__typename: 'MarketTimestamps',
close: null,
open: null,
},
};
const defaultWalletContext = {
@@ -105,19 +75,19 @@ const defaultWalletContext = {
connector: null,
};
const order = {
type: Schema.OrderType.TYPE_MARKET,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_FOK,
marketId: 'market-id',
side: Schema.Side.SIDE_BUY,
size: '0.1',
};
const defaultOrder = {
market: { ...market },
market,
step: 0.1,
order: {
...order,
orderType: Schema.OrderType.TYPE_MARKET,
orderTimeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_FOK,
estMargin: {
margin: '0,000001',
totalFees: '0,000006',
fees: {
makerFee: '0,000003',
liquidityFee: '0,000002',
infrastructureFee: '0,000001',
},
},
};
@@ -157,9 +127,9 @@ describe('useOrderValidation', () => {
it('Returns empty string when given valid data', () => {
jest.spyOn(DealTicket, 'useOrderMarginValidation').mockReturnValue({
balance: '0',
margin: '100',
balanceError: false,
balance: new BigNumber(0),
margin: new BigNumber(100),
asset,
});
const { result } = setup();
@@ -172,9 +142,9 @@ describe('useOrderValidation', () => {
it('Returns an error message when no keypair found', () => {
jest.spyOn(DealTicket, 'useOrderMarginValidation').mockReturnValue({
balance: '0',
margin: '100',
balanceError: false,
balance: new BigNumber(0),
margin: new BigNumber(100),
asset,
});
const { result } = setup(defaultOrder, { pubKey: null });
expect(result.current).toStrictEqual({
@@ -194,11 +164,7 @@ describe('useOrderValidation', () => {
`(
'Returns an error message for market state when not accepting orders',
({ state }) => {
const market = {
...defaultOrder.market,
data: { ...defaultOrder.market.data, marketState: state },
};
const { result } = setup({ market });
const { result } = setup({ market: { ...defaultOrder.market, state } });
expect(result.current).toStrictEqual({
isDisabled: true,
message: `This market is ${marketTranslations(
@@ -217,31 +183,22 @@ describe('useOrderValidation', () => {
'Returns an error message for market state suspended or pending',
({ state }) => {
jest.spyOn(DealTicket, 'useOrderMarginValidation').mockReturnValue({
balance: '0',
margin: '100',
balanceError: false,
balance: new BigNumber(0),
margin: new BigNumber(100),
asset,
});
const market = {
...defaultOrder.market,
data: {
...defaultOrder.market.data,
marketState: state,
marketTradingMode:
Schema.MarketTradingMode.TRADING_MODE_BATCH_AUCTION,
},
};
const { result } = setup({
market,
order: {
...order,
type: Schema.OrderType.TYPE_LIMIT,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTT,
market: {
...defaultOrder.market,
state,
tradingMode: Schema.MarketTradingMode.TRADING_MODE_BATCH_AUCTION,
},
orderType: Schema.OrderType.TYPE_LIMIT,
orderTimeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTT,
});
expect(result.current).toStrictEqual({
isDisabled: false,
message: `This market is ${Schema.MarketStateMapping[
message: `This market is ${MarketStateMapping[
state as Schema.MarketState
].toLowerCase()} and only accepting liquidity commitment orders`,
section: 'sec-summary',
@@ -257,16 +214,9 @@ describe('useOrderValidation', () => {
`(
`Returns an error message when trying to submit a non-limit order for a "$tradingMode" market`,
({ tradingMode, errorMessage }) => {
const market = {
...defaultOrder.market,
data: { ...defaultOrder.market.data, marketTradingMode: tradingMode },
};
const { result } = setup({
market,
order: {
...order,
type: Schema.OrderType.TYPE_MARKET,
},
market: { ...defaultOrder.market, tradingMode },
orderType: Schema.OrderType.TYPE_MARKET,
});
expect(result.current.isDisabled).toBeTruthy();
expect(result.current.message).toBe(errorMessage);
@@ -287,17 +237,10 @@ describe('useOrderValidation', () => {
`(
`Returns an error message when submitting a limit order with a "$orderTimeInForce" value to a "$tradingMode" market`,
({ tradingMode, orderTimeInForce, errorMessage }) => {
const market = {
...defaultOrder.market,
data: { ...defaultOrder.market.data, marketTradingMode: tradingMode },
};
const { result } = setup({
market,
order: {
...order,
type: Schema.OrderType.TYPE_LIMIT,
timeInForce: orderTimeInForce,
},
market: { ...defaultOrder.market, tradingMode },
orderType: Schema.OrderType.TYPE_LIMIT,
orderTimeInForce,
});
expect(result.current).toStrictEqual({
isDisabled: true,
@@ -318,10 +261,7 @@ describe('useOrderValidation', () => {
({ fieldName, errorType, section, errorMessage }) => {
const { result } = setup({
fieldErrors: { [fieldName]: { type: errorType } },
order: {
...order,
type: Schema.OrderType.TYPE_LIMIT,
},
orderType: Schema.OrderType.TYPE_LIMIT,
});
expect(result.current).toStrictEqual({
isDisabled: true,
@@ -360,9 +300,9 @@ describe('useOrderValidation', () => {
it('Returns an error message when the estimated margin is higher than collateral', async () => {
const invalidatedMockValue = {
balance: '100',
margin: '200',
balanceError: true,
balance: new BigNumber(100),
margin: new BigNumber(200),
asset,
};
jest
@@ -375,9 +315,9 @@ describe('useOrderValidation', () => {
const testElement = (
<DealTicket.MarginWarning
margin={invalidatedMockValue.margin}
balance={invalidatedMockValue.balance}
asset={asset}
margin={invalidatedMockValue.margin.toString()}
balance={invalidatedMockValue.balance.toString()}
asset={invalidatedMockValue.asset}
/>
);
expect((result.current.message as React.ReactElement)?.props).toEqual(
@@ -395,15 +335,14 @@ describe('useOrderValidation', () => {
`(
'Returns error when market state is pending and size is wrong',
({ state }) => {
const market = {
...defaultOrder.market,
data: { ...defaultOrder.market.data, marketState: state },
};
const { result } = setup({
fieldErrors: {
size: { type: `validate`, message: DealTicket.ERROR_SIZE_DECIMAL },
},
market,
market: {
...market,
state,
},
});
expect(result.current).toStrictEqual({
isDisabled: true,
@@ -1,19 +1,23 @@
import type { ReactNode } from 'react';
import type { FieldErrors } from 'react-hook-form';
import { useMemo } from 'react';
import { DataGrid, t, toDecimal } from '@vegaprotocol/react-helpers';
import { t, toDecimal } from '@vegaprotocol/react-helpers';
import { useVegaWallet } from '@vegaprotocol/wallet';
import * as Schema from '@vegaprotocol/types';
import { MarketStateMapping, Schema } from '@vegaprotocol/types';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import { Tooltip } from '@vegaprotocol/ui-toolkit';
import type {
DealTicketMarketFragment,
OrderMargin,
} from '@vegaprotocol/deal-ticket';
import {
MarketDataGrid,
compileGridData,
MarginWarning,
isMarketInAuction,
ERROR_SIZE_DECIMAL,
useOrderMarginValidation,
} from '@vegaprotocol/deal-ticket';
import type { MarketDealTicket } from '@vegaprotocol/market-list';
export const DEAL_TICKET_SECTION = {
TYPE: 'sec-type',
@@ -28,9 +32,11 @@ export const ERROR_EXPIRATION_IN_THE_PAST = 'ERROR_EXPIRATION_IN_THE_PAST';
export type ValidationProps = {
step?: number;
market: MarketDealTicket;
order: OrderSubmissionBody['orderSubmission'];
market: DealTicketMarketFragment;
orderType: Schema.OrderType;
orderTimeInForce: Schema.OrderTimeInForce;
fieldErrors?: FieldErrors<OrderSubmissionBody['orderSubmission']>;
estMargin: OrderMargin | null;
};
export const marketTranslations = (marketState: Schema.MarketState) => {
@@ -38,7 +44,7 @@ export const marketTranslations = (marketState: Schema.MarketState) => {
case Schema.MarketState.STATE_TRADING_TERMINATED:
return t('terminated');
default:
return t(Schema.MarketStateMapping[marketState]).toLowerCase();
return t(MarketStateMapping[marketState]).toLowerCase();
}
};
@@ -49,7 +55,9 @@ export type DealTicketSection =
export const useOrderValidation = ({
market,
fieldErrors,
order,
orderType,
orderTimeInForce,
estMargin,
}: ValidationProps): {
message: ReactNode | string;
isDisabled: boolean;
@@ -57,7 +65,7 @@ export const useOrderValidation = ({
} => {
const { pubKey } = useVegaWallet();
const minSize = toDecimal(market.positionDecimalPlaces);
const isInvalidOrderMargin = useOrderMarginValidation({ market, order });
const isInvalidOrderMargin = useOrderMarginValidation({ market, estMargin });
const fieldErrorChecking = useMemo<{
message: ReactNode | string;
@@ -83,7 +91,7 @@ export const useOrderValidation = ({
if (
fieldErrors?.price?.type === 'required' &&
order.type !== Schema.OrderType.TYPE_MARKET
orderType !== Schema.OrderType.TYPE_MARKET
) {
return {
isDisabled: true,
@@ -94,7 +102,7 @@ export const useOrderValidation = ({
if (
fieldErrors?.price?.type === 'min' &&
order.type !== Schema.OrderType.TYPE_MARKET
orderType !== Schema.OrderType.TYPE_MARKET
) {
return {
isDisabled: true,
@@ -143,7 +151,7 @@ export const useOrderValidation = ({
fieldErrors?.price?.type,
fieldErrors?.expiresAt?.type,
fieldErrors?.expiresAt?.message,
order.type,
orderType,
minSize,
market.positionDecimalPlaces,
]);
@@ -168,13 +176,13 @@ export const useOrderValidation = ({
Schema.MarketState.STATE_TRADING_TERMINATED,
Schema.MarketState.STATE_CANCELLED,
Schema.MarketState.STATE_CLOSED,
].includes(market.data.marketState)
].includes(market.state)
) {
return {
isDisabled: true,
message: t(
`This market is ${marketTranslations(
market.data.marketState
market.state
)} and not accepting orders`
),
section: DEAL_TICKET_SECTION.SUMMARY,
@@ -185,7 +193,7 @@ export const useOrderValidation = ({
[
Schema.MarketState.STATE_PROPOSED,
Schema.MarketState.STATE_PENDING,
].includes(market.data.marketState)
].includes(market.state)
) {
if (fieldErrorChecking) {
return fieldErrorChecking;
@@ -194,7 +202,7 @@ export const useOrderValidation = ({
isDisabled: false,
message: t(
`This market is ${marketTranslations(
market.data.marketState
market.state
)} and only accepting liquidity commitment orders`
),
section: DEAL_TICKET_SECTION.SUMMARY,
@@ -202,11 +210,11 @@ export const useOrderValidation = ({
}
if (isMarketInAuction(market)) {
if (order.type === Schema.OrderType.TYPE_MARKET) {
if (orderType === Schema.OrderType.TYPE_MARKET) {
if (
market.data.marketTradingMode ===
market.tradingMode ===
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION &&
market.data.trigger ===
market.data?.trigger ===
Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY
) {
return {
@@ -216,7 +224,7 @@ export const useOrderValidation = ({
{t('This market is in auction until it reaches')}{' '}
<Tooltip
description={
<DataGrid grid={compileGridData(market, market.data)} />
<MarketDataGrid grid={compileGridData(market)} />
}
>
<span>{t('sufficient liquidity')}</span>
@@ -229,9 +237,9 @@ export const useOrderValidation = ({
};
}
if (
market.data.marketTradingMode ===
market.tradingMode ===
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION &&
market.data.trigger === Schema.AuctionTrigger.AUCTION_TRIGGER_PRICE
market.data?.trigger === Schema.AuctionTrigger.AUCTION_TRIGGER_PRICE
) {
return {
isDisabled: true,
@@ -240,7 +248,7 @@ export const useOrderValidation = ({
{t('This market is in auction due to')}{' '}
<Tooltip
description={
<DataGrid grid={compileGridData(market, market.data)} />
<MarketDataGrid grid={compileGridData(market)} />
}
>
<span>{t('high price volatility')}</span>
@@ -261,17 +269,17 @@ export const useOrderValidation = ({
};
}
if (
order.type === Schema.OrderType.TYPE_LIMIT &&
orderType === Schema.OrderType.TYPE_LIMIT &&
[
Schema.OrderTimeInForce.TIME_IN_FORCE_FOK,
Schema.OrderTimeInForce.TIME_IN_FORCE_IOC,
Schema.OrderTimeInForce.TIME_IN_FORCE_GFN,
].includes(order.timeInForce)
].includes(orderTimeInForce)
) {
if (
market.data.marketTradingMode ===
market.tradingMode ===
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION &&
market.data.trigger ===
market.data?.trigger ===
Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY
) {
return {
@@ -281,7 +289,7 @@ export const useOrderValidation = ({
{t('This market is in auction until it reaches')}{' '}
<Tooltip
description={
<DataGrid grid={compileGridData(market, market.data)} />
<MarketDataGrid grid={compileGridData(market)} />
}
>
<span>{t('sufficient liquidity')}</span>
@@ -296,9 +304,9 @@ export const useOrderValidation = ({
};
}
if (
market.data.marketTradingMode ===
market.tradingMode ===
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION &&
market.data.trigger === Schema.AuctionTrigger.AUCTION_TRIGGER_PRICE
market.data?.trigger === Schema.AuctionTrigger.AUCTION_TRIGGER_PRICE
) {
return {
isDisabled: true,
@@ -307,7 +315,7 @@ export const useOrderValidation = ({
{t('This market is in auction due to')}{' '}
<Tooltip
description={
<DataGrid grid={compileGridData(market, market.data)} />
<MarketDataGrid grid={compileGridData(market)} />
}
>
<span>{t('high price volatility')}</span>
@@ -335,14 +343,17 @@ export const useOrderValidation = ({
return fieldErrorChecking;
}
if (isInvalidOrderMargin.balanceError) {
if (
isInvalidOrderMargin.balance.isGreaterThan(0) &&
isInvalidOrderMargin.balance.isLessThan(isInvalidOrderMargin.margin)
) {
return {
isDisabled: false,
message: (
<MarginWarning
margin={isInvalidOrderMargin.margin}
balance={isInvalidOrderMargin.balance}
asset={market.tradableInstrument.instrument.product.settlementAsset}
margin={isInvalidOrderMargin.margin.toString()}
balance={isInvalidOrderMargin.balance.toString()}
asset={isInvalidOrderMargin.asset}
/>
),
section: DEAL_TICKET_SECTION.PRICE,
@@ -354,7 +365,7 @@ export const useOrderValidation = ({
Schema.MarketTradingMode.TRADING_MODE_BATCH_AUCTION,
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION,
].includes(market.data.marketTradingMode)
].includes(market.tradingMode)
) {
return {
isDisabled: false,
@@ -375,8 +386,8 @@ export const useOrderValidation = ({
market,
fieldErrorChecking,
isInvalidOrderMargin,
order.type,
order.timeInForce,
orderType,
orderTimeInForce,
]);
return { message, isDisabled, section };
@@ -11,6 +11,8 @@ const Header = () => {
}));
const {
vegaWalletDialog: { setManage },
theme,
toggleTheme,
} = useContext(LocalContext);
return (
<div
@@ -23,7 +25,7 @@ const Header = () => {
setConnectDialog={updateVegaWalletDialog}
setManageDialog={setManage}
/>
<ThemeSwitcher className="-my-4" />
<ThemeSwitcher theme={theme} onToggle={toggleTheme} className="-my-4" />
</div>
</div>
);
@@ -16,7 +16,7 @@ import { useAccountColumnDefinitions } from '.';
const AccountsManager = () => {
const { partyId = '' } = useOutletContext<{ partyId: string }>();
const { isOpen, id, setOpen } = useAssetDetailsDialogStore();
const { isOpen, symbol, setOpen } = useAssetDetailsDialogStore();
const gridRef = useRef<AgGridReact | null>(null);
const dataRef = useRef<AccountFields[] | null>(null);
const variables = useMemo(() => ({ partyId }), [partyId]);
@@ -33,17 +33,19 @@ const AccountsManager = () => {
update,
variables,
});
const getRows = useCallback(
async ({ successCallback, startRow, endRow }: IGetRowsParams) => {
const rowsThisBlock = dataRef.current
? dataRef.current.slice(startRow, endRow)
: [];
const lastRow = dataRef.current ? dataRef.current.length : 0;
successCallback(rowsThisBlock, lastRow);
},
[]
);
const getRows = async ({
successCallback,
startRow,
endRow,
}: IGetRowsParams) => {
const rowsThisBlock = dataRef.current
? dataRef.current.slice(startRow, endRow)
: [];
const lastRow = dataRef.current?.length ?? -1;
successCallback(rowsThisBlock, lastRow);
};
const { columnDefs, defaultColDef } = useAccountColumnDefinitions();
console.log(data, loading);
return (
<>
<AsyncRenderer
@@ -64,7 +66,7 @@ const AccountsManager = () => {
/>
</AsyncRenderer>
<AssetDetailsDialog
assetId={id}
assetSymbol={symbol}
open={isOpen}
onChange={(open) => setOpen(open)}
/>
@@ -15,14 +15,14 @@ const useAccountColumnDefinitions = () => {
field: 'asset.symbol',
headerClass: 'uppercase justify-start',
cellClass: 'uppercase flex h-full items-center md:pl-4',
cellRenderer: ({ value, data }: GroupCellRendererParams) =>
cellRenderer: ({ value }: GroupCellRendererParams) =>
value && value.length > 0 ? (
<div className="md:pl-4 grid h-full items-center" title={value}>
<div className="truncate min-w-0">
<button
className="hover:underline"
onClick={() => {
open(data.asset.id);
open(value);
}}
>
{value}
@@ -12,7 +12,7 @@ import {
t,
} from '@vegaprotocol/react-helpers';
import BigNumber from 'bignumber.js';
import * as Schema from '@vegaprotocol/types';
import { Schema } from '@vegaprotocol/types';
interface Props {
partyId: string;
@@ -14,14 +14,20 @@ import {
import type { OrderFieldsFragment, Order } from '@vegaprotocol/orders';
import type { OrderCancellationBody } from '@vegaprotocol/wallet';
import { isOrderActive } from '@vegaprotocol/orders';
import * as Schema from '@vegaprotocol/types';
import {
OrderRejectionReasonMapping,
OrderStatusMapping,
OrderTypeMapping,
Schema,
OrderTimeInForceMapping,
} from '@vegaprotocol/types';
import BigNumber from 'bignumber.js';
import { Button } from '@vegaprotocol/ui-toolkit';
type StatusKey = keyof typeof Schema.OrderStatusMapping;
type RejectReasonKey = keyof typeof Schema.OrderRejectionReasonMapping;
type OrderTimeKey = keyof typeof Schema.OrderTimeInForceMapping;
type StatusKey = keyof typeof OrderStatusMapping;
type RejectReasonKey = keyof typeof OrderRejectionReasonMapping;
type OrderTimeKey = keyof typeof OrderTimeInForceMapping;
interface Props {
setEditOrder: (order: Order) => void;
orderCancel: {
@@ -75,7 +81,7 @@ const useColumnDefinitions = ({ setEditOrder, orderCancel }: Props) => {
value,
}: ValueFormatterParams & {
value?: OrderFieldsFragment['type'];
}) => Schema.OrderTypeMapping[value as Schema.OrderType],
}) => OrderTypeMapping[value as Schema.OrderType],
},
{
colId: 'status',
@@ -89,14 +95,14 @@ const useColumnDefinitions = ({ setEditOrder, orderCancel }: Props) => {
}) => {
if (value && data && data.market) {
if (value === Schema.OrderStatus.STATUS_REJECTED) {
return `${Schema.OrderStatusMapping[value as StatusKey]}: ${
return `${OrderStatusMapping[value as StatusKey]}: ${
data.rejectionReason &&
Schema.OrderRejectionReasonMapping[
OrderRejectionReasonMapping[
data.rejectionReason as RejectReasonKey
]
}`;
}
return Schema.OrderStatusMapping[value as StatusKey] as string;
return OrderStatusMapping[value as StatusKey] as string;
}
return '-';
},
@@ -170,11 +176,11 @@ const useColumnDefinitions = ({ setEditOrder, orderCancel }: Props) => {
new Date(data.expiresAt)
);
return `${
Schema.OrderTimeInForceMapping[value as OrderTimeKey]
OrderTimeInForceMapping[value as OrderTimeKey]
}: ${expiry}`;
}
return Schema.OrderTimeInForceMapping[value as OrderTimeKey];
return OrderTimeInForceMapping[value as OrderTimeKey];
}
return '-';
},
@@ -13,7 +13,7 @@ import useColumnDefinitions from './use-column-definitions';
const Positions = () => {
const gridRef = useRef<AgGridReact | null>(null);
const { partyId } = useOutletContext<{ partyId: string }>();
const { data, error, loading, getRows } = usePositionsData(partyId, gridRef);
const { data, error, loading } = usePositionsData(partyId, gridRef);
const { columnDefs, defaultColDef } = useColumnDefinitions();
return (
<AsyncRenderer
@@ -29,8 +29,7 @@ const Positions = () => {
columnDefs={columnDefs}
defaultColDef={defaultColDef}
getRowId={getRowId}
rowModelType="infinite"
datasource={{ getRows }}
rowData={data || undefined}
components={{ PriceFlashCell }}
/>
</AsyncRenderer>
@@ -16,7 +16,7 @@ import type {
GroupCellRendererParams,
ColDef,
} from 'ag-grid-community';
import * as Schema from '@vegaprotocol/types';
import { Schema } from '@vegaprotocol/types';
import type { VegaValueFormatterParams } from '@vegaprotocol/ui-toolkit';
import { Intent, ProgressBarCell } from '@vegaprotocol/ui-toolkit';
@@ -0,0 +1,27 @@
/* tslint:disable */
/* eslint-disable */
// @generated
// This file was automatically generated and should not be edited.
// ====================================================
// GraphQL subscription operation: CandleLive
// ====================================================
export interface CandleLive_candles {
__typename: "Candle";
/**
* Close price (uint64)
*/
close: string;
}
export interface CandleLive {
/**
* Subscribe to the candles updates
*/
candles: CandleLive_candles;
}
export interface CandleLiveVariables {
marketId: string;
}
@@ -0,0 +1,43 @@
import { Schema as Types } from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type CandleLiveSubscriptionVariables = Types.Exact<{
marketId: Types.Scalars['ID'];
}>;
export type CandleLiveSubscription = { __typename?: 'Subscription', candles: { __typename?: 'Candle', close: string } };
export const CandleLiveDocument = gql`
subscription CandleLive($marketId: ID!) {
candles(marketId: $marketId, interval: INTERVAL_I1H) {
close
}
}
`;
/**
* __useCandleLiveSubscription__
*
* To run a query within a React component, call `useCandleLiveSubscription` and pass it any options that fit your needs.
* When your component renders, `useCandleLiveSubscription` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the subscription, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useCandleLiveSubscription({
* variables: {
* marketId: // value for 'marketId'
* },
* });
*/
export function useCandleLiveSubscription(baseOptions: Apollo.SubscriptionHookOptions<CandleLiveSubscription, CandleLiveSubscriptionVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useSubscription<CandleLiveSubscription, CandleLiveSubscriptionVariables>(CandleLiveDocument, options);
}
export type CandleLiveSubscriptionHookResult = ReturnType<typeof useCandleLiveSubscription>;
export type CandleLiveSubscriptionResult = Apollo.SubscriptionResult<CandleLiveSubscription>;
@@ -1,6 +1,6 @@
import { t } from '@vegaprotocol/react-helpers';
import { themelite as theme } from '@vegaprotocol/tailwindcss-config';
import * as Schema from '@vegaprotocol/types';
import { Schema } from '@vegaprotocol/types';
import colors from 'tailwindcss/colors';
import type { Market } from '@vegaprotocol/market-list';
import { IS_MARKET_TRADABLE } from '../../constants';
@@ -9,7 +9,7 @@ import {
} from '@testing-library/react';
import { MockedProvider } from '@apollo/client/testing';
import { BrowserRouter } from 'react-router-dom';
import * as Schema from '@vegaprotocol/types';
import { Schema } from '@vegaprotocol/types';
import type { Market } from '@vegaprotocol/market-list';
import SimpleMarketList from './simple-market-list';
@@ -13,7 +13,7 @@ import SimpleMarketToolbar from './simple-market-toolbar';
import { IS_MARKET_TRADABLE } from '../../constants';
import { ConsoleLiteGrid } from '../console-lite-grid';
import type { Market } from '@vegaprotocol/market-list';
import * as Schema from '@vegaprotocol/types';
import { Schema } from '@vegaprotocol/types';
import { marketsWithCandlesProvider } from '@vegaprotocol/market-list';
export type MarketWithPercentChange = Market & {
@@ -4,7 +4,7 @@ import { InView } from 'react-intersection-observer';
import { useDataProvider, useYesterday } from '@vegaprotocol/react-helpers';
import type { Candle } from '@vegaprotocol/market-list';
import { marketCandlesProvider } from '@vegaprotocol/market-list';
import * as Schema from '@vegaprotocol/types';
import { Schema } from '@vegaprotocol/types';
interface Props {
candles: (Candle | null)[] | null;
@@ -1,6 +1,6 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import * as Schema from '@vegaprotocol/types';
import { Schema } from '@vegaprotocol/types';
import MarketNameRenderer from './simple-market-renderer';
import type { Market } from '@vegaprotocol/market-list';
@@ -14,7 +14,7 @@ import {
getAllByText,
} from '@testing-library/react';
import { MockedProvider } from '@apollo/react-testing';
import * as Schema from '@vegaprotocol/types';
import { Schema } from '@vegaprotocol/types';
import type { Market } from '@vegaprotocol/market-list';
import SimpleMarketToolbar from './simple-market-toolbar';
import { markets as filterData } from './mocks/market-filters.json';
@@ -13,7 +13,7 @@ import {
DropdownMenuItemIndicator,
Icon,
} from '@vegaprotocol/ui-toolkit';
import * as Schema from '@vegaprotocol/types';
import { Schema } from '@vegaprotocol/types';
import type { Market } from '@vegaprotocol/market-list';
import { HorizontalMenu } from '../horizontal-menu';
import type { HorizontalMenuItem } from '../horizontal-menu';
@@ -1,5 +1,5 @@
import { useMemo } from 'react';
import * as Schema from '@vegaprotocol/types';
import { Schema } from '@vegaprotocol/types';
import type { MarketWithCandles } from '@vegaprotocol/market-list';
import type { RouterParams } from './simple-market-list';
+1 -1
View File
@@ -1,4 +1,4 @@
import * as Schema from '@vegaprotocol/types';
import { Schema } from '@vegaprotocol/types';
import { t } from '@vegaprotocol/react-helpers';
import type { Market } from '@vegaprotocol/market-list';
@@ -14,6 +14,8 @@ interface MenuState {
export interface LocalValues {
vegaWalletDialog: VegaWalletDialogState;
menu: MenuState;
theme: 'light' | 'dark';
toggleTheme: () => void;
}
const LocalContext = createContext<LocalValues>({} as LocalValues);
@@ -3,7 +3,8 @@ import useLocalValues from './use-local-values';
describe('local values hook', () => {
it('state of wallet dialog should be properly handled', () => {
const { result } = renderHook(() => useLocalValues());
const setTheme = jest.fn();
const { result } = renderHook(() => useLocalValues('light', setTheme));
expect(result.current.vegaWalletDialog).toBeDefined();
expect(result.current.vegaWalletDialog.manage).toBe(false);
act(() => {
@@ -1,15 +1,17 @@
import { useMemo, useState } from 'react';
import type { LocalValues } from '../context/local-context';
const useLocalValues = () => {
const useLocalValues = (theme: 'light' | 'dark', toggleTheme: () => void) => {
const [manage, setManage] = useState<boolean>(false);
const [menuOpen, setMenuOpen] = useState(false);
return useMemo<LocalValues>(
() => ({
vegaWalletDialog: { manage, setManage },
menu: { menuOpen, setMenuOpen, onToggle: () => setMenuOpen(!menuOpen) },
theme,
toggleTheme,
}),
[manage, menuOpen]
[manage, theme, toggleTheme, menuOpen]
);
};
-3
View File
@@ -16,6 +16,3 @@ NX_EXPLORER_TXS_LIST=0
NX_EXPLORER_NETWORK_PARAMETERS=1
NX_EXPLORER_PARTIES=1
NX_EXPLORER_VALIDATORS=1
CYPRESS_VEGA_WALLET_API_TOKEN=
CYPRESS_VEGA_URL=http://localhost:3028/query
-1
View File
@@ -4,7 +4,6 @@ NX_TENDERMINT_URL=https://n04.d.vega.xyz/tm
NX_TENDERMINT_WEBSOCKET_URL=wss://n04.d.vega.xyz/tm/websocket
NX_VEGA_URL=https://api.n04.d.vega.xyz/graphql
NX_VEGA_ENV=DEVNET
NX_BLOCK_EXPLORER=https://be.devnet1.vega.xyz/rest
# App flags
NX_EXPLORER_ASSETS=1
-1
View File
@@ -4,7 +4,6 @@ NX_TENDERMINT_URL=https://mainnet-observer-proxy01.ops.vega.xyz/
NX_TENDERMINT_WEBSOCKET_URL=wss://mainnet-observer-proxy01.ops.vega.xyz/websocket
NX_VEGA_URL=https://api.vega.xyz/query
NX_VEGA_ENV=MAINNET
NX_BLOCK_EXPLORER=https://be.explorer.vega.xyz/rest
# App flags
NX_EXPLORER_ASSETS=1
+3 -4
View File
@@ -1,10 +1,9 @@
# App configuration variables
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://tm.n00.stagnet3.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n00.stagnet3.vega.xyz/websocket
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_TENDERMINT_URL=https://n01.stagnet3.vega.xyz/tm
NX_TENDERMINT_WEBSOCKET_URL=wss://n01.stagnet3.vega.xyz/tm/websocket
NX_VEGA_URL=https://api.n01.stagnet3.vega.xyz/graphql
NX_VEGA_ENV=STAGNET3
NX_BLOCK_EXPLORER=https://be.stagnet3.vega.xyz/rest
# App flags
NX_EXPLORER_ASSETS=1
-1
View File
@@ -4,7 +4,6 @@ NX_TENDERMINT_URL=https://tm.n07.testnet.vega.xyz/tm
NX_TENDERMINT_WEBSOCKET_URL=wss://lb.testnet.vega.xyz/tm/websocket
NX_VEGA_URL=https://api.n11.testnet.vega.xyz/graphql
NX_VEGA_ENV=TESTNET
NX_BLOCK_EXPLORER=https://be.testnet.vega.xyz/rest
# App flags
NX_EXPLORER_ASSETS=1
-39
View File
@@ -1,39 +0,0 @@
# Vega Explorer E2E tests
To run the UI automation tests with Vega Capsule, run:
```bash
yarn nx run explorer-e2e:e2e
```
To open Cypress and run in interactive mode, run:
```bash
yarn nx run explorer-e2e:e2e --watch
```
## Vega Capsule Setup
The e2e tests run against a locally running instance of the Vega network, managed and controlled by [Vega Capsule](https://github.com/vegaprotocol/vegacapsule). Vega Capsule will:
- Bootstrap and start up a Vega network
- Start up [Ganache](https://trufflesuite.com/ganache/) for a local Ethereum network
- Install the required Vega smart contracts
- Set up DataNodes with a running GraphQL and REST APIs.
1. Refer to the [Vega Capsule readme](https://github.com/vegaprotocol/vegacapsule#readme) for setting up and running Capsule - follow by Pre-start and Quick Start (points 1-2)
2. Bootstrap with auto-installed dependencies including wallet
```bash
vegacapsule network bootstrap --config-path=../frontend-monorepo/vegacapsule/config.hcl --force
```
### Troubleshooting
- You may need to run `vegacapsule nodes unsafe-reset-all` to get a clean network state
## Vega Wallet Setup
You can then refer to (or run) `frontend-monorepo/vegacapsule/setup-vegawallet.sh`. This will initialise and configure your wallet to have the correct public keys and network config to run against capsule.
Go to the .env file in `apps/explorer-e2e` and set the `CYPRESS_VEGA_WALLET_API_TOKEN` environment variable by pasting in your wallets long lived api token
+1 -1
View File
@@ -5,7 +5,7 @@ module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
require('@cypress/grep/src/plugin')(config);
require('cypress-grep/src/plugin')(config);
return config;
},
baseUrl: 'http://localhost:3000',
@@ -29,7 +29,7 @@
"market.liquidity.maximumLiquidityFeeFactorLevel",
"market.liquidity.minimum.probabilityOfTrading.lpOrders",
"market.liquidity.probabilityOfTrading.tau.scaling",
"market.liquidity.stakeToCcyVolume",
"market.liquidity.stakeToCcySiskas",
"market.liquidity.targetstake.triggering.ratio",
"market.liquidityProvision.minLpStakeQuantumMultiple",
"market.liquidityProvision.shapes.maxSize",
+11 -14
View File
@@ -47,37 +47,34 @@ context('Asset page', { tags: '@regression' }, function () {
.then((assetsListedInJson) => {
const assetInfo = this.assetsInfo[assetName];
assert.equal(assetsListedInJson.name, assetInfo.node.name);
assert.equal(assetsListedInJson.id, assetInfo.node.id);
assert.equal(
assetsListedInJson.decimals,
assetInfo.node.decimals
);
assert.equal(assetsListedInJson.symbol, assetInfo.node.symbol);
assert.equal(assetsListedInJson.name, assetInfo.name);
assert.equal(assetsListedInJson.id, assetInfo.id);
assert.equal(assetsListedInJson.decimals, assetInfo.decimals);
assert.equal(assetsListedInJson.symbol, assetInfo.symbol);
assert.equal(
assetsListedInJson.source.__typename,
assetInfo.node.source.__typename
assetInfo.source.__typename
);
if (assetInfo.node.source.__typename == 'ERC20') {
if (assetInfo.source.__typename == 'ERC20') {
assert.equal(
assetsListedInJson.source.contractAddress,
assetInfo.node.source.contractAddress
assetInfo.source.contractAddress
);
}
if (assetInfo.node.source.__typename == 'BuiltinAsset') {
if (assetInfo.source.__typename == 'BuiltinAsset') {
assert.equal(
assetsListedInJson.source.maxFaucetAmountMint,
assetInfo.node.source.maxFaucetAmountMint
assetInfo.source.maxFaucetAmountMint
);
}
let knownAssetTypes = ['BuiltinAsset', 'ERC20'];
assert.include(
knownAssetTypes,
assetInfo.node.source.__typename,
`Checking that current asset type of ${assetInfo.node.source.__typename} /
assetInfo.source.__typename,
`Checking that current asset type of ${assetInfo.source.__typename} /
is one of: ${knownAssetTypes}: /
If fail then we need to add extra tests for un-encountered asset types`
);
@@ -52,8 +52,7 @@ context('Blocks page', { tags: '@regression' }, function () {
});
});
// Skipping - see https://github.com/vegaprotocol/frontend-monorepo/issues/2494
it.skip('Previous button disabled on first block', function () {
it('Previous button disabled on first block', function () {
cy.get('[data-testid="block-input"]').type('1');
cy.get('[data-testid="go-submit"]').click();
cy.get(previousBlockBtn).find('button').should('be.disabled');
@@ -116,7 +115,7 @@ context('Blocks page', { tags: '@regression' }, function () {
});
function waitForBlocksResponse() {
cy.get('[data-testid="loader"]').should('not.exist', { timeout: 18000 });
cy.contains('Loading...').should('not.exist', { timeout: 18000 });
}
function validateBlocksDisplayed() {
+30 -26
View File
@@ -18,20 +18,22 @@ context('Home Page', function () {
const statTitles = {
0: 'Status',
1: 'Height',
2: 'Uptime',
3: 'Total nodes',
4: 'Total staked',
5: 'Backlog',
6: 'Trades / second',
7: 'Orders / block',
8: 'Orders / second',
9: 'Transactions / block',
10: 'Block time',
11: 'Time',
12: 'App',
13: 'Tendermint',
14: 'Up since',
15: 'Chain ID',
2: 'Validating nodes',
3: 'Uptime',
4: 'Total nodes',
5: 'Inactive nodes',
6: 'Total staked',
7: 'Backlog',
8: 'Trades / second',
9: 'Orders / block',
10: 'Orders / second',
11: 'Transactions / block',
12: 'Block time',
13: 'Time',
14: 'App',
15: 'Tendermint',
16: 'Up since',
17: 'Chain ID',
};
cy.get('[data-testid="stats-title"]')
@@ -39,39 +41,41 @@ context('Home Page', function () {
cy.wrap($list).should('have.text', statTitles[index]);
})
.then(($list) => {
cy.wrap($list).should('have.length', 16);
cy.wrap($list).should('have.length', 18);
});
cy.get(statsValue).eq(0).should('have.text', 'CONNECTED');
cy.get(statsValue).eq(1).should('not.be.empty');
cy.get(statsValue).eq(2).should('have.text', '2');
cy.get(statsValue)
.eq(2)
.eq(3)
.invoke('text')
.should('match', /\d+d \d+h \d+m \d+s/i);
cy.get(statsValue).eq(3).should('have.text', '2');
cy.get(statsValue).eq(4).should('have.text', '2');
cy.get(statsValue).eq(5).should('have.text', '0');
cy.get(statsValue)
.eq(4)
.eq(6)
.invoke('text')
.should('match', /\d+\.\d\d(?!\d)/i);
cy.get(statsValue).eq(5).should('have.text', '0');
cy.get(statsValue).eq(6).should('have.text', '0');
cy.get(statsValue).eq(7).should('have.text', '0');
cy.get(statsValue).eq(8).should('have.text', '0');
cy.get(statsValue).eq(9).should('not.be.empty');
cy.get(statsValue).eq(10).should('not.be.empty');
cy.get(statsValue).eq(9).should('have.text', '0');
cy.get(statsValue).eq(10).should('have.text', '0');
cy.get(statsValue).eq(11).should('not.be.empty');
cy.get(statsValue).eq(12).should('not.be.empty');
cy.get(statsValue).eq(13).should('not.be.empty');
if (Cypress.env('NIGHTLY_RUN') != true) {
cy.get(statsValue)
.eq(12)
.eq(14)
.invoke('text')
.should('match', /v\d+\.\d+\.\d+/i);
}
cy.get(statsValue)
.eq(13)
.eq(15)
.invoke('text')
.should('match', /\d+\.\d+\.\d+/i);
cy.get(statsValue).eq(14).should('not.be.empty');
cy.get(statsValue).eq(15).should('not.be.empty');
cy.get(statsValue).eq(16).should('not.be.empty');
cy.get(statsValue).eq(17).should('not.be.empty');
});
it('Block height should be updating', function () {
@@ -148,7 +148,7 @@ context('Network parameters page', { tags: '@smoke' }, function () {
const parameterName = network_parameter[0];
const parameterValue = network_parameter[1];
if (this.networkParameterFormat.fiveDecimal.includes(parameterName)) {
cy.convert_number_to_max_four_decimal(parameterValue)
cy.convert_number_to_four_decimal(parameterValue)
.add_commas_to_number_if_large_enough()
.then((parameterValueFormatted) => {
cy.get(tableRows)
@@ -179,7 +179,7 @@ context('Network parameters page', { tags: '@smoke' }, function () {
if (
this.networkParameterFormat.eighteenDecimal.includes(parameterName)
) {
cy.convert_number_to_max_eighteen_decimal(parameterValue)
cy.convert_number_to_eighteen_decimal(parameterValue)
.add_commas_to_number_if_large_enough()
.then((parameterValueFormatted) => {
cy.get(tableRows)
@@ -212,7 +212,7 @@ context('Network parameters page', { tags: '@smoke' }, function () {
const jsonFields = '.hljs';
const sideMenuBackground = '.absolute';
// Engage dark mode if not already set
// Engage dark mode if not allready set
cy.get(sideMenuBackground)
.should('have.css', 'background-color')
.then((background_color) => {
@@ -14,9 +14,7 @@ let assetData = {
const assetsInTest = Object.keys(assetData);
// skipped due to existing issue
// https://github.com/vegaprotocol/frontend-monorepo/issues/2243
context.skip('Parties page', { tags: '@regression' }, function () {
context('Parties page', { tags: '@regression' }, function () {
before('send-faucet assets to connected vega wallet', function () {
assetsInTest.forEach((asset) => {
cy.vega_wallet_receive_fauceted_asset(
@@ -204,6 +202,15 @@ context.skip('Parties page', { tags: '@regression' }, function () {
.and('include', darkThemeSideMenuBackgroundColor);
});
after(
'teardown environment to prevent test data bleeding into other tests',
function () {
if (Cypress.env('TEARDOWN_NETWORK_AFTER_FLOWS')) {
cy.restart_vegacapsule_network();
}
}
);
Cypress.Commands.add('get_asset_decimals', (assetID) => {
cy.get_asset_information().then((assetsInfo) => {
const assetDecimals = assetsInfo[assetData[assetID].name].decimals;

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