Compare commits

..
862 changed files with 11967 additions and 66377 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ env:
jobs:
add_issue:
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- name: 'Add issue to project board'
run: |
-16
View File
@@ -1,16 +0,0 @@
name: 'Check if branch is shorter than 52 chars'
on: pull_request
jobs:
branch-naming-rules:
runs-on: ubuntu-latest
steps:
# echo "branches that are longer than 51 chars can't be parsed by kubernetes to create previews. Each app has prefix of it's name like: 'governance-' (12 chars), what leaves 51 max branch length"
# current parsable length: $( git rev-parse --abbrev-ref HEAD | sed -r s/[^a-zA-Z0-9]+/-/g | sed -r s/^-+\|-+$//g | wc -c)
- uses: deepakputhraya/action-branch-name@master
with:
# regex: '([a-z])+\/([a-z])+' # Regex the branch should match. This example enforces grouping
# allowed_prefixes: 'feature,stable,fix' # All branches should start with the given prefix
# ignore: master,develop # Ignore exactly matching branch names from convention
min_length: 1 # Min length of the branch name
max_length: 51 # Max length of the branch name
-211
View File
@@ -1,211 +0,0 @@
name: CI/CD
on:
push:
branches:
- release/*
- develop
tags:
- v*
pull_request:
types:
- opened
- ready_for_review
- reopened
- edited
- synchronize
jobs:
node-modules:
runs-on: ubuntu-22.04
name: 'Cache yarn modules'
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Cache node modules
id: cache
uses: actions/cache@v3
with:
path: node_modules
key: ${{ runner.os }}-cache-node-modules-${{ hashFiles('yarn.lock') }}
# comment out "restore-keys" if you need to rebuild yarn from 0
restore-keys: |
${{ runner.os }}-cache-node-modules-
- name: Setup node
uses: actions/setup-node@v3
if: steps.cache.outputs.cache-hit != 'true'
with:
node-version-file: '.nvmrc'
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
cache: yarn
- name: yarn install
if: steps.cache.outputs.cache-hit != 'true'
run: yarn install --pure-lockfile
lint-pr-title:
needs: node-modules
if: ${{ github.event_name == 'pull_request' }}
name: Verify PR title
uses: ./.github/workflows/lint-pr.yml
secrets: inherit
lint-test-build:
timeout-minutes: 60
needs: node-modules
runs-on: ubuntu-22.04
name: '(CI) lint + unit test + build'
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup node
uses: actions/setup-node@v3
with:
node-version-file: '.nvmrc'
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
cache: yarn
- name: Cache node modules
uses: actions/cache@v3
with:
path: node_modules
key: ${{ runner.os }}-cache-node-modules-${{ hashFiles('yarn.lock') }}
- name: Derive appropriate SHAs for base and head for `nx affected` commands
uses: nrwl/nx-set-shas@v3
with:
main-branch-name: develop
- name: Check formatting
run: yarn nx format:check
- name: Lint affected
run: yarn nx affected:lint --max-warnings=0
- name: Build affected spec
run: yarn nx affected --target=build-spec
- name: Test affected
run: yarn nx affected:test
- name: Build affected
run: yarn nx affected:build || (yarn install && yarn nx affected:build)
# See affected apps
- name: See affected apps
run: |
echo ">>>> debug"
echo "NX_BASE: ${{ env.NX_BASE }}"
echo "NX_HEAD: ${{ env.NX_HEAD }}"
echo ">>>> eof debug"
affected="$(yarn nx print-affected --base=${{ env.NX_BASE }} --head=${{ env.NX_HEAD }} --select=projects)"
branch_slug="$(echo '${{ github.head_ref || github.ref_name }}' | sed -r s/[^a-zA-Z0-9]+/-/g | sed -r s/^-+\|-+$//g | cut -c 1-50 )"
projects_e2e=""
preview_governance="not deployed"
preview_trading="not deployed"
preview_explorer="not deployed"
if [[ -z "$projects_e2e" ]]; then
projects_e2e+='"governance-e2e" "trading-e2e" "explorer-e2e" '
preview_governance=$(printf "https://%s.%s.vega.rocks" "governance" "$branch_slug")
preview_trading=$(printf "https://%s.%s.vega.rocks" "trading" "$branch_slug")
preview_explorer=$(printf "https://%s.%s.vega.rocks" "explorer" "$branch_slug")
else
if [[ $affected == *"governance"* ]]; then
projects_e2e+='"governance-e2e" '
preview_governance=$(printf "https://%s.%s.vega.rocks" "governance" "$branch_slug")
fi
if [[ $affected == *"trading"* ]]; then
projects_e2e+='"trading-e2e" '
preview_trading=$(printf "https://%s.%s.vega.rocks" "trading" "$branch_slug")
fi
if [[ $affected == *"explorer"* ]]; then
projects_e2e+='"explorer-e2e" '
preview_explorer=$(printf "https://%s.%s.vega.rocks" "explorer" "$branch_slug")
fi
fi
projects_e2e=${projects_e2e%?}
projects_e2e=[${projects_e2e// /,}]
echo PROJECTS_E2E=$projects_e2e >> $GITHUB_ENV
echo PROJECTS=$(echo $projects_e2e | sed 's|-e2e||g') >> $GITHUB_ENV
echo PREVIEW_GOVERNANCE=$preview_governance >> $GITHUB_ENV
echo PREVIEW_TRADING=$preview_trading >> $GITHUB_ENV
echo PREVIEW_EXPLORER=$preview_explorer >> $GITHUB_ENV
outputs:
projects: ${{ env.PROJECTS }}
projects-e2e: ${{ env.PROJECTS_E2E }}
preview_governance: ${{ env.PREVIEW_GOVERNANCE }}
preview_trading: ${{ env.PREVIEW_TRADING }}
preview_explorer: ${{ env.PREVIEW_EXPLORER }}
cypress:
needs: lint-test-build
name: '(CI) cypress'
if: ${{ needs.lint-test-build.outputs.projects != '[]' }}
uses: ./.github/workflows/cypress-run.yml
secrets: inherit
with:
projects: ${{ needs.lint-test-build.outputs.projects-e2e }}
tags: '@smoke @regression'
publish-dist:
needs: lint-test-build
name: '(CD) publish dist'
if: ${{ needs.lint-test-build.outputs.projects != '[]' }}
uses: ./.github/workflows/publish-dist.yml
secrets: inherit
with:
projects: ${{ needs.lint-test-build.outputs.projects }}
dist-check:
runs-on: ubuntu-latest
needs:
- publish-dist
- lint-test-build
if: ${{ github.event_name == 'pull_request' }}
name: '(CD) comment preview links'
steps:
- name: Find Comment
uses: peter-evans/find-comment@v2
id: fc
with:
issue-number: ${{ github.event.pull_request.number }}
body-includes: Previews
- name: Create comment
uses: peter-evans/create-or-update-comment@v3
if: ${{ steps.fc.outputs.comment-id == 0 }}
with:
issue-number: ${{ github.event.pull_request.number }}
body: |
Previews:
* governance: ${{ needs.lint-test-build.outputs.preview_governance }}
* explorer: ${{ needs.lint-test-build.outputs.preview_explorer }}
* trading: ${{ needs.lint-test-build.outputs.preview_trading }}
cypress-check:
name: '(CI) cypress - check'
runs-on: ubuntu-latest
needs: cypress
steps:
- run: echo Done!
# Report single result at the end, to avoid mess with required checks in PR
cypress-result:
if: ${{ always() }}
needs: cypress
runs-on: ubuntu-22.04
steps:
- run: |
result="${{ needs.cypress.result }}"
if [[ $result == "success" || $result == "skipped" ]]; then
exit 0
else
exit 1
fi
+1 -1
View File
@@ -13,7 +13,7 @@ on:
jobs:
cypress-run:
name: Run Cypress Trading tests -- live environment
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
+2 -8
View File
@@ -1,4 +1,4 @@
name: (CI) Cypress Run
name: Cypress Run
on:
workflow_call:
inputs:
@@ -20,7 +20,7 @@ jobs:
project: ${{ fromJSON(inputs.projects) }}
name: ${{ matrix.project }}
runs-on: self-hosted-runner
timeout-minutes: 40
timeout-minutes: 30
steps:
# Checks if skip cache was requested
- name: Set skip-nx-cache flag
@@ -93,9 +93,3 @@ jobs:
with:
name: logs-${{ matrix.project }}
path: /home/runner/.vegacapsule/testnet/logs
- uses: actions/upload-artifact@v3
if: ${{ failure() }}
with:
name: test-report-${{ matrix.project }}
path: frontend-monorepo/apps/trading-e2e/cypress/reports
+9 -12
View File
@@ -8,25 +8,22 @@ on:
jobs:
master:
name: Generate Queries
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup node
uses: actions/setup-node@v3
uses: actions/checkout@v2
with:
node-version-file: '.nvmrc'
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
cache: yarn
fetch-depth: 0
- name: Use Node.js 16
id: Node
uses: actions/setup-node@v2
with:
node-version: 16.15.1
- name: Install root dependencies
run: yarn install --frozen-lockfile
run: yarn install
- name: Generate queries
run: node ./scripts/get-queries.js
- uses: actions/upload-artifact@v2
with:
name: queries
-29
View File
@@ -1,29 +0,0 @@
---
name: Verify PR title
on:
workflow_call:
jobs:
lint_pr:
timeout-minutes: 10
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup node
uses: actions/setup-node@v3
with:
node-version-file: '.nvmrc'
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
cache: yarn
- name: Cache node modules
uses: actions/cache@v3
with:
path: node_modules
key: ${{ runner.os }}-cache-node-modules-${{ hashFiles('yarn.lock') }}
- name: Check PR title
run: echo "${{ github.event.pull_request.title }}" | npx commitlint --config ./commitlint.config-ci.js
+23
View File
@@ -0,0 +1,23 @@
---
name: Verify PR title
on:
pull_request:
types: [opened, ready_for_review, reopened, edited, synchronize]
jobs:
lint_pr:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Use Node.js 16
id: Node
uses: actions/setup-node@v2
with:
node-version: 16.15.1
- name: Install root dependencies
run: yarn install
- name: Check PR title
run: echo "${{ github.event.pull_request.title }}" | npx commitlint --config ./commitlint.config-ci.js
+97
View File
@@ -0,0 +1,97 @@
name: PR Validations
on:
push:
branches:
- develop
- main
pull_request:
types:
- opened
- reopened
- synchronize
- ready_for_review
jobs:
pr:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Check node version
id: node-version
run: |
npmVersion=$(cat .nvmrc | head -n 1)
echo ::set-output name=npmVersion::${npmVersion}
- name: Setup node
uses: actions/setup-node@v3
with:
node-version: ${{ steps.node-version.outputs.npmVersion }}
- name: Derive appropriate SHAs for base and head for `nx affected` commands
uses: nrwl/nx-set-shas@v3
with:
main-branch-name: develop
- name: Restore node_modules from cache
uses: actions/cache@v3
with:
path: '**/node_modules'
key: node_modules-${{ hashFiles('**/yarn.lock') }}
- name: Install root dependencies
run: yarn install --frozen-lockfile
- name: See affected apps
run: |
affected="$(yarn nx print-affected --base=${{ env.NX_BASE }} --head=HEAD --select=projects)"
echo -n "Affected projects: $affected"
projects_e2e=""
if [[ $affected == *"governance"* ]]; then projects_e2e+='"governance-e2e" '; fi
if [[ $affected == *"trading"* ]]; then projects_e2e+='"trading-e2e" '; fi
if [[ $affected == *"explorer"* ]]; then projects_e2e+='"explorer-e2e" '; fi
if [[ -z "$projects_e2e" ]]; then projects_e2e+='"governance-e2e" "trading-e2e" "explorer-e2e" '; fi
projects_e2e=${projects_e2e%?}
projects_e2e=[${projects_e2e// /,}]
echo PROJECTS_E2E=$projects_e2e >> $GITHUB_ENV
echo PROJECTS=$(echo $projects_e2e | sed 's|-e2e||g') >> $GITHUB_ENV
outputs:
projects: ${{ env.PROJECTS }}
projects-e2e: ${{ env.PROJECTS_E2E }}
run-cypress:
needs: pr
if: ${{ needs.pr.outputs.projects != '[]' }}
uses: ./.github/workflows/cypress-run.yml
secrets: inherit
with:
projects: ${{ needs.pr.outputs.projects-e2e }}
tags: '@smoke @regression'
run-docker-build:
needs: pr
if: ${{ needs.pr.outputs.projects != '[]' }}
uses: ./.github/workflows/publish-docker-containers.yml
secrets: inherit
with:
projects: ${{ needs.pr.outputs.projects }}
# Report single result at the end, to avoid mess with required checks in PR
result:
if: ${{ always() }}
needs: run-cypress
runs-on: ubuntu-latest
name: Cypress result
steps:
- run: |
result="${{ needs.run-cypress.result }}"
if [[ $result == "success" || $result == "skipped" ]]; then
exit 0
else
exit 1
fi
+1 -1
View File
@@ -7,7 +7,7 @@ on:
jobs:
master:
name: Generate Queries
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- name: Checkout
-176
View File
@@ -1,176 +0,0 @@
name: (CD) Publish docker + s3
on:
workflow_call:
inputs:
projects:
required: true
type: string
jobs:
publish-dist:
strategy:
fail-fast: false
matrix:
app: ${{ fromJSON(inputs.projects) }}
name: ${{ matrix.app }}
runs-on: ubuntu-22.04
timeout-minutes: 25
steps:
- name: Check out code
uses: actions/checkout@v3
- name: Set up QEMU
id: quemu
uses: docker/setup-qemu-action@v2
- name: Available platforms
run: echo ${{ steps.qemu.outputs.platforms }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Log in to the Container registry (ghcr)
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Log in to the Container registry (docker hub)
uses: docker/login-action@v2
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
with:
# registry: registry.hub.docker.com
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Setup node
uses: actions/setup-node@v3
with:
node-version-file: '.nvmrc'
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
cache: yarn
- name: Cache node modules
uses: actions/cache@v3
with:
path: node_modules
key: ${{ runner.os }}-cache-node-modules-${{ hashFiles('yarn.lock') }}
# https://docs.github.com/en/actions/learn-github-actions/contexts
- name: Define variables
run: |
envName=''
if [[ "${{ github.event_name }}" = "push" ]]; then
domain="vega.rocks"
if [[ "${{ github.ref }}" =~ .*release/.* ]]; then
envName="$(echo ${{ github.ref }} | rev | cut -d '/' -f 1 | rev)"
if [[ "${{ github.ref }}" =~ .*mainnet.* ]]; then
domain="vega.community"
fi
elif [[ "${{ github.ref }}" =~ .*develop$ ]]; then
envName="stagnet1"
elif [[ "${{ matrix.app}}" = "trading" ]] && [[ ${{ startsWith(github.ref, 'refs/tags/v') && 'true' || 'false' }} = "true" ]]; then
envName="mainnet"
fi
bucketName="${{ matrix.app }}.${envName}.${domain}"
echo BUCKET_NAME=${bucketName} >> $GITHUB_ENV
fi
echo ENV_NAME=${envName} >> $GITHUB_ENV
- name: Build local dist
run: |
flags=""
if [[ ! -z "${{ env.ENV_NAME }}" ]]; then
if [[ "${{ env.ENV_NAME }}" != "ops-vega" ]]; then
flags="--env=${{ env.ENV_NAME }}"
fi
fi
if [ "${{ matrix.app }}" = "trading" ]; then
yarn nx export trading $flags || (yarn install && yarn nx export trading $flags)
DIST_LOCATION=dist/apps/trading/exported
else
yarn nx build ${{ matrix.app }} $flags || (yarn install && yarn nx build ${{ matrix.app }} $flags)
DIST_LOCATION=dist/apps/${{ matrix.app }}
fi
mv $DIST_LOCATION dist-result
tree dist-result
- name: Build and export to local Docker
id: docker_build
uses: docker/build-push-action@v3
with:
context: .
file: docker/node-outside-docker.Dockerfile
load: true
build-args: |
APP=${{ matrix.app }}
ENV_NAME=${{ env.ENV_NAME }}
tags: |
ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local
- name: Image digest
if: ${{ github.event_name == 'pull_request' }}
run: echo ${{ steps.docker_build.outputs.digest }}
- name: Sanity check docker image
run: |
echo "Check ipfs-hash"
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local cat /ipfs-hash
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local cat /ipfs-hash > ${{ matirx.app }}-ipfs-hash
echo "List html directory"
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local sh -c 'apk add --update tree; tree /usr/share/nginx/html'
- name: Publish dist as docker image (ghcr)
uses: docker/build-push-action@v3
if: ${{ github.event_name == 'pull_request' || (matrix.app == 'trading' && github.event_name == 'push' && !startsWith(github.ref, 'refs/tags/v') ) }}
with:
context: .
file: docker/node-outside-docker.Dockerfile
push: true
build-args: |
APP=${{ matrix.app }}
ENV_NAME=${{ env.ENV_NAME }}
tags: |
ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:${{ github.event.pull_request.head.sha || github.sha }}
- name: Publish dist as docker image (docker hub)
uses: docker/build-push-action@v3
if: ${{ matrix.app == 'trading' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
with:
context: .
file: docker/node-outside-docker.Dockerfile
push: true
build-args: |
APP=${{ matrix.app }}
ENV_NAME=${{ env.ENV_NAME }}
tags: |
vegaprotocol/${{ matrix.app }}:${{ github.ref_name }}
# bucket creation in github.com/vegaprotocol/terraform//frontend
- name: Publish dist to s3
uses: jakejarvis/s3-sync-action@master
if: ${{ github.event_name == 'push' && !startsWith(github.ref, 'refs/tags/v') }}
with:
args: --acl private --follow-symlinks --delete
env:
AWS_S3_BUCKET: ${{ env.BUCKET_NAME }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: 'eu-west-1'
SOURCE_DIR: 'dist-result'
- name: Add preview label
uses: actions-ecosystem/action-add-labels@v1
if: ${{ github.event_name == 'pull_request' }}
with:
labels: ${{ matrix.app }}-preview
number: ${{ github.event.number }}
- name: Add ipfs hash to release
uses: softprops/action-gh-release@v1
if: ${{ matrix.app == 'trading' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
with:
files: ${{ matrix.app }}-ipfs-hash
@@ -0,0 +1,94 @@
name: Docker build
on:
workflow_call:
inputs:
projects:
required: true
type: string
jobs:
master:
strategy:
fail-fast: false
matrix:
app: ${{ fromJSON(inputs.projects) }}
name: ${{ matrix.app }}
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v3
- name: Set up QEMU
id: quemu
uses: docker/setup-qemu-action@v2
- name: Available platforms
run: echo ${{ steps.qemu.outputs.platforms }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
# https://docs.github.com/en/actions/learn-github-actions/contexts
# https://github.com/actions/checkout#Checkout-pull-request-HEAD-commit-instead-of-merge-commit
- name: Determine Docker Image tag
id: tags
run: |
npmVersion=$(cat .nvmrc | head -n 1)
versionTag=${{ startsWith(github.ref, 'refs/tags/') && github.ref_name || github.event.pull_request.head.sha }}
echo ::set-output name=npmVersion::${npmVersion}
echo ::set-output name=version::${versionTag}
- name: Print config
run: |
git rev-parse --verify HEAD
git status
echo "steps.tags.outputs.version=${{ steps.tags.outputs.version }}"
- name: Build and export to local Docker
uses: docker/build-push-action@v3
with:
load: true
build-args: |
APP=${{ matrix.app }}
NODE_VERSION=${{ steps.tags.outputs.npmVersion }}
tags: |
ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local
- name: Sanity check docker image
run: |
echo "Check .env file"
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local cat .env
echo "Check ipfs-hash"
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local cat ipfs-hash
echo "List html directory"
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local ls -lah
- name: Log in to the Container registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
id: docker_build
uses: docker/build-push-action@v3
with:
push: true
build-args: |
APP=${{ matrix.app }}
NODE_VERSION=${{ steps.tags.outputs.npmVersion }}
tags: |
ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:latest
ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:${{ steps.tags.outputs.version }}
- name: Add preview label
uses: actions-ecosystem/action-add-labels@v1
if: ${{ github.event_name == 'pull_request' }}
with:
labels: ${{ matrix.app }}-preview
number: ${{ github.event.number }}
- name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}
+11 -9
View File
@@ -19,27 +19,29 @@ on:
jobs:
publish:
name: Build & Publish - Tag
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
permissions:
contents: 'read'
actions: 'read'
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup node
with:
fetch-depth: 0
- name: User Node.js 16
id: Node
uses: actions/setup-node@v3
with:
node-version-file: '.nvmrc'
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
cache: yarn
node-version: 16.15.1
- name: Restore node_modules from cache
uses: actions/cache@v3
with:
path: '**/node_modules'
key: node_modules-${{ hashFiles('**/yarn.lock') }}
- name: Install root dependencies
run: yarn install --frozen-lockfile
- name: Build project
run: yarn nx build ${{inputs.project}}
- name: Publish project to @vegaprotocol
uses: JS-DevTools/npm-publish@v1
with:
+46
View File
@@ -0,0 +1,46 @@
name: Unit tests & build
on:
push:
branches:
- develop
- main
pull_request:
jobs:
pr:
name: Test and lint - PR
runs-on: ubuntu-latest
permissions:
contents: 'read'
actions: 'read'
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Derive appropriate SHAs for base and head for `nx affected` commands
uses: nrwl/nx-set-shas@v2
with:
main-branch-name: ${{ github.base_ref }}
- name: Use Node.js 16
id: Node
uses: actions/setup-node@v3
with:
node-version: 16.15.1
- name: Restore node_modules from cache
uses: actions/cache@v3
with:
path: '**/node_modules'
key: node_modules-${{ hashFiles('**/yarn.lock') }}
- name: Install root dependencies
run: yarn install --frozen-lockfile
- name: Check formatting
run: yarn nx format:check
- name: Lint affected
run: yarn nx affected:lint --max-warnings=0
- name: Test affected
run: yarn nx affected:test
- name: Build affected
run: yarn nx affected:build
- name: Build affected spec
run: yarn nx affected --target=build-spec
-4
View File
@@ -2,7 +2,6 @@
# compiled output
/dist
/dist-result
/tmp
/out-tsc
/tools/executors/**/*.js
@@ -47,6 +46,3 @@ cypress.env.json
# Next.js
.next
#cypress
/apps/trading-e2e/cypress/reports/
+1
View File
@@ -7,4 +7,5 @@ __generated___
apps/static/src/assets/devnet-tranches.json
apps/static/src/assets/mainnet-tranches.json
apps/static/src/assets/stagnet3-tranches.json
apps/static/src/assets/testnet-tranches.json
+10 -6
View File
@@ -4,7 +4,6 @@ FROM --platform=amd64 node:${NODE_VERSION}-alpine3.16 as build
WORKDIR /app
# Argument to allow building of different apps
ARG APP
ARG ENV_NAME=""
RUN apk add --update --no-cache \
python3 \
make \
@@ -13,17 +12,22 @@ RUN apk add --update --no-cache \
COPY . ./
RUN yarn --network-timeout 100000 --pure-lockfile
# work around for different build process in trading
RUN sh docker/docker-build.sh
RUN sh ./docker-build.sh
# Server environment
# if this fails you need to docker pull nginx:1.23-alpine and pin new SHA
# this is to ensure that we run always same version of alpine to make sure ipfs is indempotent
FROM --platform=amd64 nginx:1.23-alpine@sha256:6318314189b40e73145a48060bff4783a116c34cc7241532d0d94198fb2c9629
ARG APP
# configuration of system
RUN apk add --no-cache bash go-ipfs
EXPOSE 80
COPY entrypoint.sh /entrypoint.sh
CMD ["/entrypoint.sh"]
# Copy dist
WORKDIR /usr/share/nginx/html
COPY docker/nginx.conf /etc/nginx/conf.d/default.conf
RUN rm -rf /usr/share/nginx/html/*
COPY --from=build /app/dist/apps/${APP}/* /usr/share/nginx/html
RUN apk add --no-cache go-ipfs; ipfs init && echo "$(ipfs add -rQ .)" > /ipfs-hash; apk del go-ipfs
COPY nginx/nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=build /app/dist/apps/${APP} /usr/share/nginx/html
COPY ./apps/${APP}/.env .env
RUN ipfs init && echo "$(ipfs add -rQ .)" > ipfs-hash
Vendored
+19 -1
View File
@@ -1,2 +1,20 @@
@Library('vega-shared-library') _
runApprobation ignoreFailure: false, frontendBranch: env.BRANCH_NAME, type: 'frontend'
def commitHash = 'UNKNOWN'
pipeline {
agent any
options {
skipDefaultCheckout true
parallelsAlwaysFailFast()
}
stages {
stage('approbation') {
steps {
sh 'printenv'
checkout scm
runApprobation ignoreFailure: false, frontendBranch: env.BRANCH_NAME, type: 'frontend'
}
}
}
}
-20
View File
@@ -1,20 +0,0 @@
.PHONY: latest-release
latest-release:
gh release list | head -n 1 | awk '{print $1}'
.PHONY: show-latest-release
show-latest-release:
gh release view `gh release list | head -n 1 | awk '{print $1}'`
.PHONY: recalculate-ipfs
recalculate-ipfs:
echo "ipfs hash inside the image"
docker run --rm ${TAG} cat /ipfs-hash
echo "recalculating ipfs hash"
docker run --rm ${TAG} ipfs add -rw /usr/share/nginx/html
.PHONY: eject-ipfs-hash
unpack:
docker create --name=dist ${TAG}
docker cp dist:/usr/share/nginx/html dist
docker rm dist
+13 -56
View File
@@ -72,7 +72,7 @@ Run `nx serve my-app` for a dev server. Navigate to the port specified in `app/<
In order to generate the schemas for your GraphQL queries, you can run `GRAPHQL_SCHEMA_PATH=[YOUR SCHEMA FILE / API URL HERE] nx run types:generate`.
```bash
export GRAPHQL_SCHEMA_PATH=https://api.n07.testnet.vega.xyz/graphql
export GRAPHQL_SCHEMA_PATH=https://api.n11.testnet.vega.xyz/graphql
yarn nx run types:generate
```
@@ -103,68 +103,25 @@ In CI linting, formatting and also run. These checks can be seen in the [CI work
Visit the [Nx Documentation](https://nx.dev/getting-started/intro) to learn more.
# 🐋 Hosting a console
# Docker & Vegacapsule
To host a console there are two possible build scenarios for running the frontends: nx performed **outside** or **inside** docker build. For specific build instructions follow [build instructions](#build-instructions).
## Docker
In order to run a container on port 3000:
The [Dockerfile](./dockerfiles) for running the frontends is pretty basic, merely building the application with the APP arg that is passed in and serving the application from [nginx](./nginx/nginx.conf). The only complexity that exists is that there is a script which allows the passing of run time environment variables to the containers. See configuration below for how to do this.
You can build any of the containers locally with the following command:
```bash
docker build --dockerfile dockerfiles/Dockerfile.cra . --build-arg APP=[YOUR APP] --tag=[TAG]
```
In order to run a container:
```bash
docker run -p 3000:80 [TAG]
```
## Build instructions
The [`docker`](./docker) subfolder has some docker configurations for easily setting up your own hosted version of console either for the web, or ready for pinning on IPFS
### nx build outside the docker
Packaging prepared dist into [`nginx`](https://hub.docker.com/_/nginx)([server configuration](./nginx/nginx.conf)) docker image involves building the application on docker host machine from source.
As a prerequisite you need to perform build of `dist` directory and move its content for specific application to `dist-result` directory. Use following script to do it with a single command:
```bash
./docker/prepare-dist.sh
```
You can build any of the containers locally with the following command:
```bash
docker build --dockerfile docker/node-outside-docker.Dockerfile . --tag=[TAG]
```
### nx build inside the docker
Using multistage dockerfile dist is compiled using [node](https://hub.docker.com/_/node) image and later packed to nginx as in [dist build](#dist-build) example.
```bash
docker build --build-arg APP=[YOUR APP] --build-arg NODE_VERSION=$(cat .nvmrc) --build-arg ENV_NAME=mainnet -t [TAG] -f docker/node-inside-docker.Dockerfile .
```
### Computing ipfs-hash of the build
At the moment this feature is important only for `trading` (console) releases.
Each docker build finishes with hash calculation for dist directory. Resulting hash is added to file named as `/ipfs-hash`. Once docker image is produced you can run following commad to display ipfs-hash:
```bash
make recalculate-ipfs TAG=vegaprotocol/trading:{YOUR_VERSION}
```
**updating hash:** recompiling dist directory (even if there are no changed to source code) results in different hash computed by ipfs command.
### Verifying ipfs-hash of existing current application version
An IPFS CID will be attached to every [release](https://github.com/vegaprotocol/frontend-monorepo/releases). If you are intending to pin an application on IPFS, you can check that your build matches by running the following steps:
1. Show latest release by runnning: `make latest-release`. You need to configure [`gh`](https://cli.github.com/) for this step to work, otherwise please provide release manually from [github](https://github.com/vegaprotocol/frontend-monorepo/releases) or [dockerhub](https://hub.docker.com/r/vegaprotocol/trading)
2. Set RELEASE environment variable to value that you want to validate: `export RELEASE=$(make latest-release)` or `export RELEASE=vXX.XX.XX`
3. Set TAG environment variable to image that you want to validate: `export TAG=vegaprotocol/trading:$RELEASE`
4. Download docker image with the desired release `docker pull $TAG`.
5. Recalculate hash: `make recalculate-ipfs`
6. You should see exactly same hash produced by ipfs command as one placed with the release notes: `make show-latest-release`
7. If you want to extract dist from docker image to your local filesystem you can run following command: `make unpack`
8. Now `dist` directory contains valid application build. **it is not possible to calculate same ipfs hash on files that are result of copy operation**
Images ending with `.dist` are to pack locally created transpiled HTML files into nginx container for non-compatible with yarn architectures like M1 Mac
## Config
+2 -2
View File
@@ -1,7 +1,7 @@
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=http://localhost:26617
NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
NX_VEGA_URL=http://localhost:3008/graphql
NX_VEGA_URL=http://localhost:3028/query
NX_VEGA_ENV=CUSTOM
NX_VEGA_CONFIG_URL=
@@ -18,4 +18,4 @@ NX_EXPLORER_PARTIES=1
NX_EXPLORER_VALIDATORS=1
CYPRESS_VEGA_WALLET_API_TOKEN=
CYPRESS_VEGA_URL=http://localhost:3008/graphql
CYPRESS_VEGA_URL=http://localhost:3028/query
+1 -1
View File
@@ -2,7 +2,7 @@
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://mainnet-observer-proxy01.ops.vega.xyz/
NX_TENDERMINT_WEBSOCKET_URL=wss://mainnet-observer-proxy01.ops.vega.xyz/websocket
NX_VEGA_URL=https://api.vega.community/graphql
NX_VEGA_URL=https://api.vega.xyz/query
NX_VEGA_ENV=MAINNET
NX_BLOCK_EXPLORER=https://be.explorer.vega.xyz/rest
+18
View File
@@ -0,0 +1,18 @@
# App configuration variables
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://tm.n00.stagnet3.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n00.stagnet3.vega.xyz/websocket
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_ENV=STAGNET3
NX_BLOCK_EXPLORER=https://be.stagnet3.vega.xyz/rest
# App flags
NX_EXPLORER_ASSETS=1
NX_EXPLORER_GENESIS=1
NX_EXPLORER_GOVERNANCE=1
NX_EXPLORER_MARKETS=1
NX_EXPLORER_ORACLES=1
NX_EXPLORER_TXS_LIST=0
NX_EXPLORER_NETWORK_PARAMETERS=1
NX_EXPLORER_PARTIES=1
NX_EXPLORER_VALIDATORS=1
+1 -1
View File
@@ -2,7 +2,7 @@
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://tm.n07.testnet.vega.xyz/tm
NX_TENDERMINT_WEBSOCKET_URL=wss://lb.testnet.vega.xyz/tm/websocket
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
NX_VEGA_URL=https://api.n11.testnet.vega.xyz/graphql
NX_VEGA_ENV=TESTNET
NX_BLOCK_EXPLORER=https://be.testnet.vega.xyz/rest
+1 -2
View File
@@ -21,11 +21,10 @@ module.exports = defineConfig({
chromeWebSecurity: false,
viewportWidth: 1440,
viewportHeight: 900,
testIsolation: false,
},
env: {
environment: 'CUSTOM',
networkQueryUrl: 'http://localhost:3008/graphql',
networkQueryUrl: 'http://localhost:3028/query',
ethUrl: 'https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8',
commitHash: 'dev',
tsConfig: 'tsconfig.json',
@@ -10,8 +10,6 @@
"governance.proposal.updateMarket.minVoterBalance",
"governance.proposal.updateNetParam.minProposerBalance",
"governance.proposal.updateNetParam.minVoterBalance",
"governance.proposal.updateAsset.minProposerBalance",
"governance.proposal.updateAsset.minVoterBalance",
"reward.staking.delegation.maxPayoutPerEpoch",
"reward.staking.delegation.maxPayoutPerParticipant",
"reward.staking.delegation.minimumValidatorStake",
@@ -21,6 +19,9 @@
"validators.delegation.minAmount"
],
"fiveDecimal": [
"governance.proposal.updateAsset.minProposerBalance",
"governance.proposal.updateAsset.minVoterBalance",
"governance.proposal.updateAsset.requiredParticipation",
"market.fee.factors.infrastructureFee",
"market.fee.factors.makerFee",
"market.liquidity.bondPenaltyParameter",
@@ -76,7 +77,6 @@
"governance.proposal.updateNetParam.requiredMajority",
"governance.proposal.updateNetParam.requiredParticipation",
"governance.proposal.updateMarket.minProposerEquityLikeShare",
"governance.proposal.updateAsset.requiredParticipation",
"validators.vote.required"
],
"duration": [
+46 -18
View File
@@ -9,22 +9,21 @@ context('Home Page', function () {
it('should show connected environment stats', function () {
const statTitles = {
0: 'Status',
1: 'Epoch',
2: 'Block height',
3: 'Uptime',
4: 'Total nodes',
5: 'Total staked',
6: 'Backlog',
7: 'Trades / second',
8: 'Orders / block',
9: 'Orders / second',
10: 'Transactions / block',
11: 'Block time',
12: 'Time',
13: 'App',
14: 'Tendermint',
15: 'Up since',
16: 'Chain ID',
1: 'Block height',
2: 'Uptime',
3: 'Total nodes',
4: 'Total staked',
5: 'Backlog',
6: 'Trades / second',
7: 'Orders / block',
8: 'Orders / second',
9: 'Transactions / block',
10: 'Block time',
11: 'Time',
12: 'App',
13: 'Tendermint',
14: 'Up since',
15: 'Chain ID',
};
cy.get('[data-testid="stats-title"]')
@@ -32,13 +31,42 @@ context('Home Page', function () {
cy.wrap($list).should('contain.text', statTitles[index]);
})
.then(($list) => {
cy.wrap($list).should('have.length', 17);
cy.wrap($list).should('have.length', 16);
});
cy.get(statsValue).eq(0).should('contain.text', 'CONNECTED');
cy.get(statsValue).eq(1).should('not.be.empty');
cy.get(statsValue)
.eq(2)
.invoke('text')
.should('match', /\d+d \d+h \d+m \d+s/i);
cy.get(statsValue).eq(3).should('contain.text', '2');
cy.get(statsValue)
.eq(4)
.invoke('text')
.should('match', /\d+\.\d\d(?!\d)/i);
cy.get(statsValue).eq(5).should('contain.text', '0');
cy.get(statsValue).eq(6).should('contain.text', '0');
cy.get(statsValue).eq(7).should('contain.text', '0');
cy.get(statsValue).eq(8).should('contain.text', '0');
cy.get(statsValue).eq(9).should('not.be.empty');
cy.get(statsValue).eq(10).should('not.be.empty');
cy.get(statsValue).eq(11).should('not.be.empty');
cy.get(statsValue)
.eq(12)
.invoke('text')
.should('match', /v\d+\.\d+\.\d+/i);
cy.get(statsValue)
.eq(13)
.invoke('text')
.should('match', /\d+\.\d+\.\d+/i);
cy.get(statsValue).eq(14).should('not.be.empty');
cy.get(statsValue).eq(15).should('not.be.empty');
});
it('Block height should be updating', function () {
cy.get(statsValue)
.eq(2)
.eq(1)
.invoke('text')
.then((blockHeightTxt) => {
cy.get(statsValue)
@@ -138,7 +138,7 @@ context('Network parameters page', { tags: '@smoke' }, function () {
});
});
it.skip('should list each network parameter displayed as a currency value with four decimals - in the correct format', function () {
it('should list each network parameter displayed as a currency value with four decimals - in the correct format', function () {
cy.get_network_parameters().then((network_parameters) => {
network_parameters = Object.entries(network_parameters);
network_parameters.forEach((network_parameter) => {
@@ -6,7 +6,7 @@ const customNodeBtn = 'custom-node';
context.skip('Node switcher', { tags: '@regression' }, function () {
beforeEach('visit home page', function () {
cy.intercept('GET', 'https://static.vega.xyz/assets/capsule-network.json', {
hosts: ['http://localhost:3008/graphql'],
hosts: ['http://localhost:3028/query'],
}).as('nodeData');
cy.visit('/');
cy.wait('@nodeData');
@@ -219,7 +219,7 @@ context.skip('Parties page', { tags: '@regression' }, function () {
balance type asset {id symbol decimals}}}}}}}}';
cy.request({
method: 'POST',
url: `http://localhost:3008/graphql`,
url: `http://localhost:3028/query`,
body: {
query: mutation,
},
+8 -14
View File
@@ -1,19 +1,13 @@
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_TENDERMINT_URL=https://tm.n00.stagnet3.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n00.stagnet3.vega.xyz/websocket
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
NX_VEGA_NETWORKS='{"SANDBOX":"https://sandbox.explorer.vega.xyz","STAGNET1":"https://stagnet1.token.vega.xyz", "STAGNET3":"https://stagnet3.explorer.vega.xyz","VALIDATOR_TESTNET":"https://validator-testnet.fairground.wtf","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.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
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
NX_VEGA_ENV=STAGNET1
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
NX_VEGA_TOKEN_URL=https://stagnet1.governance.vega.xyz
NX_VEGA_WALLET_URL=http://localhost:1789
NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
NX_BLOCK_EXPLORER=https://be.stagnet1.vega.xyz/rest
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
NX_VEGA_GOVERNANCE_URL=https://stagnet1.governance.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.jsoo
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
NX_BLOCK_EXPLORER=https://be.stagnet3.vega.xyz/rest
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
# App flags
NX_EXPLORER_ASSETS=1
+9 -2
View File
@@ -3,8 +3,15 @@ NX_TENDERMINT_URL=http://localhost:26617
NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
NX_VEGA_ENV=CUSTOM
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
NX_VEGA_EXPLORER_URL=/
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/main/announcements.json
# App flags
NX_EXPLORER_ASSETS=1
NX_EXPLORER_GENESIS=1
NX_EXPLORER_GOVERNANCE=1
NX_EXPLORER_MARKETS=1
NX_EXPLORER_ORACLES=1
NX_EXPLORER_TXS_LIST=0
NX_EXPLORER_NETWORK_PARAMETERS=1
NX_EXPLORER_PARTIES=1
NX_EXPLORER_VALIDATORS=1
+2 -3
View File
@@ -5,8 +5,7 @@ NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-inter
NX_VEGA_ENV=DEVNET
NX_BLOCK_EXPLORER=https://be.devnet1.vega.xyz/rest
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_GOVERNANCE_URL=https://dev.governance.vega.xyz
NX_VEGA_GOVERNANCE_URL=https://dev.token.vega.xyz
NX_VEGA_URL=https://api.devnet1.vega.xyz/graphql
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_VEGA_EXPLORER_URL=/
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
+5 -6
View File
@@ -1,10 +1,9 @@
# App configuration variables
NX_TENDERMINT_URL=https://be.vega.community
NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket
NX_TENDERMINT_URL=https://be.explorer.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://be.explorer.vega.xyz/websocket
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/mainnet1/mainnet1.toml
NX_VEGA_ENV=MAINNET
NX_BLOCK_EXPLORER=https://be.vega.community/rest/
NX_BLOCK_EXPLORER=https://be.explorer.vega.xyz/rest/
NX_ETHERSCAN_URL=https://etherscan.io
NX_VEGA_GOVERNANCE_URL=https://governance.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz/
NX_VEGA_GOVERNANCE_URL=https://token.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
+20
View File
@@ -0,0 +1,20 @@
# App configuration variables
NX_TENDERMINT_URL=https://tm.be.mainnet-mirror.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://be.mainnet-mirror.vega.xyz/websocket
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/mainnet-mirror/vegawallet-mainnet-mirror.toml
NX_VEGA_ENV=MIRROR
NX_BLOCK_EXPLORER=https://be.mainnet-mirror.vega.xyz/rest/
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_GOVERNANCE_URL=https://mainnet-mirror.token.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
# App flags
NX_EXPLORER_ASSETS=1
NX_EXPLORER_GENESIS=1
NX_EXPLORER_GOVERNANCE=1
NX_EXPLORER_NETWORK_PARAMETERS=1
NX_EXPLORER_PARTIES=1
NX_EXPLORER_VALIDATORS=1
NX_EXPLORER_MARKETS=0
NX_EXPLORER_ORACLES=0
NX_EXPLORER_TXS_LIST=1
+12
View File
@@ -0,0 +1,12 @@
# App configuration variables
NX_VEGA_ENV=SANDBOX
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/sandbox/vegawallet-sandbox.toml
NX_VEGA_EXPLORER_URL=https://sandbox.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_TENDERMINT_URL=https://tm.sandbox.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://be.sandbox.vega.xyz/websocket
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_GOVERNANCE_URL=https://sandbox.token.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
+14 -2
View File
@@ -1,2 +1,14 @@
# .env is stagnet1, so there are no overrides required
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz","STAGNET3":"https://stagnet3.explorer.vega.xyz"}'
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
NX_VEGA_ENV=STAGNET1
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
NX_VEGA_TOKEN_URL=https://stagnet1.token.vega.xyz
NX_VEGA_WALLET_URL=http://localhost:1789
NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
NX_BLOCK_EXPLORER=https://be.stagnet1.vega.xyz/rest
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_GOVERNANCE_URL=https://stagnet1.token.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
+8
View File
@@ -0,0 +1,8 @@
NX_TENDERMINT_URL=https://tm.n00.stagnet3.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://be.stagnet3.vega.xyz/websocket
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
NX_VEGA_ENV=STAGNET3
NX_BLOCK_EXPLORER=https://be.stagnet3.vega.xyz/rest
NX_VEGA_GOVERNANCE_URL=https://stagnet3.token.vega.xyz
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega-dev-releases/releases/
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
+2 -3
View File
@@ -7,6 +7,5 @@ NX_VEGA_ENV=TESTNET
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_GOVERNANCE_URL=https://governance.fairground.wtf
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
NX_VEGA_GOVERNANCE_URL=https://token.fairground.wtf
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
+1 -2
View File
@@ -9,6 +9,5 @@ NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/annou
NX_VEGA_GOVERNANCE_URL=https://validator-testnet.governance.vega.xyz
NX_TENDERMINT_URL=https://tm-be.validators-testnet.vega.rocks
NX_BLOCK_EXPLORER=https://be.validators-testnet.vega.rocks/rest
NX_BLOCK_EXPLORER=https://be.validators-testnet.vega.rocks/
NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.xyz/websocket
NX_VEGA_EXPLORER_URL=https://validator-testnet.explorer.vega.xyz/
+1 -2
View File
@@ -4,5 +4,4 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26607/websocket
NX_VEGA_ENV=CUSTOM
NX_BLOCK_EXPLORER=
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
NX_VEGA_EXPLORER_URL=/
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/main/announcements.json
+2 -1
View File
@@ -35,11 +35,12 @@ Example configurations are provided here:
- [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 explorer:serve --env={env} # e.g. stagnet1
yarn nx run explorer:serve --env={env} # e.g. stagnet3
```
There are a few different configuration options offered for this app:
+2 -24
View File
@@ -1,18 +1,9 @@
import {
AppFailure,
NetworkLoader,
NodeGuard,
NodeSwitcherDialog,
useEnvironment,
useInitializeEnv,
useNodeSwitcherStore,
} from '@vegaprotocol/environment';
import { NetworkLoader, useInitializeEnv } from '@vegaprotocol/environment';
import { TendermintWebsocketProvider } from './contexts/websocket/tendermint-websocket-provider';
import { Loader, Splash } from '@vegaprotocol/ui-toolkit';
import { DEFAULT_CACHE_CONFIG } from '@vegaprotocol/apollo-client';
import { RouterProvider } from 'react-router-dom';
import { router } from './routes/router-config';
import { t } from '@vegaprotocol/i18n';
const splashLoading = (
<Splash>
@@ -21,23 +12,10 @@ const splashLoading = (
);
function App() {
const { VEGA_URL } = useEnvironment();
const [nodeSwitcherOpen, setNodeSwitcherOpen] = useNodeSwitcherStore(
(store) => [store.dialogOpen, store.setDialogOpen]
);
return (
<TendermintWebsocketProvider>
<NetworkLoader cache={DEFAULT_CACHE_CONFIG}>
<NodeGuard
skeleton={<div>{t('Loading')}</div>}
failure={<AppFailure title={t(`Node: ${VEGA_URL} is unsuitable`)} />}
>
<RouterProvider router={router} fallbackElement={splashLoading} />
</NodeGuard>
<NodeSwitcherDialog
open={nodeSwitcherOpen}
setOpen={setNodeSwitcherOpen}
/>
<RouterProvider router={router} fallbackElement={splashLoading} />
</NetworkLoader>
</TendermintWebsocketProvider>
);
@@ -6,7 +6,6 @@ export type AssetBalanceProps = {
assetId: string;
price: string;
showAssetLink?: boolean;
showAssetSymbol?: boolean;
};
/**
@@ -17,21 +16,18 @@ const AssetBalance = ({
assetId,
price,
showAssetLink = true,
showAssetSymbol = false,
}: AssetBalanceProps) => {
const { data: asset, loading } = useAssetDataProvider(assetId);
const { data: asset } = useAssetDataProvider(assetId);
const label =
!loading && asset && asset.decimals
asset && asset.decimals
? addDecimalsFormatNumber(price, asset.decimals)
: price;
return (
<div className="inline-block">
<span>{label}</span>{' '}
{showAssetLink && asset?.id ? (
<AssetLink showAssetSymbol={showAssetSymbol} assetId={assetId} />
) : null}
{showAssetLink && asset?.id ? <AssetLink assetId={assetId} /> : null}
</div>
);
};
@@ -13,17 +13,11 @@ const DEFAULT_DECIMALS = 18;
* the governance asset first, which is set by a network parameter
*/
const GovernanceAssetBalance = ({ price }: GovernanceAssetBalanceProps) => {
const { data, loading } = useExplorerGovernanceAssetQuery();
const { data } = useExplorerGovernanceAssetQuery();
if (!loading && data && data.networkParameter?.value) {
if (data && data.networkParameter?.value) {
const governanceAssetId = data.networkParameter.value;
return (
<AssetBalance
price={price}
showAssetSymbol={true}
assetId={governanceAssetId}
/>
);
return <AssetBalance price={price} assetId={governanceAssetId} />;
} else {
return (
<div className="inline-block">
@@ -4,7 +4,7 @@ import { t } from '@vegaprotocol/i18n';
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
import type { AgGridReact } from 'ag-grid-react';
import { AgGridColumn } from 'ag-grid-react';
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/datagrid';
import type { VegaICellRendererParams } from '@vegaprotocol/datagrid';
import { useRef, useLayoutEffect } from 'react';
import { BREAKPOINT_MD } from '../../config/breakpoints';
@@ -1,60 +1,60 @@
import {
useEnvironment,
useNodeSwitcherStore,
} from '@vegaprotocol/environment';
import { NodeSwitcherDialog, useEnvironment } from '@vegaprotocol/environment';
import { t } from '@vegaprotocol/i18n';
import { useScreenDimensions } from '@vegaprotocol/react-helpers';
import { ExternalLink, Link } from '@vegaprotocol/ui-toolkit';
import { useMemo } from 'react';
import { useMemo, useState } from 'react';
import { ENV } from '../../config/env';
export const Footer = () => {
const { VEGA_URL, GIT_COMMIT_HASH, GIT_ORIGIN_URL } = useEnvironment();
const setNodeSwitcherOpen = useNodeSwitcherStore(
(store) => store.setDialogOpen
);
const [nodeSwitcherOpen, setNodeSwitcherOpen] = useState(false);
const { screenSize } = useScreenDimensions();
const showFullFeedbackLabel = useMemo(
() => ['md', 'lg', 'xl', 'xxl', 'xxxl'].includes(screenSize),
() => ['lg', 'xl', 'xxl', 'xxxl'].includes(screenSize),
[screenSize]
);
return (
<footer className="grid grid-rows-2 grid-cols-[1fr_auto] text-xs md:text-md md:flex md:col-span-2 px-4 py-2 gap-4 border-t border-vega-light-200 dark:border-vega-dark-200">
<div className="flex justify-between gap-2 align-middle">
{GIT_COMMIT_HASH && (
<div className="content-center flex border-r border-neutral-700 dark:border-neutral-300 pr-4">
<p data-testid="git-commit-hash">
{t('Version')}:{' '}
<Link
href={
GIT_ORIGIN_URL
? `${GIT_ORIGIN_URL}/commit/${GIT_COMMIT_HASH}`
: undefined
}
target={GIT_ORIGIN_URL ? '_blank' : undefined}
>
{GIT_COMMIT_HASH}
</Link>
</p>
<>
<footer className="grid grid-rows-2 grid-cols-[1fr_auto] text-xs md:text-md md:flex md:col-span-2 px-4 py-2 gap-4 border-t border-vega-light-200 dark:border-vega-dark-200">
<div className="flex justify-between gap-2 align-middle">
{GIT_COMMIT_HASH && (
<div className="content-center flex border-r border-neutral-700 dark:border-neutral-300 pr-4">
<p data-testid="git-commit-hash">
{t('Version')}:{' '}
<Link
href={
GIT_ORIGIN_URL
? `${GIT_ORIGIN_URL}/commit/${GIT_COMMIT_HASH}`
: undefined
}
target={GIT_ORIGIN_URL ? '_blank' : undefined}
>
{GIT_COMMIT_HASH}
</Link>
</p>
</div>
)}
<div className="content-center flex pl-2 md:border-r border-neutral-700 dark:border-neutral-300 pr-4">
{VEGA_URL && <NodeUrl url={VEGA_URL} />}
<Link className="ml-2" onClick={() => setNodeSwitcherOpen(true)}>
{t('Change')}
</Link>
</div>
)}
<div className="content-center flex pl-2 md:border-r border-neutral-700 dark:border-neutral-300 pr-4">
{VEGA_URL && <NodeUrl url={VEGA_URL} />}
<Link className="ml-2" onClick={() => setNodeSwitcherOpen(true)}>
{t('Change')}
</Link>
<div className="flex pl-2 content-center">
<ExternalLink href={ENV.addresses.feedback}>
{showFullFeedbackLabel ? t('Share your feedback') : t('Feedback')}
</ExternalLink>
</div>
</div>
<div className="flex pl-2 content-center">
<ExternalLink href={ENV.addresses.feedback}>
{showFullFeedbackLabel ? t('Share your feedback') : t('Feedback')}
</ExternalLink>
</div>
</div>
</footer>
</footer>
<NodeSwitcherDialog
open={nodeSwitcherOpen}
setOpen={setNodeSwitcherOpen}
/>
</>
);
};
@@ -43,7 +43,7 @@ export const AssetLink = ({
if (asDialog) {
open(assetId, e.target as HTMLElement);
} else {
navigate(`/${Routes.ASSETS}/${asset?.id}`);
navigate(`${Routes.ASSETS}/${asset?.id}`);
}
}}
{...props}
@@ -14,72 +14,11 @@ import {
SettlementAssetInfoPanel,
} from '@vegaprotocol/market-info';
import { MarketInfoTable } from '@vegaprotocol/market-info';
import type { DataSourceDefinition } from '@vegaprotocol/types';
import isEqual from 'lodash/isEqual';
import { Link } from 'react-router-dom';
export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
if (!market) return null;
const settlementData =
market.tradableInstrument.instrument.product.dataSourceSpecForSettlementData
.data;
const terminationData =
market.tradableInstrument.instrument.product
.dataSourceSpecForTradingTermination.data;
const getSigners = (data: DataSourceDefinition) => {
if (data.sourceType.__typename === 'DataSourceDefinitionExternal') {
const signers = data.sourceType.sourceType.signers || [];
return signers.map(({ signer }, i) => {
return (
(signer.__typename === 'ETHAddress' && signer.address) ||
(signer.__typename === 'PubKey' && signer.key)
);
});
}
return [];
};
const oraclePanels = isEqual(
getSigners(settlementData),
getSigners(terminationData)
)
? [
{
title: t('Settlement Oracle'),
content: (
<OracleInfoPanel
noBorder={false}
market={market}
type="settlementData"
/>
),
},
{
title: t('Termination Oracle'),
content: (
<OracleInfoPanel
noBorder={false}
market={market}
type="termination"
/>
),
},
]
: [
{
title: t('Oracle'),
content: (
<OracleInfoPanel
noBorder={false}
market={market}
type="settlementData"
/>
),
},
];
const panels = [
{
title: t('Key details'),
@@ -121,11 +60,9 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
<>
<MarketInfoTable
noBorder={false}
data={{
maxValidPrice: trigger.maxValidPrice,
minValidPrice: trigger.minValidPrice,
}}
data={trigger}
decimalPlaces={market.decimalPlaces}
omits={['referencePrice', '__typename']}
/>
<MarketInfoTable
noBorder={false}
@@ -157,7 +94,25 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
<LiquidityPriceRangeInfoPanel market={market} noBorder={false} />
),
},
...oraclePanels,
{
title: t('Oracle'),
content: (
<OracleInfoPanel noBorder={false} market={market}>
<Link
className="text-xs hover:underline"
to={`/oracles#${market.tradableInstrument.instrument.product.dataSourceSpecForSettlementData.id}`}
>
{t('View settlement data oracle specification')}
</Link>
<Link
className="text-xs hover:underline"
to={`/oracles#${market.tradableInstrument.instrument.product.dataSourceSpecForTradingTermination.id}`}
>
{t('View termination oracle specification')}
</Link>
</OracleInfoPanel>
),
},
];
return (
@@ -3,7 +3,7 @@ import { t } from '@vegaprotocol/i18n';
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
import type { AgGridReact } from 'ag-grid-react';
import { AgGridColumn } from 'ag-grid-react';
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/datagrid';
import type {
VegaICellRendererParams,
VegaValueGetterParams,
@@ -9,7 +9,7 @@ import SizeInMarket from '../size-in-market/size-in-market';
export interface DeterministicOrderDetailsProps {
id: string;
// Version to fetch, with 0 being 'latest' and 1 being 'first'. Defaults to 0
version?: number | null;
version?: number;
}
export const wrapperClasses =
@@ -28,7 +28,7 @@ export const wrapperClasses =
*/
const DeterministicOrderDetails = ({
id,
version = null,
version = 0,
}: DeterministicOrderDetailsProps) => {
const { data, error } = useExplorerDeterministicOrderQuery({
variables: { orderId: id, version },
@@ -20,7 +20,7 @@ export const PageHeader = ({
copy = false,
className,
}: PageHeaderProps) => {
const titleClasses = 'text-xl uppercase font-alpha calt';
const titleClasses = 'text-4xl xl:text-5xl uppercase font-alpha calt';
return (
<header className={className}>
<span className={`${titleClasses} block`}>{prefix}</span>
@@ -3,7 +3,7 @@ import { VoteProgress } from '@vegaprotocol/proposals';
import type { AgGridReact } from 'ag-grid-react';
import { AgGridColumn } from 'ag-grid-react';
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/datagrid';
import type {
VegaICellRendererParams,
VegaValueFormatterParams,
@@ -12,10 +12,7 @@ import { useLayoutEffect, useMemo, useRef, useState } from 'react';
import type { RowClickedEvent } from 'ag-grid-community';
import { getDateTimeFormat } from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n';
import {
NetworkParams,
useNetworkParams,
} from '@vegaprotocol/network-parameters';
import { NetworkParams, useNetworkParams } from '@vegaprotocol/react-helpers';
import { ProposalStateMapping } from '@vegaprotocol/types';
import BigNumber from 'bignumber.js';
import { DApp, TOKEN_PROPOSAL, useLinks } from '@vegaprotocol/environment';
@@ -30,7 +30,7 @@ export const BundleExists = ({
// Note if this is wrong, the wrong decoder will be used which will give incorrect data
return (
<div className="w-auto h-10 max-w-lg border-2 border-solid border-vega-light-100 dark:border-vega-dark-200 p-5 mt-5">
<div className="w-auto max-w-lg border-2 border-solid border-vega-light-100 dark:border-vega-dark-200 p-5 mt-5">
<IconForBundleStatus status={status} />
<h1 className="text-xl pb-1">
{status === 'STATUS_ENABLED'
@@ -1,3 +1,4 @@
export { TxList } from './tx-list';
export { TxOrderType } from './tx-order-type';
export { TxsInfiniteList } from './txs-infinite-list';
export { TxsInfiniteListItem } from './txs-infinite-list-item';
@@ -0,0 +1,14 @@
import { t } from '@vegaprotocol/i18n';
import type { TendermintUnconfirmedTransactionsResponse } from '../../routes/txs/tendermint-unconfirmed-transactions-response.d';
interface TxsProps {
data: TendermintUnconfirmedTransactionsResponse | undefined;
}
export const TxList = ({ data }: TxsProps) => {
if (!data) {
return <div>{t('Awaiting transactions')}</div>;
}
return <div>{JSON.stringify(data, null, ' ')}</div>;
};
@@ -7,7 +7,7 @@ import { toHex } from '../search/detect-search';
import { ChainResponseCode } from './details/chain-response-code/chain-reponse.code';
import isNumber from 'lodash/isNumber';
const TRUNCATE_LENGTH = 10;
const TRUNCATE_LENGTH = 5;
export const TxsInfiniteListItem = ({
hash,
@@ -34,10 +34,10 @@ export const TxsInfiniteListItem = ({
className="flex items-center h-full border-t border-neutral-600 dark:border-neutral-800 txs-infinite-list-item grid grid-cols-10 py-2"
>
<div
className="text-sm col-span-10 md:col-span-3 leading-none"
className="text-sm col-span-10 xl:col-span-3 leading-none"
data-testid="tx-hash"
>
<span className="md:hidden uppercase text-vega-dark-300">
<span className="xl:hidden uppercase text-vega-dark-300">
ID:&nbsp;
</span>
<TruncatedLink
@@ -48,10 +48,10 @@ export const TxsInfiniteListItem = ({
/>
</div>
<div
className="text-sm col-span-10 md:col-span-3 leading-none"
className="text-sm col-span-10 xl:col-span-3 leading-none"
data-testid="pub-key"
>
<span className="md:hidden uppercase text-vega-dark-300">
<span className="xl:hidden uppercase text-vega-dark-300">
By:&nbsp;
</span>
<TruncatedLink
@@ -61,14 +61,14 @@ export const TxsInfiniteListItem = ({
endChars={TRUNCATE_LENGTH}
/>
</div>
<div className="text-sm col-span-5 md:col-span-2 leading-none flex items-center">
<div className="text-sm col-span-5 xl:col-span-2 leading-none flex items-center">
<TxOrderType orderType={type} command={command} />
</div>
<div
className="text-sm col-span-3 md:col-span-1 leading-none flex items-center"
className="text-sm col-span-3 xl:col-span-1 leading-none flex items-center"
data-testid="tx-block"
>
<span className="md:hidden uppercase text-vega-dark-300">
<span className="xl:hidden uppercase text-vega-dark-300">
Block:&nbsp;
</span>
<TruncatedLink
@@ -79,10 +79,10 @@ export const TxsInfiniteListItem = ({
/>
</div>
<div
className="text-sm col-span-2 md:col-span-1 leading-none flex items-center"
className="text-sm col-span-2 xl:col-span-1 leading-none flex items-center"
data-testid="tx-success"
>
<span className="md:hidden uppercase text-vega-dark-300">
<span className="xl:hidden uppercase text-vega-dark-300">
Success:&nbsp;
</span>
{isNumber(code) ? (
@@ -64,7 +64,9 @@ describe('Txs infinite list', () => {
error={Error('test error!')}
/>
);
expect(screen.getByText('Cannot fetch transaction')).toBeInTheDocument();
expect(
screen.getByText('Cannot fetch transaction: Error: test error!')
).toBeInTheDocument();
});
it('item renders data of n length into list of n length', () => {
@@ -30,7 +30,7 @@ const NOOP = () => {};
const Item = ({ index, style, isLoading, error }: ItemProps) => {
let content;
if (error) {
content = t(`Cannot fetch transaction`);
content = t(`Cannot fetch transaction: ${error}`);
} else if (isLoading) {
content = <Loader />;
} else {
@@ -68,7 +68,7 @@ export const TxsInfiniteList = ({
className,
}: TxsInfiniteListProps) => {
const { screenSize } = useScreenDimensions();
const isStacked = ['xs', 'sm'].includes(screenSize);
const isStacked = ['xs', 'sm', 'md', 'lg'].includes(screenSize);
if (!txs) {
if (!areTxsLoading) {
@@ -95,15 +95,15 @@ export const TxsInfiniteList = ({
return (
<div className={className} data-testid="transactions-list">
<div className="lg:grid grid-cols-10 w-full mb-3 hidden text-vega-dark-300 uppercase">
<div className="xl:grid grid-cols-10 w-full mb-3 hidden text-vega-dark-300 uppercase">
<div className="col-span-3">
<span className="hidden xl:inline">{t('Transaction')} &nbsp;</span>
<span className="hidden xl:inline">Transaction &nbsp;</span>
<span>ID</span>
</div>
<div className="col-span-3">{t('Submitted By')}</div>
<div className="col-span-2">{t('Type')}</div>
<div className="col-span-1">{t('Block')}</div>
<div className="col-span-1">{t('Success')}</div>
<div className="col-span-3">Submitted By</div>
<div className="col-span-2">Type</div>
<div className="col-span-1">Block</div>
<div className="col-span-1">Success</div>
</div>
<div data-testid="infinite-scroll-wrapper">
<InfiniteLoader
@@ -1,4 +1,5 @@
import { Routes } from '../../routes/route-names';
import { RenderFetched } from '../render-fetched';
import { TruncatedLink } from '../truncate/truncated-link';
import { TxOrderType } from './tx-order-type';
import { Table, TableRow, TableCell } from '../table';
@@ -8,7 +9,7 @@ import type { BlockExplorerTransactions } from '../../routes/types/block-explore
import isNumber from 'lodash/isNumber';
import { ChainResponseCode } from './details/chain-response-code/chain-reponse.code';
import { getTxsDataUrl } from '../../hooks/use-txs-data';
import { AsyncRenderer, Loader } from '@vegaprotocol/ui-toolkit';
import { Loader } from '@vegaprotocol/ui-toolkit';
import EmptyList from '../empty-list/empty-list';
interface TxsPerBlockProps {
@@ -26,7 +27,7 @@ export const TxsPerBlock = ({ blockHeight, txCount }: TxsPerBlockProps) => {
} = useFetch<BlockExplorerTransactions>(url);
return (
<AsyncRenderer data={data} error={error} loading={!!loading}>
<RenderFetched error={error} loading={loading} className="text-body-large">
{data && data.transactions.length > 0 ? (
<div className="overflow-x-auto whitespace-nowrap mb-28">
<Table>
@@ -94,6 +95,6 @@ export const TxsPerBlock = ({ blockHeight, txCount }: TxsPerBlockProps) => {
label={t('0 transactions')}
/>
)}
</AsyncRenderer>
</RenderFetched>
);
};
@@ -144,12 +144,12 @@ afterEach(() => {
describe('Block', () => {
it('renders error state if error is present', async () => {
(useFetch as jest.Mock).mockReturnValue({
state: { data: null, loading: false, error: new Error('asd') },
state: { data: null, loading: false, error: 'asd' },
});
render(renderComponent());
expect(screen.getByText(`BLOCK ${blockId}`)).toBeInTheDocument();
expect(screen.getByText('Something went wrong: asd')).toBeInTheDocument();
expect(screen.getByText('Error retrieving data')).toBeInTheDocument();
});
it('renders loading state if present', async () => {
@@ -1,3 +1,4 @@
import React from 'react';
import { Link, useParams } from 'react-router-dom';
import { DATA_SOURCES } from '../../../config';
import { getDateTimeFormat } from '@vegaprotocol/utils';
@@ -11,8 +12,9 @@ import {
TableCell,
} from '../../../components/table';
import { TxsPerBlock } from '../../../components/txs/txs-per-block';
import { AsyncRenderer, Button } from '@vegaprotocol/ui-toolkit';
import { Button } from '@vegaprotocol/ui-toolkit';
import { Routes } from '../../route-names';
import { RenderFetched } from '../../../components/render-fetched';
import { t } from '@vegaprotocol/i18n';
import { useFetch } from '@vegaprotocol/react-helpers';
import { NodeLink } from '../../../components/links';
@@ -32,7 +34,7 @@ const Block = () => {
return (
<section>
<RouteTitle data-testid="block-header">{t(`BLOCK ${block}`)}</RouteTitle>
<AsyncRenderer data={blockData} error={error} loading={!!loading}>
<RenderFetched error={error} loading={loading}>
<>
<div className="grid grid-cols-2 gap-2 mb-8">
<Link
@@ -121,7 +123,7 @@ const Block = () => {
</>
)}
</>
</AsyncRenderer>
</RenderFetched>
</section>
);
};
+11 -16
View File
@@ -1,7 +1,7 @@
import { t } from '@vegaprotocol/i18n';
import { useFetch } from '@vegaprotocol/react-helpers';
import { RouteTitle } from '../../components/route-title';
import { AsyncRenderer, SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
import { Loader, SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
import { DATA_SOURCES } from '../../config';
import type { TendermintGenesisResponse } from './tendermint-genesis-response';
import { useDocumentTitle } from '../../hooks/use-document-title';
@@ -10,26 +10,21 @@ const Genesis = () => {
useDocumentTitle(['Genesis']);
const {
state: { data, loading, error },
state: { data: genesis, loading },
} = useFetch<TendermintGenesisResponse>(
`${DATA_SOURCES.tendermintUrl}/genesis`
);
if (!genesis?.result.genesis) {
if (loading) {
return <Loader />;
}
return null;
}
return (
<>
<section>
<RouteTitle data-testid="genesis-header">{t('Genesis')}</RouteTitle>
<AsyncRenderer
data={data}
error={error}
loading={!!loading}
loadingMessage={t('Loading genesis information...')}
errorMessage={t('Could not fetch genesis data')}
>
<section>
<SyntaxHighlighter data={data?.result.genesis} />
</section>
</AsyncRenderer>
</>
<SyntaxHighlighter data={genesis?.result.genesis} />
</section>
);
};
@@ -1,6 +1,6 @@
import { proposalsDataProvider } from '@vegaprotocol/proposals';
import { t } from '@vegaprotocol/i18n';
import { useDataProvider } from '@vegaprotocol/data-provider';
import { useDataProvider } from '@vegaprotocol/react-helpers';
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { ProposalsTable } from '../../components/proposals/proposals-table';
import { RouteTitle } from '../../components/route-title';
+4 -6
View File
@@ -38,16 +38,14 @@ const DialogsContainer = () => {
export const Layout = () => {
const isHome = Boolean(useMatch(Routes.HOME));
const { ANNOUNCEMENTS_CONFIG_URL } = useEnvironment();
const fixedWidthClasses = 'w-full max-w-[1500px] mx-auto';
return (
<>
<div
className={classNames(
'min-h-screen',
'max-w-[1500px] min-h-[100vh]',
'mx-auto my-0',
'grid grid-rows-[auto_1fr_auto] grid-cols-1',
'border-vega-light-200 dark:border-vega-dark-200',
'border-vega-light-200 dark:border-vega-dark-200 lg:border-l lg:border-r',
'antialiased text-black dark:text-white',
'overflow-hidden relative'
)}
@@ -61,13 +59,13 @@ export const Layout = () => {
)}
<Header />
</div>
<div className={fixedWidthClasses}>
<div>
<main className="p-4">
{!isHome && <BreadcrumbsContainer className="mb-4" />}
<Outlet />
</main>
</div>
<div className={fixedWidthClasses}>
<div>
<Footer />
</div>
</div>
@@ -1,5 +1,5 @@
import { t } from '@vegaprotocol/i18n';
import { useDataProvider } from '@vegaprotocol/data-provider';
import { useDataProvider } from '@vegaprotocol/react-helpers';
import { AsyncRenderer, Button } from '@vegaprotocol/ui-toolkit';
import { useState } from 'react';
import { useParams } from 'react-router-dom';
@@ -49,7 +49,6 @@ export const MarketPage = () => {
/>
<AsyncRenderer
noDataMessage={t('This chain has no markets')}
errorMessage={t('Could not fetch market') + ' ' + marketId}
data={data}
loading={loading}
error={error}
@@ -4,7 +4,7 @@ import { marketsProvider } from '@vegaprotocol/market-list';
import { RouteTitle } from '../../components/route-title';
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/i18n';
import { useDataProvider } from '@vegaprotocol/data-provider';
import { useDataProvider } from '@vegaprotocol/react-helpers';
import { MarketsTable } from '../../components/markets/markets-table';
export const MarketsPage = () => {
@@ -1,5 +1,5 @@
import { render, screen } from '@testing-library/react';
import type { NetworkParamsQuery } from '@vegaprotocol/network-parameters';
import type { NetworkParamsQuery } from '@vegaprotocol/react-helpers';
import { NetworkParametersTable } from './network-parameters';
describe('NetworkParametersTable', () => {
@@ -13,15 +13,14 @@ import {
import { t } from '@vegaprotocol/i18n';
import { RouteTitle } from '../../components/route-title';
import orderBy from 'lodash/orderBy';
import { useNetworkParamsQuery } from '@vegaprotocol/network-parameters';
import type { NetworkParamsQuery } from '@vegaprotocol/network-parameters';
import { useNetworkParamsQuery } from '@vegaprotocol/react-helpers';
import type { NetworkParamsQuery } from '@vegaprotocol/react-helpers';
import { useScrollToLocation } from '../../hooks/scroll-to-location';
import { useDocumentTitle } from '../../hooks/use-document-title';
const PERCENTAGE_PARAMS = [
'governance.proposal.asset.requiredMajority',
'governance.proposal.asset.requiredParticipation',
'governance.proposal.updateAsset.requiredParticipation',
'governance.proposal.freeform.requiredMajority',
'governance.proposal.freeform.requiredParticipation',
'governance.proposal.market.requiredMajority',
@@ -54,8 +53,6 @@ const BIG_NUMBER_PARAMS = [
'governance.proposal.asset.minProposerBalance',
'governance.proposal.market.minProposerBalance',
'governance.proposal.market.minVoterBalance',
'governance.proposal.updateAsset.minProposerBalance',
'governance.proposal.updateAsset.minVoterBalance',
];
export const NetworkParameterRow = ({
@@ -1,4 +1,4 @@
import { AsyncRenderer, SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
import { Loader, SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
import { RouteTitle } from '../../../components/route-title';
import { t } from '@vegaprotocol/i18n';
import { useExplorerOracleSpecsQuery } from '../__generated__/Oracles';
@@ -8,7 +8,7 @@ import { useScrollToLocation } from '../../../hooks/scroll-to-location';
import filter from 'recursive-key-filter';
const Oracles = () => {
const { data, loading, error } = useExplorerOracleSpecsQuery();
const { data, loading } = useExplorerOracleSpecsQuery();
useDocumentTitle(['Oracles']);
useScrollToLocation();
@@ -16,40 +16,28 @@ const Oracles = () => {
return (
<section>
<RouteTitle data-testid="oracle-specs-heading">{t('Oracles')}</RouteTitle>
<AsyncRenderer
data={data}
loading={loading}
error={error}
loadingMessage={t('Loading oracle data...')}
errorMessage={t('Oracle data could not be loaded')}
noDataMessage={t('No oracles found')}
noDataCondition={(data) =>
!data?.oracleSpecsConnection?.edges ||
data.oracleSpecsConnection.edges?.length === 0
}
>
{data?.oracleSpecsConnection?.edges
? data.oracleSpecsConnection.edges.map((o) => {
const id = o?.node.dataSourceSpec.spec.id;
if (!id) {
return null;
}
return (
<div id={id} key={id} className="mb-10">
<OracleDetails
id={id}
dataSource={o?.node}
showBroadcasts={false}
/>
<details>
<summary className="pointer">JSON</summary>
<SyntaxHighlighter data={filter(o, ['__typename'])} />
</details>
</div>
);
})
: null}
</AsyncRenderer>
{loading ? <Loader /> : null}
{data?.oracleSpecsConnection?.edges
? data.oracleSpecsConnection.edges.map((o) => {
const id = o?.node.dataSourceSpec.spec.id;
if (!id) {
return null;
}
return (
<div id={id} key={id} className="mb-10">
<OracleDetails
id={id}
dataSource={o?.node}
showBroadcasts={false}
/>
<details>
<summary className="pointer">JSON</summary>
<SyntaxHighlighter data={filter(o, ['__typename'])} />
</details>
</div>
);
})
: null}
</section>
);
};
@@ -1,11 +1,12 @@
import { RouteTitle } from '../../../components/route-title';
import { RenderFetched } from '../../../components/render-fetched';
import { truncateByChars } from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n';
import { useDocumentTitle } from '../../../hooks/use-document-title';
import { useParams } from 'react-router-dom';
import { useExplorerOracleSpecByIdQuery } from '../__generated__/Oracles';
import { OracleDetails } from '../components/oracle';
import { AsyncRenderer, SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
import { SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
import filter from 'recursive-key-filter';
import { TruncateInline } from '../../../components/truncate/truncate';
@@ -26,14 +27,7 @@ export const Oracle = () => {
{t(`Oracle `)}
<TruncateInline startChars={5} endChars={5} text={id || '1'} />
</RouteTitle>
<AsyncRenderer
data={data}
error={error}
loading={loading}
noDataCondition={(data) => !data?.oracleSpec}
errorMessage={t('Could not load oracle data')}
loadingMessage={t('Loading oracle data...')}
>
<RenderFetched error={error} loading={loading}>
{data?.oracleSpec ? (
<div id={id} key={id} className="mb-10">
<OracleDetails
@@ -50,7 +44,7 @@ export const Oracle = () => {
) : (
<span></span>
)}
</AsyncRenderer>
</RenderFetched>
</section>
);
};
@@ -48,13 +48,6 @@ query ExplorerPartyAssets($partyId: ID!) {
}
stakingSummary {
currentStakeAvailable
linkings(pagination: { first: 100 }) {
edges {
node {
amount
}
}
}
}
accountsConnection {
edges {
@@ -10,7 +10,7 @@ export type ExplorerPartyAssetsQueryVariables = Types.Exact<{
}>;
export type ExplorerPartyAssetsQuery = { __typename?: 'Query', partiesConnection?: { __typename?: 'PartyConnection', edges: Array<{ __typename?: 'PartyEdge', node: { __typename?: 'Party', id: string, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string, name: string } } } | null> | null } | null, stakingSummary: { __typename?: 'StakingSummary', currentStakeAvailable: string, linkings: { __typename?: 'StakesConnection', edges?: Array<{ __typename?: 'StakeLinkingEdge', node: { __typename?: 'StakeLinking', amount: string } } | null> | null } }, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', name: string, id: string, decimals: number, symbol: string, source: { __typename: 'BuiltinAsset' } | { __typename: 'ERC20', contractAddress: string } }, market?: { __typename?: 'Market', id: string, decimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } } } } | null } } | null> | null } | null } }> } | null };
export type ExplorerPartyAssetsQuery = { __typename?: 'Query', partiesConnection?: { __typename?: 'PartyConnection', edges: Array<{ __typename?: 'PartyEdge', node: { __typename?: 'Party', id: string, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string, name: string } } } | null> | null } | null, stakingSummary: { __typename?: 'StakingSummary', currentStakeAvailable: string }, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', name: string, id: string, decimals: number, symbol: string, source: { __typename: 'BuiltinAsset' } | { __typename: 'ERC20', contractAddress: string } }, market?: { __typename?: 'Market', id: string, decimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } } } } | null } } | null> | null } | null } }> } | null };
export const ExplorerPartyAssetsAccountsFragmentDoc = gql`
fragment ExplorerPartyAssetsAccounts on AccountBalance {
@@ -64,13 +64,6 @@ export const ExplorerPartyAssetsDocument = gql`
}
stakingSummary {
currentStakeAvailable
linkings(pagination: {first: 100}) {
edges {
node {
amount
}
}
}
}
accountsConnection {
edges {
@@ -1,24 +0,0 @@
import { t } from '@vegaprotocol/i18n';
import { useParams } from 'react-router-dom';
import { toNonHex } from '../../../../components/search/detect-search';
import { PageHeader } from '../../../../components/page-header';
import { useDocumentTitle } from '../../../../hooks/use-document-title';
import { PartyAccounts } from '../components/party-accounts';
const PartyAccountsByAsset = () => {
const { party } = useParams<{ party: string }>();
useDocumentTitle(['Public keys', party || '-']);
const partyId = toNonHex(party ? party : '');
return (
<section>
<PageHeader title={t('Balances by asset')} />
<PartyAccounts partyId={partyId} />
</section>
);
};
export { PartyAccountsByAsset };
@@ -1,9 +1,32 @@
import { AccountManager } from '@vegaprotocol/accounts';
import { useCallback } from 'react';
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
import { t } from '@vegaprotocol/i18n';
import get from 'lodash/get';
import AssetBalance from '../../../../components/asset-balance/asset-balance';
import { AssetLink, MarketLink } from '../../../../components/links';
import { Table, TableRow } from '../../../../components/table';
import type * as Schema from '@vegaprotocol/types';
import type { ExplorerPartyAssetsAccountsFragment } from '../__generated__/Party-assets';
const accountTypeString: Record<Schema.AccountType, string> = {
ACCOUNT_TYPE_BOND: t('Bond'),
ACCOUNT_TYPE_EXTERNAL: t('External'),
ACCOUNT_TYPE_FEES_INFRASTRUCTURE: t('Fees (Infrastructure)'),
ACCOUNT_TYPE_FEES_LIQUIDITY: t('Fees (Liquidity)'),
ACCOUNT_TYPE_FEES_MAKER: t('Fees (Maker)'),
ACCOUNT_TYPE_GENERAL: t('General'),
ACCOUNT_TYPE_GLOBAL_INSURANCE: t('Global Insurance Pool'),
ACCOUNT_TYPE_GLOBAL_REWARD: t('Global Reward Pool'),
ACCOUNT_TYPE_INSURANCE: t('Insurance'),
ACCOUNT_TYPE_MARGIN: t('Margin'),
ACCOUNT_TYPE_PENDING_TRANSFERS: t('Pending Transfers'),
ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES: t('Reward - LP Fees received'),
ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES: t('Reward - Maker fees paid'),
ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES: t('Reward - Maker fees received'),
ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS: t('Reward - Market proposers'),
ACCOUNT_TYPE_SETTLEMENT: t('Settlement'),
};
interface PartyAccountsProps {
partyId: string;
accounts: ExplorerPartyAssetsAccountsFragment[];
}
/**
@@ -11,22 +34,49 @@ interface PartyAccountsProps {
* probably do with sorting by asset, and then within asset, by type with general
* appearing first and... tbd
*/
export const PartyAccounts = ({ partyId }: PartyAccountsProps) => {
const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore();
const onClickAsset = useCallback(
(assetId?: string) => {
assetId && openAssetDetailsDialog(assetId);
},
[openAssetDetailsDialog]
);
export const PartyAccounts = ({ accounts }: PartyAccountsProps) => {
return (
<div className="block min-h-44 h-60 4 w-full border-red-800 relative">
<AccountManager
partyId={partyId}
onClickAsset={onClickAsset}
isReadOnly={true}
/>
</div>
<Table className="max-w-5xl min-w-fit">
<thead>
<TableRow modifier="bordered" className="font-mono">
<td>{t('Type')}</td>
<td>{t('Market')}</td>
<td className="text-right pr-2">{t('Balance')}</td>
<td>{t('Asset')}</td>
</TableRow>
</thead>
<tbody>
{accounts.map((account) => {
const m = get(account, 'market.tradableInstrument.instrument.name');
return (
<TableRow
key={`pa-${account.asset.id}-${account.type}`}
title={account.asset.name}
id={`${accountTypeString[account.type]} ${m ? ` - ${m}` : ''}`}
>
<td className="text-md">{accountTypeString[account.type]}</td>
<td className="text-md">
{account.market?.id ? (
<MarketLink id={account.market?.id} />
) : (
<p>-</p>
)}
</td>
<td className="text-md text-right pr-2">
<AssetBalance
assetId={account.asset.id}
price={account.balance}
showAssetLink={false}
/>
</td>
<td className="text-md">
<AssetLink assetId={account.asset.id} />
</td>
</TableRow>
);
})}
</tbody>
</Table>
);
};
@@ -1,63 +0,0 @@
import { t } from '@vegaprotocol/i18n';
import { useNavigate } from 'react-router-dom';
import { Routes } from '../../../../routes/route-names';
import { Button, Icon, Loader } from '@vegaprotocol/ui-toolkit';
import { PartyBlock } from './party-block';
import type { AccountFields } from '@vegaprotocol/accounts';
export interface PartyBlockAccountProps {
partyId: string;
accountData: AccountFields[] | null;
accountLoading: boolean;
accountError?: Error;
}
/**
* Displays an overview of a party's assets. This uses existing data
* providers to structure the details by asset, rather than looking at
* it by account. The assumption is that this is a more natural way to
* get an idea of the assets and activity of a party.
*/
export const PartyBlockAccounts = ({
partyId,
accountData,
accountLoading,
accountError,
}: PartyBlockAccountProps) => {
const navigate = useNavigate();
const shouldShowActionButton =
accountData && accountData.length > 0 && !accountLoading && !accountError;
const action = shouldShowActionButton ? (
<Button
size="sm"
onClick={() => navigate(`/${Routes.PARTIES}/${partyId}/assets`)}
>
{t('Show all')}
</Button>
) : null;
return (
<PartyBlock title={t('Assets')} action={action}>
{accountData && accountData.length > 0 ? (
<p>
{accountData.length} {t('assets, including')}{' '}
{accountData
.map((a) => a.asset.symbol)
.slice(0, 3)
.join(', ')}
</p>
) : accountLoading && !accountError ? (
<Loader size="small" />
) : accountData && accountData.length === 0 ? (
<p>{t('No accounts found')}</p>
) : (
<p>
<Icon className="mr-1" name="error" />
<span className="text-sm">{t('Could not load assets')}</span>
</p>
)}
</PartyBlock>
);
};
@@ -1,83 +0,0 @@
import { t } from '@vegaprotocol/i18n';
import { useExplorerPartyAssetsQuery } from '../__generated__/Party-assets';
import GovernanceAssetBalance from '../../../../components/asset-balance/governance-asset-balance';
import {
Icon,
KeyValueTable,
KeyValueTableRow,
Loader,
} from '@vegaprotocol/ui-toolkit';
import { PartyBlock } from './party-block';
import BigNumber from 'bignumber.js';
export interface PartyBlockStakeProps {
partyId: string;
accountLoading: boolean;
accountError?: Error;
}
/**
* Displays an overview of a single party's staking balance, importantly maintaining'
* the same height before and after the details are loaded in.
*
* Unlike PartyBlockAccounts there is not action button in the title of this block as
* there is no page for it to link to currently. That's a future task.
*/
export const PartyBlockStake = ({
partyId,
accountLoading,
accountError,
}: PartyBlockStakeProps) => {
const partyRes = useExplorerPartyAssetsQuery({
// Don't cache data for this query, party information can move quite quickly
fetchPolicy: 'network-only',
variables: { partyId: partyId },
skip: !partyId,
});
const p = partyRes.data?.partiesConnection?.edges[0].node;
const linkedLength = p?.stakingSummary?.linkings?.edges?.length;
const linkedStake =
linkedLength && linkedLength > 0
? p?.stakingSummary?.linkings?.edges
?.reduce((total, e) => {
return new BigNumber(total).plus(
new BigNumber(e?.node.amount || 0)
);
}, new BigNumber(0))
.toString()
: '0';
return (
<PartyBlock title={t('Staking')}>
{p?.stakingSummary.currentStakeAvailable ? (
<KeyValueTable>
<KeyValueTableRow noBorder={true}>
<div>{t('Available stake')}</div>
<div>
<GovernanceAssetBalance
price={p.stakingSummary.currentStakeAvailable}
/>
</div>
</KeyValueTableRow>
<KeyValueTableRow noBorder={true}>
<div>{t('Active stake')}</div>
<div>
<GovernanceAssetBalance price={linkedStake || '0'} />
</div>
</KeyValueTableRow>
</KeyValueTable>
) : accountLoading && !accountError ? (
<Loader size="small" />
) : !accountError ? (
<p>{t('No staking balance')}</p>
) : (
<p>
<Icon className="mr-1" name="error" />
<span className="text-sm">{t('Could not load stake details')}</span>
</p>
)}
</PartyBlock>
);
};
@@ -1,24 +0,0 @@
import type { ReactNode } from 'react';
export interface PartyBlockProps {
children: ReactNode;
title: string;
action?: ReactNode;
}
export function PartyBlock({ children, title, action }: PartyBlockProps) {
return (
<div className="border-2 min-h-[138px] border-solid border-vega-light-100 dark:border-vega-dark-200 p-5 mt-5">
<div
className="flex flex-col md:flex-row gap-1 justify-between content-start mb-2"
data-testid="page-title"
>
<h3 className="font-semibold text-lg">{title}</h3>
{action ? action : null}
</div>
{children}
</div>
);
}
@@ -1,26 +1,24 @@
import { getNodes } from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n';
import { useScreenDimensions } from '@vegaprotocol/react-helpers';
import { useMemo } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { useParams } from 'react-router-dom';
import { SubHeading } from '../../../components/sub-heading';
import { Panel } from '../../../components/panel';
import { toNonHex } from '../../../components/search/detect-search';
import { useTxsData } from '../../../hooks/use-txs-data';
import { TxsInfiniteList } from '../../../components/txs';
import { PageHeader } from '../../../components/page-header';
import { useExplorerPartyAssetsQuery } from './__generated__/Party-assets';
import type { ExplorerPartyAssetsAccountsFragment } from './__generated__/Party-assets';
import { useDocumentTitle } from '../../../hooks/use-document-title';
import { Icon, Intent, Notification, Splash } from '@vegaprotocol/ui-toolkit';
import { aggregatedAccountsDataProvider } from '@vegaprotocol/accounts';
import { PartyBlockStake } from './components/party-block-stake';
import { PartyBlockAccounts } from './components/party-block-accounts';
import { isValidPartyId } from './components/party-id-error';
import { useDataProvider } from '@vegaprotocol/data-provider';
import GovernanceAssetBalance from '../../../components/asset-balance/governance-asset-balance';
import { PartyAccounts } from './components/party-accounts';
const Party = () => {
const { party } = useParams<{ party: string }>();
useDocumentTitle(['Public keys', party || '-']);
const navigate = useNavigate();
const partyId = toNonHex(party ? party : '');
const { isMobile } = useScreenDimensions();
const visibleChars = useMemo(() => (isMobile ? 10 : 14), [isMobile]);
@@ -30,72 +28,71 @@ const Party = () => {
filters,
});
const variables = useMemo(() => ({ partyId }), [partyId]);
const {
data: AccountData,
loading: AccountLoading,
error: AccountError,
} = useDataProvider({
dataProvider: aggregatedAccountsDataProvider,
variables,
const partyRes = useExplorerPartyAssetsQuery({
// Don't cache data for this query, party information can move quite quickly
fetchPolicy: 'network-only',
variables: { partyId: partyId },
skip: !party,
});
if (!isValidPartyId(partyId)) {
return (
<div className="max-w-sm mx-auto">
<Notification
message={t('Invalid party ID')}
intent={Intent.Danger}
buttonProps={{
text: t('Go back'),
action: () => navigate(-1),
className: 'py-1',
size: 'sm',
}}
/>
</div>
);
}
const p = partyRes.data?.partiesConnection?.edges[0].node;
const header = p?.id ? (
<PageHeader
title={p.id}
copy
truncateStart={visibleChars}
truncateEnd={visibleChars}
/>
) : (
<Panel>
<p>No data found for public key {party}</p>
</Panel>
);
const staking = (
<section>
{p?.stakingSummary?.currentStakeAvailable ? (
<div className="mt-4 leading-3">
<strong className="font-semibold">{t('Staking Balance: ')}</strong>
<GovernanceAssetBalance
price={p.stakingSummary.currentStakeAvailable}
/>
</div>
) : null}
</section>
);
const accounts = getNodes<ExplorerPartyAssetsAccountsFragment>(
p?.accountsConnection
);
return (
<section>
<PageHeader
title={partyId}
copy
truncateStart={visibleChars}
truncateEnd={visibleChars}
/>
<h1
className="font-alpha calt uppercase font-xl mb-4 text-vega-dark-100 dark:text-vega-light-100"
data-testid="parties-header"
>
{t('Public key')}
</h1>
{partyRes.data ? (
<>
{header}
<SubHeading>{t('Asset data')}</SubHeading>
{accounts ? <PartyAccounts accounts={accounts} /> : null}
{staking}
<div className="grid md:grid-flow-col grid-flow-row md:space-x-4 grid-cols-1 md:grid-cols-2 w-full">
<PartyBlockAccounts
accountError={AccountError}
accountLoading={AccountLoading}
accountData={AccountData}
partyId={partyId}
/>
<PartyBlockStake
accountError={AccountError}
accountLoading={AccountLoading}
partyId={partyId}
/>
</div>
<SubHeading>{t('Transactions')}</SubHeading>
{!error && txsData ? (
<TxsInfiniteList
hasMoreTxs={hasMoreTxs}
areTxsLoading={loading}
txs={txsData}
loadMoreTxs={loadTxs}
error={error}
className="mb-28"
/>
) : (
<Splash>
<Icon name="error" className="mr-1" />
&nbsp;{t('Could not load transaction list for party')}
</Splash>
)}
<SubHeading>{t('Transactions')}</SubHeading>
<TxsInfiniteList
hasMoreTxs={hasMoreTxs}
areTxsLoading={loading}
txs={txsData}
loadMoreTxs={loadTxs}
error={error}
className="mb-28"
/>
</>
) : null}
</section>
);
};
@@ -1,7 +0,0 @@
import { Outlet } from 'react-router-dom';
const PartiesSubPage = () => {
return <Outlet />;
};
export default PartiesSubPage;
@@ -0,0 +1,35 @@
import React from 'react';
import { DATA_SOURCES } from '../../config';
import type { TendermintUnconfirmedTransactionsResponse } from '../txs/tendermint-unconfirmed-transactions-response.d';
import { TxList } from '../../components/txs';
import { RouteTitle } from '../../components/route-title';
import { t } from '@vegaprotocol/i18n';
import { useFetch } from '@vegaprotocol/react-helpers';
import { useDocumentTitle } from '../../hooks/use-document-title';
const PendingTxs = () => {
const {
state: { data: unconfirmedTransactions },
} = useFetch<TendermintUnconfirmedTransactionsResponse>(
`${DATA_SOURCES.tendermintUrl}/unconfirmed_txs`
);
useDocumentTitle(['Pending transactions']);
return (
<section>
<RouteTitle data-testid="unconfirmed-transactions-header">
{t('Unconfirmed transactions')}
</RouteTitle>
<br />
<div>{t(`Number: ${unconfirmedTransactions?.result?.n_txs || 0}`)}</div>
<br />
<div>
<br />
<TxList data={unconfirmedTransactions} />
</div>
</section>
);
};
export { PendingTxs };
+20 -38
View File
@@ -14,6 +14,7 @@ import { Block } from './blocks/id';
import { Blocks } from './blocks/home';
import { Tx } from './txs/id';
import { TxsList } from './txs/home';
import { PendingTxs } from './pending';
import flags from '../config/flags';
import { t } from '@vegaprotocol/i18n';
import { Routes } from './route-names';
@@ -28,7 +29,6 @@ import compact from 'lodash/compact';
import { AssetLink, MarketLink } from '../components/links';
import { truncateMiddle } from '@vegaprotocol/ui-toolkit';
import { remove0x } from '@vegaprotocol/utils';
import { PartyAccountsByAsset } from './parties/id/accounts';
export type Navigable = {
path: string;
@@ -75,43 +75,14 @@ const partiesRoutes: Route[] = flags.parties
},
{
path: ':party',
element: <Party />,
children: [
{
index: true,
element: <PartySingle />,
handle: {
breadcrumb: (params: Params<string>) => (
<Link to={linkTo(Routes.PARTIES, params.party)}>
{truncateMiddle(params.party as string)}
</Link>
),
},
},
{
path: 'assets',
element: <Party />,
handle: {
breadcrumb: (params: Params<string>) => (
<Link to={linkTo(Routes.PARTIES, params.party)}>
{truncateMiddle(params.party as string)}
</Link>
),
},
children: [
{
index: true,
element: <PartyAccountsByAsset />,
handle: {
breadcrumb: () => {
return t('Assets');
},
},
},
],
},
],
element: <PartySingle />,
handle: {
breadcrumb: (params: Params<string>) => (
<Link to={linkTo(Routes.PARTIES, params.party)}>
{truncateMiddle(params.party as string)}
</Link>
),
},
},
],
},
@@ -266,6 +237,17 @@ export const routerConfig: Route[] = [
breadcrumb: () => <Link to={Routes.TX}>{t('Transactions')}</Link>,
},
children: [
{
path: 'pending',
element: <PendingTxs />,
handle: {
breadcrumb: () => (
<Link to={linkTo(Routes.TX, 'pending')}>
{t('Pending transactions')}
</Link>
),
},
},
{
path: ':txHash',
element: <Tx />,
@@ -10,7 +10,7 @@ interface TxDetailsProps {
export const txDetailsTruncateLength = 30;
export const TxDetails = ({ txData, pubKey }: TxDetailsProps) => {
export const TxDetails = ({ txData, pubKey, className }: TxDetailsProps) => {
if (!txData) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
@@ -28,7 +28,6 @@ import {
} from '@vegaprotocol/environment';
import classNames from 'classnames';
import { NodeStatus, NodeStatusMapping } from '@vegaprotocol/types';
import { PartyLink } from '../../components/links';
type RateProps = {
value: BigNumber | number | undefined;
@@ -192,9 +191,7 @@ export const ValidatorsPage = () => {
<KeyValueTable>
<KeyValueTableRow>
<div>{t('ID')}</div>
<div className="break-all text-xs font-mono">
{v.id}
</div>
<div className="break-all text-xs">{v.id}</div>
</KeyValueTableRow>
<KeyValueTableRow>
<div>{t('Status')}</div>
@@ -221,14 +218,12 @@ export const ValidatorsPage = () => {
</div>
</KeyValueTableRow>
<KeyValueTableRow>
<div>{t('Key')}</div>
<div className="break-all text-xs">
<PartyLink id={v.pubkey} />
</div>
<div>{t('Public key')}</div>
<div className="break-all text-xs">{v.pubkey}</div>
</KeyValueTableRow>
<KeyValueTableRow>
<div>{t('Ethereum address')}</div>
<div className="break-all text-xs font-mono">
<div className="break-all text-xs">
<EtherscanLink address={v.ethereumAddress} />{' '}
<CopyWithTooltip text={v.ethereumAddress}>
<button title={t('Copy address to clipboard')}>
@@ -239,9 +234,7 @@ export const ValidatorsPage = () => {
</KeyValueTableRow>
<KeyValueTableRow>
<div>{t('Tendermint public key')}</div>
<div className="break-all text-xs font-mono">
{v.tmPubkey}
</div>
<div className="break-all text-xs">{v.tmPubkey}</div>
</KeyValueTableRow>
<KeyValueTableRow>
-49
View File
@@ -1,7 +1,3 @@
@import 'ag-grid-community/dist/styles/ag-grid.css';
@import 'ag-grid-community/dist/styles/ag-theme-balham.css';
@import 'ag-grid-community/dist/styles/ag-theme-balham-dark.css';
/* You can add global styles to this file, and also import other style files */
@tailwind base;
@tailwind components;
@@ -15,48 +11,3 @@
.react-markdown-container a:before {
content: '🔗 ';
}
/* AG GRID - Do not edit without updating other global stylesheets for each app */
.vega-ag-grid .ag-root-wrapper {
border: solid 0px;
}
.vega-ag-grid .ag-react-container {
overflow: hidden;
text-overflow: ellipsis;
}
.vega-ag-grid .ag-cell,
.vega-ag-grid .ag-full-width-row .ag-cell-wrapper.ag-row-group {
line-height: calc(min(var(--ag-line-height, 26px), 26px) - 4px);
}
.vega-ag-grid .ag-row {
border-width: 1px 0;
border-bottom: 1px solid transparent;
}
/* Light variables */
.ag-theme-balham {
--ag-background-color: theme(colors.white);
--ag-border-color: theme(colors.neutral[300]);
--ag-header-background-color: theme(colors.white);
--ag-odd-row-background-color: theme(colors.white);
--ag-header-column-separator-color: theme(colors.neutral[300]);
--ag-row-border-color: theme(colors.white);
--ag-row-hover-color: theme(colors.neutral[100]);
--ag-font-size: 12px;
}
/* Dark variables */
.ag-theme-balham-dark {
--ag-background-color: theme(colors.black);
--ag-border-color: theme(colors.neutral[700]);
--ag-header-background-color: theme(colors.black);
--ag-odd-row-background-color: theme(colors.black);
--ag-header-column-separator-color: theme(colors.neutral[600]);
--ag-row-border-color: theme(colors.black);
--ag-row-hover-color: theme(colors.neutral[800]);
--ag-font-size: 12px;
}
+6 -7
View File
@@ -5,22 +5,20 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_FAIRGROUND=false
NX_VEGA_NETWORKS={}
NX_VEGA_URL=http://localhost:3008/graphql
NX_VEGA_URL=http://localhost:3028/query
NX_ETHEREUM_CHAIN_ID=1440
NX_ETH_URL_CONNECT=1
NX_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit supply green clown session
NX_LOCAL_PROVIDER_URL=http://localhost:8545/
NX_ETH_LOCAL_PROVIDER_URL=http://localhost:8545/
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet3-k8s.ops.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
#Test configuration variables
CYPRESS_FAIRGROUND=false
CYPRESS_VEGA_URL=http://localhost:3008/graphql
CYPRESS_VEGA_URL=http://localhost:3028/query
CYPRESS_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit supply green clown session
CYPRESS_ETHEREUM_PROVIDER_URL=http://localhost:8545
CYPRESS_EXPLORER_URL=https://explorer.fairground.wtf
@@ -30,6 +28,7 @@ CYPRESS_TRUNCATED_VEGA_PUBLIC_KEY2=7f9cf0…c25535
CYPRESS_VEGA_ENV=CUSTOM
CYPRESS_VEGA_PUBLIC_KEY=02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65
CYPRESS_VEGA_PUBLIC_KEY2=7f9cf07d3a9905b1a61a1069f7a758855da428bc0f4a97de87f48644bfc25535
CYPRESS_VEGA_TOKEN_URL=https://governance.fairground.wtf
CYPRESS_VEGA_TOKEN_URL=https://token.fairground.wtf
CYPRESS_VEGA_URL=http://localhost:3028/query
CYPRESS_VEGA_WALLET_URL=http://localhost:1789
CYPRESS_VEGA_WALLET_API_TOKEN=
+1 -1
View File
@@ -1,5 +1,5 @@
# App configuration variables
NX_VEGA_ENV=MAINNET
NX_VEGA_URL=https://api.vega.community/graphql
NX_VEGA_URL=https://api.vega.xyz/query
NX_ETHEREUM_PROVIDER_URL=https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://etherscan.io
+5
View File
@@ -0,0 +1,5 @@
# App configuration variables
NX_VEGA_ENV=STAGNET3
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
+1 -1
View File
@@ -1,5 +1,5 @@
# App configuration variables
NX_VEGA_ENV=TESTNET
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
NX_VEGA_URL=https://api.n11.testnet.vega.xyz/graphql
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
-1
View File
@@ -25,7 +25,6 @@ module.exports = defineConfig({
viewportWidth: 1440,
viewportHeight: 900,
numTestsKeptInMemory: 5,
testIsolation: false,
},
env: {
ethProviderUrl: 'http://localhost:8545/',
@@ -1,38 +0,0 @@
export const upgradeProposalsData = {
lastBlockHeight: '2014133',
protocolUpgradeProposals: {
edges: [
{
node: {
upgradeBlockHeight: '2015942',
vegaReleaseTag: 'v1',
approvers: [
'02a6531716b7a6d82779b7793c3ad2fcb47290ea2ff0912c56f61219bd9675ff',
'121934387281812a2d5e6913e5d57c0f85a8f169e2752347ee2e23b52d46623c',
'65c80e2f5f84e2109eec30810f137ba04cbbecaba8f27706c146cc6c6f90db29',
'bd6339d2428c79ac3bc9011771236d17bac92bcb1806423388d52fb440043aef',
],
status: 'PROTOCOL_UPGRADE_PROPOSAL_STATUS_APPROVED',
__typename: 'ProtocolUpgradeProposal',
},
__typename: 'ProtocolUpgradeProposalEdge',
},
{
node: {
upgradeBlockHeight: '1955065',
vegaReleaseTag: 'v0.71.0+dev-12156-bca1d57e',
approvers: [
'02a6531716b7a6d82779b7793c3ad2fcb47290ea2ff0912c56f61219bd9675ff',
'121934387281812a2d5e6913e5d57c0f85a8f169e2752347ee2e23b52d46623c',
'65c80e2f5f84e2109eec30810f137ba04cbbecaba8f27706c146cc6c6f90db29',
'bd6339d2428c79ac3bc9011771236d17bac92bcb1806423388d52fb440043aef',
],
status: 'PROTOCOL_UPGRADE_PROPOSAL_STATUS_APPROVED',
__typename: 'ProtocolUpgradeProposal',
},
__typename: 'ProtocolUpgradeProposalEdge',
},
],
__typename: 'ProtocolUpgradeProposalConnection',
},
};
@@ -1,117 +0,0 @@
export const nodeData = {
epoch: {
id: '204731',
timestamps: {
start: '2023-04-14T09:30:09.452005Z',
end: null,
expiry: '2023-04-14T09:31:09.452005Z',
__typename: 'EpochTimestamps',
},
__typename: 'Epoch',
},
nodesConnection: {
edges: [
{
node: {
avatarUrl:
'https://www.gravatar.com/avatar/y2hwc4xjds7zvlam3y4in94q2rcdimsn?d=identicon',
id: 'f337b5cc50c49a928e49129a2eca62277a81b4b7336b6e4131f8f0431e8db029',
name: 'lovely-fisherman',
pubkey:
'02a6531716b7a6d82779b7793c3ad2fcb47290ea2ff0912c56f61219bd9675ff',
stakedByOperator: '3000000000000000000000',
stakedByDelegates: '0',
stakedTotal: '3000000000000000000000',
pendingStake: '0',
rankingScore: {
rankingScore: '0.4999166805532412',
stakeScore: '0.2499583402766206',
performanceScore: '1',
votingPower: '2499',
status: 'VALIDATOR_NODE_STATUS_TENDERMINT',
__typename: 'RankingScore',
},
__typename: 'Node',
},
__typename: 'NodeEdge',
},
{
node: {
avatarUrl:
'https://www.gravatar.com/avatar/g1tw70qnoo0tf8ror30jefwhae92zy16?d=identicon',
id: 'cdadcf885556e372b6b39679d6ad46854d1d9c1e982da7ff2929544df01f9088',
name: 'magnificent-door',
pubkey:
'121934387281812a2d5e6913e5d57c0f85a8f169e2752347ee2e23b52d46623c',
stakedByOperator: '3000000000000000000000',
stakedByDelegates: '0',
stakedTotal: '3000000000000000000000',
pendingStake: '0',
rankingScore: {
rankingScore: '0.4999166805532412',
stakeScore: '0.2499583402766206',
performanceScore: '1',
votingPower: '2499',
status: 'VALIDATOR_NODE_STATUS_TENDERMINT',
__typename: 'RankingScore',
},
__typename: 'Node',
},
__typename: 'NodeEdge',
},
{
node: {
avatarUrl:
'https://www.gravatar.com/avatar/s2e7hp7soq5zdhxeap7p21onetsjiy6w?d=identicon',
id: '9a13de2548fef30d928e71e76004c98ec7ad9d8fc3ddcd16ddee210b28ea4cfc',
name: 'helpful-tree',
pubkey:
'bd6339d2428c79ac3bc9011771236d17bac92bcb1806423388d52fb440043aef',
stakedByOperator: '3000000000000000000000',
stakedByDelegates: '2000000000000000000',
stakedTotal: '3002000000000000000000',
pendingStake: '0',
rankingScore: {
rankingScore: '0.5002499583402766',
stakeScore: '0.2501249791701383',
performanceScore: '1',
votingPower: '2501',
status: 'VALIDATOR_NODE_STATUS_TENDERMINT',
__typename: 'RankingScore',
},
__typename: 'Node',
},
__typename: 'NodeEdge',
},
{
node: {
avatarUrl:
'https://www.gravatar.com/avatar/3gop683kg2cvd8rpv286hzagqt3yjsdq?d=identicon',
id: '93ac271ab95038333587e47d11461e6edc0126e6e77156281c545f4c5650a6d0',
name: 'easy-cookie',
pubkey:
'65c80e2f5f84e2109eec30810f137ba04cbbecaba8f27706c146cc6c6f90db29',
stakedByOperator: '3000000000000000000000',
stakedByDelegates: '0',
stakedTotal: '3000000000000000000000',
pendingStake: '0',
rankingScore: {
rankingScore: '0.4999166805532412',
stakeScore: '0.2499583402766206',
performanceScore: '1',
votingPower: '2499',
status: 'VALIDATOR_NODE_STATUS_TENDERMINT',
__typename: 'RankingScore',
},
__typename: 'Node',
},
__typename: 'NodeEdge',
},
],
__typename: 'NodesConnection',
},
nodeData: {
stakedTotal: '12002000000000000000000',
__typename: 'NodeData',
},
};
@@ -1,325 +0,0 @@
export const proposalsData = {
proposalsConnection: {
edges: [
{
node: {
id: 'e8ba9d268e12514644fd1fc7ff289292f4ce6489cc32cc73133aea52c04aef89',
rationale: {
title: 'Add asset Wrapped Ether',
description: 'Proposal to add asset WETH to Vega network',
__typename: 'ProposalRationale',
},
reference: '',
state: 'STATE_OPEN',
datetime: '2026-12-01T11:41:28.654288Z',
rejectionReason: null,
party: {
id: '69464e35bcb8e8a2900ca0f87acaf252d50cf2ab2fc73694845a16b7c8a0dc6f',
__typename: 'Party',
},
errorDetails: null,
terms: {
closingDatetime: '2026-12-01T11:45:33Z',
enactmentDatetime: '2026-12-01T11:45:43Z',
change: {
name: 'Wrapped Ether',
symbol: 'WETH',
decimals: 18,
quantum: '0.0008',
source: {
contractAddress: '0x9B18C6CaD886D5653783E2B25759124760F4407F',
withdrawThreshold: '1',
lifetimeLimit: '400000000000000000',
__typename: 'ERC20',
},
__typename: 'NewAsset',
},
__typename: 'ProposalTerms',
},
votes: {
yes: {
totalTokens: '0',
totalNumber: '0',
totalEquityLikeShareWeight: '0',
__typename: 'ProposalVoteSide',
},
no: {
totalTokens: '0',
totalNumber: '0',
totalEquityLikeShareWeight: '0',
__typename: 'ProposalVoteSide',
},
__typename: 'ProposalVotes',
},
__typename: 'Proposal',
},
__typename: 'ProposalEdge',
},
{
node: {
id: 'd848fc7881f13d366df5f61ab139d5fcfa72bf838151bb51b54381870e357931',
rationale: {
title: 'Add asset Dai Stablecoin',
description: 'Proposal to add asset DAI to Vega network',
__typename: 'ProposalRationale',
},
reference: '',
state: 'STATE_ENACTED',
datetime: '2022-11-29T15:49:57.80978Z',
rejectionReason: null,
party: {
id: '69464e35bcb8e8a2900ca0f87acaf252d50cf2ab2fc73694845a16b7c8a0dc6f',
__typename: 'Party',
},
errorDetails: null,
terms: {
closingDatetime: '2023-04-13T15:52:58Z',
enactmentDatetime: '2023-04-13T15:53:08Z',
change: {
name: 'Dai Stablecoin',
symbol: 'DAI',
decimals: 18,
quantum: '1',
source: {
contractAddress: '0xad018fB8ec00bfd622B91C83E684a6AC7bB8fbA4',
withdrawThreshold: '1',
lifetimeLimit: '500000000000000000000',
__typename: 'ERC20',
},
__typename: 'NewAsset',
},
__typename: 'ProposalTerms',
},
votes: {
yes: {
totalTokens: '0',
totalNumber: '0',
totalEquityLikeShareWeight: '0',
__typename: 'ProposalVoteSide',
},
no: {
totalTokens: '0',
totalNumber: '0',
totalEquityLikeShareWeight: '0',
__typename: 'ProposalVoteSide',
},
__typename: 'ProposalVotes',
},
__typename: 'Proposal',
},
__typename: 'ProposalEdge',
},
{
node: {
id: 'ccbd651b4a1167fd73c4a0340ac759fa0a31ca487ad46a13254b741ad71947ed',
rationale: {
title: 'New DAI market',
description: 'New DAI market',
__typename: 'ProposalRationale',
},
reference: '0VFQusmmESdrP5GuL8naB6lxfoE3RPGaEeo7abdN',
state: 'STATE_ENACTED',
datetime: '2022-11-26T19:36:19.26034Z',
rejectionReason: null,
party: {
id: '69464e35bcb8e8a2900ca0f87acaf252d50cf2ab2fc73694845a16b7c8a0dc6f',
__typename: 'Party',
},
errorDetails: null,
terms: {
closingDatetime: '2022-11-26T19:36:42Z',
enactmentDatetime: '2023-03-22T13:57:37Z',
change: {
instrument: {
name: 'UNIDAI Monthly (Dec 2022)',
code: 'UNIDAI.MF21',
futureProduct: {
settlementAsset: { symbol: 'tDAI', __typename: 'Asset' },
__typename: 'FutureProduct',
},
__typename: 'InstrumentConfiguration',
},
__typename: 'NewMarket',
},
__typename: 'ProposalTerms',
},
votes: {
yes: {
totalTokens: '0',
totalNumber: '0',
totalEquityLikeShareWeight: '0',
__typename: 'ProposalVoteSide',
},
no: {
totalTokens: '0',
totalNumber: '0',
totalEquityLikeShareWeight: '0',
__typename: 'ProposalVoteSide',
},
__typename: 'ProposalVotes',
},
__typename: 'Proposal',
},
__typename: 'ProposalEdge',
},
{
node: {
id: 'bc70383f0e9515b15542cf4c63590cd2ca46b3363ba7c4a72af0e62112b3951b',
rationale: {
title: 'USDC-III',
description: 'USDC-III D List test',
__typename: 'ProposalRationale',
},
reference: '',
state: 'STATE_ENACTED',
datetime: '2022-11-22T15:17:28.829605Z',
rejectionReason: null,
party: {
id: '69464e35bcb8e8a2900ca0f87acaf252d50cf2ab2fc73694845a16b7c8a0dc6f',
__typename: 'Party',
},
errorDetails: null,
terms: {
closingDatetime: '2022-11-22T15:18:56Z',
enactmentDatetime: '2022-11-22T15:19:06Z',
change: {
name: 'USDC-III',
symbol: 'USDC-III',
decimals: 18,
quantum: '1',
source: {
contractAddress: '0x1F1A067aEC530b66BA5128C9Db76825eC22c3C6b',
withdrawThreshold: '100000000000000000000000000',
lifetimeLimit: '1000000000000000000000000000',
__typename: 'ERC20',
},
__typename: 'NewAsset',
},
__typename: 'ProposalTerms',
},
votes: {
yes: {
totalTokens: '0',
totalNumber: '0',
totalEquityLikeShareWeight: '0',
__typename: 'ProposalVoteSide',
},
no: {
totalTokens: '0',
totalNumber: '0',
totalEquityLikeShareWeight: '0',
__typename: 'ProposalVoteSide',
},
__typename: 'ProposalVotes',
},
__typename: 'Proposal',
},
__typename: 'ProposalEdge',
},
{
node: {
id: '9d9b2a9d0179d0e4ccb317f6c4a5db0b905d893190bfb5e5499985ef313281c8',
rationale: {
title: 'New BTC market',
description: 'New BTC market',
__typename: 'ProposalRationale',
},
reference: 'AXeRWS3TvLBFDgWOSHQpKFJf3NTbnWK6310q02fZ',
state: 'STATE_ENACTED',
datetime: '2022-11-26T19:36:19.26034Z',
rejectionReason: null,
party: {
id: '69464e35bcb8e8a2900ca0f87acaf252d50cf2ab2fc73694845a16b7c8a0dc6f',
__typename: 'Party',
},
errorDetails: null,
terms: {
closingDatetime: '2022-11-26T19:36:42Z',
enactmentDatetime: '2023-03-22T13:57:37Z',
change: {
instrument: {
name: 'ETHBTC Quarterly (Feb 2023)',
code: 'ETHBTC.QM21',
futureProduct: {
settlementAsset: { symbol: 'tBTC', __typename: 'Asset' },
__typename: 'FutureProduct',
},
__typename: 'InstrumentConfiguration',
},
__typename: 'NewMarket',
},
__typename: 'ProposalTerms',
},
votes: {
yes: {
totalTokens: '0',
totalNumber: '0',
totalEquityLikeShareWeight: '0',
__typename: 'ProposalVoteSide',
},
no: {
totalTokens: '0',
totalNumber: '0',
totalEquityLikeShareWeight: '0',
__typename: 'ProposalVoteSide',
},
__typename: 'ProposalVotes',
},
__typename: 'Proposal',
},
__typename: 'ProposalEdge',
},
{
node: {
id: '9c48796e7988769ededc2b2b02220b00e93f65f23e8141bf1fd23a6983d95943',
rationale: {
title: 'Update governance.proposal.asset.requiredMajority',
description:
'Proposal to update governance.proposal.asset.requiredMajority to 300}',
__typename: 'ProposalRationale',
},
reference: '',
state: 'STATE_ENACTED',
datetime: '2022-11-22T13:22:52.370655Z',
rejectionReason: null,
party: {
id: '69464e35bcb8e8a2900ca0f87acaf252d50cf2ab2fc73694845a16b7c8a0dc6f',
__typename: 'Party',
},
errorDetails: null,
terms: {
closingDatetime: '2022-11-22T13:27:13Z',
enactmentDatetime: '2022-11-22T13:27:33Z',
change: {
networkParameter: {
key: 'governance.proposal.asset.requiredParticipation',
value: '0.000001',
__typename: 'NetworkParameter',
},
__typename: 'UpdateNetworkParameter',
},
__typename: 'ProposalTerms',
},
votes: {
yes: {
totalTokens: '0',
totalNumber: '0',
totalEquityLikeShareWeight: '0',
__typename: 'ProposalVoteSide',
},
no: {
totalTokens: '0',
totalNumber: '0',
totalEquityLikeShareWeight: '0',
__typename: 'ProposalVoteSide',
},
__typename: 'ProposalVotes',
},
__typename: 'Proposal',
},
__typename: 'ProposalEdge',
},
],
__typename: 'ProposalsConnection',
},
};
@@ -9,7 +9,7 @@
"name": "Token test market",
"code": "Token.24h",
"future": {
"settlementAsset": "73174a6fb1d5802ba0ac7bd7ab79e0a3a4837b262de0a4e80815a55442692bd0",
"settlementAsset": "fBTC",
"quoteName": "fBTC",
"dataSourceSpecForSettlementData": {
"external": {
@@ -2,14 +2,14 @@ import {
navigateTo,
waitForSpinner,
navigation,
turnTelemetryOff,
} from '../../support/common.functions';
import {
convertUnixTimestampToDateformat,
createRawProposal,
createTenDigitUnixTimeStampForSpecifiedDays,
enterUniqueFreeFormProposalBody,
generateFreeFormProposalTitle,
getDateFormatForSpecifiedDays,
getGovernanceProposalDateFormatForSpecifiedDays,
getProposalIdFromList,
getProposalInformationFromTable,
getSubmittedProposalFromProposalList,
@@ -23,7 +23,6 @@ import { ensureSpecifiedUnstakedTokensAreAssociated } from '../../../../governan
import { ethereumWalletConnect } from '../../../../governance-e2e/src/support/wallet-eth.functions';
import { vegaWalletSetSpecifiedApprovalAmount } from '../../../../governance-e2e/src/support/wallet-teardown.functions';
import type { testFreeformProposal } from '../../support/common-interfaces';
import { formatDateWithLocalTimezone } from '@vegaprotocol/utils';
const proposalVoteProgressForPercentage =
'[data-testid="vote-progress-indicator-percentage-for"]';
@@ -45,13 +44,10 @@ describe(
function () {
before('connect wallets and set approval limit', function () {
cy.visit('/');
ethereumWalletConnect();
cy.associateTokensToVegaWallet('1');
vegaWalletSetSpecifiedApprovalAmount('1000');
});
beforeEach('visit proposals tab', function () {
cy.clearLocalStorage();
turnTelemetryOff();
cy.reload();
waitForSpinner();
cy.connectVegaWallet();
@@ -101,22 +97,20 @@ describe(
getSubmittedProposalFromProposalList(proposalTitle).within(() =>
cy.get(viewProposalButton).click()
);
cy.wrap(
formatDateWithLocalTimezone(new Date(proposalTimeStamp * 1000))
).then((closingDate) => {
getProposalInformationFromTable('Closes on')
.contains(closingDate)
.should('be.visible');
});
cy.wrap(
formatDateWithLocalTimezone(
new Date(createTenDigitUnixTimeStampForSpecifiedDays(0) * 1000)
)
).then((proposalDate) => {
getProposalInformationFromTable('Proposed on')
.contains(proposalDate)
.should('be.visible');
});
convertUnixTimestampToDateformat(proposalTimeStamp).then(
(closingDate) => {
getProposalInformationFromTable('Closes on')
.contains(closingDate)
.should('be.visible');
}
);
getGovernanceProposalDateFormatForSpecifiedDays(0).then(
(proposalDate) => {
getProposalInformationFromTable('Proposed on')
.contains(proposalDate)
.should('be.visible');
}
);
});
it('Newly created proposal details - shows default status set to fail', function () {
@@ -159,16 +153,18 @@ describe(
cy.getByTestId('vote-buttons').contains('against').should('be.visible');
cy.getByTestId('vote-buttons').contains('for').should('be.visible');
voteForProposal('for');
getDateFormatForSpecifiedDays(0).then((votedDate) => {
// 3001-VOTE-051
// 3001-VOTE-093
cy.contains('You voted:')
.siblings()
.contains('For')
.siblings()
.contains(votedDate)
.should('be.visible');
});
getGovernanceProposalDateFormatForSpecifiedDays(0, 'shortMonth').then(
(votedDate) => {
// 3001-VOTE-051
// 3001-VOTE-093
cy.contains('You voted:')
.siblings()
.contains('For')
.siblings()
.contains(votedDate)
.should('be.visible');
}
);
cy.get(proposalVoteProgressForPercentage) // 3001-VOTE-072
.contains('100.00%')
.and('be.visible');
@@ -217,12 +213,11 @@ describe(
// 3001-VOTE-042, 3001-VOTE-057, 3001-VOTE-058, 3001-VOTE-059, 3001-VOTE-060
it('Newly created proposal details - ability to increase associated tokens - by voting again after association', function () {
vegaWalletSetSpecifiedApprovalAmount('1000');
createRawProposal();
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
getSubmittedProposalFromProposalList(
rawProposal.rationale.title
).within(() => cy.get(viewProposalButton).click());
getSubmittedProposalFromProposalList(rawProposal.rationale.title)
.as('submittedProposal')
.within(() => cy.get(viewProposalButton).click());
});
voteForProposal('for');
// 3001-VOTE-079
@@ -240,9 +235,9 @@ describe(
);
navigateTo(navigation.proposals);
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
getSubmittedProposalFromProposalList(
rawProposal.rationale.title
).within(() => cy.get(viewProposalButton).click());
getSubmittedProposalFromProposalList(rawProposal.rationale.title)
.as('submittedProposal')
.within(() => cy.get(viewProposalButton).click());
});
cy.get(proposalVoteProgressForPercentage)
.contains('100.00%')
@@ -2,7 +2,6 @@
import {
navigateTo,
navigation,
turnTelemetryOff,
waitForSpinner,
} from '../../support/common.functions';
import {
@@ -14,10 +13,10 @@ import {
createUpdateNetworkProposalTxBody,
createFreeFormProposalTxBody,
} from '../../support/proposal.functions';
import { ensureSpecifiedUnstakedTokensAreAssociated } from '../../support/staking.functions';
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
import { vegaWalletSetSpecifiedApprovalAmount } from '../../support/wallet-teardown.functions';
const proposalListItem = '[data-testid="proposals-list-item"]';
const closedProposals = '[data-testid="closed-proposals"]';
const proposalStatus = '[data-testid="proposal-status"]';
const viewProposalButton = '[data-testid="view-proposal-btn"]';
@@ -34,11 +33,13 @@ context(
before('Connect wallets and set approval', function () {
cy.visit('/');
vegaWalletSetSpecifiedApprovalAmount('1000');
cy.connectVegaWallet();
ethereumWalletConnect();
ensureSpecifiedUnstakedTokensAreAssociated('1');
cy.clearLocalStorage();
});
beforeEach('visit proposals', function () {
cy.clearLocalStorage();
turnTelemetryOff();
cy.reload();
waitForSpinner();
cy.connectVegaWallet();
@@ -55,8 +56,7 @@ context(
waitForSpinner();
cy.get(closedProposals).within(() => {
cy.contains(proposalTitle)
.parentsUntil(proposalListItem)
.last()
.parentsUntil('[data-testid="proposals-list-item"]')
.within(() => {
cy.get(proposalStatus).should('have.text', 'Enacted ');
cy.get(viewProposalButton).click();
@@ -83,8 +83,7 @@ context(
waitForSpinner();
cy.get(openProposals).within(() => {
cy.contains(proposalTitle)
.parentsUntil(proposalListItem)
.last()
.parentsUntil('[data-testid="proposals-list-item"]')
.within(() => cy.get(viewProposalButton).click());
});
getProposalInformationFromTable('State')
@@ -115,10 +114,9 @@ context(
navigateTo(navigation.proposals);
cy.reload();
waitForSpinner();
cy.get(openProposals, { timeout: 6000 }).within(() => {
cy.get(openProposals).within(() => {
cy.contains(proposalTitle)
.parentsUntil(proposalListItem)
.last()
.parentsUntil('[data-testid="proposals-list-item"]')
.within(() => cy.get(viewProposalButton).click());
});
getProposalInformationFromTable('State')
@@ -140,8 +138,7 @@ context(
waitForSpinner();
cy.get(openProposals).within(() => {
cy.contains(proposalTitle)
.parentsUntil(proposalListItem)
.last()
.parentsUntil('[data-testid="proposals-list-item"]')
.within(() => cy.get(viewProposalButton).click());
});
getProposalInformationFromTable('State')
@@ -20,7 +20,6 @@ import {
navigateTo,
navigation,
closeDialog,
turnTelemetryOff,
} from '../../support/common.functions';
import {
clickOnValidatorFromList,
@@ -85,8 +84,6 @@ context(
});
beforeEach('visit governance tab', function () {
cy.clearLocalStorage();
turnTelemetryOff();
cy.reload();
waitForSpinner();
cy.connectVegaWallet();
@@ -235,7 +232,7 @@ context(
it('Unable to create a freeform proposal - when json parent section contains unexpected field', function () {
const errorMsg =
'Invalid params: the transaction does not use a valid Vega command: unknown field "unexpected" in vega.commands.v1.ProposalSubmission';
'Invalid params: the transaction does not use a valid Vega command: unknown field unexpected" in vega.commands.v1.ProposalSubmission';
// 3001-VOTE-038 3002-PROP-013 3002-PROP-014
goToMakeNewProposal(governanceProposalType.RAW);
@@ -316,7 +313,7 @@ context(
it('Unable to vote on a proposal - when vega wallet disconnected - option to connect from within', function () {
createRawProposal();
cy.get('[data-testid="manage-vega-wallet"]:visible').click();
cy.get('[data-testid="manage-vega-wallet"]').click();
cy.get('[data-testid="disconnect"]').click();
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
getSubmittedProposalFromProposalList(
@@ -2,7 +2,6 @@ import {
closeDialog,
navigateTo,
navigation,
turnTelemetryOff,
waitForSpinner,
} from '../../support/common.functions';
import {
@@ -51,8 +50,6 @@ const liquidityVoteStatus = 'liquidity-votes-status';
const tokenVoteStatus = 'token-votes-status';
const proposalTermsSection = 'proposal';
const vegaWalletPublicKey = Cypress.env('vegaWalletPublicKey');
const fUSDCId =
'816af99af60d684502a40824758f6b5377e6af48e50a9ee8ef478ecb879ea8bc';
const epochTimeout = Cypress.env('epochTimeout');
const proposalTimeout = { timeout: 14000 };
@@ -77,8 +74,6 @@ context(
});
beforeEach('visit governance tab', function () {
cy.clearLocalStorage();
turnTelemetryOff();
cy.reload();
waitForSpinner();
cy.connectVegaWallet();
@@ -223,7 +218,7 @@ context(
it('Unable to submit new market proposal with missing/invalid fields', function () {
const errorMsg =
'Invalid params: the transaction does not use a valid Vega command: unknown field "invalid" in vega.NewMarket';
'Invalid params: the transaction is not a valid Vega command: unknown field "filters" in vega.DataSourceDefinition';
goToMakeNewProposal(governanceProposalType.NEW_MARKET);
cy.get(newProposalSubmitButton).should('be.visible').click();
@@ -269,7 +264,7 @@ context(
it('Unable to submit update market proposal without minimum amount of tokens', function () {
vegaWalletTeardown();
vegaWalletFaucetAssetsWithoutCheck(
fUSDCId,
'fUSDC',
'1000000',
vegaWalletPublicKey
);
@@ -295,7 +290,7 @@ context(
// 3001-VOTE-092 3004-PMAC-001
it('Able to submit update market proposal and vote for proposal', function () {
vegaWalletFaucetAssetsWithoutCheck(
fUSDCId,
'fUSDC',
'1000000',
vegaWalletPublicKey
);
@@ -307,10 +302,7 @@ context(
cy.get('dd').eq(0).should('have.text', 'Test market 1');
cy.get('dd').eq(1).should('have.text', 'TEST.24h');
cy.get('dd').eq(2).should('not.be.empty');
cy.get('dd')
.eq(2)
.invoke('text')
.as('EnactedMarketId', { type: 'static' });
cy.get('dd').eq(2).invoke('text').as('EnactedMarketId');
});
cy.get('@EnactedMarketId').then((marketId) => {
cy.VegaWalletSubmitLiquidityProvision(String(marketId), '1');
@@ -328,7 +320,6 @@ context(
cy.get('@EnactedMarketId').then((marketId) => {
cy.contains(String(marketId))
.parentsUntil(proposalListItem)
.last()
.within(() => {
cy.getByTestId(viewProposalBtn).click();
});
@@ -382,19 +373,16 @@ context(
cy.get(newProposalSubmitButton).should('be.visible').click();
// cannot submit a proposal with ERC20 address already in use
cy.contains('Proposal rejected', proposalTimeout).should('be.visible');
cy.getByTestId('dialog-content')
.last()
.within(() => {
cy.get('p').should(
'have.text',
'PROPOSAL_ERROR_ERC20_ADDRESS_ALREADY_IN_USE'
);
});
cy.getByTestId('dialog-content').within(() => {
cy.get('p').should(
'have.text',
'PROPOSAL_ERROR_ERC20_ADDRESS_ALREADY_IN_USE'
);
});
closeDialog();
navigateTo(navigation.proposals);
cy.contains(proposalTitle)
.parentsUntil(proposalListItem)
.last()
.within(() => {
cy.getByTestId(viewProposalBtn).click();
});
@@ -432,7 +420,6 @@ context(
cy.get(proposalType)
.contains('Update asset')
.parentsUntil(proposalListItem)
.last()
.within(() => {
cy.get(proposalDetails).should('contain.text', assetId); // 3001-VOTE-029
cy.getByTestId(viewProposalBtn).click();
@@ -449,7 +436,7 @@ context(
});
});
it('Able to submit update asset proposal using max deadline', function () {
it.only('Able to submit update asset proposal using max deadline', function () {
goToMakeNewProposal(governanceProposalType.UPDATE_ASSET);
enterUpdateAssetProposalDetails();
cy.get(maxVoteDeadline).click();
@@ -2,7 +2,6 @@ import type { testFreeformProposal } from '../../support/common-interfaces';
import {
navigateTo,
navigation,
turnTelemetryOff,
waitForSpinner,
} from '../../support/common.functions';
import {
@@ -13,6 +12,7 @@ import {
generateFreeFormProposalTitle,
getProposalIdFromList,
getProposalInformationFromTable,
getSortOrderOfSuppliedArray,
getSubmittedProposalFromProposalList,
goToMakeNewProposal,
governanceProposalType,
@@ -24,9 +24,9 @@ import { ensureSpecifiedUnstakedTokensAreAssociated } from '../../support/stakin
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
import { vegaWalletSetSpecifiedApprovalAmount } from '../../support/wallet-teardown.functions';
const proposalDetailsTitle = '[data-testid="proposal-title"]';
const openProposals = '[data-testid="open-proposals"]';
const voteStatus = '[data-testid="vote-status"]';
const proposalClosingDate = '[data-testid="vote-details"]';
const viewProposalButton = '[data-testid="view-proposal-btn"]';
describe('Governance flow for proposal list', { tags: '@slow' }, function () {
@@ -36,8 +36,6 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
});
beforeEach('visit proposals tab', function () {
cy.clearLocalStorage();
turnTelemetryOff();
cy.reload();
waitForSpinner();
cy.connectVegaWallet();
@@ -47,8 +45,16 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
});
it('Newly created proposals list - proposals closest to closing date appear higher in list', function () {
const minCloseDays = 2;
const maxCloseDays = 3;
// 3001-VOTE-005
const proposalDays = [364, 50, 2];
const proposalDays = [
minCloseDays + 1,
maxCloseDays,
minCloseDays + 3,
minCloseDays + 2,
];
for (let index = 0; index < proposalDays.length; index++) {
goToMakeNewProposal(governanceProposalType.RAW);
enterRawProposalBody(
@@ -58,15 +64,19 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
waitForProposalSync();
}
const arrayOfProposals: string[] = [];
navigateTo(navigation.proposals);
cy.get(openProposals).within(() => {
cy.get(proposalClosingDate).first().should('contain.text', 'year');
cy.get(proposalClosingDate).should('contain.text', 'months');
cy.get(proposalClosingDate)
.last()
.invoke('text')
.should('match', /days|minutes/);
});
cy.get(proposalDetailsTitle)
.each((proposalTitleElement) => {
arrayOfProposals.push(proposalTitleElement.text());
})
.then(() => {
cy.wrap(getSortOrderOfSuppliedArray(arrayOfProposals)).should(
'equal',
'descending'
);
});
});
it('Newly created proposals list - able to filter by proposerID to show it in list', function () {
@@ -1,7 +1,6 @@
import {
navigateTo,
navigation,
turnTelemetryOff,
waitForSpinner,
} from '../../support/common.functions';
import {
@@ -26,11 +25,9 @@ const rewardsTimeOut = { timeout: 60000 };
context('rewards - flow', { tags: '@slow' }, function () {
before('set up environment to allow rewards', function () {
cy.clearLocalStorage();
turnTelemetryOff();
cy.visit('/');
waitForSpinner();
depositAsset(vegaAssetAddress, '1000', 18);
depositAsset(vegaAssetAddress, '1000');
cy.validatorsSelfDelegate();
ethereumWalletConnect();
cy.connectVegaWallet();
@@ -59,7 +56,7 @@ context('rewards - flow', { tags: '@slow' }, function () {
cy.getByTestId(rewardsTable)
.first()
.within(() => {
cy.getByTestId('asset', rewardsTimeOut).should('have.text', 'Vega');
cy.getByTestId('asset').should('have.text', 'Vega');
cy.getByTestId('ACCOUNT_TYPE_GLOBAL_REWARD').should('have.text', '1');
cy.getByTestId('ACCOUNT_TYPE_FEES_INFRASTRUCTURE').should(
'have.text',
@@ -96,13 +93,13 @@ context('rewards - flow', { tags: '@slow' }, function () {
.within(() => {
cy.get('h2').first().should('contain.text', 'EPOCH');
cy.getByTestId('individual-rewards-asset').should('have.text', 'Vega');
cy.getByTestId('ACCOUNT_TYPE_GLOBAL_REWARD', rewardsTimeOut)
.should('contain.text', '0.4415')
.and('contain.text', '(44.15%)');
cy.getByTestId('ACCOUNT_TYPE_GLOBAL_REWARD')
.should('contain.text', '0.1177')
.and('contain.text', '(11.7733%)');
cy.getByTestId('ACCOUNT_TYPE_FEES_INFRASTRUCTURE')
.should('contain.text', '0.0004')
.and('contain.text', '(44.15%)');
cy.getByTestId('total').should('have.text', '0.4419');
.should('contain.text', '0.0001')
.and('contain.text', '(11.7733%)');
cy.getByTestId('total').should('have.text', '0.1179');
});
});
});

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