Compare commits
156
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a30cc6237 | ||
|
|
fff8fdd78b | ||
|
|
079d8bc48d | ||
|
|
9658363b56 | ||
|
|
e24289330e | ||
|
|
0fbd2bfa72 | ||
|
|
43ef4fad6f | ||
|
|
828dcf6e93 | ||
|
|
4a583ccf09 | ||
|
|
8bcad28f50 | ||
|
|
b375681076 | ||
|
|
8a2db407cf | ||
|
|
491844d3fd | ||
|
|
f1f51c5ecd | ||
|
|
9bc78f8ccd | ||
|
|
a03031a283 | ||
|
|
b499c293e3 | ||
|
|
65747e8d26 | ||
|
|
9a84eda21b | ||
|
|
fba98f2fd0 | ||
|
|
3e32d0f396 | ||
|
|
b75d189054 | ||
|
|
afa627864c | ||
|
|
b13a866b2a | ||
|
|
c65f07eee6 | ||
|
|
5bd18cc127 | ||
|
|
ff3519279d | ||
|
|
fd338c7400 | ||
|
|
0db5d0ce87 | ||
|
|
42c316c8e1 | ||
|
|
9e2474d39a | ||
|
|
2533e5ec44 | ||
|
|
22a43249ea | ||
|
|
b40ee0caf5 | ||
|
|
95aca70434 | ||
|
|
5e13266250 | ||
|
|
5c0588887c | ||
|
|
089a7daac7 | ||
|
|
02b6251b1a | ||
|
|
9ce8907861 | ||
|
|
3be9126906 | ||
|
|
77316092d1 | ||
|
|
fca229e62a | ||
|
|
162b167860 | ||
|
|
a4149cc55e | ||
|
|
4161a74eaf | ||
|
|
5008e57a56 | ||
|
|
89031bf826 | ||
|
|
61501d4d14 | ||
|
|
f8f3ce7df9 | ||
|
|
f7aab5a78a | ||
|
|
2904975fd3 | ||
|
|
4f55c946f0 | ||
|
|
de637fee13 | ||
|
|
69c6db8ec2 | ||
|
|
8dc465c1d1 | ||
|
|
0be934edca | ||
|
|
653688c1dd | ||
|
|
34400be18a | ||
|
|
d4a0a4a42c | ||
|
|
fabf643ce7 | ||
|
|
45e210092c | ||
|
|
1dc3b3fd05 | ||
|
|
0a80e3e39d | ||
|
|
7b8d9dc94b | ||
|
|
c0320c2468 | ||
|
|
11173d6614 | ||
|
|
e3324331e2 | ||
|
|
0a6e3cb6f5 | ||
|
|
68ede90609 | ||
|
|
09778a5d3f | ||
|
|
59993e3ea6 | ||
|
|
54161a6dba | ||
|
|
26f524ea07 | ||
|
|
db13e6f21d | ||
|
|
4a679813ba | ||
|
|
a4279d5b5e | ||
|
|
1a274a67c3 | ||
|
|
1e9ff31fd7 | ||
|
|
aa2b755b93 | ||
|
|
4a7296312a | ||
|
|
1418a2259f | ||
|
|
7e5ef0157a | ||
|
|
0cf764f11e | ||
|
|
1c626aeeb2 | ||
|
|
c4cec47b0b | ||
|
|
1a67c41bb4 | ||
|
|
fc66240390 | ||
|
|
fc0da98683 | ||
|
|
4d0dafb113 | ||
|
|
eda431be9e | ||
|
|
4ff1749e54 | ||
|
|
e7a108fd7a | ||
|
|
5d3f2ea7d8 | ||
|
|
1ab27574ca | ||
|
|
0ea3c43e78 | ||
|
|
9e183568b0 | ||
|
|
69fd5b26b6 | ||
|
|
2d5b926609 | ||
|
|
98a2ba79a8 | ||
|
|
0e6e986937 | ||
|
|
15d6ea0c05 | ||
|
|
0358ce6293 | ||
|
|
0791be4636 | ||
|
|
07442848ee | ||
|
|
d5f0bd419e | ||
|
|
2c7934a8c7 | ||
|
|
fae61c28ca | ||
|
|
fcd4541625 | ||
|
|
8e0a92fdec | ||
|
|
6e7109ed87 | ||
|
|
f2c698ce06 | ||
|
|
ad9a3a3400 | ||
|
|
efeac49d58 | ||
|
|
2d430710ab | ||
|
|
bca1a98985 | ||
|
|
8a080d3279 | ||
|
|
f121836b4e | ||
|
|
b641c82ad8 | ||
|
|
bf73559c30 | ||
|
|
653cec2592 | ||
|
|
579c884a5a | ||
|
|
b2279c7e47 | ||
|
|
a8c17b6807 | ||
|
|
b4c7dc6f59 | ||
|
|
d44392bebf | ||
|
|
bd679957e2 | ||
|
|
e30d48555e | ||
|
|
b4b2416780 | ||
|
|
dc7832ac81 | ||
|
|
91207d31ee | ||
|
|
58efb460a6 | ||
|
|
044f98777b | ||
|
|
00fdc5e81a | ||
|
|
adfad3bafb | ||
|
|
e6ae88905c | ||
|
|
3953ed9953 | ||
|
|
b48ab58e6a | ||
|
|
e44cf1ff53 | ||
|
|
bded1d32ba | ||
|
|
76ddf45f4c | ||
|
|
6a2c9004d8 | ||
|
|
77ee88b43e | ||
|
|
e4958ce3c0 | ||
|
|
ecedb879f8 | ||
|
|
89700803d6 | ||
|
|
65c9fa5df2 | ||
|
|
02399c40fc | ||
|
|
2cb3b55a3b | ||
|
|
3acc0e2401 | ||
|
|
c734556eb4 | ||
|
|
792ff1fc1f | ||
|
|
3740a97d7e | ||
|
|
20350ae2cf | ||
|
|
50e93dad64 | ||
|
|
c87c4bbc91 |
@@ -0,0 +1,74 @@
|
|||||||
|
name: After Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
after-release:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
timeout-minutes: 30
|
||||||
|
steps:
|
||||||
|
- 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
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: resolve ipfs hashes for release
|
||||||
|
run: |
|
||||||
|
echo "Tag name: ${{ github.event.release.tag_name }}"
|
||||||
|
echo "Name: ${{ github.event.release.name }}"
|
||||||
|
echo "Description: ${{ github.event.release.body }}"
|
||||||
|
until docker pull vegaprotocol/trading:${{ github.event.release.tag_name }}; do
|
||||||
|
echo "Image not pushed yet, waiting 60 seconds"
|
||||||
|
sleep 60
|
||||||
|
done
|
||||||
|
docker run --rm vegaprotocol/trading:${{ github.event.release.tag_name }} cat /ipfs-hash > ipfs-hash
|
||||||
|
curl -L https://dist.ipfs.tech/kubo/v0.20.0/kubo_v0.20.0_linux-amd64.tar.gz -o kubo.tgz
|
||||||
|
tar -xzf kubo.tgz
|
||||||
|
export PATH="$PATH:$PWD/kubo"
|
||||||
|
which ipfs
|
||||||
|
echo IPFS_V0=$(cat ipfs-hash) >> $GITHUB_ENV
|
||||||
|
echo IPFS_V1=$(ipfs cid format -v 1 -b base32 $(cat ipfs-hash)) >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Edit Release
|
||||||
|
uses: irongut/EditRelease@v1.2.0
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
id: ${{ github.event.release.id }}
|
||||||
|
body: |
|
||||||
|
---
|
||||||
|
|
||||||
|
# Deployments
|
||||||
|
* https://explorer.vega.xyz
|
||||||
|
* https://governance.vega.xyz
|
||||||
|
|
||||||
|
# IPFS releases
|
||||||
|
Tye IPFS hash of this release of the Trading app is:
|
||||||
|
|
||||||
|
CIDv0: ${{ env.IPFS_V0 }}
|
||||||
|
CIDv1: ${{ env.IPFS_V1 }}
|
||||||
|
|
||||||
|
You can always access the latest IPFS release by visiting [vega.trading](https://vega.trading).
|
||||||
|
|
||||||
|
You can also access Trading directly from an IPFS gateway.
|
||||||
|
BEWARE: The Trading interface uses [localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) to remember your settings, such as which tokens you have imported. You should always use an IPFS gateway that enforces [origin separation](https://ipfs.github.io/public-gateway-checker/).
|
||||||
|
|
||||||
|
Your settings are not remembered across different URLs.
|
||||||
|
|
||||||
|
IPFS gateways:
|
||||||
|
|
||||||
|
https://${{ env.IPFS_V1 }}.ipfs.dweb.link/
|
||||||
|
https://${{ env.IPFS_V1 }}.ipfs.cf-ipfs.com/
|
||||||
|
ipfs://${{ env.IPFS_V0 }}/
|
||||||
@@ -5,6 +5,8 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- release/*
|
- release/*
|
||||||
- develop
|
- develop
|
||||||
|
tags:
|
||||||
|
- v*
|
||||||
pull_request:
|
pull_request:
|
||||||
types:
|
types:
|
||||||
- opened
|
- opened
|
||||||
@@ -96,38 +98,37 @@ jobs:
|
|||||||
# See affected apps
|
# See affected apps
|
||||||
- name: See affected apps
|
- name: See affected apps
|
||||||
run: |
|
run: |
|
||||||
|
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 )"
|
||||||
|
|
||||||
echo ">>>> debug"
|
echo ">>>> debug"
|
||||||
echo "NX Version: $nx_version"
|
|
||||||
echo "NX_BASE: ${{ env.NX_BASE }}"
|
echo "NX_BASE: ${{ env.NX_BASE }}"
|
||||||
echo "NX_HEAD: ${{ env.NX_HEAD }}"
|
echo "NX_HEAD: ${{ env.NX_HEAD }}"
|
||||||
|
echo "Affected: ${affected}"
|
||||||
|
echo "Branch slug: ${branch_slug}"
|
||||||
echo ">>>> eof debug"
|
echo ">>>> eof debug"
|
||||||
|
|
||||||
affected="$(yarn nx print-affected --base=${{ env.NX_BASE }} --head=${{ env.NX_HEAD }} --select=projects)"
|
|
||||||
echo -n "Affected projects: $affected"
|
|
||||||
|
|
||||||
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=""
|
projects_e2e=""
|
||||||
preview_governance="not deployed"
|
preview_governance="not deployed"
|
||||||
preview_trading="not deployed"
|
preview_trading="not deployed"
|
||||||
preview_explorer="not deployed"
|
preview_explorer="not deployed"
|
||||||
|
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
|
||||||
if [[ -z "$projects_e2e" ]]; then
|
if [[ -z "$projects_e2e" ]]; then
|
||||||
projects_e2e+='"governance-e2e" "trading-e2e" "explorer-e2e" '
|
projects_e2e+='"governance-e2e" "trading-e2e" "explorer-e2e" '
|
||||||
preview_governance=$(printf "https://%s.%s.vega.rocks" "governance" "$branch_slug")
|
preview_governance=$(printf "https://%s.%s.vega.rocks" "governance" "$branch_slug")
|
||||||
preview_trading=$(printf "https://%s.%s.vega.rocks" "trading" "$branch_slug")
|
preview_trading=$(printf "https://%s.%s.vega.rocks" "trading" "$branch_slug")
|
||||||
preview_explorer=$(printf "https://%s.%s.vega.rocks" "explorer" "$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
|
fi
|
||||||
projects_e2e=${projects_e2e%?}
|
projects_e2e=${projects_e2e%?}
|
||||||
projects_e2e=[${projects_e2e// /,}]
|
projects_e2e=[${projects_e2e// /,}]
|
||||||
|
|||||||
@@ -33,5 +33,4 @@ jobs:
|
|||||||
config: baseUrl=${{ github.event.inputs.url }}
|
config: baseUrl=${{ github.event.inputs.url }}
|
||||||
env: grepTags=@live
|
env: grepTags=@live
|
||||||
env:
|
env:
|
||||||
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ jobs:
|
|||||||
project: ${{ fromJSON(inputs.projects) }}
|
project: ${{ fromJSON(inputs.projects) }}
|
||||||
name: ${{ matrix.project }}
|
name: ${{ matrix.project }}
|
||||||
runs-on: self-hosted-runner
|
runs-on: self-hosted-runner
|
||||||
timeout-minutes: 40
|
timeout-minutes: 60
|
||||||
steps:
|
steps:
|
||||||
# Checks if skip cache was requested
|
# Checks if skip cache was requested
|
||||||
- name: Set skip-nx-cache flag
|
- name: Set skip-nx-cache flag
|
||||||
@@ -66,7 +66,7 @@ jobs:
|
|||||||
######
|
######
|
||||||
|
|
||||||
- name: Run Cypress tests
|
- name: Run Cypress tests
|
||||||
run: yarn nx run ${{ matrix.project }}:e2e ${{ env.SKIP_CACHE }} --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome --env.grepTags="${{ inputs.tags }}"
|
run: yarn nx run ${{ matrix.project }}:e2e ${{ env.SKIP_CACHE }} --browser chrome --env.grepTags="${{ inputs.tags }}"
|
||||||
working-directory: frontend-monorepo
|
working-directory: frontend-monorepo
|
||||||
env:
|
env:
|
||||||
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
|
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
|
||||||
@@ -98,4 +98,4 @@ jobs:
|
|||||||
if: ${{ failure() }}
|
if: ${{ failure() }}
|
||||||
with:
|
with:
|
||||||
name: test-report-${{ matrix.project }}
|
name: test-report-${{ matrix.project }}
|
||||||
path: frontend-monorepo/apps/trading-e2e/cypress/reports
|
path: frontend-monorepo/apps/${{ matrix.project }}/cypress/reports
|
||||||
|
|||||||
@@ -30,13 +30,21 @@ jobs:
|
|||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
- name: Log in to the Container registry
|
- name: Log in to the Container registry (ghcr)
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
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
|
- name: Setup node
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
@@ -54,30 +62,26 @@ jobs:
|
|||||||
- name: Define variables
|
- name: Define variables
|
||||||
run: |
|
run: |
|
||||||
envName=''
|
envName=''
|
||||||
dockerfile="dist.Dockerfile"
|
domain="vega.rocks"
|
||||||
if [[ "${{ github.event_name }}" = "push" ]]; then
|
if [[ "${{ github.event_name }}" = "push" ]]; then
|
||||||
domain="vega.rocks"
|
|
||||||
if [[ "${{ github.ref }}" =~ .*release/.* ]]; then
|
if [[ "${{ github.ref }}" =~ .*release/.* ]]; then
|
||||||
envName="$(echo ${{ github.ref }} | rev | cut -d '/' -f 1 | rev)"
|
envName="$(echo ${{ github.ref }} | rev | cut -d '/' -f 1 | rev)"
|
||||||
if [[ "${{ github.ref }}" =~ .*mainnet.* ]]; then
|
|
||||||
domain="vega.community"
|
|
||||||
if [[ "${{ matrix.app }}" = "trading" ]]; then
|
|
||||||
dockerfile="ipfs.Dockerfile"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
elif [[ "${{ github.ref }}" =~ .*develop$ ]]; then
|
elif [[ "${{ github.ref }}" =~ .*develop$ ]]; then
|
||||||
envName="stagnet1"
|
envName="stagnet1"
|
||||||
|
elif [[ "${{ matrix.app}}" = "trading" ]] && [[ ${{ startsWith(github.ref, 'refs/tags/v') && 'true' || 'false' }} = "true" ]]; then
|
||||||
|
envName="mainnet"
|
||||||
|
elif [[ "${{ github.ref }}" =~ .*main$ ]]; then
|
||||||
|
envName="mainnet"
|
||||||
|
fi
|
||||||
|
if [[ "${envName}" = "mainnet" ]]; then
|
||||||
|
domain="vega.xyz"
|
||||||
fi
|
fi
|
||||||
bucketName="${{ matrix.app }}.${envName}.${domain}"
|
bucketName="${{ matrix.app }}.${envName}.${domain}"
|
||||||
echo BUCKET_NAME=${bucketName} >> $GITHUB_ENV
|
echo BUCKET_NAME=${bucketName} >> $GITHUB_ENV
|
||||||
fi
|
fi
|
||||||
nodeVersion=$(cat .nvmrc | head -n 1)
|
|
||||||
echo ENV_NAME=${envName} >> $GITHUB_ENV
|
echo ENV_NAME=${envName} >> $GITHUB_ENV
|
||||||
echo NODE_VERSION=${nodeVersion} >> $GITHUB_ENV
|
|
||||||
echo DOCKERFILE=docker/${dockerfile} >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Build local dist
|
- name: Build local dist
|
||||||
if: ${{ env.DOCKERFILE != 'docker/ipfs.Dockerfile' }}
|
|
||||||
run: |
|
run: |
|
||||||
flags=""
|
flags=""
|
||||||
if [[ ! -z "${{ env.ENV_NAME }}" ]]; then
|
if [[ ! -z "${{ env.ENV_NAME }}" ]]; then
|
||||||
@@ -98,62 +102,60 @@ jobs:
|
|||||||
|
|
||||||
- name: Build and export to local Docker
|
- name: Build and export to local Docker
|
||||||
id: docker_build
|
id: docker_build
|
||||||
if: ${{ github.event_name == 'pull_request' || ( env.DOCKERFILE == 'docker/ipfs.Dockerfile' && github.event_name == 'push' ) }}
|
|
||||||
uses: docker/build-push-action@v3
|
uses: docker/build-push-action@v3
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ${{ env.DOCKERFILE }}
|
file: docker/node-outside-docker.Dockerfile
|
||||||
load: true
|
load: true
|
||||||
build-args: |
|
build-args: |
|
||||||
APP=${{ matrix.app }}
|
APP=${{ matrix.app }}
|
||||||
NODE_VERSION=${{ env.NODE_VERSION }}
|
|
||||||
ENV_NAME=${{ env.ENV_NAME }}
|
ENV_NAME=${{ env.ENV_NAME }}
|
||||||
tags: |
|
tags: |
|
||||||
ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local
|
ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local
|
||||||
|
|
||||||
- name: Image digest
|
- name: Image digest
|
||||||
if: ${{ github.event_name == 'pull_request' || ( env.DOCKERFILE == 'docker/ipfs.Dockerfile' && github.event_name == 'push' ) }}
|
if: ${{ github.event_name == 'pull_request' }}
|
||||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
run: echo ${{ steps.docker_build.outputs.digest }}
|
||||||
|
|
||||||
- name: Sanity check docker image
|
- name: Sanity check docker image
|
||||||
if: ${{ github.event_name == 'pull_request' || ( env.DOCKERFILE == 'docker/ipfs.Dockerfile' && github.event_name == 'push' ) }}
|
|
||||||
run: |
|
run: |
|
||||||
echo "Check ipfs-hash"
|
echo "Check ipfs-hash"
|
||||||
if [[ "${{ env.DOCKERFILE }}" = "docker/ipfs.Dockerfile" ]]; then
|
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
|
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local cat /ipfs-hash > ${{ matrix.app }}-ipfs-hash
|
||||||
fi
|
|
||||||
|
|
||||||
echo "List html directory"
|
echo "List html directory"
|
||||||
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local sh -c 'apk add --update tree; tree .'
|
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local sh -c 'apk add --update tree; tree /usr/share/nginx/html'
|
||||||
|
|
||||||
- name: Copy dist to local filesystem
|
- name: Publish dist as docker image (ghcr)
|
||||||
if: ${{ env.DOCKERFILE == 'docker/ipfs.Dockerfile' && github.event_name == 'push' }}
|
|
||||||
run: |
|
|
||||||
docker create --name=dist ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local
|
|
||||||
docker cp dist:/usr/share/nginx/html dist
|
|
||||||
|
|
||||||
echo "check local dist files"
|
|
||||||
tree dist/html
|
|
||||||
mv dist/html dist-result
|
|
||||||
|
|
||||||
- name: Publish dist as docker image
|
|
||||||
uses: docker/build-push-action@v3
|
uses: docker/build-push-action@v3
|
||||||
if: ${{ github.event_name == 'pull_request' }}
|
if: ${{ github.event_name == 'pull_request' || (matrix.app == 'trading' && github.event_name == 'push' && !startsWith(github.ref, 'refs/tags/v') ) }}
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: ${{ env.DOCKERFILE }}
|
file: docker/node-outside-docker.Dockerfile
|
||||||
push: true
|
push: true
|
||||||
build-args: |
|
build-args: |
|
||||||
APP=${{ matrix.app }}
|
APP=${{ matrix.app }}
|
||||||
NODE_VERSION=${{ env.NODE_VERSION }}
|
|
||||||
ENV_NAME=${{ env.ENV_NAME }}
|
ENV_NAME=${{ env.ENV_NAME }}
|
||||||
tags: |
|
tags: |
|
||||||
ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:${{ github.event.pull_request.head.sha || github.sha }}
|
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 }}
|
||||||
|
vegaprotocol/${{ matrix.app }}:mainnet
|
||||||
|
|
||||||
# bucket creation in github.com/vegaprotocol/terraform//frontend
|
# bucket creation in github.com/vegaprotocol/terraform//frontend
|
||||||
- name: Publish dist to s3
|
- name: Publish dist to s3
|
||||||
uses: jakejarvis/s3-sync-action@master
|
uses: jakejarvis/s3-sync-action@master
|
||||||
if: ${{ github.event_name == 'push' }}
|
if: ${{ github.event_name == 'push' && !startsWith(github.ref, 'refs/tags/v') }}
|
||||||
with:
|
with:
|
||||||
args: --acl private --follow-symlinks --delete
|
args: --acl private --follow-symlinks --delete
|
||||||
env:
|
env:
|
||||||
@@ -169,3 +171,52 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
labels: ${{ matrix.app }}-preview
|
labels: ${{ matrix.app }}-preview
|
||||||
number: ${{ github.event.number }}
|
number: ${{ github.event.number }}
|
||||||
|
|
||||||
|
- name: Trigger fleek deployment
|
||||||
|
if: ${{ matrix.app == 'trading' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
|
||||||
|
run: |
|
||||||
|
# display info about app
|
||||||
|
curl -H "Authorization: ${{ secrets.FLEEK_API_KEY }}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"query": "query{getSiteById(siteId:\"f8f2e051-f18e-49e6-b876-0a39369dc0d8\"){id latestDeploy{id status}}}"}' \
|
||||||
|
https://api.fleek.co/graphql
|
||||||
|
|
||||||
|
# trigger new deployment as base image is always set to vegaprotocol/trading:mainnet
|
||||||
|
curl -H "Authorization: ${{ secrets.FLEEK_API_KEY }}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"query": "mutation{triggerDeploy(siteId:\"f8f2e051-f18e-49e6-b876-0a39369dc0d8\"){id status}}"}' \
|
||||||
|
https://api.fleek.co/graphql
|
||||||
|
|
||||||
|
- name: Update vega.trading DNS to redirect to the new console
|
||||||
|
if: ${{ matrix.app == 'trading' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
|
||||||
|
run: |
|
||||||
|
curl -L https://dist.ipfs.tech/kubo/v0.20.0/kubo_v0.20.0_linux-amd64.tar.gz -o kubo.tgz
|
||||||
|
tar -xzf kubo.tgz
|
||||||
|
export PATH="$PATH:$PWD/kubo"
|
||||||
|
which ipfs
|
||||||
|
new_hash=$(cat ${{ matrix.app }}-ipfs-hash)
|
||||||
|
new_cid=$(ipfs cid format -v 1 -b base32 $new_hash)
|
||||||
|
|
||||||
|
# Generate console URL
|
||||||
|
new_console_url_type=ipfs
|
||||||
|
# new_console_url_type=ipns
|
||||||
|
new_console_url_domain=cf-ipfs.com
|
||||||
|
# new_console_url_domain=dweb.link
|
||||||
|
new_console_url="https://${new_cid}.${new_console_url_type}.${new_console_url_domain}/"
|
||||||
|
echo "new_console_url=${new_console_url}"
|
||||||
|
|
||||||
|
# Update record in DNSimple
|
||||||
|
# docs: https://developer.dnsimple.com/v2/zones/records/#updateZoneRecord
|
||||||
|
dnsimple_account_id=84895
|
||||||
|
dnsimple_zone_name=vega.trading
|
||||||
|
dnsimple_record_id=44409591
|
||||||
|
# see: https://dnsimple.com/a/84895/domains/vega.trading/records/44409591/edit
|
||||||
|
|
||||||
|
curl -H 'Authorization: Bearer ${{ secrets.DNSIMPLE_API_TOKEN }}' \
|
||||||
|
-H 'Accept: application/json' \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
-X PATCH \
|
||||||
|
-d "{
|
||||||
|
\"content\": \"${new_console_url}\"
|
||||||
|
}" \
|
||||||
|
https://api.dnsimple.com/v2/${dnsimple_account_id}/zones/${dnsimple_zone_name}/records/${dnsimple_record_id}
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
name: 'Rollback console'
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
version:
|
||||||
|
description: 'Version that should be set on rollback'
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
rollback:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
timeout-minutes: 10
|
||||||
|
steps:
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
|
- name: Log in to the Container registry (docker hub)
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Retag mainnet
|
||||||
|
run: |
|
||||||
|
docker pull vegaprotocol/trading:${{ inputs.version }}
|
||||||
|
docker tag vegaprotocol/trading:${{ inputs.version }} vegaprotocol/trading:mainnet
|
||||||
|
docker push vegaprotocol/trading:mainnet
|
||||||
|
docker run --rm vegaprotocol/trading:mainnet cat /ipfs-hash > ipfs-hash
|
||||||
|
|
||||||
|
- name: Trigger fleek deployment
|
||||||
|
run: |
|
||||||
|
# display info about app
|
||||||
|
curl -H "Authorization: ${{ secrets.FLEEK_API_KEY }}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"query": "query{getSiteById(siteId:\"f8f2e051-f18e-49e6-b876-0a39369dc0d8\"){id latestDeploy{id status}}}"}' \
|
||||||
|
https://api.fleek.co/graphql
|
||||||
|
|
||||||
|
# trigger new deployment as base image is always set to vegaprotocol/trading:mainnet
|
||||||
|
curl -H "Authorization: ${{ secrets.FLEEK_API_KEY }}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"query": "mutation{triggerDeploy(siteId:\"f8f2e051-f18e-49e6-b876-0a39369dc0d8\"){id status}}"}' \
|
||||||
|
https://api.fleek.co/graphql
|
||||||
|
|
||||||
|
- name: Update vega.trading DNS to redirect to the new console
|
||||||
|
run: |
|
||||||
|
curl -L https://dist.ipfs.tech/kubo/v0.20.0/kubo_v0.20.0_linux-amd64.tar.gz -o kubo.tgz
|
||||||
|
tar -xzf kubo.tgz
|
||||||
|
export PATH="$PATH:$PWD/kubo"
|
||||||
|
which ipfs
|
||||||
|
new_hash=$(cat ipfs-hash)
|
||||||
|
new_cid=$(ipfs cid format -v 1 -b base32 $new_hash)
|
||||||
|
|
||||||
|
# Generate console URL
|
||||||
|
new_console_url_type=ipfs
|
||||||
|
# new_console_url_type=ipns
|
||||||
|
new_console_url_domain=cf-ipfs.com
|
||||||
|
# new_console_url_domain=dweb.link
|
||||||
|
new_console_url="https://${new_cid}.${new_console_url_type}.${new_console_url_domain}/"
|
||||||
|
echo "new_console_url=${new_console_url}"
|
||||||
|
|
||||||
|
# Update record in DNSimple
|
||||||
|
# docs: https://developer.dnsimple.com/v2/zones/records/#updateZoneRecord
|
||||||
|
dnsimple_account_id=84895
|
||||||
|
dnsimple_zone_name=vega.trading
|
||||||
|
dnsimple_record_id=44409591
|
||||||
|
# see: https://dnsimple.com/a/84895/domains/vega.trading/records/44409591/edit
|
||||||
|
|
||||||
|
curl -H 'Authorization: Bearer ${{ secrets.DNSIMPLE_API_TOKEN }}' \
|
||||||
|
-H 'Accept: application/json' \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
-X PATCH \
|
||||||
|
-d "{
|
||||||
|
\"content\": \"${new_console_url}\"
|
||||||
|
}" \
|
||||||
|
https://api.dnsimple.com/v2/${dnsimple_account_id}/zones/${dnsimple_zone_name}/records/${dnsimple_record_id}
|
||||||
+2
-1
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
# compiled output
|
# compiled output
|
||||||
/dist
|
/dist
|
||||||
|
/dist-result
|
||||||
/tmp
|
/tmp
|
||||||
/out-tsc
|
/out-tsc
|
||||||
/tools/executors/**/*.js
|
/tools/executors/**/*.js
|
||||||
@@ -48,4 +49,4 @@ cypress.env.json
|
|||||||
.next
|
.next
|
||||||
|
|
||||||
#cypress
|
#cypress
|
||||||
/apps/trading-e2e/cypress/reports/
|
/apps/**/cypress/reports/
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
.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 -r /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
|
||||||
@@ -103,25 +103,68 @@ 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.
|
Visit the [Nx Documentation](https://nx.dev/getting-started/intro) to learn more.
|
||||||
|
|
||||||
# Docker & Vegacapsule
|
# 🐋 Hosting a console
|
||||||
|
|
||||||
## Docker
|
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).
|
||||||
|
|
||||||
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.
|
In order to run a container on port 3000:
|
||||||
|
|
||||||
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
|
```bash
|
||||||
docker run -p 3000:80 [TAG]
|
docker run -p 3000:80 [TAG]
|
||||||
```
|
```
|
||||||
|
|
||||||
Images ending with `.dist` are to pack locally created transpiled HTML files into nginx container for non-compatible with yarn architectures like M1 Mac
|
## 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**
|
||||||
|
|
||||||
## Config
|
## Config
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
|
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_URL=https://mainnet-observer-proxy01.ops.vega.xyz/
|
||||||
NX_TENDERMINT_WEBSOCKET_URL=wss://mainnet-observer-proxy01.ops.vega.xyz/websocket
|
NX_TENDERMINT_WEBSOCKET_URL=wss://mainnet-observer-proxy01.ops.vega.xyz/websocket
|
||||||
NX_VEGA_URL=https://api.vega.xyz/query
|
NX_VEGA_URL=https://api.vega.community/graphql
|
||||||
NX_VEGA_ENV=MAINNET
|
NX_VEGA_ENV=MAINNET
|
||||||
NX_BLOCK_EXPLORER=https://be.explorer.vega.xyz/rest
|
NX_BLOCK_EXPLORER=https://be.explorer.vega.xyz/rest
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
const { defineConfig } = require('cypress');
|
const { defineConfig } = require('cypress');
|
||||||
|
|
||||||
module.exports = defineConfig({
|
module.exports = defineConfig({
|
||||||
projectId: 'et4snf',
|
reporter: '../../node_modules/cypress-mochawesome-reporter',
|
||||||
|
|
||||||
e2e: {
|
e2e: {
|
||||||
setupNodeEvents(on, config) {
|
setupNodeEvents(on, config) {
|
||||||
|
require('cypress-mochawesome-reporter/plugin')(on);
|
||||||
require('@cypress/grep/src/plugin')(config);
|
require('@cypress/grep/src/plugin')(config);
|
||||||
return config;
|
return config;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -15,5 +15,6 @@
|
|||||||
|
|
||||||
import '@vegaprotocol/cypress';
|
import '@vegaprotocol/cypress';
|
||||||
import './common.functions.js';
|
import './common.functions.js';
|
||||||
|
import 'cypress-mochawesome-reporter/register';
|
||||||
import registerCypressGrep from '@cypress/grep';
|
import registerCypressGrep from '@cypress/grep';
|
||||||
registerCypressGrep();
|
registerCypressGrep();
|
||||||
|
|||||||
+4
-2
@@ -4,15 +4,17 @@ 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_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
|
||||||
NX_VEGA_ENV=STAGNET1
|
NX_VEGA_ENV=STAGNET1
|
||||||
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
|
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
|
||||||
NX_VEGA_TOKEN_URL=https://stagnet1.token.vega.xyz
|
NX_VEGA_TOKEN_URL=https://stagnet1.governance.vega.xyz
|
||||||
NX_VEGA_WALLET_URL=http://localhost:1789
|
NX_VEGA_WALLET_URL=http://localhost:1789
|
||||||
NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.xyz
|
NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.xyz
|
||||||
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
|
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
|
||||||
NX_BLOCK_EXPLORER=https://be.stagnet1.vega.xyz/rest
|
NX_BLOCK_EXPLORER=https://be.stagnet1.vega.xyz/rest
|
||||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||||
NX_VEGA_GOVERNANCE_URL=https://stagnet1.token.vega.xyz
|
NX_VEGA_GOVERNANCE_URL=https://stagnet1.governance.vega.xyz
|
||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.jsoo
|
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_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||||
|
|
||||||
# App flags
|
# App flags
|
||||||
NX_EXPLORER_ASSETS=1
|
NX_EXPLORER_ASSETS=1
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-inter
|
|||||||
NX_VEGA_ENV=DEVNET
|
NX_VEGA_ENV=DEVNET
|
||||||
NX_BLOCK_EXPLORER=https://be.devnet1.vega.xyz/rest
|
NX_BLOCK_EXPLORER=https://be.devnet1.vega.xyz/rest
|
||||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||||
NX_VEGA_GOVERNANCE_URL=https://dev.token.vega.xyz
|
NX_VEGA_GOVERNANCE_URL=https://dev.governance.vega.xyz
|
||||||
NX_VEGA_URL=https://api.devnet1.vega.xyz/graphql
|
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_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_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||||
NX_VEGA_EXPLORER_URL=/
|
NX_VEGA_EXPLORER_URL=/
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
# App configuration variables
|
# App configuration variables
|
||||||
NX_TENDERMINT_URL=https://be.explorer.vega.xyz
|
NX_TENDERMINT_URL=https://be.vega.community
|
||||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.explorer.vega.xyz/websocket
|
NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket
|
||||||
|
NX_SENTRY_DSN=https://b3a56b03eda842faad731f3ea9dfd1bc@o286262.ingest.sentry.io/6242427
|
||||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/mainnet1/mainnet1.toml
|
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/mainnet1/mainnet1.toml
|
||||||
|
NX_VEGA_URL=https://api.vega.community/graphql
|
||||||
NX_VEGA_ENV=MAINNET
|
NX_VEGA_ENV=MAINNET
|
||||||
NX_BLOCK_EXPLORER=https://be.explorer.vega.xyz/rest/
|
NX_BLOCK_EXPLORER=https://be.vega.community/rest/
|
||||||
NX_ETHERSCAN_URL=https://etherscan.io
|
NX_ETHERSCAN_URL=https://etherscan.io
|
||||||
NX_VEGA_GOVERNANCE_URL=https://token.vega.xyz
|
NX_VEGA_GOVERNANCE_URL=https://governance.vega.xyz
|
||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
|
||||||
NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz/
|
NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz/
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
# .env is stagnet1, so there are no overrides required
|
# .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"}'
|
||||||
|
|||||||
@@ -7,6 +7,6 @@ NX_VEGA_ENV=TESTNET
|
|||||||
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
|
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
|
||||||
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
||||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||||
NX_VEGA_GOVERNANCE_URL=https://token.fairground.wtf
|
NX_VEGA_GOVERNANCE_URL=https://governance.fairground.wtf
|
||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||||
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
|||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||||
|
|
||||||
NX_VEGA_GOVERNANCE_URL=https://validator-testnet.governance.vega.xyz
|
NX_VEGA_GOVERNANCE_URL=https://validator-testnet.governance.vega.xyz
|
||||||
NX_TENDERMINT_URL=https://tm-be.validators-testnet.vega.rocks
|
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/rest
|
||||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.xyz/websocket
|
NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.xyz/websocket
|
||||||
NX_VEGA_EXPLORER_URL=https://validator-testnet.explorer.vega.xyz/
|
NX_VEGA_EXPLORER_URL=https://explorer.validators-testnet.vega.rocks/
|
||||||
@@ -1,9 +1,18 @@
|
|||||||
import { NetworkLoader, useInitializeEnv } from '@vegaprotocol/environment';
|
import {
|
||||||
|
AppFailure,
|
||||||
|
NetworkLoader,
|
||||||
|
NodeGuard,
|
||||||
|
NodeSwitcherDialog,
|
||||||
|
useEnvironment,
|
||||||
|
useInitializeEnv,
|
||||||
|
useNodeSwitcherStore,
|
||||||
|
} from '@vegaprotocol/environment';
|
||||||
import { TendermintWebsocketProvider } from './contexts/websocket/tendermint-websocket-provider';
|
import { TendermintWebsocketProvider } from './contexts/websocket/tendermint-websocket-provider';
|
||||||
import { Loader, Splash } from '@vegaprotocol/ui-toolkit';
|
import { Loader, Splash } from '@vegaprotocol/ui-toolkit';
|
||||||
import { DEFAULT_CACHE_CONFIG } from '@vegaprotocol/apollo-client';
|
import { DEFAULT_CACHE_CONFIG } from '@vegaprotocol/apollo-client';
|
||||||
import { RouterProvider } from 'react-router-dom';
|
import { RouterProvider } from 'react-router-dom';
|
||||||
import { router } from './routes/router-config';
|
import { router } from './routes/router-config';
|
||||||
|
import { t } from '@vegaprotocol/i18n';
|
||||||
|
|
||||||
const splashLoading = (
|
const splashLoading = (
|
||||||
<Splash>
|
<Splash>
|
||||||
@@ -12,10 +21,23 @@ const splashLoading = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
|
const { VEGA_URL } = useEnvironment();
|
||||||
|
const [nodeSwitcherOpen, setNodeSwitcherOpen] = useNodeSwitcherStore(
|
||||||
|
(store) => [store.dialogOpen, store.setDialogOpen]
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<TendermintWebsocketProvider>
|
<TendermintWebsocketProvider>
|
||||||
<NetworkLoader cache={DEFAULT_CACHE_CONFIG}>
|
<NetworkLoader cache={DEFAULT_CACHE_CONFIG}>
|
||||||
<RouterProvider router={router} fallbackElement={splashLoading} />
|
<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}
|
||||||
|
/>
|
||||||
</NetworkLoader>
|
</NetworkLoader>
|
||||||
</TendermintWebsocketProvider>
|
</TendermintWebsocketProvider>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,13 +1,19 @@
|
|||||||
import { NodeSwitcherDialog, useEnvironment } from '@vegaprotocol/environment';
|
import {
|
||||||
|
useEnvironment,
|
||||||
|
useNodeSwitcherStore,
|
||||||
|
} from '@vegaprotocol/environment';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import { useScreenDimensions } from '@vegaprotocol/react-helpers';
|
import { useScreenDimensions } from '@vegaprotocol/react-helpers';
|
||||||
import { ExternalLink, Link } from '@vegaprotocol/ui-toolkit';
|
import { ExternalLink, Link } from '@vegaprotocol/ui-toolkit';
|
||||||
import { useMemo, useState } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { ENV } from '../../config/env';
|
import { ENV } from '../../config/env';
|
||||||
|
|
||||||
export const Footer = () => {
|
export const Footer = () => {
|
||||||
const { VEGA_URL, GIT_COMMIT_HASH, GIT_ORIGIN_URL } = useEnvironment();
|
const { VEGA_URL, GIT_COMMIT_HASH, GIT_ORIGIN_URL } = useEnvironment();
|
||||||
const [nodeSwitcherOpen, setNodeSwitcherOpen] = useState(false);
|
const setNodeSwitcherOpen = useNodeSwitcherStore(
|
||||||
|
(store) => store.setDialogOpen
|
||||||
|
);
|
||||||
|
|
||||||
const { screenSize } = useScreenDimensions();
|
const { screenSize } = useScreenDimensions();
|
||||||
const showFullFeedbackLabel = useMemo(
|
const showFullFeedbackLabel = useMemo(
|
||||||
() => ['md', 'lg', 'xl', 'xxl', 'xxxl'].includes(screenSize),
|
() => ['md', 'lg', 'xl', 'xxl', 'xxxl'].includes(screenSize),
|
||||||
@@ -15,46 +21,42 @@ export const Footer = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
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">
|
||||||
<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">
|
||||||
<div className="flex justify-between gap-2 align-middle">
|
{GIT_COMMIT_HASH && (
|
||||||
{GIT_COMMIT_HASH && (
|
<div className="content-center flex border-r border-neutral-700 dark:border-neutral-300 pr-4">
|
||||||
<div className="content-center flex border-r border-neutral-700 dark:border-neutral-300 pr-4">
|
<p data-testid="git-commit-hash">
|
||||||
<p data-testid="git-commit-hash">
|
{t('Version')}:{' '}
|
||||||
{t('Version')}:{' '}
|
<Link
|
||||||
<Link
|
href={
|
||||||
href={
|
GIT_ORIGIN_URL
|
||||||
GIT_ORIGIN_URL
|
? `${GIT_ORIGIN_URL}/commit/${GIT_COMMIT_HASH}`
|
||||||
? `${GIT_ORIGIN_URL}/commit/${GIT_COMMIT_HASH}`
|
: undefined
|
||||||
: undefined
|
}
|
||||||
}
|
target={GIT_ORIGIN_URL ? '_blank' : undefined}
|
||||||
target={GIT_ORIGIN_URL ? '_blank' : undefined}
|
>
|
||||||
>
|
{GIT_COMMIT_HASH}
|
||||||
{GIT_COMMIT_HASH}
|
</Link>
|
||||||
</Link>
|
</p>
|
||||||
</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>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<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>
|
||||||
|
|
||||||
|
{ENV.addresses.feedback ? (
|
||||||
<div className="flex pl-2 content-center">
|
<div className="flex pl-2 content-center">
|
||||||
<ExternalLink href={ENV.addresses.feedback}>
|
<ExternalLink href={ENV.addresses.feedback}>
|
||||||
{showFullFeedbackLabel ? t('Share your feedback') : t('Feedback')}
|
{showFullFeedbackLabel ? t('Share your feedback') : t('Feedback')}
|
||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
) : null}
|
||||||
</footer>
|
</div>
|
||||||
<NodeSwitcherDialog
|
</footer>
|
||||||
open={nodeSwitcherOpen}
|
|
||||||
setOpen={setNodeSwitcherOpen}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -62,9 +64,5 @@ const NodeUrl = ({ url }: { url: string }) => {
|
|||||||
// get base url from api url, api sub domain
|
// get base url from api url, api sub domain
|
||||||
const urlObj = new URL(url);
|
const urlObj = new URL(url);
|
||||||
const nodeUrl = urlObj.origin.replace(/^[^.]+\./g, '');
|
const nodeUrl = urlObj.origin.replace(/^[^.]+\./g, '');
|
||||||
return (
|
return <span className="cursor-default">{nodeUrl}</span>;
|
||||||
<Link href={'https://' + nodeUrl} target="_blank">
|
|
||||||
{nodeUrl}
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Header } from './header';
|
|||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
|
|
||||||
jest.mock('@vegaprotocol/environment', () => ({
|
jest.mock('@vegaprotocol/environment', () => ({
|
||||||
|
...jest.requireActual('@vegaprotocol/environment'),
|
||||||
NetworkSwitcher: () => (
|
NetworkSwitcher: () => (
|
||||||
<div data-testid="network-switcher">NetworkSwitcher</div>
|
<div data-testid="network-switcher">NetworkSwitcher</div>
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import type { MarketInfoWithData } from '@vegaprotocol/market-info';
|
import type { MarketInfoWithData } from '@vegaprotocol/markets';
|
||||||
import { LiquidityInfoPanel } from '@vegaprotocol/market-info';
|
|
||||||
import { LiquidityMonitoringParametersInfoPanel } from '@vegaprotocol/market-info';
|
|
||||||
import {
|
import {
|
||||||
|
LiquidityInfoPanel,
|
||||||
|
LiquidityMonitoringParametersInfoPanel,
|
||||||
InstrumentInfoPanel,
|
InstrumentInfoPanel,
|
||||||
KeyDetailsInfoPanel,
|
KeyDetailsInfoPanel,
|
||||||
LiquidityPriceRangeInfoPanel,
|
LiquidityPriceRangeInfoPanel,
|
||||||
@@ -12,20 +12,18 @@ import {
|
|||||||
RiskModelInfoPanel,
|
RiskModelInfoPanel,
|
||||||
RiskParametersInfoPanel,
|
RiskParametersInfoPanel,
|
||||||
SettlementAssetInfoPanel,
|
SettlementAssetInfoPanel,
|
||||||
} from '@vegaprotocol/market-info';
|
} from '@vegaprotocol/markets';
|
||||||
import { MarketInfoTable } from '@vegaprotocol/market-info';
|
import { MarketInfoTable } from '@vegaprotocol/markets';
|
||||||
import type { DataSourceDefinition } from '@vegaprotocol/types';
|
import type { DataSourceDefinition } from '@vegaprotocol/types';
|
||||||
import isEqual from 'lodash/isEqual';
|
import isEqual from 'lodash/isEqual';
|
||||||
|
|
||||||
export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
|
export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
|
||||||
if (!market) return null;
|
if (!market) return null;
|
||||||
|
|
||||||
const settlementData =
|
const settlementData = market.tradableInstrument.instrument.product
|
||||||
market.tradableInstrument.instrument.product.dataSourceSpecForSettlementData
|
.dataSourceSpecForSettlementData.data as DataSourceDefinition;
|
||||||
.data;
|
const terminationData = market.tradableInstrument.instrument.product
|
||||||
const terminationData =
|
.dataSourceSpecForTradingTermination.data as DataSourceDefinition;
|
||||||
market.tradableInstrument.instrument.product
|
|
||||||
.dataSourceSpecForTradingTermination.data;
|
|
||||||
|
|
||||||
const getSigners = (data: DataSourceDefinition) => {
|
const getSigners = (data: DataSourceDefinition) => {
|
||||||
if (data.sourceType.__typename === 'DataSourceDefinitionExternal') {
|
if (data.sourceType.__typename === 'DataSourceDefinitionExternal') {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { MarketFieldsFragment } from '@vegaprotocol/market-list';
|
import type { MarketFieldsFragment } from '@vegaprotocol/markets';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
|
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
|
||||||
import type { AgGridReact } from 'ag-grid-react';
|
import type { AgGridReact } from 'ag-grid-react';
|
||||||
|
|||||||
+8
-2
@@ -1,3 +1,5 @@
|
|||||||
|
import { Icon } from '@vegaprotocol/ui-toolkit';
|
||||||
|
|
||||||
// https://github.com/vegaprotocol/vega/blob/develop/core/blockchain/response.go
|
// https://github.com/vegaprotocol/vega/blob/develop/core/blockchain/response.go
|
||||||
export const ErrorCodes = new Map([
|
export const ErrorCodes = new Map([
|
||||||
[51, 'Transaction failed validation'],
|
[51, 'Transaction failed validation'],
|
||||||
@@ -28,7 +30,11 @@ export const ChainResponseCode = ({
|
|||||||
}: ChainResponseCodeProps) => {
|
}: ChainResponseCodeProps) => {
|
||||||
const isSuccess = successCodes.has(code);
|
const isSuccess = successCodes.has(code);
|
||||||
|
|
||||||
const icon = isSuccess ? '✅' : '❌';
|
const icon = isSuccess ? (
|
||||||
|
<Icon name="tick-circle" className="fill-vega-green-550" />
|
||||||
|
) : (
|
||||||
|
<Icon name="cross" className="fill-vega-pink-550" />
|
||||||
|
);
|
||||||
const label = ErrorCodes.get(code) || 'Unknown response code';
|
const label = ErrorCodes.get(code) || 'Unknown response code';
|
||||||
|
|
||||||
// Hack for batches with many errors - see https://github.com/vegaprotocol/vega/issues/7245
|
// Hack for batches with many errors - see https://github.com/vegaprotocol/vega/issues/7245
|
||||||
@@ -36,7 +42,7 @@ export const ChainResponseCode = ({
|
|||||||
error && error.length > 100 ? error.replace(/,/g, ',\r\n') : error;
|
error && error.length > 100 ? error.replace(/,/g, ',\r\n') : error;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div title={`Response code: ${code} - ${label}`} className="inline-block">
|
<div title={`Response code: ${code} - ${label}`} className=" inline-block">
|
||||||
<span
|
<span
|
||||||
className="mr-2"
|
className="mr-2"
|
||||||
aria-label={isSuccess ? 'Success' : 'Warning'}
|
aria-label={isSuccess ? 'Success' : 'Warning'}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint
|
|||||||
import { TxDetailsShared } from './shared/tx-details-shared';
|
import { TxDetailsShared } from './shared/tx-details-shared';
|
||||||
import { TableCell, TableRow, TableWithTbody } from '../../table';
|
import { TableCell, TableRow, TableWithTbody } from '../../table';
|
||||||
import ProposalLink from '../../links/proposal-link/proposal-link';
|
import ProposalLink from '../../links/proposal-link/proposal-link';
|
||||||
|
import { VoteIcon } from '../../vote-icon/vote-icon';
|
||||||
|
|
||||||
interface TxProposalVoteProps {
|
interface TxProposalVoteProps {
|
||||||
txData: BlockExplorerTransactionResult | undefined;
|
txData: BlockExplorerTransactionResult | undefined;
|
||||||
@@ -30,27 +31,22 @@ export const TxProposalVote = ({
|
|||||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const vote = txData.command.voteSubmission.value ? '👍' : '👎';
|
const vote = txData.command.voteSubmission.value === 'VALUE_YES';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableWithTbody className="mb-8" allowWrap={true}>
|
<TableWithTbody className="mb-8" allowWrap={true}>
|
||||||
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
|
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
|
||||||
<TableRow modifier="bordered">
|
|
||||||
<TableCell>{t('Proposal ID')}</TableCell>
|
|
||||||
<TableCell>{txData.command.voteSubmission.proposalId}</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Proposal details')}</TableCell>
|
<TableCell>{t('Proposal details')}</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<ProposalLink id={txData.command.voteSubmission.proposalId} />
|
<ProposalLink id={txData.command.voteSubmission.proposalId} />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<TableRow modifier="bordered">
|
|
||||||
<TableCell>{t('Proposal')}</TableCell>
|
|
||||||
<TableCell>{txData.command.voteSubmission.proposalId}</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Vote')}</TableCell>
|
<TableCell>{t('Vote')}</TableCell>
|
||||||
<TableCell>{vote}</TableCell>
|
<TableCell>
|
||||||
|
<VoteIcon vote={vote} />
|
||||||
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableWithTbody>
|
</TableWithTbody>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
import type { Proposal } from './tx-proposal';
|
||||||
|
import { proposalRequiresSignatureBundle } from './tx-proposal';
|
||||||
|
|
||||||
|
describe('proposalRequiresSignatureBundle', () => {
|
||||||
|
it('should return false for freeform proposals, which do not require a signature bundle to enact', () => {
|
||||||
|
const mock = {
|
||||||
|
terms: {
|
||||||
|
newFreeform: {},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(proposalRequiresSignatureBundle(mock)).toEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false for newMarket proposals, which do not require a signature bundle to enact', () => {
|
||||||
|
const mock = {
|
||||||
|
terms: {
|
||||||
|
newMarket: {},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(proposalRequiresSignatureBundle(mock)).toEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true for newAsset proposals, which do require a signature bundle to enact', () => {
|
||||||
|
const mock = {
|
||||||
|
terms: {
|
||||||
|
newAsset: {},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(proposalRequiresSignatureBundle(mock)).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true for updateAsset proposals, which do require a signature bundle to enact', () => {
|
||||||
|
const mock = {
|
||||||
|
terms: {
|
||||||
|
updateAsset: {},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(proposalRequiresSignatureBundle(mock)).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false when bad data is supplied', () => {
|
||||||
|
expect(
|
||||||
|
proposalRequiresSignatureBundle(false as unknown as Proposal)
|
||||||
|
).toEqual(false);
|
||||||
|
expect(
|
||||||
|
proposalRequiresSignatureBundle(undefined as unknown as Proposal)
|
||||||
|
).toEqual(false);
|
||||||
|
expect(
|
||||||
|
proposalRequiresSignatureBundle({ test: false } as unknown as Proposal)
|
||||||
|
).toEqual(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -28,11 +28,16 @@ interface TxProposalProps {
|
|||||||
* @returns boolean True if a signature bundle is required. Used to fetch a signature bundle
|
* @returns boolean True if a signature bundle is required. Used to fetch a signature bundle
|
||||||
*/
|
*/
|
||||||
export function proposalRequiresSignatureBundle(proposal?: Proposal): boolean {
|
export function proposalRequiresSignatureBundle(proposal?: Proposal): boolean {
|
||||||
|
const proposalsThatRequireBundles = ['newAsset', 'updateAsset'];
|
||||||
|
|
||||||
if (!proposal?.terms) {
|
if (!proposal?.terms) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return !!['newAsset', 'updateAsset'].filter((requiredIfExists) =>
|
|
||||||
has(proposal.terms, requiredIfExists)
|
return (
|
||||||
|
proposalsThatRequireBundles.filter((requiredIfExists) =>
|
||||||
|
has(proposal.terms, requiredIfExists)
|
||||||
|
).length > 0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,6 +86,7 @@ export const TxProposal = ({ txData, pubKey, blockData }: TxProposalProps) => {
|
|||||||
|
|
||||||
const tx = proposal.terms?.newAsset || proposal.terms?.updateAsset;
|
const tx = proposal.terms?.newAsset || proposal.terms?.updateAsset;
|
||||||
|
|
||||||
|
// This component is not rendered if no bundle is required
|
||||||
const SignatureBundleComponent = proposal.terms?.newAsset
|
const SignatureBundleComponent = proposal.terms?.newAsset
|
||||||
? ProposalSignatureBundleNewAsset
|
? ProposalSignatureBundleNewAsset
|
||||||
: ProposalSignatureBundleUpdateAsset;
|
: ProposalSignatureBundleUpdateAsset;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import type { components } from '../../../types/explorer';
|
import type { components } from '../../../types/explorer';
|
||||||
|
import { VoteIcon } from '../vote-icon/vote-icon';
|
||||||
|
|
||||||
interface TxOrderTypeProps {
|
interface TxOrderTypeProps {
|
||||||
orderType: string;
|
orderType: string;
|
||||||
@@ -137,12 +138,15 @@ export const TxOrderType = ({ orderType, command }: TxOrderTypeProps) => {
|
|||||||
let type = displayString[orderType] || orderType;
|
let type = displayString[orderType] || orderType;
|
||||||
|
|
||||||
let colours =
|
let colours =
|
||||||
'text-white dark:text-white bg-vega-dark-150 dark:bg-vega-dark-150';
|
'text-white dark:text-white bg-vega-dark-150 dark:bg-vega-dark-250';
|
||||||
|
|
||||||
// This will get unwieldy and should probably produce a different colour of tag
|
// This will get unwieldy and should probably produce a different colour of tag
|
||||||
if (type === 'Chain Event' && !!command?.chainEvent) {
|
if (type === 'Chain Event' && !!command?.chainEvent) {
|
||||||
type = getLabelForChainEvent(command.chainEvent);
|
type = getLabelForChainEvent(command.chainEvent);
|
||||||
colours = 'text-white dark-text-white bg-vega-pink dark:bg-vega-pink';
|
colours = 'text-white dark-text-white bg-vega-pink dark:bg-vega-pink';
|
||||||
|
} else if (type === 'Validator Heartbeat') {
|
||||||
|
colours =
|
||||||
|
'text-white dark-text-white bg-vega-light-200 dark:bg-vega-dark-100';
|
||||||
} else if (type === 'Proposal' || type === 'Governance Proposal') {
|
} else if (type === 'Proposal' || type === 'Governance Proposal') {
|
||||||
if (command && !!command.proposalSubmission) {
|
if (command && !!command.proposalSubmission) {
|
||||||
type = getLabelForProposal(command.proposalSubmission);
|
type = getLabelForProposal(command.proposalSubmission);
|
||||||
@@ -150,6 +154,16 @@ export const TxOrderType = ({ orderType, command }: TxOrderTypeProps) => {
|
|||||||
colours = 'text-black bg-vega-yellow';
|
colours = 'text-black bg-vega-yellow';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type === 'Vote on Proposal') {
|
||||||
|
return (
|
||||||
|
<VoteIcon
|
||||||
|
vote={command?.voteSubmission?.value === 'VALUE_YES'}
|
||||||
|
yesText="Proposal vote"
|
||||||
|
noText="Proposal vote"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (type === 'Vote on Proposal' || type === 'Vote Submission') {
|
if (type === 'Vote on Proposal' || type === 'Vote Submission') {
|
||||||
colours = 'text-black bg-vega-yellow';
|
colours = 'text-black bg-vega-yellow';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,6 +98,6 @@ describe('Txs infinite list item', () => {
|
|||||||
expect(screen.getByTestId('pub-key')).toHaveTextContent('testPubKey');
|
expect(screen.getByTestId('pub-key')).toHaveTextContent('testPubKey');
|
||||||
expect(screen.getByTestId('tx-type')).toHaveTextContent('testType');
|
expect(screen.getByTestId('tx-type')).toHaveTextContent('testType');
|
||||||
expect(screen.getByTestId('tx-block')).toHaveTextContent('1');
|
expect(screen.getByTestId('tx-block')).toHaveTextContent('1');
|
||||||
expect(screen.getByTestId('tx-success')).toHaveTextContent('Success: ✅');
|
expect(screen.getByTestId('tx-success')).toHaveTextContent('Success');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export const TxsInfiniteListItem = ({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
data-testid="transaction-row"
|
data-testid="transaction-row"
|
||||||
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"
|
className="flex items-center h-full border-t border-neutral-600 dark:border-neutral-800 txs-infinite-list-item grid grid-cols-10"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="text-sm col-span-10 md:col-span-3 leading-none"
|
className="text-sm col-span-10 md:col-span-3 leading-none"
|
||||||
@@ -83,7 +83,7 @@ export const TxsInfiniteListItem = ({
|
|||||||
data-testid="tx-success"
|
data-testid="tx-success"
|
||||||
>
|
>
|
||||||
<span className="md:hidden uppercase text-vega-dark-300">
|
<span className="md:hidden uppercase text-vega-dark-300">
|
||||||
Success:
|
Success
|
||||||
</span>
|
</span>
|
||||||
{isNumber(code) ? (
|
{isNumber(code) ? (
|
||||||
<ChainResponseCode code={code} hideLabel={true} />
|
<ChainResponseCode code={code} hideLabel={true} />
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import { render } from '@testing-library/react';
|
||||||
|
import { VoteIcon } from './vote-icon';
|
||||||
|
|
||||||
|
describe('Vote TX icon', () => {
|
||||||
|
it('should use the text For by default for yes votes', () => {
|
||||||
|
const yes = render(<VoteIcon vote={true} />);
|
||||||
|
expect(yes.getByTestId('label')).toHaveTextContent('For');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should use the yesText for yes votes if specified', () => {
|
||||||
|
const yes = render(<VoteIcon vote={true} yesText="Test" />);
|
||||||
|
expect(yes.getByTestId('label')).toHaveTextContent('Test');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display the tick icon for yes votes', () => {
|
||||||
|
const no = render(<VoteIcon vote={true} />);
|
||||||
|
expect(no.getByRole('img')).toHaveAttribute(
|
||||||
|
'aria-label',
|
||||||
|
'tick-circle icon'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should use the text Against by default for no votes', () => {
|
||||||
|
const no = render(<VoteIcon vote={false} />);
|
||||||
|
expect(no.getByTestId('label')).toHaveTextContent('Against');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should use the noText for no votes if specified', () => {
|
||||||
|
const no = render(<VoteIcon vote={false} noText="Test" />);
|
||||||
|
expect(no.getByTestId('label')).toHaveTextContent('Test');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display the delete icon for no votes', () => {
|
||||||
|
const no = render(<VoteIcon vote={false} />);
|
||||||
|
expect(no.getByRole('img')).toHaveAttribute('aria-label', 'delete icon');
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import { Icon } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import type { IconName } from '@vegaprotocol/ui-toolkit';
|
||||||
|
|
||||||
|
export interface VoteIconProps {
|
||||||
|
// True is a yes vote, false is undefined or no vorte
|
||||||
|
vote: boolean;
|
||||||
|
// Defaults to 'For', but can be any text
|
||||||
|
yesText?: string;
|
||||||
|
// Defaults to 'Against', but can be any text
|
||||||
|
noText?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays a lozenge with an icon representing the way a user voted for a proposal.
|
||||||
|
* The yes and no text can be overridden
|
||||||
|
*
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function VoteIcon({
|
||||||
|
vote,
|
||||||
|
yesText = 'For',
|
||||||
|
noText = 'Against',
|
||||||
|
}: VoteIconProps) {
|
||||||
|
const label = vote ? yesText : noText;
|
||||||
|
const bg = vote ? 'bg-vega-green-550' : 'bg-vega-pink-550';
|
||||||
|
const icon: IconName = vote ? 'tick-circle' : 'delete';
|
||||||
|
const fill = vote ? 'vega-green-300' : 'vega-pink-300';
|
||||||
|
const text = vote ? 'vega-green-200' : 'vega-pink-200';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={`voteicon inline-block my-1 py-1 px-2 py rounded-md text-white leading-one sm align-top ${bg}`}
|
||||||
|
>
|
||||||
|
<Icon name={icon} size={3} className={`mr-2 p-0 fill-${fill}`} />
|
||||||
|
<span className={`text-base text-${text}`} data-testid="label">
|
||||||
|
{label}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@ import { useScrollToLocation } from '../../hooks/scroll-to-location';
|
|||||||
import { useDocumentTitle } from '../../hooks/use-document-title';
|
import { useDocumentTitle } from '../../hooks/use-document-title';
|
||||||
import compact from 'lodash/compact';
|
import compact from 'lodash/compact';
|
||||||
import { JsonViewerDialog } from '../../components/dialogs/json-viewer-dialog';
|
import { JsonViewerDialog } from '../../components/dialogs/json-viewer-dialog';
|
||||||
import { marketInfoWithDataProvider } from '@vegaprotocol/market-info';
|
import { marketInfoWithDataProvider } from '@vegaprotocol/markets';
|
||||||
import { PageTitle } from '../../components/page-helpers/page-title';
|
import { PageTitle } from '../../components/page-helpers/page-title';
|
||||||
|
|
||||||
export const MarketPage = () => {
|
export const MarketPage = () => {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useScrollToLocation } from '../../hooks/scroll-to-location';
|
import { useScrollToLocation } from '../../hooks/scroll-to-location';
|
||||||
import { useDocumentTitle } from '../../hooks/use-document-title';
|
import { useDocumentTitle } from '../../hooks/use-document-title';
|
||||||
import { marketsProvider } from '@vegaprotocol/market-list';
|
import { marketsProvider } from '@vegaprotocol/markets';
|
||||||
import { RouteTitle } from '../../components/route-title';
|
import { RouteTitle } from '../../components/route-title';
|
||||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
|
|||||||
@@ -32,9 +32,9 @@
|
|||||||
line-height: calc(min(var(--ag-line-height, 26px), 26px) - 4px);
|
line-height: calc(min(var(--ag-line-height, 26px), 26px) - 4px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.vega-ag-grid .ag-row {
|
.vega-ag-grid .ag-row,
|
||||||
border-width: 1px 0;
|
.vega-ag-grid .ag-cell {
|
||||||
border-bottom: 1px solid transparent;
|
border-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Light variables */
|
/* Light variables */
|
||||||
@@ -46,7 +46,6 @@
|
|||||||
--ag-header-column-separator-color: theme(colors.neutral[300]);
|
--ag-header-column-separator-color: theme(colors.neutral[300]);
|
||||||
--ag-row-border-color: theme(colors.white);
|
--ag-row-border-color: theme(colors.white);
|
||||||
--ag-row-hover-color: theme(colors.neutral[100]);
|
--ag-row-hover-color: theme(colors.neutral[100]);
|
||||||
--ag-font-size: 12px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dark variables */
|
/* Dark variables */
|
||||||
@@ -58,5 +57,8 @@
|
|||||||
--ag-header-column-separator-color: theme(colors.neutral[600]);
|
--ag-header-column-separator-color: theme(colors.neutral[600]);
|
||||||
--ag-row-border-color: theme(colors.black);
|
--ag-row-border-color: theme(colors.black);
|
||||||
--ag-row-hover-color: theme(colors.neutral[800]);
|
--ag-row-hover-color: theme(colors.neutral[800]);
|
||||||
--ag-font-size: 12px;
|
}
|
||||||
|
|
||||||
|
.voteicon svg {
|
||||||
|
vertical-align: baseline;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ 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_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
|
||||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||||
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||||
|
NX_VEGA_REST_URL=http://localhost:3008/api/v2/
|
||||||
|
|
||||||
#Test configuration variables
|
#Test configuration variables
|
||||||
CYPRESS_FAIRGROUND=false
|
CYPRESS_FAIRGROUND=false
|
||||||
@@ -30,6 +31,6 @@ CYPRESS_TRUNCATED_VEGA_PUBLIC_KEY2=7f9cf0…c25535
|
|||||||
CYPRESS_VEGA_ENV=CUSTOM
|
CYPRESS_VEGA_ENV=CUSTOM
|
||||||
CYPRESS_VEGA_PUBLIC_KEY=02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65
|
CYPRESS_VEGA_PUBLIC_KEY=02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65
|
||||||
CYPRESS_VEGA_PUBLIC_KEY2=7f9cf07d3a9905b1a61a1069f7a758855da428bc0f4a97de87f48644bfc25535
|
CYPRESS_VEGA_PUBLIC_KEY2=7f9cf07d3a9905b1a61a1069f7a758855da428bc0f4a97de87f48644bfc25535
|
||||||
CYPRESS_VEGA_TOKEN_URL=https://token.fairground.wtf
|
CYPRESS_VEGA_TOKEN_URL=https://governance.fairground.wtf
|
||||||
CYPRESS_VEGA_WALLET_URL=http://localhost:1789
|
CYPRESS_VEGA_WALLET_URL=http://localhost:1789
|
||||||
CYPRESS_VEGA_WALLET_API_TOKEN=
|
CYPRESS_VEGA_WALLET_API_TOKEN=
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# App configuration variables
|
# App configuration variables
|
||||||
NX_VEGA_ENV=MAINNET
|
NX_VEGA_ENV=MAINNET
|
||||||
NX_VEGA_URL=https://api.vega.xyz/query
|
NX_VEGA_URL=https://api.vega.community/graphql
|
||||||
NX_ETHEREUM_PROVIDER_URL=https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
NX_ETHEREUM_PROVIDER_URL=https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||||
NX_ETHERSCAN_URL=https://etherscan.io
|
NX_ETHERSCAN_URL=https://etherscan.io
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
const { defineConfig } = require('cypress');
|
const { defineConfig } = require('cypress');
|
||||||
|
|
||||||
module.exports = defineConfig({
|
module.exports = defineConfig({
|
||||||
projectId: 'et4snf',
|
reporter: '../../node_modules/cypress-mochawesome-reporter',
|
||||||
|
|
||||||
e2e: {
|
e2e: {
|
||||||
setupNodeEvents(on, config) {
|
setupNodeEvents(on, config) {
|
||||||
|
require('cypress-mochawesome-reporter/plugin')(on);
|
||||||
require('@cypress/grep/src/plugin')(config);
|
require('@cypress/grep/src/plugin')(config);
|
||||||
return config;
|
return config;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,113 @@
|
|||||||
|
{
|
||||||
|
"rationale": {
|
||||||
|
"title": "New Market Proposal E2E submission",
|
||||||
|
"description": "E2E new market proposal"
|
||||||
|
},
|
||||||
|
"terms": {
|
||||||
|
"newMarket": {
|
||||||
|
"changes": {
|
||||||
|
"decimalPlaces": "5",
|
||||||
|
"positionDecimalPlaces": "5",
|
||||||
|
"linearSlippageFactor": "0.001",
|
||||||
|
"quadraticSlippageFactor": "0",
|
||||||
|
"lpPriceRange": "10",
|
||||||
|
"instrument": {
|
||||||
|
"name": "Token test market",
|
||||||
|
"code": "TEST.24h",
|
||||||
|
"future": {
|
||||||
|
"settlementAsset": "73174a6fb1d5802ba0ac7bd7ab79e0a3a4837b262de0a4e80815a55442692bd0",
|
||||||
|
"quoteName": "fBTC",
|
||||||
|
"dataSourceSpecForSettlementData": {
|
||||||
|
"external": {
|
||||||
|
"oracle": {
|
||||||
|
"signers": [
|
||||||
|
{
|
||||||
|
"pubKey": {
|
||||||
|
"key": "70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"key": {
|
||||||
|
"name": "prices.ETH.value",
|
||||||
|
"type": "TYPE_INTEGER",
|
||||||
|
"numberDecimalPlaces": "0"
|
||||||
|
},
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"operator": "OPERATOR_GREATER_THAN",
|
||||||
|
"value": "0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dataSourceSpecForTradingTermination": {
|
||||||
|
"external": {
|
||||||
|
"oracle": {
|
||||||
|
"signers": [
|
||||||
|
{
|
||||||
|
"pubKey": {
|
||||||
|
"key": "70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"key": {
|
||||||
|
"name": "trading.terminated.ETH5",
|
||||||
|
"type": "TYPE_BOOLEAN"
|
||||||
|
},
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"operator": "OPERATOR_EQUALS",
|
||||||
|
"value": "true"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dataSourceSpecBinding": {
|
||||||
|
"settlementDataProperty": "prices.ETH.value",
|
||||||
|
"tradingTerminationProperty": "trading.terminated.ETH5"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"metadata": ["sector:energy", "sector:tech", "source:docs.vega.xyz"],
|
||||||
|
"priceMonitoringParameters": {
|
||||||
|
"triggers": [
|
||||||
|
{
|
||||||
|
"horizon": "43200",
|
||||||
|
"probability": "0.9999999",
|
||||||
|
"auctionExtension": "600"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"liquidityMonitoringParameters": {
|
||||||
|
"targetStakeParameters": {
|
||||||
|
"timeWindow": "3600",
|
||||||
|
"scalingFactor": 10
|
||||||
|
},
|
||||||
|
"triggeringRatio": "0.7",
|
||||||
|
"auctionExtension": "1"
|
||||||
|
},
|
||||||
|
"logNormal": {
|
||||||
|
"tau": 0.0001140771161,
|
||||||
|
"riskAversionParameter": 0.01,
|
||||||
|
"params": {
|
||||||
|
"mu": 0,
|
||||||
|
"r": 0.016,
|
||||||
|
"sigma": 0.5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"closingTimestamp": 0,
|
||||||
|
"enactmentTimestamp": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,21 +2,17 @@ import {
|
|||||||
navigateTo,
|
navigateTo,
|
||||||
waitForSpinner,
|
waitForSpinner,
|
||||||
navigation,
|
navigation,
|
||||||
|
turnTelemetryOff,
|
||||||
} from '../../support/common.functions';
|
} from '../../support/common.functions';
|
||||||
import {
|
import {
|
||||||
createRawProposal,
|
createRawProposal,
|
||||||
createTenDigitUnixTimeStampForSpecifiedDays,
|
createTenDigitUnixTimeStampForSpecifiedDays,
|
||||||
enterUniqueFreeFormProposalBody,
|
|
||||||
generateFreeFormProposalTitle,
|
generateFreeFormProposalTitle,
|
||||||
getDateFormatForSpecifiedDays,
|
getDateFormatForSpecifiedDays,
|
||||||
getProposalIdFromList,
|
getProposalFromTitle,
|
||||||
getProposalInformationFromTable,
|
getProposalInformationFromTable,
|
||||||
getSubmittedProposalFromProposalList,
|
submitUniqueRawProposal,
|
||||||
goToMakeNewProposal,
|
|
||||||
governanceProposalType,
|
|
||||||
voteForProposal,
|
voteForProposal,
|
||||||
waitForProposalSubmitted,
|
|
||||||
waitForProposalSync,
|
|
||||||
} from '../../../../governance-e2e/src/support/governance.functions';
|
} from '../../../../governance-e2e/src/support/governance.functions';
|
||||||
import { ensureSpecifiedUnstakedTokensAreAssociated } from '../../../../governance-e2e/src/support/staking.functions';
|
import { ensureSpecifiedUnstakedTokensAreAssociated } from '../../../../governance-e2e/src/support/staking.functions';
|
||||||
import { ethereumWalletConnect } from '../../../../governance-e2e/src/support/wallet-eth.functions';
|
import { ethereumWalletConnect } from '../../../../governance-e2e/src/support/wallet-eth.functions';
|
||||||
@@ -37,6 +33,8 @@ const proposalDetailsTitle = '[data-testid="proposal-title"]';
|
|||||||
const proposalDetailsDescription = '[data-testid="proposal-description"]';
|
const proposalDetailsDescription = '[data-testid="proposal-description"]';
|
||||||
const openProposals = '[data-testid="open-proposals"]';
|
const openProposals = '[data-testid="open-proposals"]';
|
||||||
const viewProposalButton = '[data-testid="view-proposal-btn"]';
|
const viewProposalButton = '[data-testid="view-proposal-btn"]';
|
||||||
|
const voteBreakdownToggle = 'vote-breakdown-toggle';
|
||||||
|
const proposalTermsToggle = 'proposal-terms-toggle';
|
||||||
|
|
||||||
describe(
|
describe(
|
||||||
'Governance flow for proposal details',
|
'Governance flow for proposal details',
|
||||||
@@ -50,6 +48,7 @@ describe(
|
|||||||
|
|
||||||
beforeEach('visit proposals tab', function () {
|
beforeEach('visit proposals tab', function () {
|
||||||
cy.clearLocalStorage();
|
cy.clearLocalStorage();
|
||||||
|
turnTelemetryOff();
|
||||||
cy.reload();
|
cy.reload();
|
||||||
waitForSpinner();
|
waitForSpinner();
|
||||||
cy.connectVegaWallet();
|
cy.connectVegaWallet();
|
||||||
@@ -60,23 +59,25 @@ describe(
|
|||||||
|
|
||||||
// 3001-VOTE-050 3001-VOTE-054 3001-VOTE-055 3002-PROP-019
|
// 3001-VOTE-050 3001-VOTE-054 3001-VOTE-055 3002-PROP-019
|
||||||
it('Newly created raw proposal details - shows proposal title and full description', function () {
|
it('Newly created raw proposal details - shows proposal title and full description', function () {
|
||||||
|
const proposalDescription =
|
||||||
|
'I propose that everyone evaluate the following IPFS document and vote Yes if they agree. bafybeigwwctpv37xdcwacqxvekr6e4kaemqsrv34em6glkbiceo3fcy4si';
|
||||||
|
|
||||||
createRawProposal();
|
createRawProposal();
|
||||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||||
getProposalIdFromList(rawProposal.rationale.title);
|
cy.get(openProposals).within(() => {
|
||||||
cy.get('@proposalIdText').then((proposalId) => {
|
getProposalFromTitle(rawProposal.rationale.title).within(() => {
|
||||||
cy.get(openProposals).within(() => {
|
cy.get(viewProposalButton).should('be.visible').click();
|
||||||
cy.get(`#${proposalId}`).within(() => {
|
|
||||||
cy.get(viewProposalButton).should('be.visible').click();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
cy.get(proposalDetailsTitle)
|
cy.get(proposalDetailsTitle).should(
|
||||||
.should('contain', rawProposal.rationale.title)
|
'contain.text',
|
||||||
.and('be.visible');
|
rawProposal.rationale.title
|
||||||
|
);
|
||||||
cy.get(proposalDetailsDescription)
|
cy.get(proposalDetailsDescription)
|
||||||
.should('contain', rawProposal.rationale.description)
|
.find('p')
|
||||||
.and('be.visible');
|
.should('have.text', proposalDescription);
|
||||||
});
|
});
|
||||||
|
cy.getByTestId(proposalTermsToggle).click();
|
||||||
// 3001-VOTE-052
|
// 3001-VOTE-052
|
||||||
cy.get('code.language-json')
|
cy.get('code.language-json')
|
||||||
.should('exist')
|
.should('exist')
|
||||||
@@ -87,33 +88,36 @@ describe(
|
|||||||
|
|
||||||
// 3001-VOTE-043
|
// 3001-VOTE-043
|
||||||
it('Newly created freeform proposal details - shows proposed and closing dates', function () {
|
it('Newly created freeform proposal details - shows proposed and closing dates', function () {
|
||||||
const closingVoteHrs = '72';
|
|
||||||
const proposalTitle = generateFreeFormProposalTitle();
|
const proposalTitle = generateFreeFormProposalTitle();
|
||||||
const proposalTimeStamp = createTenDigitUnixTimeStampForSpecifiedDays(3);
|
const proposalTimeStamp = createTenDigitUnixTimeStampForSpecifiedDays(3);
|
||||||
|
// const currentDate = new Date(createTenDigitUnixTimeStampForSpecifiedDays(0) * 1000)
|
||||||
|
// const proposedDate = new Date(currentDate.getTime() + 60000)
|
||||||
|
|
||||||
goToMakeNewProposal(governanceProposalType.FREEFORM);
|
submitUniqueRawProposal({
|
||||||
enterUniqueFreeFormProposalBody(closingVoteHrs, proposalTitle);
|
proposalTitle: proposalTitle,
|
||||||
waitForProposalSubmitted();
|
closingTimestamp: proposalTimeStamp,
|
||||||
waitForProposalSync();
|
});
|
||||||
navigateTo(navigation.proposals);
|
navigateTo(navigation.proposals);
|
||||||
getSubmittedProposalFromProposalList(proposalTitle).within(() =>
|
getProposalFromTitle(proposalTitle).within(() =>
|
||||||
cy.get(viewProposalButton).click()
|
cy.get(viewProposalButton).click()
|
||||||
);
|
);
|
||||||
cy.wrap(
|
cy.wrap(
|
||||||
formatDateWithLocalTimezone(new Date(proposalTimeStamp * 1000))
|
formatDateWithLocalTimezone(new Date(proposalTimeStamp * 1000))
|
||||||
).then((closingDate) => {
|
).then((closingDate) => {
|
||||||
getProposalInformationFromTable('Closes on')
|
getProposalInformationFromTable('Closes on').should(
|
||||||
.contains(closingDate)
|
'have.text',
|
||||||
.should('be.visible');
|
closingDate
|
||||||
|
);
|
||||||
});
|
});
|
||||||
cy.wrap(
|
cy.wrap(
|
||||||
formatDateWithLocalTimezone(
|
formatDateWithLocalTimezone(
|
||||||
new Date(createTenDigitUnixTimeStampForSpecifiedDays(0) * 1000)
|
new Date(createTenDigitUnixTimeStampForSpecifiedDays(0) * 1000)
|
||||||
)
|
)
|
||||||
).then((proposalDate) => {
|
).then((proposalDate) => {
|
||||||
getProposalInformationFromTable('Proposed on')
|
getProposalInformationFromTable('Proposed on').should(
|
||||||
.contains(proposalDate)
|
'have.text',
|
||||||
.should('be.visible');
|
proposalDate
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -123,13 +127,14 @@ describe(
|
|||||||
// 3001-VOTE-067
|
// 3001-VOTE-067
|
||||||
createRawProposal();
|
createRawProposal();
|
||||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||||
getSubmittedProposalFromProposalList(
|
getProposalFromTitle(rawProposal.rationale.title).within(() =>
|
||||||
rawProposal.rationale.title
|
cy.get(viewProposalButton).click()
|
||||||
).within(() => cy.get(viewProposalButton).click());
|
);
|
||||||
});
|
});
|
||||||
cy.contains('Participation: Not Met 0.00 0.00%(0.00% Required)').should(
|
cy.contains('Participation: Not Met 0.00 0.00%(0.00% Required)').should(
|
||||||
'be.visible'
|
'be.visible'
|
||||||
);
|
);
|
||||||
|
cy.getByTestId(voteBreakdownToggle).click();
|
||||||
getProposalInformationFromTable('Expected to pass')
|
getProposalInformationFromTable('Expected to pass')
|
||||||
.contains('👎')
|
.contains('👎')
|
||||||
.should('be.visible');
|
.should('be.visible');
|
||||||
@@ -149,9 +154,9 @@ describe(
|
|||||||
it('Newly created proposal details - ability to vote for and against proposal - with minimum required tokens associated', function () {
|
it('Newly created proposal details - ability to vote for and against proposal - with minimum required tokens associated', function () {
|
||||||
createRawProposal();
|
createRawProposal();
|
||||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||||
getSubmittedProposalFromProposalList(
|
getProposalFromTitle(rawProposal.rationale.title).within(() =>
|
||||||
rawProposal.rationale.title
|
cy.get(viewProposalButton).click()
|
||||||
).within(() => cy.get(viewProposalButton).click());
|
);
|
||||||
});
|
});
|
||||||
// 3001-VOTE-080
|
// 3001-VOTE-080
|
||||||
cy.getByTestId('vote-buttons').contains('against').should('be.visible');
|
cy.getByTestId('vote-buttons').contains('against').should('be.visible');
|
||||||
@@ -177,6 +182,7 @@ describe(
|
|||||||
cy.get(proposalVoteProgressAgainstTokens)
|
cy.get(proposalVoteProgressAgainstTokens)
|
||||||
.contains('0.00')
|
.contains('0.00')
|
||||||
.and('be.visible');
|
.and('be.visible');
|
||||||
|
cy.getByTestId(voteBreakdownToggle).click();
|
||||||
getProposalInformationFromTable('Tokens for proposal')
|
getProposalInformationFromTable('Tokens for proposal')
|
||||||
.should('have.text', (1).toFixed(2))
|
.should('have.text', (1).toFixed(2))
|
||||||
.and('be.visible');
|
.and('be.visible');
|
||||||
@@ -218,14 +224,15 @@ describe(
|
|||||||
vegaWalletSetSpecifiedApprovalAmount('1000');
|
vegaWalletSetSpecifiedApprovalAmount('1000');
|
||||||
createRawProposal();
|
createRawProposal();
|
||||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||||
getSubmittedProposalFromProposalList(
|
getProposalFromTitle(rawProposal.rationale.title).within(() =>
|
||||||
rawProposal.rationale.title
|
cy.get(viewProposalButton).click()
|
||||||
).within(() => cy.get(viewProposalButton).click());
|
);
|
||||||
});
|
});
|
||||||
voteForProposal('for');
|
voteForProposal('for');
|
||||||
// 3001-VOTE-079
|
// 3001-VOTE-079
|
||||||
cy.contains('You voted: For').should('be.visible');
|
cy.contains('You voted: For').should('be.visible');
|
||||||
cy.get(proposalVoteProgressForTokens).contains('1').and('be.visible');
|
cy.get(proposalVoteProgressForTokens).contains('1').and('be.visible');
|
||||||
|
cy.getByTestId(voteBreakdownToggle).click();
|
||||||
getProposalInformationFromTable('Total Supply')
|
getProposalInformationFromTable('Total Supply')
|
||||||
.invoke('text')
|
.invoke('text')
|
||||||
.then((totalSupply) => {
|
.then((totalSupply) => {
|
||||||
@@ -233,14 +240,15 @@ describe(
|
|||||||
(Number(totalSupply.replace(/,/g, '')) * 0.001) /
|
(Number(totalSupply.replace(/,/g, '')) * 0.001) /
|
||||||
100
|
100
|
||||||
).toFixed(2);
|
).toFixed(2);
|
||||||
|
ethereumWalletConnect();
|
||||||
ensureSpecifiedUnstakedTokensAreAssociated(
|
ensureSpecifiedUnstakedTokensAreAssociated(
|
||||||
tokensRequiredToAchieveResult
|
tokensRequiredToAchieveResult
|
||||||
);
|
);
|
||||||
navigateTo(navigation.proposals);
|
navigateTo(navigation.proposals);
|
||||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||||
getSubmittedProposalFromProposalList(
|
getProposalFromTitle(rawProposal.rationale.title).within(() =>
|
||||||
rawProposal.rationale.title
|
cy.get(viewProposalButton).click()
|
||||||
).within(() => cy.get(viewProposalButton).click());
|
);
|
||||||
});
|
});
|
||||||
cy.get(proposalVoteProgressForPercentage)
|
cy.get(proposalVoteProgressForPercentage)
|
||||||
.contains('100.00%')
|
.contains('100.00%')
|
||||||
@@ -257,6 +265,7 @@ describe(
|
|||||||
cy.get(proposalVoteProgressAgainstTokens)
|
cy.get(proposalVoteProgressAgainstTokens)
|
||||||
.contains('0.00')
|
.contains('0.00')
|
||||||
.and('be.visible');
|
.and('be.visible');
|
||||||
|
cy.getByTestId(voteBreakdownToggle).click();
|
||||||
getProposalInformationFromTable('Total tokens voted percentage')
|
getProposalInformationFromTable('Total tokens voted percentage')
|
||||||
.should('have.text', '0.00%')
|
.should('have.text', '0.00%')
|
||||||
.and('be.visible');
|
.and('be.visible');
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import {
|
import {
|
||||||
navigateTo,
|
navigateTo,
|
||||||
navigation,
|
navigation,
|
||||||
|
turnTelemetryOff,
|
||||||
waitForSpinner,
|
waitForSpinner,
|
||||||
} from '../../support/common.functions';
|
} from '../../support/common.functions';
|
||||||
import {
|
import {
|
||||||
@@ -37,6 +38,7 @@ context(
|
|||||||
|
|
||||||
beforeEach('visit proposals', function () {
|
beforeEach('visit proposals', function () {
|
||||||
cy.clearLocalStorage();
|
cy.clearLocalStorage();
|
||||||
|
turnTelemetryOff();
|
||||||
cy.reload();
|
cy.reload();
|
||||||
waitForSpinner();
|
waitForSpinner();
|
||||||
cy.connectVegaWallet();
|
cy.connectVegaWallet();
|
||||||
@@ -56,14 +58,12 @@ context(
|
|||||||
.parentsUntil(proposalListItem)
|
.parentsUntil(proposalListItem)
|
||||||
.last()
|
.last()
|
||||||
.within(() => {
|
.within(() => {
|
||||||
cy.get(proposalStatus).should('have.text', 'Enacted ');
|
cy.get(proposalStatus).should('have.text', 'Enacted');
|
||||||
cy.get(viewProposalButton).click();
|
cy.get(viewProposalButton).click();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
cy.getByTestId('proposal-type').should('have.text', 'New market');
|
cy.getByTestId('proposal-type').should('have.text', 'New market');
|
||||||
getProposalInformationFromTable('State')
|
cy.get(proposalStatus).should('have.text', 'Enacted');
|
||||||
.contains('Enacted')
|
|
||||||
.and('be.visible');
|
|
||||||
cy.get(votesTable).within(() => {
|
cy.get(votesTable).within(() => {
|
||||||
cy.contains('Vote passed.').should('be.visible');
|
cy.contains('Vote passed.').should('be.visible');
|
||||||
cy.contains('Voting has ended.').should('be.visible');
|
cy.contains('Voting has ended.').should('be.visible');
|
||||||
@@ -85,16 +85,10 @@ context(
|
|||||||
.last()
|
.last()
|
||||||
.within(() => cy.get(viewProposalButton).click());
|
.within(() => cy.get(viewProposalButton).click());
|
||||||
});
|
});
|
||||||
getProposalInformationFromTable('State')
|
cy.get(proposalStatus).should('have.text', 'Open');
|
||||||
.contains('Open')
|
|
||||||
.and('be.visible');
|
|
||||||
voteForProposal('for');
|
voteForProposal('for');
|
||||||
getProposalInformationFromTable('State') // 3001-VOTE-047
|
cy.get(proposalStatus, proposalTimeout).should('have.text', 'Passed');
|
||||||
.contains('Passed', proposalTimeout)
|
cy.get(proposalStatus, proposalTimeout).should('have.text', 'Enacted');
|
||||||
.and('be.visible');
|
|
||||||
getProposalInformationFromTable('State')
|
|
||||||
.contains('Enacted', proposalTimeout)
|
|
||||||
.and('be.visible');
|
|
||||||
cy.get(votesTable).within(() => {
|
cy.get(votesTable).within(() => {
|
||||||
cy.contains('Vote passed.').should('be.visible');
|
cy.contains('Vote passed.').should('be.visible');
|
||||||
cy.contains('Voting has ended.').should('be.visible');
|
cy.contains('Voting has ended.').should('be.visible');
|
||||||
@@ -119,13 +113,9 @@ context(
|
|||||||
.last()
|
.last()
|
||||||
.within(() => cy.get(viewProposalButton).click());
|
.within(() => cy.get(viewProposalButton).click());
|
||||||
});
|
});
|
||||||
getProposalInformationFromTable('State')
|
cy.get(proposalStatus).should('have.text', 'Open');
|
||||||
.contains('Open')
|
|
||||||
.and('be.visible');
|
|
||||||
voteForProposal('for');
|
voteForProposal('for');
|
||||||
getProposalInformationFromTable('State')
|
cy.get(proposalStatus, proposalTimeout).should('have.text', 'Enacted');
|
||||||
.contains('Enacted', proposalTimeout)
|
|
||||||
.and('be.visible');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 3001-VOTE-048 3001-VOTE-049 3001-VOTE-050
|
// 3001-VOTE-048 3001-VOTE-049 3001-VOTE-050
|
||||||
@@ -142,12 +132,8 @@ context(
|
|||||||
.last()
|
.last()
|
||||||
.within(() => cy.get(viewProposalButton).click());
|
.within(() => cy.get(viewProposalButton).click());
|
||||||
});
|
});
|
||||||
getProposalInformationFromTable('State')
|
cy.get(proposalStatus).should('have.text', 'Open');
|
||||||
.contains('Open')
|
cy.get(proposalStatus, proposalTimeout).should('have.text', 'Declined');
|
||||||
.and('be.visible');
|
|
||||||
getProposalInformationFromTable('State') // 3001-VOTE-047
|
|
||||||
.contains('Declined', proposalTimeout)
|
|
||||||
.and('be.visible');
|
|
||||||
getProposalInformationFromTable('Rejection reason')
|
getProposalInformationFromTable('Rejection reason')
|
||||||
.contains('PROPOSAL_ERROR_PARTICIPATION_THRESHOLD_NOT_REACHED')
|
.contains('PROPOSAL_ERROR_PARTICIPATION_THRESHOLD_NOT_REACHED')
|
||||||
.and('be.visible');
|
.and('be.visible');
|
||||||
|
|||||||
@@ -5,10 +5,11 @@ import {
|
|||||||
enterRawProposalBody,
|
enterRawProposalBody,
|
||||||
enterUniqueFreeFormProposalBody,
|
enterUniqueFreeFormProposalBody,
|
||||||
generateFreeFormProposalTitle,
|
generateFreeFormProposalTitle,
|
||||||
|
getProposalFromTitle,
|
||||||
getProposalInformationFromTable,
|
getProposalInformationFromTable,
|
||||||
getSubmittedProposalFromProposalList,
|
|
||||||
goToMakeNewProposal,
|
goToMakeNewProposal,
|
||||||
governanceProposalType,
|
governanceProposalType,
|
||||||
|
submitUniqueRawProposal,
|
||||||
voteForProposal,
|
voteForProposal,
|
||||||
waitForProposalSubmitted,
|
waitForProposalSubmitted,
|
||||||
waitForProposalSync,
|
waitForProposalSync,
|
||||||
@@ -20,6 +21,7 @@ import {
|
|||||||
navigateTo,
|
navigateTo,
|
||||||
navigation,
|
navigation,
|
||||||
closeDialog,
|
closeDialog,
|
||||||
|
turnTelemetryOff,
|
||||||
} from '../../support/common.functions';
|
} from '../../support/common.functions';
|
||||||
import {
|
import {
|
||||||
clickOnValidatorFromList,
|
clickOnValidatorFromList,
|
||||||
@@ -80,11 +82,11 @@ context(
|
|||||||
});
|
});
|
||||||
|
|
||||||
vegaWalletSetSpecifiedApprovalAmount('1000');
|
vegaWalletSetSpecifiedApprovalAmount('1000');
|
||||||
cy.associateTokensToVegaWallet('1');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach('visit governance tab', function () {
|
beforeEach('visit governance tab', function () {
|
||||||
cy.clearLocalStorage();
|
cy.clearLocalStorage();
|
||||||
|
turnTelemetryOff();
|
||||||
cy.reload();
|
cy.reload();
|
||||||
waitForSpinner();
|
waitForSpinner();
|
||||||
cy.connectVegaWallet();
|
cy.connectVegaWallet();
|
||||||
@@ -93,7 +95,8 @@ context(
|
|||||||
navigateTo(navigation.proposals);
|
navigateTo(navigation.proposals);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should be able to see that no proposals exist', function () {
|
// Test can only pass if run before other proposal tests.
|
||||||
|
it.skip('Should be able to see that no proposals exist', function () {
|
||||||
// 3001-VOTE-003
|
// 3001-VOTE-003
|
||||||
cy.get(noOpenProposals)
|
cy.get(noOpenProposals)
|
||||||
.should('be.visible')
|
.should('be.visible')
|
||||||
@@ -105,7 +108,7 @@ context(
|
|||||||
|
|
||||||
// 3002-PROP-002
|
// 3002-PROP-002
|
||||||
// 3002-PROP-003
|
// 3002-PROP-003
|
||||||
it('Submit a proposal form - shows how many vega tokens are required to make a proposal', function () {
|
it('Proposal form - shows how many vega tokens are required to make a proposal', function () {
|
||||||
// 3002-PROP-005
|
// 3002-PROP-005
|
||||||
goToMakeNewProposal(governanceProposalType.NEW_MARKET);
|
goToMakeNewProposal(governanceProposalType.NEW_MARKET);
|
||||||
cy.contains(
|
cy.contains(
|
||||||
@@ -113,8 +116,9 @@ context(
|
|||||||
).should('be.visible');
|
).should('be.visible');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Skipping as currently unable to propose using forms other than raw
|
||||||
// 3002-PROP-011
|
// 3002-PROP-011
|
||||||
it('Able to submit a valid freeform proposal - with minimum required tokens associated', function () {
|
it.skip('Able to submit a valid freeform proposal - with minimum required tokens associated', function () {
|
||||||
goToMakeNewProposal(governanceProposalType.FREEFORM);
|
goToMakeNewProposal(governanceProposalType.FREEFORM);
|
||||||
cy.get(minVoteButton).should('be.visible'); // 3002-PROP-008
|
cy.get(minVoteButton).should('be.visible'); // 3002-PROP-008
|
||||||
cy.get(maxVoteButton).should('be.visible');
|
cy.get(maxVoteButton).should('be.visible');
|
||||||
@@ -138,16 +142,13 @@ context(
|
|||||||
closeStakingDialog();
|
closeStakingDialog();
|
||||||
|
|
||||||
cy.get(vegaWalletStakedBalances, txTimeout).should('contain', '2');
|
cy.get(vegaWalletStakedBalances, txTimeout).should('contain', '2');
|
||||||
|
createRawProposal();
|
||||||
navigateTo(navigation.proposals);
|
|
||||||
goToMakeNewProposal(governanceProposalType.FREEFORM);
|
|
||||||
enterUniqueFreeFormProposalBody('50', generateFreeFormProposalTitle());
|
|
||||||
waitForProposalSubmitted();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Creating a proposal - proposal rejected - when closing time sooner than system default', function () {
|
it.skip('Creating a proposal - proposal rejected - when closing time sooner than system default', function () {
|
||||||
goToMakeNewProposal(governanceProposalType.FREEFORM);
|
goToMakeNewProposal(governanceProposalType.FREEFORM);
|
||||||
enterUniqueFreeFormProposalBody('0.1', generateFreeFormProposalTitle());
|
enterUniqueFreeFormProposalBody('0.1', generateFreeFormProposalTitle());
|
||||||
|
|
||||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||||
'not.exist'
|
'not.exist'
|
||||||
);
|
);
|
||||||
@@ -156,7 +157,7 @@ context(
|
|||||||
.should('equal', 'Value must be greater than or equal to 1.');
|
.should('equal', 'Value must be greater than or equal to 1.');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Creating a proposal - proposal rejected - when closing time later than system default', function () {
|
it.skip('Creating a proposal - proposal rejected - when closing time later than system default', function () {
|
||||||
goToMakeNewProposal(governanceProposalType.FREEFORM);
|
goToMakeNewProposal(governanceProposalType.FREEFORM);
|
||||||
enterUniqueFreeFormProposalBody(
|
enterUniqueFreeFormProposalBody(
|
||||||
'100000',
|
'100000',
|
||||||
@@ -183,17 +184,13 @@ context(
|
|||||||
navigateTo(navigation.proposals);
|
navigateTo(navigation.proposals);
|
||||||
cy.get(rejectProposalsLink).click();
|
cy.get(rejectProposalsLink).click();
|
||||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||||
getSubmittedProposalFromProposalList(
|
getProposalFromTitle(rawProposal.rationale.title).within(() => {
|
||||||
rawProposal.rationale.title
|
|
||||||
).within(() => {
|
|
||||||
cy.contains('Rejected').should('be.visible');
|
cy.contains('Rejected').should('be.visible');
|
||||||
cy.contains('Close time too late').should('be.visible');
|
cy.contains('Close time too late').should('be.visible');
|
||||||
cy.get(viewProposalButton).click();
|
cy.get(viewProposalButton).click();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
getProposalInformationFromTable('State')
|
cy.getByTestId('proposal-status').should('have.text', 'Rejected');
|
||||||
.contains('Rejected')
|
|
||||||
.and('be.visible');
|
|
||||||
getProposalInformationFromTable('Rejection reason')
|
getProposalInformationFromTable('Rejection reason')
|
||||||
.contains('PROPOSAL_ERROR_CLOSE_TIME_TOO_LATE')
|
.contains('PROPOSAL_ERROR_CLOSE_TIME_TOO_LATE')
|
||||||
.and('be.visible');
|
.and('be.visible');
|
||||||
@@ -288,18 +285,19 @@ context(
|
|||||||
const proposalTitle = generateFreeFormProposalTitle();
|
const proposalTitle = generateFreeFormProposalTitle();
|
||||||
|
|
||||||
ensureSpecifiedUnstakedTokensAreAssociated('1');
|
ensureSpecifiedUnstakedTokensAreAssociated('1');
|
||||||
goToMakeNewProposal(governanceProposalType.FREEFORM);
|
submitUniqueRawProposal({ proposalTitle: proposalTitle });
|
||||||
enterUniqueFreeFormProposalBody('50', proposalTitle);
|
ethereumWalletConnect();
|
||||||
waitForProposalSubmitted();
|
|
||||||
stakingPageDisassociateTokens('0.0001');
|
stakingPageDisassociateTokens('0.0001');
|
||||||
cy.get(vegaWallet).within(() => {
|
cy.get(vegaWallet)
|
||||||
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
|
.first()
|
||||||
'contain',
|
.within(() => {
|
||||||
'0.9999'
|
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
|
||||||
);
|
'contain',
|
||||||
});
|
'0.9999'
|
||||||
|
);
|
||||||
|
});
|
||||||
navigateTo(navigation.proposals);
|
navigateTo(navigation.proposals);
|
||||||
getSubmittedProposalFromProposalList(proposalTitle).within(() =>
|
getProposalFromTitle(proposalTitle).within(() =>
|
||||||
cy.get(viewProposalButton).click()
|
cy.get(viewProposalButton).click()
|
||||||
);
|
);
|
||||||
cy.contains('Vote breakdown').should('be.visible', {
|
cy.contains('Vote breakdown').should('be.visible', {
|
||||||
@@ -317,9 +315,9 @@ context(
|
|||||||
cy.get('[data-testid="manage-vega-wallet"]:visible').click();
|
cy.get('[data-testid="manage-vega-wallet"]:visible').click();
|
||||||
cy.get('[data-testid="disconnect"]').click();
|
cy.get('[data-testid="disconnect"]').click();
|
||||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||||
getSubmittedProposalFromProposalList(
|
getProposalFromTitle(rawProposal.rationale.title).within(() =>
|
||||||
rawProposal.rationale.title
|
cy.get(viewProposalButton).click()
|
||||||
).within(() => cy.get(viewProposalButton).click());
|
);
|
||||||
});
|
});
|
||||||
// 3001-VOTE-075
|
// 3001-VOTE-075
|
||||||
// 3001-VOTE-076
|
// 3001-VOTE-076
|
||||||
|
|||||||
@@ -2,11 +2,13 @@ import {
|
|||||||
closeDialog,
|
closeDialog,
|
||||||
navigateTo,
|
navigateTo,
|
||||||
navigation,
|
navigation,
|
||||||
|
turnTelemetryOff,
|
||||||
waitForSpinner,
|
waitForSpinner,
|
||||||
} from '../../support/common.functions';
|
} from '../../support/common.functions';
|
||||||
import {
|
import {
|
||||||
getProposalInformationFromTable,
|
getProposalInformationFromTable,
|
||||||
goToMakeNewProposal,
|
goToMakeNewProposal,
|
||||||
|
governanceProposalType,
|
||||||
voteForProposal,
|
voteForProposal,
|
||||||
waitForProposalSubmitted,
|
waitForProposalSubmitted,
|
||||||
} from '../../support/governance.functions';
|
} from '../../support/governance.functions';
|
||||||
@@ -55,18 +57,8 @@ const fUSDCId =
|
|||||||
const epochTimeout = Cypress.env('epochTimeout');
|
const epochTimeout = Cypress.env('epochTimeout');
|
||||||
const proposalTimeout = { timeout: 14000 };
|
const proposalTimeout = { timeout: 14000 };
|
||||||
|
|
||||||
const governanceProposalType = {
|
|
||||||
NETWORK_PARAMETER: 'Network parameter',
|
|
||||||
NEW_MARKET: 'New market',
|
|
||||||
UPDATE_MARKET: 'Update market',
|
|
||||||
NEW_ASSET: 'New asset',
|
|
||||||
UPDATE_ASSET: 'Update asset',
|
|
||||||
FREEFORM: 'Freeform',
|
|
||||||
RAW: 'raw proposal',
|
|
||||||
};
|
|
||||||
|
|
||||||
// 3001-VOTE-007
|
// 3001-VOTE-007
|
||||||
context(
|
context.skip(
|
||||||
'Governance flow - form validations for different governance proposals',
|
'Governance flow - form validations for different governance proposals',
|
||||||
{ tags: '@slow' },
|
{ tags: '@slow' },
|
||||||
function () {
|
function () {
|
||||||
@@ -77,6 +69,7 @@ context(
|
|||||||
|
|
||||||
beforeEach('visit governance tab', function () {
|
beforeEach('visit governance tab', function () {
|
||||||
cy.clearLocalStorage();
|
cy.clearLocalStorage();
|
||||||
|
turnTelemetryOff();
|
||||||
cy.reload();
|
cy.reload();
|
||||||
waitForSpinner();
|
waitForSpinner();
|
||||||
cy.connectVegaWallet();
|
cy.connectVegaWallet();
|
||||||
|
|||||||
@@ -2,19 +2,19 @@ import type { testFreeformProposal } from '../../support/common-interfaces';
|
|||||||
import {
|
import {
|
||||||
navigateTo,
|
navigateTo,
|
||||||
navigation,
|
navigation,
|
||||||
|
turnTelemetryOff,
|
||||||
waitForSpinner,
|
waitForSpinner,
|
||||||
} from '../../support/common.functions';
|
} from '../../support/common.functions';
|
||||||
import {
|
import {
|
||||||
createFreeformProposal,
|
|
||||||
createRawProposal,
|
createRawProposal,
|
||||||
createTenDigitUnixTimeStampForSpecifiedDays,
|
createTenDigitUnixTimeStampForSpecifiedDays,
|
||||||
enterRawProposalBody,
|
enterRawProposalBody,
|
||||||
generateFreeFormProposalTitle,
|
generateFreeFormProposalTitle,
|
||||||
getProposalIdFromList,
|
getProposalFromTitle,
|
||||||
getProposalInformationFromTable,
|
getProposalInformationFromTable,
|
||||||
getSubmittedProposalFromProposalList,
|
|
||||||
goToMakeNewProposal,
|
goToMakeNewProposal,
|
||||||
governanceProposalType,
|
governanceProposalType,
|
||||||
|
submitUniqueRawProposal,
|
||||||
voteForProposal,
|
voteForProposal,
|
||||||
waitForProposalSubmitted,
|
waitForProposalSubmitted,
|
||||||
waitForProposalSync,
|
waitForProposalSync,
|
||||||
@@ -23,10 +23,14 @@ import { ensureSpecifiedUnstakedTokensAreAssociated } from '../../support/stakin
|
|||||||
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
|
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
|
||||||
import { vegaWalletSetSpecifiedApprovalAmount } from '../../support/wallet-teardown.functions';
|
import { vegaWalletSetSpecifiedApprovalAmount } from '../../support/wallet-teardown.functions';
|
||||||
|
|
||||||
|
const proposalListItem = 'proposals-list-item';
|
||||||
const openProposals = '[data-testid="open-proposals"]';
|
const openProposals = '[data-testid="open-proposals"]';
|
||||||
const voteStatus = '[data-testid="vote-status"]';
|
const voteStatus = 'vote-status';
|
||||||
|
const proposalType = 'proposal-type';
|
||||||
|
const proposalStatus = 'proposal-status';
|
||||||
const proposalClosingDate = '[data-testid="vote-details"]';
|
const proposalClosingDate = '[data-testid="vote-details"]';
|
||||||
const viewProposalButton = '[data-testid="view-proposal-btn"]';
|
const viewProposalButton = '[data-testid="view-proposal-btn"]';
|
||||||
|
const voteBreakDownToggle = 'vote-breakdown-toggle';
|
||||||
|
|
||||||
describe('Governance flow for proposal list', { tags: '@slow' }, function () {
|
describe('Governance flow for proposal list', { tags: '@slow' }, function () {
|
||||||
before('connect wallets and set approval limit', function () {
|
before('connect wallets and set approval limit', function () {
|
||||||
@@ -36,6 +40,7 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
|
|||||||
|
|
||||||
beforeEach('visit proposals tab', function () {
|
beforeEach('visit proposals tab', function () {
|
||||||
cy.clearLocalStorage();
|
cy.clearLocalStorage();
|
||||||
|
turnTelemetryOff();
|
||||||
cy.reload();
|
cy.reload();
|
||||||
waitForSpinner();
|
waitForSpinner();
|
||||||
cy.connectVegaWallet();
|
cy.connectVegaWallet();
|
||||||
@@ -58,12 +63,12 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
|
|||||||
|
|
||||||
navigateTo(navigation.proposals);
|
navigateTo(navigation.proposals);
|
||||||
cy.get(openProposals).within(() => {
|
cy.get(openProposals).within(() => {
|
||||||
cy.get(proposalClosingDate).first().should('contain.text', 'year');
|
|
||||||
cy.get(proposalClosingDate).should('contain.text', 'months');
|
|
||||||
cy.get(proposalClosingDate)
|
cy.get(proposalClosingDate)
|
||||||
.last()
|
.first()
|
||||||
.invoke('text')
|
.invoke('text')
|
||||||
.should('match', /days|minutes/);
|
.should('match', /days|minutes/);
|
||||||
|
cy.get(proposalClosingDate).should('contain.text', 'months');
|
||||||
|
cy.get(proposalClosingDate).last().should('contain.text', 'year');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -71,36 +76,27 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
|
|||||||
const proposerId = Cypress.env('vegaWalletPublicKey');
|
const proposerId = Cypress.env('vegaWalletPublicKey');
|
||||||
const proposalTitle = generateFreeFormProposalTitle();
|
const proposalTitle = generateFreeFormProposalTitle();
|
||||||
|
|
||||||
createFreeformProposal(proposalTitle);
|
submitUniqueRawProposal({ proposalTitle: proposalTitle });
|
||||||
getProposalIdFromList(proposalTitle);
|
cy.get('[data-testid="set-proposals-filter-visible"]').click();
|
||||||
cy.get('@proposalIdText').then((proposalId) => {
|
cy.get('[data-testid="filter-input"]').type(proposerId);
|
||||||
cy.get('[data-testid="set-proposals-filter-visible"]').click();
|
// cy.get(`#${proposalId}`).should('contain', proposalId);
|
||||||
cy.get('[data-testid="filter-input"]').type(proposerId);
|
cy.contains(proposalTitle).should('be.visible');
|
||||||
cy.get(`#${proposalId}`).should('contain', proposalId);
|
cy.get('[data-testid="filter-input"]').type('123');
|
||||||
});
|
cy.getByTestId(proposalListItem).should('not.exist');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Newly created proposals list - shows title and portion of summary', function () {
|
it('Newly created proposals list - shows title and portion of summary', function () {
|
||||||
createRawProposal(this.minProposerBalance); // 3001-VOTE-052
|
const proposalPath = '/proposals/new-market-raw.json';
|
||||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
const enactmentTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(3);
|
||||||
getProposalIdFromList(rawProposal.rationale.title);
|
submitUniqueRawProposal({
|
||||||
cy.get('@proposalIdText').then((proposalId) => {
|
proposalBody: proposalPath,
|
||||||
cy.get(openProposals).within(() => {
|
enactmentTimestamp: enactmentTimestamp,
|
||||||
// 3001-VOTE-008
|
}); // 3001-VOTE-052
|
||||||
// 3001-VOTE-034
|
// 3001-VOTE-008
|
||||||
cy.get(`#${proposalId}`)
|
// 3001-VOTE-034
|
||||||
// 3001-VOTE-097
|
// 3001-VOTE-097
|
||||||
.should('contain', rawProposal.rationale.title)
|
cy.contains('New Market Proposal E2E submission');
|
||||||
.and('be.visible');
|
cy.contains('Code: TEST.24h. fBTC settled future.').should('be.visible');
|
||||||
cy.get(`#${proposalId}`)
|
|
||||||
.should(
|
|
||||||
'contain',
|
|
||||||
rawProposal.rationale.description.substring(0, 59)
|
|
||||||
)
|
|
||||||
.and('be.visible');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Newly created proposals list - shows open proposals in an open state', function () {
|
it('Newly created proposals list - shows open proposals in an open state', function () {
|
||||||
@@ -108,23 +104,11 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
|
|||||||
// 3001-VOTE-035
|
// 3001-VOTE-035
|
||||||
createRawProposal(this.minProposerBalance);
|
createRawProposal(this.minProposerBalance);
|
||||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||||
getSubmittedProposalFromProposalList(rawProposal.rationale.title).within(
|
getProposalFromTitle(rawProposal.rationale.title).within(() => {
|
||||||
() => {
|
cy.get(viewProposalButton).should('be.visible');
|
||||||
cy.get(viewProposalButton).should('be.visible').click();
|
cy.getByTestId(proposalType).should('have.text', 'Freeform');
|
||||||
}
|
cy.getByTestId(proposalStatus).should('have.text', 'Open');
|
||||||
);
|
|
||||||
|
|
||||||
cy.get('@proposalIdText').then((proposalId) => {
|
|
||||||
getProposalInformationFromTable('ID')
|
|
||||||
.contains(String(proposalId))
|
|
||||||
.and('be.visible');
|
|
||||||
});
|
});
|
||||||
getProposalInformationFromTable('State')
|
|
||||||
.contains('Open')
|
|
||||||
.and('be.visible');
|
|
||||||
getProposalInformationFromTable('Type')
|
|
||||||
.contains('Freeform')
|
|
||||||
.and('be.visible');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -132,18 +116,22 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
|
|||||||
it('Newly created freeform proposals list - shows proposal participation - both met and not', function () {
|
it('Newly created freeform proposals list - shows proposal participation - both met and not', function () {
|
||||||
const proposalTitle = generateFreeFormProposalTitle();
|
const proposalTitle = generateFreeFormProposalTitle();
|
||||||
|
|
||||||
createFreeformProposal(proposalTitle);
|
submitUniqueRawProposal({ proposalTitle: proposalTitle });
|
||||||
getSubmittedProposalFromProposalList(proposalTitle).within(() => {
|
getProposalFromTitle(proposalTitle).within(() => {
|
||||||
// 3001-VOTE-039
|
// 3001-VOTE-039
|
||||||
cy.get(voteStatus).should('have.text', 'Participation not reached');
|
cy.getByTestId(voteStatus).should(
|
||||||
|
'have.text',
|
||||||
|
'Participation not reached'
|
||||||
|
);
|
||||||
cy.get(viewProposalButton).click();
|
cy.get(viewProposalButton).click();
|
||||||
});
|
});
|
||||||
voteForProposal('for');
|
voteForProposal('for');
|
||||||
navigateTo(navigation.proposals);
|
navigateTo(navigation.proposals);
|
||||||
getSubmittedProposalFromProposalList(proposalTitle).within(() => {
|
getProposalFromTitle(proposalTitle).within(() => {
|
||||||
cy.get(voteStatus).should('have.text', 'Set to pass');
|
cy.getByTestId(voteStatus).should('have.text', 'Set to pass');
|
||||||
cy.get(viewProposalButton).click();
|
cy.get(viewProposalButton).click();
|
||||||
});
|
});
|
||||||
|
cy.getByTestId(voteBreakDownToggle).click();
|
||||||
getProposalInformationFromTable('Token participation met')
|
getProposalInformationFromTable('Token participation met')
|
||||||
.contains('👍')
|
.contains('👍')
|
||||||
.should('be.visible');
|
.should('be.visible');
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
navigateTo,
|
navigateTo,
|
||||||
navigation,
|
navigation,
|
||||||
|
turnTelemetryOff,
|
||||||
waitForSpinner,
|
waitForSpinner,
|
||||||
} from '../../support/common.functions';
|
} from '../../support/common.functions';
|
||||||
import {
|
import {
|
||||||
@@ -26,6 +27,7 @@ const rewardsTimeOut = { timeout: 60000 };
|
|||||||
context('rewards - flow', { tags: '@slow' }, function () {
|
context('rewards - flow', { tags: '@slow' }, function () {
|
||||||
before('set up environment to allow rewards', function () {
|
before('set up environment to allow rewards', function () {
|
||||||
cy.clearLocalStorage();
|
cy.clearLocalStorage();
|
||||||
|
turnTelemetryOff();
|
||||||
cy.visit('/');
|
cy.visit('/');
|
||||||
waitForSpinner();
|
waitForSpinner();
|
||||||
depositAsset(vegaAssetAddress, '1000', 18);
|
depositAsset(vegaAssetAddress, '1000', 18);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
waitForSpinner,
|
waitForSpinner,
|
||||||
navigateTo,
|
navigateTo,
|
||||||
navigation,
|
navigation,
|
||||||
|
turnTelemetryOff,
|
||||||
} from '../../support/common.functions';
|
} from '../../support/common.functions';
|
||||||
import {
|
import {
|
||||||
clickOnValidatorFromList,
|
clickOnValidatorFromList,
|
||||||
@@ -67,6 +68,7 @@ context(
|
|||||||
'teardown wallet & drill into a specific validator',
|
'teardown wallet & drill into a specific validator',
|
||||||
function () {
|
function () {
|
||||||
cy.clearLocalStorage();
|
cy.clearLocalStorage();
|
||||||
|
turnTelemetryOff();
|
||||||
cy.reload();
|
cy.reload();
|
||||||
waitForSpinner();
|
waitForSpinner();
|
||||||
cy.connectVegaWallet();
|
cy.connectVegaWallet();
|
||||||
@@ -94,7 +96,7 @@ context(
|
|||||||
navigateTo(navigation.validators);
|
navigateTo(navigation.validators);
|
||||||
|
|
||||||
// 2002-SINC-007
|
// 2002-SINC-007
|
||||||
validateValidatorListTotalStakeAndShare('0', '2.00', '100.00%');
|
validateValidatorListTotalStakeAndShare('0', '3,002.00', '50.02%');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Able to view validators staked by me', function () {
|
it('Able to view validators staked by me', function () {
|
||||||
@@ -144,7 +146,7 @@ context(
|
|||||||
verifyThisEpochValue(2.0);
|
verifyThisEpochValue(2.0);
|
||||||
closeStakingDialog();
|
closeStakingDialog();
|
||||||
navigateTo(navigation.validators);
|
navigateTo(navigation.validators);
|
||||||
validateValidatorListTotalStakeAndShare('0', '2.00', '100.00%');
|
validateValidatorListTotalStakeAndShare('0', '3,002.00', '50.02%');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Able to stake against a validator - using vega from both wallet and vesting contract', function () {
|
it('Able to stake against a validator - using vega from both wallet and vesting contract', function () {
|
||||||
@@ -164,10 +166,11 @@ context(
|
|||||||
verifyThisEpochValue(6.0);
|
verifyThisEpochValue(6.0);
|
||||||
closeStakingDialog();
|
closeStakingDialog();
|
||||||
navigateTo(navigation.validators);
|
navigateTo(navigation.validators);
|
||||||
validateValidatorListTotalStakeAndShare('0', '6.00', '100.00%');
|
validateValidatorListTotalStakeAndShare('0', '3,006.00', '50.05%');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Able to stake against multiple validators', function () {
|
it('Able to stake against multiple validators', function () {
|
||||||
|
vegaWalletTeardown();
|
||||||
stakingPageAssociateTokens('5');
|
stakingPageAssociateTokens('5');
|
||||||
verifyUnstakedBalance(5.0);
|
verifyUnstakedBalance(5.0);
|
||||||
cy.get('button').contains('Select a validator to nominate').click();
|
cy.get('button').contains('Select a validator to nominate').click();
|
||||||
@@ -195,14 +198,10 @@ context(
|
|||||||
.eq(1)
|
.eq(1)
|
||||||
.within(() => {
|
.within(() => {
|
||||||
cy.getByTestId(stakeValidatorListTotalStake)
|
cy.getByTestId(stakeValidatorListTotalStake)
|
||||||
.should('have.text', '2.00')
|
.should('have.text', '3,002.00')
|
||||||
.and('be.visible');
|
.and('be.visible');
|
||||||
cy.getByTestId(stakeValidatorListTotalShare)
|
cy.getByTestId(stakeValidatorListTotalShare)
|
||||||
.should('have.text', '66.67%')
|
.should('have.text', '50.01%')
|
||||||
.and('be.visible');
|
|
||||||
cy.getByTestId(stakeValidatorListTotalStake)
|
|
||||||
.scrollIntoView()
|
|
||||||
.should('have.text', '2.00')
|
|
||||||
.and('be.visible');
|
.and('be.visible');
|
||||||
});
|
});
|
||||||
cy.get(`[row-id="${1}"]`)
|
cy.get(`[row-id="${1}"]`)
|
||||||
@@ -210,14 +209,10 @@ context(
|
|||||||
.within(() => {
|
.within(() => {
|
||||||
cy.getByTestId(stakeValidatorListTotalStake)
|
cy.getByTestId(stakeValidatorListTotalStake)
|
||||||
.scrollIntoView()
|
.scrollIntoView()
|
||||||
.should('have.text', '1.00')
|
.should('have.text', '3,001.00')
|
||||||
.and('be.visible');
|
.and('be.visible');
|
||||||
cy.getByTestId(stakeValidatorListTotalShare)
|
cy.getByTestId(stakeValidatorListTotalShare)
|
||||||
.should('have.text', '33.33%')
|
.should('have.text', '49.99%')
|
||||||
.and('be.visible');
|
|
||||||
cy.getByTestId(stakeValidatorListTotalStake)
|
|
||||||
.scrollIntoView()
|
|
||||||
.should('have.text', '1.00')
|
|
||||||
.and('be.visible');
|
.and('be.visible');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -252,10 +247,10 @@ context(
|
|||||||
waitForBeginningOfEpoch();
|
waitForBeginningOfEpoch();
|
||||||
cy.getByTestId(stakeValidatorListStakePercentage).should(
|
cy.getByTestId(stakeValidatorListStakePercentage).should(
|
||||||
'have.text',
|
'have.text',
|
||||||
'100%'
|
'50.02%'
|
||||||
);
|
);
|
||||||
navigateTo(navigation.validators);
|
navigateTo(navigation.validators);
|
||||||
validateValidatorListTotalStakeAndShare('0', '2.00', '100.00%');
|
validateValidatorListTotalStakeAndShare('0', '3,002.00', '50.02%');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -280,7 +275,7 @@ context(
|
|||||||
txTimeout
|
txTimeout
|
||||||
);
|
);
|
||||||
navigateTo(navigation.validators);
|
navigateTo(navigation.validators);
|
||||||
validateValidatorListTotalStakeAndShare('0', '0.00', '0.00%');
|
validateValidatorListTotalStakeAndShare('0', '3,000.00', '50.00%');
|
||||||
|
|
||||||
cy.getByTestId(userStakeBtn).should('not.exist');
|
cy.getByTestId(userStakeBtn).should('not.exist');
|
||||||
cy.getByTestId(userStake).should('not.exist');
|
cy.getByTestId(userStake).should('not.exist');
|
||||||
@@ -352,7 +347,7 @@ context(
|
|||||||
txTimeout
|
txTimeout
|
||||||
);
|
);
|
||||||
navigateTo(navigation.validators);
|
navigateTo(navigation.validators);
|
||||||
validateValidatorListTotalStakeAndShare('0', '0.00', '0.00%');
|
validateValidatorListTotalStakeAndShare('0', '3,000.00', '50.00%');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Disassociating all vesting contract tokens max - removes all staked tokens', function () {
|
it('Disassociating all vesting contract tokens max - removes all staked tokens', function () {
|
||||||
@@ -380,7 +375,7 @@ context(
|
|||||||
txTimeout
|
txTimeout
|
||||||
);
|
);
|
||||||
navigateTo(navigation.validators);
|
navigateTo(navigation.validators);
|
||||||
validateValidatorListTotalStakeAndShare('0', '0.00', '0.00%');
|
validateValidatorListTotalStakeAndShare('0', '3,000.00', '50.00%');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Disassociating some tokens - prioritizes unstaked tokens', function () {
|
it('Disassociating some tokens - prioritizes unstaked tokens', function () {
|
||||||
@@ -402,7 +397,7 @@ context(
|
|||||||
});
|
});
|
||||||
verifyStakedBalance(2.0);
|
verifyStakedBalance(2.0);
|
||||||
navigateTo(navigation.validators);
|
navigateTo(navigation.validators);
|
||||||
validateValidatorListTotalStakeAndShare('0', '2.00', '100.00%');
|
validateValidatorListTotalStakeAndShare('0', '3,002.00', '50.02%');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Associating wallet tokens - when some already staked - auto stakes tokens to staked validator', function () {
|
it('Associating wallet tokens - when some already staked - auto stakes tokens to staked validator', function () {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
waitForSpinner,
|
waitForSpinner,
|
||||||
navigateTo,
|
navigateTo,
|
||||||
navigation,
|
navigation,
|
||||||
|
turnTelemetryOff,
|
||||||
} from '../../support/common.functions';
|
} from '../../support/common.functions';
|
||||||
import {
|
import {
|
||||||
stakingPageAssociateTokens,
|
stakingPageAssociateTokens,
|
||||||
@@ -54,6 +55,7 @@ context(
|
|||||||
'teardown wallet & drill into a specific validator',
|
'teardown wallet & drill into a specific validator',
|
||||||
function () {
|
function () {
|
||||||
cy.clearLocalStorage();
|
cy.clearLocalStorage();
|
||||||
|
turnTelemetryOff();
|
||||||
cy.reload();
|
cy.reload();
|
||||||
waitForSpinner();
|
waitForSpinner();
|
||||||
cy.connectVegaWallet();
|
cy.connectVegaWallet();
|
||||||
@@ -109,10 +111,10 @@ context(
|
|||||||
// 1004-ASSO-028
|
// 1004-ASSO-028
|
||||||
// 1004-ASSO-029
|
// 1004-ASSO-029
|
||||||
// 1004-ASSO-031
|
// 1004-ASSO-031
|
||||||
|
vegaWalletTeardown();
|
||||||
stakingPageAssociateTokens('2');
|
stakingPageAssociateTokens('2');
|
||||||
verifyEthWalletAssociatedBalance('2.0');
|
verifyEthWalletAssociatedBalance('2.0');
|
||||||
verifyEthWalletTotalAssociatedBalance('2.0');
|
verifyEthWalletTotalAssociatedBalance('6,002.00');
|
||||||
cy.get('button').contains('Select a validator to nominate').click();
|
cy.get('button').contains('Select a validator to nominate').click();
|
||||||
stakingPageDisassociateTokens('2');
|
stakingPageDisassociateTokens('2');
|
||||||
cy.getByTestId('currency-title', txTimeout).should(
|
cy.getByTestId('currency-title', txTimeout).should(
|
||||||
@@ -123,17 +125,18 @@ context(
|
|||||||
validateWalletCurrency('Pending association', '2.00');
|
validateWalletCurrency('Pending association', '2.00');
|
||||||
validateWalletCurrency('Total associated after pending', '0.00');
|
validateWalletCurrency('Total associated after pending', '0.00');
|
||||||
cy.getByTestId('currency-title', txTimeout).should('have.length', 6);
|
cy.getByTestId('currency-title', txTimeout).should('have.length', 6);
|
||||||
cy.getByTestId('eth-wallet-associated-balances', txTimeout).should(
|
cy.get(
|
||||||
'not.exist'
|
'[data-testid="eth-wallet-associated-balances"]:visible',
|
||||||
);
|
txTimeout
|
||||||
verifyEthWalletTotalAssociatedBalance('0.00');
|
).should('have.length', 2);
|
||||||
|
verifyEthWalletTotalAssociatedBalance('6,000.00');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Able to associate more tokens than the approved amount of 1000 - requires re-approval', function () {
|
it('Able to associate more tokens than the approved amount of 1000 - requires re-approval', function () {
|
||||||
//1004-ASSO-011
|
//1004-ASSO-011
|
||||||
stakingPageAssociateTokens('1001', { approve: true });
|
stakingPageAssociateTokens('1001', { approve: true });
|
||||||
verifyEthWalletAssociatedBalance('1,001.00');
|
verifyEthWalletAssociatedBalance('1,001.00');
|
||||||
verifyEthWalletTotalAssociatedBalance('1,001.00');
|
verifyEthWalletTotalAssociatedBalance('7,001.00');
|
||||||
cy.get(vegaWallet)
|
cy.get(vegaWallet)
|
||||||
.last()
|
.last()
|
||||||
.within(() => {
|
.within(() => {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
navigateTo,
|
navigateTo,
|
||||||
navigation,
|
navigation,
|
||||||
|
turnTelemetryOff,
|
||||||
waitForSpinner,
|
waitForSpinner,
|
||||||
} from '../../support/common.functions';
|
} from '../../support/common.functions';
|
||||||
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
|
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
|
||||||
@@ -46,15 +47,13 @@ context(
|
|||||||
function () {
|
function () {
|
||||||
before('visit withdrawals and connect vega wallet', function () {
|
before('visit withdrawals and connect vega wallet', function () {
|
||||||
cy.visit('/');
|
cy.visit('/');
|
||||||
// When running tests locally, will fail if run without restarting capsule
|
ethereumWalletConnect();
|
||||||
cy.updateCapsuleMultiSig().then(() => {
|
depositAsset(usdcEthAddress, '1000', 5);
|
||||||
ethereumWalletConnect();
|
|
||||||
depositAsset(usdcEthAddress, '1000', 5);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach('Navigate to withdrawal page', function () {
|
beforeEach('Navigate to withdrawal page', function () {
|
||||||
cy.clearLocalStorage();
|
cy.clearLocalStorage();
|
||||||
|
turnTelemetryOff();
|
||||||
cy.reload();
|
cy.reload();
|
||||||
waitForSpinner();
|
waitForSpinner();
|
||||||
navigateTo(navigation.withdraw);
|
navigateTo(navigation.withdraw);
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
|
|||||||
cy.getByTestId('menu-drawer').should('be.visible');
|
cy.getByTestId('menu-drawer').should('be.visible');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have link for proposal page', function () {
|
it.skip('should have link for proposal page', function () {
|
||||||
cy.getByTestId('menu-drawer').within(() => {
|
cy.getByTestId('menu-drawer').within(() => {
|
||||||
cy.get('[href="/proposals"]')
|
cy.get('[href="/proposals"]')
|
||||||
.should('exist')
|
.should('exist')
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ context(
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to see button for - new proposal', function () {
|
it.skip('should be able to see button for - new proposal', function () {
|
||||||
// 3001-VOTE-002
|
// 3001-VOTE-002
|
||||||
cy.get(newProposalLink)
|
cy.get(newProposalLink)
|
||||||
.should('be.visible')
|
.should('be.visible')
|
||||||
@@ -63,7 +63,7 @@ context(
|
|||||||
.and('equal', '/proposals/propose');
|
.and('equal', '/proposals/propose');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to see a connect wallet button - if vega wallet disconnected and user is submitting new proposal', function () {
|
it.skip('should be able to see a connect wallet button - if vega wallet disconnected and user is submitting new proposal', function () {
|
||||||
goToMakeNewProposal(governanceProposalType.NETWORK_PARAMETER);
|
goToMakeNewProposal(governanceProposalType.NETWORK_PARAMETER);
|
||||||
cy.get(connectToVegaWalletButton)
|
cy.get(connectToVegaWalletButton)
|
||||||
.should('be.visible')
|
.should('be.visible')
|
||||||
@@ -109,7 +109,7 @@ context(
|
|||||||
);
|
);
|
||||||
cy.getByTestId('protocol-upgrade-proposal-status').should(
|
cy.getByTestId('protocol-upgrade-proposal-status').should(
|
||||||
'have.text',
|
'have.text',
|
||||||
'Approved '
|
'Approved by validators '
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -136,7 +136,7 @@ context(
|
|||||||
);
|
);
|
||||||
cy.getByTestId('protocol-upgrade-state').should(
|
cy.getByTestId('protocol-upgrade-state').should(
|
||||||
'have.text',
|
'have.text',
|
||||||
'Approved'
|
'Approved by validators'
|
||||||
);
|
);
|
||||||
cy.getByTestId('protocol-upgrade-release-tag').should(
|
cy.getByTestId('protocol-upgrade-release-tag').should(
|
||||||
'have.text',
|
'have.text',
|
||||||
|
|||||||
@@ -3,11 +3,13 @@
|
|||||||
import {
|
import {
|
||||||
navigateTo,
|
navigateTo,
|
||||||
navigation,
|
navigation,
|
||||||
|
turnTelemetryOff,
|
||||||
waitForSpinner,
|
waitForSpinner,
|
||||||
} from '../../support/common.functions';
|
} from '../../support/common.functions';
|
||||||
import {
|
import {
|
||||||
enterUniqueFreeFormProposalBody,
|
enterUniqueFreeFormProposalBody,
|
||||||
goToMakeNewProposal,
|
goToMakeNewProposal,
|
||||||
|
governanceProposalType,
|
||||||
} from '../../support/governance.functions';
|
} from '../../support/governance.functions';
|
||||||
import { vegaWalletFaucetAssetsWithoutCheck } from '../../support/wallet-vega.functions';
|
import { vegaWalletFaucetAssetsWithoutCheck } from '../../support/wallet-vega.functions';
|
||||||
|
|
||||||
@@ -26,6 +28,7 @@ context('View functionality with public key', { tags: '@smoke' }, function () {
|
|||||||
|
|
||||||
beforeEach('visit home page', function () {
|
beforeEach('visit home page', function () {
|
||||||
cy.clearLocalStorage();
|
cy.clearLocalStorage();
|
||||||
|
turnTelemetryOff();
|
||||||
cy.visit('/');
|
cy.visit('/');
|
||||||
waitForSpinner();
|
waitForSpinner();
|
||||||
cy.connectPublicKey(vegaWalletPubKey);
|
cy.connectPublicKey(vegaWalletPubKey);
|
||||||
@@ -44,11 +47,11 @@ context('View functionality with public key', { tags: '@smoke' }, function () {
|
|||||||
.and('contain.text', 'USDC (fake)');
|
.and('contain.text', 'USDC (fake)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Unable to submit proposal with public key', function () {
|
it.skip('Unable to submit proposal with public key', function () {
|
||||||
const expectedErrorTxt = `You are connected in a view only state for public key: ${vegaWalletPubKey}. In order to send transactions you must connect to a real wallet.`;
|
const expectedErrorTxt = `You are connected in a view only state for public key: ${vegaWalletPubKey}. In order to send transactions you must connect to a real wallet.`;
|
||||||
|
|
||||||
navigateTo(navigation.proposals);
|
navigateTo(navigation.proposals);
|
||||||
goToMakeNewProposal('Freeform');
|
goToMakeNewProposal(governanceProposalType.FREEFORM);
|
||||||
enterUniqueFreeFormProposalBody('50', 'pub key proposal test');
|
enterUniqueFreeFormProposalBody('50', 'pub key proposal test');
|
||||||
cy.getByTestId('dialog-content')
|
cy.getByTestId('dialog-content')
|
||||||
.first()
|
.first()
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ context(
|
|||||||
{ tags: '@regression' },
|
{ tags: '@regression' },
|
||||||
function () {
|
function () {
|
||||||
before('navigate to rewards page', function () {
|
before('navigate to rewards page', function () {
|
||||||
cy.clearLocalStorage();
|
|
||||||
cy.visit('/');
|
cy.visit('/');
|
||||||
navigateTo(navigation.rewards);
|
navigateTo(navigation.rewards);
|
||||||
});
|
});
|
||||||
@@ -64,7 +63,6 @@ context(
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should have option to go to last and newest page', function () {
|
it('should have option to go to last and newest page', function () {
|
||||||
waitForBeginningOfEpoch();
|
|
||||||
cy.getByTestId('goto-last-page').click();
|
cy.getByTestId('goto-last-page').click();
|
||||||
cy.getByTestId('epoch-total-rewards-table')
|
cy.getByTestId('epoch-total-rewards-table')
|
||||||
.last()
|
.last()
|
||||||
|
|||||||
@@ -29,11 +29,10 @@ const performancePenaltyToolTip = '[data-testid="performance-penalty-tooltip"]';
|
|||||||
const overstakedPenaltyToolTip = '[data-testid="overstaked-penalty-tooltip"]';
|
const overstakedPenaltyToolTip = '[data-testid="overstaked-penalty-tooltip"]';
|
||||||
const totalPenaltyToolTip = '[data-testid="total-penalty-tooltip"]';
|
const totalPenaltyToolTip = '[data-testid="total-penalty-tooltip"]';
|
||||||
const epochCountDown = '[data-testid="epoch-countdown"]';
|
const epochCountDown = '[data-testid="epoch-countdown"]';
|
||||||
const stakeNumberRegex = /^\d*\.?\d*$/;
|
const stakeNumberRegex = /^\d{1,3}(,\d{3})*(\.\d+)?$/;
|
||||||
|
|
||||||
context('Validators Page - verify elements on page', function () {
|
context('Validators Page - verify elements on page', function () {
|
||||||
before('navigate to validators page', function () {
|
before('navigate to validators page', function () {
|
||||||
cy.clearAllLocalStorage();
|
|
||||||
cy.visit('/validators');
|
cy.visit('/validators');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -85,13 +84,13 @@ context('Validators Page - verify elements on page', function () {
|
|||||||
|
|
||||||
cy.get(stakedByOperatorToolTip)
|
cy.get(stakedByOperatorToolTip)
|
||||||
.invoke('text')
|
.invoke('text')
|
||||||
.should('contain', 'Staked by operator: 0.00');
|
.should('contain', 'Staked by operator: 3,000.00');
|
||||||
cy.get(stakedByDelegatesToolTip)
|
cy.get(stakedByDelegatesToolTip)
|
||||||
.invoke('text')
|
.invoke('text')
|
||||||
.should('contain', 'Staked by delegates: 0.00');
|
.should('contain', 'Staked by delegates: 0.00');
|
||||||
cy.get(totalStakedToolTip)
|
cy.get(totalStakedToolTip)
|
||||||
.invoke('text')
|
.invoke('text')
|
||||||
.should('contain', 'Total stake: 0.00');
|
.should('contain', 'Total stake: 3,000.00');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should be able to see validator normalised voting power', function () {
|
it('Should be able to see validator normalised voting power', function () {
|
||||||
@@ -107,10 +106,10 @@ context('Validators Page - verify elements on page', function () {
|
|||||||
|
|
||||||
cy.get(unnormalisedVotingPowerToolTip)
|
cy.get(unnormalisedVotingPowerToolTip)
|
||||||
.invoke('text')
|
.invoke('text')
|
||||||
.should('contain', 'Unnormalised voting power: 0.00%');
|
.should('contain', 'Unnormalised voting power: 20.00%');
|
||||||
cy.get(normalisedVotingPowerToolTip)
|
cy.get(normalisedVotingPowerToolTip)
|
||||||
.invoke('text')
|
.invoke('text')
|
||||||
.should('contain', 'Normalised voting power: 0.10%');
|
.should('contain', 'Normalised voting power: 50.00%');
|
||||||
});
|
});
|
||||||
|
|
||||||
// 2002-SINC-018
|
// 2002-SINC-018
|
||||||
@@ -127,13 +126,13 @@ context('Validators Page - verify elements on page', function () {
|
|||||||
|
|
||||||
cy.get(performancePenaltyToolTip)
|
cy.get(performancePenaltyToolTip)
|
||||||
.invoke('text')
|
.invoke('text')
|
||||||
.should('contain', 'Performance penalty: 100.00%');
|
.should('contain', 'Performance penalty: 0.00%');
|
||||||
cy.get(overstakedPenaltyToolTip)
|
cy.get(overstakedPenaltyToolTip)
|
||||||
.invoke('text')
|
.invoke('text')
|
||||||
.should('contain', 'Overstaked penalty:'); // value not asserted due to #2886
|
.should('contain', 'Overstaked penalty: 60.00%'); // value not asserted due to #2886
|
||||||
cy.get(totalPenaltyToolTip)
|
cy.get(totalPenaltyToolTip)
|
||||||
.invoke('text')
|
.invoke('text')
|
||||||
.should('contain', 'Total penalties: 0.00%');
|
.should('contain', 'Total penalties: 60.00%');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should be able to see validator pending stake', function () {
|
it('Should be able to see validator pending stake', function () {
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ context(
|
|||||||
{ tags: '@regression' },
|
{ tags: '@regression' },
|
||||||
() => {
|
() => {
|
||||||
before('visit token home page', () => {
|
before('visit token home page', () => {
|
||||||
cy.clearAllLocalStorage();
|
|
||||||
cy.visit('/');
|
cy.visit('/');
|
||||||
cy.get(walletContainer, { timeout: 60000 }).should('be.visible');
|
cy.get(walletContainer, { timeout: 60000 }).should('be.visible');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ context(
|
|||||||
{ tags: '@smoke' },
|
{ tags: '@smoke' },
|
||||||
function () {
|
function () {
|
||||||
before('navigate to withdrawals page', function () {
|
before('navigate to withdrawals page', function () {
|
||||||
cy.clearAllLocalStorage();
|
|
||||||
cy.visit('/');
|
cy.visit('/');
|
||||||
navigateTo(navigation.withdraw);
|
navigateTo(navigation.withdraw);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -90,3 +90,10 @@ export function verifyEthWalletAssociatedBalance(amount: string) {
|
|||||||
export function closeDialog() {
|
export function closeDialog() {
|
||||||
cy.getByTestId('dialog-close').click();
|
cy.getByTestId('dialog-close').click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function turnTelemetryOff() {
|
||||||
|
// Ensuring the telemetry modal doesn't disrupt the tests
|
||||||
|
cy.window().then((win) =>
|
||||||
|
win.localStorage.setItem('vega_telemetry_on', 'false')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
import { format } from 'date-fns';
|
import { format } from 'date-fns';
|
||||||
import { closeDialog, navigateTo, navigation } from './common.functions';
|
import {
|
||||||
|
closeDialog,
|
||||||
|
navigateTo,
|
||||||
|
navigation,
|
||||||
|
waitForSpinner,
|
||||||
|
} from './common.functions';
|
||||||
import { ensureSpecifiedUnstakedTokensAreAssociated } from './staking.functions';
|
import { ensureSpecifiedUnstakedTokensAreAssociated } from './staking.functions';
|
||||||
|
|
||||||
const newProposalButton = '[data-testid="new-proposal-link"]';
|
|
||||||
const proposalInformationTableRows = '[data-testid="key-value-table-row"]';
|
const proposalInformationTableRows = '[data-testid="key-value-table-row"]';
|
||||||
const proposalListItem = '[data-testid="proposals-list-item"]';
|
const proposalListItem = '[data-testid="proposals-list-item"]';
|
||||||
const newProposalTitle = '[data-testid="proposal-title"]';
|
const newProposalTitle = '[data-testid="proposal-title"]';
|
||||||
@@ -46,6 +50,53 @@ export function enterRawProposalBody(timestamp: number) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function submitUniqueRawProposal(proposalFields: {
|
||||||
|
proposalBody?: string;
|
||||||
|
proposalTitle?: string;
|
||||||
|
proposalDescription?: string;
|
||||||
|
closingTimestamp?: number;
|
||||||
|
enactmentTimestamp?: number;
|
||||||
|
submit?: boolean;
|
||||||
|
}) {
|
||||||
|
goToMakeNewProposal(governanceProposalType.RAW);
|
||||||
|
let proposalBodyPath = '/proposals/raw.json';
|
||||||
|
if (proposalFields.proposalBody) {
|
||||||
|
proposalBodyPath = proposalFields.proposalBody;
|
||||||
|
}
|
||||||
|
cy.fixture(proposalBodyPath).then((rawProposal) => {
|
||||||
|
if (proposalFields.proposalTitle) {
|
||||||
|
rawProposal.rationale.title = proposalFields.proposalTitle;
|
||||||
|
cy.wrap(proposalFields.proposalTitle).as('proposalTitle');
|
||||||
|
}
|
||||||
|
if (proposalFields.proposalDescription) {
|
||||||
|
rawProposal.rationale.description = proposalFields.proposalDescription;
|
||||||
|
}
|
||||||
|
if (proposalFields.closingTimestamp) {
|
||||||
|
rawProposal.terms.closingTimestamp = proposalFields.closingTimestamp;
|
||||||
|
} else {
|
||||||
|
const minTimeStamp = createTenDigitUnixTimeStampForSpecifiedDays(2);
|
||||||
|
rawProposal.terms.closingTimestamp = minTimeStamp;
|
||||||
|
}
|
||||||
|
if (proposalFields.enactmentTimestamp) {
|
||||||
|
rawProposal.terms.enactmentTimestamp = proposalFields.enactmentTimestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
const proposalPayload = JSON.stringify(rawProposal);
|
||||||
|
cy.get(rawProposalData).type(proposalPayload, {
|
||||||
|
parseSpecialCharSequences: false,
|
||||||
|
delay: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (proposalFields.submit !== false) {
|
||||||
|
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||||
|
cy.wrap(rawProposal).as('rawProposal');
|
||||||
|
waitForProposalSubmitted();
|
||||||
|
waitForProposalSync();
|
||||||
|
navigateTo(navigation.proposals);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function enterUniqueFreeFormProposalBody(
|
export function enterUniqueFreeFormProposalBody(
|
||||||
timestamp: string,
|
timestamp: string,
|
||||||
proposalTitle: string
|
proposalTitle: string
|
||||||
@@ -58,6 +109,10 @@ export function enterUniqueFreeFormProposalBody(
|
|||||||
cy.getByTestId('proposal-submit').should('be.visible').click();
|
cy.getByTestId('proposal-submit').should('be.visible').click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getProposalFromTitle(proposalTitle: string) {
|
||||||
|
return cy.contains(proposalTitle).parentsUntil(proposalListItem).last();
|
||||||
|
}
|
||||||
|
|
||||||
export function getSubmittedProposalFromProposalList(proposalTitle: string) {
|
export function getSubmittedProposalFromProposalList(proposalTitle: string) {
|
||||||
getProposalIdFromList(proposalTitle);
|
getProposalIdFromList(proposalTitle);
|
||||||
cy.get('@proposalIdText').then((proposalId) => {
|
cy.get('@proposalIdText').then((proposalId) => {
|
||||||
@@ -120,13 +175,17 @@ export function waitForProposalSync() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function goToMakeNewProposal(proposalType: string) {
|
export function goToMakeNewProposal(proposalType: governanceProposalType) {
|
||||||
navigateTo(navigation.proposals);
|
cy.visit('/proposals/propose');
|
||||||
cy.get(newProposalButton).should('be.visible').click();
|
waitForSpinner();
|
||||||
cy.url().should('include', '/proposals/propose');
|
cy.url().should('include', '/proposals/propose');
|
||||||
cy.get(navigation.pageSpinner, { timeout: 20000 }).should('not.exist');
|
cy.get(navigation.pageSpinner, { timeout: 20000 }).should('not.exist');
|
||||||
cy.get('li').should('contain.text', proposalType).and('be.visible');
|
if (proposalType == governanceProposalType.RAW) {
|
||||||
cy.get('li').contains(proposalType).click();
|
cy.get('[href="/proposals/propose/raw"]').click();
|
||||||
|
} else {
|
||||||
|
cy.get('li').should('contain.text', proposalType).and('be.visible');
|
||||||
|
cy.get('li').contains(proposalType).click();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function waitForProposalSubmitted() {
|
export function waitForProposalSubmitted() {
|
||||||
@@ -163,11 +222,12 @@ export function createFreeformProposal(proposalTitle: string) {
|
|||||||
navigateTo(navigation.proposals);
|
navigateTo(navigation.proposals);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const governanceProposalType = {
|
export enum governanceProposalType {
|
||||||
NETWORK_PARAMETER: 'Network parameter',
|
NETWORK_PARAMETER = 'Network parameter',
|
||||||
NEW_MARKET: 'New market',
|
NEW_MARKET = 'New market',
|
||||||
UPDATE_MARKET: 'Update market',
|
UPDATE_MARKET = 'Update market',
|
||||||
NEW_ASSET: 'New asset',
|
NEW_ASSET = 'New asset',
|
||||||
FREEFORM: 'Freeform',
|
UPDATE_ASSET = 'Update asset',
|
||||||
RAW: 'raw proposal',
|
FREEFORM = 'Freeform',
|
||||||
};
|
RAW = 'raw proposal',
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,9 +8,11 @@ import './wallet-eth.functions.ts';
|
|||||||
import './wallet-teardown.functions.ts';
|
import './wallet-teardown.functions.ts';
|
||||||
import './wallet-vega.functions.ts';
|
import './wallet-vega.functions.ts';
|
||||||
import './proposal.functions.ts';
|
import './proposal.functions.ts';
|
||||||
|
import 'cypress-mochawesome-reporter/register';
|
||||||
import registerCypressGrep from '@cypress/grep';
|
import registerCypressGrep from '@cypress/grep';
|
||||||
import { aliasGQLQuery } from '@vegaprotocol/cypress';
|
import { aliasGQLQuery } from '@vegaprotocol/cypress';
|
||||||
import { chainIdQuery, statisticsQuery } from '@vegaprotocol/mock';
|
import { chainIdQuery, statisticsQuery } from '@vegaprotocol/mock';
|
||||||
|
import { turnTelemetryOff } from './common.functions.ts';
|
||||||
registerCypressGrep();
|
registerCypressGrep();
|
||||||
|
|
||||||
// Hide fetch/XHR requests - They create a lot of noise in command log
|
// Hide fetch/XHR requests - They create a lot of noise in command log
|
||||||
@@ -24,9 +26,14 @@ if (!app.document.head.querySelector('[data-hide-command-log-request]')) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
before(() => {
|
before(() => {
|
||||||
|
cy.clearLocalStorage();
|
||||||
|
// // Ensuring the telemetry modal doesn't disrupt the tests
|
||||||
|
turnTelemetryOff();
|
||||||
// Mock chainId fetch which happens on every page for wallet connection
|
// Mock chainId fetch which happens on every page for wallet connection
|
||||||
cy.mockGQL((req) => {
|
cy.mockGQL((req) => {
|
||||||
aliasGQLQuery(req, 'ChainId', chainIdQuery());
|
aliasGQLQuery(req, 'ChainId', chainIdQuery());
|
||||||
aliasGQLQuery(req, 'Statistics', statisticsQuery());
|
aliasGQLQuery(req, 'Statistics', statisticsQuery());
|
||||||
});
|
});
|
||||||
|
// Self stake validators so they are displayed
|
||||||
|
cy.validatorsSelfDelegate();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -85,6 +85,132 @@ export function createFreeFormProposalTxBody(): ProposalSubmissionBody {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function createNewMarketProposalTxBody(): ProposalSubmissionBody {
|
||||||
|
const MIN_CLOSE_SEC = 5;
|
||||||
|
const MIN_ENACT_SEC = 7;
|
||||||
|
|
||||||
|
const closingDate = addSeconds(new Date(), MIN_CLOSE_SEC);
|
||||||
|
const enactmentDate = addSeconds(closingDate, MIN_ENACT_SEC);
|
||||||
|
const closingTimestamp = millisecondsToSeconds(closingDate.getTime());
|
||||||
|
const enactmentTimestamp = millisecondsToSeconds(enactmentDate.getTime());
|
||||||
|
return {
|
||||||
|
proposalSubmission: {
|
||||||
|
rationale: {
|
||||||
|
title: 'New Market Proposal E2E submission',
|
||||||
|
description: 'E2E new market proposal',
|
||||||
|
},
|
||||||
|
terms: {
|
||||||
|
newMarket: {
|
||||||
|
changes: {
|
||||||
|
decimalPlaces: '5',
|
||||||
|
positionDecimalPlaces: '5',
|
||||||
|
linearSlippageFactor: '0.001',
|
||||||
|
quadraticSlippageFactor: '0',
|
||||||
|
lpPriceRange: '10',
|
||||||
|
instrument: {
|
||||||
|
name: 'Token test market',
|
||||||
|
code: 'TEST.24h',
|
||||||
|
future: {
|
||||||
|
settlementAsset:
|
||||||
|
'73174a6fb1d5802ba0ac7bd7ab79e0a3a4837b262de0a4e80815a55442692bd0',
|
||||||
|
quoteName: 'fBTC',
|
||||||
|
dataSourceSpecForSettlementData: {
|
||||||
|
external: {
|
||||||
|
oracle: {
|
||||||
|
signers: [
|
||||||
|
{
|
||||||
|
pubKey: {
|
||||||
|
key: '70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
key: {
|
||||||
|
name: 'prices.ETH.value',
|
||||||
|
type: 'TYPE_INTEGER' as const,
|
||||||
|
numberDecimalPlaces: '0',
|
||||||
|
},
|
||||||
|
conditions: [
|
||||||
|
{
|
||||||
|
operator: 'OPERATOR_GREATER_THAN' as const,
|
||||||
|
value: '0',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dataSourceSpecForTradingTermination: {
|
||||||
|
external: {
|
||||||
|
oracle: {
|
||||||
|
signers: [
|
||||||
|
{
|
||||||
|
pubKey: {
|
||||||
|
key: '70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
key: {
|
||||||
|
name: 'trading.terminated.ETH5',
|
||||||
|
type: 'TYPE_BOOLEAN' as const,
|
||||||
|
},
|
||||||
|
conditions: [
|
||||||
|
{
|
||||||
|
operator: 'OPERATOR_EQUALS' as const,
|
||||||
|
value: 'true',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
dataSourceSpecBinding: {
|
||||||
|
settlementDataProperty: 'prices.ETH.value',
|
||||||
|
tradingTerminationProperty: 'trading.terminated.ETH5',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
metadata: ['sector:energy', 'sector:tech', 'source:docs.vega.xyz'],
|
||||||
|
priceMonitoringParameters: {
|
||||||
|
triggers: [
|
||||||
|
{
|
||||||
|
horizon: '43200',
|
||||||
|
probability: '0.9999999',
|
||||||
|
auctionExtension: '600',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
liquidityMonitoringParameters: {
|
||||||
|
targetStakeParameters: {
|
||||||
|
timeWindow: '3600',
|
||||||
|
scalingFactor: 10,
|
||||||
|
},
|
||||||
|
triggeringRatio: '0.7',
|
||||||
|
auctionExtension: '1',
|
||||||
|
},
|
||||||
|
logNormal: {
|
||||||
|
tau: 0.0001140771161,
|
||||||
|
riskAversionParameter: 0.01,
|
||||||
|
params: {
|
||||||
|
mu: 0,
|
||||||
|
r: 0.016,
|
||||||
|
sigma: 0.5,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
closingTimestamp,
|
||||||
|
enactmentTimestamp,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function mockNetworkUpgradeProposal() {
|
export function mockNetworkUpgradeProposal() {
|
||||||
cy.mockGQL((req) => {
|
cy.mockGQL((req) => {
|
||||||
aliasGQLQuery(req, 'Nodes', nodeData);
|
aliasGQLQuery(req, 'Nodes', nodeData);
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import {
|
|||||||
StakingBridge,
|
StakingBridge,
|
||||||
Token,
|
Token,
|
||||||
TokenVesting,
|
TokenVesting,
|
||||||
TokenFaucetable,
|
|
||||||
CollateralBridge,
|
CollateralBridge,
|
||||||
} from '@vegaprotocol/smart-contracts';
|
} from '@vegaprotocol/smart-contracts';
|
||||||
import { ethers, Wallet } from 'ethers';
|
import { ethers, Wallet } from 'ethers';
|
||||||
@@ -41,7 +40,7 @@ export async function depositAsset(
|
|||||||
decimalPlaces: number
|
decimalPlaces: number
|
||||||
) {
|
) {
|
||||||
// Approve asset
|
// Approve asset
|
||||||
const faucet = new TokenFaucetable(assetEthAddress, signer);
|
const faucet = new Token(assetEthAddress, signer);
|
||||||
cy.wrap(
|
cy.wrap(
|
||||||
faucet.approve(Erc20BridgeAddress, amount + '0'.repeat(decimalPlaces + 1)),
|
faucet.approve(Erc20BridgeAddress, amount + '0'.repeat(decimalPlaces + 1)),
|
||||||
{
|
{
|
||||||
@@ -62,13 +61,12 @@ export async function depositAsset(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function faucetAsset(assetEthAddress: string) {
|
export async function faucetAsset(assetEthAddress: string) {
|
||||||
const faucet = new TokenFaucetable(assetEthAddress, signer);
|
const faucet = new Token(assetEthAddress, signer);
|
||||||
await promiseWithTimeout(faucet.faucet(), 10 * 60 * 1000, 'faucet asset');
|
await promiseWithTimeout(faucet.faucet(), 10 * 60 * 1000, 'faucet asset');
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function vegaWalletTeardown() {
|
export async function vegaWalletTeardown() {
|
||||||
cy.get(associatedAmountInWallet)
|
cy.get(associatedAmountInWallet)
|
||||||
.should('be.visible')
|
|
||||||
.invoke('text')
|
.invoke('text')
|
||||||
.then((associatedAmount) => {
|
.then((associatedAmount) => {
|
||||||
cy.get('body').then(($body) => {
|
cy.get('body').then(($body) => {
|
||||||
@@ -83,9 +81,11 @@ export async function vegaWalletTeardown() {
|
|||||||
cy.get(vegaWalletContainer).within(() => {
|
cy.get(vegaWalletContainer).within(() => {
|
||||||
cy.get(associatedAmountInWallet, {
|
cy.get(associatedAmountInWallet, {
|
||||||
timeout: transactionTimeout,
|
timeout: transactionTimeout,
|
||||||
}).contains('0.00', {
|
})
|
||||||
timeout: transactionTimeout,
|
.should('have.length', 1, { timeout: transactionTimeout })
|
||||||
});
|
.contains('0.00', {
|
||||||
|
timeout: transactionTimeout,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ NX_VEGA_URL=https://api.n00.stagnet1.vega.xyz/graphql
|
|||||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||||
NX_FAIRGROUND=false
|
NX_FAIRGROUND=false
|
||||||
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET1":"https://stagnet1.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
|
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","STAGNET1":"https://stagnet1.governance.vega.xyz","TESTNET":"https://governance.fairground.wtf","MAINNET":"https://governance.vega.xyz"}'
|
||||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||||
NX_VEGA_WALLET_URL=http://localhost:1789
|
NX_VEGA_WALLET_URL=http://localhost:1789
|
||||||
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
|
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
|
||||||
@@ -15,6 +15,7 @@ NX_DELEGATIONS_PAGINATION=50
|
|||||||
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
|
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
|
||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/main/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/main/announcements.json
|
||||||
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||||
|
NX_VEGA_REST_URL=https://api.n00.stagnet1.vega.xyz/api/v2/
|
||||||
|
|
||||||
#Test configuration variables
|
#Test configuration variables
|
||||||
CYPRESS_FAIRGROUND=false
|
CYPRESS_FAIRGROUND=false
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ NX_VEGA_ENV=CUSTOM
|
|||||||
NX_ETHEREUM_PROVIDER_URL=http://localhost:8545
|
NX_ETHEREUM_PROVIDER_URL=http://localhost:8545
|
||||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||||
NX_FAIRGROUND=false
|
NX_FAIRGROUND=false
|
||||||
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
|
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","TESTNET":"https://governance.fairground.wtf","MAINNET":"https://governance.vega.xyz"}'
|
||||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
|
||||||
NX_VEGA_CONFIG_URL=''
|
NX_VEGA_CONFIG_URL=''
|
||||||
@@ -17,6 +17,7 @@ NX_VEGA_WALLET_URL=http://localhost:1789
|
|||||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||||
NX_DELEGATIONS_PAGINATION=50
|
NX_DELEGATIONS_PAGINATION=50
|
||||||
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
|
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
|
||||||
|
NX_VEGA_REST_URL=http://localhost:3008/api/v2/
|
||||||
|
|
||||||
#Test configuration variables
|
#Test configuration variables
|
||||||
CYPRESS_FAIRGROUND=false
|
CYPRESS_FAIRGROUND=false
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
NX_VEGA_ENV=DEVNET
|
NX_VEGA_ENV=DEVNET
|
||||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
|
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
|
||||||
NX_VEGA_URL=https://api.n00.devnet1.vega.xyz/graphql
|
NX_VEGA_URL=https://api.n00.devnet1.vega.xyz/graphql
|
||||||
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
|
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","TESTNET":"https://governance.fairground.wtf","MAINNET":"https://governance.vega.xyz"}'
|
||||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||||
@@ -10,4 +10,6 @@ NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
|
|||||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||||
NX_DELEGATIONS_PAGINATION=50
|
NX_DELEGATIONS_PAGINATION=50
|
||||||
NX_TRANCHES_SERVICE_URL=https://tranches-devnet1-k8s.ops.vega.xyz
|
NX_TRANCHES_SERVICE_URL=https://tranches-devnet1-k8s.ops.vega.xyz
|
||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||||
|
NX_VEGA_REST_URL=https://api.n00.devnet1.vega.xyz/api/v2/
|
||||||
|
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
# App configuration variables
|
# App configuration variables
|
||||||
NX_VEGA_ENV=MAINNET
|
NX_VEGA_ENV=MAINNET
|
||||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/mainnet1/mainnet1.toml
|
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/mainnet1/mainnet1.toml
|
||||||
NX_VEGA_URL=https://api.vega.xyz/query
|
NX_VEGA_URL=https://api.vega.community/graphql
|
||||||
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
|
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","TESTNET":"https://governance.fairground.wtf","MAINNET":"https://governance.vega.xyz"}'
|
||||||
NX_ETHEREUM_PROVIDER_URL=https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
NX_ETHEREUM_PROVIDER_URL=https://eth-mainnet.gateway.pokt.network/v1/lb/6684b914570bbfa533ba9324
|
||||||
NX_ETHERSCAN_URL=https://etherscan.io
|
NX_ETHERSCAN_URL=https://etherscan.io
|
||||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||||
|
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996
|
||||||
NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz
|
NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz
|
||||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
|
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
|
||||||
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40:87edc2605e544f888305d7fc4a9141bd@o286262.ingest.sentry.io/5882996
|
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40:87edc2605e544f888305d7fc4a9141bd@o286262.ingest.sentry.io/5882996
|
||||||
NX_DELEGATIONS_PAGINATION=50
|
NX_DELEGATIONS_PAGINATION=50
|
||||||
NX_TRANCHES_SERVICE_URL=https://tranches-mainnet-k8s.ops.vega.xyz
|
NX_TRANCHES_SERVICE_URL=https://tranches-mainnet-k8s.ops.vega.xyz
|
||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
|
||||||
|
NX_VEGA_REST_URL=https://api.vega.community/api/v2/
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
# App configuration variables
|
# App configuration variables
|
||||||
NX_VEGA_URL=https://api.n00.stagnet1.vega.xyz/graphql
|
NX_VEGA_URL=https://api.n00.stagnet1.vega.xyz/graphql
|
||||||
NX_VEGA_ENV=STAGNET1
|
NX_VEGA_ENV=STAGNET1
|
||||||
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET1":"https://stagnet1.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
|
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","STAGNET1":"https://stagnet1.governance.vega.xyz","TESTNET":"https://governance.fairground.wtf","MAINNET":"https://governance.vega.xyz"}'
|
||||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
|
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
|
||||||
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
|
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
|
||||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||||
NX_DELEGATIONS_PAGINATION=50
|
NX_DELEGATIONS_PAGINATION=50
|
||||||
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
|
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
|
||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||||
|
NX_VEGA_REST_URL=https://api.n00.stagnet1.vega.xyz/api/v2/
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
NX_VEGA_ENV=TESTNET
|
NX_VEGA_ENV=TESTNET
|
||||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/fairground/vegawallet-fairground.toml
|
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/fairground/vegawallet-fairground.toml
|
||||||
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
|
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
|
||||||
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
|
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","TESTNET":"https://governance.fairground.wtf","MAINNET":"https://governance.vega.xyz"}'
|
||||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||||
@@ -12,3 +12,5 @@ NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
|||||||
NX_DELEGATIONS_PAGINATION=50
|
NX_DELEGATIONS_PAGINATION=50
|
||||||
NX_TRANCHES_SERVICE_URL=https://tranches-testnet-k8s.ops.vega.xyz
|
NX_TRANCHES_SERVICE_URL=https://tranches-testnet-k8s.ops.vega.xyz
|
||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||||
|
NX_VEGA_REST_URL=https://api.n07.testnet.vega.xyz/api/v2/
|
||||||
|
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996
|
||||||
@@ -3,9 +3,11 @@ NX_VEGA_ENV=VALIDATOR_TESTNET
|
|||||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/testnet2/testnet2.toml
|
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/testnet2/testnet2.toml
|
||||||
NX_VEGA_URL=https://api-validators-testnet.vega.rocks/graphql
|
NX_VEGA_URL=https://api-validators-testnet.vega.rocks/graphql
|
||||||
NX_VEGA_REST=https://api-validators-testnet.vega.rocks/
|
NX_VEGA_REST=https://api-validators-testnet.vega.rocks/
|
||||||
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
|
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","TESTNET":"https://governance.fairground.wtf","MAINNET":"https://governance.vega.xyz"}'
|
||||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||||
NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
|
NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
|
||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||||
|
NX_VEGA_REST_URL=https://api-validators-testnet.vega.rocks/api/v2/
|
||||||
|
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
function ReactMarkdown({ children }) {
|
||||||
|
// eslint-disable-next-line react/jsx-no-useless-fragment
|
||||||
|
return <>{children}</>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ReactMarkdown;
|
||||||
@@ -58,9 +58,15 @@ export const AppLoader = ({ children }: { children: React.ReactElement }) => {
|
|||||||
token.decimals(),
|
token.decimals(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const totalSupply = toBigNum(supply, decimals);
|
const totalSupply = toBigNum(supply.toString(), decimals);
|
||||||
const totalWallet = toBigNum(totalAssociatedWallet, decimals);
|
const totalWallet = toBigNum(
|
||||||
const totalVesting = toBigNum(totalAssociatedVesting, decimals);
|
totalAssociatedWallet.toString(),
|
||||||
|
decimals
|
||||||
|
);
|
||||||
|
const totalVesting = toBigNum(
|
||||||
|
totalAssociatedVesting.toString(),
|
||||||
|
decimals
|
||||||
|
);
|
||||||
|
|
||||||
appDispatch({
|
appDispatch({
|
||||||
type: AppStateActionType.SET_TOKEN,
|
type: AppStateActionType.SET_TOKEN,
|
||||||
|
|||||||
+104
-30
@@ -2,7 +2,6 @@ import './i18n';
|
|||||||
|
|
||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import * as Sentry from '@sentry/react';
|
import * as Sentry from '@sentry/react';
|
||||||
import { Integrations } from '@sentry/tracing';
|
|
||||||
import { BrowserRouter as Router, useLocation } from 'react-router-dom';
|
import { BrowserRouter as Router, useLocation } from 'react-router-dom';
|
||||||
import { AppLoader } from './app-loader';
|
import { AppLoader } from './app-loader';
|
||||||
import { NetworkInfo } from '@vegaprotocol/network-info';
|
import { NetworkInfo } from '@vegaprotocol/network-info';
|
||||||
@@ -17,6 +16,7 @@ import { AppStateProvider } from './contexts/app-state/app-state-provider';
|
|||||||
import { ContractsProvider } from './contexts/contracts/contracts-provider';
|
import { ContractsProvider } from './contexts/contracts/contracts-provider';
|
||||||
import { AppRouter } from './routes';
|
import { AppRouter } from './routes';
|
||||||
import type { EthereumConfig } from '@vegaprotocol/web3';
|
import type { EthereumConfig } from '@vegaprotocol/web3';
|
||||||
|
import { WithdrawalApprovalDialogContainer } from '@vegaprotocol/web3';
|
||||||
import {
|
import {
|
||||||
createConnectors,
|
createConnectors,
|
||||||
useEthTransactionManager,
|
useEthTransactionManager,
|
||||||
@@ -37,12 +37,23 @@ import {
|
|||||||
useEnvironment,
|
useEnvironment,
|
||||||
NetworkLoader,
|
NetworkLoader,
|
||||||
useInitializeEnv,
|
useInitializeEnv,
|
||||||
|
NodeGuard,
|
||||||
|
AppFailure,
|
||||||
|
NodeSwitcherDialog,
|
||||||
|
useNodeSwitcherStore,
|
||||||
} from '@vegaprotocol/environment';
|
} from '@vegaprotocol/environment';
|
||||||
import { ENV } from './config';
|
import { ENV } from './config';
|
||||||
import type { InMemoryCacheConfig } from '@apollo/client';
|
import type { InMemoryCacheConfig } from '@apollo/client';
|
||||||
import { WithdrawalDialog } from '@vegaprotocol/withdraws';
|
import { CreateWithdrawalDialog } from '@vegaprotocol/withdraws';
|
||||||
import { SplashLoader } from './components/splash-loader';
|
import { SplashLoader } from './components/splash-loader';
|
||||||
import { ToastsManager } from './toasts-manager';
|
import { ToastsManager } from './toasts-manager';
|
||||||
|
import {
|
||||||
|
TelemetryDialog,
|
||||||
|
TELEMETRY_ON,
|
||||||
|
} from './components/telemetry-dialog/telemetry-dialog';
|
||||||
|
import { useLocalStorage } from '@vegaprotocol/react-helpers';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { isPartyNotFoundError } from './lib/party';
|
||||||
|
|
||||||
const cache: InMemoryCacheConfig = {
|
const cache: InMemoryCacheConfig = {
|
||||||
typePolicies: {
|
typePolicies: {
|
||||||
@@ -148,7 +159,9 @@ const Web3Container = ({
|
|||||||
<InitializeHandlers />
|
<InitializeHandlers />
|
||||||
<VegaWalletDialogs />
|
<VegaWalletDialogs />
|
||||||
<TransactionModal />
|
<TransactionModal />
|
||||||
<WithdrawalDialog />
|
<CreateWithdrawalDialog />
|
||||||
|
<WithdrawalApprovalDialogContainer />
|
||||||
|
<TelemetryDialog />
|
||||||
</>
|
</>
|
||||||
</BalanceManager>
|
</BalanceManager>
|
||||||
</AppLoader>
|
</AppLoader>
|
||||||
@@ -173,58 +186,119 @@ const ScrollToTop = () => {
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const removeQueryParams = (url: string) => {
|
||||||
|
return url.split('?')[0];
|
||||||
|
};
|
||||||
|
|
||||||
const AppContainer = () => {
|
const AppContainer = () => {
|
||||||
const { config, loading, error } = useEthereumConfig();
|
const { config, loading, error } = useEthereumConfig();
|
||||||
const { VEGA_ENV, GIT_COMMIT_HASH, GIT_BRANCH, ETHEREUM_PROVIDER_URL } =
|
const {
|
||||||
useEnvironment();
|
VEGA_ENV,
|
||||||
|
VEGA_URL,
|
||||||
|
GIT_COMMIT_HASH,
|
||||||
|
GIT_BRANCH,
|
||||||
|
ETHEREUM_PROVIDER_URL,
|
||||||
|
} = useEnvironment();
|
||||||
|
const [telemetryOn] = useLocalStorage(TELEMETRY_ON);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [nodeSwitcherOpen, setNodeSwitcher] = useNodeSwitcherStore((store) => [
|
||||||
|
store.dialogOpen,
|
||||||
|
store.setDialogOpen,
|
||||||
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (ENV.dsn) {
|
if (ENV.dsn && telemetryOn === 'true') {
|
||||||
Sentry.init({
|
Sentry.init({
|
||||||
dsn: ENV.dsn,
|
dsn: ENV.dsn,
|
||||||
integrations: [new Integrations.BrowserTracing()],
|
|
||||||
tracesSampleRate: 0.1,
|
tracesSampleRate: 0.1,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
environment: VEGA_ENV,
|
environment: VEGA_ENV,
|
||||||
release: GIT_COMMIT_HASH,
|
release: GIT_COMMIT_HASH,
|
||||||
beforeSend(event) {
|
beforeSend(event, hint) {
|
||||||
if (event.request?.url?.includes('/claim?')) {
|
const error = hint?.originalException;
|
||||||
return {
|
const errorIsString = typeof error === 'string';
|
||||||
...event,
|
const errorIsObject = error instanceof Error;
|
||||||
request: {
|
const requestUrl = event.request?.url;
|
||||||
...event.request,
|
const transaction = event.transaction;
|
||||||
url: event.request?.url.split('?')[0],
|
|
||||||
},
|
if (
|
||||||
};
|
(errorIsString && isPartyNotFoundError({ message: error })) ||
|
||||||
|
(errorIsObject && isPartyNotFoundError(error))
|
||||||
|
) {
|
||||||
|
// This error is caused by a pubkey making an API request before
|
||||||
|
// it has interacted with the chain. This isn't needed in Sentry.
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return event;
|
|
||||||
|
const updatedRequest =
|
||||||
|
requestUrl && requestUrl.includes('/claim?')
|
||||||
|
? { ...event.request, url: removeQueryParams(requestUrl) }
|
||||||
|
: event.request;
|
||||||
|
|
||||||
|
const updatedTransaction =
|
||||||
|
transaction && transaction.includes('/claim?')
|
||||||
|
? removeQueryParams(transaction)
|
||||||
|
: transaction;
|
||||||
|
|
||||||
|
const updatedBreadcrumbs = event.breadcrumbs?.map((breadcrumb) => {
|
||||||
|
if (
|
||||||
|
breadcrumb.type === 'navigation' &&
|
||||||
|
breadcrumb.data?.to?.includes('/claim?')
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
...breadcrumb,
|
||||||
|
data: {
|
||||||
|
...breadcrumb.data,
|
||||||
|
to: removeQueryParams(breadcrumb.data.to),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return breadcrumb;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
...event,
|
||||||
|
request: updatedRequest,
|
||||||
|
transaction: updatedTransaction,
|
||||||
|
breadcrumbs: updatedBreadcrumbs ?? event.breadcrumbs,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
Sentry.setTag('branch', GIT_BRANCH);
|
Sentry.setTag('branch', GIT_BRANCH);
|
||||||
Sentry.setTag('commit', GIT_COMMIT_HASH);
|
Sentry.setTag('commit', GIT_COMMIT_HASH);
|
||||||
|
} else {
|
||||||
|
Sentry.close();
|
||||||
}
|
}
|
||||||
}, [GIT_COMMIT_HASH, GIT_BRANCH, VEGA_ENV]);
|
}, [GIT_COMMIT_HASH, GIT_BRANCH, VEGA_ENV, telemetryOn]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Router>
|
<Router>
|
||||||
<ScrollToTop />
|
<ScrollToTop />
|
||||||
<AppStateProvider>
|
<AppStateProvider>
|
||||||
<div className="grid min-h-full text-white">
|
<div className="grid min-h-full text-white">
|
||||||
<AsyncRenderer<EthereumConfig | null>
|
<NodeGuard
|
||||||
loading={loading}
|
skeleton={<div>{t('Loading')}</div>}
|
||||||
data={config}
|
failure={
|
||||||
error={error}
|
<AppFailure title={t('NodeUnsuitable', { url: VEGA_URL })} />
|
||||||
render={(cnf) =>
|
|
||||||
cnf && (
|
|
||||||
<Web3Container
|
|
||||||
chainId={Number(cnf.chain_id)}
|
|
||||||
providerUrl={ETHEREUM_PROVIDER_URL}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
/>
|
>
|
||||||
|
<AsyncRenderer<EthereumConfig | null>
|
||||||
|
loading={loading}
|
||||||
|
data={config}
|
||||||
|
error={error}
|
||||||
|
render={(cnf) =>
|
||||||
|
cnf && (
|
||||||
|
<Web3Container
|
||||||
|
chainId={Number(cnf.chain_id)}
|
||||||
|
providerUrl={ETHEREUM_PROVIDER_URL}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</NodeGuard>
|
||||||
</div>
|
</div>
|
||||||
</AppStateProvider>
|
</AppStateProvider>
|
||||||
|
<NodeSwitcherDialog open={nodeSwitcherOpen} setOpen={setNodeSwitcher} />
|
||||||
</Router>
|
</Router>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,23 +1,14 @@
|
|||||||
import { Button } from '@vegaprotocol/ui-toolkit';
|
import { Button } from '@vegaprotocol/ui-toolkit';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { useWeb3ConnectStore } from '@vegaprotocol/web3';
|
||||||
import {
|
|
||||||
AppStateActionType,
|
|
||||||
useAppState,
|
|
||||||
} from '../../contexts/app-state/app-state-context';
|
|
||||||
|
|
||||||
export const EthConnectPrompt = () => {
|
export const EthConnectPrompt = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { appDispatch } = useAppState();
|
const { open } = useWeb3ConnectStore();
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
variant="default"
|
variant="default"
|
||||||
onClick={() =>
|
onClick={open}
|
||||||
appDispatch({
|
|
||||||
type: AppStateActionType.SET_ETH_WALLET_OVERLAY,
|
|
||||||
isOpen: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
fill={true}
|
fill={true}
|
||||||
data-testid="connect-to-eth-btn"
|
data-testid="connect-to-eth-btn"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -2,10 +2,7 @@ import { Button } from '@vegaprotocol/ui-toolkit';
|
|||||||
import { useWeb3React } from '@web3-react/core';
|
import { useWeb3React } from '@web3-react/core';
|
||||||
import type { ReactElement } from 'react';
|
import type { ReactElement } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import {
|
import { useWeb3ConnectStore } from '@vegaprotocol/web3';
|
||||||
AppStateActionType,
|
|
||||||
useAppState,
|
|
||||||
} from '../../contexts/app-state/app-state-context';
|
|
||||||
|
|
||||||
export const EthWalletContainer = ({
|
export const EthWalletContainer = ({
|
||||||
children,
|
children,
|
||||||
@@ -14,21 +11,12 @@ export const EthWalletContainer = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const { account } = useWeb3React();
|
const { account } = useWeb3React();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { appDispatch } = useAppState();
|
const { open } = useWeb3ConnectStore();
|
||||||
|
|
||||||
if (!account) {
|
if (!account) {
|
||||||
return (
|
return (
|
||||||
<div className="w-full text-center">
|
<div className="w-full text-center">
|
||||||
<Button
|
<Button onClick={open}>{t('connectEthWallet')}</Button>
|
||||||
onClick={() =>
|
|
||||||
appDispatch({
|
|
||||||
type: AppStateActionType.SET_ETH_WALLET_OVERLAY,
|
|
||||||
isOpen: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{t('connectEthWallet')}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,11 @@ import {
|
|||||||
import { Loader } from '@vegaprotocol/ui-toolkit';
|
import { Loader } from '@vegaprotocol/ui-toolkit';
|
||||||
import colors from 'tailwindcss/colors';
|
import colors from 'tailwindcss/colors';
|
||||||
import { useBalances } from '../../lib/balances/balances-store';
|
import { useBalances } from '../../lib/balances/balances-store';
|
||||||
import { useEthereumConfig, useWeb3Disconnect } from '@vegaprotocol/web3';
|
import {
|
||||||
|
useEthereumConfig,
|
||||||
|
useWeb3ConnectStore,
|
||||||
|
useWeb3Disconnect,
|
||||||
|
} from '@vegaprotocol/web3';
|
||||||
import { getChainName } from '@vegaprotocol/web3';
|
import { getChainName } from '@vegaprotocol/web3';
|
||||||
|
|
||||||
const removeLeadingAddressSymbol = (key: string) => {
|
const removeLeadingAddressSymbol = (key: string) => {
|
||||||
@@ -189,6 +193,7 @@ export const EthWallet = () => {
|
|||||||
const pendingTxs = usePendingTransactions();
|
const pendingTxs = usePendingTransactions();
|
||||||
const disconnect = useWeb3Disconnect(connector);
|
const disconnect = useWeb3Disconnect(connector);
|
||||||
const { config } = useEthereumConfig();
|
const { config } = useEthereumConfig();
|
||||||
|
const { open } = useWeb3ConnectStore();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WalletCard>
|
<WalletCard>
|
||||||
@@ -233,12 +238,7 @@ export const EthWallet = () => {
|
|||||||
) : (
|
) : (
|
||||||
<Button
|
<Button
|
||||||
fill={true}
|
fill={true}
|
||||||
onClick={() =>
|
onClick={open}
|
||||||
appDispatch({
|
|
||||||
type: AppStateActionType.SET_ETH_WALLET_OVERLAY,
|
|
||||||
isOpen: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
data-testid="connect-to-eth-wallet-button"
|
data-testid="connect-to-eth-wallet-button"
|
||||||
>
|
>
|
||||||
{t('connectEthWalletToAssociate')}
|
{t('connectEthWalletToAssociate')}
|
||||||
|
|||||||
@@ -11,11 +11,26 @@ import {
|
|||||||
NavigationLink,
|
NavigationLink,
|
||||||
NavigationList,
|
NavigationList,
|
||||||
NavigationTrigger,
|
NavigationTrigger,
|
||||||
|
Icon,
|
||||||
} from '@vegaprotocol/ui-toolkit';
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
import { EthWallet } from '../eth-wallet';
|
import { EthWallet } from '../eth-wallet';
|
||||||
import { VegaWallet } from '../vega-wallet';
|
import { VegaWallet } from '../vega-wallet';
|
||||||
import { useLocation, useMatch } from 'react-router-dom';
|
import { useLocation, useMatch } from 'react-router-dom';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
|
import { useTelemetryDialog } from '../telemetry-dialog/telemetry-dialog';
|
||||||
|
|
||||||
|
export const SettingsLink = () => {
|
||||||
|
const { open, isOpen, close } = useTelemetryDialog();
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => (isOpen ? close() : open())}
|
||||||
|
aria-label="Open Telemetry Settings"
|
||||||
|
>
|
||||||
|
<Icon name="cog" className="w-5 h-5 mr-2" />
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const Nav = ({ theme }: Pick<NavigationProps, 'theme'>) => {
|
export const Nav = ({ theme }: Pick<NavigationProps, 'theme'>) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -42,7 +57,12 @@ export const Nav = ({ theme }: Pick<NavigationProps, 'theme'>) => {
|
|||||||
));
|
));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Navigation appName="Governance" theme={theme} breakpoints={[458, 959]}>
|
<Navigation
|
||||||
|
appName="Governance"
|
||||||
|
theme={theme}
|
||||||
|
breakpoints={[458, 959]}
|
||||||
|
actions={<SettingsLink />}
|
||||||
|
>
|
||||||
<NavigationList
|
<NavigationList
|
||||||
className="[.drawer-content_&]:border-b [.drawer-content_&]:border-b-vega-light-200 dark:[.drawer-content_&]:border-b-vega-dark-200 [.drawer-content_&]:pb-8 [.drawer-content_&]:mb-2"
|
className="[.drawer-content_&]:border-b [.drawer-content_&]:border-b-vega-light-200 dark:[.drawer-content_&]:border-b-vega-dark-200 [.drawer-content_&]:pb-8 [.drawer-content_&]:mb-2"
|
||||||
hide={[NavigationBreakpoint.Small]}
|
hide={[NavigationBreakpoint.Small]}
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
import { renderHook, act } from '@testing-library/react';
|
||||||
|
import { useTelemetryDialog, TELEMETRY_ON } from './telemetry-dialog';
|
||||||
|
|
||||||
|
describe('useTelemetryDialog', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
localStorage.clear();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have the correct initial state based on localStorage', () => {
|
||||||
|
localStorage.setItem(TELEMETRY_ON, 'true');
|
||||||
|
|
||||||
|
const { result } = renderHook(() => useTelemetryDialog());
|
||||||
|
|
||||||
|
expect(result.current.isOpen).toBe(false);
|
||||||
|
expect(result.current.telemetryAccepted).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update localStorage and the telemetryAccepted state when setTelemetryAccepted is called', () => {
|
||||||
|
const { result } = renderHook(() => useTelemetryDialog());
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
result.current.setTelemetryAccepted(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result.current.telemetryAccepted).toBe(true);
|
||||||
|
expect(localStorage.getItem(TELEMETRY_ON)).toBe('true');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update localStorage and the isOpen state when close is called', () => {
|
||||||
|
const { result } = renderHook(() => useTelemetryDialog());
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
result.current.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result.current.isOpen).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update the isOpen state when open is called', () => {
|
||||||
|
const { result } = renderHook(() => useTelemetryDialog());
|
||||||
|
|
||||||
|
act(() => {
|
||||||
|
result.current.open();
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result.current.isOpen).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should open the dialog if TELEMETRY_ON is not set', () => {
|
||||||
|
const { result } = renderHook(() => useTelemetryDialog());
|
||||||
|
expect(result.current.isOpen).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
import { create } from 'zustand';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { useLocalStorage } from '@vegaprotocol/react-helpers';
|
||||||
|
import { Dialog, Icon, Button } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { Networks, useEnvironment } from '@vegaprotocol/environment';
|
||||||
|
|
||||||
|
type TelemetryDialogState = {
|
||||||
|
isOpen: boolean;
|
||||||
|
open: () => void;
|
||||||
|
close: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const useTelemetryDialogStore = create<TelemetryDialogState>((set) => ({
|
||||||
|
isOpen: false,
|
||||||
|
open: () => set({ isOpen: true }),
|
||||||
|
close: () => set({ isOpen: false }),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const TELEMETRY_ON = 'vega_telemetry_on';
|
||||||
|
|
||||||
|
export const useTelemetryDialog = () => {
|
||||||
|
const [telemetryOn, setTelemetryOn] = useLocalStorage(TELEMETRY_ON);
|
||||||
|
const { VEGA_ENV } = useEnvironment();
|
||||||
|
const isMainnet = VEGA_ENV === Networks.MAINNET;
|
||||||
|
|
||||||
|
const defaultTelemetryAccepted = isMainnet ? 'false' : 'true';
|
||||||
|
|
||||||
|
const { isOpen, open, close } = useTelemetryDialogStore();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (telemetryOn === null || telemetryOn === undefined) {
|
||||||
|
open();
|
||||||
|
setTelemetryOn(defaultTelemetryAccepted);
|
||||||
|
}
|
||||||
|
}, [defaultTelemetryAccepted, open, setTelemetryOn, telemetryOn]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
isOpen,
|
||||||
|
open: open,
|
||||||
|
close: close,
|
||||||
|
telemetryAccepted: telemetryOn === 'true',
|
||||||
|
setTelemetryAccepted: (value: boolean) => {
|
||||||
|
setTelemetryOn(value.toString());
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const TelemetryDialog = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { isOpen, open, close, telemetryAccepted, setTelemetryAccepted } =
|
||||||
|
useTelemetryDialog();
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
title={t('ImproveVegaGovernance')}
|
||||||
|
open={isOpen}
|
||||||
|
onChange={(isOpen) => (isOpen ? open() : close())}
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<div className="mt-6">{t('TelemetryModalIntro')}</div>
|
||||||
|
<div className="flex items-center mt-6">
|
||||||
|
<Icon name="eye-off" className="mr-6" size={6} />
|
||||||
|
<div className="flex flex-col gap-1">
|
||||||
|
<div className="font-semibold">{t('Anonymous')}</div>
|
||||||
|
<div>{t('YourIdentityAnonymous')}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center mt-6">
|
||||||
|
<Icon name="cog" className="mr-6" size={6} />
|
||||||
|
<div className="flex flex-col gap-1">
|
||||||
|
<div className="font-semibold">{t('Optional')}</div>
|
||||||
|
<div>{t('OptOutOfTelemetry')}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center mt-10 gap-4">
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
setTelemetryAccepted(false);
|
||||||
|
close();
|
||||||
|
}}
|
||||||
|
variant="default"
|
||||||
|
data-testid="do-not-share-data-button"
|
||||||
|
>
|
||||||
|
{t('NoThanks')}
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
setTelemetryAccepted(true);
|
||||||
|
close();
|
||||||
|
}}
|
||||||
|
variant="primary"
|
||||||
|
data-testid="share-data-button"
|
||||||
|
>
|
||||||
|
{telemetryAccepted ? t('ContinueSharingData') : t('ShareData')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import { t } from '@vegaprotocol/i18n';
|
||||||
|
import {
|
||||||
|
ExternalLink,
|
||||||
|
VegaIcon,
|
||||||
|
VegaIconNames,
|
||||||
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
|
import Routes from '../../routes/routes';
|
||||||
|
|
||||||
|
export const RiskMessage = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="bg-vega-light-100 dark:bg-vega-dark-100 p-6 mb-6">
|
||||||
|
<ul className="list-[square] ml-4">
|
||||||
|
<li>
|
||||||
|
{t(
|
||||||
|
'You may encounter bugs, loss of functionality or loss of assets using the App.'
|
||||||
|
)}
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
{t(
|
||||||
|
'No party accepts any liability for any losses whatsoever related to its use.'
|
||||||
|
)}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<p className="mb-8">
|
||||||
|
{t(
|
||||||
|
'By using the Vega Governance App, you acknowledge that you have read and understood the'
|
||||||
|
)}{' '}
|
||||||
|
<ExternalLink href={Routes.DISCLAIMER} className="underline">
|
||||||
|
<span className="flex items-center gap-1">
|
||||||
|
<span>{t('Vega Governance Disclaimer')}</span>
|
||||||
|
<VegaIcon name={VegaIconNames.OPEN_EXTERNAL} />
|
||||||
|
</span>
|
||||||
|
</ExternalLink>
|
||||||
|
.
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -4,9 +4,11 @@ import {
|
|||||||
useAppState,
|
useAppState,
|
||||||
} from '../../contexts/app-state/app-state-context';
|
} from '../../contexts/app-state/app-state-context';
|
||||||
import { Connectors } from '../../lib/vega-connectors';
|
import { Connectors } from '../../lib/vega-connectors';
|
||||||
|
import { RiskMessage } from './risk-message';
|
||||||
|
|
||||||
export const VegaWalletDialogs = () => {
|
export const VegaWalletDialogs = () => {
|
||||||
const { appState, appDispatch } = useAppState();
|
const { appState, appDispatch } = useAppState();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<VegaConnectDialog
|
<VegaConnectDialog
|
||||||
@@ -17,6 +19,7 @@ export const VegaWalletDialogs = () => {
|
|||||||
isOpen: open,
|
isOpen: open,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
riskMessage={<RiskMessage />}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<VegaManageDialog
|
<VegaManageDialog
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Link } from '@vegaprotocol/ui-toolkit';
|
import { Link } from '@vegaprotocol/ui-toolkit';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { ExternalLinks } from '@vegaprotocol/utils';
|
import { ExternalLinks } from '@vegaprotocol/environment';
|
||||||
|
|
||||||
export const DownloadWalletPrompt = () => {
|
export const DownloadWalletPrompt = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import type {
|
|||||||
WalletDelegationFieldsFragment,
|
WalletDelegationFieldsFragment,
|
||||||
} from './__generated__/Delegations';
|
} from './__generated__/Delegations';
|
||||||
import { DelegationsDocument } from './__generated__/Delegations';
|
import { DelegationsDocument } from './__generated__/Delegations';
|
||||||
|
import { isPartyNotFoundError } from '../../lib/party';
|
||||||
|
|
||||||
export const usePollForDelegations = () => {
|
export const usePollForDelegations = () => {
|
||||||
const { token: vegaToken } = useContracts();
|
const { token: vegaToken } = useContracts();
|
||||||
@@ -75,6 +76,7 @@ export const usePollForDelegations = () => {
|
|||||||
})
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
|
|
||||||
const canonisedDelegations = removePaginationWrapper(
|
const canonisedDelegations = removePaginationWrapper(
|
||||||
res.data.party?.delegationsConnection?.edges
|
res.data.party?.delegationsConnection?.edges
|
||||||
);
|
);
|
||||||
@@ -203,6 +205,15 @@ export const usePollForDelegations = () => {
|
|||||||
setDelegatedNodes(delegatedAmounts);
|
setDelegatedNodes(delegatedAmounts);
|
||||||
})
|
})
|
||||||
.catch((err: Error) => {
|
.catch((err: Error) => {
|
||||||
|
// if party isn't found, dont log to Sentry, just clear state as, user
|
||||||
|
// will not have any delagations or accounts
|
||||||
|
if (isPartyNotFoundError(err)) {
|
||||||
|
setDelegations([]);
|
||||||
|
setAccounts([]);
|
||||||
|
setDelegatedNodes([]);
|
||||||
|
setCurrentStakeAvailable(new BigNumber(0));
|
||||||
|
return;
|
||||||
|
}
|
||||||
Sentry.captureException(err);
|
Sentry.captureException(err);
|
||||||
// If query fails stop interval. Its almost certain that the query
|
// If query fails stop interval. Its almost certain that the query
|
||||||
// will just continue to fail
|
// will just continue to fail
|
||||||
|
|||||||
@@ -25,20 +25,26 @@ export function Web3Connector({
|
|||||||
connectors,
|
connectors,
|
||||||
chainId,
|
chainId,
|
||||||
}: Web3ConnectorProps) {
|
}: Web3ConnectorProps) {
|
||||||
const { appState, appDispatch } = useAppState();
|
const { open, close, isOpen } = useWeb3ConnectStore();
|
||||||
|
|
||||||
const setDialogOpen = useCallback(
|
const setDialogOpen = useCallback(
|
||||||
(isOpen: boolean) => {
|
(isOpen: boolean) => {
|
||||||
appDispatch({ type: AppStateActionType.SET_ETH_WALLET_OVERLAY, isOpen });
|
if (isOpen) {
|
||||||
|
open();
|
||||||
|
} else {
|
||||||
|
close();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
[appDispatch]
|
[open, close]
|
||||||
);
|
);
|
||||||
|
|
||||||
const appChainId = Number(chainId);
|
const appChainId = Number(chainId);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Web3Content appChainId={appChainId}>{children}</Web3Content>
|
<Web3Content appChainId={appChainId}>{children}</Web3Content>
|
||||||
<Web3ConnectDialog
|
<Web3ConnectDialog
|
||||||
connectors={connectors}
|
connectors={connectors}
|
||||||
dialogOpen={appState.ethConnectOverlay}
|
dialogOpen={isOpen}
|
||||||
setDialogOpen={setDialogOpen}
|
setDialogOpen={setDialogOpen}
|
||||||
desiredChainId={appChainId}
|
desiredChainId={appChainId}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ export const ENV = {
|
|||||||
ethWalletMnemonic: windowOrDefault('NX_ETH_WALLET_MNEMONIC'),
|
ethWalletMnemonic: windowOrDefault('NX_ETH_WALLET_MNEMONIC'),
|
||||||
localProviderUrl: windowOrDefault('NX_LOCAL_PROVIDER_URL'),
|
localProviderUrl: windowOrDefault('NX_LOCAL_PROVIDER_URL'),
|
||||||
delegationsPagination: windowOrDefault('NX_DELEGATIONS_PAGINATION'),
|
delegationsPagination: windowOrDefault('NX_DELEGATIONS_PAGINATION'),
|
||||||
|
rest: windowOrDefault('NX_VEGA_REST_URL'),
|
||||||
flags: {
|
flags: {
|
||||||
NETWORK_DOWN: TRUTHY.includes(windowOrDefault('NX_NETWORK_DOWN')),
|
NETWORK_DOWN: TRUTHY.includes(windowOrDefault('NX_NETWORK_DOWN')),
|
||||||
MOCK: TRUTHY.includes(windowOrDefault('NX_MOCKED')),
|
MOCK: TRUTHY.includes(windowOrDefault('NX_MOCKED')),
|
||||||
|
|||||||
@@ -34,9 +34,6 @@ export interface AppState {
|
|||||||
/** Whether or not the manage VEGA wallet overlay is open */
|
/** Whether or not the manage VEGA wallet overlay is open */
|
||||||
vegaWalletManageOverlay: boolean;
|
vegaWalletManageOverlay: boolean;
|
||||||
|
|
||||||
/** Whether or not the connect to Ethereum wallet overlay is open */
|
|
||||||
ethConnectOverlay: boolean;
|
|
||||||
|
|
||||||
/** Whether or not the transaction modal is open */
|
/** Whether or not the transaction modal is open */
|
||||||
transactionOverlay: boolean;
|
transactionOverlay: boolean;
|
||||||
/**
|
/**
|
||||||
@@ -57,7 +54,6 @@ export enum AppStateActionType {
|
|||||||
REFRESH_BALANCES,
|
REFRESH_BALANCES,
|
||||||
SET_VEGA_WALLET_OVERLAY,
|
SET_VEGA_WALLET_OVERLAY,
|
||||||
SET_VEGA_WALLET_MANAGE_OVERLAY,
|
SET_VEGA_WALLET_MANAGE_OVERLAY,
|
||||||
SET_ETH_WALLET_OVERLAY,
|
|
||||||
SET_DRAWER,
|
SET_DRAWER,
|
||||||
REFRESH_ASSOCIATED_BALANCES,
|
REFRESH_ASSOCIATED_BALANCES,
|
||||||
SET_ASSOCIATION_BREAKDOWN,
|
SET_ASSOCIATION_BREAKDOWN,
|
||||||
@@ -81,10 +77,6 @@ export type AppStateAction =
|
|||||||
type: AppStateActionType.SET_VEGA_WALLET_MANAGE_OVERLAY;
|
type: AppStateActionType.SET_VEGA_WALLET_MANAGE_OVERLAY;
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
}
|
}
|
||||||
| {
|
|
||||||
type: AppStateActionType.SET_ETH_WALLET_OVERLAY;
|
|
||||||
isOpen: boolean;
|
|
||||||
}
|
|
||||||
| {
|
| {
|
||||||
type: AppStateActionType.SET_DRAWER;
|
type: AppStateActionType.SET_DRAWER;
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ const initialAppState: AppState = {
|
|||||||
totalSupply: new BigNumber(0),
|
totalSupply: new BigNumber(0),
|
||||||
vegaWalletOverlay: false,
|
vegaWalletOverlay: false,
|
||||||
vegaWalletManageOverlay: false,
|
vegaWalletManageOverlay: false,
|
||||||
ethConnectOverlay: false,
|
|
||||||
transactionOverlay: false,
|
transactionOverlay: false,
|
||||||
bannerMessage: '',
|
bannerMessage: '',
|
||||||
disconnectNotice: false,
|
disconnectNotice: false,
|
||||||
@@ -45,12 +44,6 @@ function appStateReducer(state: AppState, action: AppStateAction): AppState {
|
|||||||
vegaWalletOverlay: action.isOpen ? false : state.vegaWalletOverlay,
|
vegaWalletOverlay: action.isOpen ? false : state.vegaWalletOverlay,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case AppStateActionType.SET_ETH_WALLET_OVERLAY: {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
ethConnectOverlay: action.isOpen,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
case AppStateActionType.SET_DRAWER: {
|
case AppStateActionType.SET_DRAWER: {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
export function useDocumentTitle(name?: string) {
|
export function useDocumentTitle(name?: string) {
|
||||||
const base = 'VEGA token';
|
const base = 'VEGA Governance';
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (name) {
|
if (name) {
|
||||||
|
|||||||
@@ -66,7 +66,7 @@
|
|||||||
"claim": "This code ({{code}}) entitles <bold>{{user}}</bold> to <bold>{{amount}} $VEGA</bold> tokens from <trancheLink>{{linkText}}</trancheLink> of the vesting contract. {{expiry}}.",
|
"claim": "This code ({{code}}) entitles <bold>{{user}}</bold> to <bold>{{amount}} $VEGA</bold> tokens from <trancheLink>{{linkText}}</trancheLink> of the vesting contract. {{expiry}}.",
|
||||||
"claimExpiry": "The code expires on {{date}}",
|
"claimExpiry": "The code expires on {{date}}",
|
||||||
"claimNoExpiry": "It has no expiry date",
|
"claimNoExpiry": "It has no expiry date",
|
||||||
"showRedeem": "You'll be able to redeem your unlocked tokens at token.vega.xyz/vesting",
|
"showRedeem": "You'll be able to redeem your unlocked tokens at governance.vega.xyz/vesting",
|
||||||
"codeUsed": "Code already used",
|
"codeUsed": "Code already used",
|
||||||
"codeUsedText": "Looks like that code has already been used. Check the Vesting page to see if you can redeem your tokens.",
|
"codeUsedText": "Looks like that code has already been used. Check the Vesting page to see if you can redeem your tokens.",
|
||||||
"codeExpired": "Code expired",
|
"codeExpired": "Code expired",
|
||||||
@@ -86,7 +86,7 @@
|
|||||||
"Awaiting action in Ethereum wallet (e.g. MetaMask)": "Awaiting action in Ethereum wallet (e.g. MetaMask)",
|
"Awaiting action in Ethereum wallet (e.g. MetaMask)": "Awaiting action in Ethereum wallet (e.g. MetaMask)",
|
||||||
"Claim {amount} Vega": "Claim {{amount}} $VEGA",
|
"Claim {amount} Vega": "Claim {{amount}} $VEGA",
|
||||||
"Sorry. It is not possible to claim tokens in your country or region.": "It is not possible to claim tokens in your country or region.",
|
"Sorry. It is not possible to claim tokens in your country or region.": "It is not possible to claim tokens in your country or region.",
|
||||||
"none redeemable": "Tokens in this tranche unlock on {{unlockDate}} and continue to unlock gradually until {{trancheEndDate}} when all tokens are unlocked. Come back to token.vega.xyz to redeem your tokens once they begin to unlock.",
|
"none redeemable": "Tokens in this tranche unlock on {{unlockDate}} and continue to unlock gradually until {{trancheEndDate}} when all tokens are unlocked. Come back to governance.vega.xyz to redeem your tokens once they begin to unlock.",
|
||||||
"partially redeemable": "Tokens in this tranche began to unlock on {{unlockDate}} and will continue to unlock gradually until {{trancheEndDate}} when all tokens are unlocked.",
|
"partially redeemable": "Tokens in this tranche began to unlock on {{unlockDate}} and will continue to unlock gradually until {{trancheEndDate}} when all tokens are unlocked.",
|
||||||
"fully redeemable": "Tokens in this tranche have fully unlocked and can be redeemed once claimed.",
|
"fully redeemable": "Tokens in this tranche have fully unlocked and can be redeemed once claimed.",
|
||||||
"This page can not be found, please check the URL and try again.": "This page can not be found, please check the URL and try again.",
|
"This page can not be found, please check the URL and try again.": "This page can not be found, please check the URL and try again.",
|
||||||
@@ -202,6 +202,7 @@
|
|||||||
"tokenVotes": "Token votes",
|
"tokenVotes": "Token votes",
|
||||||
"liquidityVotes": "Liquidity votes",
|
"liquidityVotes": "Liquidity votes",
|
||||||
"castYourVote": "Cast your vote",
|
"castYourVote": "Cast your vote",
|
||||||
|
"yourVote": "Your vote",
|
||||||
"for": "For",
|
"for": "For",
|
||||||
"against": "Against",
|
"against": "Against",
|
||||||
"majorityRequired": "Majority Required",
|
"majorityRequired": "Majority Required",
|
||||||
@@ -593,7 +594,9 @@
|
|||||||
"numberOfAgainstVotes": "Number of votes against",
|
"numberOfAgainstVotes": "Number of votes against",
|
||||||
"yesPercentage": "Yes percentage",
|
"yesPercentage": "Yes percentage",
|
||||||
"noPercentage": "No percentage",
|
"noPercentage": "No percentage",
|
||||||
"proposalTerms": "Proposal terms",
|
"proposalJson": "Full proposal JSON",
|
||||||
|
"proposalDetails": "Proposal details",
|
||||||
|
"proposalDescription": "Description",
|
||||||
"currentlySetTo": "Currently expected to ",
|
"currentlySetTo": "Currently expected to ",
|
||||||
"currently": "currently",
|
"currently": "currently",
|
||||||
"finalOutcomeMayDiffer": "Final outcome may differ",
|
"finalOutcomeMayDiffer": "Final outcome may differ",
|
||||||
@@ -678,6 +681,8 @@
|
|||||||
"FilterProposalsDescription": "Filter by proposal ID or proposer ID",
|
"FilterProposalsDescription": "Filter by proposal ID or proposer ID",
|
||||||
"Freeform proposal": "Freeform proposal",
|
"Freeform proposal": "Freeform proposal",
|
||||||
"NewProposal": "New proposal",
|
"NewProposal": "New proposal",
|
||||||
|
"CreateProposalAndDownloadJSONToShare": "Create proposal and download JSON to share",
|
||||||
|
"SubmitAnAgreedProposalFromTheForum": "Submit an agreed proposal from the forum",
|
||||||
"ProposalTypeQuestion": "What type of proposal would you like to make?",
|
"ProposalTypeQuestion": "What type of proposal would you like to make?",
|
||||||
"NetworkParameterProposal": "Update network parameter proposal",
|
"NetworkParameterProposal": "Update network parameter proposal",
|
||||||
"parameter": "parameter",
|
"parameter": "parameter",
|
||||||
@@ -701,6 +706,7 @@
|
|||||||
"AssetID": "Asset ID",
|
"AssetID": "Asset ID",
|
||||||
"Freeform": "Freeform",
|
"Freeform": "Freeform",
|
||||||
"RawProposal": "Let me choose (raw proposal)",
|
"RawProposal": "Let me choose (raw proposal)",
|
||||||
|
"SubmitAgreedRawProposal": "Submit agreed raw proposal",
|
||||||
"UseMin": "Use minimum",
|
"UseMin": "Use minimum",
|
||||||
"UseMax": "Use maximum",
|
"UseMax": "Use maximum",
|
||||||
"Proposal": "Proposal",
|
"Proposal": "Proposal",
|
||||||
@@ -784,9 +790,9 @@
|
|||||||
"homeVegaTokenButtonText": "Manage tokens",
|
"homeVegaTokenButtonText": "Manage tokens",
|
||||||
"downloadProposalJson": "Download proposal as JSON",
|
"downloadProposalJson": "Download proposal as JSON",
|
||||||
"networkUpgrade": "Network Upgrade",
|
"networkUpgrade": "Network Upgrade",
|
||||||
"PROTOCOL_UPGRADE_PROPOSAL_STATUS_APPROVED": "Approved",
|
"PROTOCOL_UPGRADE_PROPOSAL_STATUS_APPROVED": "Approved by validators",
|
||||||
"PROTOCOL_UPGRADE_PROPOSAL_STATUS_PENDING": "Pending",
|
"PROTOCOL_UPGRADE_PROPOSAL_STATUS_PENDING": "Waiting for validator votes",
|
||||||
"PROTOCOL_UPGRADE_PROPOSAL_STATUS_REJECTED": "Rejected",
|
"PROTOCOL_UPGRADE_PROPOSAL_STATUS_REJECTED": "Declined by validators",
|
||||||
"PROTOCOL_UPGRADE_PROPOSAL_STATUS_UNSPECIFIED": "Unspecified",
|
"PROTOCOL_UPGRADE_PROPOSAL_STATUS_UNSPECIFIED": "Unspecified",
|
||||||
"vegaRelease{release}": "Vega Release {{release}}",
|
"vegaRelease{release}": "Vega Release {{release}}",
|
||||||
"upgradeBlockHeight": "Upgrade block height",
|
"upgradeBlockHeight": "Upgrade block height",
|
||||||
@@ -799,5 +805,21 @@
|
|||||||
"associateVegaNow": "Associate $VEGA now",
|
"associateVegaNow": "Associate $VEGA now",
|
||||||
"disconnectedNotice": "You have been disconnected. Connect your ETH wallet to the {{correctNetwork}} network to use this app.",
|
"disconnectedNotice": "You have been disconnected. Connect your ETH wallet to the {{correctNetwork}} network to use this app.",
|
||||||
"connectAVegaWalletToVote": "Connect a Vega wallet with $VEGA tokens to vote on a proposal.",
|
"connectAVegaWalletToVote": "Connect a Vega wallet with $VEGA tokens to vote on a proposal.",
|
||||||
"findOutMoreAboutHowToVote": "Find out more about how to vote on Vega"
|
"findOutMoreAboutHowToVote": "Find out more about how to vote on Vega",
|
||||||
|
"ImproveVegaGovernance": "Improve Vega governance",
|
||||||
|
"TelemetryModalIntro": "Help us identify bugs and improve Vega Governance by sharing anonymous usage data.",
|
||||||
|
"Anonymous": "Anonymous",
|
||||||
|
"YourIdentityAnonymous": "Your identity is always anonymous on Vega",
|
||||||
|
"Optional": "Optional",
|
||||||
|
"OptOutOfTelemetry": "You can opt out any time via settings",
|
||||||
|
"NoThanks": "No thanks",
|
||||||
|
"ShareData": "Share data",
|
||||||
|
"ContinueSharingData": "Continue sharing data",
|
||||||
|
"NodeUnsuitable": "Node: {{url}} is unsuitable",
|
||||||
|
"Disclaimer": "Disclaimer",
|
||||||
|
"disclaimer1": "The Vega Governance App allows the Vega network to arrive at on-chain decisions, where tokenholders can create proposals that other tokenholders can vote to approve or reject. Vega supports on-chain proposals for creating markets and assets, and changing network parameters, markets and assets. Vega also supports freeform proposals for community suggestions that will not be enacted on-chain.",
|
||||||
|
"disclaimer2": "The Vega Governance App is free, public and open source software. Software upgrades may contain bugs or security vulnerabilities that might result in loss of functionality.",
|
||||||
|
"disclaimer3": "The Vega Governance App uses data obtained from nodes on the Vega Blockchain. The developers of the Vega Governance App do not operate or run the Vega Blockchain or any other blockchain.",
|
||||||
|
"disclaimer4": "The Vega Governance App is provided “as is”. The developers of the Vega Governance App make no representations or warranties of any kind, whether express or implied, statutory or otherwise regarding the Vega Governance App. They disclaim all warranties of merchantability, quality, fitness for purpose. They disclaim all warranties that the Vega Governance App is free of harmful components or errors.",
|
||||||
|
"disclaimer5": "No developer of the Vega Governance App accepts any responsibility for, or liability to users in connection with their use of the Vega Governance App."
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
type="font/woff2"
|
type="font/woff2"
|
||||||
crossorigin="anonymous"
|
crossorigin="anonymous"
|
||||||
/>
|
/>
|
||||||
<title>Vega Token dApp</title>
|
<title>Vega Governance dApp</title>
|
||||||
<script src="./assets/env-config.js"></script>
|
<script src="./assets/env-config.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body class="h-full">
|
<body class="h-full">
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export const PARTY_NOT_FOUND = 'failed to get party for ID';
|
||||||
|
|
||||||
|
export const isPartyNotFoundError = (error: { message: string }) => {
|
||||||
|
if (error.message.includes(PARTY_NOT_FOUND)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
@@ -50,7 +50,22 @@ export const useTranches = create<TranchesStore>()((set) => ({
|
|||||||
?.map((t) => {
|
?.map((t) => {
|
||||||
const tranche_progress =
|
const tranche_progress =
|
||||||
t.duration !== 0 ? (now - t.cliff_start) / t.duration : 0;
|
t.duration !== 0 ? (now - t.cliff_start) / t.duration : 0;
|
||||||
const lockedDecimal = tranche_progress < 0 ? 1 : 1 - tranche_progress;
|
let lockedDecimal;
|
||||||
|
if (t.duration !== 0) {
|
||||||
|
if (tranche_progress < 0) {
|
||||||
|
lockedDecimal = 1;
|
||||||
|
} else {
|
||||||
|
lockedDecimal = 1 - tranche_progress;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (now < t.cliff_start) {
|
||||||
|
lockedDecimal = 1;
|
||||||
|
} else {
|
||||||
|
lockedDecimal = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const clampedLockedDecimal = Math.max(0, Math.min(1, lockedDecimal));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
tranche_id: t.tranche_id,
|
tranche_id: t.tranche_id,
|
||||||
tranche_start: secondsToDate(t.cliff_start),
|
tranche_start: secondsToDate(t.cliff_start),
|
||||||
@@ -60,7 +75,7 @@ export const useTranches = create<TranchesStore>()((set) => ({
|
|||||||
toBigNum(t.current_balance, decimals)
|
toBigNum(t.current_balance, decimals)
|
||||||
),
|
),
|
||||||
locked_amount: toBigNum(t.initial_balance, decimals).times(
|
locked_amount: toBigNum(t.initial_balance, decimals).times(
|
||||||
lockedDecimal
|
clampedLockedDecimal
|
||||||
),
|
),
|
||||||
users: t.users,
|
users: t.users,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import type { RouteChildProps } from '..';
|
||||||
|
import { useDocumentTitle } from '../../hooks/use-document-title';
|
||||||
|
import { Heading } from '../../components/heading';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
const Disclaimer = ({ name }: RouteChildProps) => {
|
||||||
|
useDocumentTitle(name);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Heading title={t('Disclaimer')} />
|
||||||
|
<p className="mb-6 mt-10">{t('disclaimer1')}</p>
|
||||||
|
<p className="mb-6">{t('disclaimer2')}</p>
|
||||||
|
<p className="mb-6">{t('disclaimer3')}</p>
|
||||||
|
<p className="mb-8">{t('disclaimer4')}</p>
|
||||||
|
<p className="mb-8">{t('disclaimer5')}</p>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Disclaimer;
|
||||||
@@ -12,7 +12,8 @@ import { useRefreshAfterEpoch } from '../../hooks/use-refresh-after-epoch';
|
|||||||
import { ProposalsListItem } from '../proposals/components/proposals-list-item';
|
import { ProposalsListItem } from '../proposals/components/proposals-list-item';
|
||||||
import { ProtocolUpgradeProposalsListItem } from '../proposals/components/protocol-upgrade-proposals-list-item/protocol-upgrade-proposals-list-item';
|
import { ProtocolUpgradeProposalsListItem } from '../proposals/components/protocol-upgrade-proposals-list-item/protocol-upgrade-proposals-list-item';
|
||||||
import Routes from '../routes';
|
import Routes from '../routes';
|
||||||
import { ExternalLinks, removePaginationWrapper } from '@vegaprotocol/utils';
|
import { ExternalLinks } from '@vegaprotocol/environment';
|
||||||
|
import { removePaginationWrapper } from '@vegaprotocol/utils';
|
||||||
import { useNodesQuery } from '../staking/home/__generated__/Nodes';
|
import { useNodesQuery } from '../staking/home/__generated__/Nodes';
|
||||||
import { useProposalsQuery } from '../proposals/proposals/__generated__/Proposals';
|
import { useProposalsQuery } from '../proposals/proposals/__generated__/Proposals';
|
||||||
import {
|
import {
|
||||||
@@ -26,6 +27,10 @@ import type { ProposalFieldsFragment } from '../proposals/proposals/__generated_
|
|||||||
import type { NodesFragmentFragment } from '../staking/home/__generated__/Nodes';
|
import type { NodesFragmentFragment } from '../staking/home/__generated__/Nodes';
|
||||||
import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals';
|
import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals';
|
||||||
import { useProtocolUpgradeProposalsQuery } from '@vegaprotocol/proposals';
|
import { useProtocolUpgradeProposalsQuery } from '@vegaprotocol/proposals';
|
||||||
|
import {
|
||||||
|
orderByDate,
|
||||||
|
orderByUpgradeBlockHeight,
|
||||||
|
} from '../proposals/components/proposals-list/proposals-list';
|
||||||
|
|
||||||
const nodesToShow = 6;
|
const nodesToShow = 6;
|
||||||
|
|
||||||
@@ -199,17 +204,20 @@ const GovernanceHome = ({ name }: RouteChildProps) => {
|
|||||||
const proposals = useMemo(
|
const proposals = useMemo(
|
||||||
() =>
|
() =>
|
||||||
proposalsData
|
proposalsData
|
||||||
? getNotRejectedProposals<ProposalFieldsFragment>(
|
? getNotRejectedProposals(proposalsData.proposalsConnection)
|
||||||
proposalsData.proposalsConnection
|
|
||||||
)
|
|
||||||
: [],
|
: [],
|
||||||
[proposalsData]
|
[proposalsData]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const sortedProposals = useMemo(
|
||||||
|
() => orderByDate(proposals).reverse(),
|
||||||
|
[proposals]
|
||||||
|
);
|
||||||
|
|
||||||
const protocolUpgradeProposals = useMemo(
|
const protocolUpgradeProposals = useMemo(
|
||||||
() =>
|
() =>
|
||||||
protocolUpgradesData
|
protocolUpgradesData
|
||||||
? getNotRejectedProtocolUpgradeProposals<ProtocolUpgradeProposalFieldsFragment>(
|
? getNotRejectedProtocolUpgradeProposals(
|
||||||
protocolUpgradesData.protocolUpgradeProposals
|
protocolUpgradesData.protocolUpgradeProposals
|
||||||
).filter(
|
).filter(
|
||||||
(p) =>
|
(p) =>
|
||||||
@@ -220,15 +228,20 @@ const GovernanceHome = ({ name }: RouteChildProps) => {
|
|||||||
[protocolUpgradesData]
|
[protocolUpgradesData]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const sortedProtocolUpgradeProposals = useMemo(
|
||||||
|
() => orderByUpgradeBlockHeight(protocolUpgradeProposals),
|
||||||
|
[protocolUpgradeProposals]
|
||||||
|
);
|
||||||
|
|
||||||
const totalProposalsDesired = 4;
|
const totalProposalsDesired = 4;
|
||||||
const protocolUpgradeProposalsToShow = protocolUpgradeProposals.slice(
|
const protocolUpgradeProposalsToShow = sortedProtocolUpgradeProposals.slice(
|
||||||
0,
|
0,
|
||||||
totalProposalsDesired
|
totalProposalsDesired
|
||||||
);
|
);
|
||||||
const proposalsToShow =
|
const proposalsToShow =
|
||||||
protocolUpgradeProposalsToShow.length === totalProposalsDesired
|
protocolUpgradeProposalsToShow.length === totalProposalsDesired
|
||||||
? []
|
? []
|
||||||
: proposals.slice(
|
: sortedProposals.slice(
|
||||||
0,
|
0,
|
||||||
totalProposalsDesired - protocolUpgradeProposalsToShow.length
|
totalProposalsDesired - protocolUpgradeProposalsToShow.length
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ const mockAppState: AppState = {
|
|||||||
totalSupply: new BigNumber(65000000),
|
totalSupply: new BigNumber(65000000),
|
||||||
vegaWalletOverlay: false,
|
vegaWalletOverlay: false,
|
||||||
vegaWalletManageOverlay: false,
|
vegaWalletManageOverlay: false,
|
||||||
ethConnectOverlay: false,
|
|
||||||
transactionOverlay: false,
|
transactionOverlay: false,
|
||||||
bannerMessage: '',
|
bannerMessage: '',
|
||||||
disconnectNotice: false,
|
disconnectNotice: false,
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export { ProposalDescription } from './proposal-description';
|
||||||
+51
@@ -0,0 +1,51 @@
|
|||||||
|
import ReactMarkdown from 'react-markdown';
|
||||||
|
import classnames from 'classnames';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { Icon, RoundedWrapper } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { SubHeading } from '../../../../components/heading';
|
||||||
|
|
||||||
|
export const ProposalDescription = ({
|
||||||
|
description,
|
||||||
|
}: {
|
||||||
|
description: string;
|
||||||
|
}) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [showDescription, setShowDescription] = useState(false);
|
||||||
|
const showDescriptionIconClasses = classnames('mb-4', {
|
||||||
|
'rotate-180': showDescription,
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section data-testid="proposal-description">
|
||||||
|
<button
|
||||||
|
onClick={() => setShowDescription(!showDescription)}
|
||||||
|
data-testid="proposal-description-toggle"
|
||||||
|
>
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<SubHeading title={t('proposalDescription')} />
|
||||||
|
<div className={showDescriptionIconClasses}>
|
||||||
|
<Icon name="chevron-down" size={8} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{showDescription && (
|
||||||
|
<RoundedWrapper paddingBottom={true} marginBottomLarge={true}>
|
||||||
|
<div className="p-2">
|
||||||
|
<ReactMarkdown
|
||||||
|
className="react-markdown-container"
|
||||||
|
/* Prevents HTML embedded in the description from rendering */
|
||||||
|
skipHtml={true}
|
||||||
|
/* Stops users embedding images which could be used for tracking */
|
||||||
|
disallowedElements={['img']}
|
||||||
|
linkTarget="_blank"
|
||||||
|
>
|
||||||
|
{description}
|
||||||
|
</ReactMarkdown>
|
||||||
|
</div>
|
||||||
|
</RoundedWrapper>
|
||||||
|
)}
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
+1
-23
@@ -124,7 +124,7 @@ describe('Proposal header', () => {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
expect(screen.getByTestId('proposal-title')).toHaveTextContent(
|
expect(screen.getByTestId('proposal-title')).toHaveTextContent(
|
||||||
'Unknown proposal'
|
'New asset proposal'
|
||||||
);
|
);
|
||||||
expect(screen.getByTestId('proposal-type')).toHaveTextContent('New asset');
|
expect(screen.getByTestId('proposal-type')).toHaveTextContent('New asset');
|
||||||
expect(screen.getByTestId('proposal-details')).toHaveTextContent(
|
expect(screen.getByTestId('proposal-details')).toHaveTextContent(
|
||||||
@@ -206,28 +206,6 @@ describe('Proposal header', () => {
|
|||||||
).not.toBeInTheDocument();
|
).not.toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Renders Freeform proposal - long rationale (105 chars) - details', () => {
|
|
||||||
renderComponent(
|
|
||||||
generateProposal({
|
|
||||||
id: 'long',
|
|
||||||
rationale: {
|
|
||||||
title: '0x0',
|
|
||||||
description:
|
|
||||||
'Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean dolor.',
|
|
||||||
},
|
|
||||||
terms: {
|
|
||||||
change: {
|
|
||||||
__typename: 'NewFreeform',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
false
|
|
||||||
);
|
|
||||||
expect(screen.getByTestId('proposal-description')).toHaveTextContent(
|
|
||||||
/Class aptent/
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Remove once proposals have rationale and re-enable above tests
|
// Remove once proposals have rationale and re-enable above tests
|
||||||
it('Renders Freeform proposal - id for title', () => {
|
it('Renders Freeform proposal - id for title', () => {
|
||||||
renderComponent(
|
renderComponent(
|
||||||
|
|||||||
+14
-26
@@ -5,7 +5,6 @@ import { Heading, SubHeading } from '../../../../components/heading';
|
|||||||
import type { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
|
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
|
||||||
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
|
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
|
||||||
import ReactMarkdown from 'react-markdown';
|
|
||||||
import { truncateMiddle } from '../../../../lib/truncate-middle';
|
import { truncateMiddle } from '../../../../lib/truncate-middle';
|
||||||
import { CurrentProposalState } from '../current-proposal-state';
|
import { CurrentProposalState } from '../current-proposal-state';
|
||||||
import { ProposalInfoLabel } from '../proposal-info-label';
|
import { ProposalInfoLabel } from '../proposal-info-label';
|
||||||
@@ -22,19 +21,16 @@ export const ProposalHeader = ({
|
|||||||
|
|
||||||
let details: ReactNode;
|
let details: ReactNode;
|
||||||
let proposalType = '';
|
let proposalType = '';
|
||||||
|
let fallbackTitle = '';
|
||||||
|
|
||||||
let title = proposal?.rationale.title.trim();
|
const title = proposal?.rationale.title.trim();
|
||||||
let description = proposal?.rationale.description.trim();
|
|
||||||
if (title?.length === 0 && description && description.length > 0) {
|
|
||||||
title = description;
|
|
||||||
description = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
const titleContent = shorten(title ?? '', 100);
|
const titleContent = shorten(title ?? '', 100);
|
||||||
|
|
||||||
switch (change?.__typename) {
|
switch (change?.__typename) {
|
||||||
case 'NewMarket': {
|
case 'NewMarket': {
|
||||||
proposalType = 'NewMarket';
|
proposalType = 'NewMarket';
|
||||||
|
fallbackTitle = t('NewMarketProposal');
|
||||||
details = (
|
details = (
|
||||||
<>
|
<>
|
||||||
<span>
|
<span>
|
||||||
@@ -56,6 +52,7 @@ export const ProposalHeader = ({
|
|||||||
}
|
}
|
||||||
case 'UpdateMarket': {
|
case 'UpdateMarket': {
|
||||||
proposalType = 'UpdateMarket';
|
proposalType = 'UpdateMarket';
|
||||||
|
fallbackTitle = t('UpdateMarketProposal');
|
||||||
details = (
|
details = (
|
||||||
<>
|
<>
|
||||||
<span>{t('Market change')}:</span>{' '}
|
<span>{t('Market change')}:</span>{' '}
|
||||||
@@ -66,6 +63,7 @@ export const ProposalHeader = ({
|
|||||||
}
|
}
|
||||||
case 'NewAsset': {
|
case 'NewAsset': {
|
||||||
proposalType = 'NewAsset';
|
proposalType = 'NewAsset';
|
||||||
|
fallbackTitle = t('NewAssetProposal');
|
||||||
details = (
|
details = (
|
||||||
<>
|
<>
|
||||||
<span>{t('Symbol')}:</span> <Lozenge>{change.symbol}.</Lozenge>{' '}
|
<span>{t('Symbol')}:</span> <Lozenge>{change.symbol}.</Lozenge>{' '}
|
||||||
@@ -87,6 +85,7 @@ export const ProposalHeader = ({
|
|||||||
}
|
}
|
||||||
case 'UpdateNetworkParameter': {
|
case 'UpdateNetworkParameter': {
|
||||||
proposalType = 'NetworkParameter';
|
proposalType = 'NetworkParameter';
|
||||||
|
fallbackTitle = t('NetworkParameterProposal');
|
||||||
details = (
|
details = (
|
||||||
<>
|
<>
|
||||||
<span>{t('Change')}:</span>{' '}
|
<span>{t('Change')}:</span>{' '}
|
||||||
@@ -101,11 +100,13 @@ export const ProposalHeader = ({
|
|||||||
}
|
}
|
||||||
case 'NewFreeform': {
|
case 'NewFreeform': {
|
||||||
proposalType = 'Freeform';
|
proposalType = 'Freeform';
|
||||||
|
fallbackTitle = t('FreeformProposal');
|
||||||
details = <span />;
|
details = <span />;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'UpdateAsset': {
|
case 'UpdateAsset': {
|
||||||
proposalType = 'UpdateAsset';
|
proposalType = 'UpdateAsset';
|
||||||
|
fallbackTitle = t('UpdateAssetProposal');
|
||||||
details = (
|
details = (
|
||||||
<>
|
<>
|
||||||
<span>{t('AssetID')}:</span>{' '}
|
<span>{t('AssetID')}:</span>{' '}
|
||||||
@@ -121,10 +122,14 @@ export const ProposalHeader = ({
|
|||||||
<div data-testid="proposal-title">
|
<div data-testid="proposal-title">
|
||||||
{isListItem ? (
|
{isListItem ? (
|
||||||
<header>
|
<header>
|
||||||
<SubHeading title={titleContent || t('Unknown proposal')} />
|
<SubHeading
|
||||||
|
title={titleContent || fallbackTitle || t('Unknown proposal')}
|
||||||
|
/>
|
||||||
</header>
|
</header>
|
||||||
) : (
|
) : (
|
||||||
<Heading title={titleContent || t('Unknown proposal')} />
|
<Heading
|
||||||
|
title={titleContent || fallbackTitle || t('Unknown proposal')}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -145,23 +150,6 @@ export const ProposalHeader = ({
|
|||||||
{details}
|
{details}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{description && !isListItem && (
|
|
||||||
<div data-testid="proposal-description">
|
|
||||||
{/*<div className="uppercase mr-2">{t('ProposalDescription')}:</div>*/}
|
|
||||||
<SubHeading title={t('ProposalDescription')} />
|
|
||||||
<ReactMarkdown
|
|
||||||
className="react-markdown-container"
|
|
||||||
/* Prevents HTML embedded in the description from rendering */
|
|
||||||
skipHtml={true}
|
|
||||||
/* Stops users embedding images which could be used for tracking */
|
|
||||||
disallowedElements={['img']}
|
|
||||||
linkTarget="_blank"
|
|
||||||
>
|
|
||||||
{description}
|
|
||||||
</ReactMarkdown>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export { ProposalJson } from './proposal-json';
|
||||||
+11
-11
@@ -1,15 +1,15 @@
|
|||||||
|
import classnames from 'classnames';
|
||||||
|
import { useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Icon, SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
import { Icon, SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
||||||
import { SubHeading } from '../../../../components/heading';
|
import { SubHeading } from '../../../../components/heading';
|
||||||
import type { PartialDeep } from 'type-fest';
|
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
|
||||||
import type * as Schema from '@vegaprotocol/types';
|
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
|
||||||
import { useState } from 'react';
|
|
||||||
import classnames from 'classnames';
|
|
||||||
|
|
||||||
export const ProposalTermsJson = ({
|
export const ProposalJson = ({
|
||||||
terms,
|
proposal,
|
||||||
}: {
|
}: {
|
||||||
terms: PartialDeep<Schema.ProposalTerms>;
|
proposal: ProposalFieldsFragment | ProposalQuery['proposal'];
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [showDetails, setShowDetails] = useState(false);
|
const [showDetails, setShowDetails] = useState(false);
|
||||||
@@ -18,20 +18,20 @@ export const ProposalTermsJson = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section>
|
<section data-testid="proposal-json">
|
||||||
<button
|
<button
|
||||||
onClick={() => setShowDetails(!showDetails)}
|
onClick={() => setShowDetails(!showDetails)}
|
||||||
data-testid="proposal-terms-toggle"
|
data-testid="proposal-json-toggle"
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<SubHeading title={t('proposalTerms')} />
|
<SubHeading title={t('proposalJson')} />
|
||||||
<div className={showDetailsIconClasses}>
|
<div className={showDetailsIconClasses}>
|
||||||
<Icon name="chevron-down" size={8} />
|
<Icon name="chevron-down" size={8} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{showDetails && <SyntaxHighlighter data={terms} />}
|
{showDetails && <SyntaxHighlighter data={proposal} />}
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { ProposalTermsJson } from './proposal-terms-json';
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { ProposalTerms } from './proposal-terms';
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user