Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fc7a5f5627 |
@@ -1,31 +0,0 @@
|
||||
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
|
||||
if: ${{ inputs.all }}
|
||||
shell: bash
|
||||
run: |
|
||||
wget 'https://github.com/vegaprotocol/vega/releases/download/${{ env.VEGA_VERSION }}/vega-linux-amd64.zip' -q
|
||||
unzip vega-linux-amd64.zip -d ${{ inputs.gobin }}
|
||||
|
||||
- name: Install date-node binaries
|
||||
if: ${{ inputs.all }}
|
||||
shell: bash
|
||||
run: |
|
||||
wget 'https://github.com/vegaprotocol/vega/releases/download/${{ env.VEGA_VERSION }}/data-node-linux-amd64.zip' -q
|
||||
unzip data-node-linux-amd64.zip -d ${{ inputs.gobin }}
|
||||
|
||||
- name: Install Vega wallet binaries
|
||||
shell: bash
|
||||
run: |
|
||||
wget 'https://github.com/vegaprotocol/vega/releases/download/${{ env.VEGA_VERSION }}/vegawallet-linux-amd64.zip' -q
|
||||
unzip vegawallet-linux-amd64.zip -d ${{ inputs.gobin }}
|
||||
@@ -1,30 +0,0 @@
|
||||
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 &
|
||||
|
||||
- name: Bootstrap network
|
||||
shell: bash
|
||||
run: vegacapsule network bootstrap --config-path=./frontend-monorepo/vegacapsule/config.hcl --force
|
||||
@@ -1,45 +0,0 @@
|
||||
inputs:
|
||||
recovery:
|
||||
description: 'Recovery phrase'
|
||||
passphrase:
|
||||
description: 'Wallet password'
|
||||
capsule:
|
||||
description: 'Is Capsule network used'
|
||||
default: false
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Create passphrase
|
||||
shell: bash
|
||||
run: echo "${{ inputs.passphrase }}" > ./passphrase
|
||||
|
||||
- name: Create recovery
|
||||
shell: bash
|
||||
run: echo "${{ inputs.recovery }}" > ./recovery
|
||||
|
||||
- name: Initialize wallet
|
||||
shell: bash
|
||||
run: vegawallet init -f --home ~/.vegacapsule/testnet/wallet
|
||||
|
||||
- name: Import wallet
|
||||
shell: bash
|
||||
run: vegawallet import -w UI_Trading_Test --recovery-phrase-file ./recovery -p ./passphrase --home ~/.vegacapsule/testnet/wallet
|
||||
|
||||
- name: Create public key 2
|
||||
shell: bash
|
||||
run: vegawallet key generate -w UI_Trading_Test -p ./passphrase --home ~/.vegacapsule/testnet/wallet
|
||||
|
||||
- name: Import fairground network
|
||||
shell: bash
|
||||
if: ${{ inputs.capsule==false }}
|
||||
run: vegawallet network import --from-url="https://raw.githubusercontent.com/vegaprotocol/networks/master/fairground/fairground.toml" --force --home ~/.vegacapsule/testnet/wallet
|
||||
|
||||
- name: Start service using fairground network
|
||||
shell: bash
|
||||
if: ${{ inputs.capsule==false }}
|
||||
run: vegawallet service run --network fairground --automatic-consent --home ~/.vegacapsule/testnet/wallet &
|
||||
|
||||
- name: Start service using capsule network
|
||||
shell: bash
|
||||
if: ${{ inputs.capsule }}
|
||||
run: vegawallet service run --network DV --automatic-consent --home ~/.vegacapsule/testnet/wallet &
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Cypress tests -- manual trigger
|
||||
name: Capsule tests -- manual trigger
|
||||
|
||||
# This workflow runs the frontend tests against chosen branch
|
||||
|
||||
@@ -15,43 +15,20 @@ on:
|
||||
- stats-e2e
|
||||
- token-e2e
|
||||
- trading-e2e
|
||||
smokeOnly:
|
||||
runAlltests:
|
||||
description: 'Run only smoke tests?'
|
||||
required: true
|
||||
type: boolean
|
||||
default: false
|
||||
skip-nx-cache:
|
||||
description: 'Add --skip-nx-cache to cypress test'
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
manual:
|
||||
name: Run Cypress tests -- manual trigger
|
||||
name: Run capsule tests -- manual trigger
|
||||
runs-on: self-hosted
|
||||
env:
|
||||
GO111MODULE: 'on'
|
||||
GOBIN: /home/runner/go/bin
|
||||
VEGA_VERSION: 'v0.57.0'
|
||||
steps:
|
||||
#######
|
||||
## Setup flags
|
||||
#######
|
||||
|
||||
- name: Set smoke tag
|
||||
if: ${{ github.event.inputs.smokeOnly == 'true' }}
|
||||
run: echo TAGS="--env.grepTags @smoke" >> $GITHUB_ENV
|
||||
|
||||
- name: Set --skip-nx-cache flag
|
||||
if: ${{ github.event.inputs.skip-nx-cache == 'true' }}
|
||||
run: echo SKIP_NX_CACHE="--skip-nx-cache" >> $GITHUB_ENV
|
||||
|
||||
# See if we capsule is needed for this project
|
||||
- name: Set capsule flag
|
||||
if: ${{ github.event.inputs.project == 'explorer-e2e' || github.event.inputs.project == 'token-e2e' }}
|
||||
run: echo RUN_CAPSULE=true >> $GITHUB_ENV
|
||||
|
||||
#######
|
||||
## Setup langs
|
||||
#######
|
||||
@@ -60,7 +37,6 @@ jobs:
|
||||
id: go
|
||||
with:
|
||||
go-version: 1.19
|
||||
|
||||
- name: Set up Node 16
|
||||
uses: actions/setup-node@v2
|
||||
id: npm
|
||||
@@ -81,9 +57,25 @@ jobs:
|
||||
- name: Checkout frontend mono repo
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.ref }}
|
||||
fetch-depth: 0
|
||||
path: './frontend-monorepo'
|
||||
|
||||
# See if we capsule is needed for this project
|
||||
- name: See if capsule is necessary
|
||||
if: ${{ github.event.inputs.project == 'explorer-e2e' || github.event.inputs.project == 'token-e2e' }}
|
||||
run: echo RUN_CAPSULE=true >> $GITHUB_ENV
|
||||
|
||||
# Checkout capsule to build local network
|
||||
- name: Checkout capsule
|
||||
if: ${{ env.RUN_CAPSULE }}
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: vegaprotocol/vegacapsule
|
||||
ref: main
|
||||
token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
|
||||
path: './capsule'
|
||||
|
||||
# Restore node_modules from cache if possible
|
||||
- name: Restore node_modules from cache
|
||||
uses: actions/cache@v3
|
||||
@@ -99,32 +91,75 @@ jobs:
|
||||
working-directory: frontend-monorepo
|
||||
|
||||
#######
|
||||
## Build and run Vegacapsule network
|
||||
## Build binaries
|
||||
#######
|
||||
- name: Build capsule
|
||||
if: ${{ env.RUN_CAPSULE }}
|
||||
run: go install
|
||||
working-directory: capsule
|
||||
|
||||
- name: Set GOBIN
|
||||
run: echo GOBIN=$(go env GOPATH)/bin >> $GITHUB_ENV
|
||||
|
||||
- name: Install Vega binaries
|
||||
uses: ./frontend-monorepo/.github/actions/install-vega-binaries
|
||||
with:
|
||||
all: ${{ env.RUN_CAPSULE }}
|
||||
version: ${{ env.VEGA_VERSION }}
|
||||
gobin: ${{ env.GOBIN }}
|
||||
|
||||
- name: Build and run Vegacapsule network
|
||||
if: ${{ env.RUN_CAPSULE }}
|
||||
uses: ./frontend-monorepo/.github/actions/run-vegacapsule
|
||||
with:
|
||||
github-token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
|
||||
run: |
|
||||
wget 'https://github.com/vegaprotocol/vega/releases/download/${{ env.VEGA_VERSION }}/vega-linux-amd64.zip'
|
||||
unzip vega-linux-amd64.zip -d ${{ env.GOBIN }}
|
||||
|
||||
- name: Install date-node binaries
|
||||
if: ${{ env.RUN_CAPSULE }}
|
||||
run: |
|
||||
wget 'https://github.com/vegaprotocol/vega/releases/download/${{ env.VEGA_VERSION }}/data-node-linux-amd64.zip'
|
||||
unzip data-node-linux-amd64.zip -d ${{ env.GOBIN }}
|
||||
|
||||
- name: Install Vega wallet binaries
|
||||
run: |
|
||||
wget 'https://github.com/vegaprotocol/vega/releases/download/${{ env.VEGA_VERSION }}/vegawallet-linux-amd64.zip'
|
||||
unzip vegawallet-linux-amd64.zip -d ${{ env.GOBIN }}
|
||||
|
||||
######
|
||||
## Start capsule
|
||||
######
|
||||
- name: Login to docker
|
||||
if: ${{ env.RUN_CAPSULE }}
|
||||
run: echo -n ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }} | docker login https://ghcr.io -u vega-ci-bot --password-stdin
|
||||
|
||||
- name: Start nomad
|
||||
if: ${{ env.RUN_CAPSULE }}
|
||||
run: vegacapsule nomad &
|
||||
|
||||
- name: Bootstrap network
|
||||
if: ${{ env.RUN_CAPSULE }}
|
||||
run: vegacapsule network bootstrap --config-path=../frontend-monorepo/vegacapsule/config.hcl --force
|
||||
working-directory: capsule
|
||||
|
||||
######
|
||||
## Setup a Vega wallet for our user
|
||||
######
|
||||
- name: Create passphrase
|
||||
run: echo "${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}" > ./passphrase
|
||||
- name: Create recovery
|
||||
run: echo "${{ secrets.TRADING_TEST_VEGA_WALLET_RECOVERY }}" > ./recovery
|
||||
|
||||
- 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 }}
|
||||
capsule: ${{ env.RUN_CAPSULE }}
|
||||
- name: Initialize wallet
|
||||
run: vegawallet init -f --home ~/.vegacapsule/testnet/wallet
|
||||
- name: Import wallet
|
||||
run: vegawallet import -w UI_Trading_Test --recovery-phrase-file ./recovery -p ./passphrase --home ~/.vegacapsule/testnet/wallet
|
||||
- name: Create public key 2
|
||||
run: vegawallet key generate -w UI_Trading_Test -p ./passphrase --home ~/.vegacapsule/testnet/wallet
|
||||
|
||||
- name: Import fairground network
|
||||
if: ${{ env.RUN_CAPSULE==false }}
|
||||
run: vegawallet network import --from-url="https://raw.githubusercontent.com/vegaprotocol/networks/master/fairground/fairground.toml" --force --home ~/.vegacapsule/testnet/wallet
|
||||
|
||||
- name: Start service using fairground network
|
||||
if: ${{ env.RUN_CAPSULE==false }}
|
||||
run: vegawallet service run --network fairground --automatic-consent --home ~/.vegacapsule/testnet/wallet &
|
||||
|
||||
- name: Start service using capsule network
|
||||
if: ${{ env.RUN_CAPSULE }}
|
||||
run: vegawallet service run --network DV --automatic-consent --home ~/.vegacapsule/testnet/wallet &
|
||||
|
||||
######
|
||||
## Run some tests
|
||||
@@ -135,13 +170,24 @@ jobs:
|
||||
run: yarn cypress install
|
||||
working-directory: frontend-monorepo
|
||||
|
||||
- name: Run Cypress tests
|
||||
run: yarn nx run ${{ github.event.inputs.project }}:e2e ${{ env.SKIP_NX_CACHE }} --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome ${{ env.TAGS }}
|
||||
- name: Run smoke Cypress tests
|
||||
if: ${{ github.event.inputs.runAlltests == 'true' }}
|
||||
run: yarn nx run ${{ github.event.inputs.project }}:e2e --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --env.grepTags='@smoke' --browser chrome
|
||||
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_ETH_WALLET_MNEMONIC: ${{ secrets.CYPESS_ETH_WALLET_MNEMONIC }}
|
||||
CYPRESS_TEARDOWN_NETWORK_AFTER_FLOWS: true
|
||||
|
||||
- name: Run Cypress tests
|
||||
if: ${{ github.event.inputs.runAlltests == 'false' }}
|
||||
run: yarn nx run ${{ github.event.inputs.project }}:e2e --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome
|
||||
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.CYPESS_ETH_WALLET_MNEMONIC }}
|
||||
CYPRESS_TEARDOWN_NETWORK_AFTER_FLOWS: true
|
||||
|
||||
######
|
||||
|
||||
@@ -1,22 +1,18 @@
|
||||
name: Cypress tests -- night run
|
||||
name: Capsule tests -- night run
|
||||
|
||||
# This workflow runs the frontend tests against latest develop of the core to preempt breaking changes
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 4 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
nightly:
|
||||
name: Run Cypress tests -- nightly
|
||||
name: Run capsule tests -- nightly
|
||||
runs-on: self-hosted
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
GO111MODULE: 'on'
|
||||
GOBIN: /home/runner/go/bin
|
||||
VEGA_VERSION: 'v0.57.0'
|
||||
RUN_CAPSULE: true
|
||||
steps:
|
||||
#######
|
||||
## Setup langs
|
||||
@@ -46,9 +42,19 @@ jobs:
|
||||
- name: Checkout frontend mono repo
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.ref }}
|
||||
fetch-depth: 0
|
||||
path: './frontend-monorepo'
|
||||
|
||||
# Checkout capsule to build local network
|
||||
- name: Checkout capsule
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: vegaprotocol/vegacapsule
|
||||
ref: main
|
||||
token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
|
||||
path: './capsule'
|
||||
|
||||
# Restore node_modules from cache if possible
|
||||
- name: Restore node_modules from cache
|
||||
uses: actions/cache@v3
|
||||
@@ -64,32 +70,59 @@ jobs:
|
||||
working-directory: frontend-monorepo
|
||||
|
||||
#######
|
||||
## Build and run Vegacapsule network
|
||||
## Build binaries
|
||||
#######
|
||||
- name: Build capsule
|
||||
run: go install
|
||||
working-directory: capsule
|
||||
|
||||
- name: Set GOBIN
|
||||
run: echo GOBIN=$(go env GOPATH)/bin >> $GITHUB_ENV
|
||||
|
||||
- name: Install Vega binaries
|
||||
uses: ./frontend-monorepo/.github/actions/install-vega-binaries
|
||||
with:
|
||||
all: ${{ env.RUN_CAPSULE }}
|
||||
version: ${{ env.VEGA_VERSION }}
|
||||
gobin: ${{ env.GOBIN }}
|
||||
run: |
|
||||
wget 'https://github.com/vegaprotocol/vega/releases/download/${{ env.VEGA_VERSION }}/vega-linux-amd64.zip'
|
||||
unzip vega-linux-amd64.zip -d ${{ env.GOBIN }}
|
||||
|
||||
- name: Build and run Vegacapsule network
|
||||
if: ${{ env.RUN_CAPSULE }}
|
||||
uses: ./frontend-monorepo/.github/actions/run-vegacapsule
|
||||
with:
|
||||
github-token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
|
||||
- name: Install date-node binaries
|
||||
run: |
|
||||
wget 'https://github.com/vegaprotocol/vega/releases/download/${{ env.VEGA_VERSION }}/data-node-linux-amd64.zip'
|
||||
unzip data-node-linux-amd64.zip -d ${{ env.GOBIN }}
|
||||
|
||||
- name: Install Vega wallet binaries
|
||||
run: |
|
||||
wget 'https://github.com/vegaprotocol/vega/releases/download/${{ env.VEGA_VERSION }}/vegawallet-linux-amd64.zip'
|
||||
unzip vegawallet-linux-amd64.zip -d ${{ env.GOBIN }}
|
||||
|
||||
######
|
||||
## Start capsule
|
||||
######
|
||||
- name: Login to docker
|
||||
run: echo -n ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }} | docker login https://ghcr.io -u vega-ci-bot --password-stdin
|
||||
|
||||
- name: Start nomad
|
||||
run: vegacapsule nomad &
|
||||
|
||||
- name: Bootstrap network
|
||||
run: vegacapsule network bootstrap --config-path=../frontend-monorepo/vegacapsule/config.hcl --force
|
||||
working-directory: capsule
|
||||
|
||||
######
|
||||
## Setup a Vega wallet for our user
|
||||
######
|
||||
- name: Create passphrase
|
||||
run: echo "${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}" > ./passphrase
|
||||
- name: Create recovery
|
||||
run: echo "${{ secrets.TRADING_TEST_VEGA_WALLET_RECOVERY }}" > ./recovery
|
||||
|
||||
- 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 }}
|
||||
capsule: ${{ env.RUN_CAPSULE }}
|
||||
- name: Initialize wallet
|
||||
run: vegawallet init -f --home ~/.vegacapsule/testnet/wallet
|
||||
- name: Import wallet
|
||||
run: vegawallet import -w UI_Trading_Test --recovery-phrase-file ./recovery -p ./passphrase --home ~/.vegacapsule/testnet/wallet
|
||||
- name: Create public key 2
|
||||
run: vegawallet key generate -w UI_Trading_Test -p ./passphrase --home ~/.vegacapsule/testnet/wallet
|
||||
- name: Start service
|
||||
run: vegawallet service run --network DV --automatic-consent --home ~/.vegacapsule/testnet/wallet &
|
||||
|
||||
######
|
||||
## Run some tests
|
||||
@@ -101,12 +134,12 @@ jobs:
|
||||
working-directory: frontend-monorepo
|
||||
|
||||
- name: Run Cypress tests
|
||||
run: yarn nx run-many --skip-nx-cache --target=e2e --all --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome
|
||||
run: yarn nx run-many --target=e2e --all --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome
|
||||
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_ETH_WALLET_MNEMONIC: ${{ secrets.CYPESS_ETH_WALLET_MNEMONIC }}
|
||||
CYPRESS_NIGHTLY_RUN: true
|
||||
CYPRESS_TEARDOWN_NETWORK_AFTER_FLOWS: true
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Cypress tests
|
||||
name: Capsule tests
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -14,12 +14,10 @@ on:
|
||||
|
||||
jobs:
|
||||
pr:
|
||||
name: Run Cypress tests - PR
|
||||
name: Run capsule tests - PR
|
||||
runs-on: self-hosted
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
GO111MODULE: 'on'
|
||||
GOBIN: /home/runner/go/bin
|
||||
VEGA_VERSION: 'v0.57.0'
|
||||
steps:
|
||||
#######
|
||||
@@ -30,7 +28,6 @@ jobs:
|
||||
id: go
|
||||
with:
|
||||
go-version: 1.19
|
||||
|
||||
- name: Set up Node 16
|
||||
uses: actions/setup-node@v2
|
||||
id: npm
|
||||
@@ -51,6 +48,7 @@ jobs:
|
||||
- name: Checkout frontend mono repo
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.ref }}
|
||||
fetch-depth: 0
|
||||
path: './frontend-monorepo'
|
||||
|
||||
@@ -68,55 +66,106 @@ jobs:
|
||||
run: yarn install --frozen-lockfile
|
||||
working-directory: frontend-monorepo
|
||||
|
||||
# Check SHAs
|
||||
- name: Derive appropriate SHAs for base and head for `nx affected` commands
|
||||
uses: nrwl/nx-set-shas@v2
|
||||
with:
|
||||
working-directory: frontend-monorepo
|
||||
main-branch-name: ${{ github.base_ref || github.ref_name }}
|
||||
set-environment-variables-for-job: true
|
||||
|
||||
# See if we capsule is needed for this project
|
||||
# See affected apps to see if building all binaries is necessary
|
||||
- name: See affected apps
|
||||
run: echo AFFECTED=$(yarn nx print-affected --base=${{ env.NX_BASE }} --head=${{ env.NX_HEAD }} --select=projects) >> $GITHUB_ENV
|
||||
run: echo AFFECTED=$(yarn nx print-affected --base=origin/${{github.base_ref}} --head=${{github.head_ref}} --select=projects) >> $GITHUB_ENV
|
||||
working-directory: frontend-monorepo
|
||||
|
||||
- name: See if capsule is necessary
|
||||
if: ${{ contains(env.AFFECTED, 'token') || contains(env.AFFECTED, 'token-e2e') || contains(env.AFFECTED, 'explorer') || contains(env.AFFECTED, 'explorer-e2e') }}
|
||||
run: echo RUN_CAPSULE=true >> $GITHUB_ENV
|
||||
|
||||
# Checkout capsule to build local network
|
||||
- name: Checkout capsule
|
||||
if: ${{ env.RUN_CAPSULE }}
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: vegaprotocol/vegacapsule
|
||||
ref: main
|
||||
token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
|
||||
path: './capsule'
|
||||
|
||||
#######
|
||||
## Build and run Vegacapsule network
|
||||
## Build binaries
|
||||
#######
|
||||
- name: Build capsule
|
||||
if: ${{ env.RUN_CAPSULE }}
|
||||
run: go install
|
||||
working-directory: capsule
|
||||
|
||||
- name: Set GOBIN
|
||||
run: echo GOBIN=$(go env GOPATH)/bin >> $GITHUB_ENV
|
||||
|
||||
- name: Install Vega binaries
|
||||
uses: ./frontend-monorepo/.github/actions/install-vega-binaries
|
||||
with:
|
||||
all: ${{ env.RUN_CAPSULE }}
|
||||
version: ${{ env.VEGA_VERSION }}
|
||||
gobin: ${{ env.GOBIN }}
|
||||
|
||||
- name: Build and run Vegacapsule network
|
||||
if: ${{ env.RUN_CAPSULE }}
|
||||
uses: ./frontend-monorepo/.github/actions/run-vegacapsule
|
||||
with:
|
||||
github-token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
|
||||
run: |
|
||||
wget 'https://github.com/vegaprotocol/vega/releases/download/${{ env.VEGA_VERSION }}/vega-linux-amd64.zip'
|
||||
unzip vega-linux-amd64.zip -d ${{ env.GOBIN }}
|
||||
|
||||
- name: Install date-node binaries
|
||||
if: ${{ env.RUN_CAPSULE }}
|
||||
run: |
|
||||
wget 'https://github.com/vegaprotocol/vega/releases/download/${{ env.VEGA_VERSION }}/data-node-linux-amd64.zip'
|
||||
unzip data-node-linux-amd64.zip -d ${{ env.GOBIN }}
|
||||
|
||||
- name: Install Vega wallet binaries
|
||||
run: |
|
||||
wget 'https://github.com/vegaprotocol/vega/releases/download/${{ env.VEGA_VERSION }}/vegawallet-linux-amd64.zip'
|
||||
unzip vegawallet-linux-amd64.zip -d ${{ env.GOBIN }}
|
||||
|
||||
######
|
||||
## Start capsule
|
||||
######
|
||||
- name: Login to docker
|
||||
if: ${{ env.RUN_CAPSULE }}
|
||||
run: echo -n ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }} | docker login https://ghcr.io -u vega-ci-bot --password-stdin
|
||||
|
||||
- name: Start nomad
|
||||
if: ${{ env.RUN_CAPSULE }}
|
||||
run: vegacapsule nomad &
|
||||
|
||||
- name: Bootstrap network
|
||||
if: ${{ env.RUN_CAPSULE }}
|
||||
run: vegacapsule network bootstrap --config-path=../frontend-monorepo/vegacapsule/config.hcl --force
|
||||
working-directory: capsule
|
||||
|
||||
######
|
||||
## Setup a Vega wallet for our user
|
||||
######
|
||||
- name: Create passphrase
|
||||
run: echo "${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}" > ./passphrase
|
||||
- name: Create recovery
|
||||
run: echo "${{ secrets.TRADING_TEST_VEGA_WALLET_RECOVERY }}" > ./recovery
|
||||
|
||||
- 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 }}
|
||||
capsule: ${{ env.RUN_CAPSULE }}
|
||||
- name: Initialize wallet
|
||||
run: vegawallet init -f --home ~/.vegacapsule/testnet/wallet
|
||||
- name: Import wallet
|
||||
run: vegawallet import -w UI_Trading_Test --recovery-phrase-file ./recovery -p ./passphrase --home ~/.vegacapsule/testnet/wallet
|
||||
- name: Create public key 2
|
||||
run: vegawallet key generate -w UI_Trading_Test -p ./passphrase --home ~/.vegacapsule/testnet/wallet
|
||||
|
||||
- name: Import fairground network
|
||||
if: ${{ env.RUN_CAPSULE==false }}
|
||||
run: vegawallet network import --from-url="https://raw.githubusercontent.com/vegaprotocol/networks/master/fairground/fairground.toml" --force --home ~/.vegacapsule/testnet/wallet
|
||||
|
||||
- name: Start service using fairground network
|
||||
if: ${{ env.RUN_CAPSULE==false }}
|
||||
run: vegawallet service run --network fairground --automatic-consent --home ~/.vegacapsule/testnet/wallet &
|
||||
|
||||
- name: Start service using capsule network
|
||||
if: ${{ env.RUN_CAPSULE }}
|
||||
run: vegawallet service run --network DV --automatic-consent --home ~/.vegacapsule/testnet/wallet &
|
||||
|
||||
######
|
||||
## Run some tests
|
||||
######
|
||||
|
||||
- name: Derive appropriate SHAs for base and head for `nx affected` commands
|
||||
uses: nrwl/nx-set-shas@v2
|
||||
with:
|
||||
working-directory: frontend-monorepo
|
||||
main-branch-name: ${{github.base_ref}}
|
||||
|
||||
# To make sure that all Cypress binaries are installed properly
|
||||
- name: Install cypress bins
|
||||
run: yarn cypress install
|
||||
@@ -128,8 +177,8 @@ jobs:
|
||||
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: false
|
||||
CYPRESS_ETH_WALLET_MNEMONIC: ${{ secrets.CYPESS_ETH_WALLET_MNEMONIC }}
|
||||
CYPRESS_TEARDOWN_NETWORK_AFTER_FLOWS: true
|
||||
|
||||
######
|
||||
## Upload logs
|
||||
|
||||
@@ -30,10 +30,6 @@ An application for the status of the Vega network. Showing block height and othe
|
||||
|
||||
Hosting for static content being shared across apps, for example fonts.
|
||||
|
||||
### [Multisig-signer](./apps/multisig-signer)
|
||||
|
||||
The utility dApp for validators wishing to add or remove themselves as a signer of the multisig contract.
|
||||
|
||||
# 🧱 Libraries in this repo
|
||||
|
||||
### [UI toolkit](./libs/ui-toolkit)
|
||||
|
||||
@@ -21,6 +21,6 @@ NX_URL=$URL
|
||||
NX_DEPLOY_URL=$DEPLOY_URL
|
||||
NX_DEPLOY_PRIME_URL=$DEPLOY_PRIME_URL
|
||||
|
||||
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
|
||||
NX_VEGA_URL=https://api.n11.testnet.vega.xyz/graphql
|
||||
NX_VEGA_ENV=TESTNET
|
||||
NX_VEGA_WALLET_URL=http://localhost:1789
|
||||
NX_VEGA_WALLET_URL=http://localhost:1789/api/v1
|
||||
|
||||
@@ -25,7 +25,7 @@ module.exports = defineConfig({
|
||||
env: {
|
||||
TRADING_TEST_VEGA_WALLET_NAME: 'UI_Trading_Test',
|
||||
ETHEREUM_PROVIDER_URL:
|
||||
'https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8',
|
||||
'https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8',
|
||||
VEGA_PUBLIC_KEY:
|
||||
'47836c253520d2661bf5bed6339c0de08fd02cf5d4db0efee3b4373f20c7d278',
|
||||
VEGA_PUBLIC_KEY2:
|
||||
@@ -33,7 +33,7 @@ module.exports = defineConfig({
|
||||
TRUNCATED_VEGA_PUBLIC_KEY: '47836c…c7d278',
|
||||
TRUNCATED_VEGA_PUBLIC_KEY2: '1a18cd…0cf2e4',
|
||||
ETHEREUM_WALLET_ADDRESS: '0x265Cc6d39a1B53d0d92068443009eE7410807158',
|
||||
ETHERSCAN_URL: 'https://sepolia.etherscan.io',
|
||||
ETHERSCAN_URL: 'https://ropsten.etherscan.io',
|
||||
tsConfig: 'tsconfig.json',
|
||||
TAGS: 'not @todo and not @ignore and not @manual',
|
||||
TRADING_TEST_VEGA_WALLET_PASSPHRASE: '123',
|
||||
|
||||
@@ -1,17 +1,5 @@
|
||||
import { aliasQuery } from '@vegaprotocol/cypress';
|
||||
import {
|
||||
generateSimpleMarkets,
|
||||
generateMarketsCandles,
|
||||
} from '../support/mocks/generate-markets';
|
||||
|
||||
describe('simple trading app', { tags: '@smoke' }, () => {
|
||||
beforeEach(() => {
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'Markets', generateSimpleMarkets());
|
||||
aliasQuery(req, 'MarketsCandles', generateMarketsCandles());
|
||||
});
|
||||
cy.visit('/');
|
||||
});
|
||||
beforeEach(() => cy.visit('/'));
|
||||
|
||||
it('render', () => {
|
||||
cy.get('#root').should('exist');
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { aliasQuery } from '@vegaprotocol/cypress';
|
||||
import type { MarketsQuery } from '@vegaprotocol/market-list';
|
||||
import type { Markets } from '@vegaprotocol/market-list';
|
||||
import {
|
||||
generateLongListMarkets,
|
||||
generateSimpleMarkets,
|
||||
generateMarketsData,
|
||||
generateMarketsCandles,
|
||||
} from '../support/mocks/generate-markets';
|
||||
|
||||
@@ -11,7 +12,8 @@ describe('market list', { tags: '@smoke' }, () => {
|
||||
beforeEach(() => {
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'Markets', generateSimpleMarkets());
|
||||
aliasQuery(req, 'MarketsCandles', generateMarketsCandles());
|
||||
aliasQuery(req, 'MarketsDataQuery', generateMarketsData());
|
||||
aliasQuery(req, 'MarketsCandlesQuery', generateMarketsCandles());
|
||||
});
|
||||
cy.visit('/markets');
|
||||
});
|
||||
@@ -66,7 +68,8 @@ describe('market list', { tags: '@smoke' }, () => {
|
||||
beforeEach(() => {
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'Markets', generateSimpleMarkets());
|
||||
aliasQuery(req, 'MarketsCandles', generateMarketsCandles());
|
||||
aliasQuery(req, 'MarketsDataQuery', generateMarketsData());
|
||||
aliasQuery(req, 'MarketsCandlesQuery', generateMarketsCandles());
|
||||
});
|
||||
});
|
||||
|
||||
@@ -78,10 +81,10 @@ describe('market list', { tags: '@smoke' }, () => {
|
||||
it('last asset (if exists)', () => {
|
||||
cy.visit('/markets');
|
||||
cy.wait('@Markets').then((filters) => {
|
||||
const data: MarketsQuery | undefined = filters?.response?.body?.data;
|
||||
if (data?.marketsConnection?.edges.length) {
|
||||
const data: Markets | undefined = filters?.response?.body?.data;
|
||||
if (data.marketsConnection.edges.length) {
|
||||
const asset =
|
||||
data?.marketsConnection?.edges[0].node.tradableInstrument.instrument
|
||||
data.marketsConnection.edges[0].node.tradableInstrument.instrument
|
||||
.product.settlementAsset.symbol;
|
||||
cy.visit(`/markets/Suspended/Future/${asset}`);
|
||||
cy.getByTestId('market-assets-menu')
|
||||
@@ -104,7 +107,8 @@ describe('market list', { tags: '@smoke' }, () => {
|
||||
cy.viewport(1440, 900);
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'Markets', generateLongListMarkets(1000));
|
||||
aliasQuery(req, 'MarketsCandles', generateMarketsCandles());
|
||||
aliasQuery(req, 'MarketsDataQuery', generateMarketsData());
|
||||
aliasQuery(req, 'MarketsCandlesQuery', generateMarketsCandles());
|
||||
});
|
||||
performance.mark('start-1k');
|
||||
cy.visit('/markets');
|
||||
|
||||
@@ -14,15 +14,15 @@ import { generatePartyMarketData } from '../support/mocks/generate-party-market-
|
||||
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 type { Market, Markets } from '@vegaprotocol/market-list';
|
||||
|
||||
describe('market selector', { tags: '@smoke' }, () => {
|
||||
let markets: Market[];
|
||||
beforeEach(() => {
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'Markets', generateSimpleMarkets());
|
||||
aliasQuery(req, 'MarketsCandles', generateMarketsCandles());
|
||||
aliasQuery(req, 'MarketsData', generateMarketsData());
|
||||
aliasQuery(req, 'MarketsCandlesQuery', generateMarketsCandles());
|
||||
aliasQuery(req, 'MarketsDataQuery', generateMarketsData());
|
||||
aliasQuery(req, 'DealTicket', generateDealTicket());
|
||||
aliasQuery(req, 'MarketTags', generateMarketTags());
|
||||
aliasQuery(req, 'MarketPositions', generateMarketPositions());
|
||||
@@ -36,9 +36,9 @@ describe('market selector', { tags: '@smoke' }, () => {
|
||||
|
||||
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);
|
||||
const data: Markets | undefined = response?.response?.body?.data;
|
||||
if (data.marketsConnection.edges.length) {
|
||||
markets = data.marketsConnection.edges.map((edge) => edge.node);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,15 +13,15 @@ import { generatePartyMarketData } from '../support/mocks/generate-party-market-
|
||||
import { generateMarketMarkPrice } from '../support/mocks/generate-market-mark-price';
|
||||
import { generateMarketDepth } from '../support/mocks/generate-market-depth';
|
||||
import { connectVegaWallet } from '../support/connect-wallet';
|
||||
import type { MarketsQuery, Market } from '@vegaprotocol/market-list';
|
||||
import type { Markets, Market } from '@vegaprotocol/market-list';
|
||||
|
||||
describe('Market trade', { tags: '@smoke' }, () => {
|
||||
let markets: Market[];
|
||||
beforeEach(() => {
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'Markets', generateSimpleMarkets());
|
||||
aliasQuery(req, 'MarketsCandles', generateMarketsCandles());
|
||||
aliasQuery(req, 'MarketsData', generateMarketsData());
|
||||
aliasQuery(req, 'MarketsCandlesQuery', generateMarketsCandles());
|
||||
aliasQuery(req, 'MarketsDataQuery', generateMarketsData());
|
||||
aliasQuery(req, 'SimpleMarkets', generateSimpleMarkets());
|
||||
aliasQuery(req, 'DealTicket', generateDealTicket());
|
||||
aliasQuery(req, 'MarketTags', generateMarketTags());
|
||||
@@ -34,9 +34,9 @@ describe('Market trade', { tags: '@smoke' }, () => {
|
||||
});
|
||||
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);
|
||||
const data: Markets | undefined = response?.response?.body?.data;
|
||||
if (data.marketsConnection.edges.length) {
|
||||
markets = data.marketsConnection.edges.map((edge) => edge.node);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -299,7 +299,7 @@ describe('Market trade', { tags: '@smoke' }, () => {
|
||||
cy.getByTestId('place-order').click();
|
||||
cy.getByTestId('dialog-title').should(
|
||||
'have.text',
|
||||
'Awaiting network confirmation'
|
||||
'Confirm transaction in wallet'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -6,19 +6,11 @@ import { aliasQuery } from '@vegaprotocol/cypress';
|
||||
import {
|
||||
generatePositions,
|
||||
emptyPositions,
|
||||
generateMargins,
|
||||
} from '../support/mocks/generate-positions';
|
||||
import {
|
||||
generateAccounts,
|
||||
generateAssets,
|
||||
} from '../support/mocks/generate-accounts';
|
||||
import { generateAccounts } from '../support/mocks/generate-accounts';
|
||||
import { generateOrders } from '../support/mocks/generate-orders';
|
||||
import { generateFills } from '../support/mocks/generate-fills';
|
||||
import {
|
||||
generateFillsMarkets,
|
||||
generateMarketsData,
|
||||
generatePositionsMarkets,
|
||||
} from '../support/mocks/generate-markets';
|
||||
import { generateFillsMarkets } from '../support/mocks/generate-markets';
|
||||
|
||||
describe('Portfolio page', { tags: '@smoke' }, () => {
|
||||
afterEach(() => {
|
||||
@@ -57,18 +49,14 @@ describe('Portfolio page', { tags: '@smoke' }, () => {
|
||||
beforeEach(() => {
|
||||
cy.mockGQL((req) => {
|
||||
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', 3);
|
||||
cy.get('.ag-center-cols-container .ag-row').should('have.length', 5);
|
||||
cy.get(
|
||||
'.ag-center-cols-container [row-id="ACCOUNT_TYPE_GENERAL-asset-id-null"]'
|
||||
)
|
||||
@@ -87,10 +75,6 @@ describe('Portfolio page', { tags: '@smoke' }, () => {
|
||||
cy.mockGQL((req) => {
|
||||
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.visit('/portfolio/positions');
|
||||
connectVegaWallet();
|
||||
@@ -142,9 +126,6 @@ describe('Portfolio page', { tags: '@smoke' }, () => {
|
||||
aliasQuery(req, 'Markets', {
|
||||
marketsConnection: { edges: [], __typename: 'MarketConnection' },
|
||||
});
|
||||
aliasQuery(req, 'Assets', {
|
||||
assetsConnection: { edges: null, __typename: 'AssetsConnection' },
|
||||
});
|
||||
});
|
||||
cy.visit('/portfolio');
|
||||
connectVegaWallet();
|
||||
@@ -152,26 +133,22 @@ describe('Portfolio page', { tags: '@smoke' }, () => {
|
||||
|
||||
it('"No data to display" should be always displayed', () => {
|
||||
cy.getByTestId('assets').click();
|
||||
cy.get('div.flex.items-center.justify-center').should(
|
||||
'contain.text',
|
||||
cy.get('div.flex.items-center.justify-center').contains(
|
||||
'No data to display'
|
||||
);
|
||||
|
||||
cy.getByTestId('positions').click();
|
||||
cy.get('div.flex.items-center.justify-center').should(
|
||||
'contain.text',
|
||||
cy.get('div.flex.items-center.justify-center').contains(
|
||||
'No data to display'
|
||||
);
|
||||
|
||||
cy.getByTestId('orders').click();
|
||||
cy.get('div.flex.items-center.justify-center').should(
|
||||
'contain.text',
|
||||
cy.get('div.flex.items-center.justify-center').contains(
|
||||
'No data to display'
|
||||
);
|
||||
|
||||
cy.getByTestId('fills').click();
|
||||
cy.get('div.flex.items-center.justify-center').should(
|
||||
'contain.text',
|
||||
cy.get('div.flex.items-center.justify-center').contains(
|
||||
'No data to display'
|
||||
);
|
||||
});
|
||||
|
||||
@@ -4,9 +4,7 @@ export const connectVegaWallet = () => {
|
||||
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('connectors-list').find('button').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();
|
||||
|
||||
@@ -18,17 +18,4 @@ import 'cypress-real-events/support';
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands';
|
||||
import registerCypressGrep from 'cypress-grep';
|
||||
import { aliasQuery } from '@vegaprotocol/cypress';
|
||||
registerCypressGrep();
|
||||
|
||||
before(() => {
|
||||
// Mock chainId fetch which happens on every page for wallet connection
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'ChainId', {
|
||||
statistics: {
|
||||
__typename: 'Statistics',
|
||||
chainId: 'vega-fairground-202210041151',
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -77,7 +77,7 @@ export const protoCandles = [
|
||||
];
|
||||
|
||||
export const protoMarket: Market = {
|
||||
id: 'ca7768f6de84bf86a21bbb6b0109d9659c81917b0e0339b2c262566c9b581a15',
|
||||
id: 'first-btcusd-id',
|
||||
tradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
state: MarketState.STATE_ACTIVE,
|
||||
decimalPlaces: 5,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import merge from 'lodash/merge';
|
||||
import type { AccountsQuery, AssetsQuery } from '@vegaprotocol/accounts';
|
||||
import { AccountType, Schema as Types } from '@vegaprotocol/types';
|
||||
import type { AccountsQuery } from '@vegaprotocol/accounts';
|
||||
import { AccountType } from '@vegaprotocol/types';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
|
||||
export const generateAccounts = (
|
||||
@@ -19,6 +19,8 @@ export const generateAccounts = (
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
id: 'asset-id',
|
||||
symbol: 'tEURO',
|
||||
decimals: 5,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -27,11 +29,20 @@ export const generateAccounts = (
|
||||
balance: '100000000',
|
||||
market: {
|
||||
id: '0604e8c918655474525e1a95367902266ade70d318c2c908f0cca6e3d11dcb13',
|
||||
tradableInstrument: {
|
||||
__typename: 'TradableInstrument',
|
||||
instrument: {
|
||||
__typename: 'Instrument',
|
||||
name: 'AAVEDAI Monthly (30 Jun 2022)',
|
||||
},
|
||||
},
|
||||
__typename: 'Market',
|
||||
},
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
id: 'asset-id-2',
|
||||
symbol: 'tDAI',
|
||||
decimals: 5,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -40,11 +51,20 @@ export const generateAccounts = (
|
||||
balance: '1000',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
tradableInstrument: {
|
||||
__typename: 'TradableInstrument',
|
||||
instrument: {
|
||||
__typename: 'Instrument',
|
||||
name: '',
|
||||
},
|
||||
},
|
||||
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
|
||||
},
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
id: 'asset-id',
|
||||
symbol: 'tEURO',
|
||||
decimals: 5,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -53,11 +73,20 @@ export const generateAccounts = (
|
||||
balance: '1000',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
tradableInstrument: {
|
||||
__typename: 'TradableInstrument',
|
||||
instrument: {
|
||||
__typename: 'Instrument',
|
||||
name: '',
|
||||
},
|
||||
},
|
||||
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
|
||||
},
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
id: 'asset-id-2',
|
||||
symbol: 'tDAI',
|
||||
decimals: 5,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -68,6 +97,8 @@ export const generateAccounts = (
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
id: 'asset-0',
|
||||
symbol: 'AST0',
|
||||
decimals: 5,
|
||||
},
|
||||
},
|
||||
],
|
||||
@@ -75,43 +106,3 @@ export const generateAccounts = (
|
||||
};
|
||||
return merge(defaultAccounts, override);
|
||||
};
|
||||
|
||||
export const generateAssets = (override?: PartialDeep<AssetsQuery>) => {
|
||||
const defaultAssets: AssetsQuery = {
|
||||
assetsConnection: {
|
||||
edges: [
|
||||
{
|
||||
node: {
|
||||
id: 'asset-id',
|
||||
symbol: 'tEURO',
|
||||
decimals: 5,
|
||||
name: 'Euro',
|
||||
quantum: '',
|
||||
status: Types.AssetStatus.STATUS_ENABLED,
|
||||
},
|
||||
},
|
||||
{
|
||||
node: {
|
||||
id: 'asset-id-2',
|
||||
symbol: 'tDAI',
|
||||
decimals: 5,
|
||||
name: 'DAI',
|
||||
quantum: '',
|
||||
status: Types.AssetStatus.STATUS_ENABLED,
|
||||
},
|
||||
},
|
||||
{
|
||||
node: {
|
||||
id: 'asset-0',
|
||||
symbol: 'AST0',
|
||||
decimals: 5,
|
||||
name: 'Asto',
|
||||
quantum: '',
|
||||
status: Types.AssetStatus.STATUS_ENABLED,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
return merge(defaultAssets, override);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export const generateDealTicket = () => {
|
||||
return {
|
||||
market: {
|
||||
id: 'ca7768f6de84bf86a21bbb6b0109d9659c81917b0e0339b2c262566c9b581a15',
|
||||
id: 'first-btcusd-id',
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
state: 'STATE_ACTIVE',
|
||||
|
||||
@@ -21,7 +21,7 @@ export const generateMarketPositions = () => {
|
||||
},
|
||||
balance: '265329',
|
||||
market: {
|
||||
id: 'ca7768f6de84bf86a21bbb6b0109d9659c81917b0e0339b2c262566c9b581a15',
|
||||
id: 'first-btcusd-id',
|
||||
__typename: 'Market',
|
||||
},
|
||||
},
|
||||
@@ -43,7 +43,7 @@ export const generateMarketPositions = () => {
|
||||
node: {
|
||||
openVolume: '12',
|
||||
market: {
|
||||
id: 'ca7768f6de84bf86a21bbb6b0109d9659c81917b0e0339b2c262566c9b581a15',
|
||||
id: 'first-btcusd-id',
|
||||
__typename: 'Market',
|
||||
},
|
||||
__typename: 'Position',
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -31,8 +31,6 @@ export const generateOrders = (override?: PartialDeep<Orders>): Orders => {
|
||||
updatedAt: null,
|
||||
expiresAt: null,
|
||||
rejectionReason: null,
|
||||
liquidityProvision: null,
|
||||
peggedOrder: null,
|
||||
},
|
||||
{
|
||||
__typename: 'Order',
|
||||
@@ -52,8 +50,6 @@ export const generateOrders = (override?: PartialDeep<Orders>): Orders => {
|
||||
updatedAt: null,
|
||||
expiresAt: null,
|
||||
rejectionReason: null,
|
||||
liquidityProvision: null,
|
||||
peggedOrder: null,
|
||||
},
|
||||
{
|
||||
__typename: 'Order',
|
||||
@@ -73,8 +69,6 @@ export const generateOrders = (override?: PartialDeep<Orders>): Orders => {
|
||||
updatedAt: null,
|
||||
expiresAt: null,
|
||||
rejectionReason: null,
|
||||
liquidityProvision: null,
|
||||
peggedOrder: null,
|
||||
},
|
||||
{
|
||||
__typename: 'Order',
|
||||
@@ -94,8 +88,6 @@ export const generateOrders = (override?: PartialDeep<Orders>): Orders => {
|
||||
updatedAt: null,
|
||||
expiresAt: null,
|
||||
rejectionReason: null,
|
||||
liquidityProvision: null,
|
||||
peggedOrder: null,
|
||||
},
|
||||
{
|
||||
__typename: 'Order',
|
||||
@@ -114,8 +106,6 @@ export const generateOrders = (override?: PartialDeep<Orders>): Orders => {
|
||||
createdAt: new Date(2020, 1, 27).toISOString(),
|
||||
updatedAt: null,
|
||||
expiresAt: null,
|
||||
liquidityProvision: null,
|
||||
peggedOrder: null,
|
||||
rejectionReason: null,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -4,6 +4,7 @@ import type {
|
||||
Positions,
|
||||
Positions_party_positionsConnection_edges_node,
|
||||
} from '@vegaprotocol/positions';
|
||||
import { MarketTradingMode } from '@vegaprotocol/types';
|
||||
|
||||
export const generatePositions = (
|
||||
override?: PartialDeep<Positions>
|
||||
@@ -16,8 +17,49 @@ export const generatePositions = (
|
||||
unrealisedPNL: '895000',
|
||||
averageEntryPrice: '1129935',
|
||||
updatedAt: '2022-07-28T15:09:34.441143Z',
|
||||
marginsConnection: {
|
||||
__typename: 'MarginConnection',
|
||||
edges: [
|
||||
{
|
||||
__typename: 'MarginEdge',
|
||||
node: {
|
||||
__typename: 'MarginLevels',
|
||||
maintenanceLevel: '0',
|
||||
searchLevel: '0',
|
||||
initialLevel: '0',
|
||||
collateralReleaseLevel: '0',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
|
||||
},
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
symbol: 'tDAI',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
market: {
|
||||
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
|
||||
tradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
data: {
|
||||
markPrice: '17588787',
|
||||
__typename: 'MarketData',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
|
||||
},
|
||||
},
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
name: 'UNIDAI Monthly (30 Jun 2022)',
|
||||
__typename: 'Instrument',
|
||||
},
|
||||
__typename: 'TradableInstrument',
|
||||
},
|
||||
__typename: 'Market',
|
||||
},
|
||||
},
|
||||
@@ -28,8 +70,49 @@ export const generatePositions = (
|
||||
unrealisedPNL: '895000',
|
||||
averageEntryPrice: '8509338',
|
||||
updatedAt: '2022-07-28T15:09:34.441143Z',
|
||||
marginsConnection: {
|
||||
__typename: 'MarginConnection',
|
||||
edges: [
|
||||
{
|
||||
__typename: 'MarginEdge',
|
||||
node: {
|
||||
__typename: 'MarginLevels',
|
||||
maintenanceLevel: '0',
|
||||
searchLevel: '0',
|
||||
initialLevel: '0',
|
||||
collateralReleaseLevel: '0',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: '0604e8c918655474525e1a95367902266ade70d318c2c908f0cca6e3d11dcb13',
|
||||
},
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
symbol: 'tDAI',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
market: {
|
||||
id: '0604e8c918655474525e1a95367902266ade70d318c2c908f0cca6e3d11dcb13',
|
||||
tradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
data: {
|
||||
markPrice: '8649338',
|
||||
__typename: 'MarketData',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: '0604e8c918655474525e1a95367902266ade70d318c2c908f0cca6e3d11dcb13',
|
||||
},
|
||||
},
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
name: 'AAVEDAI Monthly (30 Jun 2022)',
|
||||
__typename: 'Instrument',
|
||||
},
|
||||
__typename: 'TradableInstrument',
|
||||
},
|
||||
__typename: 'Market',
|
||||
},
|
||||
},
|
||||
@@ -39,8 +122,49 @@ export const generatePositions = (
|
||||
unrealisedPNL: '-22519',
|
||||
averageEntryPrice: '84400088',
|
||||
updatedAt: '2022-07-28T14:53:54.725477Z',
|
||||
marginsConnection: {
|
||||
__typename: 'MarginConnection',
|
||||
edges: [
|
||||
{
|
||||
__typename: 'MarginEdge',
|
||||
node: {
|
||||
__typename: 'MarginLevels',
|
||||
maintenanceLevel: '0',
|
||||
searchLevel: '0',
|
||||
initialLevel: '0',
|
||||
collateralReleaseLevel: '0',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
|
||||
},
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
symbol: 'tEURO',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
market: {
|
||||
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
|
||||
tradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
data: {
|
||||
markPrice: '84377569',
|
||||
__typename: 'MarketData',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
|
||||
},
|
||||
},
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
name: 'Tesla Quarterly (30 Jun 2022)',
|
||||
__typename: 'Instrument',
|
||||
},
|
||||
__typename: 'TradableInstrument',
|
||||
},
|
||||
__typename: 'Market',
|
||||
},
|
||||
__typename: 'Position',
|
||||
@@ -75,70 +199,3 @@ export const emptyPositions = () => {
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const generateMargins = () => {
|
||||
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: {
|
||||
m_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',
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"jsx": "react-jsx",
|
||||
"sourceMap": false,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
|
||||
@@ -20,8 +20,8 @@ NX_DEPLOY_PRIME_URL=$DEPLOY_PRIME_URL
|
||||
NX_VEGA_CONFIG_URL="https://static.vega.xyz/assets/testnet-network.json"
|
||||
NX_VEGA_ENV = 'TESTNET'
|
||||
NX_VEGA_URL="https://api.n11.testnet.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
|
||||
NX_VEGA_WALLET_URL=http://localhost:1789/api/v1
|
||||
NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://ropsten.etherscan.io
|
||||
NX_VEGA_NETWORKS={"MAINNET":"https://alpha.console.vega.xyz"}
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
||||
|
||||
@@ -3,6 +3,6 @@ NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/devnet-network.json
|
||||
NX_VEGA_URL=https://api.n04.d.vega.xyz/graphql
|
||||
NX_VEGA_ENV=DEVNET
|
||||
NX_VEGA_NETWORKS={\"MAINNET\":\"https://alpha.console.vega.xyz\"}
|
||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://ropsten.etherscan.io
|
||||
NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
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_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://ropsten.etherscan.io
|
||||
NX_VEGA_EXPLORER_URL=https://staging2.explorer.vega.xyz
|
||||
|
||||
@@ -3,6 +3,6 @@ NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json
|
||||
NX_VEGA_URL=https://api.n12.testnet.vega.xyz/graphql
|
||||
NX_VEGA_ENV=TESTNET
|
||||
NX_VEGA_NETWORKS='{\"MAINNET\":\"https://alpha.console.vega.xyz\"}'
|
||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://ropsten.etherscan.io
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
||||
|
||||
@@ -105,7 +105,9 @@ const ConsoleLiteGrid = <T extends { id?: string }>(
|
||||
);
|
||||
};
|
||||
|
||||
const ConsoleLiteGridForwarder = forwardRef(ConsoleLiteGrid) as <T>(
|
||||
const ConsoleLiteGridForwarder = forwardRef(ConsoleLiteGrid) as <
|
||||
T extends { id?: string }
|
||||
>(
|
||||
p: Props<T> & { ref?: React.Ref<AgGridReact> }
|
||||
) => React.ReactElement;
|
||||
|
||||
|
||||
@@ -37,13 +37,13 @@ const PARTY_BALANCE_QUERY = gql`
|
||||
|
||||
export const DealTicketContainer = () => {
|
||||
const { marketId } = useParams<{ marketId: string }>();
|
||||
const { pubKey } = useVegaWallet();
|
||||
const { keypair } = useVegaWallet();
|
||||
|
||||
const { data: partyData, loading } = useQuery<PartyBalanceQuery>(
|
||||
PARTY_BALANCE_QUERY,
|
||||
{
|
||||
variables: { partyId: pubKey },
|
||||
skip: !pubKey,
|
||||
variables: { partyId: keypair?.pub },
|
||||
skip: !keypair?.pub,
|
||||
}
|
||||
);
|
||||
|
||||
@@ -63,7 +63,7 @@ export const DealTicketContainer = () => {
|
||||
data.market.tradableInstrument.instrument.product?.settlementAsset
|
||||
}
|
||||
accounts={partyData?.party?.accounts || []}
|
||||
isWalletConnected={!!pubKey}
|
||||
isWalletConnected={!!keypair?.pub}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -82,7 +82,7 @@ export const DealTicketContainer = () => {
|
||||
return (
|
||||
<section className="flex p-4 md:p-6">
|
||||
<section className="w-full md:w-1/2 md:min-w-[500px]">
|
||||
{pubKey ? container : <ConnectWallet />}
|
||||
{keypair ? container : <ConnectWallet />}
|
||||
</section>
|
||||
<Baubles />
|
||||
</section>
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useForm, Controller } from 'react-hook-form';
|
||||
import { Stepper } from '../stepper';
|
||||
import type { DealTicketMarketFragment } from '@vegaprotocol/deal-ticket';
|
||||
import {
|
||||
getDefaultOrder,
|
||||
useOrderValidation,
|
||||
validateSize,
|
||||
} from '@vegaprotocol/deal-ticket';
|
||||
import { InputError } from '@vegaprotocol/ui-toolkit';
|
||||
import { BigNumber } from 'bignumber.js';
|
||||
import { MarketSelector } from '@vegaprotocol/deal-ticket';
|
||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||
import type { Order } from '@vegaprotocol/orders';
|
||||
import { useVegaWallet, VegaTxStatus } from '@vegaprotocol/wallet';
|
||||
import {
|
||||
t,
|
||||
@@ -20,11 +15,14 @@ import {
|
||||
removeDecimal,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import {
|
||||
getDefaultOrder,
|
||||
useOrderValidation,
|
||||
useOrderSubmit,
|
||||
getOrderDialogTitle,
|
||||
getOrderDialogIntent,
|
||||
getOrderDialogIcon,
|
||||
OrderFeedback,
|
||||
validateSize,
|
||||
} from '@vegaprotocol/orders';
|
||||
import { DealTicketSize } from './deal-ticket-size';
|
||||
import MarketNameRenderer from '../simple-market-list/simple-market-renderer';
|
||||
@@ -61,7 +59,7 @@ export const DealTicketSteps = ({
|
||||
watch,
|
||||
setValue,
|
||||
formState: { errors },
|
||||
} = useForm<OrderSubmissionBody['orderSubmission']>({
|
||||
} = useForm<Order>({
|
||||
mode: 'onChange',
|
||||
defaultValues: getDefaultOrder(market),
|
||||
});
|
||||
@@ -80,15 +78,15 @@ export const DealTicketSteps = ({
|
||||
fieldErrors: errors,
|
||||
});
|
||||
const { submit, transaction, finalizedOrder, Dialog } = useOrderSubmit();
|
||||
const { pubKey } = useVegaWallet();
|
||||
const { keypair } = useVegaWallet();
|
||||
const estMargin = useOrderMargin({
|
||||
order,
|
||||
market,
|
||||
partyId: pubKey || '',
|
||||
partyId: keypair?.pub || '',
|
||||
});
|
||||
|
||||
const maxTrade = useMaximumPositionSize({
|
||||
partyId: pubKey || '',
|
||||
partyId: keypair?.pub || '',
|
||||
accounts: partyData?.party?.accounts || [],
|
||||
marketId: market.id,
|
||||
settlementAssetId:
|
||||
@@ -205,7 +203,7 @@ export const DealTicketSteps = ({
|
||||
);
|
||||
|
||||
const onSubmit = useCallback(
|
||||
(order: OrderSubmissionBody['orderSubmission']) => {
|
||||
(order: Order) => {
|
||||
if (transactionStatus !== 'pending') {
|
||||
submit({
|
||||
...order,
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import type { DealTicketMarketFragment } from '@vegaprotocol/deal-ticket';
|
||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||
import type { Order } from '@vegaprotocol/orders';
|
||||
import { SIDE_NAMES } from './side-selector';
|
||||
import SimpleMarketExpires from '../simple-market-list/simple-market-expires';
|
||||
import { gql, useQuery } from '@apollo/client';
|
||||
@@ -36,7 +36,7 @@ interface Props {
|
||||
market: DealTicketMarketFragment;
|
||||
isDisabled: boolean;
|
||||
transactionStatus?: string;
|
||||
order: OrderSubmissionBody['orderSubmission'];
|
||||
order: Order;
|
||||
estCloseOut: string;
|
||||
estMargin: string;
|
||||
quoteName: string;
|
||||
|
||||
@@ -33,11 +33,11 @@ const DEPOSITS_QUERY = gql`
|
||||
*/
|
||||
export const DepositContainer = () => {
|
||||
const { VEGA_ENV } = useEnvironment();
|
||||
const { pubKey } = useVegaWallet();
|
||||
const { keypair } = useVegaWallet();
|
||||
|
||||
const { data, loading, error } = useQuery<DepositAssets>(DEPOSITS_QUERY, {
|
||||
variables: { partyId: pubKey },
|
||||
skip: !pubKey,
|
||||
variables: { partyId: keypair?.pub },
|
||||
skip: !keypair?.pub,
|
||||
});
|
||||
|
||||
const assets = getEnabledAssets(data);
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
import { useMemo, useRef, useCallback } from 'react';
|
||||
import { useMemo, useRef } from 'react';
|
||||
import { useOutletContext } from 'react-router-dom';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import { PriceCell, useDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import type { AccountFields } from '@vegaprotocol/accounts';
|
||||
import { aggregatedAccountsDataProvider, getId } from '@vegaprotocol/accounts';
|
||||
import type { IGetRowsParams } from 'ag-grid-community';
|
||||
import type {
|
||||
AccountFieldsFragment,
|
||||
AccountEventsSubscription,
|
||||
} from '@vegaprotocol/accounts';
|
||||
import {
|
||||
accountsDataProvider,
|
||||
accountsManagerUpdate,
|
||||
getId,
|
||||
} from '@vegaprotocol/accounts';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import {
|
||||
AssetDetailsDialog,
|
||||
@@ -14,43 +20,20 @@ import { NO_DATA_MESSAGE } from '../../../constants';
|
||||
import { ConsoleLiteGrid } from '../../console-lite-grid';
|
||||
import { useAccountColumnDefinitions } from '.';
|
||||
|
||||
interface AccountObj extends AccountFieldsFragment {
|
||||
id: string;
|
||||
}
|
||||
|
||||
const AccountsManager = () => {
|
||||
const { partyId = '' } = useOutletContext<{ partyId: string }>();
|
||||
const { isOpen, symbol, setOpen } = useAssetDetailsDialogStore();
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const dataRef = useRef<AccountFields[] | null>(null);
|
||||
const variables = useMemo(() => ({ partyId }), [partyId]);
|
||||
const update = useCallback(
|
||||
({ data }: { data: AccountFields[] | null }) => {
|
||||
if (!gridRef.current?.api) {
|
||||
return false;
|
||||
}
|
||||
if (dataRef.current?.length) {
|
||||
dataRef.current = data;
|
||||
gridRef.current.api.refreshInfiniteCache();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[gridRef]
|
||||
);
|
||||
const { data, error, loading } = useDataProvider<AccountFields[], never>({
|
||||
dataProvider: aggregatedAccountsDataProvider,
|
||||
update,
|
||||
variables,
|
||||
});
|
||||
dataRef.current = data;
|
||||
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 update = useMemo(() => accountsManagerUpdate(gridRef), []);
|
||||
const { data, error, loading } = useDataProvider<
|
||||
AccountFieldsFragment[],
|
||||
AccountEventsSubscription['accounts']
|
||||
>({ dataProvider: accountsDataProvider, update, variables });
|
||||
const { columnDefs, defaultColDef } = useAccountColumnDefinitions();
|
||||
return (
|
||||
<>
|
||||
@@ -60,11 +43,8 @@ const AccountsManager = () => {
|
||||
data={data}
|
||||
noDataMessage={NO_DATA_MESSAGE}
|
||||
>
|
||||
<ConsoleLiteGrid<AccountFields>
|
||||
rowData={data?.length ? undefined : []}
|
||||
rowModelType={data?.length ? 'infinite' : 'clientSide'}
|
||||
ref={gridRef}
|
||||
datasource={{ getRows }}
|
||||
<ConsoleLiteGrid<AccountObj>
|
||||
rowData={data as AccountObj[]}
|
||||
columnDefs={columnDefs}
|
||||
defaultColDef={defaultColDef}
|
||||
components={{ PriceCell }}
|
||||
|
||||
+59
-28
@@ -1,9 +1,45 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { addDecimalsFormatNumber, t } from '@vegaprotocol/react-helpers';
|
||||
import type { AccountFields } from '@vegaprotocol/accounts';
|
||||
import type { SummaryRow } from '@vegaprotocol/react-helpers';
|
||||
import type { AccountFieldsFragment } from '@vegaprotocol/accounts';
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||
import type { ColDef, GroupCellRendererParams } from 'ag-grid-community';
|
||||
import type { VegaValueFormatterParams } from '@vegaprotocol/ui-toolkit';
|
||||
import type {
|
||||
ColDef,
|
||||
GroupCellRendererParams,
|
||||
ValueFormatterParams,
|
||||
} from 'ag-grid-community';
|
||||
import type { AccountType } from '@vegaprotocol/types';
|
||||
import { AccountTypeMapping } from '@vegaprotocol/types';
|
||||
|
||||
interface AccountsTableValueFormatterParams extends ValueFormatterParams {
|
||||
data: AccountFieldsFragment;
|
||||
}
|
||||
|
||||
const comparator = (
|
||||
valueA: string,
|
||||
valueB: string,
|
||||
nodeA: { data: AccountFieldsFragment & SummaryRow },
|
||||
nodeB: { data: AccountFieldsFragment & SummaryRow },
|
||||
isInverted: boolean
|
||||
) => {
|
||||
if (valueA < valueB) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (valueA > valueB) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (nodeA.data.__summaryRow) {
|
||||
return isInverted ? -1 : 1;
|
||||
}
|
||||
|
||||
if (nodeB.data.__summaryRow) {
|
||||
return isInverted ? 1 : -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
const useAccountColumnDefinitions = () => {
|
||||
const { open } = useAssetDetailsDialogStore();
|
||||
@@ -13,6 +49,7 @@ const useAccountColumnDefinitions = () => {
|
||||
colId: 'account-asset',
|
||||
headerName: t('Asset'),
|
||||
field: 'asset.symbol',
|
||||
comparator,
|
||||
headerClass: 'uppercase justify-start',
|
||||
cellClass: 'uppercase flex h-full items-center md:pl-4',
|
||||
cellRenderer: ({ value }: GroupCellRendererParams) =>
|
||||
@@ -34,34 +71,28 @@ const useAccountColumnDefinitions = () => {
|
||||
),
|
||||
},
|
||||
{
|
||||
colId: 'deposited',
|
||||
headerName: t('Deposited'),
|
||||
field: 'deposited',
|
||||
cellRenderer: 'PriceCell',
|
||||
valueFormatter: ({
|
||||
value,
|
||||
data,
|
||||
}: VegaValueFormatterParams<AccountFields, 'deposited'>) => {
|
||||
if (value && data) {
|
||||
return addDecimalsFormatNumber(value, data.asset.decimals);
|
||||
}
|
||||
return '-';
|
||||
},
|
||||
colId: 'type',
|
||||
headerName: t('Type'),
|
||||
field: 'type',
|
||||
cellClass: 'uppercase !flex h-full items-center',
|
||||
valueFormatter: ({ value }: ValueFormatterParams) =>
|
||||
value ? AccountTypeMapping[value as AccountType] : '-',
|
||||
},
|
||||
{
|
||||
colId: 'used',
|
||||
headerName: t('Used'),
|
||||
field: 'used',
|
||||
colId: 'market',
|
||||
headerName: t('Market'),
|
||||
cellClass: 'uppercase !flex h-full items-center',
|
||||
field: 'market.tradableInstrument.instrument.name',
|
||||
valueFormatter: "value || '—'",
|
||||
},
|
||||
{
|
||||
colId: 'balance',
|
||||
headerName: t('Balance'),
|
||||
field: 'balance',
|
||||
cellClass: 'uppercase !flex h-full items-center',
|
||||
cellRenderer: 'PriceCell',
|
||||
valueFormatter: ({
|
||||
value,
|
||||
data,
|
||||
}: VegaValueFormatterParams<AccountFields, 'used'>) => {
|
||||
if (value && data) {
|
||||
return addDecimalsFormatNumber(value, data.asset.decimals);
|
||||
}
|
||||
return '-';
|
||||
},
|
||||
valueFormatter: ({ value, data }: AccountsTableValueFormatterParams) =>
|
||||
addDecimalsFormatNumber(value, data.asset.decimals),
|
||||
},
|
||||
];
|
||||
}, [open]);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useRef } from 'react';
|
||||
import { useOutletContext } from 'react-router-dom';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import type { Trade } from '@vegaprotocol/fills';
|
||||
import type { TradeWithMarket } from '@vegaprotocol/fills';
|
||||
import { useFillsList } from '@vegaprotocol/fills';
|
||||
import type { BodyScrollEndEvent, BodyScrollEvent } from 'ag-grid-community';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
@@ -37,7 +37,7 @@ const FillsManager = () => {
|
||||
data={data?.length ? data : null}
|
||||
noDataMessage={NO_DATA_MESSAGE}
|
||||
>
|
||||
<ConsoleLiteGrid<Trade>
|
||||
<ConsoleLiteGrid<TradeWithMarket>
|
||||
ref={gridRef}
|
||||
rowModelType="infinite"
|
||||
datasource={{ getRows }}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useMemo } from 'react';
|
||||
import type { ColDef, ValueFormatterParams } from 'ag-grid-community';
|
||||
import type { Trade } from '@vegaprotocol/fills';
|
||||
import type { TradeWithMarket } from '@vegaprotocol/fills';
|
||||
import classNames from 'classnames';
|
||||
import {
|
||||
addDecimal,
|
||||
@@ -34,7 +34,7 @@ const useColumnDefinitions = ({ partyId }: Props) => {
|
||||
headerClass: 'uppercase',
|
||||
field: 'size',
|
||||
width: 100,
|
||||
cellClass: ({ data }: { data: Trade }) => {
|
||||
cellClass: ({ data }: { data: TradeWithMarket }) => {
|
||||
return classNames('!flex h-full items-center justify-center', {
|
||||
[positiveClassNames]: data?.buyer.id === partyId,
|
||||
[negativeClassNames]: data?.seller.id,
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useRef, useState } from 'react';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import type { BodyScrollEndEvent, BodyScrollEvent } from 'ag-grid-community';
|
||||
import { useOutletContext } from 'react-router-dom';
|
||||
import type { Order } from '@vegaprotocol/orders';
|
||||
import type { OrderWithMarket } from '@vegaprotocol/orders';
|
||||
import {
|
||||
useOrderCancel,
|
||||
useOrderListData,
|
||||
@@ -20,7 +20,7 @@ import useColumnDefinitions from './use-column-definitions';
|
||||
|
||||
const OrdersManager = () => {
|
||||
const { partyId } = useOutletContext<{ partyId: string }>();
|
||||
const [editOrder, setEditOrder] = useState<Order | null>(null);
|
||||
const [editOrder, setEditOrder] = useState<OrderWithMarket | null>(null);
|
||||
const orderCancel = useOrderCancel();
|
||||
const orderEdit = useOrderEdit(editOrder);
|
||||
const { columnDefs, defaultColDef } = useColumnDefinitions({
|
||||
@@ -54,7 +54,7 @@ const OrdersManager = () => {
|
||||
data={data?.length ? data : null}
|
||||
noDataMessage={NO_DATA_MESSAGE}
|
||||
>
|
||||
<ConsoleLiteGrid<Order>
|
||||
<ConsoleLiteGrid<OrderWithMarket>
|
||||
ref={gridRef}
|
||||
rowModelType={data?.length ? 'infinite' : 'clientSide'}
|
||||
rowData={data?.length ? undefined : []}
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import type {
|
||||
Orders_party_ordersConnection_edges_node,
|
||||
Order,
|
||||
OrderWithMarket,
|
||||
CancelOrderArgs,
|
||||
} from '@vegaprotocol/orders';
|
||||
import { isOrderActive } from '@vegaprotocol/orders';
|
||||
@@ -35,7 +35,7 @@ type StatusKey = keyof typeof OrderStatusMapping;
|
||||
type RejectReasonKey = keyof typeof OrderRejectionReasonMapping;
|
||||
type OrderTimeKey = keyof typeof OrderTimeInForceMapping;
|
||||
interface Props {
|
||||
setEditOrder: (order: Order) => void;
|
||||
setEditOrder: (order: OrderWithMarket) => void;
|
||||
orderCancel: {
|
||||
cancel: (args: CancelOrderArgs) => void;
|
||||
[key: string]: unknown;
|
||||
|
||||
@@ -6,11 +6,11 @@ import { HorizontalMenu } from '../horizontal-menu';
|
||||
import * as constants from './constants';
|
||||
|
||||
export const Portfolio = () => {
|
||||
const { pubKey } = useVegaWallet();
|
||||
const { keypair } = useVegaWallet();
|
||||
const { pathname } = useLocation();
|
||||
const module = pathname.split('/portfolio/')?.[1] ?? '';
|
||||
const outlet = useOutlet({ partyId: pubKey || '' });
|
||||
if (!pubKey) {
|
||||
const outlet = useOutlet({ partyId: keypair?.pub || '' });
|
||||
if (!keypair) {
|
||||
return (
|
||||
<section className="xl:w-1/2">
|
||||
<ConnectWallet />
|
||||
|
||||
@@ -11,7 +11,7 @@ import type {
|
||||
PositionsTableValueFormatterParams,
|
||||
Position,
|
||||
} from '@vegaprotocol/positions';
|
||||
import { AmountCell } from '@vegaprotocol/positions';
|
||||
import { AmountCell, ProgressBarCell } from '@vegaprotocol/positions';
|
||||
import type {
|
||||
CellRendererSelectorResult,
|
||||
ICellRendererParams,
|
||||
@@ -20,7 +20,7 @@ import type {
|
||||
ColDef,
|
||||
} from 'ag-grid-community';
|
||||
import { MarketTradingMode } from '@vegaprotocol/types';
|
||||
import { Intent, ProgressBarCell } from '@vegaprotocol/ui-toolkit';
|
||||
import { Intent } from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
const EmptyCell = () => '';
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { EXPIRE_DATE_FORMAT } from '../../constants';
|
||||
const SimpleMarketExpires = ({
|
||||
tags,
|
||||
}: {
|
||||
tags?: ReadonlyArray<string> | null;
|
||||
tags: ReadonlyArray<string> | null;
|
||||
}) => {
|
||||
if (tags) {
|
||||
const dateFound = tags.reduce<Date | null>((agg, tag) => {
|
||||
|
||||
@@ -58,17 +58,21 @@ let marketsMock = [
|
||||
},
|
||||
] as unknown as Market[];
|
||||
|
||||
const LIB = '@vegaprotocol/react-helpers';
|
||||
const useDataProvider = () => {
|
||||
const LIB = '@vegaprotocol/market-list';
|
||||
const useMarketList = () => {
|
||||
return {
|
||||
data: marketsMock,
|
||||
data: {
|
||||
markets: marketsMock,
|
||||
marketsData: [],
|
||||
marketsCandles: [],
|
||||
},
|
||||
loading: false,
|
||||
error: false,
|
||||
};
|
||||
};
|
||||
jest.mock(LIB, () => ({
|
||||
...jest.requireActual(LIB),
|
||||
useDataProvider: jest.fn(() => useDataProvider()),
|
||||
useMarketList: jest.fn(() => useMarketList()),
|
||||
}));
|
||||
|
||||
const mockIsTradable = jest.fn((_arg) => true);
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import { useCallback, useEffect, useRef, useMemo } from 'react';
|
||||
import React, { useCallback, useEffect, useRef } from 'react';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import {
|
||||
useScreenDimensions,
|
||||
useDataProvider,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import { useScreenDimensions } from '@vegaprotocol/react-helpers';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import type { MarketState } from '@vegaprotocol/types';
|
||||
import useMarketsFilterData from './use-markets-filter-data';
|
||||
@@ -12,9 +9,8 @@ import useColumnDefinitions from './use-column-definitions';
|
||||
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 { Interval } from '@vegaprotocol/types';
|
||||
import { marketsWithCandlesProvider } from '@vegaprotocol/market-list';
|
||||
import type { Market, MarketsListData } from '@vegaprotocol/market-list';
|
||||
import { useMarketList } from '@vegaprotocol/market-list';
|
||||
|
||||
export type MarketWithPercentChange = Market & {
|
||||
percentChange?: number | '-';
|
||||
@@ -33,19 +29,8 @@ const SimpleMarketList = () => {
|
||||
const statusesRef = useRef<Record<string, MarketState | ''>>({});
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
|
||||
const variables = useMemo(() => {
|
||||
const yesterday = Math.round(new Date().getTime() / 1000) - 24 * 3600;
|
||||
return {
|
||||
since: new Date(yesterday * 1000).toISOString(),
|
||||
interval: Interval.INTERVAL_I1H,
|
||||
};
|
||||
}, []);
|
||||
const { data, error, loading } = useDataProvider({
|
||||
dataProvider: marketsWithCandlesProvider,
|
||||
variables,
|
||||
noUpdate: true,
|
||||
});
|
||||
const localData = useMarketsFilterData(data, params);
|
||||
const { data, error, loading } = useMarketList();
|
||||
const localData = useMarketsFilterData(data as MarketsListData, params);
|
||||
|
||||
const handleOnGridReady = useCallback(() => {
|
||||
gridRef.current?.api?.sizeColumnsToFit();
|
||||
@@ -53,7 +38,7 @@ const SimpleMarketList = () => {
|
||||
|
||||
useEffect(() => {
|
||||
const statuses: Record<string, MarketState | ''> = {};
|
||||
data?.forEach((market) => {
|
||||
data?.markets?.forEach((market) => {
|
||||
statuses[market.id] = market.state || '';
|
||||
});
|
||||
statusesRef.current = statuses;
|
||||
@@ -77,7 +62,7 @@ const SimpleMarketList = () => {
|
||||
|
||||
return (
|
||||
<div className="h-full p-4 md:p-6 grid grid-rows-[min-content,1fr]">
|
||||
<SimpleMarketToolbar data={data || []} />
|
||||
<SimpleMarketToolbar data={data?.markets || []} />
|
||||
<AsyncRenderer loading={loading} error={error} data={localData}>
|
||||
<ConsoleLiteGrid<MarketWithPercentChange>
|
||||
classNamesParam="mb-32 min-h-[300px]"
|
||||
@@ -85,7 +70,6 @@ const SimpleMarketList = () => {
|
||||
rowData={localData}
|
||||
defaultColDef={defaultColDef}
|
||||
handleRowClicked={handleRowClicked}
|
||||
getRowId={({ data }) => data.id}
|
||||
/>
|
||||
</AsyncRenderer>
|
||||
</div>
|
||||
|
||||
@@ -15,13 +15,13 @@ import {
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { MarketState } from '@vegaprotocol/types';
|
||||
import useMarketFiltersData from '../../hooks/use-markets-filter';
|
||||
import type { Market } from '@vegaprotocol/market-list';
|
||||
import type { Markets_marketsConnection_edges_node } from '@vegaprotocol/market-list';
|
||||
import { HorizontalMenu } from '../horizontal-menu';
|
||||
import type { HorizontalMenuItem } from '../horizontal-menu';
|
||||
import * as constants from './constants';
|
||||
|
||||
interface Props {
|
||||
data: Market[];
|
||||
data: Markets_marketsConnection_edges_node[];
|
||||
}
|
||||
|
||||
const SimpleMarketToolbar = ({ data }: Props) => {
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Icon } from '@vegaprotocol/ui-toolkit';
|
||||
import type { ValueSetterParams } from 'ag-grid-community';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import { IS_MARKET_TRADABLE, MARKET_STATES_MAP } from '../../constants';
|
||||
import type { MarketWithCandles as Market } from '@vegaprotocol/market-list';
|
||||
import type { Candle, Market } from '@vegaprotocol/market-list';
|
||||
|
||||
interface Props {
|
||||
isMobile: boolean;
|
||||
@@ -69,16 +69,15 @@ const useColumnDefinitions = ({ isMobile }: Props) => {
|
||||
data,
|
||||
setValue,
|
||||
}: {
|
||||
data: Market;
|
||||
data: { id: string; candles: Candle[] };
|
||||
setValue: (arg: unknown) => void;
|
||||
}) =>
|
||||
data.candles && (
|
||||
<SimpleMarketPercentChange
|
||||
candles={data.candles}
|
||||
marketId={data.id}
|
||||
setValue={setValue}
|
||||
/>
|
||||
),
|
||||
}) => (
|
||||
<SimpleMarketPercentChange
|
||||
candles={data.candles}
|
||||
marketId={data.id}
|
||||
setValue={setValue}
|
||||
/>
|
||||
),
|
||||
comparator: (valueA: number | '-', valueB: number | '-') => {
|
||||
if (valueA === valueB) return 0;
|
||||
if (valueA === '-') {
|
||||
|
||||
+19
-10
@@ -1,15 +1,12 @@
|
||||
import { useMemo } from 'react';
|
||||
import { MarketState } from '@vegaprotocol/types';
|
||||
import type { MarketWithCandles } from '@vegaprotocol/market-list';
|
||||
import type { MarketsListData } from '@vegaprotocol/market-list';
|
||||
import type { RouterParams } from './simple-market-list';
|
||||
|
||||
const useMarketsFilterData = (
|
||||
data: MarketWithCandles[] | null,
|
||||
params: RouterParams
|
||||
) => {
|
||||
const useMarketsFilterData = (data: MarketsListData, params: RouterParams) => {
|
||||
return useMemo(() => {
|
||||
return (
|
||||
data?.filter((item) => {
|
||||
const markets =
|
||||
data?.markets?.filter((item) => {
|
||||
if (
|
||||
params.product &&
|
||||
params.product !==
|
||||
@@ -35,9 +32,21 @@ const useMarketsFilterData = (
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}) || []
|
||||
);
|
||||
}, [data, params.product, params.asset, params.state]);
|
||||
}) || [];
|
||||
|
||||
return markets.map((market) => ({
|
||||
...market,
|
||||
candles: (data?.marketsCandles || [])
|
||||
.filter((c) => c.marketId === market.id)
|
||||
.map((c) => c.candles),
|
||||
}));
|
||||
}, [
|
||||
data?.marketsCandles,
|
||||
data?.markets,
|
||||
params.product,
|
||||
params.asset,
|
||||
params.state,
|
||||
]);
|
||||
};
|
||||
|
||||
export default useMarketsFilterData;
|
||||
|
||||
+3
-3
@@ -10,8 +10,8 @@ export const VegaWalletConnectButton = ({
|
||||
setConnectDialog,
|
||||
setManageDialog,
|
||||
}: VegaWalletConnectButtonProps) => {
|
||||
const { pubKey } = useVegaWallet();
|
||||
const isConnected = pubKey !== null;
|
||||
const { keypair } = useVegaWallet();
|
||||
const isConnected = keypair !== null;
|
||||
|
||||
const handleClick = () => {
|
||||
if (isConnected) {
|
||||
@@ -31,7 +31,7 @@ export const VegaWalletConnectButton = ({
|
||||
onClick={handleClick}
|
||||
className="ml-auto inline-block text-ui-small font-mono hover:underline"
|
||||
>
|
||||
{isConnected ? truncateByChars(pubKey) : 'Connect Vega wallet'}
|
||||
{isConnected ? truncateByChars(keypair.pub) : 'Connect Vega wallet'}
|
||||
</button>
|
||||
</span>
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { Side } from '@vegaprotocol/types';
|
||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||
import type { Order } from '@vegaprotocol/orders';
|
||||
import useCalculateSlippage from './use-calculate-slippage';
|
||||
|
||||
const mockData = {
|
||||
@@ -84,10 +84,7 @@ describe('useCalculateSlippage Hook', () => {
|
||||
() =>
|
||||
useCalculateSlippage({
|
||||
marketId: 'marketId',
|
||||
order: {
|
||||
size: '10',
|
||||
side: Side.SIDE_BUY,
|
||||
} as OrderSubmissionBody['orderSubmission'],
|
||||
order: { size: '10', side: Side.SIDE_BUY } as Order,
|
||||
}),
|
||||
{
|
||||
wrapper: MockedProvider,
|
||||
@@ -101,10 +98,7 @@ describe('useCalculateSlippage Hook', () => {
|
||||
() =>
|
||||
useCalculateSlippage({
|
||||
marketId: 'marketId',
|
||||
order: {
|
||||
size: '10',
|
||||
side: Side.SIDE_SELL,
|
||||
} as OrderSubmissionBody['orderSubmission'],
|
||||
order: { size: '10', side: Side.SIDE_SELL } as Order,
|
||||
}),
|
||||
{
|
||||
wrapper: MockedProvider,
|
||||
@@ -127,10 +121,7 @@ describe('useCalculateSlippage Hook', () => {
|
||||
() =>
|
||||
useCalculateSlippage({
|
||||
marketId: 'marketId',
|
||||
order: {
|
||||
size: '10',
|
||||
side: Side.SIDE_SELL,
|
||||
} as OrderSubmissionBody['orderSubmission'],
|
||||
order: { size: '10', side: Side.SIDE_SELL } as Order,
|
||||
}),
|
||||
{
|
||||
wrapper: MockedProvider,
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Side } from '@vegaprotocol/types';
|
||||
import { useOrderBookData } from '@vegaprotocol/market-depth';
|
||||
import { marketProvider } from '@vegaprotocol/market-list';
|
||||
import type { Market } from '@vegaprotocol/market-list';
|
||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||
import type { Order } from '@vegaprotocol/orders';
|
||||
import { BigNumber } from 'bignumber.js';
|
||||
import {
|
||||
formatNumber,
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
|
||||
interface Props {
|
||||
marketId: string;
|
||||
order: OrderSubmissionBody['orderSubmission'];
|
||||
order: Order;
|
||||
}
|
||||
|
||||
const useCalculateSlippage = ({ marketId, order }: Props) => {
|
||||
|
||||
@@ -14,9 +14,6 @@ const useMarketFilters = (data: Market[]) => {
|
||||
const product = item.tradableInstrument.instrument.product.__typename;
|
||||
const asset =
|
||||
item.tradableInstrument.instrument.product.settlementAsset.symbol;
|
||||
if (!product) {
|
||||
return;
|
||||
}
|
||||
if (!(product in localAssetPerProduct)) {
|
||||
localAssetPerProduct[product] = new Set<string>();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import useMarketPositions from './use-market-positions';
|
||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||
import type { Order } from '@vegaprotocol/orders';
|
||||
import type { PartyBalanceQuery_party_accounts } from '../components/deal-ticket/__generated__/PartyBalanceQuery';
|
||||
import { useSettlementAccount } from './use-settlement-account';
|
||||
import { AccountType, Side } from '@vegaprotocol/types';
|
||||
@@ -11,7 +11,7 @@ interface Props {
|
||||
marketId: string;
|
||||
price?: string;
|
||||
settlementAssetId: string;
|
||||
order: OrderSubmissionBody['orderSubmission'];
|
||||
order: Order;
|
||||
}
|
||||
|
||||
const getSize = (balance: string, price: string) =>
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as React from 'react';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import useOrderCloseOut from './use-order-closeout';
|
||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||
import type { Order } from '@vegaprotocol/orders';
|
||||
import type { DealTicketMarketFragment } from '@vegaprotocol/deal-ticket';
|
||||
import type { PartyBalanceQuery } from '../components/deal-ticket/__generated__/PartyBalanceQuery';
|
||||
|
||||
@@ -48,7 +48,7 @@ describe('useOrderCloseOut Hook', () => {
|
||||
const { result } = renderHook(
|
||||
() =>
|
||||
useOrderCloseOut({
|
||||
order: order as OrderSubmissionBody['orderSubmission'],
|
||||
order: order as Order,
|
||||
market: market as DealTicketMarketFragment,
|
||||
partyData: partyData as PartyBalanceQuery,
|
||||
}),
|
||||
@@ -65,10 +65,7 @@ describe('useOrderCloseOut Hook', () => {
|
||||
const { result } = renderHook(
|
||||
() =>
|
||||
useOrderCloseOut({
|
||||
order: {
|
||||
...order,
|
||||
side: 'SIDE_SELL',
|
||||
} as OrderSubmissionBody['orderSubmission'],
|
||||
order: { ...order, side: 'SIDE_SELL' } as Order,
|
||||
market: market as DealTicketMarketFragment,
|
||||
partyData: partyData as PartyBalanceQuery,
|
||||
}),
|
||||
@@ -85,10 +82,7 @@ describe('useOrderCloseOut Hook', () => {
|
||||
const { result } = renderHook(
|
||||
() =>
|
||||
useOrderCloseOut({
|
||||
order: {
|
||||
...order,
|
||||
side: 'SIDE_SELL',
|
||||
} as OrderSubmissionBody['orderSubmission'],
|
||||
order: { ...order, side: 'SIDE_SELL' } as Order,
|
||||
market: market as DealTicketMarketFragment,
|
||||
}),
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { BigNumber } from 'bignumber.js';
|
||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||
import type { Order } from '@vegaprotocol/orders';
|
||||
import type { DealTicketMarketFragment } from '@vegaprotocol/deal-ticket';
|
||||
import type { PartyBalanceQuery } from '../components/deal-ticket/__generated__/PartyBalanceQuery';
|
||||
import { useSettlementAccount } from './use-settlement-account';
|
||||
@@ -46,13 +46,13 @@ const CLOSEOUT_PRICE_QUERY = gql`
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
order: OrderSubmissionBody['orderSubmission'];
|
||||
order: Order;
|
||||
market: DealTicketMarketFragment;
|
||||
partyData?: PartyBalanceQuery;
|
||||
}
|
||||
|
||||
const useOrderCloseOut = ({ order, market, partyData }: Props): string => {
|
||||
const { pubKey } = useVegaWallet();
|
||||
const { keypair } = useVegaWallet();
|
||||
const account = useSettlementAccount(
|
||||
market.tradableInstrument.instrument.product.settlementAsset.id,
|
||||
partyData?.party?.accounts || []
|
||||
@@ -61,15 +61,15 @@ const useOrderCloseOut = ({ order, market, partyData }: Props): string => {
|
||||
CLOSEOUT_PRICE_QUERY,
|
||||
{
|
||||
pollInterval: 5000,
|
||||
variables: { partyId: pubKey || '' },
|
||||
skip: !pubKey,
|
||||
variables: { partyId: keypair?.pub || '' },
|
||||
skip: !keypair?.pub,
|
||||
}
|
||||
);
|
||||
|
||||
const markPriceData = useMarketData(market.id);
|
||||
const marketPositions = useMarketPositions({
|
||||
marketId: market.id,
|
||||
partyId: pubKey || '',
|
||||
partyId: keypair?.pub || '',
|
||||
});
|
||||
|
||||
const marginMaintenanceLevel = new BigNumber(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { useQuery } from '@apollo/client';
|
||||
import { BigNumber } from 'bignumber.js';
|
||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||
import type { Order } from '@vegaprotocol/orders';
|
||||
import type { DealTicketMarketFragment } from '@vegaprotocol/deal-ticket';
|
||||
import type { PositionMargin } from './use-market-positions';
|
||||
import useOrderMargin from './use-order-margin';
|
||||
@@ -53,7 +53,7 @@ describe('useOrderMargin Hook', () => {
|
||||
it('margin should be properly calculated', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useOrderMargin({
|
||||
order: order as OrderSubmissionBody['orderSubmission'],
|
||||
order: order as Order,
|
||||
market: market as DealTicketMarketFragment,
|
||||
partyId,
|
||||
})
|
||||
@@ -71,7 +71,7 @@ describe('useOrderMargin Hook', () => {
|
||||
it('fees should be properly calculated', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useOrderMargin({
|
||||
order: order as OrderSubmissionBody['orderSubmission'],
|
||||
order: order as Order,
|
||||
market: market as DealTicketMarketFragment,
|
||||
partyId,
|
||||
})
|
||||
@@ -83,7 +83,7 @@ describe('useOrderMargin Hook', () => {
|
||||
mockMarketPositions = null;
|
||||
const { result } = renderHook(() =>
|
||||
useOrderMargin({
|
||||
order: order as OrderSubmissionBody['orderSubmission'],
|
||||
order: order as Order,
|
||||
market: market as DealTicketMarketFragment,
|
||||
partyId,
|
||||
})
|
||||
@@ -110,7 +110,7 @@ describe('useOrderMargin Hook', () => {
|
||||
};
|
||||
const { result } = renderHook(() =>
|
||||
useOrderMargin({
|
||||
order: order as OrderSubmissionBody['orderSubmission'],
|
||||
order: order as Order,
|
||||
market: market as DealTicketMarketFragment,
|
||||
partyId,
|
||||
})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { BigNumber } from 'bignumber.js';
|
||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||
import type { Order } from '@vegaprotocol/orders';
|
||||
import { gql, useQuery } from '@apollo/client';
|
||||
import type {
|
||||
EstimateOrder,
|
||||
@@ -46,7 +46,7 @@ export const ESTIMATE_ORDER_QUERY = gql`
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
order: OrderSubmissionBody['orderSubmission'];
|
||||
order: Order;
|
||||
market: DealTicketMarketFragment;
|
||||
partyId: string;
|
||||
}
|
||||
|
||||
@@ -25,16 +25,11 @@ module.exports = defineConfig({
|
||||
env: {
|
||||
environment: 'CUSTOM',
|
||||
networkQueryUrl: 'http://localhost:3028/query',
|
||||
ethUrl: 'https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8',
|
||||
ethUrl: 'https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8',
|
||||
commitHash: 'dev',
|
||||
CYPRESS_TEARDOWN_NETWORK_AFTER_FLOWS: true,
|
||||
tsConfig: 'tsconfig.json',
|
||||
grepTags: '@regression @smoke @slow',
|
||||
grepFilterSpecs: true,
|
||||
grepOmitFiltered: true,
|
||||
vegaWalletName: 'capsule_wallet',
|
||||
vegaWalletLocation: '~/.vegacapsule/testnet/wallet',
|
||||
vegaWalletPublicKey:
|
||||
'02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io"
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
123
|
||||
@@ -1 +0,0 @@
|
||||
ozone access unlock valid olympic save include omit supply green clown session
|
||||
@@ -1,111 +1,16 @@
|
||||
import '../support/common.functions';
|
||||
|
||||
context('Asset page', { tags: '@regression' }, function () {
|
||||
describe('Verify elements on page', function () {
|
||||
const assetsNavigation = 'a[href="/assets"]';
|
||||
const assetHeader = '[data-testid="asset-header"]';
|
||||
const jsonSection = '.language-json';
|
||||
|
||||
before('Navigate to assets page', function () {
|
||||
cy.visit('/');
|
||||
cy.get(assetsNavigation).click();
|
||||
});
|
||||
|
||||
it('Assets page is displayed', function () {
|
||||
cy.visit('/');
|
||||
cy.get(assetsNavigation).click();
|
||||
cy.common_validate_blocks_data_displayed(assetHeader);
|
||||
});
|
||||
|
||||
it('Assets and all asset details are displayed in JSON', function () {
|
||||
cy.get_asset_information().then((assetsInfo) => {
|
||||
const assetNames = Object.keys(assetsInfo);
|
||||
assert.isAtLeast(
|
||||
assetNames.length,
|
||||
3,
|
||||
'Ensuring we have at least 3 assets to test'
|
||||
);
|
||||
|
||||
assetNames.forEach((assetName) => {
|
||||
cy.get(assetHeader)
|
||||
.contains(assetName)
|
||||
.next()
|
||||
.within(() => {
|
||||
cy.get(jsonSection)
|
||||
.invoke('text')
|
||||
.convert_string_json_to_js_object()
|
||||
.then((assetsListedInJson) => {
|
||||
const assetInfo = assetsInfo[assetName];
|
||||
|
||||
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.source.__typename
|
||||
);
|
||||
|
||||
if (assetInfo.source.__typename == 'ERC20') {
|
||||
assert.equal(
|
||||
assetsListedInJson.source.contractAddress,
|
||||
assetInfo.source.contractAddress
|
||||
);
|
||||
}
|
||||
|
||||
if (assetInfo.source.__typename == 'BuiltinAsset') {
|
||||
assert.equal(
|
||||
assetsListedInJson.source.maxFaucetAmountMint,
|
||||
assetInfo.source.maxFaucetAmountMint
|
||||
);
|
||||
}
|
||||
|
||||
let knownAssetTypes = ['BuiltinAsset', 'ERC20'];
|
||||
assert.include(
|
||||
knownAssetTypes,
|
||||
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`
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Assets page able to switch between light and dark mode', function () {
|
||||
const whiteThemeSelectedMenuOptionColor = 'rgb(255, 7, 127)';
|
||||
const whiteThemeJsonFieldBackColor = 'rgb(255, 255, 255)';
|
||||
const whiteThemeSideMenuBackgroundColor = 'rgb(255, 255, 255)';
|
||||
const blackThemeSelectedMenuOptionColor = 'rgb(223, 255, 11)';
|
||||
const blackThemeJsonFieldBackColor = 'rgb(38, 38, 38)';
|
||||
const blackThemeSideMenuBackgroundColor = 'rgb(0, 0, 0)';
|
||||
const themeSwitcher = '[data-testid="theme-switcher"]';
|
||||
const jsonFields = '.hljs';
|
||||
const sideMenuBackground = '.absolute';
|
||||
|
||||
// White Mode
|
||||
cy.get(themeSwitcher).click();
|
||||
cy.get(assetsNavigation)
|
||||
.should('have.css', 'background-color')
|
||||
.and('include', whiteThemeSelectedMenuOptionColor);
|
||||
cy.get(jsonFields)
|
||||
.should('have.css', 'background-color')
|
||||
.and('include', whiteThemeJsonFieldBackColor);
|
||||
cy.get(sideMenuBackground)
|
||||
.should('have.css', 'background-color')
|
||||
.and('include', whiteThemeSideMenuBackgroundColor);
|
||||
|
||||
// Dark Mode
|
||||
cy.get(themeSwitcher).click();
|
||||
cy.get(assetsNavigation)
|
||||
.should('have.css', 'background-color')
|
||||
.and('include', blackThemeSelectedMenuOptionColor);
|
||||
cy.get(jsonFields)
|
||||
.should('have.css', 'background-color')
|
||||
.and('include', blackThemeJsonFieldBackColor);
|
||||
cy.get(sideMenuBackground)
|
||||
.should('have.css', 'background-color')
|
||||
.and('include', blackThemeSideMenuBackgroundColor);
|
||||
});
|
||||
|
||||
it('Assets page displayed in mobile', function () {
|
||||
cy.common_switch_to_mobile_and_click_toggle();
|
||||
cy.get(assetsNavigation).click();
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import '../support/common.functions';
|
||||
|
||||
context('Blocks page', { tags: '@regression' }, function () {
|
||||
before('visit token home page', function () {
|
||||
cy.visit('/');
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import '../support/common.functions';
|
||||
|
||||
//Tests set to skip until market bug for capsule checkpoint is fixed
|
||||
context.skip('Market page', { tags: '@regression' }, function () {
|
||||
describe('Verify elements on page', function () {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import '../support/common.functions';
|
||||
|
||||
context('Network parameters page', { tags: '@smoke' }, function () {
|
||||
before('visit token home page', function () {
|
||||
cy.visit('/');
|
||||
|
||||
@@ -1,240 +0,0 @@
|
||||
const vegaWalletPublicKey = Cypress.env('vegaWalletPublicKey');
|
||||
const partiesMenuHeader = 'a[href="/parties"]';
|
||||
const partiesSearchBox = '[data-testid="party-input"]';
|
||||
const partiesSearchAction = '[data-testid="go-submit"]';
|
||||
const partiesJsonSection = '[data-testid="parties-json"]';
|
||||
const txTimeout = Cypress.env('txTimeout');
|
||||
|
||||
let assetData = {
|
||||
fUSDC: { id: 'fUSDC', name: 'USDC (fake)', amount: '10' },
|
||||
fBTC: { id: 'fBTC', name: 'BTC (fake)', amount: '6' },
|
||||
fEURO: { id: 'fEURO', name: 'EURO (fake)', amount: '8' },
|
||||
fDAI: { id: 'fDAI', name: 'DAI (fake)', amount: '2' },
|
||||
};
|
||||
|
||||
const assetsInTest = Object.keys(assetData);
|
||||
|
||||
context('Parties page', { tags: '@regression' }, function () {
|
||||
before('send-faucet assets to connected vega wallet', function () {
|
||||
cy.vega_wallet_import();
|
||||
assetsInTest.forEach((asset) => {
|
||||
cy.vega_wallet_receive_fauceted_asset(
|
||||
assetData[asset].name,
|
||||
assetData[asset].amount,
|
||||
vegaWalletPublicKey
|
||||
);
|
||||
});
|
||||
cy.visit('/');
|
||||
});
|
||||
|
||||
describe('Verify parties page content', function () {
|
||||
before('navigate to parties page and search for party', function () {
|
||||
cy.get(partiesMenuHeader).click();
|
||||
// Deliberate slow entry of party id/key - enabling transactions to sync
|
||||
cy.get(partiesSearchBox).type(vegaWalletPublicKey, { delay: 120 });
|
||||
cy.get(partiesSearchAction).click();
|
||||
cy.get_connected_parties_accounts().as('party_accounts');
|
||||
|
||||
// Ensure balance of each party asset is correct
|
||||
cy.get('@party_accounts').then((accounts) => {
|
||||
assetsInTest.forEach((asset) => {
|
||||
cy.get_asset_decimals(assetData[asset].id).then((assetDecimals) => {
|
||||
assert.equal(
|
||||
accounts[assetData[asset].id].balance,
|
||||
assetData[asset].amount + assetDecimals,
|
||||
`Checking ${assetData[asset].id} faucet was successfull`
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should see party address id - having searched', function () {
|
||||
cy.contains('Address')
|
||||
.siblings()
|
||||
.contains(vegaWalletPublicKey)
|
||||
.should('be.visible');
|
||||
});
|
||||
|
||||
it('should see each asset and balance - within asset data section', function () {
|
||||
assetsInTest.forEach((asset) => {
|
||||
cy.contains(assetData[asset].name, txTimeout).should('be.visible');
|
||||
cy.contains(assetData[asset].name)
|
||||
.siblings()
|
||||
.contains(assetData[asset].id)
|
||||
.should('be.visible');
|
||||
cy.contains(assetData[asset].name, txTimeout)
|
||||
.parent()
|
||||
.siblings()
|
||||
.within(() => {
|
||||
cy.get_asset_decimals(asset).then((assetDecimals) => {
|
||||
cy.contains_exactly(
|
||||
assetData[asset].amount + '.' + assetDecimals
|
||||
).should('be.visible');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to copy the party address id', function () {
|
||||
cy.monitor_clipboard().as('clipboard');
|
||||
cy.contains('Address').siblings().last().click();
|
||||
cy.get('@clipboard')
|
||||
.get_copied_text_from_clipboard()
|
||||
.should('equal', vegaWalletPublicKey);
|
||||
});
|
||||
|
||||
it('should be able to copy an asset id', function () {
|
||||
cy.monitor_clipboard().as('clipboard');
|
||||
|
||||
cy.contains(assetData.fDAI.name, txTimeout).should('be.visible');
|
||||
cy.contains(assetData.fDAI.name)
|
||||
.siblings()
|
||||
.within(() => {
|
||||
cy.get('[data-state="closed"]').last().click({ force: true });
|
||||
});
|
||||
|
||||
cy.get('@clipboard')
|
||||
.get_copied_text_from_clipboard()
|
||||
.should('equal', assetData.fDAI.id);
|
||||
});
|
||||
|
||||
it('should be able to see JSON of each asset containing correct balance and decimals', function () {
|
||||
cy.get(partiesJsonSection).should('be.visible');
|
||||
|
||||
assetsInTest.forEach((assetInTest) => {
|
||||
cy.get(partiesJsonSection)
|
||||
.invoke('text')
|
||||
.convert_string_json_to_js_object()
|
||||
.get_party_accounts_data_from_js_object()
|
||||
.then((accountsListedInJson) => {
|
||||
cy.get_asset_information().then((assetsInfo) => {
|
||||
const assetInfo =
|
||||
assetsInfo[accountsListedInJson[assetInTest].asset.name];
|
||||
|
||||
assert.equal(
|
||||
accountsListedInJson[assetInTest].asset.name,
|
||||
assetInfo.name
|
||||
);
|
||||
assert.equal(
|
||||
accountsListedInJson[assetInTest].asset.id,
|
||||
assetInfo.id
|
||||
);
|
||||
assert.equal(
|
||||
accountsListedInJson[assetInTest].asset.decimals,
|
||||
assetInfo.decimals
|
||||
);
|
||||
assert.equal(
|
||||
accountsListedInJson[assetInTest].asset.symbol,
|
||||
assetInfo.symbol
|
||||
);
|
||||
assert.equal(
|
||||
accountsListedInJson[assetInTest].asset.source.__typename,
|
||||
assetInfo.source.__typename
|
||||
);
|
||||
cy.get_asset_decimals(assetInTest).then((assetDecimals) => {
|
||||
assert.equal(
|
||||
accountsListedInJson[assetInTest].balance,
|
||||
assetData[assetInTest].amount + assetDecimals
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to switch parties page between light and dark mode', function () {
|
||||
const whiteThemeSelectedMenuOptionColor = 'rgb(255, 7, 127)';
|
||||
const whiteThemeJsonFieldBackColor = 'rgb(255, 255, 255)';
|
||||
const whiteThemeSideMenuBackgroundColor = 'rgb(255, 255, 255)';
|
||||
const blackThemeSelectedMenuOptionColor = 'rgb(223, 255, 11)';
|
||||
const blackThemeJsonFieldBackColor = 'rgb(38, 38, 38)';
|
||||
const blackThemeSideMenuBackgroundColor = 'rgb(0, 0, 0)';
|
||||
const themeSwitcher = '[data-testid="theme-switcher"]';
|
||||
const jsonFields = '.hljs';
|
||||
const sideMenuBackground = '.absolute';
|
||||
|
||||
// White Mode
|
||||
cy.get(themeSwitcher).click();
|
||||
cy.get(partiesMenuHeader)
|
||||
.should('have.css', 'background-color')
|
||||
.and('include', whiteThemeSelectedMenuOptionColor);
|
||||
cy.get(jsonFields)
|
||||
.should('have.css', 'background-color')
|
||||
.and('include', whiteThemeJsonFieldBackColor);
|
||||
cy.get(sideMenuBackground)
|
||||
.should('have.css', 'background-color')
|
||||
.and('include', whiteThemeSideMenuBackgroundColor);
|
||||
|
||||
// Dark Mode
|
||||
cy.get(themeSwitcher).click();
|
||||
cy.get(partiesMenuHeader)
|
||||
.should('have.css', 'background-color')
|
||||
.and('include', blackThemeSelectedMenuOptionColor);
|
||||
cy.get(jsonFields)
|
||||
.should('have.css', 'background-color')
|
||||
.and('include', blackThemeJsonFieldBackColor);
|
||||
cy.get(sideMenuBackground)
|
||||
.should('have.css', 'background-color')
|
||||
.and('include', blackThemeSideMenuBackgroundColor);
|
||||
});
|
||||
|
||||
after(
|
||||
'teardown environment to prevent test data bleeding into other tests',
|
||||
function () {
|
||||
if (Cypress.env('CYPRESS_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;
|
||||
let decimals = '';
|
||||
for (let i = 0; i < assetDecimals; i++) decimals += '0';
|
||||
return decimals;
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('get_connected_parties_accounts', () => {
|
||||
const mutation =
|
||||
'{partiesConnection {edges{node{accountsConnection{edges{node{\
|
||||
balance type asset {id symbol decimals}}}}}}}}';
|
||||
cy.request({
|
||||
method: 'POST',
|
||||
url: `http://localhost:3028/query`,
|
||||
body: {
|
||||
query: mutation,
|
||||
},
|
||||
headers: { 'content-type': 'application/json' },
|
||||
})
|
||||
.its(
|
||||
`body.data.partiesConnection.edges.1.node.accountsConnection.edges`
|
||||
)
|
||||
.then(function (response) {
|
||||
let accounts = {};
|
||||
response.forEach((account) => {
|
||||
accounts[account.node.asset.id] = account.node;
|
||||
});
|
||||
return accounts;
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add(
|
||||
'get_party_accounts_data_from_js_object',
|
||||
{ prevSubject: true },
|
||||
(jsObject) => {
|
||||
const accounts = jsObject.party.accounts.reduce(function (
|
||||
account,
|
||||
entry
|
||||
) {
|
||||
account[entry.asset.id] = entry;
|
||||
return account;
|
||||
},
|
||||
{});
|
||||
return accounts;
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1,3 +1,5 @@
|
||||
import '../support/common.functions';
|
||||
|
||||
context('Validator page', { tags: '@smoke' }, function () {
|
||||
describe('Verify elements on page', function () {
|
||||
const validatorNavigation = 'a[href="/validators"]';
|
||||
|
||||
@@ -51,27 +51,3 @@ Cypress.Commands.add('common_verify_json_int_values', function (expectedNum) {
|
||||
cy.wrap($paramValue).should('not.be.empty');
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('monitor_clipboard', () => {
|
||||
cy.window().then((win) => {
|
||||
return cy.stub(win, 'prompt').returns(win.prompt);
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add(
|
||||
'get_copied_text_from_clipboard',
|
||||
{ prevSubject: true },
|
||||
(clipboard) => {
|
||||
// Must first setup with cy.monitor_clipboard().as('clipboard')
|
||||
// This function then chained off a cy.get('@clipboard')
|
||||
return clipboard.args[0][1];
|
||||
}
|
||||
);
|
||||
|
||||
Cypress.Commands.add(
|
||||
'convert_string_json_to_js_object',
|
||||
{ prevSubject: true },
|
||||
(jsonBlobString) => {
|
||||
return JSON.parse(jsonBlobString);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -14,6 +14,5 @@
|
||||
// ***********************************************************
|
||||
|
||||
import '@vegaprotocol/cypress';
|
||||
import './common.functions.js';
|
||||
import registerCypressGrep from 'cypress-grep';
|
||||
registerCypressGrep();
|
||||
|
||||
@@ -5,7 +5,6 @@ NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
|
||||
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
|
||||
NX_VEGA_ENV=STAGNET3
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
||||
|
||||
# App flags
|
||||
NX_EXPLORER_ASSETS=1
|
||||
|
||||
@@ -7,4 +7,3 @@ NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https:
|
||||
NX_VEGA_ENV=TESTNET
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_VEGA_URL=https://api.n09.testnet.vega.xyz/graphql
|
||||
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
||||
|
||||
@@ -14,12 +14,7 @@ jest.mock('../search', () => ({
|
||||
|
||||
const renderComponent = () => (
|
||||
<MemoryRouter>
|
||||
<Header
|
||||
theme="dark"
|
||||
toggleTheme={jest.fn()}
|
||||
menuOpen={false}
|
||||
setMenuOpen={jest.fn()}
|
||||
/>
|
||||
<Header />
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
|
||||
@@ -1,231 +0,0 @@
|
||||
import {
|
||||
detectTypeByFetching,
|
||||
detectTypeFromQuery,
|
||||
getSearchType,
|
||||
isBlock,
|
||||
isHexadecimal,
|
||||
isNetworkParty,
|
||||
isNonHex,
|
||||
SearchTypes,
|
||||
toHex,
|
||||
toNonHex,
|
||||
} from './detect-search';
|
||||
import { DATA_SOURCES } from '../../config';
|
||||
|
||||
global.fetch = jest.fn();
|
||||
|
||||
describe('Detect Search', () => {
|
||||
it("should detect that it's a hexadecimal", () => {
|
||||
const expected = true;
|
||||
const testString =
|
||||
'0x073ceaab59e5f2dd0561dec4883e7ee5bc7165cd4de34717a3ab8f2cbe3007f9';
|
||||
const actual = isHexadecimal(testString);
|
||||
expect(actual).toBe(expected);
|
||||
});
|
||||
|
||||
it("should detect that it's not hexadecimal", () => {
|
||||
const expected = true;
|
||||
const testString =
|
||||
'073ceaab59e5f2dd0561dec4883e7ee5bc7165cd4de34717a3ab8f2cbe3007f9';
|
||||
const actual = isNonHex(testString);
|
||||
expect(actual).toBe(expected);
|
||||
});
|
||||
|
||||
it("should detect that it's a network party", () => {
|
||||
const expected = true;
|
||||
const testString = 'network';
|
||||
const actual = isNetworkParty(testString);
|
||||
expect(actual).toBe(expected);
|
||||
});
|
||||
|
||||
it("should detect that it's a block", () => {
|
||||
const expected = true;
|
||||
const testString = '3188';
|
||||
const actual = isBlock(testString);
|
||||
expect(actual).toBe(expected);
|
||||
});
|
||||
|
||||
it('should convert from non-hex to hex', () => {
|
||||
const expected = '0x123';
|
||||
const testString = '123';
|
||||
const actual = toHex(testString);
|
||||
expect(actual).toBe(expected);
|
||||
});
|
||||
|
||||
it('should convert from hex to non-hex', () => {
|
||||
const expected = '123';
|
||||
const testString = '0x123';
|
||||
const actual = toNonHex(testString);
|
||||
expect(actual).toBe(expected);
|
||||
});
|
||||
|
||||
it("should detect type client side from query if it's a hexadecimal", () => {
|
||||
const expected = [SearchTypes.Party, SearchTypes.Transaction];
|
||||
const testString =
|
||||
'0x4624293CFE3D8B67A0AB448BAFF8FBCF1A1B770D9D5F263761D3D6CBEA94D97F';
|
||||
const actual = detectTypeFromQuery(testString);
|
||||
expect(actual).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
it("should detect type client side from query if it's a non hex", () => {
|
||||
const expected = [SearchTypes.Party, SearchTypes.Transaction];
|
||||
const testString =
|
||||
'4624293CFE3D8B67A0AB448BAFF8FBCF1A1B770D9D5F263761D3D6CBEA94D97F';
|
||||
const actual = detectTypeFromQuery(testString);
|
||||
expect(actual).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
it("should detect type client side from query if it's a network party", () => {
|
||||
const expected = [SearchTypes.Party];
|
||||
const testString = 'network';
|
||||
const actual = detectTypeFromQuery(testString);
|
||||
expect(actual).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
it("should detect type client side from query if it's a block (number)", () => {
|
||||
const expected = [SearchTypes.Block];
|
||||
const testString = '23432';
|
||||
const actual = detectTypeFromQuery(testString);
|
||||
expect(actual).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
it("detectTypeByFetching should call fetch with hex query it's a transaction", async () => {
|
||||
const query = 'abc';
|
||||
const type = SearchTypes.Transaction;
|
||||
// @ts-ignore issue related to polyfill
|
||||
fetch.mockImplementation(
|
||||
jest.fn(() =>
|
||||
Promise.resolve({
|
||||
ok: true,
|
||||
json: () =>
|
||||
Promise.resolve({
|
||||
result: {
|
||||
tx: query,
|
||||
},
|
||||
}),
|
||||
})
|
||||
)
|
||||
);
|
||||
const result = await detectTypeByFetching(query, type);
|
||||
expect(fetch).toHaveBeenCalledWith(
|
||||
`${DATA_SOURCES.tendermintUrl}/tx?hash=0x${query}`
|
||||
);
|
||||
expect(result).toBe(type);
|
||||
});
|
||||
|
||||
it("detectTypeByFetching should call fetch with non-hex query it's a party", async () => {
|
||||
const query = 'abc';
|
||||
const type = SearchTypes.Party;
|
||||
// @ts-ignore issue related to polyfill
|
||||
fetch.mockImplementation(
|
||||
jest.fn(() =>
|
||||
Promise.resolve({
|
||||
ok: true,
|
||||
json: () =>
|
||||
Promise.resolve({
|
||||
result: {
|
||||
txs: [query],
|
||||
},
|
||||
}),
|
||||
})
|
||||
)
|
||||
);
|
||||
const result = await detectTypeByFetching(query, type);
|
||||
expect(fetch).toHaveBeenCalledWith(
|
||||
`${DATA_SOURCES.tendermintUrl}/tx_search?query="tx.submitter='${query}'"`
|
||||
);
|
||||
expect(result).toBe(type);
|
||||
});
|
||||
|
||||
it('detectTypeByFetching should return undefined if no matches', async () => {
|
||||
const query = 'abc';
|
||||
const type = SearchTypes.Party;
|
||||
// @ts-ignore issue related to polyfill
|
||||
fetch.mockImplementation(
|
||||
jest.fn(() =>
|
||||
Promise.resolve({
|
||||
ok: false,
|
||||
})
|
||||
)
|
||||
);
|
||||
const result = await detectTypeByFetching(query, type);
|
||||
expect(fetch).toHaveBeenCalledWith(
|
||||
`${DATA_SOURCES.tendermintUrl}/tx_search?query="tx.submitter='${query}'"`
|
||||
);
|
||||
expect(result).toBe(undefined);
|
||||
});
|
||||
|
||||
it('getSearchType should return party from fetch response', async () => {
|
||||
const query =
|
||||
'0x4624293CFE3D8B67A0AB448BAFF8FBCF1A1B770D9D5F263761D3D6CBEA94D97F';
|
||||
const expected = SearchTypes.Party;
|
||||
// @ts-ignore issue related to polyfill
|
||||
fetch.mockImplementation(
|
||||
jest.fn(() =>
|
||||
Promise.resolve({
|
||||
ok: true,
|
||||
json: () =>
|
||||
Promise.resolve({
|
||||
result: {
|
||||
txs: [query],
|
||||
},
|
||||
}),
|
||||
})
|
||||
)
|
||||
);
|
||||
const result = await getSearchType(query);
|
||||
expect(result).toBe(expected);
|
||||
});
|
||||
|
||||
it('getSearchType should return party from transaction response', async () => {
|
||||
const query =
|
||||
'4624293CFE3D8B67A0AB448BAFF8FBCF1A1B770D9D5F263761D3D6CBEA94D97F';
|
||||
const expected = SearchTypes.Transaction;
|
||||
// @ts-ignore issue related to polyfill
|
||||
fetch.mockImplementation(
|
||||
jest.fn(() =>
|
||||
Promise.resolve({
|
||||
ok: true,
|
||||
json: () =>
|
||||
Promise.resolve({
|
||||
result: {
|
||||
tx: query,
|
||||
},
|
||||
}),
|
||||
})
|
||||
)
|
||||
);
|
||||
const result = await getSearchType(query);
|
||||
expect(result).toBe(expected);
|
||||
});
|
||||
|
||||
it('getSearchType should return undefined from transaction response', async () => {
|
||||
const query =
|
||||
'0x4624293CFE3D8B67A0AB448BAFF8FBCF1A1B770D9D5F263761D3D6CBEA94D97F';
|
||||
const expected = undefined;
|
||||
// @ts-ignore issue related to polyfill
|
||||
fetch.mockImplementation(
|
||||
jest.fn(() =>
|
||||
Promise.resolve({
|
||||
ok: false,
|
||||
})
|
||||
)
|
||||
);
|
||||
const result = await getSearchType(query);
|
||||
expect(result).toBe(expected);
|
||||
});
|
||||
|
||||
it('getSearchType should return block if query is number', async () => {
|
||||
const query = '123';
|
||||
const expected = SearchTypes.Block;
|
||||
const result = await getSearchType(query);
|
||||
expect(result).toBe(expected);
|
||||
});
|
||||
|
||||
it('getSearchType should return party if query is network', async () => {
|
||||
const query = 'network';
|
||||
const expected = SearchTypes.Party;
|
||||
const result = await getSearchType(query);
|
||||
expect(result).toBe(expected);
|
||||
});
|
||||
});
|
||||
@@ -1,104 +0,0 @@
|
||||
import { DATA_SOURCES } from '../../config';
|
||||
|
||||
export enum SearchTypes {
|
||||
Transaction = 'transaction',
|
||||
Party = 'party',
|
||||
Block = 'block',
|
||||
Order = 'order',
|
||||
}
|
||||
|
||||
export const TX_LENGTH = 64;
|
||||
|
||||
export const isHexadecimal = (search: string) =>
|
||||
search.startsWith('0x') && search.length === 2 + TX_LENGTH;
|
||||
|
||||
export const isNonHex = (search: string) =>
|
||||
!search.startsWith('0x') && search.length === TX_LENGTH;
|
||||
|
||||
export const isBlock = (search: string) => !Number.isNaN(Number(search));
|
||||
|
||||
export const isNetworkParty = (search: string) => search === 'network';
|
||||
|
||||
export const toHex = (query: string) =>
|
||||
isHexadecimal(query) ? query : `0x${query}`;
|
||||
|
||||
export const toNonHex = (query: string) =>
|
||||
isNonHex(query) ? query : `${query.replace('0x', '')}`;
|
||||
|
||||
export const detectTypeFromQuery = (
|
||||
query: string
|
||||
): SearchTypes[] | undefined => {
|
||||
const i = query.toLowerCase();
|
||||
|
||||
if (isHexadecimal(i) || isNonHex(i)) {
|
||||
return [SearchTypes.Party, SearchTypes.Transaction];
|
||||
} else if (isNetworkParty(i)) {
|
||||
return [SearchTypes.Party];
|
||||
} else if (isBlock(i)) {
|
||||
return [SearchTypes.Block];
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
export const detectTypeByFetching = async (
|
||||
query: string,
|
||||
type: SearchTypes
|
||||
): Promise<SearchTypes | undefined> => {
|
||||
const TYPES = [SearchTypes.Party, SearchTypes.Transaction];
|
||||
|
||||
if (!TYPES.includes(type)) {
|
||||
throw new Error('Search type provided not recognised');
|
||||
}
|
||||
|
||||
if (type === SearchTypes.Transaction) {
|
||||
const hash = toHex(query);
|
||||
const request = await fetch(
|
||||
`${DATA_SOURCES.tendermintUrl}/tx?hash=${hash}`
|
||||
);
|
||||
|
||||
if (request?.ok) {
|
||||
const body = await request.json();
|
||||
|
||||
if (body?.result?.tx) {
|
||||
return SearchTypes.Transaction;
|
||||
}
|
||||
}
|
||||
} else if (type === SearchTypes.Party) {
|
||||
const party = toNonHex(query);
|
||||
const request = await fetch(
|
||||
`${DATA_SOURCES.tendermintUrl}/tx_search?query="tx.submitter='${party}'"`
|
||||
);
|
||||
|
||||
if (request.ok) {
|
||||
const body = await request.json();
|
||||
|
||||
if (body?.result?.txs?.length) {
|
||||
return SearchTypes.Party;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
export const getSearchType = async (
|
||||
query: string
|
||||
): Promise<SearchTypes | undefined> => {
|
||||
const searchTypes = detectTypeFromQuery(query);
|
||||
const hasResults = searchTypes?.length;
|
||||
|
||||
if (hasResults) {
|
||||
if (hasResults > 1) {
|
||||
const promises = searchTypes.map((type) =>
|
||||
detectTypeByFetching(query, type)
|
||||
);
|
||||
const results = await Promise.all(promises);
|
||||
return results.find((type) => type !== undefined);
|
||||
}
|
||||
|
||||
return searchTypes[0];
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
@@ -2,23 +2,14 @@ import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
||||
import { Search } from './search';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { Routes } from '../../routes/route-names';
|
||||
import { SearchTypes, getSearchType } from './detect-search';
|
||||
|
||||
const mockedNavigate = jest.fn();
|
||||
const mockGetSearchType = getSearchType as jest.MockedFunction<
|
||||
typeof getSearchType
|
||||
>;
|
||||
|
||||
jest.mock('react-router-dom', () => ({
|
||||
...jest.requireActual('react-router-dom'),
|
||||
useNavigate: () => mockedNavigate,
|
||||
}));
|
||||
|
||||
jest.mock('./detect-search', () => ({
|
||||
...jest.requireActual('./detect-search'),
|
||||
getSearchType: jest.fn(),
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
mockedNavigate.mockClear();
|
||||
});
|
||||
@@ -48,10 +39,9 @@ describe('Search', () => {
|
||||
fireEvent.click(button);
|
||||
|
||||
expect(await screen.findByTestId('search-error')).toHaveTextContent(
|
||||
'Transaction type is not recognised'
|
||||
"Something doesn't look right"
|
||||
);
|
||||
});
|
||||
|
||||
it('should render error if no input is given', async () => {
|
||||
render(renderComponent());
|
||||
const { button } = getInputs();
|
||||
@@ -59,14 +49,47 @@ describe('Search', () => {
|
||||
fireEvent.click(button);
|
||||
|
||||
expect(await screen.findByTestId('search-error')).toHaveTextContent(
|
||||
'Search query required'
|
||||
'Search required'
|
||||
);
|
||||
});
|
||||
|
||||
it('should render error if transaction is not hex', async () => {
|
||||
render(renderComponent());
|
||||
const { button, input } = getInputs();
|
||||
fireEvent.change(input, {
|
||||
target: {
|
||||
value:
|
||||
'0x123456789012345678901234567890123456789012345678901234567890123Q',
|
||||
},
|
||||
});
|
||||
|
||||
fireEvent.click(button);
|
||||
|
||||
expect(await screen.findByTestId('search-error')).toHaveTextContent(
|
||||
'Transaction is not hexadecimal'
|
||||
);
|
||||
});
|
||||
|
||||
it('should render error if transaction is not hex and does not have leading 0x', async () => {
|
||||
render(renderComponent());
|
||||
const { button, input } = getInputs();
|
||||
fireEvent.change(input, {
|
||||
target: {
|
||||
value:
|
||||
'123456789012345678901234567890123456789012345678901234567890123Q',
|
||||
},
|
||||
});
|
||||
|
||||
fireEvent.click(button);
|
||||
|
||||
expect(await screen.findByTestId('search-error')).toHaveTextContent(
|
||||
'Transaction is not hexadecimal'
|
||||
);
|
||||
});
|
||||
|
||||
it('should redirect to transactions page', async () => {
|
||||
render(renderComponent());
|
||||
const { button, input } = getInputs();
|
||||
mockGetSearchType.mockResolvedValue(SearchTypes.Transaction);
|
||||
fireEvent.change(input, {
|
||||
target: {
|
||||
value:
|
||||
@@ -85,7 +108,6 @@ describe('Search', () => {
|
||||
it('should redirect to transactions page without proceeding 0x', async () => {
|
||||
render(renderComponent());
|
||||
const { button, input } = getInputs();
|
||||
mockGetSearchType.mockResolvedValue(SearchTypes.Transaction);
|
||||
fireEvent.change(input, {
|
||||
target: {
|
||||
value:
|
||||
@@ -101,48 +123,9 @@ describe('Search', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should redirect to parties page', async () => {
|
||||
render(renderComponent());
|
||||
const { button, input } = getInputs();
|
||||
mockGetSearchType.mockResolvedValue(SearchTypes.Party);
|
||||
fireEvent.change(input, {
|
||||
target: {
|
||||
value:
|
||||
'0x1234567890123456789012345678901234567890123456789012345678901234',
|
||||
},
|
||||
});
|
||||
|
||||
fireEvent.click(button);
|
||||
await waitFor(() => {
|
||||
expect(mockedNavigate).toBeCalledWith(
|
||||
`${Routes.PARTIES}/0x1234567890123456789012345678901234567890123456789012345678901234`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('should redirect to parties page without proceeding 0x', async () => {
|
||||
render(renderComponent());
|
||||
const { button, input } = getInputs();
|
||||
mockGetSearchType.mockResolvedValue(SearchTypes.Party);
|
||||
fireEvent.change(input, {
|
||||
target: {
|
||||
value:
|
||||
'1234567890123456789012345678901234567890123456789012345678901234',
|
||||
},
|
||||
});
|
||||
|
||||
fireEvent.click(button);
|
||||
await waitFor(() => {
|
||||
expect(mockedNavigate).toBeCalledWith(
|
||||
`${Routes.PARTIES}/0x1234567890123456789012345678901234567890123456789012345678901234`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('should redirect to blocks page if passed a number', async () => {
|
||||
render(renderComponent());
|
||||
const { button, input } = getInputs();
|
||||
mockGetSearchType.mockResolvedValue(SearchTypes.Block);
|
||||
fireEvent.change(input, {
|
||||
target: {
|
||||
value: '123',
|
||||
|
||||
@@ -1,57 +1,55 @@
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { Button, Input, InputError } from '@vegaprotocol/ui-toolkit';
|
||||
import { Input, InputError, Button } from '@vegaprotocol/ui-toolkit';
|
||||
import React from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { getSearchType, SearchTypes, toHex } from './detect-search';
|
||||
import { Routes } from '../../routes/route-names';
|
||||
|
||||
const TX_LENGTH = 64;
|
||||
|
||||
interface FormFields {
|
||||
search: string;
|
||||
}
|
||||
|
||||
const isPrependedTransaction = (search: string) =>
|
||||
search.startsWith('0x') && search.length === 2 + TX_LENGTH;
|
||||
|
||||
const isTransaction = (search: string) =>
|
||||
!search.startsWith('0x') && search.length === TX_LENGTH;
|
||||
|
||||
const isBlock = (search: string) => !Number.isNaN(Number(search));
|
||||
|
||||
export const Search = () => {
|
||||
const { register, handleSubmit } = useForm<FormFields>();
|
||||
const navigate = useNavigate();
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
|
||||
const onSubmit = useCallback(
|
||||
async (fields: FormFields) => {
|
||||
const [error, setError] = React.useState<Error | null>(null);
|
||||
const onSubmit = React.useCallback(
|
||||
(fields: FormFields) => {
|
||||
setError(null);
|
||||
|
||||
const query = fields.search;
|
||||
|
||||
if (!query) {
|
||||
setError(new Error(t('Search query required')));
|
||||
} else {
|
||||
const result = await getSearchType(query);
|
||||
const urlAsHex = toHex(query);
|
||||
const unrecognisedError = new Error(
|
||||
t('Transaction type is not recognised')
|
||||
);
|
||||
|
||||
if (result) {
|
||||
switch (result) {
|
||||
case SearchTypes.Party:
|
||||
navigate(`${Routes.PARTIES}/${urlAsHex}`);
|
||||
break;
|
||||
case SearchTypes.Transaction:
|
||||
navigate(`${Routes.TX}/${urlAsHex}`);
|
||||
break;
|
||||
case SearchTypes.Block:
|
||||
navigate(`${Routes.BLOCKS}/${Number(query)}`);
|
||||
break;
|
||||
default:
|
||||
setError(unrecognisedError);
|
||||
}
|
||||
const search = fields.search;
|
||||
if (!search) {
|
||||
setError(new Error(t('Search required')));
|
||||
} else if (isPrependedTransaction(search)) {
|
||||
if (Number.isNaN(Number(search))) {
|
||||
setError(new Error(t('Transaction is not hexadecimal')));
|
||||
} else {
|
||||
navigate(`${Routes.TX}/${search}`);
|
||||
}
|
||||
|
||||
setError(unrecognisedError);
|
||||
} else if (isTransaction(search)) {
|
||||
if (Number.isNaN(Number(`0x${search}`))) {
|
||||
setError(new Error(t('Transaction is not hexadecimal')));
|
||||
} else {
|
||||
navigate(`${Routes.TX}/0x${search}`);
|
||||
}
|
||||
} else if (isBlock(search)) {
|
||||
navigate(`${Routes.BLOCKS}/${Number(search)}`);
|
||||
} else {
|
||||
setError(new Error(t("Something doesn't look right")));
|
||||
}
|
||||
},
|
||||
[navigate]
|
||||
);
|
||||
|
||||
return (
|
||||
<form
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
@@ -68,7 +66,7 @@ export const Search = () => {
|
||||
className="text-white"
|
||||
hasError={Boolean(error?.message)}
|
||||
type="text"
|
||||
placeholder={t('Enter block number, party id or transaction hash')}
|
||||
placeholder={t('Enter block number or transaction hash')}
|
||||
/>
|
||||
{error?.message && (
|
||||
<div className="absolute top-[100%] flex-1 w-full">
|
||||
|
||||
@@ -150,9 +150,7 @@ const Party = () => {
|
||||
<SubHeading>{t('Staking')}</SubHeading>
|
||||
{staking}
|
||||
<SubHeading>{t('JSON')}</SubHeading>
|
||||
<section data-testid="parties-json">
|
||||
<SyntaxHighlighter data={data} />
|
||||
</section>
|
||||
<SyntaxHighlighter data={data} />
|
||||
</>
|
||||
) : null}
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@ NX_DEPLOY_PRIME_URL=$DEPLOY_PRIME_URL
|
||||
NX_VEGA_CONFIG_URL="https://static.vega.xyz/assets/testnet-network.json"
|
||||
NX_VEGA_ENV = 'TESTNET'
|
||||
NX_VEGA_URL="https://api.n11.testnet.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
|
||||
NX_VEGA_WALLET_URL=http://localhost:1789/api/v1
|
||||
NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://ropsten.etherscan.io
|
||||
NX_VEGA_NETWORKS={"MAINNET":"https://alpha.console.vega.xyz"}
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
||||
|
||||
@@ -3,6 +3,6 @@ NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/devnet-network.json
|
||||
NX_VEGA_URL=https://api.n04.d.vega.xyz/graphql
|
||||
NX_VEGA_ENV=DEVNET
|
||||
NX_VEGA_NETWORKS={\"MAINNET\":\"https://alpha.console.vega.xyz\"}
|
||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://ropsten.etherscan.io
|
||||
NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
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_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://ropsten.etherscan.io
|
||||
NX_VEGA_EXPLORER_URL=https://staging2.explorer.vega.xyz
|
||||
|
||||
@@ -3,6 +3,6 @@ NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json
|
||||
NX_VEGA_URL=https://api.n11.testnet.vega.xyz/graphql
|
||||
NX_VEGA_ENV=TESTNET
|
||||
NX_VEGA_NETWORKS='{\"MAINNET\":\"https://alpha.console.vega.xyz\"}'
|
||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://ropsten.etherscan.io
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
||||
|
||||
@@ -50,8 +50,7 @@
|
||||
"executor": "./tools/executors/webpack:serve",
|
||||
"options": {
|
||||
"buildTarget": "liquidity-provision-dashboard:build",
|
||||
"hmr": true,
|
||||
"port": 4201
|
||||
"hmr": true
|
||||
},
|
||||
"configurations": {
|
||||
"development": {
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
"@nrwl/react/babel",
|
||||
{
|
||||
"runtime": "automatic"
|
||||
}
|
||||
]
|
||||
],
|
||||
"plugins": []
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
# This file is used by:
|
||||
# 1. autoprefixer to adjust CSS to support the below specified browsers
|
||||
# 2. babel preset-env to adjust included polyfills
|
||||
#
|
||||
# For additional information regarding the format and rule options, please see:
|
||||
# https://github.com/browserslist/browserslist#queries
|
||||
#
|
||||
# If you need to support different browsers in production, you may tweak the list below.
|
||||
|
||||
last 1 Chrome version
|
||||
last 1 Firefox version
|
||||
last 2 Edge major versions
|
||||
last 2 Safari major version
|
||||
last 2 iOS major versions
|
||||
Firefox ESR
|
||||
not IE 9-11 # For IE 9-11 support, remove 'not'.
|
||||
@@ -1,4 +0,0 @@
|
||||
NX_VEGA_URL=https://api.n01.stagnet3.vega.xyz/graphql
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
|
||||
NX_VEGA_NETWORKS='{"TESTNET":"https://multisig-signer.fairground.wtf","MAINNET":"https://multisig-signer.vega.xyz"}'
|
||||
NX_VEGA_ENV=STAGNET3
|
||||
@@ -1,5 +0,0 @@
|
||||
# App configuration variables
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/devnet-network.json
|
||||
NX_VEGA_URL=https://api.n04.d.vega.xyz/graphql
|
||||
NX_VEGA_NETWORKS='{"TESTNET":"https://multisig-signer.fairground.wtf","MAINNET":"https://multisig-signer.vega.xyz"}'
|
||||
NX_VEGA_ENV=DEVNET
|
||||
@@ -1,5 +0,0 @@
|
||||
# App configuration variables
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/mainnet-network.json
|
||||
NX_VEGA_URL=https://api.vega.xyz/query
|
||||
NX_VEGA_NETWORKS='{"TESTNET":"https://multisig-signer.fairground.wtf","MAINNET":"https://multisig-signer.vega.xyz"}'
|
||||
NX_VEGA_ENV=MAINNET
|
||||
@@ -1,5 +0,0 @@
|
||||
# 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_NETWORKS='{"TESTNET":"https://multisig-signer.fairground.wtf","MAINNET":"https://multisig-signer.vega.xyz"}'
|
||||
NX_VEGA_ENV=STAGNET3
|
||||
@@ -1,5 +0,0 @@
|
||||
# App configuration variables
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json
|
||||
NX_VEGA_URL=https://api.n09.testnet.vega.xyz/graphql
|
||||
NX_VEGA_NETWORKS='{"TESTNET":"https://multisig-signer.fairground.wtf","MAINNET":"https://multisig-signer.vega.xyz"}'
|
||||
NX_VEGA_ENV=TESTNET
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"extends": ["plugin:@nrwl/nx/react", "../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*", "__generated__", "__generated___"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
## Multisig-signer
|
||||
|
||||
## Development
|
||||
|
||||
First copy the configuration of the application you are starting:
|
||||
|
||||
```bash
|
||||
cp .env.[environment] .env.local
|
||||
```
|
||||
|
||||
Starting the app:
|
||||
|
||||
```bash
|
||||
yarn nx serve multisig-signer
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
Example configurations are provided here:
|
||||
|
||||
- [Mainnet](./.env.mainnet)
|
||||
- [Devnet](./.env.devnet)
|
||||
- [Capsule](./.env.capsule)
|
||||
- [Testnet](./.env.testnet)
|
||||
- [Stagnet3](./.env.stagnet3)
|
||||
|
||||
For convenience, you can boot the app injecting one of the configurations above by running:
|
||||
|
||||
```bash
|
||||
yarn nx run multisig-signer:serve --env={env} # e.g. stagnet3
|
||||
```
|
||||
|
||||
There are a few different configuration options offered for this app:
|
||||
|
||||
| **Flag** | **Purpose** |
|
||||
| -------------------------------- | ---------------------------------------------------------------------------------------------------- | --- | |
|
||||
| `NX_VEGA_URL` | The GraphQl query endpoint of a [Vega data node](https://github.com/vegaprotocol/networks#data-node) |
|
||||
| `NX_VEGA_ENV` | The name of the currently connected vega environment |
|
||||
|
||||
## Testing
|
||||
|
||||
To run the minimal set of unit tests, run the following:
|
||||
|
||||
```bash
|
||||
yarn nx test multisig-signer
|
||||
```
|
||||
Vendored
-5
@@ -1,5 +0,0 @@
|
||||
/// <reference types="react-scripts" />
|
||||
|
||||
interface Window {
|
||||
_env_?: Record<string, string>;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
/* eslint-disable */
|
||||
export default {
|
||||
displayName: 'multisig-signer',
|
||||
preset: '../../jest.preset.js',
|
||||
transform: {
|
||||
'^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': '@nrwl/react/plugins/jest',
|
||||
'^.+\\.[tj]sx?$': 'babel-jest',
|
||||
},
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
||||
coverageDirectory: '../../coverage/apps/multisig-signer',
|
||||
setupFilesAfterEnv: ['./src/app/setup-tests.ts'],
|
||||
};
|
||||
@@ -1,4 +0,0 @@
|
||||
[[redirects]]
|
||||
from = "/*"
|
||||
to = "/index.html"
|
||||
status = 200
|
||||
@@ -1,10 +0,0 @@
|
||||
const { join } = require('path');
|
||||
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {
|
||||
config: join(__dirname, 'tailwind.config.js'),
|
||||
},
|
||||
autoprefixer: {},
|
||||
},
|
||||
};
|
||||
@@ -1,80 +0,0 @@
|
||||
{
|
||||
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||
"sourceRoot": "apps/multisig-signer/src",
|
||||
"projectType": "application",
|
||||
"targets": {
|
||||
"build": {
|
||||
"executor": "./tools/executors/webpack:build",
|
||||
"outputs": ["{options.outputPath}"],
|
||||
"defaultConfiguration": "production",
|
||||
"options": {
|
||||
"compiler": "babel",
|
||||
"outputPath": "dist/apps/multisig-signer",
|
||||
"index": "apps/multisig-signer/src/index.html",
|
||||
"baseHref": "/",
|
||||
"main": "apps/multisig-signer/src/main.tsx",
|
||||
"polyfills": "apps/multisig-signer/src/polyfills.ts",
|
||||
"tsConfig": "apps/multisig-signer/tsconfig.app.json",
|
||||
"assets": ["apps/multisig-signer/src/assets"],
|
||||
"styles": ["apps/multisig-signer/src/styles.css"],
|
||||
"scripts": [],
|
||||
"webpackConfig": "apps/multisig-signer/webpack.config.js"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "apps/multisig-signer/src/environments/environment.ts",
|
||||
"with": "apps/multisig-signer/src/environments/environment.prod.ts"
|
||||
}
|
||||
],
|
||||
"optimization": true,
|
||||
"outputHashing": "all",
|
||||
"sourceMap": true,
|
||||
"namedChunks": false,
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"executor": "./tools/executors/webpack:serve",
|
||||
"options": {
|
||||
"port": 3000,
|
||||
"buildTarget": "multisig-signer:build:development",
|
||||
"hmr": true
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"buildTarget": "multisig-signer:build:production",
|
||||
"hmr": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nrwl/linter:eslint",
|
||||
"outputs": ["{options.outputFile}"],
|
||||
"options": {
|
||||
"lintFilePatterns": ["apps/multisig-signer/**/*.{ts,tsx,js,jsx}"]
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"executor": "@nrwl/jest:jest",
|
||||
"outputs": ["coverage/apps/multisig-signer"],
|
||||
"options": {
|
||||
"jestConfig": "apps/multisig-signer/jest.config.ts",
|
||||
"passWithNoTests": true
|
||||
}
|
||||
},
|
||||
"build-netlify": {
|
||||
"executor": "@nrwl/workspace:run-commands",
|
||||
"options": {
|
||||
"commands": [
|
||||
"cp apps/multisig-signer/netlify.toml netlify.toml",
|
||||
"nx build multisig-signer"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": []
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
import * as Sentry from '@sentry/react';
|
||||
import classnames from 'classnames';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { BrowserTracing } from '@sentry/tracing';
|
||||
import {
|
||||
EnvironmentProvider,
|
||||
NetworkLoader,
|
||||
useEnvironment,
|
||||
} from '@vegaprotocol/environment';
|
||||
import { AsyncRenderer, Button, Lozenge } from '@vegaprotocol/ui-toolkit';
|
||||
import type { EthereumConfig } from '@vegaprotocol/web3';
|
||||
import { useEthereumConfig, Web3Provider } from '@vegaprotocol/web3';
|
||||
import { ThemeContext, useThemeSwitcher, t } from '@vegaprotocol/react-helpers';
|
||||
import { createClient } from './lib/apollo-client';
|
||||
import { ENV } from './config/env';
|
||||
import { ContractsProvider } from './config/contracts/contracts-provider';
|
||||
import {
|
||||
AddSignerForm,
|
||||
RemoveSignerForm,
|
||||
Header,
|
||||
ContractDetails,
|
||||
} from './components';
|
||||
import { createConnectors } from './lib/web3-connectors';
|
||||
import { Web3Connector } from './components/web3-connector';
|
||||
import { EthWalletContainer } from './components/eth-wallet-container';
|
||||
import { useWeb3React } from '@web3-react/core';
|
||||
|
||||
const pageWrapperClasses = classnames(
|
||||
'min-h-screen w-screen',
|
||||
'grid grid-rows-[auto,1fr]',
|
||||
'bg-white dark:bg-black',
|
||||
'text-neutral-900 dark:text-neutral-100'
|
||||
);
|
||||
|
||||
const ConnectedApp = ({ config }: { config: EthereumConfig | null }) => {
|
||||
const { account, connector } = useWeb3React();
|
||||
return (
|
||||
<main className="w-full max-w-3xl px-5 justify-self-center">
|
||||
<h1>{t('Multisig signer')}</h1>
|
||||
<div className="mb-8">
|
||||
<p>
|
||||
Connected to Eth wallet: <Lozenge>{account}</Lozenge>
|
||||
</p>
|
||||
<Button onClick={() => connector.deactivate()}>Disconnect</Button>
|
||||
</div>
|
||||
<ContractDetails config={config} />
|
||||
<h2>{t('Add or remove signer')}</h2>
|
||||
<AddSignerForm />
|
||||
<RemoveSignerForm />
|
||||
</main>
|
||||
);
|
||||
};
|
||||
|
||||
function App() {
|
||||
const { VEGA_ENV, ETHEREUM_PROVIDER_URL } = useEnvironment();
|
||||
const { config, loading, error } = useEthereumConfig();
|
||||
const [dialogOpen, setDialogOpen] = useState(false);
|
||||
const [theme, toggleTheme] = useThemeSwitcher();
|
||||
|
||||
useEffect(() => {
|
||||
Sentry.init({
|
||||
dsn: ENV.dsn,
|
||||
integrations: [new BrowserTracing()],
|
||||
tracesSampleRate: 1,
|
||||
environment: VEGA_ENV,
|
||||
});
|
||||
}, [VEGA_ENV]);
|
||||
const Connectors = useMemo(() => {
|
||||
if (config?.chain_id) {
|
||||
return createConnectors(ETHEREUM_PROVIDER_URL, Number(config.chain_id));
|
||||
}
|
||||
return [];
|
||||
}, [config?.chain_id, ETHEREUM_PROVIDER_URL]);
|
||||
|
||||
return (
|
||||
<ThemeContext.Provider value={theme}>
|
||||
<Web3Provider connectors={Connectors}>
|
||||
<Web3Connector dialogOpen={dialogOpen} setDialogOpen={setDialogOpen}>
|
||||
<div className={pageWrapperClasses}>
|
||||
<AsyncRenderer loading={loading} data={config} error={error}>
|
||||
<Header theme={theme} toggleTheme={toggleTheme} />
|
||||
<EthWalletContainer
|
||||
dialogOpen={dialogOpen}
|
||||
setDialogOpen={setDialogOpen}
|
||||
>
|
||||
<ConnectedApp config={config} />
|
||||
</EthWalletContainer>
|
||||
</AsyncRenderer>
|
||||
</div>
|
||||
</Web3Connector>
|
||||
</Web3Provider>
|
||||
</ThemeContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
const Wrapper = () => {
|
||||
return (
|
||||
<EnvironmentProvider>
|
||||
<NetworkLoader createClient={createClient}>
|
||||
<ContractsProvider>
|
||||
<App />
|
||||
</ContractsProvider>
|
||||
</NetworkLoader>
|
||||
</EnvironmentProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default Wrapper;
|
||||
@@ -1,45 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @generated
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
// ====================================================
|
||||
// GraphQL query operation: AddSignerBundle
|
||||
// ====================================================
|
||||
|
||||
export interface AddSignerBundle_erc20MultiSigSignerAddedBundles_edges_node {
|
||||
__typename: "ERC20MultiSigSignerAddedBundle";
|
||||
/**
|
||||
* The ethereum address of the signer to be added
|
||||
*/
|
||||
newSigner: string;
|
||||
/**
|
||||
* The nonce used in the signing operation
|
||||
*/
|
||||
nonce: string;
|
||||
/**
|
||||
* The bundle of signatures from current validators to sign in the new signer
|
||||
*/
|
||||
signatures: string;
|
||||
}
|
||||
|
||||
export interface AddSignerBundle_erc20MultiSigSignerAddedBundles_edges {
|
||||
__typename: "ERC20MultiSigSignerAddedBundleEdge";
|
||||
node: AddSignerBundle_erc20MultiSigSignerAddedBundles_edges_node;
|
||||
}
|
||||
|
||||
export interface AddSignerBundle_erc20MultiSigSignerAddedBundles {
|
||||
__typename: "ERC20MultiSigSignerAddedConnection";
|
||||
edges: (AddSignerBundle_erc20MultiSigSignerAddedBundles_edges | null)[] | null;
|
||||
}
|
||||
|
||||
export interface AddSignerBundle {
|
||||
/**
|
||||
* Get the signature bundle to add a particular validator to the signer list of the multisig contract
|
||||
*/
|
||||
erc20MultiSigSignerAddedBundles: AddSignerBundle_erc20MultiSigSignerAddedBundles;
|
||||
}
|
||||
|
||||
export interface AddSignerBundleVariables {
|
||||
nodeId: string;
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @generated
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
// ====================================================
|
||||
// GraphQL query operation: RemoveSignerBundle
|
||||
// ====================================================
|
||||
|
||||
export interface RemoveSignerBundle_erc20MultiSigSignerRemovedBundles_edges_node {
|
||||
__typename: "ERC20MultiSigSignerRemovedBundle";
|
||||
/**
|
||||
* The ethereum address of the signer to be removed
|
||||
*/
|
||||
oldSigner: string;
|
||||
/**
|
||||
* The nonce used in the signing operation
|
||||
*/
|
||||
nonce: string;
|
||||
/**
|
||||
* The bundle of signatures from current validators to sign in the new signer
|
||||
*/
|
||||
signatures: string;
|
||||
}
|
||||
|
||||
export interface RemoveSignerBundle_erc20MultiSigSignerRemovedBundles_edges {
|
||||
__typename: "ERC20MultiSigSignerRemovedBundleEdge";
|
||||
node: RemoveSignerBundle_erc20MultiSigSignerRemovedBundles_edges_node;
|
||||
}
|
||||
|
||||
export interface RemoveSignerBundle_erc20MultiSigSignerRemovedBundles {
|
||||
__typename: "ERC20MultiSigSignerRemovedConnection";
|
||||
/**
|
||||
* The list of signer bundles for that validator
|
||||
*/
|
||||
edges: (RemoveSignerBundle_erc20MultiSigSignerRemovedBundles_edges | null)[] | null;
|
||||
}
|
||||
|
||||
export interface RemoveSignerBundle {
|
||||
/**
|
||||
* Get the signatures bundle to remove a particular validator from signer list of the multisig contract
|
||||
*/
|
||||
erc20MultiSigSignerRemovedBundles: RemoveSignerBundle_erc20MultiSigSignerRemovedBundles;
|
||||
}
|
||||
|
||||
export interface RemoveSignerBundleVariables {
|
||||
nodeId: string;
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
import { useState } from 'react';
|
||||
import { gql, useLazyQuery } from '@apollo/client';
|
||||
import { captureException } from '@sentry/react';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { useEthereumTransaction } from '@vegaprotocol/web3';
|
||||
import {
|
||||
FormGroup,
|
||||
Input,
|
||||
Button,
|
||||
InputError,
|
||||
Loader,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { prepend0x } from '@vegaprotocol/smart-contracts';
|
||||
import { useContracts } from '../../config/contracts/contracts-context';
|
||||
import type { FormEvent } from 'react';
|
||||
import type {
|
||||
AddSignerBundle,
|
||||
AddSignerBundleVariables,
|
||||
} from '../__generated__/AddSignerBundle';
|
||||
import type { MultisigControl } from '@vegaprotocol/smart-contracts';
|
||||
|
||||
export const ADD_SIGNER_QUERY = gql`
|
||||
query AddSignerBundle($nodeId: ID!) {
|
||||
erc20MultiSigSignerAddedBundles(nodeId: $nodeId) {
|
||||
edges {
|
||||
node {
|
||||
newSigner
|
||||
nonce
|
||||
signatures
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const AddSignerForm = () => {
|
||||
const { multisig } = useContracts();
|
||||
const [address, setAddress] = useState('');
|
||||
const [bundleNotFound, setBundleNotFound] = useState(false);
|
||||
const [runQuery, { data, error, loading }] = useLazyQuery<
|
||||
AddSignerBundle,
|
||||
AddSignerBundleVariables
|
||||
>(ADD_SIGNER_QUERY);
|
||||
const { perform, Dialog } = useEthereumTransaction<
|
||||
MultisigControl,
|
||||
'add_signer'
|
||||
>(multisig, 'add_signer');
|
||||
const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
setBundleNotFound(false);
|
||||
try {
|
||||
if (address === '') {
|
||||
return;
|
||||
}
|
||||
await runQuery({
|
||||
variables: { nodeId: address },
|
||||
});
|
||||
const bundle = data?.erc20MultiSigSignerAddedBundles?.edges?.[0]?.node;
|
||||
|
||||
if (!bundle) {
|
||||
if (!error) {
|
||||
setBundleNotFound(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
await perform(
|
||||
bundle.newSigner,
|
||||
bundle.nonce.startsWith('0x') ? bundle.nonce : prepend0x(bundle.nonce),
|
||||
bundle.signatures.startsWith('0x')
|
||||
? bundle.signatures
|
||||
: prepend0x(bundle.signatures)
|
||||
);
|
||||
} catch (err: unknown) {
|
||||
captureException(err);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={(e) => handleSubmit(e)}>
|
||||
<FormGroup
|
||||
label={t('Add signer')}
|
||||
labelFor="add-signer-input"
|
||||
labelDescription={t('Public key of the signer to add')}
|
||||
className="max-w-xl"
|
||||
>
|
||||
<div className="grid grid-cols-[1fr,auto] gap-2">
|
||||
<Input
|
||||
id="add-signer-input"
|
||||
onChange={(e) => setAddress(e.target.value)}
|
||||
data-testid="add-signer-input-input"
|
||||
/>
|
||||
<Button
|
||||
type="submit"
|
||||
data-testid="add-signer-submit"
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? <Loader size="small" /> : t('Add')}
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
{error && (
|
||||
<InputError intent="danger">
|
||||
{error?.message.includes('InvalidArgument')
|
||||
? t('Invalid node id')
|
||||
: error?.message}
|
||||
</InputError>
|
||||
)}
|
||||
{bundleNotFound && !error && (
|
||||
<InputError intent="danger">
|
||||
{t(
|
||||
'Bundle was not found, are you sure this validator needs to be added?'
|
||||
)}
|
||||
</InputError>
|
||||
)}
|
||||
</div>
|
||||
</FormGroup>
|
||||
<Dialog />
|
||||
</form>
|
||||
);
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
export * from './add-signer-form';
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user