Compare commits
225
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d959e37e59 | ||
|
|
64db83fe52 | ||
|
|
ac4762f9d7 | ||
|
|
1195309b61 | ||
|
|
8ce77e23ba | ||
|
|
5cae2ce400 | ||
|
|
b8c9f9772e | ||
|
|
c3e39b6e15 | ||
|
|
77a391448b | ||
|
|
484d7888cf | ||
|
|
187f1929fe | ||
|
|
0a4333645b | ||
|
|
310506e5af | ||
|
|
0b33ed4299 | ||
|
|
13f2e51798 | ||
|
|
fc047feeee | ||
|
|
005455c870 | ||
|
|
2c2bc391e8 | ||
|
|
445a085190 | ||
|
|
bb1b236cdf | ||
|
|
da66b7b20d | ||
|
|
ec12811f72 | ||
|
|
180de8cf25 | ||
|
|
df88e77cdf | ||
|
|
9441aee8cf | ||
|
|
2353812834 | ||
|
|
bba2b3c177 | ||
|
|
ae57bd92f4 | ||
|
|
115b642140 | ||
|
|
ce3da97a8a | ||
|
|
cabd99d3ef | ||
|
|
597e07608f | ||
|
|
e451dc54b3 | ||
|
|
9703c3b7a6 | ||
|
|
c22b6f3ce9 | ||
|
|
c740c11eaa | ||
|
|
d1fabb31a3 | ||
|
|
94f045a60b | ||
|
|
1af375bab8 | ||
|
|
5a48ba4a33 | ||
|
|
d1fd9184ce | ||
|
|
8f29824f9e | ||
|
|
fc3c73ad24 | ||
|
|
1027827576 | ||
|
|
0089920d4c | ||
|
|
35896a9cf5 | ||
|
|
5a90ebe12e | ||
|
|
6be117086a | ||
|
|
9c6dd9f254 | ||
|
|
a675576a52 | ||
|
|
98d248e02e | ||
|
|
c8d55c6293 | ||
|
|
3467feb3e5 | ||
|
|
bdf1663709 | ||
|
|
d775573543 | ||
|
|
c0fdc8d570 | ||
|
|
a9ebb36b9b | ||
|
|
f6c0082f2d | ||
|
|
931ad75cc9 | ||
|
|
f25a58a3c3 | ||
|
|
37340b4dc3 | ||
|
|
17ba3eb351 | ||
|
|
8f966a4ba6 | ||
|
|
cc7f403718 | ||
|
|
9184c2374c | ||
|
|
37247a504a | ||
|
|
2e7a6a6458 | ||
|
|
bf6c13f523 | ||
|
|
a6f3a08d2f | ||
|
|
f13e456a29 | ||
|
|
5cab040189 | ||
|
|
e47b868c53 | ||
|
|
b6286cd0f3 | ||
|
|
f66e976b66 | ||
|
|
866e7232db | ||
|
|
5a8ff90890 | ||
|
|
7b8f654906 | ||
|
|
d6f39049bd | ||
|
|
1d06be8f4e | ||
|
|
5eba8fe28f | ||
|
|
2ba0e9a1b2 | ||
|
|
43d3754c64 | ||
|
|
aae5c44fa4 | ||
|
|
878bed9c7a | ||
|
|
6f9f432c90 | ||
|
|
3f01b93159 | ||
|
|
473c244d7b | ||
|
|
d6a32f5090 | ||
|
|
71540a90fb | ||
|
|
cefdbe6a3c | ||
|
|
3928dd5c0e | ||
|
|
1521bab4c4 | ||
|
|
b3036d520f | ||
|
|
429a5a23d3 | ||
|
|
5b02fd5d54 | ||
|
|
b8309a76e7 | ||
|
|
e8ae085c06 | ||
|
|
fdcd24847c | ||
|
|
e054db39b5 | ||
|
|
a01e48d508 | ||
|
|
0d96c487d9 | ||
|
|
011e4e4cec | ||
|
|
d6e2432955 | ||
|
|
18c034b910 | ||
|
|
849cbb43c4 | ||
|
|
cd34cb181f | ||
|
|
97b3f4decf | ||
|
|
0465fb8ca9 | ||
|
|
22af89e78c | ||
|
|
adfd2f41b6 | ||
|
|
d9b1aa6da3 | ||
|
|
205f369cdc | ||
|
|
9f63fde123 | ||
|
|
f2c70e6da4 | ||
|
|
e8ff1b0b60 | ||
|
|
f5989b0022 | ||
|
|
653ca034f2 | ||
|
|
ef25552311 | ||
|
|
0a8439d125 | ||
|
|
702ea0c6b4 | ||
|
|
0f2b86770a | ||
|
|
cd6d350047 | ||
|
|
c5a06c57ac | ||
|
|
5bb31fa38d | ||
|
|
fd8f38803c | ||
|
|
a22f8f0ef1 | ||
|
|
c2d5c71f35 | ||
|
|
f88c35648e | ||
|
|
348c61530e | ||
|
|
f364dabe2f | ||
|
|
1ae1fdff5e | ||
|
|
3ed615c36e | ||
|
|
6b50816234 | ||
|
|
f5e67a0c2d | ||
|
|
e4d4646878 | ||
|
|
bbd1536c18 | ||
|
|
f8444c0c88 | ||
|
|
b1adf776c0 | ||
|
|
ad898ab0e8 | ||
|
|
5b0fffc5cb | ||
|
|
a9dbc0f6eb | ||
|
|
a71786817f | ||
|
|
9ee0cb7b65 | ||
|
|
8c4aa41240 | ||
|
|
91ac977704 | ||
|
|
1190033776 | ||
|
|
b99e2235b4 | ||
|
|
002bc4f188 | ||
|
|
0c2af8c75f | ||
|
|
a305c5b8a9 | ||
|
|
4c3ceb94f3 | ||
|
|
2215864d0c | ||
|
|
589785ce09 | ||
|
|
babd99088d | ||
|
|
d155909fe4 | ||
|
|
1d3298cdc9 | ||
|
|
c2baaa2dd9 | ||
|
|
e2c4c4a841 | ||
|
|
7a89dc984d | ||
|
|
19580fb9ce | ||
|
|
0721099d7d | ||
|
|
9ee2810c51 | ||
|
|
9f8f99b50b | ||
|
|
3208f762fd | ||
|
|
7a06c946d1 | ||
|
|
70e172045d | ||
|
|
06c540666e | ||
|
|
f81503b8f7 | ||
|
|
1699e33cbd | ||
|
|
5280b79927 | ||
|
|
34526d527e | ||
|
|
7b9aae700d | ||
|
|
e9cb2ad217 | ||
|
|
6dd4536fdd | ||
|
|
522eb521b9 | ||
|
|
3aa0e974c2 | ||
|
|
a0eb381ab1 | ||
|
|
a51ab4d98d | ||
|
|
67643afd74 | ||
|
|
145539e0c0 | ||
|
|
48109b584c | ||
|
|
a4512e6064 | ||
|
|
45adac2932 | ||
|
|
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 |
@@ -14,8 +14,7 @@ What we need to achieve and who for
|
|||||||
|
|
||||||
## Tasks
|
## Tasks
|
||||||
|
|
||||||
- [ ] What do we need to do first
|
- [ ]
|
||||||
- [ ] and then what?
|
- [ ]
|
||||||
- [ ] Etc.
|
|
||||||
|
|
||||||
## Additional details / background info
|
## Additional details / background info
|
||||||
|
|||||||
@@ -22,11 +22,14 @@ So that
|
|||||||
|
|
||||||
## Tasks
|
## Tasks
|
||||||
|
|
||||||
- [ ] Explore and sketch
|
- [ ] UX (if needed)
|
||||||
|
- [ ] Design (if needed)
|
||||||
- [ ] Team and stakeholder review
|
- [ ] Team and stakeholder review
|
||||||
- [ ] Visual Design
|
- [ ] Specs reviewed and created or adjusted
|
||||||
- [ ] Team review
|
- [ ] Implementation
|
||||||
- [ ] Etc.
|
- [ ] Testing (unit and/or e2e)
|
||||||
|
- [ ] Code review
|
||||||
|
- [ ] QA review
|
||||||
|
|
||||||
## Sketch
|
## Sketch
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,11 @@ jobs:
|
|||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
steps:
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
@@ -27,14 +32,16 @@ jobs:
|
|||||||
|
|
||||||
- name: resolve ipfs hashes for release
|
- name: resolve ipfs hashes for release
|
||||||
run: |
|
run: |
|
||||||
echo "Tag name: ${{ github.event.release.tag_name }}"
|
|
||||||
echo "Name: ${{ github.event.release.name }}"
|
echo "Name: ${{ github.event.release.name }}"
|
||||||
echo "Description: ${{ github.event.release.body }}"
|
echo "Description: ${{ github.event.release.body }}"
|
||||||
until docker pull vegaprotocol/trading:${{ github.event.release.tag_name }}; do
|
echo "Tag: ${{ github.event.release.tag_name }}"
|
||||||
|
commit="$(git rev-list -n 1 ${{ github.event.release.tag_name }})"
|
||||||
|
echo "Commit: $commit"
|
||||||
|
until docker pull vegaprotocol/trading:$commit; do
|
||||||
echo "Image not pushed yet, waiting 60 seconds"
|
echo "Image not pushed yet, waiting 60 seconds"
|
||||||
sleep 60
|
sleep 60
|
||||||
done
|
done
|
||||||
docker run --rm vegaprotocol/trading:${{ github.event.release.tag_name }} cat /ipfs-hash > ipfs-hash
|
docker run --rm vegaprotocol/trading:$commit 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
|
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
|
tar -xzf kubo.tgz
|
||||||
export PATH="$PATH:$PWD/kubo"
|
export PATH="$PATH:$PWD/kubo"
|
||||||
@@ -48,19 +55,20 @@ jobs:
|
|||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
id: ${{ github.event.release.id }}
|
id: ${{ github.event.release.id }}
|
||||||
body: |
|
body: |
|
||||||
---
|
|
||||||
|
___
|
||||||
|
|
||||||
# Deployments
|
# Deployments
|
||||||
* https://explorer.vega.xyz
|
* https://explorer.vega.xyz
|
||||||
* https://governance.vega.xyz
|
* https://governance.vega.xyz
|
||||||
|
|
||||||
# IPFS releases
|
# IPFS releases
|
||||||
Tye IPFS hash of this release of the Trading app is:
|
The IPFS hash of this release of the Trading app is:
|
||||||
|
|
||||||
CIDv0: ${{ env.IPFS_V0 }}
|
CIDv0: ${{ env.IPFS_V0 }}
|
||||||
CIDv1: ${{ env.IPFS_V1 }}
|
CIDv1: ${{ env.IPFS_V1 }}
|
||||||
|
|
||||||
You can always access the latest IPFS release by visiting [vega.trading](https://vega.trading).
|
You can always access the latest IPFS release by visiting [console.vega.xyz](https://console.vega.xyz).
|
||||||
|
|
||||||
You can also access Trading directly from an IPFS gateway.
|
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/).
|
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/).
|
||||||
|
|||||||
@@ -5,9 +5,10 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- release/*
|
- release/*
|
||||||
- develop
|
- develop
|
||||||
tags:
|
- main
|
||||||
- v*
|
# uncomment pull_request and comment pull_request_target to test CI changes against feature branch not target branch (develop)
|
||||||
pull_request:
|
# pull_request:
|
||||||
|
pull_request_target:
|
||||||
types:
|
types:
|
||||||
- opened
|
- opened
|
||||||
- ready_for_review
|
- ready_for_review
|
||||||
@@ -21,6 +22,8 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||||
|
|
||||||
- name: Cache node modules
|
- name: Cache node modules
|
||||||
id: cache
|
id: cache
|
||||||
@@ -61,6 +64,7 @@ jobs:
|
|||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||||
|
|
||||||
- name: Setup node
|
- name: Setup node
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
@@ -98,44 +102,96 @@ 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_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)"
|
projects_array=()
|
||||||
|
|
||||||
branch_slug="$(echo '${{ github.head_ref || github.ref_name }}' | sed -r s/[^a-zA-Z0-9]+/-/g | sed -r s/^-+\|-+$//g | cut -c 1-50 )"
|
|
||||||
projects_e2e=""
|
|
||||||
preview_governance="not deployed"
|
preview_governance="not deployed"
|
||||||
preview_trading="not deployed"
|
preview_trading="not deployed"
|
||||||
preview_explorer="not deployed"
|
preview_explorer="not deployed"
|
||||||
if [[ -z "$projects_e2e" ]]; then
|
preview_tools="not deployed"
|
||||||
projects_e2e+='"governance-e2e" "trading-e2e" "explorer-e2e" '
|
|
||||||
|
# parse if affected is any of three main applications, if none - use all of them
|
||||||
|
if echo "$affected" | grep -q governance; then
|
||||||
|
echo "Governance is affected"
|
||||||
|
projects_array+=("governance")
|
||||||
|
preview_governance=$(printf "https://%s.%s.vega.rocks" "governance" "$branch_slug")
|
||||||
|
fi
|
||||||
|
if echo "$affected" | grep -q trading; then
|
||||||
|
echo "Trading is affected"
|
||||||
|
projects_array+=("trading")
|
||||||
|
preview_trading=$(printf "https://%s.%s.vega.rocks" "trading" "$branch_slug")
|
||||||
|
fi
|
||||||
|
if echo "$affected" | grep -q explorer; then
|
||||||
|
echo "Explorer is affected"
|
||||||
|
projects_array+=("explorer")
|
||||||
|
preview_explorer=$(printf "https://%s.%s.vega.rocks" "explorer" "$branch_slug")
|
||||||
|
fi
|
||||||
|
if [[ ${#projects_array[@]} -eq 0 ]]; then
|
||||||
|
projects_array=("governance" "trading" "explorer")
|
||||||
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
|
fi
|
||||||
if [[ $affected == *"governance"* ]]; then
|
|
||||||
projects_e2e+='"governance-e2e" '
|
# applications parsed before this loop are applicable for running e2e-tests
|
||||||
preview_governance=$(printf "https://%s.%s.vega.rocks" "governance" "$branch_slug")
|
projects_e2e_array=()
|
||||||
|
for project in "${projects_array[@]}"; do
|
||||||
|
projects_e2e_array+=("${project}-e2e")
|
||||||
|
done
|
||||||
|
# all applications below this loop are not applicable for running e2e-test
|
||||||
|
|
||||||
|
# check if pull request event to deploy tools
|
||||||
|
if [[ "${{ github.event_name }}" = "pull_request" ]]; then
|
||||||
|
if echo "$affected" | grep -q multisig-signer; then
|
||||||
|
echo "Tools are affected"
|
||||||
|
echo "Deploying tools on preview"
|
||||||
|
preview_tools=$(printf "https://%s.%s.vega.rocks" "tools" "$branch_slug")
|
||||||
|
|
||||||
|
projects_array+=("multisig-signer")
|
||||||
fi
|
fi
|
||||||
if [[ $affected == *"trading"* ]]; then
|
# those apps deploy only from develop to mainnet
|
||||||
projects_e2e+='"trading-e2e" '
|
elif [[ "${{ github.ref }}" =~ .*develop$ ]]; then
|
||||||
preview_trading=$(printf "https://%s.%s.vega.rocks" "trading" "$branch_slug")
|
if echo "$affected" | grep -q multisig-signer; then
|
||||||
|
echo "Tools are affected"
|
||||||
|
echo "Deploying tools on s3"
|
||||||
|
|
||||||
|
projects_array+=("multisig-signer")
|
||||||
fi
|
fi
|
||||||
if [[ $affected == *"explorer"* ]]; then
|
if echo "$affected" | grep -q static; then
|
||||||
projects_e2e+='"explorer-e2e" '
|
echo "static is affected"
|
||||||
preview_explorer=$(printf "https://%s.%s.vega.rocks" "explorer" "$branch_slug")
|
echo "Deploying static on s3"
|
||||||
|
|
||||||
|
projects_array+=("static")
|
||||||
|
fi
|
||||||
|
if echo "$affected" | grep -q ui-toolkit; then
|
||||||
|
echo "ui-toolkit is affected"
|
||||||
|
echo "Deploying ui-toolkit on s3"
|
||||||
|
|
||||||
|
projects_array+=("ui-toolkit")
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
projects_e2e=${projects_e2e%?}
|
|
||||||
projects_e2e=[${projects_e2e// /,}]
|
echo "Projects: ${projects_array[@]}"
|
||||||
echo PROJECTS_E2E=$projects_e2e >> $GITHUB_ENV
|
echo "Projects E2E: ${projects_e2e_array[@]}"
|
||||||
echo PROJECTS=$(echo $projects_e2e | sed 's|-e2e||g') >> $GITHUB_ENV
|
projects_json=$(jq -M --compact-output --null-input '$ARGS.positional' --args -- "${projects_array[@]}")
|
||||||
|
projects_e2e_json=$(jq -M --compact-output --null-input '$ARGS.positional' --args -- "${projects_e2e_array[@]}")
|
||||||
|
|
||||||
|
echo PROJECTS_E2E=$projects_e2e_json >> $GITHUB_ENV
|
||||||
|
echo PROJECTS=$projects_json >> $GITHUB_ENV
|
||||||
|
|
||||||
echo PREVIEW_GOVERNANCE=$preview_governance >> $GITHUB_ENV
|
echo PREVIEW_GOVERNANCE=$preview_governance >> $GITHUB_ENV
|
||||||
echo PREVIEW_TRADING=$preview_trading >> $GITHUB_ENV
|
echo PREVIEW_TRADING=$preview_trading >> $GITHUB_ENV
|
||||||
echo PREVIEW_EXPLORER=$preview_explorer >> $GITHUB_ENV
|
echo PREVIEW_EXPLORER=$preview_explorer >> $GITHUB_ENV
|
||||||
|
echo PREVIEW_TOOLS=$preview_tools >> $GITHUB_ENV
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
projects: ${{ env.PROJECTS }}
|
projects: ${{ env.PROJECTS }}
|
||||||
@@ -143,11 +199,12 @@ jobs:
|
|||||||
preview_governance: ${{ env.PREVIEW_GOVERNANCE }}
|
preview_governance: ${{ env.PREVIEW_GOVERNANCE }}
|
||||||
preview_trading: ${{ env.PREVIEW_TRADING }}
|
preview_trading: ${{ env.PREVIEW_TRADING }}
|
||||||
preview_explorer: ${{ env.PREVIEW_EXPLORER }}
|
preview_explorer: ${{ env.PREVIEW_EXPLORER }}
|
||||||
|
preview_tools: ${{ env.PREVIEW_TOOLS }}
|
||||||
|
|
||||||
cypress:
|
cypress:
|
||||||
needs: lint-test-build
|
needs: lint-test-build
|
||||||
name: '(CI) cypress'
|
name: '(CI) cypress'
|
||||||
if: ${{ needs.lint-test-build.outputs.projects != '[]' }}
|
if: ${{ needs.lint-test-build.outputs.projects-e2e != '[]' }}
|
||||||
uses: ./.github/workflows/cypress-run.yml
|
uses: ./.github/workflows/cypress-run.yml
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
with:
|
with:
|
||||||
@@ -169,6 +226,7 @@ jobs:
|
|||||||
- publish-dist
|
- publish-dist
|
||||||
- lint-test-build
|
- lint-test-build
|
||||||
if: ${{ github.event_name == 'pull_request' }}
|
if: ${{ github.event_name == 'pull_request' }}
|
||||||
|
timeout-minutes: 60
|
||||||
name: '(CD) comment preview links'
|
name: '(CD) comment preview links'
|
||||||
steps:
|
steps:
|
||||||
- name: Find Comment
|
- name: Find Comment
|
||||||
@@ -178,6 +236,35 @@ jobs:
|
|||||||
issue-number: ${{ github.event.pull_request.number }}
|
issue-number: ${{ github.event.pull_request.number }}
|
||||||
body-includes: Previews
|
body-includes: Previews
|
||||||
|
|
||||||
|
- name: Wait for deployments
|
||||||
|
run: |
|
||||||
|
# https://stackoverflow.com/questions/3183444/check-for-valid-link-url
|
||||||
|
regex='(https?|ftp|file)://[-[:alnum:]\+&@#/%?=~_|!:,.;]*[-[:alnum:]\+&@#/%=~_|]'
|
||||||
|
if [[ "${{ needs.lint-test-build.outputs.preview_governance }}" =~ $regex ]]; then
|
||||||
|
until curl -L --fail "${{ needs.lint-test-build.outputs.preview_governance }}"; do
|
||||||
|
echo "waiting for governance preview"
|
||||||
|
sleep 5
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
if [[ "${{ needs.lint-test-build.outputs.preview_explorer }}" =~ $regex ]]; then
|
||||||
|
until curl -L --fail "${{ needs.lint-test-build.outputs.preview_explorer }}"; do
|
||||||
|
echo "waiting for explorer preview"
|
||||||
|
sleep 5
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
if [[ "${{ needs.lint-test-build.outputs.preview_trading }}" =~ $regex ]]; then
|
||||||
|
until curl -L --fail "${{ needs.lint-test-build.outputs.preview_trading }}"; do
|
||||||
|
echo "waiting for trading preview"
|
||||||
|
sleep 5
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
if [[ "${{ needs.lint-test-build.outputs.preview_tools }}" =~ $regex ]]; then
|
||||||
|
until curl -L --fail "${{ needs.lint-test-build.outputs.preview_tools }}"; do
|
||||||
|
echo "waiting for tools preview"
|
||||||
|
sleep 5
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Create comment
|
- name: Create comment
|
||||||
uses: peter-evans/create-or-update-comment@v3
|
uses: peter-evans/create-or-update-comment@v3
|
||||||
if: ${{ steps.fc.outputs.comment-id == 0 }}
|
if: ${{ steps.fc.outputs.comment-id == 0 }}
|
||||||
@@ -188,16 +275,11 @@ jobs:
|
|||||||
* governance: ${{ needs.lint-test-build.outputs.preview_governance }}
|
* governance: ${{ needs.lint-test-build.outputs.preview_governance }}
|
||||||
* explorer: ${{ needs.lint-test-build.outputs.preview_explorer }}
|
* explorer: ${{ needs.lint-test-build.outputs.preview_explorer }}
|
||||||
* trading: ${{ needs.lint-test-build.outputs.preview_trading }}
|
* trading: ${{ needs.lint-test-build.outputs.preview_trading }}
|
||||||
|
* tools: ${{ needs.lint-test-build.outputs.preview_tools }}
|
||||||
cypress-check:
|
|
||||||
name: '(CI) cypress - check'
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: cypress
|
|
||||||
steps:
|
|
||||||
- run: echo Done!
|
|
||||||
|
|
||||||
# Report single result at the end, to avoid mess with required checks in PR
|
# Report single result at the end, to avoid mess with required checks in PR
|
||||||
cypress-result:
|
cypress-check:
|
||||||
|
name: '(CI) cypress - check'
|
||||||
if: ${{ always() }}
|
if: ${{ always() }}
|
||||||
needs: cypress
|
needs: cypress
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
|
|||||||
@@ -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: 60
|
timeout-minutes: 100
|
||||||
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
|
||||||
@@ -33,6 +33,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
path: './frontend-monorepo'
|
path: './frontend-monorepo'
|
||||||
|
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||||
|
|
||||||
# Restore node_modules from cache if possible
|
# Restore node_modules from cache if possible
|
||||||
- name: Restore node_modules from cache
|
- name: Restore node_modules from cache
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||||
|
|
||||||
- name: Setup node
|
- name: Setup node
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
name: Generate tranches
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 */6 * * *'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
master:
|
|
||||||
name: Generate Queries
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
|
|
||||||
fetch-depth: 0
|
|
||||||
- name: Use Node.js 16
|
|
||||||
id: Node
|
|
||||||
uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: 16.15.1
|
|
||||||
- name: Install root dependencies
|
|
||||||
run: yarn install
|
|
||||||
- name: Generate queries
|
|
||||||
run: node ./scripts/get-tranches.js
|
|
||||||
- uses: stefanzweifel/git-auto-commit-action@v4
|
|
||||||
with:
|
|
||||||
commit_message: 'chore: update tranches'
|
|
||||||
commit_options: '--no-verify --signoff'
|
|
||||||
skip_fetch: true
|
|
||||||
skip_checkout: true
|
|
||||||
@@ -19,6 +19,8 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Check out code
|
- name: Check out code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
id: quemu
|
id: quemu
|
||||||
@@ -31,6 +33,7 @@ jobs:
|
|||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
- name: Log in to the Container registry (ghcr)
|
- name: Log in to the Container registry (ghcr)
|
||||||
|
if: ${{ github.event_name == 'pull_request' }}
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
@@ -39,7 +42,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Log in to the Container registry (docker hub)
|
- name: Log in to the Container registry (docker hub)
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v2
|
||||||
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
|
if: ${{ matrix.app == 'trading' && github.event_name == 'push' && ( endsWith(github.ref, 'main') || endsWith(github.ref, 'release/testnet') ) }}
|
||||||
with:
|
with:
|
||||||
# registry: registry.hub.docker.com
|
# registry: registry.hub.docker.com
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
@@ -59,38 +62,68 @@ jobs:
|
|||||||
key: ${{ runner.os }}-cache-node-modules-${{ hashFiles('yarn.lock') }}
|
key: ${{ runner.os }}-cache-node-modules-${{ hashFiles('yarn.lock') }}
|
||||||
|
|
||||||
# https://docs.github.com/en/actions/learn-github-actions/contexts
|
# https://docs.github.com/en/actions/learn-github-actions/contexts
|
||||||
- name: Define variables
|
- name: Define dist variables
|
||||||
|
if: ${{ github.event_name == 'push' }}
|
||||||
run: |
|
run: |
|
||||||
envName=''
|
envName=''
|
||||||
if [[ "${{ github.event_name }}" = "push" ]]; then
|
domain="vega.rocks"
|
||||||
domain="vega.rocks"
|
bucketName=''
|
||||||
if [[ "${{ github.ref }}" =~ .*release/.* ]]; then
|
|
||||||
envName="$(echo ${{ github.ref }} | rev | cut -d '/' -f 1 | rev)"
|
if [[ "${{ github.ref }}" =~ .*release/.* ]]; then
|
||||||
if [[ "${{ github.ref }}" =~ .*mainnet.* ]]; then
|
envName="$(echo ${{ github.ref }} | rev | cut -d '/' -f 1 | rev)"
|
||||||
domain="vega.community"
|
elif [[ "${{ github.ref }}" =~ .*develop$ ]]; then
|
||||||
fi
|
envName="stagnet1"
|
||||||
elif [[ "${{ github.ref }}" =~ .*develop$ ]]; then
|
if [[ "${{ matrix.app }}" = "multisig-signer" ]]; then
|
||||||
envName="stagnet1"
|
|
||||||
elif [[ "${{ matrix.app}}" = "trading" ]] && [[ ${{ startsWith(github.ref, 'refs/tags/v') && 'true' || 'false' }} = "true" ]]; then
|
|
||||||
envName="mainnet"
|
envName="mainnet"
|
||||||
|
bucketName="tools.vega.xyz"
|
||||||
fi
|
fi
|
||||||
bucketName="${{ matrix.app }}.${envName}.${domain}"
|
if [[ "${{ matrix.app }}" = "static" ]]; then
|
||||||
echo BUCKET_NAME=${bucketName} >> $GITHUB_ENV
|
envName="mainnet"
|
||||||
|
bucketName="static.vega.xyz"
|
||||||
|
fi
|
||||||
|
if [[ "${{ matrix.app }}" = "ui-toolkit" ]]; then
|
||||||
|
envName="mainnet"
|
||||||
|
bucketName="ui.vega.rocks"
|
||||||
|
fi
|
||||||
|
elif [[ "${{ github.ref }}" =~ .*main$ ]]; then
|
||||||
|
envName="mainnet"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ "${envName}" = "mainnet" ]]; then
|
||||||
|
domain="vega.xyz"
|
||||||
|
if [[ -z "${bucketName}" ]]; then
|
||||||
|
bucketName="${{ matrix.app }}.${domain}"
|
||||||
|
fi
|
||||||
|
elif [[ "${envName}" = "testnet" ]]; then
|
||||||
|
domain="fairground.wtf"
|
||||||
|
if [[ -z "${bucketName}" ]]; then
|
||||||
|
bucketName="${{ matrix.app }}.${domain}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "${bucketName}" ]]; then
|
||||||
|
bucketName="${{ matrix.app }}.${envName}.${domain}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "bucket name: ${bucketName}"
|
||||||
|
echo "env name: ${envName}"
|
||||||
|
|
||||||
|
echo BUCKET_NAME=${bucketName} >> $GITHUB_ENV
|
||||||
echo ENV_NAME=${envName} >> $GITHUB_ENV
|
echo ENV_NAME=${envName} >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Build local dist
|
- name: Build local dist
|
||||||
run: |
|
run: |
|
||||||
flags=""
|
flags=""
|
||||||
if [[ ! -z "${{ env.ENV_NAME }}" ]]; then
|
if [[ ! -z "${{ env.ENV_NAME }}" ]]; then
|
||||||
if [[ "${{ env.ENV_NAME }}" != "ops-vega" ]]; then
|
flags="--env=${{ env.ENV_NAME }}"
|
||||||
flags="--env=${{ env.ENV_NAME }}"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "${{ matrix.app }}" = "trading" ]; then
|
if [ "${{ matrix.app }}" = "trading" ]; then
|
||||||
yarn nx export trading $flags || (yarn install && yarn nx export trading $flags)
|
yarn nx export trading $flags || (yarn install && yarn nx export trading $flags)
|
||||||
DIST_LOCATION=dist/apps/trading/exported
|
DIST_LOCATION=dist/apps/trading/exported
|
||||||
|
elif [ "${{ matrix.app }}" = "ui-toolkit" ]; then
|
||||||
|
NODE_ENV=production yarn nx run ui-toolkit:build-storybook
|
||||||
|
DIST_LOCATION=dist/storybook/ui-toolkit
|
||||||
else
|
else
|
||||||
yarn nx build ${{ matrix.app }} $flags || (yarn install && yarn nx build ${{ matrix.app }} $flags)
|
yarn nx build ${{ matrix.app }} $flags || (yarn install && yarn nx build ${{ matrix.app }} $flags)
|
||||||
DIST_LOCATION=dist/apps/${{ matrix.app }}
|
DIST_LOCATION=dist/apps/${{ matrix.app }}
|
||||||
@@ -125,7 +158,9 @@ jobs:
|
|||||||
|
|
||||||
- name: Publish dist as docker image (ghcr)
|
- name: Publish dist as docker image (ghcr)
|
||||||
uses: docker/build-push-action@v3
|
uses: docker/build-push-action@v3
|
||||||
if: ${{ github.event_name == 'pull_request' || (matrix.app == 'trading' && github.event_name == 'push' && !startsWith(github.ref, 'refs/tags/v') ) }}
|
continue-on-error: true
|
||||||
|
id: ghcr-push
|
||||||
|
if: ${{ github.event_name == 'pull_request' }}
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: docker/node-outside-docker.Dockerfile
|
file: docker/node-outside-docker.Dockerfile
|
||||||
@@ -138,7 +173,9 @@ jobs:
|
|||||||
|
|
||||||
- name: Publish dist as docker image (docker hub)
|
- name: Publish dist as docker image (docker hub)
|
||||||
uses: docker/build-push-action@v3
|
uses: docker/build-push-action@v3
|
||||||
if: ${{ matrix.app == 'trading' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
|
continue-on-error: true
|
||||||
|
id: dockerhub-push
|
||||||
|
if: ${{ matrix.app == 'trading' && github.event_name == 'push' && ( endsWith(github.ref, 'main') || endsWith(github.ref, 'release/testnet') ) }}
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: docker/node-outside-docker.Dockerfile
|
file: docker/node-outside-docker.Dockerfile
|
||||||
@@ -147,13 +184,41 @@ jobs:
|
|||||||
APP=${{ matrix.app }}
|
APP=${{ matrix.app }}
|
||||||
ENV_NAME=${{ env.ENV_NAME }}
|
ENV_NAME=${{ env.ENV_NAME }}
|
||||||
tags: |
|
tags: |
|
||||||
vegaprotocol/${{ matrix.app }}:${{ github.ref_name }}
|
vegaprotocol/${{ matrix.app }}:${{ github.sha }}
|
||||||
vegaprotocol/${{ matrix.app }}:mainnet
|
vegaprotocol/${{ matrix.app }}:${{ endsWith(github.ref, 'main') && 'mainnet' || endsWith(github.ref, 'release/testnet') && 'testnet' || '' }}
|
||||||
|
|
||||||
|
- name: Publish dist as docker image (ghcr - retry)
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
if: ${{ steps.ghcr-push.outcome == 'failure' }}
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: docker/node-outside-docker.Dockerfile
|
||||||
|
push: true
|
||||||
|
build-args: |
|
||||||
|
APP=${{ matrix.app }}
|
||||||
|
ENV_NAME=${{ env.ENV_NAME }}
|
||||||
|
tags: |
|
||||||
|
ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:${{ github.event.pull_request.head.sha || github.sha }}
|
||||||
|
|
||||||
|
- name: Publish dist as docker image (docker hub - retry)
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
if: ${{ steps.dockerhub-push.outcome == 'failure' }}
|
||||||
|
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.sha }}
|
||||||
|
vegaprotocol/${{ matrix.app }}:${{ endsWith(github.ref, 'main') && 'mainnet' || endsWith(github.ref, 'release/testnet') && 'testnet' || '' }}
|
||||||
|
|
||||||
# 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' && !startsWith(github.ref, 'refs/tags/v') }}
|
# s3 releases are not happening for trading on mainnet - it's IPFS
|
||||||
|
if: ${{ github.event_name == 'push' && ( matrix.app != 'trading' || (matrix.app == 'trading' && !( endsWith(github.ref, 'main') || endsWith(github.ref, 'release/testnet') ) ) ) }}
|
||||||
with:
|
with:
|
||||||
args: --acl private --follow-symlinks --delete
|
args: --acl private --follow-symlinks --delete
|
||||||
env:
|
env:
|
||||||
@@ -171,23 +236,51 @@ jobs:
|
|||||||
number: ${{ github.event.number }}
|
number: ${{ github.event.number }}
|
||||||
|
|
||||||
- name: Trigger fleek deployment
|
- name: Trigger fleek deployment
|
||||||
if: ${{ matrix.app == 'trading' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
|
# release to ipfs happens only on mainnet (represented by main branch) for trading
|
||||||
|
if: ${{ matrix.app == 'trading' && github.event_name == 'push' && ( endsWith(github.ref, 'main') || endsWith(github.ref, 'release/testnet') ) }}
|
||||||
run: |
|
run: |
|
||||||
# display info about app
|
if echo ${{ github.ref }} | grep -q main; then
|
||||||
curl -H "Authorization: ${{ secrets.FLEEK_API_KEY }}" \
|
# display info about app
|
||||||
-H "Content-Type: application/json" \
|
curl --fail -H "Authorization: ${{ secrets.FLEEK_API_KEY }}" \
|
||||||
-d '{"query": "query{getSiteById(siteId:\"f8f2e051-f18e-49e6-b876-0a39369dc0d8\"){id latestDeploy{id status}}}"}' \
|
-H "Content-Type: application/json" \
|
||||||
https://api.fleek.co/graphql
|
-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
|
# trigger new deployment as base image is always set to vegaprotocol/trading:mainnet
|
||||||
curl -H "Authorization: ${{ secrets.FLEEK_API_KEY }}" \
|
curl --fail -H "Authorization: ${{ secrets.FLEEK_API_KEY }}" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{"query": "mutation{triggerDeploy(siteId:\"f8f2e051-f18e-49e6-b876-0a39369dc0d8\"){id status}}"}' \
|
-d '{"query": "mutation{triggerDeploy(siteId:\"f8f2e051-f18e-49e6-b876-0a39369dc0d8\"){id status}}"}' \
|
||||||
https://api.fleek.co/graphql
|
https://api.fleek.co/graphql
|
||||||
|
|
||||||
- name: Update vega.trading DNS to redirect to the new console
|
elif echo ${{ github.ref }} | grep -q release/testnet; then
|
||||||
if: ${{ matrix.app == 'trading' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
|
# display info about app
|
||||||
|
curl --fail -H "Authorization: ${{ secrets.FLEEK_API_KEY }}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"query": "query{getSiteById(siteId:\"79baaeca-1952-4ae7-a256-f668cfc1d68e\"){id latestDeploy{id status}}}"}' \
|
||||||
|
https://api.fleek.co/graphql
|
||||||
|
|
||||||
|
# trigger new deployment as base image is always set to vegaprotocol/trading:mainnet
|
||||||
|
curl --fail -H "Authorization: ${{ secrets.FLEEK_API_KEY }}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"query": "mutation{triggerDeploy(siteId:\"79baaeca-1952-4ae7-a256-f668cfc1d68e\"){id status}}"}' \
|
||||||
|
https://api.fleek.co/graphql
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Check out ipfs-redirect
|
||||||
|
if: ${{ matrix.app == 'trading' && github.event_name == 'push' && ( endsWith(github.ref, 'main') || endsWith(github.ref, 'testnet') ) }}
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
repository: 'vegaprotocol/ipfs-redirect'
|
||||||
|
path: 'ipfs-redirect'
|
||||||
|
fetch-depth: '0'
|
||||||
|
token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Update interstitial page to point to the new console
|
||||||
|
if: ${{ matrix.app == 'trading' && github.event_name == 'push' && ( endsWith(github.ref, 'main') || endsWith(github.ref, 'testnet') ) }}
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
|
# set CID
|
||||||
curl -L https://dist.ipfs.tech/kubo/v0.20.0/kubo_v0.20.0_linux-amd64.tar.gz -o kubo.tgz
|
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
|
tar -xzf kubo.tgz
|
||||||
export PATH="$PATH:$PWD/kubo"
|
export PATH="$PATH:$PWD/kubo"
|
||||||
@@ -195,26 +288,28 @@ jobs:
|
|||||||
new_hash=$(cat ${{ matrix.app }}-ipfs-hash)
|
new_hash=$(cat ${{ matrix.app }}-ipfs-hash)
|
||||||
new_cid=$(ipfs cid format -v 1 -b base32 $new_hash)
|
new_cid=$(ipfs cid format -v 1 -b base32 $new_hash)
|
||||||
|
|
||||||
# Generate console URL
|
(
|
||||||
new_console_url_type=ipfs
|
cd ipfs-redirect
|
||||||
# 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
|
# configure git
|
||||||
# docs: https://developer.dnsimple.com/v2/zones/records/#updateZoneRecord
|
git status
|
||||||
dnsimple_account_id=84895
|
cat .git/config
|
||||||
dnsimple_zone_name=vega.trading
|
git config --global user.email "vega-ci-bot@vega.xyz"
|
||||||
dnsimple_record_id=44409591
|
git config --global user.name "vega-ci-bot"
|
||||||
# see: https://dnsimple.com/a/84895/domains/vega.trading/records/44409591/edit
|
|
||||||
|
|
||||||
curl -H 'Authorization: Bearer ${{ secrets.DNSIMPLE_API_TOKEN }}' \
|
# update CID files
|
||||||
-H 'Accept: application/json' \
|
if echo ${{ github.ref }} | grep -q main; then
|
||||||
-H 'Content-Type: application/json' \
|
echo $new_hash > cidv0-mainnet.txt
|
||||||
-X PATCH \
|
echo $new_cid > cidv1-mainnet.txt
|
||||||
-d "{
|
git add cidv0-mainnet.txt cidv1-mainnet.txt
|
||||||
\"content\": \"${new_console_url}\"
|
elif echo ${{ github.ref }} | grep -q release/testnet; then
|
||||||
}" \
|
echo $new_hash > cidv0-fairground.txt
|
||||||
https://api.dnsimple.com/v2/${dnsimple_account_id}/zones/${dnsimple_zone_name}/records/${dnsimple_record_id}
|
echo $new_cid > cidv1-fairground.txt
|
||||||
|
git add cidv0-fairground.txt cidv1-fairground.txt
|
||||||
|
fi
|
||||||
|
|
||||||
|
# create commit
|
||||||
|
commit_msg="Automated hash update from ${{ github.ref }}"
|
||||||
|
git commit -m "$commit_msg"
|
||||||
|
git push -u origin "main"
|
||||||
|
)
|
||||||
|
|||||||
@@ -43,7 +43,17 @@ jobs:
|
|||||||
-d '{"query": "mutation{triggerDeploy(siteId:\"f8f2e051-f18e-49e6-b876-0a39369dc0d8\"){id status}}"}' \
|
-d '{"query": "mutation{triggerDeploy(siteId:\"f8f2e051-f18e-49e6-b876-0a39369dc0d8\"){id status}}"}' \
|
||||||
https://api.fleek.co/graphql
|
https://api.fleek.co/graphql
|
||||||
|
|
||||||
- name: Update vega.trading DNS to redirect to the new console
|
- name: Check out ipfs-redirect
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
repository: 'vegaprotocol/ipfs-redirect'
|
||||||
|
path: 'ipfs-redirect'
|
||||||
|
fetch-depth: '0'
|
||||||
|
token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Update console.vega.xyz DNS to redirect to the new console
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
curl -L https://dist.ipfs.tech/kubo/v0.20.0/kubo_v0.20.0_linux-amd64.tar.gz -o kubo.tgz
|
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
|
tar -xzf kubo.tgz
|
||||||
@@ -51,27 +61,24 @@ jobs:
|
|||||||
which ipfs
|
which ipfs
|
||||||
new_hash=$(cat ipfs-hash)
|
new_hash=$(cat ipfs-hash)
|
||||||
new_cid=$(ipfs cid format -v 1 -b base32 $new_hash)
|
new_cid=$(ipfs cid format -v 1 -b base32 $new_hash)
|
||||||
|
git config --global user.email "vega-ci-bot@vega.xyz"
|
||||||
|
git config --global user.name "vega-ci-bot"
|
||||||
|
echo $new_hash > ipfs-redirect/cidv0.txt
|
||||||
|
echo $new_cid > ipfs-redirect/cidv1.txt
|
||||||
|
|
||||||
# Generate console URL
|
(
|
||||||
new_console_url_type=ipfs
|
cd ipfs-redirect
|
||||||
# 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
|
git status
|
||||||
# docs: https://developer.dnsimple.com/v2/zones/records/#updateZoneRecord
|
branch_name="rollback-to-$new_hash"
|
||||||
dnsimple_account_id=84895
|
git checkout -b "$branch_name"
|
||||||
dnsimple_zone_name=vega.trading
|
commit_msg="hash rollback to $new_hash"
|
||||||
dnsimple_record_id=44409591
|
git add cidv0.txt cidv1.txt
|
||||||
# see: https://dnsimple.com/a/84895/domains/vega.trading/records/44409591/edit
|
git commit -m "$commit_msg"
|
||||||
|
git push -u origin "$branch_name" --force-with-lease
|
||||||
curl -H 'Authorization: Bearer ${{ secrets.DNSIMPLE_API_TOKEN }}' \
|
pr_url="$(gh pr create --title "${commit_msg}" --body 'automated pull request to update CIDs')"
|
||||||
-H 'Accept: application/json' \
|
echo $pr_url
|
||||||
-H 'Content-Type: application/json' \
|
# once auto merge get's enabled on documentation repo let's do follow up
|
||||||
-X PATCH \
|
sleep 5
|
||||||
-d "{
|
gh pr merge "${pr_url}" --delete-branch --squash --admin
|
||||||
\"content\": \"${new_console_url}\"
|
)
|
||||||
}" \
|
|
||||||
https://api.dnsimple.com/v2/${dnsimple_account_id}/zones/${dnsimple_zone_name}/records/${dnsimple_record_id}
|
|
||||||
|
|||||||
@@ -50,3 +50,5 @@ cypress.env.json
|
|||||||
|
|
||||||
#cypress
|
#cypress
|
||||||
/apps/**/cypress/reports/
|
/apps/**/cypress/reports/
|
||||||
|
/apps/**/cypress/downloads/
|
||||||
|
/apps/**/fixtures/wallet/node**
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
|
|
||||||
NX_TENDERMINT_URL=http://localhost:26617
|
NX_TENDERMINT_URL=http://localhost:26617
|
||||||
NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
|
NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
|
||||||
NX_VEGA_URL=http://localhost:3008/graphql
|
NX_VEGA_URL=http://localhost:3008/graphql
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
# App configuration variables
|
# App configuration variables
|
||||||
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
|
|
||||||
NX_TENDERMINT_URL=https://n04.d.vega.xyz/tm
|
NX_TENDERMINT_URL=https://n04.d.vega.xyz/tm
|
||||||
NX_TENDERMINT_WEBSOCKET_URL=wss://n04.d.vega.xyz/tm/websocket
|
NX_TENDERMINT_WEBSOCKET_URL=wss://n04.d.vega.xyz/tm/websocket
|
||||||
NX_VEGA_URL=https://api.n04.d.vega.xyz/graphql
|
NX_VEGA_URL=https://api.n04.d.vega.xyz/graphql
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
# App configuration variables
|
# App configuration variables
|
||||||
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.community/graphql
|
NX_VEGA_URL=https://api.vega.community/graphql
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
# App configuration variables
|
# App configuration variables
|
||||||
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
|
|
||||||
NX_TENDERMINT_URL=https://tm.n07.testnet.vega.xyz/tm
|
NX_TENDERMINT_URL=https://tm.n07.testnet.vega.xyz/tm
|
||||||
NX_TENDERMINT_WEBSOCKET_URL=wss://lb.testnet.vega.xyz/tm/websocket
|
NX_TENDERMINT_WEBSOCKET_URL=wss://lb.testnet.vega.xyz/tm/websocket
|
||||||
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
|
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
|
||||||
|
|||||||
+6
-4
@@ -3,17 +3,19 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
|||||||
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
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://explorer.stagnet1.vega.rocks
|
||||||
NX_VEGA_TOKEN_URL=https://stagnet1.governance.vega.xyz
|
NX_VEGA_TOKEN_URL=https://governance.stagnet1.vega.rocks
|
||||||
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.governance.vega.xyz
|
NX_VEGA_GOVERNANCE_URL=https://governance.stagnet1.vega.rocks
|
||||||
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.json
|
||||||
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
|
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
|
||||||
|
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||||
|
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases/tag/
|
||||||
|
|
||||||
# App flags
|
# App flags
|
||||||
NX_EXPLORER_ASSETS=1
|
NX_EXPLORER_ASSETS=1
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
# App configuration variables
|
# App configuration variables
|
||||||
NX_TENDERMINT_URL=https://be.vega.community
|
NX_TENDERMINT_URL=https://be.vega.community
|
||||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/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_URL=https://api.vega.community/graphql
|
||||||
NX_VEGA_ENV=MAINNET
|
NX_VEGA_ENV=MAINNET
|
||||||
NX_BLOCK_EXPLORER=https://be.vega.community/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://governance.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/
|
||||||
|
NX_VEGA_CONSOLE_URL=https://console.vega.xyz
|
||||||
|
|||||||
@@ -1,2 +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"}'
|
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz","STAGNET1":"https://stagnet1.explorer.vega.xyz"}'
|
||||||
|
|||||||
@@ -10,3 +10,4 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
|||||||
NX_VEGA_GOVERNANCE_URL=https://governance.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
|
||||||
|
NX_VEGA_CONSOLE_URL=https://console.fairground.wtf
|
||||||
|
|||||||
@@ -7,8 +7,9 @@ NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9
|
|||||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
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_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_GOVERNANCE_URL=https://governance.validators-testnet.vega.rocks
|
||||||
|
NX_VEGA_EXPLORER_URL=https://explorer.validators-testnet.vega.rocks/
|
||||||
|
NX_VEGA_CONSOLE_URL=https://trading.validators-testnet.vega.rocks/
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
"executor": "@nrwl/workspace:run-commands",
|
"executor": "@nrwl/workspace:run-commands",
|
||||||
"options": {
|
"options": {
|
||||||
"commands": [
|
"commands": [
|
||||||
"npx openapi-typescript https://raw.githubusercontent.com/vegaprotocol/documentation/main/specs/v0.67.3/blockexplorer.openapi.json --output apps/explorer/src/types/explorer.d.ts --immutable-types"
|
"npx openapi-typescript https://raw.githubusercontent.com/vegaprotocol/documentation/main/specs/v0.71.4/blockexplorer.openapi.json --output apps/explorer/src/types/explorer.d.ts --immutable-types"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ 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';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
|
import { Suspense } from 'react';
|
||||||
|
|
||||||
const splashLoading = (
|
const splashLoading = (
|
||||||
<Splash>
|
<Splash>
|
||||||
@@ -32,7 +33,9 @@ function App() {
|
|||||||
skeleton={<div>{t('Loading')}</div>}
|
skeleton={<div>{t('Loading')}</div>}
|
||||||
failure={<AppFailure title={t(`Node: ${VEGA_URL} is unsuitable`)} />}
|
failure={<AppFailure title={t(`Node: ${VEGA_URL} is unsuitable`)} />}
|
||||||
>
|
>
|
||||||
<RouterProvider router={router} fallbackElement={splashLoading} />
|
<Suspense fallback={splashLoading}>
|
||||||
|
<RouterProvider router={router} fallbackElement={splashLoading} />
|
||||||
|
</Suspense>
|
||||||
</NodeGuard>
|
</NodeGuard>
|
||||||
<NodeSwitcherDialog
|
<NodeSwitcherDialog
|
||||||
open={nodeSwitcherOpen}
|
open={nodeSwitcherOpen}
|
||||||
|
|||||||
@@ -1,29 +1,13 @@
|
|||||||
import WS from 'jest-websocket-mock';
|
import WS from 'jest-websocket-mock';
|
||||||
import useWebSocket from 'react-use-websocket';
|
import { render, screen } from '@testing-library/react';
|
||||||
import {
|
|
||||||
render,
|
|
||||||
screen,
|
|
||||||
fireEvent,
|
|
||||||
act,
|
|
||||||
waitFor,
|
|
||||||
} from '@testing-library/react';
|
|
||||||
import { TendermintWebsocketContext } from '../../contexts/websocket/tendermint-websocket-context';
|
|
||||||
import { BlocksRefetch } from './blocks-refetch';
|
import { BlocksRefetch } from './blocks-refetch';
|
||||||
|
|
||||||
const BlocksRefetchInWebsocketProvider = ({
|
const BlocksRefetchInWebsocketProvider = ({
|
||||||
callback,
|
callback,
|
||||||
mocketLocation,
|
|
||||||
}: {
|
}: {
|
||||||
callback: () => null;
|
callback: () => null;
|
||||||
mocketLocation: string;
|
|
||||||
}) => {
|
}) => {
|
||||||
const contextShape = useWebSocket(mocketLocation);
|
return <BlocksRefetch refetch={callback} />;
|
||||||
|
|
||||||
return (
|
|
||||||
<TendermintWebsocketContext.Provider value={{ ...contextShape }}>
|
|
||||||
<BlocksRefetch refetch={callback} />
|
|
||||||
</TendermintWebsocketContext.Provider>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('Blocks refetch', () => {
|
describe('Blocks refetch', () => {
|
||||||
@@ -32,111 +16,8 @@ describe('Blocks refetch', () => {
|
|||||||
const mocket = new WS(mocketLocation, { jsonProtocol: true });
|
const mocket = new WS(mocketLocation, { jsonProtocol: true });
|
||||||
new WebSocket(mocketLocation);
|
new WebSocket(mocketLocation);
|
||||||
|
|
||||||
render(
|
render(<BlocksRefetchInWebsocketProvider callback={() => null} />);
|
||||||
<BlocksRefetchInWebsocketProvider
|
|
||||||
callback={() => null}
|
|
||||||
mocketLocation={mocketLocation}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
await mocket.connected;
|
|
||||||
expect(screen.getByTestId('new-blocks')).toHaveTextContent('new blocks');
|
|
||||||
expect(screen.getByTestId('refresh')).toBeInTheDocument();
|
expect(screen.getByTestId('refresh')).toBeInTheDocument();
|
||||||
mocket.close();
|
mocket.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should initiate callback when the button is clicked', async () => {
|
|
||||||
const mocketLocation = 'wss:localhost:3003';
|
|
||||||
const mocket = new WS(mocketLocation, { jsonProtocol: true });
|
|
||||||
new WebSocket(mocketLocation);
|
|
||||||
|
|
||||||
const callback = jest.fn();
|
|
||||||
render(
|
|
||||||
<BlocksRefetchInWebsocketProvider
|
|
||||||
callback={callback}
|
|
||||||
mocketLocation={mocketLocation}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
await mocket.connected;
|
|
||||||
const button = screen.getByTestId('refresh');
|
|
||||||
|
|
||||||
act(() => {
|
|
||||||
fireEvent.click(button);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(callback.mock.calls.length).toEqual(1);
|
|
||||||
mocket.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should show new blocks as websocket is correctly updated', async () => {
|
|
||||||
const mocketLocation = 'wss:localhost:3004';
|
|
||||||
const mocket = new WS(mocketLocation, { jsonProtocol: true });
|
|
||||||
new WebSocket(mocketLocation);
|
|
||||||
render(
|
|
||||||
<BlocksRefetchInWebsocketProvider
|
|
||||||
callback={() => null}
|
|
||||||
mocketLocation={mocketLocation}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
await mocket.connected;
|
|
||||||
|
|
||||||
// Ensuring we send an ID equal to the one the client subscribed with.
|
|
||||||
await waitFor(() => expect(mocket.messages.length).toEqual(1));
|
|
||||||
// @ts-ignore id on messages
|
|
||||||
const id = mocket.messages[0].id;
|
|
||||||
|
|
||||||
const newBlockMessage = {
|
|
||||||
id,
|
|
||||||
result: {
|
|
||||||
query: "tm.event = 'NewBlock'",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(screen.getByTestId('new-blocks')).toHaveTextContent('0 new blocks');
|
|
||||||
|
|
||||||
act(() => {
|
|
||||||
mocket.send(newBlockMessage);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(screen.getByTestId('new-blocks')).toHaveTextContent('1 new blocks');
|
|
||||||
|
|
||||||
act(() => {
|
|
||||||
mocket.send(newBlockMessage);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(screen.getByTestId('new-blocks')).toHaveTextContent('2 new blocks');
|
|
||||||
mocket.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('will not show new blocks if websocket has wrong ID', async () => {
|
|
||||||
const mocketLocation = 'wss:localhost:3005';
|
|
||||||
const mocket = new WS(mocketLocation, { jsonProtocol: true });
|
|
||||||
new WebSocket(mocketLocation);
|
|
||||||
|
|
||||||
render(
|
|
||||||
<BlocksRefetchInWebsocketProvider
|
|
||||||
callback={() => null}
|
|
||||||
mocketLocation={mocketLocation}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
await mocket.connected;
|
|
||||||
|
|
||||||
// Ensuring we send an ID equal to the one the client subscribed with.
|
|
||||||
await waitFor(() => expect(mocket.messages.length).toEqual(1));
|
|
||||||
|
|
||||||
const newBlockMessageBadId = {
|
|
||||||
id: 'blahblahblah',
|
|
||||||
result: {
|
|
||||||
query: "tm.event = 'NewBlock'",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(screen.getByTestId('new-blocks')).toHaveTextContent('0 new blocks');
|
|
||||||
|
|
||||||
act(() => {
|
|
||||||
mocket.send(newBlockMessageBadId);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(screen.getByTestId('new-blocks')).toHaveTextContent('0 new blocks');
|
|
||||||
mocket.close();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,36 +1,19 @@
|
|||||||
import { useState, useEffect } from 'react';
|
|
||||||
import { useTendermintWebsocket } from '../../hooks/use-tendermint-websocket';
|
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
|
import { Button, Icon } from '@vegaprotocol/ui-toolkit';
|
||||||
|
|
||||||
interface BlocksRefetchProps {
|
interface BlocksRefetchProps {
|
||||||
refetch: () => void;
|
refetch: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const BlocksRefetch = ({ refetch }: BlocksRefetchProps) => {
|
export const BlocksRefetch = ({ refetch }: BlocksRefetchProps) => {
|
||||||
const [blocksToLoad, setBlocksToLoad] = useState<number>(0);
|
|
||||||
|
|
||||||
const { messages } = useTendermintWebsocket({
|
|
||||||
query: "tm.event = 'NewBlock'",
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (messages.length > 0) {
|
|
||||||
setBlocksToLoad((prev) => prev + 1);
|
|
||||||
}
|
|
||||||
}, [messages]);
|
|
||||||
|
|
||||||
const refresh = () => {
|
const refresh = () => {
|
||||||
refetch();
|
refetch();
|
||||||
setBlocksToLoad(0);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mb-4">
|
<Button onClick={refresh} data-testid="refresh" size="xs">
|
||||||
<span data-testid="new-blocks">{blocksToLoad} new blocks - </span>
|
<Icon name="refresh" className="!align-baseline mr-2" size={3} />
|
||||||
<ButtonLink onClick={refresh} data-testid="refresh">
|
{t('Load new')}
|
||||||
{t('refresh to see latest')}
|
</Button>
|
||||||
</ButtonLink>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ import {
|
|||||||
} from '@vegaprotocol/environment';
|
} 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 { Link, ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { ENV } from '../../config/env';
|
import { ENV } from '../../config/env';
|
||||||
|
import { Routes } from '../../routes/route-names';
|
||||||
|
import { Link as RouteLink } from 'react-router-dom';
|
||||||
|
|
||||||
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();
|
||||||
@@ -21,7 +23,7 @@ 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 lg:grid-cols-[1fr_auto] text-xs md:text-md lg: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">
|
||||||
@@ -48,23 +50,26 @@ export const Footer = () => {
|
|||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex pl-2 content-center">
|
{ENV.addresses.feedback ? (
|
||||||
<ExternalLink href={ENV.addresses.feedback}>
|
<div className="flex pl-2 content-center">
|
||||||
{showFullFeedbackLabel ? t('Share your feedback') : t('Feedback')}
|
<ExternalLink href={ENV.addresses.feedback}>
|
||||||
</ExternalLink>
|
{showFullFeedbackLabel ? t('Share your feedback') : t('Feedback')}
|
||||||
</div>
|
</ExternalLink>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
<div className="pl-2 align-center lg:align-right lg:flex lg:justify-end gap-2 align-middle lg:max-w-xs lg:ml-auto">
|
||||||
|
<RouteLink to={`/${Routes.DISCLAIMER}`} className="underline">
|
||||||
|
Disclaimer
|
||||||
|
</RouteLink>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const NodeUrl = ({ url }: { url: string }) => {
|
export 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>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import type { MarketInfoWithData } from '@vegaprotocol/markets';
|
import type { MarketInfoWithData } from '@vegaprotocol/markets';
|
||||||
|
import { PriceMonitoringBoundsInfoPanel } from '@vegaprotocol/markets';
|
||||||
import {
|
import {
|
||||||
LiquidityInfoPanel,
|
LiquidityInfoPanel,
|
||||||
LiquidityMonitoringParametersInfoPanel,
|
LiquidityMonitoringParametersInfoPanel,
|
||||||
@@ -20,12 +21,10 @@ 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') {
|
||||||
@@ -41,133 +40,69 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
|
|||||||
return [];
|
return [];
|
||||||
};
|
};
|
||||||
|
|
||||||
const oraclePanels = isEqual(
|
const showTwoOracles = isEqual(
|
||||||
getSigners(settlementData),
|
getSigners(settlementData),
|
||||||
getSigners(terminationData)
|
getSigners(terminationData)
|
||||||
)
|
);
|
||||||
? [
|
|
||||||
{
|
|
||||||
title: t('Settlement Oracle'),
|
|
||||||
content: (
|
|
||||||
<OracleInfoPanel
|
|
||||||
noBorder={false}
|
|
||||||
market={market}
|
|
||||||
type="settlementData"
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('Termination Oracle'),
|
|
||||||
content: (
|
|
||||||
<OracleInfoPanel
|
|
||||||
noBorder={false}
|
|
||||||
market={market}
|
|
||||||
type="termination"
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
]
|
|
||||||
: [
|
|
||||||
{
|
|
||||||
title: t('Oracle'),
|
|
||||||
content: (
|
|
||||||
<OracleInfoPanel
|
|
||||||
noBorder={false}
|
|
||||||
market={market}
|
|
||||||
type="settlementData"
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const panels = [
|
const headerClassName = 'font-alpha calt text-xl mt-4 border-b-2 pb-2';
|
||||||
{
|
|
||||||
title: t('Key details'),
|
|
||||||
content: <KeyDetailsInfoPanel noBorder={false} market={market} />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('Instrument'),
|
|
||||||
content: <InstrumentInfoPanel noBorder={false} market={market} />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('Settlement asset'),
|
|
||||||
content: <SettlementAssetInfoPanel market={market} noBorder={false} />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('Metadata'),
|
|
||||||
content: <MetadataInfoPanel noBorder={false} market={market} />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('Risk model'),
|
|
||||||
content: <RiskModelInfoPanel noBorder={false} market={market} />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('Risk parameters'),
|
|
||||||
content: <RiskParametersInfoPanel noBorder={false} market={market} />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('Risk factors'),
|
|
||||||
content: <RiskFactorsInfoPanel noBorder={false} market={market} />,
|
|
||||||
},
|
|
||||||
...(market.priceMonitoringSettings?.parameters?.triggers || []).map(
|
|
||||||
(trigger, i) => ({
|
|
||||||
title: t(`Price monitoring trigger ${i + 1}`),
|
|
||||||
content: <MarketInfoTable noBorder={false} data={trigger} />,
|
|
||||||
})
|
|
||||||
),
|
|
||||||
...(market.data?.priceMonitoringBounds || []).map((trigger, i) => ({
|
|
||||||
title: t(`Price monitoring bound ${i + 1}`),
|
|
||||||
content: (
|
|
||||||
<>
|
|
||||||
<MarketInfoTable
|
|
||||||
noBorder={false}
|
|
||||||
data={{
|
|
||||||
maxValidPrice: trigger.maxValidPrice,
|
|
||||||
minValidPrice: trigger.minValidPrice,
|
|
||||||
}}
|
|
||||||
decimalPlaces={market.decimalPlaces}
|
|
||||||
/>
|
|
||||||
<MarketInfoTable
|
|
||||||
noBorder={false}
|
|
||||||
data={{ referencePrice: trigger.referencePrice }}
|
|
||||||
decimalPlaces={
|
|
||||||
market.tradableInstrument.instrument.product.settlementAsset
|
|
||||||
.decimals
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
})),
|
|
||||||
{
|
|
||||||
title: t('Liquidity monitoring parameters'),
|
|
||||||
content: (
|
|
||||||
<LiquidityMonitoringParametersInfoPanel
|
|
||||||
noBorder={false}
|
|
||||||
market={market}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('Liquidity'),
|
|
||||||
content: <LiquidityInfoPanel market={market} noBorder={false} />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t('Liquidity price range'),
|
|
||||||
content: (
|
|
||||||
<LiquidityPriceRangeInfoPanel market={market} noBorder={false} />
|
|
||||||
),
|
|
||||||
},
|
|
||||||
...oraclePanels,
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div>
|
||||||
{panels.map((p) => (
|
<h2 className={headerClassName}>{t('Key details')}</h2>
|
||||||
<div key={p.title} className="mb-3">
|
<KeyDetailsInfoPanel market={market} />
|
||||||
<h2 className="font-alpha calt text-xl">{p.title}</h2>
|
<h2 className={headerClassName}>{t('Instrument')}</h2>
|
||||||
{p.content}
|
<InstrumentInfoPanel market={market} />
|
||||||
</div>
|
<h2 className={headerClassName}>{t('Settlement asset')}</h2>
|
||||||
|
<SettlementAssetInfoPanel market={market} />
|
||||||
|
<h2 className={headerClassName}>{t('Metadata')}</h2>
|
||||||
|
<MetadataInfoPanel market={market} />
|
||||||
|
<h2 className={headerClassName}>{t('Risk model')}</h2>
|
||||||
|
<RiskModelInfoPanel market={market} />
|
||||||
|
<h2 className={headerClassName}>{t('Risk parameters')}</h2>
|
||||||
|
<RiskParametersInfoPanel market={market} />
|
||||||
|
<h2 className={headerClassName}>{t('Risk factors')}</h2>
|
||||||
|
<RiskFactorsInfoPanel market={market} />
|
||||||
|
{(market.data?.priceMonitoringBounds || []).map((trigger, i) => (
|
||||||
|
<>
|
||||||
|
<h2 className={headerClassName}>
|
||||||
|
{t('Price monitoring bounds %s', [(i + 1).toString()])}
|
||||||
|
</h2>
|
||||||
|
<PriceMonitoringBoundsInfoPanel
|
||||||
|
market={market}
|
||||||
|
triggerIndex={i + 1}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
))}
|
))}
|
||||||
</>
|
{(market.priceMonitoringSettings?.parameters?.triggers || []).map(
|
||||||
|
(trigger, i) => (
|
||||||
|
<>
|
||||||
|
<h2 className={headerClassName}>
|
||||||
|
{t('Price monitoring settings %s', [(i + 1).toString()])}
|
||||||
|
</h2>
|
||||||
|
<MarketInfoTable data={trigger} key={i} />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
<h2 className={headerClassName}>{t('Liquidity monitoring')}</h2>
|
||||||
|
<LiquidityMonitoringParametersInfoPanel market={market} />
|
||||||
|
<h2 className={headerClassName}>{t('Liquidity')}</h2>
|
||||||
|
<LiquidityInfoPanel market={market} />
|
||||||
|
<h2 className={headerClassName}>{t('Liquidity price range')}</h2>
|
||||||
|
<LiquidityPriceRangeInfoPanel market={market} />
|
||||||
|
{showTwoOracles ? (
|
||||||
|
<>
|
||||||
|
<h2 className={headerClassName}>{t('Settlement oracle')}</h2>
|
||||||
|
<OracleInfoPanel market={market} type="settlementData" />
|
||||||
|
<h2 className={headerClassName}>{t('Termination oracle')}</h2>
|
||||||
|
<OracleInfoPanel market={market} type="termination" />
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<h2 className={headerClassName}>{t('Oracle')}</h2>
|
||||||
|
<OracleInfoPanel market={market} type="settlementData" />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -77,22 +77,24 @@ export const MarketsTable = ({ data }: MarketsTableProps) => {
|
|||||||
hide={window.innerWidth <= BREAKPOINT_MD}
|
hide={window.innerWidth <= BREAKPOINT_MD}
|
||||||
valueGetter={({
|
valueGetter={({
|
||||||
data,
|
data,
|
||||||
}: VegaValueGetterParams<MarketFieldsFragment, 'state'>) => {
|
}: VegaValueGetterParams<MarketFieldsFragment>) => {
|
||||||
return data?.state ? MarketStateMapping[data?.state] : '-';
|
return data?.state ? MarketStateMapping[data?.state] : '-';
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<AgGridColumn
|
<AgGridColumn
|
||||||
colId="asset"
|
colId="asset"
|
||||||
headerName={t('Settlement asset')}
|
headerName={t('Settlement asset')}
|
||||||
field="tradableInstrument.instrument.product.settlementAsset"
|
field="tradableInstrument.instrument.product.settlementAsset.symbol"
|
||||||
hide={window.innerWidth <= BREAKPOINT_MD}
|
hide={window.innerWidth <= BREAKPOINT_MD}
|
||||||
cellRenderer={({
|
cellRenderer={({
|
||||||
value,
|
data,
|
||||||
}: VegaICellRendererParams<
|
}: VegaICellRendererParams<
|
||||||
MarketFieldsFragment,
|
MarketFieldsFragment,
|
||||||
'tradableInstrument.instrument.product.settlementAsset'
|
'tradableInstrument.instrument.product.settlementAsset.symbol'
|
||||||
>) =>
|
>) => {
|
||||||
value ? (
|
const value =
|
||||||
|
data?.tradableInstrument.instrument.product.settlementAsset;
|
||||||
|
return value ? (
|
||||||
<ButtonLink
|
<ButtonLink
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
openAssetDetailsDialog(value.id, e.target as HTMLElement);
|
openAssetDetailsDialog(value.id, e.target as HTMLElement);
|
||||||
@@ -102,8 +104,8 @@ export const MarketsTable = ({ data }: MarketsTableProps) => {
|
|||||||
</ButtonLink>
|
</ButtonLink>
|
||||||
) : (
|
) : (
|
||||||
''
|
''
|
||||||
)
|
);
|
||||||
}
|
}}
|
||||||
/>
|
/>
|
||||||
<AgGridColumn
|
<AgGridColumn
|
||||||
flex={2}
|
flex={2}
|
||||||
|
|||||||
+6
-4
@@ -5,12 +5,13 @@ export const ErrorCodes = new Map([
|
|||||||
[51, 'Transaction failed validation'],
|
[51, 'Transaction failed validation'],
|
||||||
[60, 'Transaction could not be decoded'],
|
[60, 'Transaction could not be decoded'],
|
||||||
[70, 'Error'],
|
[70, 'Error'],
|
||||||
|
[71, 'Partial success/error'],
|
||||||
[80, 'Unknown command'],
|
[80, 'Unknown command'],
|
||||||
[89, 'Rejected as spam'],
|
[89, 'Rejected as spam'],
|
||||||
[0, 'Success'],
|
[0, 'Success'],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const successCodes = new Set([0]);
|
export const successCodes = new Set([0, 71]);
|
||||||
|
|
||||||
interface ChainResponseCodeProps {
|
interface ChainResponseCodeProps {
|
||||||
code: number;
|
code: number;
|
||||||
@@ -29,11 +30,12 @@ export const ChainResponseCode = ({
|
|||||||
error,
|
error,
|
||||||
}: ChainResponseCodeProps) => {
|
}: ChainResponseCodeProps) => {
|
||||||
const isSuccess = successCodes.has(code);
|
const isSuccess = successCodes.has(code);
|
||||||
|
const successColour =
|
||||||
|
code === 71 ? 'fill-vega-orange' : 'fill-vega-green-600';
|
||||||
const icon = isSuccess ? (
|
const icon = isSuccess ? (
|
||||||
<Icon name="tick-circle" className="fill-vega-green-550" />
|
<Icon name="tick-circle" className={successColour} />
|
||||||
) : (
|
) : (
|
||||||
<Icon name="cross" className="fill-vega-pink-550" />
|
<Icon name="cross" className="fill-vega-pink-600" />
|
||||||
);
|
);
|
||||||
const label = ErrorCodes.get(code) || 'Unknown response code';
|
const label = ErrorCodes.get(code) || 'Unknown response code';
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import { t } from '@vegaprotocol/i18n';
|
||||||
|
|
||||||
|
export interface FilterLabelProps {
|
||||||
|
filters: Set<string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the list (currently limited to 1) of filters set by the
|
||||||
|
* Transaction Filter
|
||||||
|
*/
|
||||||
|
export function FilterLabel({ filters }: FilterLabelProps) {
|
||||||
|
if (!filters || filters.size !== 1) {
|
||||||
|
return <span className="uppercase">{t('Filter')}</span>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<span className="uppercase">{t('Filters')}:</span>
|
||||||
|
<code className="bg-vega-light-150 px-2 rounded-md capitalize">
|
||||||
|
{Array.from(filters)[0]}
|
||||||
|
</code>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,164 @@
|
|||||||
|
import { t } from '@vegaprotocol/i18n';
|
||||||
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuCheckboxItem,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuItemIndicator,
|
||||||
|
DropdownMenuSeparator,
|
||||||
|
DropdownMenuSub,
|
||||||
|
DropdownMenuSubTrigger,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
DropdownMenuSubContent,
|
||||||
|
Icon,
|
||||||
|
Button,
|
||||||
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
|
import type { Dispatch, SetStateAction } from 'react';
|
||||||
|
import { FilterLabel } from './tx-filter-label';
|
||||||
|
|
||||||
|
// All possible transaction types. Should be generated.
|
||||||
|
export type FilterOption =
|
||||||
|
| 'Amend LiquidityProvision Order'
|
||||||
|
| 'Amend Order'
|
||||||
|
| 'Batch Market Instructions'
|
||||||
|
| 'Cancel LiquidityProvision Order'
|
||||||
|
| 'Cancel Order'
|
||||||
|
| 'Cancel Transfer Funds'
|
||||||
|
| 'Chain Event'
|
||||||
|
| 'Delegate'
|
||||||
|
| 'Ethereum Key Rotate Submission'
|
||||||
|
| 'Issue Signatures'
|
||||||
|
| 'Key Rotate Submission'
|
||||||
|
| 'Liquidity Provision Order'
|
||||||
|
| 'Node Signature'
|
||||||
|
| 'Node Vote'
|
||||||
|
| 'Proposal'
|
||||||
|
| 'Protocol Upgrade'
|
||||||
|
| 'Register new Node'
|
||||||
|
| 'State Variable Proposal'
|
||||||
|
| 'Submit Oracle Data'
|
||||||
|
| 'Submit Order'
|
||||||
|
| 'Transfer Funds'
|
||||||
|
| 'Undelegate'
|
||||||
|
| 'Validator Heartbeat'
|
||||||
|
| 'Vote on Proposal'
|
||||||
|
| 'Withdraw';
|
||||||
|
|
||||||
|
// Alphabetised list of transaction types to appear at the top level
|
||||||
|
export const PrimaryFilterOptions: FilterOption[] = [
|
||||||
|
'Amend LiquidityProvision Order',
|
||||||
|
'Amend Order',
|
||||||
|
'Batch Market Instructions',
|
||||||
|
'Cancel LiquidityProvision Order',
|
||||||
|
'Cancel Order',
|
||||||
|
'Cancel Transfer Funds',
|
||||||
|
'Delegate',
|
||||||
|
'Liquidity Provision Order',
|
||||||
|
'Proposal',
|
||||||
|
'Submit Oracle Data',
|
||||||
|
'Submit Order',
|
||||||
|
'Transfer Funds',
|
||||||
|
'Undelegate',
|
||||||
|
'Vote on Proposal',
|
||||||
|
'Withdraw',
|
||||||
|
];
|
||||||
|
|
||||||
|
// Alphabetised list of transaction types to nest under a 'More...' submenu
|
||||||
|
export const SecondaryFilterOptions: FilterOption[] = [
|
||||||
|
'Chain Event',
|
||||||
|
'Ethereum Key Rotate Submission',
|
||||||
|
'Issue Signatures',
|
||||||
|
'Key Rotate Submission',
|
||||||
|
'Node Signature',
|
||||||
|
'Node Vote',
|
||||||
|
'Protocol Upgrade',
|
||||||
|
'Register new Node',
|
||||||
|
'State Variable Proposal',
|
||||||
|
'Validator Heartbeat',
|
||||||
|
];
|
||||||
|
|
||||||
|
export const AllFilterOptions: FilterOption[] = [
|
||||||
|
...PrimaryFilterOptions,
|
||||||
|
...SecondaryFilterOptions,
|
||||||
|
];
|
||||||
|
|
||||||
|
export interface TxFilterProps {
|
||||||
|
filters: Set<FilterOption>;
|
||||||
|
setFilters: Dispatch<SetStateAction<Set<FilterOption>>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders a structured dropdown menu of all of the available transaction
|
||||||
|
* types. It allows a user to select one transaction type to view. Later
|
||||||
|
* it will support multiple selection, but until the API supports that it is
|
||||||
|
* one or all.
|
||||||
|
* @param filters null or Set of tranaction types
|
||||||
|
* @param setFilters A function to update the filters prop
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const TxsFilter = ({ filters, setFilters }: TxFilterProps) => {
|
||||||
|
return (
|
||||||
|
<DropdownMenu
|
||||||
|
modal={false}
|
||||||
|
trigger={
|
||||||
|
<DropdownMenuTrigger className="ml-2">
|
||||||
|
<Button size="xs">
|
||||||
|
<FilterLabel filters={filters} />
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<DropdownMenuContent>
|
||||||
|
{filters.size > 1 ? null : (
|
||||||
|
<>
|
||||||
|
<DropdownMenuCheckboxItem
|
||||||
|
onCheckedChange={() => setFilters(new Set(AllFilterOptions))}
|
||||||
|
>
|
||||||
|
{t('Clear filters')} <Icon name="cross" />
|
||||||
|
</DropdownMenuCheckboxItem>
|
||||||
|
<DropdownMenuSeparator />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{PrimaryFilterOptions.map((f) => (
|
||||||
|
<DropdownMenuCheckboxItem
|
||||||
|
key={f}
|
||||||
|
checked={filters.has(f)}
|
||||||
|
onCheckedChange={() => {
|
||||||
|
// NOTE: These act like radio buttons until the API supports multiple filters
|
||||||
|
setFilters(new Set([f]));
|
||||||
|
}}
|
||||||
|
id={`radio-${f}`}
|
||||||
|
>
|
||||||
|
{f}
|
||||||
|
<DropdownMenuItemIndicator>
|
||||||
|
<Icon name="tick-circle" />
|
||||||
|
</DropdownMenuItemIndicator>
|
||||||
|
</DropdownMenuCheckboxItem>
|
||||||
|
))}
|
||||||
|
<DropdownMenuSub>
|
||||||
|
<DropdownMenuSubTrigger>
|
||||||
|
{t('More Types')}
|
||||||
|
<Icon name="chevron-right" />
|
||||||
|
</DropdownMenuSubTrigger>
|
||||||
|
<DropdownMenuSubContent>
|
||||||
|
{SecondaryFilterOptions.map((f) => (
|
||||||
|
<DropdownMenuCheckboxItem
|
||||||
|
key={f}
|
||||||
|
checked={filters.has(f)}
|
||||||
|
onCheckedChange={(checked) => {
|
||||||
|
// NOTE: These act like radio buttons until the API supports multiple filters
|
||||||
|
setFilters(new Set([f]));
|
||||||
|
}}
|
||||||
|
id={`radio-${f}`}
|
||||||
|
>
|
||||||
|
{f}
|
||||||
|
<DropdownMenuItemIndicator>
|
||||||
|
<Icon name="tick-circle" className="inline" />
|
||||||
|
</DropdownMenuItemIndicator>
|
||||||
|
</DropdownMenuCheckboxItem>
|
||||||
|
))}
|
||||||
|
</DropdownMenuSubContent>
|
||||||
|
</DropdownMenuSub>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -160,6 +160,7 @@ export const TxOrderType = ({ orderType, command }: TxOrderTypeProps) => {
|
|||||||
vote={command?.voteSubmission?.value === 'VALUE_YES'}
|
vote={command?.voteSubmission?.value === 'VALUE_YES'}
|
||||||
yesText="Proposal vote"
|
yesText="Proposal vote"
|
||||||
noText="Proposal vote"
|
noText="Proposal vote"
|
||||||
|
useVoteColour={false}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React from 'react';
|
import React, { useEffect, useRef } from 'react';
|
||||||
import { FixedSizeList as List } from 'react-window';
|
import { FixedSizeList as List } from 'react-window';
|
||||||
import InfiniteLoader from 'react-window-infinite-loader';
|
import InfiniteLoader from 'react-window-infinite-loader';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
@@ -69,6 +69,17 @@ export const TxsInfiniteList = ({
|
|||||||
}: TxsInfiniteListProps) => {
|
}: TxsInfiniteListProps) => {
|
||||||
const { screenSize } = useScreenDimensions();
|
const { screenSize } = useScreenDimensions();
|
||||||
const isStacked = ['xs', 'sm'].includes(screenSize);
|
const isStacked = ['xs', 'sm'].includes(screenSize);
|
||||||
|
const infiniteLoaderRef = useRef<InfiniteLoader>(null);
|
||||||
|
const hasMountedRef = useRef(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (hasMountedRef.current) {
|
||||||
|
if (infiniteLoaderRef.current) {
|
||||||
|
infiniteLoaderRef.current.resetloadMoreItemsCache(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hasMountedRef.current = true;
|
||||||
|
}, [loadMoreTxs]);
|
||||||
|
|
||||||
if (!txs) {
|
if (!txs) {
|
||||||
if (!areTxsLoading) {
|
if (!areTxsLoading) {
|
||||||
@@ -110,6 +121,7 @@ export const TxsInfiniteList = ({
|
|||||||
isItemLoaded={isItemLoaded}
|
isItemLoaded={isItemLoaded}
|
||||||
itemCount={itemCount}
|
itemCount={itemCount}
|
||||||
loadMoreItems={loadMoreItems}
|
loadMoreItems={loadMoreItems}
|
||||||
|
ref={infiniteLoaderRef}
|
||||||
>
|
>
|
||||||
{({ onItemsRendered, ref }) => (
|
{({ onItemsRendered, ref }) => (
|
||||||
<List
|
<List
|
||||||
|
|||||||
@@ -34,4 +34,17 @@ describe('Vote TX icon', () => {
|
|||||||
const no = render(<VoteIcon vote={false} />);
|
const no = render(<VoteIcon vote={false} />);
|
||||||
expect(no.getByRole('img')).toHaveAttribute('aria-label', 'delete icon');
|
expect(no.getByRole('img')).toHaveAttribute('aria-label', 'delete icon');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('useVoteColour prop can be used to override coloured background', () => {
|
||||||
|
const no = render(<VoteIcon vote={false} />);
|
||||||
|
expect(no.container.children[0]).toHaveClass('bg-vega-pink-550');
|
||||||
|
|
||||||
|
const monochromeNo = render(
|
||||||
|
<VoteIcon vote={false} useVoteColour={false} />
|
||||||
|
);
|
||||||
|
expect(monochromeNo.container.children[0]).not.toHaveClass(
|
||||||
|
'bg-vega-pink-550'
|
||||||
|
);
|
||||||
|
expect(monochromeNo.container.children[0]).toHaveClass('bg-vega-dark-200');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,6 +8,32 @@ export interface VoteIconProps {
|
|||||||
yesText?: string;
|
yesText?: string;
|
||||||
// Defaults to 'Against', but can be any text
|
// Defaults to 'Against', but can be any text
|
||||||
noText?: string;
|
noText?: string;
|
||||||
|
// If set to false the background will not be coloured
|
||||||
|
useVoteColour?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBgColour(useVoteColour: boolean, vote: boolean) {
|
||||||
|
if (useVoteColour === false) {
|
||||||
|
return 'bg-vega-dark-200';
|
||||||
|
}
|
||||||
|
|
||||||
|
return vote ? 'bg-vega-green-550' : 'bg-vega-pink-550';
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFillColour(useVoteColour: boolean, vote: boolean) {
|
||||||
|
if (useVoteColour === false) {
|
||||||
|
return 'white';
|
||||||
|
}
|
||||||
|
|
||||||
|
return vote ? 'vega-green-300' : 'vega-pink-300';
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTextColour(useVoteColour: boolean, vote: boolean) {
|
||||||
|
if (useVoteColour === false) {
|
||||||
|
return 'white';
|
||||||
|
}
|
||||||
|
|
||||||
|
return vote ? 'vega-green-200' : 'vega-pink-200';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -18,14 +44,15 @@ export interface VoteIconProps {
|
|||||||
*/
|
*/
|
||||||
export function VoteIcon({
|
export function VoteIcon({
|
||||||
vote,
|
vote,
|
||||||
|
useVoteColour = true,
|
||||||
yesText = 'For',
|
yesText = 'For',
|
||||||
noText = 'Against',
|
noText = 'Against',
|
||||||
}: VoteIconProps) {
|
}: VoteIconProps) {
|
||||||
const label = vote ? yesText : noText;
|
const label = vote ? yesText : noText;
|
||||||
const bg = vote ? 'bg-vega-green-550' : 'bg-vega-pink-550';
|
|
||||||
const icon: IconName = vote ? 'tick-circle' : 'delete';
|
const icon: IconName = vote ? 'tick-circle' : 'delete';
|
||||||
const fill = vote ? 'vega-green-300' : 'vega-pink-300';
|
const bg = getBgColour(useVoteColour, vote);
|
||||||
const text = vote ? 'vega-green-200' : 'vega-pink-200';
|
const fill = getFillColour(useVoteColour, vote);
|
||||||
|
const text = getTextColour(useVoteColour, vote);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export const getTxsDataUrl = ({ limit, filters }: IGetTxsDataUrl) => {
|
|||||||
// Hacky fix for param as array
|
// Hacky fix for param as array
|
||||||
let urlAsString = url.toString();
|
let urlAsString = url.toString();
|
||||||
if (filters) {
|
if (filters) {
|
||||||
urlAsString += '&' + filters;
|
urlAsString += '&' + filters.replace(' ', '%20');
|
||||||
}
|
}
|
||||||
|
|
||||||
return urlAsString;
|
return urlAsString;
|
||||||
@@ -65,6 +65,14 @@ export const useTxsData = ({ limit, filters }: IUseTxsData) => {
|
|||||||
}
|
}
|
||||||
}, [setTxsState, data]);
|
}, [setTxsState, data]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setTxsState((prev) => ({
|
||||||
|
txsData: [],
|
||||||
|
hasMoreTxs: true,
|
||||||
|
lastCursor: '',
|
||||||
|
}));
|
||||||
|
}, [filters]);
|
||||||
|
|
||||||
const loadTxs = useCallback(() => {
|
const loadTxs = useCallback(() => {
|
||||||
return refetch({
|
return refetch({
|
||||||
limit: limit,
|
limit: limit,
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import { render } from '@testing-library/react';
|
import { render } from '@testing-library/react';
|
||||||
import { OracleDetailsType } from './oracle-details-type';
|
import { OracleDetailsType, isInternalSourceType } from './oracle-details-type';
|
||||||
import type { SourceTypeName } from './oracle-details-type';
|
import type { SourceType } from './oracle';
|
||||||
|
import { PropertyKeyType } from '@vegaprotocol/types';
|
||||||
|
|
||||||
function renderComponent(type: SourceTypeName) {
|
function renderComponent(type: SourceType) {
|
||||||
return <OracleDetailsType type={type} />;
|
return <OracleDetailsType sourceType={type} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderWrappedComponent(type: SourceTypeName) {
|
function renderWrappedComponent(type: SourceType) {
|
||||||
return (
|
return (
|
||||||
<table>
|
<table>
|
||||||
<tbody>{renderComponent(type)}</tbody>
|
<tbody>{renderComponent(type)}</tbody>
|
||||||
@@ -14,19 +15,53 @@ function renderWrappedComponent(type: SourceTypeName) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mock(name: string): SourceType {
|
||||||
|
return {
|
||||||
|
sourceType: {
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
__typename: 'Filter',
|
||||||
|
key: {
|
||||||
|
name,
|
||||||
|
type: PropertyKeyType.TYPE_STRING,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
describe('Oracle type view', () => {
|
describe('Oracle type view', () => {
|
||||||
it('Renders nothing when type is null', () => {
|
it('Renders nothing when type is null', () => {
|
||||||
const res = render(renderComponent(null as unknown as SourceTypeName));
|
const res = render(renderComponent(null as unknown as SourceType));
|
||||||
expect(res.container).toBeEmptyDOMElement();
|
expect(res.container).toBeEmptyDOMElement();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Renders Internal time for internal sources', () => {
|
it('Renders Internal time for internal sources - timestamp', () => {
|
||||||
const res = render(renderWrappedComponent('DataSourceDefinitionInternal'));
|
const s = mock('vegaprotocol.builtin.timestamp');
|
||||||
expect(res.getByText('Internal time')).toBeInTheDocument();
|
expect(isInternalSourceType(s)).toEqual(true);
|
||||||
|
const res = render(renderWrappedComponent(s));
|
||||||
|
expect(res.getByText('Internal data')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders Internal time for internal sources - potential future types', () => {
|
||||||
|
const s = mock('vegaprotocol.builtin.boolean');
|
||||||
|
expect(isInternalSourceType(s)).toEqual(true);
|
||||||
|
const res = render(renderWrappedComponent(s));
|
||||||
|
expect(res.getByText('Internal data')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders External data otherwise - prices.external.whatever', () => {
|
||||||
|
const s = mock('prices.external.whatever');
|
||||||
|
expect(isInternalSourceType(s)).toEqual(false);
|
||||||
|
const res = render(renderWrappedComponent(s));
|
||||||
|
expect(res.getByText('External data')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Renders External data otherwise', () => {
|
it('Renders External data otherwise', () => {
|
||||||
const res = render(renderWrappedComponent('DataSourceDefinitionExternal'));
|
const s = mock('prices.external.vegaprotocol.builtin.');
|
||||||
|
expect(isInternalSourceType(s)).toEqual(false);
|
||||||
|
const res = render(renderWrappedComponent(s));
|
||||||
expect(res.getByText('External data')).toBeInTheDocument();
|
expect(res.getByText('External data')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,27 +1,51 @@
|
|||||||
import { TableRow, TableCell, TableHeader } from '../../../components/table';
|
import { TableRow, TableCell, TableHeader } from '../../../components/table';
|
||||||
import type { SourceType } from './oracle';
|
import type { SourceType } from './oracle';
|
||||||
|
|
||||||
export type SourceTypeName = SourceType['__typename'] | undefined;
|
/**
|
||||||
|
* Basic function to determine if a source is internal or external.
|
||||||
|
*
|
||||||
|
* This should be distinguishable using __typename, but the type is incorrectly
|
||||||
|
* reported at the moment, so instead we check the filters.
|
||||||
|
*
|
||||||
|
* @param s SourceType
|
||||||
|
* @returns boolean True if the source is internal
|
||||||
|
*/
|
||||||
|
export function isInternalSourceType(s: SourceType) {
|
||||||
|
if ('filters' in s.sourceType) {
|
||||||
|
const filters = s.sourceType.filters;
|
||||||
|
|
||||||
|
if (filters) {
|
||||||
|
return (
|
||||||
|
filters?.filter((f) => {
|
||||||
|
return f.key.name?.indexOf('vegaprotocol.builtin.') === 0;
|
||||||
|
}).length > 0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
interface OracleDetailsTypeProps {
|
interface OracleDetailsTypeProps {
|
||||||
type: SourceTypeName;
|
sourceType: SourceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders a a single table row for the Oracle Details view that shows
|
* Renders a a single table row for the Oracle Details view that shows
|
||||||
* if the oracle is using the internal time oracle or external data
|
* if the oracle is using the internal time oracle or external data
|
||||||
*/
|
*/
|
||||||
export function OracleDetailsType({ type }: OracleDetailsTypeProps) {
|
export function OracleDetailsType({ sourceType }: OracleDetailsTypeProps) {
|
||||||
if (!type) {
|
if (!sourceType) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isInternal = isInternalSourceType(sourceType);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableHeader scope="row">Type</TableHeader>
|
<TableHeader scope="row">Type</TableHeader>
|
||||||
<TableCell modifier="bordered">
|
<TableCell modifier="bordered">
|
||||||
{type === 'DataSourceDefinitionInternal'
|
{isInternal ? 'Internal data' : 'External data'}
|
||||||
? 'Internal time'
|
|
||||||
: 'External data'}
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ export const OracleDetails = ({
|
|||||||
<OracleLink id={id} />
|
<OracleLink id={id} />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
<OracleDetailsType type={sourceType.__typename} />
|
<OracleDetailsType sourceType={sourceType} />
|
||||||
<OracleSigners sourceType={sourceType} />
|
<OracleSigners sourceType={sourceType} />
|
||||||
<OracleMarkets id={id} />
|
<OracleMarkets id={id} />
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import { t } from '@vegaprotocol/i18n';
|
||||||
|
import { RouteTitle } from '../../components/route-title';
|
||||||
|
|
||||||
|
export const Disclaimer = () => {
|
||||||
|
return (
|
||||||
|
<section>
|
||||||
|
<div className="px-40 max-sm:px-0 max-md:px-10 mb-4 max-w-5xl">
|
||||||
|
<RouteTitle data-testid="disclaimer-header">
|
||||||
|
{t('Disclaimer')}
|
||||||
|
</RouteTitle>
|
||||||
|
<p className="mt-3">
|
||||||
|
The Vega Block Explorer is an application that allows users to, among
|
||||||
|
other things, browse through blocks, view wallet addresses, network
|
||||||
|
hashrate, transaction data and other key information on the Vega
|
||||||
|
blockchain. It is free, public and open source software. Software
|
||||||
|
upgrades may contain bugs or security vulnerabilities that might
|
||||||
|
result in loss of functionality.
|
||||||
|
</p>
|
||||||
|
<p className="mt-3">
|
||||||
|
The Vega Block Explorer uses data from nodes on the Vega Blockchain.
|
||||||
|
The developers of the Vega Block Explorer do not operate or run the
|
||||||
|
Vega Blockchain or any other blockchain.
|
||||||
|
</p>
|
||||||
|
<p className="mt-3 font-semibold">
|
||||||
|
The Vega Block Explorer is provided “as is”. The developers of the
|
||||||
|
Vega Block Explorer make no representations or warranties of any kind,
|
||||||
|
whether express or implied, statutory or otherwise regarding the Vega
|
||||||
|
Block Explorer. They disclaim all warranties of merchantability,
|
||||||
|
quality, fitness for purpose. They disclaim all warranties that the
|
||||||
|
Vega Block Explorer is free of harmful components or errors.
|
||||||
|
</p>
|
||||||
|
<p className="mt-3 font-bold">
|
||||||
|
No developer of the Vega Block Explorer accepts any responsibility
|
||||||
|
for, or liability to users in connection with their use of the Vega
|
||||||
|
Block Explorer.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -10,4 +10,5 @@ export const Routes = {
|
|||||||
MARKETS: 'markets',
|
MARKETS: 'markets',
|
||||||
ORACLES: 'oracles',
|
ORACLES: 'oracles',
|
||||||
NETWORK_PARAMETERS: 'network-parameters',
|
NETWORK_PARAMETERS: 'network-parameters',
|
||||||
|
DISCLAIMER: 'disclaimer',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import { AssetLink, MarketLink } from '../components/links';
|
|||||||
import { truncateMiddle } from '@vegaprotocol/ui-toolkit';
|
import { truncateMiddle } from '@vegaprotocol/ui-toolkit';
|
||||||
import { remove0x } from '@vegaprotocol/utils';
|
import { remove0x } from '@vegaprotocol/utils';
|
||||||
import { PartyAccountsByAsset } from './parties/id/accounts';
|
import { PartyAccountsByAsset } from './parties/id/accounts';
|
||||||
|
import { Disclaimer } from './pages/disclaimer';
|
||||||
|
|
||||||
export type Navigable = {
|
export type Navigable = {
|
||||||
path: string;
|
path: string;
|
||||||
@@ -335,6 +336,17 @@ export const routerConfig: Route[] = [
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: Routes.DISCLAIMER,
|
||||||
|
element: <Disclaimer />,
|
||||||
|
handle: {
|
||||||
|
name: t('Disclaimer'),
|
||||||
|
text: t('Disclaimer'),
|
||||||
|
breadcrumb: () => (
|
||||||
|
<Link to={Routes.DISCLAIMER}>{t('Disclaimer')}</Link>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
...partiesRoutes,
|
...partiesRoutes,
|
||||||
...assetsRoutes,
|
...assetsRoutes,
|
||||||
...genesisRoutes,
|
...genesisRoutes,
|
||||||
|
|||||||
@@ -5,17 +5,43 @@ import { TxsInfiniteList } from '../../../components/txs';
|
|||||||
import { useTxsData } from '../../../hooks/use-txs-data';
|
import { useTxsData } from '../../../hooks/use-txs-data';
|
||||||
import { useDocumentTitle } from '../../../hooks/use-document-title';
|
import { useDocumentTitle } from '../../../hooks/use-document-title';
|
||||||
|
|
||||||
const BE_TXS_PER_REQUEST = 20;
|
import { useState } from 'react';
|
||||||
|
import { AllFilterOptions, TxsFilter } from '../../../components/txs/tx-filter';
|
||||||
|
|
||||||
|
const BE_TXS_PER_REQUEST = 15;
|
||||||
|
|
||||||
export const TxsList = () => {
|
export const TxsList = () => {
|
||||||
useDocumentTitle(['Transactions']);
|
useDocumentTitle(['Transactions']);
|
||||||
|
|
||||||
const { hasMoreTxs, loadTxs, error, txsData, refreshTxs, loading } =
|
|
||||||
useTxsData({ limit: BE_TXS_PER_REQUEST });
|
|
||||||
return (
|
return (
|
||||||
<section className="md:p-2 lg:p-4 xl:p-6">
|
<section className="md:p-2 lg:p-4 xl:p-6 relative">
|
||||||
<RouteTitle>{t('Transactions')}</RouteTitle>
|
<RouteTitle>{t('Transactions')}</RouteTitle>
|
||||||
<BlocksRefetch refetch={refreshTxs} />
|
<TxsListFiltered />
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const TxsListFiltered = () => {
|
||||||
|
const [filters, setFilters] = useState(new Set(AllFilterOptions));
|
||||||
|
|
||||||
|
const f =
|
||||||
|
filters && filters.size === 1
|
||||||
|
? `filters[cmd.type]=${Array.from(filters)[0]}`
|
||||||
|
: '';
|
||||||
|
|
||||||
|
const { hasMoreTxs, loadTxs, error, txsData, refreshTxs, loading } =
|
||||||
|
useTxsData({
|
||||||
|
limit: BE_TXS_PER_REQUEST,
|
||||||
|
filters: f,
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<menu className="mb-2">
|
||||||
|
<BlocksRefetch refetch={refreshTxs} />
|
||||||
|
<TxsFilter filters={filters} setFilters={setFilters} />
|
||||||
|
</menu>
|
||||||
|
|
||||||
<TxsInfiniteList
|
<TxsInfiniteList
|
||||||
hasMoreTxs={hasMoreTxs}
|
hasMoreTxs={hasMoreTxs}
|
||||||
areTxsLoading={loading}
|
areTxsLoading={loading}
|
||||||
@@ -24,6 +50,6 @@ export const TxsList = () => {
|
|||||||
error={error}
|
error={error}
|
||||||
className="mb-28"
|
className="mb-28"
|
||||||
/>
|
/>
|
||||||
</section>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
+428
-421
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ module.exports = defineConfig({
|
|||||||
viewportWidth: 1440,
|
viewportWidth: 1440,
|
||||||
viewportHeight: 900,
|
viewportHeight: 900,
|
||||||
numTestsKeptInMemory: 5,
|
numTestsKeptInMemory: 5,
|
||||||
|
downloadsFolder: 'cypress/downloads',
|
||||||
testIsolation: false,
|
testIsolation: false,
|
||||||
},
|
},
|
||||||
env: {
|
env: {
|
||||||
@@ -48,7 +49,7 @@ module.exports = defineConfig({
|
|||||||
vegaTokenContractAddress: '0xF41bD86d462D36b997C0bbb4D97a0a3382f205B7',
|
vegaTokenContractAddress: '0xF41bD86d462D36b997C0bbb4D97a0a3382f205B7',
|
||||||
vegaTokenAddress: '0x67175Da1D5e966e40D11c4B2519392B2058373de',
|
vegaTokenAddress: '0x67175Da1D5e966e40D11c4B2519392B2058373de',
|
||||||
txTimeout: { timeout: 70000 },
|
txTimeout: { timeout: 70000 },
|
||||||
epochTimeout: { timeout: 6000 },
|
epochTimeout: { timeout: 12000 },
|
||||||
blockConfirmations: 3,
|
blockConfirmations: 3,
|
||||||
grepTags: '@regression @smoke @slow',
|
grepTags: '@regression @smoke @slow',
|
||||||
grepFilterSpecs: true,
|
grepFilterSpecs: true,
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
export const previousEpochData = {
|
||||||
|
epoch: {
|
||||||
|
id: '7611',
|
||||||
|
validatorsConnection: {
|
||||||
|
edges: [
|
||||||
|
{
|
||||||
|
node: {
|
||||||
|
id: 'cd96782bc0ad5679869cf69fe7838a92212da7f53b4a214bed68067117494122',
|
||||||
|
stakedTotal: '3154229668720612941799',
|
||||||
|
rewardScore: {
|
||||||
|
rawValidatorScore: '0.2',
|
||||||
|
performanceScore: '1',
|
||||||
|
multisigScore: '0',
|
||||||
|
validatorScore: '0.2',
|
||||||
|
normalisedScore: '0.2007216887087119',
|
||||||
|
validatorStatus: 'VALIDATOR_NODE_STATUS_TENDERMINT',
|
||||||
|
__typename: 'RewardScore',
|
||||||
|
},
|
||||||
|
rankingScore: {
|
||||||
|
status: 'VALIDATOR_NODE_STATUS_TENDERMINT',
|
||||||
|
previousStatus: 'VALIDATOR_NODE_STATUS_TENDERMINT',
|
||||||
|
rankingScore: '0.211713765544955625',
|
||||||
|
stakeScore: '0.2016321576618625',
|
||||||
|
performanceScore: '1',
|
||||||
|
votingPower: '2007',
|
||||||
|
__typename: 'RankingScore',
|
||||||
|
},
|
||||||
|
__typename: 'Node',
|
||||||
|
},
|
||||||
|
__typename: 'NodeEdge',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
node: {
|
||||||
|
id: '887d936f797a47032eceb572a13b69b581d3b1fa595a7d021a3e3cf2a5d2acfd',
|
||||||
|
stakedTotal: '3151161904761904764551',
|
||||||
|
rewardScore: {
|
||||||
|
rawValidatorScore: '0.2',
|
||||||
|
performanceScore: '1',
|
||||||
|
multisigScore: '1',
|
||||||
|
validatorScore: '0.2',
|
||||||
|
normalisedScore: '0.2007216887087119',
|
||||||
|
validatorStatus: 'VALIDATOR_NODE_STATUS_TENDERMINT',
|
||||||
|
__typename: 'RewardScore',
|
||||||
|
},
|
||||||
|
rankingScore: {
|
||||||
|
status: 'VALIDATOR_NODE_STATUS_TENDERMINT',
|
||||||
|
previousStatus: 'VALIDATOR_NODE_STATUS_TENDERMINT',
|
||||||
|
rankingScore: '0.211507855409133255',
|
||||||
|
stakeScore: '0.2014360527706031',
|
||||||
|
performanceScore: '1',
|
||||||
|
votingPower: '2007',
|
||||||
|
__typename: 'RankingScore',
|
||||||
|
},
|
||||||
|
__typename: 'Node',
|
||||||
|
},
|
||||||
|
__typename: 'NodeEdge',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
__typename: 'NodesConnection',
|
||||||
|
},
|
||||||
|
__typename: 'Epoch',
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,21 +7,23 @@ import {
|
|||||||
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,
|
||||||
|
stakingPageAssociateTokens,
|
||||||
|
stakingPageDisassociateAllTokens,
|
||||||
|
} 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';
|
||||||
import { vegaWalletSetSpecifiedApprovalAmount } from '../../../../governance-e2e/src/support/wallet-teardown.functions';
|
import {
|
||||||
|
switchVegaWalletPubKey,
|
||||||
|
vegaWalletSetSpecifiedApprovalAmount,
|
||||||
|
} from '../../support/wallet-functions';
|
||||||
import type { testFreeformProposal } from '../../support/common-interfaces';
|
import type { testFreeformProposal } from '../../support/common-interfaces';
|
||||||
import { formatDateWithLocalTimezone } from '@vegaprotocol/utils';
|
import { formatDateWithLocalTimezone } from '@vegaprotocol/utils';
|
||||||
|
|
||||||
@@ -38,6 +40,9 @@ 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 proposalDescriptionToggle = 'proposal-description-toggle';
|
||||||
|
const voteBreakdownToggle = 'vote-breakdown-toggle';
|
||||||
|
const proposalTermsToggle = 'proposal-json-toggle';
|
||||||
|
|
||||||
describe(
|
describe(
|
||||||
'Governance flow for proposal details',
|
'Governance flow for proposal details',
|
||||||
@@ -46,7 +51,7 @@ describe(
|
|||||||
before('connect wallets and set approval limit', function () {
|
before('connect wallets and set approval limit', function () {
|
||||||
cy.visit('/');
|
cy.visit('/');
|
||||||
ethereumWalletConnect();
|
ethereumWalletConnect();
|
||||||
cy.associateTokensToVegaWallet('1');
|
// cy.associateTokensToVegaWallet('1');
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach('visit proposals tab', function () {
|
beforeEach('visit proposals tab', function () {
|
||||||
@@ -62,61 +67,69 @@ 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.getByTestId(proposalDescriptionToggle).click();
|
||||||
|
cy.getByTestId('proposal-description-toggle');
|
||||||
cy.get(proposalDetailsDescription)
|
cy.get(proposalDetailsDescription)
|
||||||
.should('contain', rawProposal.rationale.description)
|
.find('p')
|
||||||
.and('be.visible');
|
.should('have.text', proposalDescription);
|
||||||
});
|
});
|
||||||
// 3001-VOTE-052
|
// 3001-VOTE-008
|
||||||
|
getProposalInformationFromTable('ID')
|
||||||
|
.invoke('text')
|
||||||
|
.should('not.be.empty')
|
||||||
|
.and('have.length', 64);
|
||||||
|
// 3001-VOTE-009
|
||||||
|
getProposalInformationFromTable('Proposed by')
|
||||||
|
.invoke('text')
|
||||||
|
.should('not.be.empty')
|
||||||
|
.and('have.length', 64);
|
||||||
|
cy.getByTestId(proposalTermsToggle).click();
|
||||||
|
// 3001-VOTE-052 3001-VOTE-010
|
||||||
cy.get('code.language-json')
|
cy.get('code.language-json')
|
||||||
.should('exist')
|
.should('exist')
|
||||||
.within(() => {
|
.within(() => {
|
||||||
cy.get('.hljs-string').eq(0).should('have.text', '"ProposalTerms"');
|
cy.get('.hljs-attr').eq(0).should('have.text', '"id"');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// 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);
|
||||||
|
|
||||||
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(
|
|
||||||
formatDateWithLocalTimezone(
|
|
||||||
new Date(createTenDigitUnixTimeStampForSpecifiedDays(0) * 1000)
|
|
||||||
)
|
|
||||||
).then((proposalDate) => {
|
|
||||||
getProposalInformationFromTable('Proposed on')
|
|
||||||
.contains(proposalDate)
|
|
||||||
.should('be.visible');
|
|
||||||
});
|
});
|
||||||
|
getProposalInformationFromTable('Proposed on')
|
||||||
|
.invoke('text')
|
||||||
|
.should('not.be.empty');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Newly created proposal details - shows default status set to fail', function () {
|
it('Newly created proposal details - shows default status set to fail', function () {
|
||||||
@@ -125,13 +138,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');
|
||||||
@@ -151,9 +165,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');
|
||||||
@@ -179,6 +193,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');
|
||||||
@@ -220,14 +235,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) => {
|
||||||
@@ -235,14 +251,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%')
|
||||||
@@ -259,6 +276,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');
|
||||||
@@ -286,5 +304,33 @@ describe(
|
|||||||
.and('be.visible');
|
.and('be.visible');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Able to vote for proposal twice by switching public key', function () {
|
||||||
|
ensureSpecifiedUnstakedTokensAreAssociated('1');
|
||||||
|
createRawProposal();
|
||||||
|
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||||
|
getProposalFromTitle(rawProposal.rationale.title).within(() =>
|
||||||
|
cy.get(viewProposalButton).click()
|
||||||
|
);
|
||||||
|
voteForProposal('for');
|
||||||
|
cy.contains('You voted: For').should('be.visible');
|
||||||
|
ethereumWalletConnect();
|
||||||
|
switchVegaWalletPubKey();
|
||||||
|
stakingPageAssociateTokens('2');
|
||||||
|
navigateTo(navigation.proposals);
|
||||||
|
getProposalFromTitle(rawProposal.rationale.title).within(() =>
|
||||||
|
cy.get(viewProposalButton).click()
|
||||||
|
);
|
||||||
|
cy.getByTestId('you-voted').should('not.exist');
|
||||||
|
voteForProposal('against');
|
||||||
|
cy.contains('You voted: Against').should('be.visible');
|
||||||
|
switchVegaWalletPubKey();
|
||||||
|
cy.get(proposalVoteProgressForTokens).should('contain.text', '1.00');
|
||||||
|
// Checking vote status for different public keys is displayed correctly
|
||||||
|
cy.contains('You voted: For').should('be.visible');
|
||||||
|
});
|
||||||
|
switchVegaWalletPubKey();
|
||||||
|
stakingPageDisassociateAllTokens();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -14,8 +14,9 @@ import {
|
|||||||
createUpdateNetworkProposalTxBody,
|
createUpdateNetworkProposalTxBody,
|
||||||
createFreeFormProposalTxBody,
|
createFreeFormProposalTxBody,
|
||||||
} from '../../support/proposal.functions';
|
} from '../../support/proposal.functions';
|
||||||
|
import { ensureSpecifiedUnstakedTokensAreAssociated } from '../../support/staking.functions';
|
||||||
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-functions';
|
||||||
|
|
||||||
const proposalListItem = '[data-testid="proposals-list-item"]';
|
const proposalListItem = '[data-testid="proposals-list-item"]';
|
||||||
const closedProposals = '[data-testid="closed-proposals"]';
|
const closedProposals = '[data-testid="closed-proposals"]';
|
||||||
@@ -43,6 +44,7 @@ context(
|
|||||||
waitForSpinner();
|
waitForSpinner();
|
||||||
cy.connectVegaWallet();
|
cy.connectVegaWallet();
|
||||||
ethereumWalletConnect();
|
ethereumWalletConnect();
|
||||||
|
ensureSpecifiedUnstakedTokensAreAssociated('1');
|
||||||
navigateTo(navigation.proposals);
|
navigateTo(navigation.proposals);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -58,14 +60,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');
|
||||||
@@ -87,16 +87,16 @@ 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)
|
||||||
.contains('Passed', proposalTimeout)
|
.should('have.text', 'Passed')
|
||||||
.and('be.visible');
|
.then(() => {
|
||||||
getProposalInformationFromTable('State')
|
cy.get(proposalStatus, proposalTimeout).should(
|
||||||
.contains('Enacted', proposalTimeout)
|
'have.text',
|
||||||
.and('be.visible');
|
'Enacted'
|
||||||
|
);
|
||||||
|
});
|
||||||
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');
|
||||||
@@ -121,13 +121,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
|
||||||
@@ -144,12 +140,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,12 +5,12 @@ import {
|
|||||||
enterRawProposalBody,
|
enterRawProposalBody,
|
||||||
enterUniqueFreeFormProposalBody,
|
enterUniqueFreeFormProposalBody,
|
||||||
generateFreeFormProposalTitle,
|
generateFreeFormProposalTitle,
|
||||||
|
getProposalFromTitle,
|
||||||
getProposalInformationFromTable,
|
getProposalInformationFromTable,
|
||||||
getSubmittedProposalFromProposalList,
|
|
||||||
goToMakeNewProposal,
|
goToMakeNewProposal,
|
||||||
governanceProposalType,
|
governanceProposalType,
|
||||||
|
submitUniqueRawProposal,
|
||||||
voteForProposal,
|
voteForProposal,
|
||||||
waitForProposalSubmitted,
|
|
||||||
waitForProposalSync,
|
waitForProposalSync,
|
||||||
} from '../../support/governance.functions';
|
} from '../../support/governance.functions';
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
vegaWalletSetSpecifiedApprovalAmount,
|
vegaWalletSetSpecifiedApprovalAmount,
|
||||||
vegaWalletTeardown,
|
vegaWalletTeardown,
|
||||||
} from '../../support/wallet-teardown.functions';
|
} from '../../support/wallet-functions';
|
||||||
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
|
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
|
||||||
import type { testFreeformProposal } from '../../support/common-interfaces';
|
import type { testFreeformProposal } from '../../support/common-interfaces';
|
||||||
|
|
||||||
@@ -45,11 +45,7 @@ const connectToVegaWalletButton = '[data-testid="connect-to-vega-wallet-btn"]';
|
|||||||
const newProposalSubmitButton = '[data-testid="proposal-submit"]';
|
const newProposalSubmitButton = '[data-testid="proposal-submit"]';
|
||||||
const viewProposalButton = '[data-testid="view-proposal-btn"]';
|
const viewProposalButton = '[data-testid="view-proposal-btn"]';
|
||||||
const rawProposalData = '[data-testid="proposal-data"]';
|
const rawProposalData = '[data-testid="proposal-data"]';
|
||||||
const minVoteButton = '[data-testid="min-vote"]';
|
|
||||||
const maxVoteButton = '[data-testid="max-vote"]';
|
|
||||||
const voteButtons = '[data-testid="vote-buttons"]';
|
const voteButtons = '[data-testid="vote-buttons"]';
|
||||||
const votingDate = '[data-testid="voting-date"]';
|
|
||||||
const voteTwoMinExtraNote = '[data-testid="voting-2-mins-extra"]';
|
|
||||||
const rejectProposalsLink = '[href="/proposals/rejected"]';
|
const rejectProposalsLink = '[href="/proposals/rejected"]';
|
||||||
const feedbackError = '[data-testid="Error"]';
|
const feedbackError = '[data-testid="Error"]';
|
||||||
const noOpenProposals = '[data-testid="no-open-proposals"]';
|
const noOpenProposals = '[data-testid="no-open-proposals"]';
|
||||||
@@ -81,7 +77,6 @@ context(
|
|||||||
});
|
});
|
||||||
|
|
||||||
vegaWalletSetSpecifiedApprovalAmount('1000');
|
vegaWalletSetSpecifiedApprovalAmount('1000');
|
||||||
cy.associateTokensToVegaWallet('1');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach('visit governance tab', function () {
|
beforeEach('visit governance tab', function () {
|
||||||
@@ -95,7 +90,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,9 +101,8 @@ context(
|
|||||||
.and('have.text', 'There are no enacted or rejected proposals');
|
.and('have.text', 'There are no enacted or rejected proposals');
|
||||||
});
|
});
|
||||||
|
|
||||||
// 3002-PROP-002
|
// 3002-PROP-002 3002-PROP-003 3001-VOTE-012 3007-PNE-020 3004-PMAC-004 3005-PASN-004 3008-PFRO-016 3003-PMAN-004
|
||||||
// 3002-PROP-003
|
it('Proposal form - shows how many vega tokens are required to make a proposal', function () {
|
||||||
it('Submit a 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(
|
||||||
@@ -115,22 +110,14 @@ context(
|
|||||||
).should('be.visible');
|
).should('be.visible');
|
||||||
});
|
});
|
||||||
|
|
||||||
// 3002-PROP-011
|
// 3002-PROP-011 3008-PFRO-005
|
||||||
it('Able to submit a valid freeform proposal - with minimum required tokens associated', function () {
|
it('Able to submit a valid freeform proposal - with minimum required tokens associated', function () {
|
||||||
goToMakeNewProposal(governanceProposalType.FREEFORM);
|
ensureSpecifiedUnstakedTokensAreAssociated('1');
|
||||||
cy.get(minVoteButton).should('be.visible'); // 3002-PROP-008
|
verifyUnstakedBalance(1);
|
||||||
cy.get(maxVoteButton).should('be.visible');
|
createRawProposal();
|
||||||
cy.get(votingDate).should('not.be.empty');
|
|
||||||
cy.get(voteTwoMinExtraNote).should(
|
|
||||||
'contain.text',
|
|
||||||
'we add 2 minutes of extra time'
|
|
||||||
);
|
|
||||||
enterUniqueFreeFormProposalBody('50', generateFreeFormProposalTitle());
|
|
||||||
// 3002-PROP-012
|
|
||||||
// 3002-PROP-016
|
|
||||||
waitForProposalSubmitted();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 3008-PFRO-002 3008-PFRO-004
|
||||||
it('Able to submit a valid freeform proposal - with minimum required tokens associated - but also staked', function () {
|
it('Able to submit a valid freeform proposal - with minimum required tokens associated - but also staked', function () {
|
||||||
ensureSpecifiedUnstakedTokensAreAssociated('2');
|
ensureSpecifiedUnstakedTokensAreAssociated('2');
|
||||||
verifyUnstakedBalance(2);
|
verifyUnstakedBalance(2);
|
||||||
@@ -140,19 +127,12 @@ 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('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(
|
|
||||||
'not.exist'
|
|
||||||
);
|
|
||||||
cy.get('input:invalid')
|
cy.get('input:invalid')
|
||||||
.invoke('prop', 'validationMessage')
|
.invoke('prop', 'validationMessage')
|
||||||
.should('equal', 'Value must be greater than or equal to 1.');
|
.should('equal', 'Value must be greater than or equal to 1.');
|
||||||
@@ -185,17 +165,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');
|
||||||
@@ -285,23 +261,38 @@ context(
|
|||||||
closeDialog();
|
closeDialog();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 3007-PNE-022 3007-PNE-023 3004-PMAC-006 3004-PMAC-007 3005-PASN-006 3005-PASN-007
|
||||||
|
// 3006-PASC-006 3006-PASC-007 3008-PFRO-018 3008-PFRO-019 3003-PMAN-006 3003-PMAN-007
|
||||||
|
it('Unable to submit proposal without valid json', function () {
|
||||||
|
goToMakeNewProposal(governanceProposalType.RAW);
|
||||||
|
cy.get(newProposalSubmitButton).click();
|
||||||
|
cy.getByTestId('input-error-text').should('have.text', 'Required');
|
||||||
|
cy.get(rawProposalData).type('Not a valid json string');
|
||||||
|
cy.get(newProposalSubmitButton).click();
|
||||||
|
cy.getByTestId('input-error-text').should(
|
||||||
|
'have.text',
|
||||||
|
'Must be valid JSON'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
// 1005-PROP-009
|
// 1005-PROP-009
|
||||||
it('Unable to vote on a freeform proposal - when some but not enough vega associated', function () {
|
it('Unable to vote on a freeform proposal - when some but not enough vega associated', function () {
|
||||||
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', {
|
||||||
@@ -319,9 +310,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
|
||||||
|
|||||||
@@ -1,23 +1,34 @@
|
|||||||
import {
|
import {
|
||||||
closeDialog,
|
closeDialog,
|
||||||
|
dissociateFromSecondWalletKey,
|
||||||
navigateTo,
|
navigateTo,
|
||||||
navigation,
|
navigation,
|
||||||
turnTelemetryOff,
|
turnTelemetryOff,
|
||||||
waitForSpinner,
|
waitForSpinner,
|
||||||
} from '../../support/common.functions';
|
} from '../../support/common.functions';
|
||||||
|
import {
|
||||||
|
getDownloadedProposalJsonPath,
|
||||||
|
getProposalFromTitle,
|
||||||
|
submitUniqueRawProposal,
|
||||||
|
} from '../../support/governance.functions';
|
||||||
import {
|
import {
|
||||||
getProposalInformationFromTable,
|
getProposalInformationFromTable,
|
||||||
goToMakeNewProposal,
|
goToMakeNewProposal,
|
||||||
|
governanceProposalType,
|
||||||
voteForProposal,
|
voteForProposal,
|
||||||
waitForProposalSubmitted,
|
|
||||||
} from '../../support/governance.functions';
|
} from '../../support/governance.functions';
|
||||||
import { ensureSpecifiedUnstakedTokensAreAssociated } from '../../support/staking.functions';
|
import {
|
||||||
|
ensureSpecifiedUnstakedTokensAreAssociated,
|
||||||
|
stakingPageAssociateTokens,
|
||||||
|
stakingPageDisassociateAllTokens,
|
||||||
|
} from '../../support/staking.functions';
|
||||||
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
|
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
|
||||||
import {
|
import {
|
||||||
|
switchVegaWalletPubKey,
|
||||||
|
vegaWalletFaucetAssetsWithoutCheck,
|
||||||
vegaWalletSetSpecifiedApprovalAmount,
|
vegaWalletSetSpecifiedApprovalAmount,
|
||||||
vegaWalletTeardown,
|
vegaWalletTeardown,
|
||||||
} from '../../support/wallet-teardown.functions';
|
} from '../../support/wallet-functions';
|
||||||
import { vegaWalletFaucetAssetsWithoutCheck } from '../../support/wallet-vega.functions';
|
|
||||||
|
|
||||||
const proposalListItem = '[data-testid="proposals-list-item"]';
|
const proposalListItem = '[data-testid="proposals-list-item"]';
|
||||||
const openProposals = '[data-testid="open-proposals"]';
|
const openProposals = '[data-testid="open-proposals"]';
|
||||||
@@ -25,15 +36,11 @@ const proposalType = '[data-testid="proposal-type"]';
|
|||||||
const proposalDetails = '[data-testid="proposal-details"]';
|
const proposalDetails = '[data-testid="proposal-details"]';
|
||||||
const newProposalSubmitButton = '[data-testid="proposal-submit"]';
|
const newProposalSubmitButton = '[data-testid="proposal-submit"]';
|
||||||
const proposalVoteDeadline = '[data-testid="proposal-vote-deadline"]';
|
const proposalVoteDeadline = '[data-testid="proposal-vote-deadline"]';
|
||||||
const proposalValidationDeadline =
|
|
||||||
'[data-testid="proposal-validation-deadline"]';
|
|
||||||
const proposalParameterSelect = '[data-testid="proposal-parameter-select"]';
|
const proposalParameterSelect = '[data-testid="proposal-parameter-select"]';
|
||||||
const proposalMarketSelect = '[data-testid="proposal-market-select"]';
|
const proposalMarketSelect = '[data-testid="proposal-market-select"]';
|
||||||
const newProposalTitle = '[data-testid="proposal-title"]';
|
const newProposalTitle = '[data-testid="proposal-title"]';
|
||||||
const newProposalDescription = '[data-testid="proposal-description"]';
|
const newProposalDescription = '[data-testid="proposal-description"]';
|
||||||
const newProposalTerms = '[data-testid="proposal-terms"]';
|
const newProposalTerms = '[data-testid="proposal-terms"]';
|
||||||
const currentParameterValue =
|
|
||||||
'[data-testid="selected-proposal-param-current-value"]';
|
|
||||||
const newProposedParameterValue =
|
const newProposedParameterValue =
|
||||||
'[data-testid="selected-proposal-param-new-value"]';
|
'[data-testid="selected-proposal-param-new-value"]';
|
||||||
const minVoteDeadline = '[data-testid="min-vote"]';
|
const minVoteDeadline = '[data-testid="min-vote"]';
|
||||||
@@ -49,23 +56,13 @@ const feedbackError = '[data-testid="Error"]';
|
|||||||
const viewProposalBtn = 'view-proposal-btn';
|
const viewProposalBtn = 'view-proposal-btn';
|
||||||
const liquidityVoteStatus = 'liquidity-votes-status';
|
const liquidityVoteStatus = 'liquidity-votes-status';
|
||||||
const tokenVoteStatus = 'token-votes-status';
|
const tokenVoteStatus = 'token-votes-status';
|
||||||
const proposalTermsSection = 'proposal';
|
const proposalJsonToggle = 'proposal-json-toggle';
|
||||||
|
const proposalJsonSection = 'proposal-json';
|
||||||
const vegaWalletPublicKey = Cypress.env('vegaWalletPublicKey');
|
const vegaWalletPublicKey = Cypress.env('vegaWalletPublicKey');
|
||||||
const fUSDCId =
|
const fUSDCId =
|
||||||
'816af99af60d684502a40824758f6b5377e6af48e50a9ee8ef478ecb879ea8bc';
|
'816af99af60d684502a40824758f6b5377e6af48e50a9ee8ef478ecb879ea8bc';
|
||||||
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(
|
||||||
'Governance flow - form validations for different governance proposals',
|
'Governance flow - form validations for different governance proposals',
|
||||||
@@ -88,28 +85,10 @@ context(
|
|||||||
navigateTo(navigation.proposals);
|
navigateTo(navigation.proposals);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Able to submit valid update network parameter proposal', function () {
|
|
||||||
goToMakeNewProposal(governanceProposalType.NETWORK_PARAMETER);
|
|
||||||
// 3002-PROP-006
|
|
||||||
cy.get(newProposalTitle).type('Test update network parameter proposal');
|
|
||||||
// 3002-PROP-007
|
|
||||||
cy.get(newProposalDescription).type('E2E test for proposals');
|
|
||||||
|
|
||||||
cy.get(proposalParameterSelect).find('option').should('have.length', 117);
|
|
||||||
cy.get(proposalParameterSelect).select(
|
|
||||||
// 3007-PNEC-002
|
|
||||||
'governance_proposal_asset_minEnact'
|
|
||||||
);
|
|
||||||
cy.get(currentParameterValue).should('have.value', '2s');
|
|
||||||
cy.get(newProposedParameterValue).type('5s'); // 3007-PNEC-003
|
|
||||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
|
||||||
waitForProposalSubmitted();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Unable to submit network parameter with missing/invalid fields', function () {
|
it('Unable to submit network parameter with missing/invalid fields', function () {
|
||||||
navigateTo(navigation.proposals);
|
navigateTo(navigation.proposals);
|
||||||
goToMakeNewProposal(governanceProposalType.NETWORK_PARAMETER);
|
goToMakeNewProposal(governanceProposalType.NETWORK_PARAMETER);
|
||||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
cy.get(proposalDownloadBtn).click();
|
||||||
cy.get(inputError).should('have.length', 3);
|
cy.get(inputError).should('have.length', 3);
|
||||||
cy.get(newProposalTitle).type(
|
cy.get(newProposalTitle).type(
|
||||||
'Invalid update network parameter proposal'
|
'Invalid update network parameter proposal'
|
||||||
@@ -120,62 +99,78 @@ context(
|
|||||||
);
|
);
|
||||||
cy.get(newProposedParameterValue).type('0');
|
cy.get(newProposedParameterValue).type('0');
|
||||||
cy.get(proposalVoteDeadline).clear().type('0');
|
cy.get(proposalVoteDeadline).clear().type('0');
|
||||||
cy.get(newProposalSubmitButton).click();
|
|
||||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
|
||||||
'not.exist'
|
|
||||||
);
|
|
||||||
cy.get(proposalVoteDeadline).clear().type('9000');
|
|
||||||
cy.get(newProposalSubmitButton).click();
|
|
||||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
|
||||||
'not.exist'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Able to download network param proposal json', function () {
|
|
||||||
const downloadFolder = './cypress/downloads/';
|
|
||||||
goToMakeNewProposal(governanceProposalType.NETWORK_PARAMETER);
|
|
||||||
cy.log('Download proposal file');
|
|
||||||
cy.get(proposalDownloadBtn)
|
cy.get(proposalDownloadBtn)
|
||||||
.should('be.visible')
|
|
||||||
.click()
|
.click()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const filename =
|
cy.wrap(
|
||||||
downloadFolder +
|
getDownloadedProposalJsonPath('vega-network-param-proposal-')
|
||||||
'vega-network-param-proposal-' +
|
).then((filePath) => {
|
||||||
getFormattedTime() +
|
goToMakeNewProposal(governanceProposalType.RAW);
|
||||||
'.json';
|
submitUniqueRawProposal({ proposalBody: filePath, submit: false });
|
||||||
cy.readFile(filename, proposalTimeout)
|
});
|
||||||
.its('terms.updateNetworkParameter')
|
|
||||||
.should('exist');
|
|
||||||
});
|
});
|
||||||
|
cy.get(newProposalSubmitButton).click();
|
||||||
|
validateDialogContentMsg('PROPOSAL_ERROR_CLOSE_TIME_TOO_SOON');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 3007-PNEC-001 3007-PNEC-003
|
||||||
|
it('Able to download and submit network param proposal', function () {
|
||||||
|
goToMakeNewProposal(governanceProposalType.NETWORK_PARAMETER);
|
||||||
|
// 3007-PNEC-006
|
||||||
|
cy.get(newProposalTitle)
|
||||||
|
.siblings()
|
||||||
|
.should('contain.text', '(100 characters or less)');
|
||||||
|
// 3007-PNEC-004 3007-PNEC-005
|
||||||
|
cy.get(newProposalTitle).type('Test update network parameter proposal');
|
||||||
|
// 3007-PNEC-009
|
||||||
|
cy.get(newProposalDescription)
|
||||||
|
.siblings()
|
||||||
|
.should('contain.text', '(20,000 characters or less)');
|
||||||
|
// 3007-PNEC-007 3007-PNEC-008
|
||||||
cy.get(newProposalDescription).type('E2E test for downloading proposals');
|
cy.get(newProposalDescription).type('E2E test for downloading proposals');
|
||||||
|
// 3007-PNEC-010
|
||||||
cy.get(proposalParameterSelect).select(
|
cy.get(proposalParameterSelect).select(
|
||||||
'governance_proposal_asset_minClose'
|
'governance_proposal_asset_minClose'
|
||||||
);
|
);
|
||||||
|
// 3007-PNEC-011
|
||||||
cy.get(newProposedParameterValue).type('10s');
|
cy.get(newProposedParameterValue).type('10s');
|
||||||
|
// 3007-PNEC-012
|
||||||
|
cy.get(proposalVoteDeadline).clear().type('2');
|
||||||
|
// 3007-PNEC-013 3007-PNEC-014
|
||||||
|
cy.getByTestId('voting-date').invoke('text').should('not.be.empty');
|
||||||
|
// 3007-PNEC-015
|
||||||
|
cy.get(maxEnactDeadline).click();
|
||||||
|
// 3007-PNEC-016
|
||||||
|
cy.getByTestId('enactment-date').invoke('text').should('not.be.empty');
|
||||||
|
// 3007-PNEC-017
|
||||||
|
cy.contains(
|
||||||
|
'Time till enactment (must be equal to or after vote close)'
|
||||||
|
).should('be.visible');
|
||||||
|
// 3007-PNE-018
|
||||||
cy.log('Download updated proposal file');
|
cy.log('Download updated proposal file');
|
||||||
cy.get(proposalDownloadBtn)
|
cy.get(proposalDownloadBtn)
|
||||||
.should('be.visible')
|
.should('be.visible')
|
||||||
.click()
|
.click()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const filename =
|
cy.wrap(
|
||||||
downloadFolder +
|
getDownloadedProposalJsonPath('vega-network-param-proposal-')
|
||||||
'vega-network-param-proposal-' +
|
).then((filePath) => {
|
||||||
getFormattedTime() +
|
cy.readFile(String(filePath), { timeout: 14000 }).then(
|
||||||
'.json';
|
(jsonFile) => {
|
||||||
cy.get(proposalDownloadBtn).should('be.visible').click();
|
cy.wrap(jsonFile)
|
||||||
cy.readFile(filename, proposalTimeout).then((jsonFile) => {
|
.its('rationale.description')
|
||||||
cy.wrap(jsonFile)
|
.should('eq', 'E2E test for downloading proposals');
|
||||||
.its('rationale.description')
|
cy.wrap(jsonFile)
|
||||||
.should('eq', 'E2E test for downloading proposals');
|
.its('terms.updateNetworkParameter.changes.key')
|
||||||
cy.wrap(jsonFile)
|
.should('eq', 'governance.proposal.asset.minClose');
|
||||||
.its('terms.updateNetworkParameter.changes.key')
|
cy.wrap(jsonFile)
|
||||||
.should('eq', 'governance.proposal.asset.minClose');
|
.its('terms.updateNetworkParameter.changes.value')
|
||||||
cy.wrap(jsonFile)
|
.should('eq', '10s');
|
||||||
.its('terms.updateNetworkParameter.changes.value')
|
}
|
||||||
.should('eq', '10s');
|
);
|
||||||
|
// 3007-PNE-019
|
||||||
|
goToMakeNewProposal(governanceProposalType.RAW);
|
||||||
|
submitUniqueRawProposal({ proposalBody: filePath });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -193,40 +188,78 @@ context(
|
|||||||
cy.get(maxVoteDeadline).click();
|
cy.get(maxVoteDeadline).click();
|
||||||
cy.get(enactmentDeadlineError).should(
|
cy.get(enactmentDeadlineError).should(
|
||||||
'have.text',
|
'have.text',
|
||||||
'Proposal will fail if enactment is earlier than the voting deadline'
|
'The proposal will fail if enactment is earlier than the voting deadline'
|
||||||
);
|
);
|
||||||
|
cy.get(proposalDownloadBtn)
|
||||||
|
.should('be.visible')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
cy.wrap(
|
||||||
|
getDownloadedProposalJsonPath('vega-network-param-proposal-')
|
||||||
|
).then((filePath) => {
|
||||||
|
goToMakeNewProposal(governanceProposalType.RAW);
|
||||||
|
submitUniqueRawProposal({ proposalBody: filePath, submit: false });
|
||||||
|
});
|
||||||
|
});
|
||||||
cy.get(newProposalSubmitButton).click();
|
cy.get(newProposalSubmitButton).click();
|
||||||
cy.get(feedbackError).should(
|
validateFeedBackMsg(
|
||||||
'have.text',
|
|
||||||
'Invalid params: proposal_submission.terms.closing_timestamp (cannot be after enactment time)'
|
'Invalid params: proposal_submission.terms.closing_timestamp (cannot be after enactment time)'
|
||||||
);
|
);
|
||||||
closeDialog();
|
|
||||||
cy.get(minVoteDeadline).click();
|
|
||||||
cy.get(enactmentDeadlineError).should('not.exist');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 3003-PMAN-001
|
// 3003-PMAN-001
|
||||||
it('Able to submit valid new market proposal', function () {
|
it(
|
||||||
goToMakeNewProposal(governanceProposalType.NEW_MARKET);
|
'Able to submit valid new market proposal',
|
||||||
cy.get(newProposalTitle).type('Test new market proposal');
|
{ tags: '@smoke' },
|
||||||
cy.get(newProposalDescription).type('E2E test for proposals');
|
function () {
|
||||||
cy.fixture('/proposals/new-market').then((newMarketProposal) => {
|
const proposalTitle = 'Test new market proposal';
|
||||||
const newMarketPayload = JSON.stringify(newMarketProposal);
|
goToMakeNewProposal(governanceProposalType.NEW_MARKET);
|
||||||
cy.get(newProposalTerms).type(newMarketPayload, {
|
cy.get(newProposalTitle).type('Test new market proposal');
|
||||||
parseSpecialCharSequences: false,
|
cy.get(newProposalDescription).type('E2E test for proposals');
|
||||||
delay: 2,
|
cy.fixture('/proposals/new-market').then((newMarketProposal) => {
|
||||||
|
const newMarketPayload = JSON.stringify(newMarketProposal);
|
||||||
|
cy.get(newProposalTerms).type(newMarketPayload, {
|
||||||
|
parseSpecialCharSequences: false,
|
||||||
|
delay: 2,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
cy.get(proposalDownloadBtn)
|
||||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
.should('be.visible')
|
||||||
waitForProposalSubmitted();
|
.click()
|
||||||
});
|
.then(() => {
|
||||||
|
cy.wrap(
|
||||||
|
getDownloadedProposalJsonPath('vega-new-market-proposal-')
|
||||||
|
).then((filePath) => {
|
||||||
|
goToMakeNewProposal(governanceProposalType.RAW);
|
||||||
|
submitUniqueRawProposal({ proposalBody: filePath }); // 3003-PMAN-003
|
||||||
|
});
|
||||||
|
});
|
||||||
|
navigateTo(navigation.proposals);
|
||||||
|
getProposalFromTitle(proposalTitle).within(() =>
|
||||||
|
cy.getByTestId('view-proposal-btn').click()
|
||||||
|
);
|
||||||
|
cy.getByTestId('proposal-market-data').within(() => {
|
||||||
|
cy.getByTestId('proposal-market-data-toggle').click();
|
||||||
|
cy.contains('Key details').click();
|
||||||
|
getMarketProposalDetailsFromTable('Name').should(
|
||||||
|
'have.text',
|
||||||
|
'Token test market'
|
||||||
|
);
|
||||||
|
cy.contains('Settlement asset').click();
|
||||||
|
// Settlement asset symbol
|
||||||
|
cy.getByTestId('3_value').should('have.text', 'fBTC');
|
||||||
|
cy.contains('Oracle').click();
|
||||||
|
cy.getByTestId('oracle-spec-links').should('have.attr', 'href');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
it('Unable to submit new market proposal with missing/invalid fields', function () {
|
it('Unable to submit new market proposal with missing/invalid fields', function () {
|
||||||
const errorMsg =
|
const errorMsg =
|
||||||
'Invalid params: the transaction does not use a valid Vega command: unknown field "invalid" in vega.NewMarket';
|
'Invalid params: the transaction does not use a valid Vega command: unknown field "invalid" in vega.NewMarket';
|
||||||
|
|
||||||
goToMakeNewProposal(governanceProposalType.NEW_MARKET);
|
goToMakeNewProposal(governanceProposalType.NEW_MARKET);
|
||||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
cy.get(proposalDownloadBtn).should('be.visible').click();
|
||||||
cy.get(inputError).should('have.length', 3);
|
cy.get(inputError).should('have.length', 3);
|
||||||
cy.get(newProposalTitle).type('Test new market proposal');
|
cy.get(newProposalTitle).type('Test new market proposal');
|
||||||
cy.get(newProposalDescription).type('E2E test for proposals');
|
cy.get(newProposalDescription).type('E2E test for proposals');
|
||||||
@@ -238,14 +271,27 @@ context(
|
|||||||
delay: 2,
|
delay: 2,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
cy.get(proposalDownloadBtn)
|
||||||
|
.should('be.visible')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
cy.wrap(
|
||||||
|
getDownloadedProposalJsonPath('vega-new-market-proposal-')
|
||||||
|
).then((filePath) => {
|
||||||
|
goToMakeNewProposal(governanceProposalType.RAW);
|
||||||
|
submitUniqueRawProposal({ proposalBody: filePath, submit: false });
|
||||||
|
});
|
||||||
|
});
|
||||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||||
cy.contains('Transaction failed', proposalTimeout).should('be.visible');
|
cy.contains('Transaction failed', proposalTimeout).should('be.visible');
|
||||||
cy.get(feedbackError).should('have.text', errorMsg);
|
validateFeedBackMsg(errorMsg);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Will fail if run after 'Able to submit update market proposal and vote for proposal'
|
// Will fail if run after 'Able to submit update market proposal and vote for proposal'
|
||||||
// 3002-PROP-022
|
// 3002-PROP-022
|
||||||
it('Unable to submit update market proposal without equity-like share in the market', function () {
|
it('Unable to submit update market proposal without equity-like share in the market', function () {
|
||||||
|
switchVegaWalletPubKey();
|
||||||
|
stakingPageAssociateTokens('1');
|
||||||
goToMakeNewProposal(governanceProposalType.UPDATE_MARKET);
|
goToMakeNewProposal(governanceProposalType.UPDATE_MARKET);
|
||||||
cy.get(newProposalTitle).type('Test update market proposal - rejected');
|
cy.get(newProposalTitle).type('Test update market proposal - rejected');
|
||||||
cy.get(newProposalDescription).type('E2E test for proposals');
|
cy.get(newProposalDescription).type('E2E test for proposals');
|
||||||
@@ -257,12 +303,24 @@ context(
|
|||||||
delay: 2,
|
delay: 2,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
cy.get(proposalDownloadBtn)
|
||||||
|
.should('be.visible')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
cy.wrap(
|
||||||
|
getDownloadedProposalJsonPath('vega-update-market-proposal-')
|
||||||
|
).then((filePath) => {
|
||||||
|
goToMakeNewProposal(governanceProposalType.RAW);
|
||||||
|
submitUniqueRawProposal({ proposalBody: filePath, submit: false });
|
||||||
|
});
|
||||||
|
});
|
||||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||||
cy.contains('Proposal rejected', proposalTimeout).should('be.visible');
|
cy.contains('Proposal rejected', proposalTimeout).should('be.visible');
|
||||||
cy.getByTestId('dialog-content')
|
validateDialogContentMsg('PROPOSAL_ERROR_INSUFFICIENT_EQUITY_LIKE_SHARE');
|
||||||
.find('p')
|
closeDialog();
|
||||||
.should('have.text', 'PROPOSAL_ERROR_INSUFFICIENT_EQUITY_LIKE_SHARE');
|
ethereumWalletConnect();
|
||||||
ensureSpecifiedUnstakedTokensAreAssociated('1');
|
stakingPageDisassociateAllTokens();
|
||||||
|
switchVegaWalletPubKey();
|
||||||
});
|
});
|
||||||
|
|
||||||
// 3002-PROP-020
|
// 3002-PROP-020
|
||||||
@@ -284,15 +342,25 @@ context(
|
|||||||
delay: 2,
|
delay: 2,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
cy.get(proposalDownloadBtn)
|
||||||
|
.should('be.visible')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
cy.wrap(
|
||||||
|
getDownloadedProposalJsonPath('vega-update-market-proposal-')
|
||||||
|
).then((filePath) => {
|
||||||
|
goToMakeNewProposal(governanceProposalType.RAW);
|
||||||
|
submitUniqueRawProposal({ proposalBody: filePath, submit: false });
|
||||||
|
});
|
||||||
|
});
|
||||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||||
cy.contains('Transaction failed', proposalTimeout).should('be.visible');
|
cy.contains('Transaction failed', proposalTimeout).should('be.visible');
|
||||||
cy.get(feedbackError).should(
|
validateFeedBackMsg(
|
||||||
'have.text',
|
|
||||||
'Network error: the network blocked the transaction through the spam protection: party has insufficient associated governance tokens in their staking account to submit proposal request (ABCI code 89)'
|
'Network error: the network blocked the transaction through the spam protection: party has insufficient associated governance tokens in their staking account to submit proposal request (ABCI code 89)'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 3001-VOTE-092 3004-PMAC-001
|
// 3001-VOTE-092 3004-PMAC-001 3004-PMAC-003
|
||||||
it('Able to submit update market proposal and vote for proposal', function () {
|
it('Able to submit update market proposal and vote for proposal', function () {
|
||||||
vegaWalletFaucetAssetsWithoutCheck(
|
vegaWalletFaucetAssetsWithoutCheck(
|
||||||
fUSDCId,
|
fUSDCId,
|
||||||
@@ -322,11 +390,20 @@ context(
|
|||||||
delay: 2,
|
delay: 2,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
cy.get(proposalDownloadBtn)
|
||||||
waitForProposalSubmitted();
|
.should('be.visible')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
cy.wrap(
|
||||||
|
getDownloadedProposalJsonPath('vega-update-market-proposal-')
|
||||||
|
).then((filePath) => {
|
||||||
|
goToMakeNewProposal(governanceProposalType.RAW);
|
||||||
|
submitUniqueRawProposal({ proposalBody: filePath });
|
||||||
|
});
|
||||||
|
});
|
||||||
navigateTo(navigation.proposals);
|
navigateTo(navigation.proposals);
|
||||||
cy.get('@EnactedMarketId').then((marketId) => {
|
cy.get('@EnactedMarketId').then((marketId) => {
|
||||||
cy.contains(String(marketId))
|
cy.contains(String(marketId).slice(0, 6))
|
||||||
.parentsUntil(proposalListItem)
|
.parentsUntil(proposalListItem)
|
||||||
.last()
|
.last()
|
||||||
.within(() => {
|
.within(() => {
|
||||||
@@ -350,12 +427,13 @@ context(
|
|||||||
'contain.text',
|
'contain.text',
|
||||||
'Currently expected to pass'
|
'Currently expected to pass'
|
||||||
);
|
);
|
||||||
|
cy.getByTestId('vote-breakdown-toggle').click();
|
||||||
getProposalInformationFromTable('Expected to pass')
|
getProposalInformationFromTable('Expected to pass')
|
||||||
.contains('👍 by token vote')
|
.contains('👍 by token vote')
|
||||||
.should('be.visible');
|
.should('be.visible');
|
||||||
});
|
});
|
||||||
|
|
||||||
// 3001-VOTE-026 3001-VOTE-027 3001-VOTE-028 3001-VOTE-095 3001-VOTE-096 3005-PASN-001
|
// 3001-VOTE-026 3001-VOTE-027 3001-VOTE-028 3001-VOTE-095 3001-VOTE-096 3005-PASN-001
|
||||||
it('Able to submit new asset proposal using min deadlines', function () {
|
it('Able to submit new asset proposal using min deadlines', function () {
|
||||||
const proposalTitle = 'Test new asset proposal';
|
const proposalTitle = 'Test new asset proposal';
|
||||||
goToMakeNewProposal(governanceProposalType.NEW_ASSET);
|
goToMakeNewProposal(governanceProposalType.NEW_ASSET);
|
||||||
@@ -371,25 +449,23 @@ context(
|
|||||||
cy.get(minVoteDeadline).click();
|
cy.get(minVoteDeadline).click();
|
||||||
cy.get(minValidationDeadline).click();
|
cy.get(minValidationDeadline).click();
|
||||||
cy.get(minEnactDeadline).click();
|
cy.get(minEnactDeadline).click();
|
||||||
|
cy.get(proposalDownloadBtn)
|
||||||
|
.should('be.visible')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
cy.wrap(
|
||||||
|
getDownloadedProposalJsonPath('vega-new-asset-proposal-')
|
||||||
|
).then((filePath) => {
|
||||||
|
goToMakeNewProposal(governanceProposalType.RAW);
|
||||||
|
submitUniqueRawProposal({ proposalBody: filePath, submit: false }); // 3005-PASN-003
|
||||||
|
});
|
||||||
|
});
|
||||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
|
||||||
'be.visible'
|
|
||||||
);
|
|
||||||
cy.contains('Proposal waiting for node vote', proposalTimeout).should(
|
|
||||||
'be.visible'
|
|
||||||
);
|
|
||||||
closeDialog();
|
closeDialog();
|
||||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||||
// cannot submit a proposal with ERC20 address already in use
|
// cannot submit a proposal with ERC20 address already in use
|
||||||
cy.contains('Proposal rejected', proposalTimeout).should('be.visible');
|
cy.contains('Proposal rejected', proposalTimeout).should('be.visible');
|
||||||
cy.getByTestId('dialog-content')
|
validateDialogContentMsg('PROPOSAL_ERROR_ERC20_ADDRESS_ALREADY_IN_USE');
|
||||||
.last()
|
|
||||||
.within(() => {
|
|
||||||
cy.get('p').should(
|
|
||||||
'have.text',
|
|
||||||
'PROPOSAL_ERROR_ERC20_ADDRESS_ALREADY_IN_USE'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
closeDialog();
|
closeDialog();
|
||||||
navigateTo(navigation.proposals);
|
navigateTo(navigation.proposals);
|
||||||
cy.contains(proposalTitle)
|
cy.contains(proposalTitle)
|
||||||
@@ -398,7 +474,8 @@ context(
|
|||||||
.within(() => {
|
.within(() => {
|
||||||
cy.getByTestId(viewProposalBtn).click();
|
cy.getByTestId(viewProposalBtn).click();
|
||||||
});
|
});
|
||||||
cy.getByTestId(proposalTermsSection).within(() => {
|
cy.getByTestId(proposalJsonToggle).click();
|
||||||
|
cy.getByTestId(proposalJsonSection).within(() => {
|
||||||
cy.contains('USDT Coin').should('be.visible');
|
cy.contains('USDT Coin').should('be.visible');
|
||||||
cy.contains('USDT').should('be.visible');
|
cy.contains('USDT').should('be.visible');
|
||||||
});
|
});
|
||||||
@@ -406,15 +483,8 @@ context(
|
|||||||
|
|
||||||
it('Unable to submit new asset proposal with missing/invalid fields', function () {
|
it('Unable to submit new asset proposal with missing/invalid fields', function () {
|
||||||
goToMakeNewProposal(governanceProposalType.NEW_ASSET);
|
goToMakeNewProposal(governanceProposalType.NEW_ASSET);
|
||||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
cy.get(proposalDownloadBtn).should('be.visible').click();
|
||||||
cy.get(inputError).should('have.length', 3);
|
cy.get(inputError).should('have.length', 3);
|
||||||
cy.get(newProposalTitle).type('Invalid new asset proposal');
|
|
||||||
cy.get(newProposalDescription).type('Invalid E2E test for proposals');
|
|
||||||
cy.get(proposalValidationDeadline).clear().type('2');
|
|
||||||
cy.get(newProposalSubmitButton).click();
|
|
||||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
|
||||||
'not.exist'
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Able to submit update asset proposal using min deadline', function () {
|
it('Able to submit update asset proposal using min deadline', function () {
|
||||||
@@ -425,8 +495,17 @@ context(
|
|||||||
enterUpdateAssetProposalDetails();
|
enterUpdateAssetProposalDetails();
|
||||||
cy.get(minVoteDeadline).click();
|
cy.get(minVoteDeadline).click();
|
||||||
cy.get(minEnactDeadline).click();
|
cy.get(minEnactDeadline).click();
|
||||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
cy.get(proposalDownloadBtn)
|
||||||
waitForProposalSubmitted();
|
.should('be.visible')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
cy.wrap(
|
||||||
|
getDownloadedProposalJsonPath('vega-update-asset-proposal-')
|
||||||
|
).then((filePath) => {
|
||||||
|
goToMakeNewProposal(governanceProposalType.RAW);
|
||||||
|
submitUniqueRawProposal({ proposalBody: filePath });
|
||||||
|
});
|
||||||
|
});
|
||||||
navigateTo(navigation.proposals);
|
navigateTo(navigation.proposals);
|
||||||
cy.get(openProposals).within(() => {
|
cy.get(openProposals).within(() => {
|
||||||
cy.get(proposalType)
|
cy.get(proposalType)
|
||||||
@@ -434,7 +513,7 @@ context(
|
|||||||
.parentsUntil(proposalListItem)
|
.parentsUntil(proposalListItem)
|
||||||
.last()
|
.last()
|
||||||
.within(() => {
|
.within(() => {
|
||||||
cy.get(proposalDetails).should('contain.text', assetId); // 3001-VOTE-029
|
cy.get(proposalDetails).should('contain.text', assetId.slice(0, 6)); // 3001-VOTE-029
|
||||||
cy.getByTestId(viewProposalBtn).click();
|
cy.getByTestId(viewProposalBtn).click();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -442,37 +521,95 @@ context(
|
|||||||
.invoke('text')
|
.invoke('text')
|
||||||
.should('not.be.empty');
|
.should('not.be.empty');
|
||||||
// 3001-VOTE-030 3001-VOTE-031
|
// 3001-VOTE-030 3001-VOTE-031
|
||||||
cy.getByTestId(proposalTermsSection).within(() => {
|
cy.getByTestId(proposalJsonToggle).click();
|
||||||
cy.contains('UpdateAsset').should('be.visible');
|
cy.getByTestId(proposalJsonSection).within(() => {
|
||||||
cy.contains('UpdateERC20').should('be.visible');
|
cy.contains(assetId).should('be.visible');
|
||||||
cy.contains('"lifetimeLimit": "10"').should('be.visible');
|
cy.contains('lifetimeLimit').should('be.visible');
|
||||||
|
cy.contains('10').should('be.visible');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 3006-PASC-001 3006-PASC-003
|
||||||
it('Able to submit update asset proposal using max deadline', function () {
|
it('Able to submit update asset proposal using max deadline', function () {
|
||||||
goToMakeNewProposal(governanceProposalType.UPDATE_ASSET);
|
goToMakeNewProposal(governanceProposalType.UPDATE_ASSET);
|
||||||
enterUpdateAssetProposalDetails();
|
enterUpdateAssetProposalDetails();
|
||||||
cy.get(maxVoteDeadline).click();
|
cy.get(maxVoteDeadline).click();
|
||||||
cy.get(maxEnactDeadline).click();
|
cy.get(maxEnactDeadline).click();
|
||||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
cy.get(proposalDownloadBtn)
|
||||||
waitForProposalSubmitted();
|
.should('be.visible')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
cy.wrap(
|
||||||
|
getDownloadedProposalJsonPath('vega-update-asset-proposal-')
|
||||||
|
).then((filePath) => {
|
||||||
|
goToMakeNewProposal(governanceProposalType.RAW);
|
||||||
|
submitUniqueRawProposal({ proposalBody: filePath });
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Unable to submit edit asset proposal with missing/invalid fields', function () {
|
it('Unable to submit edit asset proposal with missing/invalid fields', function () {
|
||||||
goToMakeNewProposal(governanceProposalType.UPDATE_ASSET);
|
goToMakeNewProposal(governanceProposalType.UPDATE_ASSET);
|
||||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
cy.get(proposalDownloadBtn).should('be.visible').click();
|
||||||
cy.get(inputError).should('have.length', 3);
|
cy.get(inputError).should('have.length', 3);
|
||||||
});
|
});
|
||||||
|
|
||||||
function getFormattedTime() {
|
it('Able to download and submit freeform proposal', function () {
|
||||||
const now = new Date();
|
goToMakeNewProposal(governanceProposalType.FREEFORM);
|
||||||
const day = now.getDate().toString().padStart(2, '0');
|
// 3008-PFRO-006
|
||||||
const month = now.toLocaleString('en-US', { month: 'short' });
|
cy.get(newProposalTitle)
|
||||||
const year = now.getFullYear().toString();
|
.siblings()
|
||||||
const hours = now.getHours().toString().padStart(2, '0');
|
.should('contain.text', '(100 characters or less)'); // 3008-PFRO-007
|
||||||
const minutes = now.getMinutes().toString().padStart(2, '0');
|
// 3008-PFRO-005
|
||||||
|
cy.get(newProposalTitle).type('Test freeform proposal form');
|
||||||
|
// 3008-PFRO-009
|
||||||
|
cy.get(newProposalDescription)
|
||||||
|
.siblings()
|
||||||
|
.should('contain.text', '(20,000 characters or less)'); // 3008-PFRO-010
|
||||||
|
// 3008-PFRO-008 3002-PROP-012 3002-PROP-016
|
||||||
|
cy.get(newProposalDescription).type(
|
||||||
|
'E2E test for downloading freeform proposal'
|
||||||
|
);
|
||||||
|
// 3008-PFRO-012
|
||||||
|
cy.get(minVoteDeadline).should('exist'); // 3002-PROP-008
|
||||||
|
cy.get(maxVoteDeadline).should('exist');
|
||||||
|
// 3008-PFRO-011
|
||||||
|
cy.get(proposalVoteDeadline).clear().type('2');
|
||||||
|
// 3008-PFRO-013 3008-PFRO-014
|
||||||
|
cy.getByTestId('voting-date').invoke('text').should('not.be.empty');
|
||||||
|
// 3008-PFRO-015
|
||||||
|
cy.log('Download updated proposal file');
|
||||||
|
cy.get(proposalDownloadBtn)
|
||||||
|
.should('be.visible')
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
cy.wrap(
|
||||||
|
getDownloadedProposalJsonPath('vega-freeform-proposal-')
|
||||||
|
).then((filePath) => {
|
||||||
|
// 3008-PFRO-019
|
||||||
|
goToMakeNewProposal(governanceProposalType.RAW);
|
||||||
|
submitUniqueRawProposal({ proposalBody: filePath });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
return `${day}-${month}-${year}-${hours}-${minutes}`;
|
after('Disassociate from second wallet key if present', function () {
|
||||||
|
cy.reload();
|
||||||
|
waitForSpinner();
|
||||||
|
ethereumWalletConnect();
|
||||||
|
dissociateFromSecondWalletKey();
|
||||||
|
});
|
||||||
|
|
||||||
|
function validateDialogContentMsg(expectedMsg: string) {
|
||||||
|
cy.getByTestId('dialog-content')
|
||||||
|
.last()
|
||||||
|
.within(() => {
|
||||||
|
cy.get('p').should('have.text', expectedMsg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateFeedBackMsg(expectedMsg: string) {
|
||||||
|
cy.get(feedbackError).should('have.text', expectedMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
function enterUpdateAssetProposalDetails() {
|
function enterUpdateAssetProposalDetails() {
|
||||||
@@ -486,5 +623,13 @@ context(
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getMarketProposalDetailsFromTable(heading: string) {
|
||||||
|
return cy
|
||||||
|
.getByTestId('key-value-table-row')
|
||||||
|
.contains(heading)
|
||||||
|
.parent()
|
||||||
|
.siblings();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,28 +6,31 @@ import {
|
|||||||
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,
|
||||||
} from '../../support/governance.functions';
|
} from '../../support/governance.functions';
|
||||||
import { ensureSpecifiedUnstakedTokensAreAssociated } from '../../support/staking.functions';
|
import { ensureSpecifiedUnstakedTokensAreAssociated } from '../../support/staking.functions';
|
||||||
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-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 () {
|
||||||
@@ -60,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');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -73,36 +76,28 @@ 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 = 'src/fixtures/proposals/new-market-raw.json';
|
||||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
const proposalTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(3);
|
||||||
getProposalIdFromList(rawProposal.rationale.title);
|
submitUniqueRawProposal({
|
||||||
cy.get('@proposalIdText').then((proposalId) => {
|
proposalBody: proposalPath,
|
||||||
cy.get(openProposals).within(() => {
|
enactmentTimestamp: proposalTimestamp,
|
||||||
// 3001-VOTE-008
|
closingTimestamp: proposalTimestamp,
|
||||||
// 3001-VOTE-034
|
}); // 3001-VOTE-052
|
||||||
cy.get(`#${proposalId}`)
|
// 3001-VOTE-008
|
||||||
// 3001-VOTE-097
|
// 3001-VOTE-034
|
||||||
.should('contain', rawProposal.rationale.title)
|
// 3001-VOTE-097
|
||||||
.and('be.visible');
|
cy.contains('New Market Proposal E2E submission');
|
||||||
cy.get(`#${proposalId}`)
|
cy.contains('Code: TEST.24h. fBTC settled future.').should('be.visible');
|
||||||
.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 () {
|
||||||
@@ -110,23 +105,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');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -134,18 +117,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');
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import {
|
|||||||
import {
|
import {
|
||||||
clickOnValidatorFromList,
|
clickOnValidatorFromList,
|
||||||
closeStakingDialog,
|
closeStakingDialog,
|
||||||
stakingPageAssociateTokens,
|
|
||||||
stakingValidatorPageAddStake,
|
stakingValidatorPageAddStake,
|
||||||
waitForBeginningOfEpoch,
|
waitForBeginningOfEpoch,
|
||||||
} from '../../support/staking.functions';
|
} from '../../support/staking.functions';
|
||||||
@@ -15,7 +14,7 @@ import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
|
|||||||
import {
|
import {
|
||||||
depositAsset,
|
depositAsset,
|
||||||
vegaWalletTeardown,
|
vegaWalletTeardown,
|
||||||
} from '../../support/wallet-teardown.functions';
|
} from '../../support/wallet-functions';
|
||||||
|
|
||||||
const vegaAssetAddress = '0x67175Da1D5e966e40D11c4B2519392B2058373de';
|
const vegaAssetAddress = '0x67175Da1D5e966e40D11c4B2519392B2058373de';
|
||||||
const vegaWalletUnstakedBalance =
|
const vegaWalletUnstakedBalance =
|
||||||
@@ -30,20 +29,22 @@ context('rewards - flow', { tags: '@slow' }, function () {
|
|||||||
turnTelemetryOff();
|
turnTelemetryOff();
|
||||||
cy.visit('/');
|
cy.visit('/');
|
||||||
waitForSpinner();
|
waitForSpinner();
|
||||||
depositAsset(vegaAssetAddress, '1000', 18);
|
|
||||||
cy.validatorsSelfDelegate();
|
|
||||||
ethereumWalletConnect();
|
ethereumWalletConnect();
|
||||||
cy.connectVegaWallet();
|
cy.connectVegaWallet();
|
||||||
cy.VegaWalletTopUpRewardsPool(30, 200);
|
depositAsset(vegaAssetAddress, '1000', 18);
|
||||||
navigateTo(navigation.validators);
|
cy.getByTestId('currency-title', txTimeout).should(
|
||||||
|
'contain.text',
|
||||||
|
'Collateral'
|
||||||
|
);
|
||||||
vegaWalletTeardown();
|
vegaWalletTeardown();
|
||||||
stakingPageAssociateTokens('6000');
|
cy.associateTokensToVegaWallet('6000');
|
||||||
|
navigateTo(navigation.validators);
|
||||||
|
cy.VegaWalletTopUpRewardsPool();
|
||||||
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
|
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
|
||||||
'contain',
|
'contain',
|
||||||
'6,000.0',
|
'6,000.0',
|
||||||
txTimeout
|
txTimeout
|
||||||
);
|
);
|
||||||
cy.get('button').contains('Select a validator to nominate').click();
|
|
||||||
clickOnValidatorFromList(0);
|
clickOnValidatorFromList(0);
|
||||||
stakingValidatorPageAddStake('3000');
|
stakingValidatorPageAddStake('3000');
|
||||||
closeStakingDialog();
|
closeStakingDialog();
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
|
|||||||
import {
|
import {
|
||||||
vegaWalletSetSpecifiedApprovalAmount,
|
vegaWalletSetSpecifiedApprovalAmount,
|
||||||
vegaWalletTeardown,
|
vegaWalletTeardown,
|
||||||
} from '../../support/wallet-teardown.functions';
|
} from '../../support/wallet-functions';
|
||||||
const stakeValidatorListTotalStake = 'total-stake';
|
const stakeValidatorListTotalStake = 'total-stake';
|
||||||
const stakeValidatorListTotalShare = 'total-stake-share';
|
const stakeValidatorListTotalShare = 'total-stake-share';
|
||||||
const stakeValidatorListStakePercentage = 'stake-percentage';
|
const stakeValidatorListStakePercentage = 'stake-percentage';
|
||||||
@@ -54,12 +54,10 @@ context(
|
|||||||
'Staking Tab - with eth and vega wallets connected',
|
'Staking Tab - with eth and vega wallets connected',
|
||||||
{ tags: '@slow' },
|
{ tags: '@slow' },
|
||||||
function () {
|
function () {
|
||||||
// 2001-STKE-002, 2001-STKE-032
|
// 1002-STKE-002, 1002-STKE-032
|
||||||
before('visit staking tab and connect vega wallet', function () {
|
before('visit staking tab and connect vega wallet', function () {
|
||||||
cy.visit('/');
|
cy.visit('/');
|
||||||
ethereumWalletConnect();
|
ethereumWalletConnect();
|
||||||
// this is a workaround for #2422 which can be removed once issue is resolved
|
|
||||||
cy.associateTokensToVegaWallet('4');
|
|
||||||
vegaWalletSetSpecifiedApprovalAmount('1000');
|
vegaWalletSetSpecifiedApprovalAmount('1000');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -77,26 +75,42 @@ context(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 1002-STKE-035 1002-STKE-036
|
||||||
|
it('Unable to stake against a validator with less than minimum and more than associated amount', function () {
|
||||||
|
ensureSpecifiedUnstakedTokensAreAssociated('3');
|
||||||
|
verifyUnstakedBalance(3.0);
|
||||||
|
verifyEthWalletTotalAssociatedBalance('3.0');
|
||||||
|
verifyEthWalletAssociatedBalance('3.0');
|
||||||
|
cy.get('button').contains('Select a validator to nominate').click();
|
||||||
|
clickOnValidatorFromList(0);
|
||||||
|
cy.getByTestId(stakeAddStakeRadioButton, epochTimeout).click({
|
||||||
|
force: true,
|
||||||
|
});
|
||||||
|
cy.getByTestId(stakeTokenAmountInputBox).type('0.001');
|
||||||
|
cy.getByTestId(stakeTokenSubmitButton).should('be.disabled');
|
||||||
|
cy.getByTestId(stakeTokenAmountInputBox).clear().type('4');
|
||||||
|
cy.getByTestId(stakeTokenSubmitButton).should('be.disabled');
|
||||||
|
});
|
||||||
it('Able to stake against a validator - using vega from wallet', function () {
|
it('Able to stake against a validator - using vega from wallet', function () {
|
||||||
ensureSpecifiedUnstakedTokensAreAssociated('3');
|
ensureSpecifiedUnstakedTokensAreAssociated('3');
|
||||||
verifyUnstakedBalance(3.0);
|
verifyUnstakedBalance(3.0);
|
||||||
verifyEthWalletTotalAssociatedBalance('3.0');
|
verifyEthWalletTotalAssociatedBalance('3.0');
|
||||||
verifyEthWalletAssociatedBalance('3.0');
|
verifyEthWalletAssociatedBalance('3.0');
|
||||||
cy.get('button').contains('Select a validator to nominate').click();
|
cy.get('button').contains('Select a validator to nominate').click();
|
||||||
// 2001-STKE-031
|
// 1002-STKE-031
|
||||||
clickOnValidatorFromList(0);
|
clickOnValidatorFromList(0);
|
||||||
// 2001-STKE-033, 2001-STKE-034, 2001-STKE-037
|
// 1002-STKE-033, 1002-STKE-034, 1002-STKE-037
|
||||||
stakingValidatorPageAddStake('2');
|
stakingValidatorPageAddStake('2');
|
||||||
verifyUnstakedBalance(1.0);
|
verifyUnstakedBalance(1.0);
|
||||||
// 2001-STKE-039
|
// 1002-STKE-039
|
||||||
verifyStakedBalance(2.0);
|
verifyStakedBalance(2.0);
|
||||||
verifyNextEpochValue(2.0); // 2001-STKE-016 2001-STKE-038
|
verifyNextEpochValue(2.0); // 1002-STKE-016 1002-STKE-038
|
||||||
verifyThisEpochValue(2.0); // 2001-STKE-013
|
verifyThisEpochValue(2.0); // 1002-STKE-013
|
||||||
closeStakingDialog();
|
closeStakingDialog();
|
||||||
navigateTo(navigation.validators);
|
navigateTo(navigation.validators);
|
||||||
|
|
||||||
// 2002-SINC-007
|
// 2002-SINC-007 1002-STKE-015 1002-STKE-017 1002-STKE-052
|
||||||
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 () {
|
||||||
@@ -109,6 +123,7 @@ context(
|
|||||||
cy.getByTestId(userStake, epochTimeout)
|
cy.getByTestId(userStake, epochTimeout)
|
||||||
.first()
|
.first()
|
||||||
.should('have.text', '2.00');
|
.should('have.text', '2.00');
|
||||||
|
waitForBeginningOfEpoch();
|
||||||
cy.getByTestId('total-stake').first().realHover();
|
cy.getByTestId('total-stake').first().realHover();
|
||||||
cy.getByTestId('staked-by-user-tooltip')
|
cy.getByTestId('staked-by-user-tooltip')
|
||||||
.first()
|
.first()
|
||||||
@@ -146,7 +161,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 () {
|
||||||
@@ -166,10 +181,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();
|
||||||
@@ -197,14 +213,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}"]`)
|
||||||
@@ -212,19 +224,15 @@ 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');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// 2001-STKE-041
|
// 1002-STKE-041 1002-STKE-053
|
||||||
it(
|
it(
|
||||||
'Able to remove part of a stake against a validator',
|
'Able to remove part of a stake against a validator',
|
||||||
{ tags: '@smoke' },
|
{ tags: '@smoke' },
|
||||||
@@ -237,11 +245,11 @@ context(
|
|||||||
verifyUnstakedBalance(1.0);
|
verifyUnstakedBalance(1.0);
|
||||||
closeStakingDialog();
|
closeStakingDialog();
|
||||||
navigateTo(navigation.validators);
|
navigateTo(navigation.validators);
|
||||||
// 2001-STKE-040
|
// 1002-STKE-040
|
||||||
clickOnValidatorFromList(0);
|
clickOnValidatorFromList(0);
|
||||||
// 2001-STKE-044, 2001-STKE-048
|
// 1002-STKE-044, 1002-STKE-048
|
||||||
stakingValidatorPageRemoveStake('1');
|
stakingValidatorPageRemoveStake('1');
|
||||||
// 2001-STKE-049
|
// 1002-STKE-049
|
||||||
verifyNextEpochValue(2.0);
|
verifyNextEpochValue(2.0);
|
||||||
verifyUnstakedBalance(2.0);
|
verifyUnstakedBalance(2.0);
|
||||||
verifyStakedBalance(2.0);
|
verifyStakedBalance(2.0);
|
||||||
@@ -261,7 +269,7 @@ context(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// 2001-STKE-045
|
// 1002-STKE-045
|
||||||
it('Able to remove a full stake against a validator', function () {
|
it('Able to remove a full stake against a validator', function () {
|
||||||
stakingPageAssociateTokens('3');
|
stakingPageAssociateTokens('3');
|
||||||
verifyUnstakedBalance(3.0);
|
verifyUnstakedBalance(3.0);
|
||||||
@@ -282,7 +290,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');
|
||||||
@@ -309,6 +317,7 @@ context(
|
|||||||
.and('be.visible');
|
.and('be.visible');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 1002-STKE-046 1002-STKE-047
|
||||||
it('Unable to remove a stake greater than staked amount next epoch for a validator', function () {
|
it('Unable to remove a stake greater than staked amount next epoch for a validator', function () {
|
||||||
stakingPageAssociateTokens('3');
|
stakingPageAssociateTokens('3');
|
||||||
verifyUnstakedBalance(3.0);
|
verifyUnstakedBalance(3.0);
|
||||||
@@ -354,7 +363,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 () {
|
||||||
@@ -382,10 +391,13 @@ 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 () {
|
||||||
|
vegaWalletSetSpecifiedApprovalAmount('1000');
|
||||||
|
cy.reload();
|
||||||
|
ethereumWalletConnect();
|
||||||
stakingPageAssociateTokens('3');
|
stakingPageAssociateTokens('3');
|
||||||
verifyUnstakedBalance(3.0);
|
verifyUnstakedBalance(3.0);
|
||||||
cy.get('button').contains('Select a validator to nominate').click();
|
cy.get('button').contains('Select a validator to nominate').click();
|
||||||
@@ -404,11 +416,11 @@ 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 () {
|
||||||
// 2001-STKE-004
|
// 1002-STKE-004
|
||||||
stakingPageAssociateTokens('3');
|
stakingPageAssociateTokens('3');
|
||||||
verifyUnstakedBalance(3.0);
|
verifyUnstakedBalance(3.0);
|
||||||
cy.get('button').contains('Select a validator to nominate').click();
|
cy.get('button').contains('Select a validator to nominate').click();
|
||||||
@@ -422,7 +434,7 @@ context(
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Associating vesting contract tokens - when some already staked - auto stakes tokens to staked validator', function () {
|
it('Associating vesting contract tokens - when some already staked - auto stakes tokens to staked validator', function () {
|
||||||
// 2001-STKE-004
|
// 1002-STKE-004
|
||||||
stakingPageAssociateTokens('3', { type: 'contract' });
|
stakingPageAssociateTokens('3', { type: 'contract' });
|
||||||
verifyUnstakedBalance(3.0);
|
verifyUnstakedBalance(3.0);
|
||||||
cy.get('button').contains('Select a validator to nominate').click();
|
cy.get('button').contains('Select a validator to nominate').click();
|
||||||
@@ -436,7 +448,7 @@ context(
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Associating vesting contract tokens - when wallet tokens already staked - auto stakes tokens to staked validator', function () {
|
it('Associating vesting contract tokens - when wallet tokens already staked - auto stakes tokens to staked validator', function () {
|
||||||
// 2001-STKE-004
|
// 1002-STKE-004
|
||||||
stakingPageAssociateTokens('3', { type: 'wallet' });
|
stakingPageAssociateTokens('3', { type: 'wallet' });
|
||||||
verifyUnstakedBalance(3.0);
|
verifyUnstakedBalance(3.0);
|
||||||
cy.get('button').contains('Select a validator to nominate').click();
|
cy.get('button').contains('Select a validator to nominate').click();
|
||||||
@@ -450,7 +462,7 @@ context(
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Associating tokens - with multiple validators already staked - auto stakes to staked validators - abiding by existing stake ratio', function () {
|
it('Associating tokens - with multiple validators already staked - auto stakes to staked validators - abiding by existing stake ratio', function () {
|
||||||
// 2001-STKE-004
|
// 1002-STKE-004
|
||||||
stakingPageAssociateTokens('6');
|
stakingPageAssociateTokens('6');
|
||||||
verifyUnstakedBalance(6.0);
|
verifyUnstakedBalance(6.0);
|
||||||
cy.get('button').contains('Select a validator to nominate').click();
|
cy.get('button').contains('Select a validator to nominate').click();
|
||||||
@@ -492,6 +504,7 @@ context(
|
|||||||
});
|
});
|
||||||
|
|
||||||
afterEach('Teardown Wallet', function () {
|
afterEach('Teardown Wallet', function () {
|
||||||
|
navigateTo(navigation.home);
|
||||||
vegaWalletTeardown();
|
vegaWalletTeardown();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -502,7 +515,7 @@ context(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function verifyThisEpochValue(amount: number) {
|
function verifyThisEpochValue(amount: number) {
|
||||||
cy.getByTestId('stake-this-epoch', epochTimeout) // 2001-STKE-013
|
cy.getByTestId('stake-this-epoch', epochTimeout) // 1002-STKE-013
|
||||||
.contains(amount, epochTimeout)
|
.contains(amount, epochTimeout)
|
||||||
.should('be.visible');
|
.should('be.visible');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,11 +14,12 @@ import {
|
|||||||
} from '../../support/staking.functions';
|
} from '../../support/staking.functions';
|
||||||
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
|
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
|
||||||
import {
|
import {
|
||||||
|
switchVegaWalletPubKey,
|
||||||
vegaWalletAssociate,
|
vegaWalletAssociate,
|
||||||
vegaWalletDisassociate,
|
vegaWalletDisassociate,
|
||||||
vegaWalletSetSpecifiedApprovalAmount,
|
vegaWalletSetSpecifiedApprovalAmount,
|
||||||
vegaWalletTeardown,
|
vegaWalletTeardown,
|
||||||
} from '../../support/wallet-teardown.functions';
|
} from '../../support/wallet-functions';
|
||||||
|
|
||||||
const ethWalletContainer = '[data-testid="ethereum-wallet"]';
|
const ethWalletContainer = '[data-testid="ethereum-wallet"]';
|
||||||
const vegaWalletAssociatedBalance = '[data-testid="currency-value"]';
|
const vegaWalletAssociatedBalance = '[data-testid="currency-value"]';
|
||||||
@@ -38,7 +39,7 @@ const associatedKey = '[data-testid="associated-key"]';
|
|||||||
const associatedAmount = '[data-testid="associated-amount"]';
|
const associatedAmount = '[data-testid="associated-amount"]';
|
||||||
const associateCompleteText = '[data-testid="transaction-complete-body"]';
|
const associateCompleteText = '[data-testid="transaction-complete-body"]';
|
||||||
const disassociationWarning = '[data-testid="disassociation-warning"]';
|
const disassociationWarning = '[data-testid="disassociation-warning"]';
|
||||||
const vegaWallet = '[data-testid="vega-wallet"]';
|
const vegaWallet = 'aside [data-testid="vega-wallet"]';
|
||||||
|
|
||||||
context(
|
context(
|
||||||
'Token association flow - with eth and vega wallets connected',
|
'Token association flow - with eth and vega wallets connected',
|
||||||
@@ -64,46 +65,38 @@ context(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
it('Able to associate tokens - from wallet', function () {
|
it(
|
||||||
//1004-ASSO-003
|
'Able to associate tokens - from wallet',
|
||||||
//1004-ASSO-005
|
{ tags: '@smoke' },
|
||||||
//1004-ASSO-009
|
function () {
|
||||||
//1004-ASSO-030
|
//1004-ASSO-003
|
||||||
//1004-ASSO-012
|
//1004-ASSO-005
|
||||||
//1004-ASSO-013
|
//1004-ASSO-009
|
||||||
//1004-ASSO-014
|
//1004-ASSO-030
|
||||||
//1004-ASSO-015
|
//1004-ASSO-012
|
||||||
//1004-ASSO-030
|
//1004-ASSO-013
|
||||||
//0005-ETXN-006
|
//1004-ASSO-014
|
||||||
//0005-ETXN-003
|
//1004-ASSO-015
|
||||||
//0005-ETXN-005
|
//1004-ASSO-030
|
||||||
stakingPageAssociateTokens('2', { skipConfirmation: true });
|
//0005-ETXN-006
|
||||||
|
//0005-ETXN-003
|
||||||
cy.getByTestId('currency-title', txTimeout).should(
|
//0005-ETXN-005
|
||||||
'have.length.above',
|
stakingPageAssociateTokens('2', { skipConfirmation: true });
|
||||||
6
|
validateWalletCurrency('Associated', '0.00');
|
||||||
);
|
validateWalletCurrency('Pending association', '2.00');
|
||||||
validateWalletCurrency('Associated', '0.00');
|
validateWalletCurrency('Total associated after pending', '2.00');
|
||||||
validateWalletCurrency('Pending association', '2.00');
|
// 0005-ETXN-002
|
||||||
validateWalletCurrency('Total associated after pending', '2.00');
|
verifyEthWalletAssociatedBalance('2.0');
|
||||||
cy.getByTestId('currency-title', txTimeout).should('have.length', 6);
|
verifyEthWalletTotalAssociatedBalance('2.0');
|
||||||
|
cy.get(vegaWallet).within(() => {
|
||||||
// 0005-ETXN-002
|
|
||||||
verifyEthWalletAssociatedBalance('2.0');
|
|
||||||
|
|
||||||
verifyEthWalletTotalAssociatedBalance('2.0');
|
|
||||||
|
|
||||||
cy.get(vegaWallet)
|
|
||||||
.first()
|
|
||||||
.within(() => {
|
|
||||||
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
|
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
|
||||||
'contain',
|
'contain',
|
||||||
2.0
|
2.0
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
cy.get(vegaWalletUnstakedBalance, txTimeout).should('contain', 2.0);
|
||||||
cy.get(vegaWalletUnstakedBalance, txTimeout).should('contain', 2.0);
|
}
|
||||||
});
|
);
|
||||||
|
|
||||||
it('Able to disassociate all associated tokens - manually', function () {
|
it('Able to disassociate all associated tokens - manually', function () {
|
||||||
// 1004-ASSO-025
|
// 1004-ASSO-025
|
||||||
@@ -111,63 +104,48 @@ 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();
|
||||||
|
cy.getByTestId('epoch-countdown').should('be.visible');
|
||||||
stakingPageDisassociateTokens('2');
|
stakingPageDisassociateTokens('2');
|
||||||
cy.getByTestId('currency-title', txTimeout).should(
|
|
||||||
'have.length.above',
|
|
||||||
6
|
|
||||||
);
|
|
||||||
validateWalletCurrency('Associated', '2.00');
|
validateWalletCurrency('Associated', '2.00');
|
||||||
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.get(
|
||||||
cy.getByTestId('eth-wallet-associated-balances', txTimeout).should(
|
'[data-testid="eth-wallet-associated-balances"]:visible',
|
||||||
'not.exist'
|
txTimeout
|
||||||
);
|
).should('have.length', 2);
|
||||||
verifyEthWalletTotalAssociatedBalance('0.00');
|
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).within(() => {
|
||||||
.last()
|
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
|
||||||
.within(() => {
|
'contain',
|
||||||
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
|
'1,001.00'
|
||||||
'contain',
|
);
|
||||||
'1,001.00'
|
});
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Able to disassociate a partial amount of tokens currently associated', function () {
|
it('Able to disassociate a partial amount of tokens currently associated', function () {
|
||||||
stakingPageAssociateTokens('2');
|
stakingPageAssociateTokens('2');
|
||||||
cy.get(vegaWallet)
|
cy.get(vegaWallet).within(() => {
|
||||||
.first()
|
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 2.0);
|
||||||
.within(() => {
|
});
|
||||||
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
|
|
||||||
'contain',
|
|
||||||
2.0
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
cy.get('button').contains('Select a validator to nominate').click();
|
cy.get('button').contains('Select a validator to nominate').click();
|
||||||
|
cy.getByTestId('epoch-countdown').should('be.visible');
|
||||||
stakingPageDisassociateTokens('1');
|
stakingPageDisassociateTokens('1');
|
||||||
verifyEthWalletAssociatedBalance('1.0');
|
verifyEthWalletAssociatedBalance('1.0');
|
||||||
cy.get(vegaWallet)
|
cy.get(vegaWallet).within(() => {
|
||||||
.first()
|
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 1.0);
|
||||||
.within(() => {
|
});
|
||||||
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
|
|
||||||
'contain',
|
|
||||||
1.0
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Able to disassociate all tokens - using max', function () {
|
it('Able to disassociate all tokens - using max', function () {
|
||||||
@@ -175,15 +153,11 @@ context(
|
|||||||
const warningText =
|
const warningText =
|
||||||
'Warning: Any tokens that have been nominated to a node will sacrifice rewards they are due for the current epoch. If you do not wish to sacrifice these, you should remove stake from a node at the end of an epoch before disassociation.';
|
'Warning: Any tokens that have been nominated to a node will sacrifice rewards they are due for the current epoch. If you do not wish to sacrifice these, you should remove stake from a node at the end of an epoch before disassociation.';
|
||||||
stakingPageAssociateTokens('2');
|
stakingPageAssociateTokens('2');
|
||||||
cy.get(vegaWallet)
|
cy.get(vegaWallet).within(() => {
|
||||||
.first()
|
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 2.0);
|
||||||
.within(() => {
|
});
|
||||||
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
|
|
||||||
'contain',
|
|
||||||
2.0
|
|
||||||
);
|
|
||||||
});
|
|
||||||
cy.get('button').contains('Select a validator to nominate').click();
|
cy.get('button').contains('Select a validator to nominate').click();
|
||||||
|
cy.getByTestId('epoch-countdown').should('be.visible');
|
||||||
cy.get(ethWalletDissociateButton).click();
|
cy.get(ethWalletDissociateButton).click();
|
||||||
cy.get(disassociationWarning).should('contain', warningText);
|
cy.get(disassociationWarning).should('contain', warningText);
|
||||||
stakingPageDisassociateAllTokens();
|
stakingPageDisassociateAllTokens();
|
||||||
@@ -201,14 +175,9 @@ context(
|
|||||||
'not.exist'
|
'not.exist'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
cy.get(vegaWallet)
|
cy.get(vegaWallet).within(() => {
|
||||||
.first()
|
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 0.0);
|
||||||
.within(() => {
|
});
|
||||||
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
|
|
||||||
'contain',
|
|
||||||
0.0
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Able to associate and disassociate vesting contract tokens', function () {
|
it('Able to associate and disassociate vesting contract tokens', function () {
|
||||||
@@ -223,38 +192,22 @@ context(
|
|||||||
type: 'contract',
|
type: 'contract',
|
||||||
skipConfirmation: true,
|
skipConfirmation: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
cy.getByTestId('currency-title', txTimeout).should(
|
|
||||||
'have.length.above',
|
|
||||||
6
|
|
||||||
);
|
|
||||||
validateWalletCurrency('Associated', '0.00');
|
validateWalletCurrency('Associated', '0.00');
|
||||||
validateWalletCurrency('Pending association', '2.00');
|
validateWalletCurrency('Pending association', '2.00');
|
||||||
validateWalletCurrency('Total associated after pending', '2.00');
|
validateWalletCurrency('Total associated after pending', '2.00');
|
||||||
cy.getByTestId('currency-title', txTimeout).should('have.length', 6);
|
|
||||||
verifyEthWalletAssociatedBalance('2.0');
|
verifyEthWalletAssociatedBalance('2.0');
|
||||||
verifyEthWalletTotalAssociatedBalance('2.0');
|
verifyEthWalletTotalAssociatedBalance('2.0');
|
||||||
cy.get(vegaWallet)
|
cy.get(vegaWallet).within(() => {
|
||||||
.first()
|
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 2.0);
|
||||||
.within(() => {
|
});
|
||||||
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
|
|
||||||
'contain',
|
|
||||||
2.0
|
|
||||||
);
|
|
||||||
});
|
|
||||||
cy.get(vegaWalletUnstakedBalance, txTimeout).should('contain', 2.0);
|
cy.get(vegaWalletUnstakedBalance, txTimeout).should('contain', 2.0);
|
||||||
stakingPageDisassociateTokens('1', {
|
stakingPageDisassociateTokens('1', {
|
||||||
type: 'contract',
|
type: 'contract',
|
||||||
skipConfirmation: true,
|
skipConfirmation: true,
|
||||||
});
|
});
|
||||||
cy.getByTestId('currency-title', txTimeout).should(
|
|
||||||
'have.length.above',
|
|
||||||
6
|
|
||||||
);
|
|
||||||
validateWalletCurrency('Associated', '2.00');
|
validateWalletCurrency('Associated', '2.00');
|
||||||
validateWalletCurrency('Pending association', '1.00');
|
validateWalletCurrency('Pending association', '1.00');
|
||||||
validateWalletCurrency('Total associated after pending', '1.00');
|
validateWalletCurrency('Total associated after pending', '1.00');
|
||||||
cy.getByTestId('currency-title', txTimeout).should('have.length', 6);
|
|
||||||
verifyEthWalletAssociatedBalance('1.0');
|
verifyEthWalletAssociatedBalance('1.0');
|
||||||
verifyEthWalletTotalAssociatedBalance('1.0');
|
verifyEthWalletTotalAssociatedBalance('1.0');
|
||||||
});
|
});
|
||||||
@@ -266,6 +219,7 @@ context(
|
|||||||
// 1004-ASSO-022
|
// 1004-ASSO-022
|
||||||
stakingPageAssociateTokens('21', { type: 'wallet' });
|
stakingPageAssociateTokens('21', { type: 'wallet' });
|
||||||
cy.get('button').contains('Select a validator to nominate').click();
|
cy.get('button').contains('Select a validator to nominate').click();
|
||||||
|
cy.getByTestId('epoch-countdown').should('be.visible');
|
||||||
stakingPageAssociateTokens('37', { type: 'contract' });
|
stakingPageAssociateTokens('37', { type: 'contract' });
|
||||||
cy.get(vestingContractSection)
|
cy.get(vestingContractSection)
|
||||||
.first()
|
.first()
|
||||||
@@ -285,28 +239,18 @@ context(
|
|||||||
);
|
);
|
||||||
cy.get(associatedAmount, txTimeout).should('contain', 21);
|
cy.get(associatedAmount, txTimeout).should('contain', 21);
|
||||||
});
|
});
|
||||||
cy.get(vegaWallet)
|
cy.get(vegaWallet).within(() => {
|
||||||
.first()
|
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 58);
|
||||||
.within(() => {
|
});
|
||||||
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
|
|
||||||
'contain',
|
|
||||||
58
|
|
||||||
);
|
|
||||||
});
|
|
||||||
stakingPageDisassociateTokens('6', { type: 'contract' });
|
stakingPageDisassociateTokens('6', { type: 'contract' });
|
||||||
cy.get(vestingContractSection)
|
cy.get(vestingContractSection)
|
||||||
.first()
|
.first()
|
||||||
.within(() => {
|
.within(() => {
|
||||||
cy.get(associatedAmount, txTimeout).should('contain', 31);
|
cy.get(associatedAmount, txTimeout).should('contain', 31);
|
||||||
});
|
});
|
||||||
cy.get(vegaWallet)
|
cy.get(vegaWallet).within(() => {
|
||||||
.first()
|
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 52);
|
||||||
.within(() => {
|
});
|
||||||
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
|
|
||||||
'contain',
|
|
||||||
52
|
|
||||||
);
|
|
||||||
});
|
|
||||||
navigateTo(navigation.validators);
|
navigateTo(navigation.validators);
|
||||||
stakingPageDisassociateTokens('9', { type: 'wallet' });
|
stakingPageDisassociateTokens('9', { type: 'wallet' });
|
||||||
cy.get(vegaInWalletSection)
|
cy.get(vegaInWalletSection)
|
||||||
@@ -314,14 +258,9 @@ context(
|
|||||||
.within(() => {
|
.within(() => {
|
||||||
cy.get(associatedAmount, txTimeout).should('contain', 12);
|
cy.get(associatedAmount, txTimeout).should('contain', 12);
|
||||||
});
|
});
|
||||||
cy.get(vegaWallet)
|
cy.get(vegaWallet).within(() => {
|
||||||
.first()
|
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 43);
|
||||||
.within(() => {
|
});
|
||||||
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
|
|
||||||
'contain',
|
|
||||||
43
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Not able to associate more tokens than owned', function () {
|
it('Not able to associate more tokens than owned', function () {
|
||||||
@@ -338,14 +277,9 @@ context(
|
|||||||
// 1004-ASSO-004
|
// 1004-ASSO-004
|
||||||
it('Pending association outside of app is shown', function () {
|
it('Pending association outside of app is shown', function () {
|
||||||
vegaWalletAssociate('2');
|
vegaWalletAssociate('2');
|
||||||
cy.getByTestId('currency-title', txTimeout).should(
|
|
||||||
'have.length.above',
|
|
||||||
6
|
|
||||||
);
|
|
||||||
validateWalletCurrency('Associated', '0.00');
|
validateWalletCurrency('Associated', '0.00');
|
||||||
validateWalletCurrency('Pending association', '2.00');
|
validateWalletCurrency('Pending association', '2.00');
|
||||||
validateWalletCurrency('Total associated after pending', '2.00');
|
validateWalletCurrency('Total associated after pending', '2.00');
|
||||||
cy.getByTestId('currency-title', txTimeout).should('have.length', 6);
|
|
||||||
validateWalletCurrency('Associated', '2.00');
|
validateWalletCurrency('Associated', '2.00');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -354,14 +288,9 @@ context(
|
|||||||
cy.wrap(validateWalletCurrency('Associated', '2.00')).then(() => {
|
cy.wrap(validateWalletCurrency('Associated', '2.00')).then(() => {
|
||||||
vegaWalletDisassociate('2');
|
vegaWalletDisassociate('2');
|
||||||
});
|
});
|
||||||
cy.getByTestId('currency-title', txTimeout).should(
|
|
||||||
'have.length.above',
|
|
||||||
6
|
|
||||||
);
|
|
||||||
validateWalletCurrency('Associated', '2.00');
|
validateWalletCurrency('Associated', '2.00');
|
||||||
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);
|
|
||||||
validateWalletCurrency('Associated', '0.00');
|
validateWalletCurrency('Associated', '0.00');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -373,21 +302,15 @@ context(
|
|||||||
Cypress.env('vegaWalletPublicKey')
|
Cypress.env('vegaWalletPublicKey')
|
||||||
);
|
);
|
||||||
|
|
||||||
cy.get('[data-testid="manage-vega-wallet"]:visible').click();
|
switchVegaWalletPubKey();
|
||||||
cy.get('[data-testid="select-keypair-button"]').eq(0).click();
|
|
||||||
cy.get(connectedVegaKey).should(
|
cy.get(connectedVegaKey).should(
|
||||||
'have.text',
|
'have.text',
|
||||||
Cypress.env('vegaWalletPublicKey2')
|
Cypress.env('vegaWalletPublicKey2')
|
||||||
);
|
);
|
||||||
stakingPageAssociateTokens('2');
|
stakingPageAssociateTokens('2');
|
||||||
cy.get(vegaWallet)
|
cy.get(vegaWallet).within(() => {
|
||||||
.first()
|
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 2.0);
|
||||||
.within(() => {
|
});
|
||||||
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
|
|
||||||
'contain',
|
|
||||||
2.0
|
|
||||||
);
|
|
||||||
});
|
|
||||||
cy.get(associateCompleteText).should(
|
cy.get(associateCompleteText).should(
|
||||||
'have.text',
|
'have.text',
|
||||||
`Vega key ${Cypress.env(
|
`Vega key ${Cypress.env(
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
waitForSpinner,
|
waitForSpinner,
|
||||||
} from '../../support/common.functions';
|
} from '../../support/common.functions';
|
||||||
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
|
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
|
||||||
import { depositAsset } from '../../support/wallet-teardown.functions';
|
import { depositAsset } from '../../support/wallet-functions';
|
||||||
|
|
||||||
const withdraw = 'withdraw';
|
const withdraw = 'withdraw';
|
||||||
const withdrawalForm = 'withdraw-form';
|
const withdrawalForm = 'withdraw-form';
|
||||||
@@ -15,13 +15,7 @@ const balanceAvailable = 'BALANCE_AVAILABLE_value';
|
|||||||
const withdrawalThreshold = 'WITHDRAWAL_THRESHOLD_value';
|
const withdrawalThreshold = 'WITHDRAWAL_THRESHOLD_value';
|
||||||
const delayTime = 'DELAY_TIME_value';
|
const delayTime = 'DELAY_TIME_value';
|
||||||
const submitWithdrawalButton = 'submit-withdrawal';
|
const submitWithdrawalButton = 'submit-withdrawal';
|
||||||
const dialogTitle = 'dialog-title';
|
|
||||||
const dialogClose = 'dialog-close';
|
const dialogClose = 'dialog-close';
|
||||||
const txExplorerLink = 'tx-block-explorer';
|
|
||||||
const withdrawalAssetSymbol = 'withdrawal-asset-symbol';
|
|
||||||
const withdrawalAmount = 'withdrawal-amount';
|
|
||||||
const withdrawalRecipient = 'withdrawal-recipient';
|
|
||||||
const withdrawFundsButton = 'withdraw-funds';
|
|
||||||
const completeWithdrawalButton = 'complete-withdrawal';
|
const completeWithdrawalButton = 'complete-withdrawal';
|
||||||
const tableTxHash = '[col-id="txHash"]';
|
const tableTxHash = '[col-id="txHash"]';
|
||||||
const tableAssetSymbol = '[col-id="asset.symbol"]';
|
const tableAssetSymbol = '[col-id="asset.symbol"]';
|
||||||
@@ -30,14 +24,16 @@ const tableReceiverAddress = '[col-id="details.receiverAddress"]';
|
|||||||
const tableWithdrawnTimeStamp = '[col-id="withdrawnTimestamp"]';
|
const tableWithdrawnTimeStamp = '[col-id="withdrawnTimestamp"]';
|
||||||
const tableWithdrawnStatus = '[col-id="status"]';
|
const tableWithdrawnStatus = '[col-id="status"]';
|
||||||
const tableCreatedTimeStamp = '[col-id="createdTimestamp"]';
|
const tableCreatedTimeStamp = '[col-id="createdTimestamp"]';
|
||||||
const toastContent = 'toast-content';
|
const toast = 'toast';
|
||||||
const toastPanel = 'toast-panel';
|
const toastPanel = 'toast-panel';
|
||||||
|
const toastClose = 'toast-close';
|
||||||
|
const withdrawalDialogContent = 'dialog-content';
|
||||||
|
const toastCompleteWithdrawal = 'toast-complete-withdrawal';
|
||||||
const usdtName = 'USDC (local)';
|
const usdtName = 'USDC (local)';
|
||||||
const usdcEthAddress = '0x1b8a1B6CBE5c93609b46D1829Cc7f3Cb8eeE23a0';
|
const usdcEthAddress = '0x1b8a1B6CBE5c93609b46D1829Cc7f3Cb8eeE23a0';
|
||||||
const usdcSymbol = 'tUSDC';
|
const usdcSymbol = 'tUSDC';
|
||||||
const usdtSelectValue =
|
const usdtSelectValue =
|
||||||
'993ed98f4f770d91a796faab1738551193ba45c62341d20597df70fea6704ede';
|
'993ed98f4f770d91a796faab1738551193ba45c62341d20597df70fea6704ede';
|
||||||
const truncatedWithdrawalEthAddress = '0xEe7D…22d94F';
|
|
||||||
const formValidationError = 'input-error-text';
|
const formValidationError = 'input-error-text';
|
||||||
const txTimeout = Cypress.env('txTimeout');
|
const txTimeout = Cypress.env('txTimeout');
|
||||||
|
|
||||||
@@ -47,11 +43,8 @@ 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 () {
|
||||||
@@ -62,6 +55,10 @@ context(
|
|||||||
navigateTo(navigation.withdraw);
|
navigateTo(navigation.withdraw);
|
||||||
cy.connectVegaWallet();
|
cy.connectVegaWallet();
|
||||||
ethereumWalletConnect();
|
ethereumWalletConnect();
|
||||||
|
cy.getByTestId('currency-title', txTimeout).should(
|
||||||
|
'contain.text',
|
||||||
|
usdtName
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Able to open withdrawal form with vega wallet connected', function () {
|
it('Able to open withdrawal form with vega wallet connected', function () {
|
||||||
@@ -76,7 +73,10 @@ context(
|
|||||||
it('Unable to submit withdrawal with invalid fields', function () {
|
it('Unable to submit withdrawal with invalid fields', function () {
|
||||||
cy.getByTestId(withdraw).should('be.visible').click();
|
cy.getByTestId(withdraw).should('be.visible').click();
|
||||||
cy.getByTestId(withdrawalForm, txTimeout).within(() => {
|
cy.getByTestId(withdrawalForm, txTimeout).within(() => {
|
||||||
cy.get('select').select(usdtSelectValue, { force: true });
|
cy.getByTestId('select-asset').click();
|
||||||
|
cy.get('select')
|
||||||
|
.select(usdtSelectValue, { force: true })
|
||||||
|
.should('have.value', usdtSelectValue);
|
||||||
cy.getByTestId(balanceAvailable, txTimeout).should('exist');
|
cy.getByTestId(balanceAvailable, txTimeout).should('exist');
|
||||||
cy.getByTestId(submitWithdrawalButton).click();
|
cy.getByTestId(submitWithdrawalButton).click();
|
||||||
cy.getByTestId(formValidationError).should('have.length', 1);
|
cy.getByTestId(formValidationError).should('have.length', 1);
|
||||||
@@ -96,62 +96,75 @@ context(
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Able to withdraw asset: -eth wallet connected -withdraw funds button', function () {
|
it(
|
||||||
// fill in withdrawal form
|
'Able to withdraw asset: -eth wallet connected -withdraw funds button',
|
||||||
cy.getByTestId(withdraw).should('be.visible').click();
|
{ tags: '@smoke' },
|
||||||
cy.getByTestId(withdrawalForm, txTimeout).within(() => {
|
function () {
|
||||||
cy.get('select').select(usdtSelectValue, { force: true });
|
// fill in withdrawal form
|
||||||
cy.getByTestId(balanceAvailable, txTimeout).should('exist');
|
cy.getByTestId(withdraw).should('be.visible').click();
|
||||||
cy.getByTestId(withdrawalThreshold).should(
|
cy.getByTestId(withdrawalForm, txTimeout).within(() => {
|
||||||
'have.text',
|
cy.getByTestId('select-asset').click();
|
||||||
'100,000.00000T'
|
cy.get('select')
|
||||||
);
|
.select(usdtSelectValue, { force: true })
|
||||||
cy.getByTestId(delayTime).should('have.text', 'None');
|
.should('have.value', usdtSelectValue);
|
||||||
cy.getByTestId(amountInput).click().type('120');
|
cy.getByTestId(balanceAvailable, txTimeout).should('exist');
|
||||||
cy.getByTestId(submitWithdrawalButton).click();
|
cy.getByTestId(withdrawalThreshold).should(
|
||||||
});
|
'have.text',
|
||||||
|
'100,000.00000T'
|
||||||
cy.contains('Awaiting network confirmation').should('be.visible');
|
);
|
||||||
// assert withdrawal request
|
cy.getByTestId(delayTime).should('have.text', 'None');
|
||||||
cy.getByTestId(dialogTitle, txTimeout).should(
|
cy.getByTestId(amountInput).click().type('120');
|
||||||
'have.text',
|
cy.getByTestId(submitWithdrawalButton).click();
|
||||||
'Transaction complete'
|
|
||||||
);
|
|
||||||
cy.getByTestId(txExplorerLink)
|
|
||||||
.should('have.attr', 'href')
|
|
||||||
.and('contain', '/txs/');
|
|
||||||
cy.getByTestId(withdrawalAssetSymbol).should('have.text', usdcSymbol);
|
|
||||||
cy.getByTestId(withdrawalAmount).should('have.text', '120.00');
|
|
||||||
cy.getByTestId(withdrawalRecipient)
|
|
||||||
.should('have.text', truncatedWithdrawalEthAddress)
|
|
||||||
.and('have.attr', 'href')
|
|
||||||
.and('contain', `/address/${Cypress.env('ethWalletPublicKey')}`);
|
|
||||||
cy.getByTestId(withdrawFundsButton).click();
|
|
||||||
// withdrawal complete
|
|
||||||
cy.getByTestId(dialogTitle, txTimeout).should(
|
|
||||||
'have.text',
|
|
||||||
'Withdraw asset complete'
|
|
||||||
);
|
|
||||||
cy.getByTestId(dialogClose).click();
|
|
||||||
// withdrawal history for complete withdrawal displayed
|
|
||||||
cy.get(tableWithdrawnStatus)
|
|
||||||
.eq(1, txTimeout)
|
|
||||||
.should('have.text', 'Completed')
|
|
||||||
.parent()
|
|
||||||
.within(() => {
|
|
||||||
cy.get(tableAssetSymbol).should('have.text', usdcSymbol);
|
|
||||||
cy.get(tableAmount).should('have.text', '120.00');
|
|
||||||
cy.get(tableReceiverAddress)
|
|
||||||
.find('a')
|
|
||||||
.should('have.attr', 'href')
|
|
||||||
.and('contain', 'https://sepolia.etherscan.io/address/');
|
|
||||||
cy.get(tableWithdrawnTimeStamp).should('not.be.empty');
|
|
||||||
cy.get(tableTxHash)
|
|
||||||
.find('a')
|
|
||||||
.should('have.attr', 'href')
|
|
||||||
.and('contain', 'https://sepolia.etherscan.io/tx/');
|
|
||||||
});
|
});
|
||||||
});
|
// assert withdrawal request
|
||||||
|
cy.getByTestId(toast)
|
||||||
|
.first(txTimeout)
|
||||||
|
.should('contain.text', 'Funds unlocked')
|
||||||
|
.within(() => {
|
||||||
|
cy.getByTestId('external-link').should('exist');
|
||||||
|
cy.getByTestId(toastPanel).should(
|
||||||
|
'contain.text',
|
||||||
|
'Withdraw 120.00 tUSDC'
|
||||||
|
);
|
||||||
|
cy.getByTestId(toastCompleteWithdrawal).click();
|
||||||
|
cy.getByTestId(toastClose).click();
|
||||||
|
});
|
||||||
|
// withdrawal complete
|
||||||
|
cy.getByTestId(toast)
|
||||||
|
.first(txTimeout)
|
||||||
|
.should('contain.text', 'The withdrawal has been approved.')
|
||||||
|
.within(() => {
|
||||||
|
cy.getByTestId(toastPanel).should(
|
||||||
|
'contain.text',
|
||||||
|
'Withdraw 120.00 tUSDC'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
cy.getByTestId(toast)
|
||||||
|
.last(txTimeout)
|
||||||
|
.should('contain.text', 'Transaction confirmed')
|
||||||
|
.within(() => {
|
||||||
|
cy.getByTestId('external-link').should('exist');
|
||||||
|
});
|
||||||
|
// withdrawal history for complete withdrawal displayed
|
||||||
|
cy.get(tableWithdrawnStatus)
|
||||||
|
.eq(1, txTimeout)
|
||||||
|
.should('have.text', 'Completed')
|
||||||
|
.parent()
|
||||||
|
.within(() => {
|
||||||
|
cy.get(tableAssetSymbol).should('have.text', usdcSymbol);
|
||||||
|
cy.get(tableAmount).should('have.text', '120.00');
|
||||||
|
cy.get(tableReceiverAddress)
|
||||||
|
.find('a')
|
||||||
|
.should('have.attr', 'href')
|
||||||
|
.and('contain', 'https://sepolia.etherscan.io/address/');
|
||||||
|
cy.get(tableWithdrawnTimeStamp).should('not.be.empty');
|
||||||
|
cy.get(tableTxHash)
|
||||||
|
.find('a')
|
||||||
|
.should('have.attr', 'href')
|
||||||
|
.and('contain', 'https://sepolia.etherscan.io/tx/');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
it('Able to withdraw asset: -eth wallet not connected', function () {
|
it('Able to withdraw asset: -eth wallet not connected', function () {
|
||||||
const ethWalletAddress = Cypress.env('ethWalletPublicKey');
|
const ethWalletAddress = Cypress.env('ethWalletPublicKey');
|
||||||
@@ -160,7 +173,10 @@ context(
|
|||||||
// fill in withdrawal form
|
// fill in withdrawal form
|
||||||
cy.getByTestId(withdraw).should('be.visible').click();
|
cy.getByTestId(withdraw).should('be.visible').click();
|
||||||
cy.getByTestId(withdrawalForm, txTimeout).within(() => {
|
cy.getByTestId(withdrawalForm, txTimeout).within(() => {
|
||||||
cy.get('select').select(usdtSelectValue, { force: true });
|
cy.getByTestId('select-asset').click();
|
||||||
|
cy.get('select')
|
||||||
|
.select(usdtSelectValue, { force: true })
|
||||||
|
.should('have.value', usdtSelectValue);
|
||||||
cy.getByTestId(ethAddressInput).should('be.empty');
|
cy.getByTestId(ethAddressInput).should('be.empty');
|
||||||
cy.getByTestId(amountInput).click().type('110');
|
cy.getByTestId(amountInput).click().type('110');
|
||||||
cy.getByTestId(submitWithdrawalButton).click();
|
cy.getByTestId(submitWithdrawalButton).click();
|
||||||
@@ -171,13 +187,17 @@ context(
|
|||||||
cy.getByTestId(submitWithdrawalButton).click();
|
cy.getByTestId(submitWithdrawalButton).click();
|
||||||
});
|
});
|
||||||
|
|
||||||
cy.contains('Awaiting network confirmation').should('be.visible');
|
cy.getByTestId(toast)
|
||||||
// assert withdrawal request
|
.first(txTimeout)
|
||||||
cy.getByTestId(dialogTitle, txTimeout).should(
|
.should('contain.text', 'Funds unlocked')
|
||||||
'have.text',
|
.within(() => {
|
||||||
'Transaction complete'
|
cy.getByTestId('external-link').should('exist');
|
||||||
);
|
cy.getByTestId(toastPanel).should(
|
||||||
cy.getByTestId(dialogClose).click();
|
'contain.text',
|
||||||
|
'Withdraw 110.00 tUSDC'
|
||||||
|
);
|
||||||
|
cy.getByTestId(toastClose).click();
|
||||||
|
});
|
||||||
cy.get(tableTxHash)
|
cy.get(tableTxHash)
|
||||||
.eq(1)
|
.eq(1)
|
||||||
.should('have.text', 'Complete withdrawal')
|
.should('have.text', 'Complete withdrawal')
|
||||||
@@ -192,28 +212,78 @@ context(
|
|||||||
cy.get(tableCreatedTimeStamp).should('not.be.empty');
|
cy.get(tableCreatedTimeStamp).should('not.be.empty');
|
||||||
});
|
});
|
||||||
ethereumWalletConnect();
|
ethereumWalletConnect();
|
||||||
cy.getByTestId(completeWithdrawalButton).click();
|
cy.getByTestId(completeWithdrawalButton).first().click();
|
||||||
cy.getByTestId(toastContent)
|
cy.getByTestId(toast)
|
||||||
.last()
|
.last(txTimeout)
|
||||||
.should('contain.text', 'Awaiting confirmation')
|
.should('contain.text', 'Awaiting confirmation')
|
||||||
.within(() => {
|
.within(() => {
|
||||||
cy.getByTestId('external-link').should('exist');
|
cy.getByTestId('external-link').should('exist');
|
||||||
});
|
});
|
||||||
cy.getByTestId(toastContent)
|
cy.getByTestId(toast)
|
||||||
.first()
|
.first(txTimeout)
|
||||||
.should('contain.text', 'The withdrawal has been approved.')
|
.should('contain.text', 'The withdrawal has been approved.')
|
||||||
.within(() => {
|
.within(() => {
|
||||||
cy.getByTestId(toastPanel).should('contain.text', '110.00', 'tUSDC');
|
cy.getByTestId(toastPanel).should('contain.text', '110.00', 'tUSDC');
|
||||||
});
|
});
|
||||||
cy.getByTestId(toastContent)
|
cy.getByTestId(toast)
|
||||||
.last()
|
.last(txTimeout)
|
||||||
.should('contain.text', 'Transaction confirmed')
|
.should('contain.text', 'Transaction confirmed')
|
||||||
.within(() => {
|
.within(() => {
|
||||||
cy.getByTestId('external-link').should('exist');
|
cy.getByTestId('external-link').should('exist');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Unable to withdraw asset on pub key view', function () {
|
it('Should be able to see withdrawal details from toast', function () {
|
||||||
|
cy.getByTestId(withdraw).click();
|
||||||
|
cy.getByTestId(withdrawalForm, txTimeout).within(() => {
|
||||||
|
cy.getByTestId('select-asset').click();
|
||||||
|
cy.get('select')
|
||||||
|
.select(usdtSelectValue, { force: true })
|
||||||
|
.should('have.value', usdtSelectValue);
|
||||||
|
cy.getByTestId(balanceAvailable, txTimeout).should('exist');
|
||||||
|
cy.getByTestId(withdrawalThreshold).should(
|
||||||
|
'have.text',
|
||||||
|
'100,000.00000T'
|
||||||
|
);
|
||||||
|
cy.getByTestId(amountInput).click().type('50');
|
||||||
|
cy.getByTestId(submitWithdrawalButton).click();
|
||||||
|
});
|
||||||
|
cy.getByTestId(toast)
|
||||||
|
.first(txTimeout)
|
||||||
|
.should('contain.text', 'Funds unlocked')
|
||||||
|
.within(() => {
|
||||||
|
cy.getByTestId('external-link').should('exist');
|
||||||
|
cy.getByTestId(toastPanel).should(
|
||||||
|
'contain.text',
|
||||||
|
'Withdraw 50.00 tUSDC'
|
||||||
|
);
|
||||||
|
cy.contains('save your withdrawal details').click();
|
||||||
|
});
|
||||||
|
cy.getByTestId(withdrawalDialogContent)
|
||||||
|
.last()
|
||||||
|
.within(() => {
|
||||||
|
cy.getByTestId('assetSource_value').should(
|
||||||
|
'have.text',
|
||||||
|
'0x1b8a1B6CBE5c93609b46D1829Cc7f3Cb8eeE23a0'
|
||||||
|
);
|
||||||
|
cy.getByTestId('amount_value').should('have.text', '5000000');
|
||||||
|
cy.getByTestId('nonce_value').invoke('text').should('not.be.empty');
|
||||||
|
cy.getByTestId('signatures_value')
|
||||||
|
.invoke('text')
|
||||||
|
.should('not.be.empty');
|
||||||
|
cy.getByTestId('targetAddress_value').should(
|
||||||
|
'have.text',
|
||||||
|
Cypress.env('ethWalletPublicKey')
|
||||||
|
);
|
||||||
|
cy.getByTestId('creation_value')
|
||||||
|
.invoke('text')
|
||||||
|
.should('not.be.empty');
|
||||||
|
});
|
||||||
|
cy.getByTestId(dialogClose).click();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Skipping test due to bug #3882
|
||||||
|
it.skip('Unable to withdraw asset on pub key view', function () {
|
||||||
const vegaWalletPubKey = Cypress.env('vegaWalletPublicKey');
|
const vegaWalletPubKey = Cypress.env('vegaWalletPublicKey');
|
||||||
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.`;
|
||||||
|
|
||||||
@@ -224,13 +294,17 @@ context(
|
|||||||
cy.connectPublicKey(vegaWalletPubKey);
|
cy.connectPublicKey(vegaWalletPubKey);
|
||||||
cy.getByTestId(withdraw).should('be.visible').click();
|
cy.getByTestId(withdraw).should('be.visible').click();
|
||||||
cy.getByTestId(withdrawalForm, txTimeout).within(() => {
|
cy.getByTestId(withdrawalForm, txTimeout).within(() => {
|
||||||
cy.get('select').select(usdtSelectValue, { force: true });
|
cy.getByTestId('select-asset').click();
|
||||||
|
cy.get('select')
|
||||||
|
.select(usdtSelectValue, { force: true })
|
||||||
|
.should('have.value', usdtSelectValue);
|
||||||
cy.getByTestId(balanceAvailable, txTimeout).should('exist');
|
cy.getByTestId(balanceAvailable, txTimeout).should('exist');
|
||||||
cy.getByTestId(amountInput).click().type('100');
|
cy.getByTestId(amountInput).click().type('100');
|
||||||
|
cy.pause();
|
||||||
cy.getByTestId(submitWithdrawalButton).click();
|
cy.getByTestId(submitWithdrawalButton).click();
|
||||||
});
|
});
|
||||||
|
|
||||||
cy.getByTestId('dialog-content')
|
cy.getByTestId(withdrawalDialogContent)
|
||||||
.last()
|
.last()
|
||||||
.within(() => {
|
.within(() => {
|
||||||
cy.get('h1').should('have.text', 'Transaction failed');
|
cy.get('h1').should('have.text', 'Transaction failed');
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import {
|
|||||||
import { mockNetworkUpgradeProposal } from '../../support/proposal.functions';
|
import { mockNetworkUpgradeProposal } from '../../support/proposal.functions';
|
||||||
|
|
||||||
const proposalDocumentationLink = '[data-testid="proposal-documentation-link"]';
|
const proposalDocumentationLink = '[data-testid="proposal-documentation-link"]';
|
||||||
const newProposalLink = '[data-testid="new-proposal-link"]';
|
|
||||||
const governanceDocsUrl = 'https://vega.xyz/governance';
|
const governanceDocsUrl = 'https://vega.xyz/governance';
|
||||||
const connectToVegaWalletButton = '[data-testid="connect-to-vega-wallet-btn"]';
|
const connectToVegaWalletButton = '[data-testid="connect-to-vega-wallet-btn"]';
|
||||||
|
|
||||||
@@ -32,6 +31,14 @@ context(
|
|||||||
verifyPageHeader('Proposals');
|
verifyPageHeader('Proposals');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 3002-PROP-023 3004-PMAC-002 3005-PASN-002 3006-PASC-002 3007-PNEC-002 3008-PFRO-003
|
||||||
|
it('should have button for link to more information on proposals', function () {
|
||||||
|
const proposalsUrl = 'https://docs.vega.xyz/mainnet/tutorials/proposals';
|
||||||
|
cy.getByTestId('new-proposal-link')
|
||||||
|
.find('a')
|
||||||
|
.should('have.attr', 'href', proposalsUrl);
|
||||||
|
});
|
||||||
|
|
||||||
it('should be able to see a working link for - find out more about Vega governance', function () {
|
it('should be able to see a working link for - find out more about Vega governance', function () {
|
||||||
// 3001-VOTE-001
|
// 3001-VOTE-001
|
||||||
cy.get(proposalDocumentationLink)
|
cy.get(proposalDocumentationLink)
|
||||||
@@ -54,17 +61,62 @@ context(
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip('should be able to see button for - new proposal', function () {
|
// 3007-PNE-021
|
||||||
// 3001-VOTE-002
|
it('should have documentation links for network parameter proposal', function () {
|
||||||
cy.get(newProposalLink)
|
goToMakeNewProposal(governanceProposalType.NETWORK_PARAMETER);
|
||||||
.should('be.visible')
|
cy.getByTestId('proposal-docs-link')
|
||||||
.and('have.text', 'New proposal')
|
.find('a')
|
||||||
.and('have.attr', 'href')
|
.should('have.attr', 'href')
|
||||||
.and('equal', '/proposals/propose');
|
.and('contain', '/tutorials/proposals/network-parameter-proposal');
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip('should be able to see a connect wallet button - if vega wallet disconnected and user is submitting new proposal', function () {
|
// 3003-PMAN-002 3003-PMAN-005
|
||||||
goToMakeNewProposal(governanceProposalType.NETWORK_PARAMETER);
|
it('should have documentation links for new market proposal', function () {
|
||||||
|
goToMakeNewProposal(governanceProposalType.NEW_MARKET);
|
||||||
|
cy.getByTestId('proposal-docs-link')
|
||||||
|
.find('a')
|
||||||
|
.should('have.attr', 'href')
|
||||||
|
.and('contain', '/tutorials/proposals/new-market-proposal');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 3004-PMAC-005
|
||||||
|
it('should have documentation links for update market proposal', function () {
|
||||||
|
goToMakeNewProposal(governanceProposalType.UPDATE_MARKET);
|
||||||
|
cy.getByTestId('proposal-docs-link')
|
||||||
|
.find('a')
|
||||||
|
.should('have.attr', 'href')
|
||||||
|
.and('contain', '/tutorials/proposals/update-market-proposal');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 3005-PASN-002 005-PASN-005
|
||||||
|
it('should have documentation links for new asset proposal', function () {
|
||||||
|
goToMakeNewProposal(governanceProposalType.NEW_ASSET);
|
||||||
|
cy.getByTestId('proposal-docs-link')
|
||||||
|
.find('a')
|
||||||
|
.should('have.attr', 'href')
|
||||||
|
.and('contain', '/tutorials/proposals/new-asset-proposal');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 3006-PASC-002 3006-PASC-005
|
||||||
|
it('should have documentation links for update asset proposal', function () {
|
||||||
|
goToMakeNewProposal(governanceProposalType.UPDATE_ASSET);
|
||||||
|
cy.getByTestId('proposal-docs-link')
|
||||||
|
.find('a')
|
||||||
|
.should('have.attr', 'href')
|
||||||
|
.and('contain', '/tutorials/proposals/update-asset-proposal');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 3008-PFRO-003 3008-PFRO-017
|
||||||
|
it('should have documentation links for freeform proposal', function () {
|
||||||
|
goToMakeNewProposal(governanceProposalType.FREEFORM);
|
||||||
|
cy.getByTestId('proposal-docs-link')
|
||||||
|
.find('a')
|
||||||
|
.should('have.attr', 'href')
|
||||||
|
.and('contain', '/tutorials/proposals/freeform-proposal');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to see a connect wallet button - if vega wallet disconnected and user is submitting new proposal', function () {
|
||||||
|
goToMakeNewProposal(governanceProposalType.RAW);
|
||||||
cy.get(connectToVegaWalletButton)
|
cy.get(connectToVegaWalletButton)
|
||||||
.should('be.visible')
|
.should('be.visible')
|
||||||
.and('have.text', 'Connect Vega wallet');
|
.and('have.text', 'Connect Vega wallet');
|
||||||
@@ -128,6 +180,7 @@ context(
|
|||||||
.first()
|
.first()
|
||||||
.find('[data-testid="view-proposal-btn"]')
|
.find('[data-testid="view-proposal-btn"]')
|
||||||
.click();
|
.click();
|
||||||
|
cy.url().should('contain', '/protocol-upgrades/v1');
|
||||||
cy.getByTestId('protocol-upgrade-proposal').within(() => {
|
cy.getByTestId('protocol-upgrade-proposal').within(() => {
|
||||||
cy.get('h1').should('have.text', 'Vega Release v1');
|
cy.get('h1').should('have.text', 'Vega Release v1');
|
||||||
cy.getByTestId('protocol-upgrade-block-height').should(
|
cy.getByTestId('protocol-upgrade-block-height').should(
|
||||||
|
|||||||
@@ -9,8 +9,9 @@ import {
|
|||||||
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-functions';
|
||||||
|
|
||||||
const vegaWalletPubKey = Cypress.env('vegaWalletPublicKey2');
|
const vegaWalletPubKey = Cypress.env('vegaWalletPublicKey2');
|
||||||
const vegaPubkeyTruncated = Cypress.env('vegaWalletPublicKey2Short');
|
const vegaPubkeyTruncated = Cypress.env('vegaWalletPublicKey2Short');
|
||||||
@@ -50,7 +51,7 @@ context('View functionality with public key', { tags: '@smoke' }, 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()
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
/// <reference types="cypress" />
|
/// <reference types="cypress" />
|
||||||
|
|
||||||
|
import { aliasGQLQuery } from '@vegaprotocol/cypress';
|
||||||
import {
|
import {
|
||||||
navigation,
|
navigation,
|
||||||
verifyPageHeader,
|
verifyPageHeader,
|
||||||
verifyTabHighlighted,
|
verifyTabHighlighted,
|
||||||
} from '../../support/common.functions';
|
} from '../../support/common.functions';
|
||||||
import { clickOnValidatorFromList } from '../../support/staking.functions';
|
import {
|
||||||
|
clickOnValidatorFromList,
|
||||||
|
waitForBeginningOfEpoch,
|
||||||
|
} from '../../support/staking.functions';
|
||||||
|
import { previousEpochData } from '../../fixtures/mocks/previous-epoch';
|
||||||
|
|
||||||
const guideLink = '[data-testid="staking-guide-link"]';
|
const guideLink = '[data-testid="staking-guide-link"]';
|
||||||
const validatorTitle = '[data-testid="validator-node-title"]';
|
const validatorTitle = '[data-testid="validator-node-title"]';
|
||||||
@@ -27,7 +32,7 @@ const normalisedVotingPowerToolTip =
|
|||||||
'[data-testid="normalised-voting-power-tooltip"]';
|
'[data-testid="normalised-voting-power-tooltip"]';
|
||||||
const performancePenaltyToolTip = '[data-testid="performance-penalty-tooltip"]';
|
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 multisigPenaltyToolTip = '[data-testid="multisig-error-tooltip"]';
|
||||||
const epochCountDown = '[data-testid="epoch-countdown"]';
|
const epochCountDown = '[data-testid="epoch-countdown"]';
|
||||||
const stakeNumberRegex = /^\d{1,3}(,\d{3})*(\.\d+)?$/;
|
const stakeNumberRegex = /^\d{1,3}(,\d{3})*(\.\d+)?$/;
|
||||||
|
|
||||||
@@ -37,206 +42,226 @@ context('Validators Page - verify elements on page', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('with wallets disconnected', { tags: '@smoke' }, function () {
|
describe('with wallets disconnected', { tags: '@smoke' }, function () {
|
||||||
describe('description section', function () {
|
it('Should have validators tab highlighted', function () {
|
||||||
it('Should have validators tab highlighted', function () {
|
verifyTabHighlighted(navigation.validators);
|
||||||
verifyTabHighlighted(navigation.validators);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Should have validators ON VEGA header visible', function () {
|
|
||||||
verifyPageHeader('Validators');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Should have Staking Guide link visible', function () {
|
|
||||||
// 2001-STKE-003
|
|
||||||
cy.get(guideLink)
|
|
||||||
.should('be.visible')
|
|
||||||
.and('have.text', 'Read more about staking on Vega')
|
|
||||||
.and(
|
|
||||||
'have.attr',
|
|
||||||
'href',
|
|
||||||
'https://docs.vega.xyz/mainnet/concepts/vega-chain/#staking-on-vega'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
describe(
|
|
||||||
'Should be able to see validator list from the staking page',
|
|
||||||
{ tags: '@regression' },
|
|
||||||
function () {
|
|
||||||
// 2001-STKE-050
|
|
||||||
it('Should be able to see validator names', function () {
|
|
||||||
cy.get('[col-id="validator"] > div > span')
|
|
||||||
.should('have.length.at.least', 1)
|
|
||||||
.each(($name) => {
|
|
||||||
cy.wrap($name).should('not.be.empty');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Should be able to see validator stake', function () {
|
it('Should have validators ON VEGA header visible', function () {
|
||||||
cy.getByTestId('total-stake')
|
verifyPageHeader('Validators');
|
||||||
.should('have.length.at.least', 1)
|
});
|
||||||
.each(($stake) => {
|
|
||||||
cy.wrap($stake).should('not.be.empty');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Should be able to see validator stake tooltip', function () {
|
it('Should have Staking Guide link visible', function () {
|
||||||
cy.getByTestId('total-stake').first().realHover();
|
// 1002-STKE-003
|
||||||
|
cy.get(guideLink)
|
||||||
|
.should('be.visible')
|
||||||
|
.and('have.text', 'Read more about staking on Vega')
|
||||||
|
.and(
|
||||||
|
'have.attr',
|
||||||
|
'href',
|
||||||
|
'https://docs.vega.xyz/mainnet/concepts/vega-chain/#staking-on-vega'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
cy.get(stakedByOperatorToolTip)
|
// 1002-STKE-032
|
||||||
.invoke('text')
|
it('Should have button to connect vega wallet in validator page', function () {
|
||||||
.should('contain', 'Staked by operator: 3,000.00');
|
clickOnValidatorFromList(0);
|
||||||
cy.get(stakedByDelegatesToolTip)
|
cy.getByTestId('connect-to-vega-wallet-btn').should('be.visible');
|
||||||
.invoke('text')
|
cy.visit('/validators');
|
||||||
.should('contain', 'Staked by delegates: 0.00');
|
});
|
||||||
cy.get(totalStakedToolTip)
|
|
||||||
.invoke('text')
|
|
||||||
.should('contain', 'Total stake: 3,000.00');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Should be able to see validator normalised voting power', function () {
|
|
||||||
cy.getByTestId('normalised-voting-power')
|
|
||||||
.should('have.length.at.least', 1)
|
|
||||||
.each(($vPower) => {
|
|
||||||
cy.wrap($vPower).should('not.be.empty');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Should be able to see validator normalised voting power tooltip', function () {
|
|
||||||
cy.getByTestId('normalised-voting-power').first().realHover();
|
|
||||||
|
|
||||||
cy.get(unnormalisedVotingPowerToolTip)
|
|
||||||
.invoke('text')
|
|
||||||
.should('contain', 'Unnormalised voting power: 20.00%');
|
|
||||||
cy.get(normalisedVotingPowerToolTip)
|
|
||||||
.invoke('text')
|
|
||||||
.should('contain', 'Normalised voting power: 50.00%');
|
|
||||||
});
|
|
||||||
|
|
||||||
// 2002-SINC-018
|
|
||||||
it('Should be able to see validator total penalties', function () {
|
|
||||||
cy.getByTestId('total-penalty')
|
|
||||||
.should('have.length.at.least', 1)
|
|
||||||
.each(($penalties) => {
|
|
||||||
cy.wrap($penalties).should('contain.text', '0%');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Should be able to see validator penalties tooltip', function () {
|
|
||||||
cy.getByTestId('total-penalty').realHover();
|
|
||||||
|
|
||||||
cy.get(performancePenaltyToolTip)
|
|
||||||
.invoke('text')
|
|
||||||
.should('contain', 'Performance penalty: 0.00%');
|
|
||||||
cy.get(overstakedPenaltyToolTip)
|
|
||||||
.invoke('text')
|
|
||||||
.should('contain', 'Overstaked penalty: 60.00%'); // value not asserted due to #2886
|
|
||||||
cy.get(totalPenaltyToolTip)
|
|
||||||
.invoke('text')
|
|
||||||
.should('contain', 'Total penalties: 60.00%');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Should be able to see validator pending stake', function () {
|
|
||||||
cy.getByTestId('total-pending-stake')
|
|
||||||
.should('have.length.at.least', 1)
|
|
||||||
.each(($pendingStake) => {
|
|
||||||
cy.wrap($pendingStake).should('contain.text', '0.00');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// 2001-STKE-050
|
|
||||||
describe(
|
|
||||||
'Should be able to see static information about a validator',
|
|
||||||
{ tags: '@smoke' },
|
|
||||||
function () {
|
|
||||||
before('connect wallets and click on validator', function () {
|
|
||||||
cy.connectVegaWallet();
|
|
||||||
clickOnValidatorFromList(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 2001-STKE-006
|
|
||||||
it('Should be able to see validator name', function () {
|
|
||||||
cy.get(validatorTitle).should('not.be.empty');
|
|
||||||
});
|
|
||||||
|
|
||||||
// 2001-STKE-007
|
|
||||||
it('Should be able to see validator id', function () {
|
|
||||||
cy.get(validatorId).should('not.be.empty');
|
|
||||||
});
|
|
||||||
|
|
||||||
// 2001-STKE-008
|
|
||||||
it('Should be able to see validator public key', function () {
|
|
||||||
cy.get(validatorPubKey).should('not.be.empty');
|
|
||||||
});
|
|
||||||
|
|
||||||
// 2001-STKE-010
|
|
||||||
it('Should be able to see Ethereum address', function () {
|
|
||||||
cy.get(ethAddressLink)
|
|
||||||
.should('not.be.empty')
|
|
||||||
.and('have.attr', 'href');
|
|
||||||
});
|
|
||||||
// TODO validators missing url for more information about them 2001-STKE-09
|
|
||||||
|
|
||||||
it('Should be able to see validator status', function () {
|
|
||||||
cy.get(validatorStatus).should('have.text', 'Consensus');
|
|
||||||
});
|
|
||||||
|
|
||||||
// 2001-STKE-012
|
|
||||||
it('Should be able to see total stake', function () {
|
|
||||||
cy.get(totalStake).invoke('text').should('match', stakeNumberRegex);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Should be able to see pending stake', function () {
|
|
||||||
cy.get(pendingStake).invoke('text').should('match', stakeNumberRegex);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Should be able to see staked by operator', function () {
|
|
||||||
cy.get(stakedByOperator)
|
|
||||||
.invoke('text')
|
|
||||||
.should('match', stakeNumberRegex);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Should be able to see staked by delegates', function () {
|
|
||||||
cy.get(stakedByDelegates)
|
|
||||||
.invoke('text')
|
|
||||||
.should('match', stakeNumberRegex);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 2001-STKE-051
|
|
||||||
it('Should be able to see stake share in percentage', function () {
|
|
||||||
cy.get(stakeShare)
|
|
||||||
.invoke('text')
|
|
||||||
.then(($stakePercentage) => {
|
|
||||||
// The pattern must start at a word boundary (\b).
|
|
||||||
// The pattern cannot be immediately preceded by a dot ((?<!\.)).
|
|
||||||
// The pattern can be one of the following:
|
|
||||||
// A percentage value of zero (0%), or
|
|
||||||
// A non-zero percentage value that can be:
|
|
||||||
// A single digit (\d) between 0 and 9, or
|
|
||||||
// A two-digit number between 0 and 99 (\d{1,2}), or
|
|
||||||
// The number 100.
|
|
||||||
// The pattern can optionally include a decimal point and one or more digits after the decimal point ((?:(?<!100)\.\d+)?). However, if the number is 100, it cannot have a decimal point.
|
|
||||||
// The pattern must end with a percentage sign (%).
|
|
||||||
|
|
||||||
cy.wrap($stakePercentage).should(
|
|
||||||
'match',
|
|
||||||
/\b(?<!\.)(?:0+(?:\.0+)?%|(?:\d|\d{1,2}|100)(?:(?<!100)\.\d+)?)%/
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// 2001-STKE-011 2002-SINC-001 2002-SINC-002
|
|
||||||
it('Should be able to see epoch information', function () {
|
|
||||||
const epochTitle = 'h3';
|
|
||||||
const nextEpochInfo = 'p';
|
|
||||||
|
|
||||||
cy.get(epochCountDown).within(() => {
|
|
||||||
cy.get(epochTitle).should('not.be.empty');
|
|
||||||
cy.get(nextEpochInfo).should('contain.text', 'Next epoch');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
// 1002-STKE-020 1002-STKE-021 1002-STKE-022 1002-STKE-023 1002-STKE-024
|
||||||
|
describe(
|
||||||
|
'Should be able to see validator list from the staking page',
|
||||||
|
{ tags: '@regression' },
|
||||||
|
function () {
|
||||||
|
// 1002-STKE-050
|
||||||
|
it('Should be able to see validator names', function () {
|
||||||
|
cy.get('[col-id="validator"] > div > span')
|
||||||
|
.should('have.length.at.least', 1)
|
||||||
|
.each(($name) => {
|
||||||
|
cy.wrap($name).should('not.be.empty');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to see validator stake', function () {
|
||||||
|
cy.getByTestId('total-stake')
|
||||||
|
.should('have.length.at.least', 1)
|
||||||
|
.each(($stake) => {
|
||||||
|
cy.wrap($stake).should('not.be.empty');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to see validator stake tooltip', function () {
|
||||||
|
waitForBeginningOfEpoch();
|
||||||
|
cy.getByTestId('total-stake').first().realHover();
|
||||||
|
|
||||||
|
cy.get(stakedByOperatorToolTip)
|
||||||
|
.invoke('text')
|
||||||
|
.should('contain', 'Staked by operator: 3,000.00');
|
||||||
|
cy.get(stakedByDelegatesToolTip)
|
||||||
|
.invoke('text')
|
||||||
|
.should('contain', 'Staked by delegates: 0.00');
|
||||||
|
cy.get(totalStakedToolTip)
|
||||||
|
.invoke('text')
|
||||||
|
.should('contain', 'Total stake: 3,000.00');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to see validator normalised voting power', function () {
|
||||||
|
cy.getByTestId('normalised-voting-power')
|
||||||
|
.should('have.length.at.least', 1)
|
||||||
|
.each(($vPower) => {
|
||||||
|
cy.wrap($vPower).should('not.be.empty');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to see validator normalised voting power tooltip', function () {
|
||||||
|
waitForBeginningOfEpoch();
|
||||||
|
cy.getByTestId('normalised-voting-power').first().realHover();
|
||||||
|
|
||||||
|
cy.get(unnormalisedVotingPowerToolTip)
|
||||||
|
.invoke('text')
|
||||||
|
.should('contain', 'Unnormalised voting power: 20.00%');
|
||||||
|
cy.get(normalisedVotingPowerToolTip)
|
||||||
|
.invoke('text')
|
||||||
|
.should('contain', 'Normalised voting power: 50.00%');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2002-SINC-018
|
||||||
|
it('Should be able to see validator total penalties', function () {
|
||||||
|
cy.getByTestId('total-penalty')
|
||||||
|
.should('have.length.at.least', 1)
|
||||||
|
.each(($penalties) => {
|
||||||
|
cy.wrap($penalties).should('contain.text', '0%');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to see validator penalties tooltip', function () {
|
||||||
|
waitForBeginningOfEpoch();
|
||||||
|
cy.getByTestId('total-penalty').realHover();
|
||||||
|
|
||||||
|
cy.get(performancePenaltyToolTip)
|
||||||
|
.invoke('text')
|
||||||
|
.should('contain', 'Performance penalty: 0.00%');
|
||||||
|
cy.get(overstakedPenaltyToolTip)
|
||||||
|
.invoke('text')
|
||||||
|
.should('contain', 'Overstaked penalty: 60.00%'); // value not asserted due to #2886
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to see validator pending stake', function () {
|
||||||
|
cy.getByTestId('total-pending-stake')
|
||||||
|
.should('have.length.at.least', 1)
|
||||||
|
.each(($pendingStake) => {
|
||||||
|
cy.wrap($pendingStake).should('contain.text', '0.00');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to see multisig error', function () {
|
||||||
|
cy.mockGQL((req) => {
|
||||||
|
aliasGQLQuery(req, 'PreviousEpoch', previousEpochData);
|
||||||
|
});
|
||||||
|
waitForBeginningOfEpoch();
|
||||||
|
cy.getByTestId('total-penalty').first().realHover();
|
||||||
|
cy.get(multisigPenaltyToolTip)
|
||||||
|
.invoke('text')
|
||||||
|
.should('contain', 'Multisig penalty: 100%');
|
||||||
|
|
||||||
|
cy.getByTestId('total-penalty').eq(1).realHover();
|
||||||
|
cy.get(multisigPenaltyToolTip)
|
||||||
|
.invoke('text')
|
||||||
|
.should('contain', 'Multisig penalty: 100%');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// 1002-STKE-050
|
||||||
|
describe(
|
||||||
|
'Should be able to see static information about a validator',
|
||||||
|
{ tags: '@smoke' },
|
||||||
|
function () {
|
||||||
|
before('connect wallets and click on validator', function () {
|
||||||
|
cy.connectVegaWallet();
|
||||||
|
clickOnValidatorFromList(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 1002-STKE-006
|
||||||
|
it('Should be able to see validator name', function () {
|
||||||
|
cy.get(validatorTitle).should('not.be.empty');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 1002-STKE-007
|
||||||
|
it('Should be able to see validator id', function () {
|
||||||
|
cy.get(validatorId).should('not.be.empty');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 1002-STKE-008
|
||||||
|
it('Should be able to see validator public key', function () {
|
||||||
|
cy.get(validatorPubKey).should('not.be.empty');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 1002-STKE-010
|
||||||
|
it('Should be able to see Ethereum address', function () {
|
||||||
|
cy.get(ethAddressLink).should('not.be.empty').and('have.attr', 'href');
|
||||||
|
});
|
||||||
|
// TODO validators missing url for more information about them 1002-STKE-09
|
||||||
|
|
||||||
|
it('Should be able to see validator status', function () {
|
||||||
|
cy.get(validatorStatus).should('have.text', 'Consensus');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 1002-STKE-012
|
||||||
|
it('Should be able to see total stake', function () {
|
||||||
|
cy.get(totalStake).invoke('text').should('match', stakeNumberRegex);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to see pending stake', function () {
|
||||||
|
cy.get(pendingStake).invoke('text').should('match', stakeNumberRegex);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to see staked by operator', function () {
|
||||||
|
cy.get(stakedByOperator)
|
||||||
|
.invoke('text')
|
||||||
|
.should('match', stakeNumberRegex);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should be able to see staked by delegates', function () {
|
||||||
|
cy.get(stakedByDelegates)
|
||||||
|
.invoke('text')
|
||||||
|
.should('match', stakeNumberRegex);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 1002-STKE-051
|
||||||
|
it('Should be able to see stake share in percentage', function () {
|
||||||
|
cy.get(stakeShare)
|
||||||
|
.invoke('text')
|
||||||
|
.then(($stakePercentage) => {
|
||||||
|
// The pattern must start at a word boundary (\b).
|
||||||
|
// The pattern cannot be immediately preceded by a dot ((?<!\.)).
|
||||||
|
// The pattern can be one of the following:
|
||||||
|
// A percentage value of zero (0%), or
|
||||||
|
// A non-zero percentage value that can be:
|
||||||
|
// A single digit (\d) between 0 and 9, or
|
||||||
|
// A two-digit number between 0 and 99 (\d{1,2}), or
|
||||||
|
// The number 100.
|
||||||
|
// The pattern can optionally include a decimal point and one or more digits after the decimal point ((?:(?<!100)\.\d+)?). However, if the number is 100, it cannot have a decimal point.
|
||||||
|
// The pattern must end with a percentage sign (%).
|
||||||
|
|
||||||
|
cy.wrap($stakePercentage).should(
|
||||||
|
'match',
|
||||||
|
/\b(?<!\.)(?:0+(?:\.0+)?%|(?:\d|\d{1,2}|100)(?:(?<!100)\.\d+)?)%/
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 1002-STKE-011 2002-SINC-001 2002-SINC-002
|
||||||
|
it('Should be able to see epoch information', function () {
|
||||||
|
const epochTitle = 'h3';
|
||||||
|
const nextEpochInfo = 'p';
|
||||||
|
|
||||||
|
cy.get(epochCountDown).within(() => {
|
||||||
|
cy.get(epochTitle).should('not.be.empty');
|
||||||
|
cy.get(nextEpochInfo).should('contain.text', 'Next epoch');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import { truncateByChars } from '@vegaprotocol/utils';
|
import { truncateByChars } from '@vegaprotocol/utils';
|
||||||
import { waitForSpinner } from '../../support/common.functions';
|
import { waitForSpinner } from '../../support/common.functions';
|
||||||
import { vegaWalletTeardown } from '../../support/wallet-teardown.functions';
|
import {
|
||||||
import { vegaWalletFaucetAssetsWithoutCheck } from '../../support/wallet-vega.functions';
|
vegaWalletFaucetAssetsWithoutCheck,
|
||||||
|
vegaWalletTeardown,
|
||||||
|
} from '../../support/wallet-functions';
|
||||||
|
|
||||||
const walletContainer = 'aside [data-testid="vega-wallet"]';
|
const walletContainer = 'aside [data-testid="vega-wallet"]';
|
||||||
const walletHeader = '[data-testid="wallet-header"] h1';
|
const walletHeader = '[data-testid="wallet-header"] h1';
|
||||||
@@ -285,28 +287,28 @@ context(
|
|||||||
name: 'USDC (fake)',
|
name: 'USDC (fake)',
|
||||||
symbol: 'fUSDC',
|
symbol: 'fUSDC',
|
||||||
amount: '1000000',
|
amount: '1000000',
|
||||||
expectedAmount: '10.00',
|
expectedAmount: 10.0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '8566db7257222b5b7ef2886394ad28b938b28680a54a169bbc795027b89d6665',
|
id: '8566db7257222b5b7ef2886394ad28b938b28680a54a169bbc795027b89d6665',
|
||||||
name: 'DAI (fake)',
|
name: 'DAI (fake)',
|
||||||
symbol: 'fDAI',
|
symbol: 'fDAI',
|
||||||
amount: '200000',
|
amount: '200000',
|
||||||
expectedAmount: '2.00',
|
expectedAmount: 2.0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '73174a6fb1d5802ba0ac7bd7ab79e0a3a4837b262de0a4e80815a55442692bd0',
|
id: '73174a6fb1d5802ba0ac7bd7ab79e0a3a4837b262de0a4e80815a55442692bd0',
|
||||||
name: 'BTC (fake)',
|
name: 'BTC (fake)',
|
||||||
symbol: 'fBTC',
|
symbol: 'fBTC',
|
||||||
amount: '600000',
|
amount: '600000',
|
||||||
expectedAmount: '6.00',
|
expectedAmount: 6.0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'e02d4c15d790d1d2dffaf2dcd1cf06a1fe656656cf4ed18c8ce99f9e83643567',
|
id: 'e02d4c15d790d1d2dffaf2dcd1cf06a1fe656656cf4ed18c8ce99f9e83643567',
|
||||||
name: 'EURO (fake)',
|
name: 'EURO (fake)',
|
||||||
symbol: 'fEURO',
|
symbol: 'fEURO',
|
||||||
amount: '800000',
|
amount: '800000',
|
||||||
expectedAmount: '8.00',
|
expectedAmount: 8.0,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -317,12 +319,6 @@ context(
|
|||||||
cy.reload();
|
cy.reload();
|
||||||
waitForSpinner();
|
waitForSpinner();
|
||||||
cy.connectVegaWallet();
|
cy.connectVegaWallet();
|
||||||
cy.get(walletContainer).within(() => {
|
|
||||||
cy.getByTestId('currency-title', txTimeout).should(
|
|
||||||
'have.length.at.least',
|
|
||||||
5
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const { name, symbol, expectedAmount } of assets) {
|
for (const { name, symbol, expectedAmount } of assets) {
|
||||||
@@ -336,9 +332,10 @@ context(
|
|||||||
.contains(name)
|
.contains(name)
|
||||||
.parent()
|
.parent()
|
||||||
.siblings()
|
.siblings()
|
||||||
.invoke('text')
|
.then((elementAmount) => {
|
||||||
.then(parseFloat)
|
const displayedAmount = parseFloat(elementAmount.text());
|
||||||
.should('be.gte', parseFloat(expectedAmount));
|
expect(displayedAmount).be.gte(expectedAmount);
|
||||||
|
});
|
||||||
|
|
||||||
cy.get(vegaWalletCurrencyTitle)
|
cy.get(vegaWalletCurrencyTitle)
|
||||||
.contains(name)
|
.contains(name)
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
|
import { stakingPageDisassociateAllTokens } from './staking.functions';
|
||||||
|
|
||||||
const tokenDropDown = 'state-trigger';
|
const tokenDropDown = 'state-trigger';
|
||||||
const txTimeout = Cypress.env('txTimeout');
|
const txTimeout = Cypress.env('txTimeout');
|
||||||
|
|
||||||
export enum navigation {
|
export enum navigation {
|
||||||
section = 'nav',
|
section = 'nav',
|
||||||
|
home = '[href="/"]',
|
||||||
vesting = '[href="/token/redeem"]',
|
vesting = '[href="/token/redeem"]',
|
||||||
validators = '[href="/validators"]',
|
validators = '[href="/validators"]',
|
||||||
rewards = '[href="/rewards"]',
|
rewards = '[href="/rewards"]',
|
||||||
@@ -18,6 +21,7 @@ export function convertTokenValueToNumber(subject: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const topLevelRoutes = [
|
const topLevelRoutes = [
|
||||||
|
navigation.home,
|
||||||
navigation.proposals,
|
navigation.proposals,
|
||||||
navigation.validators,
|
navigation.validators,
|
||||||
navigation.rewards,
|
navigation.rewards,
|
||||||
@@ -33,7 +37,7 @@ export function navigateTo(page: navigation) {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return cy.get(navigation.section, { timeout: 10000 }).within(() => {
|
return cy.get(navigation.section, { timeout: 10000 }).within(() => {
|
||||||
cy.get(page).eq(0).click();
|
cy.get(page).eq(0).click({ force: true });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -97,3 +101,25 @@ export function turnTelemetryOff() {
|
|||||||
win.localStorage.setItem('vega_telemetry_on', 'false')
|
win.localStorage.setItem('vega_telemetry_on', 'false')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function dissociateFromSecondWalletKey() {
|
||||||
|
const secondWalletKey = Cypress.env('vegaWalletPublicKey2Short');
|
||||||
|
cy.getByTestId('vega-in-wallet')
|
||||||
|
.first()
|
||||||
|
.within(() => {
|
||||||
|
cy.getByTestId('eth-wallet-associated-balances')
|
||||||
|
.last()
|
||||||
|
.within(() => {
|
||||||
|
cy.getByTestId('associated-key')
|
||||||
|
.invoke('text')
|
||||||
|
.as('associatedPubKey');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
cy.get('@associatedPubKey').then((associatedPubKey) => {
|
||||||
|
if (associatedPubKey == secondWalletKey) {
|
||||||
|
cy.get('[data-testid="manage-vega-wallet"]:visible').click();
|
||||||
|
cy.get('[data-testid="select-keypair-button"]').eq(0).click();
|
||||||
|
stakingPageDisassociateAllTokens();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -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,56 @@ 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 = 'src/fixtures/proposals/raw.json';
|
||||||
|
if (proposalFields.proposalBody) {
|
||||||
|
proposalBodyPath = proposalFields.proposalBody;
|
||||||
|
}
|
||||||
|
cy.readFile(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 if (
|
||||||
|
!proposalFields.closingTimestamp &&
|
||||||
|
!proposalFields.proposalBody
|
||||||
|
) {
|
||||||
|
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
|
||||||
@@ -55,7 +109,11 @@ export function enterUniqueFreeFormProposalBody(
|
|||||||
'this is a e2e freeform proposal description'
|
'this is a e2e freeform proposal description'
|
||||||
);
|
);
|
||||||
cy.get(proposalVoteDeadline).clear().click().type(timestamp);
|
cy.get(proposalVoteDeadline).clear().click().type(timestamp);
|
||||||
cy.getByTestId('proposal-submit').should('be.visible').click();
|
cy.getByTestId('proposal-download-json').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) {
|
||||||
@@ -120,15 +178,20 @@ 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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 3001-VOTE-013 3001-VOTE-014
|
||||||
export function waitForProposalSubmitted() {
|
export function waitForProposalSubmitted() {
|
||||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||||
'be.visible'
|
'be.visible'
|
||||||
@@ -163,11 +226,29 @@ export function createFreeformProposal(proposalTitle: string) {
|
|||||||
navigateTo(navigation.proposals);
|
navigateTo(navigation.proposals);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const governanceProposalType = {
|
export function getDownloadedProposalJsonPath(proposalType: string) {
|
||||||
NETWORK_PARAMETER: 'Network parameter',
|
const downloadPath = './cypress/downloads/';
|
||||||
NEW_MARKET: 'New market',
|
const filepath = downloadPath + proposalType + getFormattedTime() + '.json';
|
||||||
UPDATE_MARKET: 'Update market',
|
return filepath;
|
||||||
NEW_ASSET: 'New asset',
|
}
|
||||||
FREEFORM: 'Freeform',
|
|
||||||
RAW: 'raw proposal',
|
function getFormattedTime() {
|
||||||
};
|
const now = new Date();
|
||||||
|
const day = now.getDate().toString().padStart(2, '0');
|
||||||
|
const month = now.toLocaleString('en-US', { month: 'short' });
|
||||||
|
const year = now.getFullYear().toString();
|
||||||
|
const hours = now.getHours().toString().padStart(2, '0');
|
||||||
|
const minutes = now.getMinutes().toString().padStart(2, '0');
|
||||||
|
|
||||||
|
return `${day}-${month}-${year}-${hours}-${minutes}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum 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',
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,8 +5,7 @@ import './common.functions.ts';
|
|||||||
import './staking.functions.ts';
|
import './staking.functions.ts';
|
||||||
import './governance.functions.ts';
|
import './governance.functions.ts';
|
||||||
import './wallet-eth.functions.ts';
|
import './wallet-eth.functions.ts';
|
||||||
import './wallet-teardown.functions.ts';
|
import './wallet-functions.ts';
|
||||||
import './wallet-vega.functions.ts';
|
|
||||||
import './proposal.functions.ts';
|
import './proposal.functions.ts';
|
||||||
import 'cypress-mochawesome-reporter/register';
|
import 'cypress-mochawesome-reporter/register';
|
||||||
import registerCypressGrep from '@cypress/grep';
|
import registerCypressGrep from '@cypress/grep';
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { closeDialog } from './common.functions';
|
import { closeDialog } from './common.functions';
|
||||||
import { vegaWalletTeardown } from './wallet-teardown.functions';
|
import { vegaWalletTeardown } from './wallet-functions';
|
||||||
|
|
||||||
const tokenAmountInputBox = '[data-testid="token-amount-input"]';
|
const tokenAmountInputBox = '[data-testid="token-amount-input"]';
|
||||||
const tokenSubmitButton = '[data-testid="token-input-submit-button"]';
|
const tokenSubmitButton = '[data-testid="token-input-submit-button"]';
|
||||||
@@ -221,7 +221,7 @@ export function ensureSpecifiedUnstakedTokensAreAssociated(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function closeStakingDialog() {
|
export function closeStakingDialog() {
|
||||||
cy.getByTestId('dialog-title').should(
|
cy.getByTestId('dialog-title', txTimeout).should(
|
||||||
'contain.text',
|
'contain.text',
|
||||||
'At the beginning of the next epoch'
|
'At the beginning of the next epoch'
|
||||||
);
|
);
|
||||||
@@ -236,8 +236,8 @@ export function validateWalletCurrency(
|
|||||||
currencyTitle: string,
|
currencyTitle: string,
|
||||||
expectedAmount: string
|
expectedAmount: string
|
||||||
) {
|
) {
|
||||||
cy.get("[data-testid='currency-title']")
|
cy.get("[data-testid='currency-title']", txTimeout)
|
||||||
.contains(currencyTitle)
|
.contains(currencyTitle, txTimeout)
|
||||||
.parent()
|
.parent()
|
||||||
.parent()
|
.parent()
|
||||||
.within(() => {
|
.within(() => {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ const capsuleWalletConnectButton = '[data-testid="web3-connector-Unknown"]';
|
|||||||
|
|
||||||
export function ethereumWalletConnect() {
|
export function ethereumWalletConnect() {
|
||||||
cy.highlight('Connecting Eth Wallet');
|
cy.highlight('Connecting Eth Wallet');
|
||||||
cy.get(connectToEthButton).within(() => {
|
cy.get(connectToEthButton, { timeout: 60000 }).within(() => {
|
||||||
cy.contains('Connect Ethereum wallet to associate $VEGA')
|
cy.contains('Connect Ethereum wallet to associate $VEGA')
|
||||||
.should('be.visible')
|
.should('be.visible')
|
||||||
.click();
|
.click();
|
||||||
|
|||||||
+49
-33
@@ -19,7 +19,7 @@ const ethStakingBridgeContractAddress = Cypress.env(
|
|||||||
);
|
);
|
||||||
const ethProviderUrl = Cypress.env('ethProviderUrl');
|
const ethProviderUrl = Cypress.env('ethProviderUrl');
|
||||||
const getAccount = (number = 0) => `m/44'/60'/0'/0/${number}`;
|
const getAccount = (number = 0) => `m/44'/60'/0'/0/${number}`;
|
||||||
const transactionTimeout = 100000;
|
const transactionTimeout = { timeout: 100000, log: false };
|
||||||
const Erc20BridgeAddress = '0x9708FF7510D4A7B9541e1699d15b53Ecb1AFDc54';
|
const Erc20BridgeAddress = '0x9708FF7510D4A7B9541e1699d15b53Ecb1AFDc54';
|
||||||
|
|
||||||
const provider = new ethers.providers.JsonRpcProvider({ url: ethProviderUrl });
|
const provider = new ethers.providers.JsonRpcProvider({ url: ethProviderUrl });
|
||||||
@@ -43,10 +43,7 @@ export async function depositAsset(
|
|||||||
const faucet = new Token(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)),
|
||||||
{
|
transactionTimeout
|
||||||
timeout: transactionTimeout,
|
|
||||||
log: false,
|
|
||||||
}
|
|
||||||
).then(() => {
|
).then(() => {
|
||||||
const collateralBridge = new CollateralBridge(Erc20BridgeAddress, signer);
|
const collateralBridge = new CollateralBridge(Erc20BridgeAddress, signer);
|
||||||
cy.wrap(
|
cy.wrap(
|
||||||
@@ -55,7 +52,7 @@ export async function depositAsset(
|
|||||||
amount + '0'.repeat(decimalPlaces),
|
amount + '0'.repeat(decimalPlaces),
|
||||||
'0x' + vegaWalletPubKey
|
'0x' + vegaWalletPubKey
|
||||||
),
|
),
|
||||||
{ timeout: transactionTimeout, log: false }
|
transactionTimeout
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -67,7 +64,6 @@ export async function faucetAsset(assetEthAddress: string) {
|
|||||||
|
|
||||||
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) => {
|
||||||
@@ -80,11 +76,13 @@ export async function vegaWalletTeardown() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
cy.get(vegaWalletContainer).within(() => {
|
cy.get(vegaWalletContainer).within(() => {
|
||||||
cy.get(associatedAmountInWallet, {
|
cy.get(associatedAmountInWallet, transactionTimeout).should(
|
||||||
timeout: transactionTimeout,
|
'have.length',
|
||||||
}).contains('0.00', {
|
1
|
||||||
timeout: transactionTimeout,
|
);
|
||||||
});
|
cy.get(associatedAmountInWallet)
|
||||||
|
.first(transactionTimeout)
|
||||||
|
.should('have.text', '0.00');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -108,7 +106,7 @@ async function vegaWalletTeardownStaking(stakingBridgeContract: StakingBridge) {
|
|||||||
cy.highlight('Tearing down staking tokens from vega wallet if present');
|
cy.highlight('Tearing down staking tokens from vega wallet if present');
|
||||||
cy.wrap(
|
cy.wrap(
|
||||||
stakingBridgeContract.stake_balance(ethWalletPubKey, vegaWalletPubKey),
|
stakingBridgeContract.stake_balance(ethWalletPubKey, vegaWalletPubKey),
|
||||||
{ timeout: transactionTimeout }
|
transactionTimeout
|
||||||
).then((stakeBalance) => {
|
).then((stakeBalance) => {
|
||||||
if (Number(stakeBalance) != 0) {
|
if (Number(stakeBalance) != 0) {
|
||||||
cy.get(vegaWalletContainer).within(() => {
|
cy.get(vegaWalletContainer).within(() => {
|
||||||
@@ -121,31 +119,25 @@ async function vegaWalletTeardownStaking(stakingBridgeContract: StakingBridge) {
|
|||||||
String(stakeBalance),
|
String(stakeBalance),
|
||||||
vegaWalletPubKey
|
vegaWalletPubKey
|
||||||
),
|
),
|
||||||
{ timeout: transactionTimeout }
|
transactionTimeout
|
||||||
);
|
);
|
||||||
cy.wrap(
|
cy.wrap(
|
||||||
vestingContract.stake_balance(ethWalletPubKey, vegaWalletPubKey),
|
vestingContract.stake_balance(ethWalletPubKey, vegaWalletPubKey),
|
||||||
{
|
transactionTimeout
|
||||||
timeout: transactionTimeout,
|
|
||||||
log: false,
|
|
||||||
}
|
|
||||||
).then((vestingAmount) => {
|
).then((vestingAmount) => {
|
||||||
if (Number(vestingAmount) != 0) {
|
if (Number(vestingAmount) != 0) {
|
||||||
cy.contains('Associated', {
|
cy.contains('Associated', transactionTimeout)
|
||||||
timeout: transactionTimeout,
|
|
||||||
})
|
|
||||||
.parent()
|
.parent()
|
||||||
.parent()
|
.parent()
|
||||||
.within(() => {
|
.within(() => {
|
||||||
cy.getByTestId('currency-value', {
|
cy.getByTestId('currency-value', transactionTimeout)
|
||||||
timeout: transactionTimeout,
|
.first()
|
||||||
})
|
|
||||||
.should('have.length', 1)
|
|
||||||
.invoke('text')
|
.invoke('text')
|
||||||
.as('displayedAmount');
|
.as('displayedAmount');
|
||||||
cy.get('@displayedAmount', {
|
cy.get('@displayedAmount', transactionTimeout).should(
|
||||||
timeout: transactionTimeout,
|
'not.eq',
|
||||||
}).should('not.eq', $associatedAmount);
|
$associatedAmount
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -157,14 +149,14 @@ async function vegaWalletTeardownStaking(stakingBridgeContract: StakingBridge) {
|
|||||||
|
|
||||||
async function vegaWalletTeardownVesting(vestingContract: TokenVesting) {
|
async function vegaWalletTeardownVesting(vestingContract: TokenVesting) {
|
||||||
cy.highlight('Tearing down vesting tokens from vega wallet if present');
|
cy.highlight('Tearing down vesting tokens from vega wallet if present');
|
||||||
cy.wrap(vestingContract.stake_balance(ethWalletPubKey, vegaWalletPubKey), {
|
cy.wrap(
|
||||||
timeout: transactionTimeout,
|
vestingContract.stake_balance(ethWalletPubKey, vegaWalletPubKey),
|
||||||
log: false,
|
transactionTimeout
|
||||||
}).then((vestingAmount) => {
|
).then((vestingAmount) => {
|
||||||
if (Number(vestingAmount) != 0) {
|
if (Number(vestingAmount) != 0) {
|
||||||
cy.wrap(
|
cy.wrap(
|
||||||
vestingContract.remove_stake(String(vestingAmount), vegaWalletPubKey),
|
vestingContract.remove_stake(String(vestingAmount), vegaWalletPubKey),
|
||||||
{ timeout: transactionTimeout }
|
transactionTimeout
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -181,3 +173,27 @@ export async function vegaWalletDisassociate(amount: string) {
|
|||||||
amount = amount + '0'.repeat(18);
|
amount = amount + '0'.repeat(18);
|
||||||
stakingBridgeContract.remove_stake(amount, vegaWalletPubKey);
|
stakingBridgeContract.remove_stake(amount, vegaWalletPubKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function vegaWalletFaucetAssetsWithoutCheck(
|
||||||
|
asset: string,
|
||||||
|
amount: string,
|
||||||
|
vegaWalletPublicKey: string
|
||||||
|
) {
|
||||||
|
cy.highlight(`Topping up vega wallet with ${asset}, amount: ${amount}`);
|
||||||
|
cy.exec(
|
||||||
|
`curl -X POST -d '{"amount": "${amount}", "asset": "${asset}", "party": "${vegaWalletPublicKey}"}' http://localhost:1790/api/v1/mint`
|
||||||
|
)
|
||||||
|
.its('stdout')
|
||||||
|
.then((response) => {
|
||||||
|
assert.include(
|
||||||
|
response,
|
||||||
|
`"success":true`,
|
||||||
|
'Ensuring curl command was successfully undertaken'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function switchVegaWalletPubKey() {
|
||||||
|
cy.get('[data-testid="manage-vega-wallet"]:visible').click();
|
||||||
|
cy.get('[data-testid="select-keypair-button"]').eq(0).click();
|
||||||
|
}
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
export function vegaWalletFaucetAssetsWithoutCheck(
|
|
||||||
asset: string,
|
|
||||||
amount: string,
|
|
||||||
vegaWalletPublicKey: string
|
|
||||||
) {
|
|
||||||
cy.highlight(`Topping up vega wallet with ${asset}, amount: ${amount}`);
|
|
||||||
cy.exec(
|
|
||||||
`curl -X POST -d '{"amount": "${amount}", "asset": "${asset}", "party": "${vegaWalletPublicKey}"}' http://localhost:1790/api/v1/mint`
|
|
||||||
)
|
|
||||||
.its('stdout')
|
|
||||||
.then((response) => {
|
|
||||||
assert.include(
|
|
||||||
response,
|
|
||||||
`"success":true`,
|
|
||||||
'Ensuring curl command was successfully undertaken'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -5,16 +5,18 @@ 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.governance.vega.xyz","STAGNET1":"https://stagnet1.governance.vega.xyz","TESTNET":"https://governance.fairground.wtf","MAINNET":"https://governance.vega.xyz"}'
|
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","STAGNET1":"https://governance.stagnet1.vega.rocks","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://explorer.stagnet1.vega.rocks
|
||||||
|
|
||||||
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
NX_HOSTED_WALLET_URL=https://wallet.testnet.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/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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -6,8 +6,10 @@ NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","TESTNET":"https:/
|
|||||||
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=#
|
||||||
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
|
||||||
|
|||||||
@@ -3,12 +3,14 @@ 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.community/graphql
|
NX_VEGA_URL=https://api.vega.community/graphql
|
||||||
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","TESTNET":"https://governance.fairground.wtf","MAINNET":"https://governance.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://mainnet.infura.io/v3/3ba145ccc2884bcd91213d8dc989ca76
|
||||||
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.governance.vega.xyz","STAGNET1":"https://stagnet1.governance.vega.xyz","TESTNET":"https://governance.fairground.wtf","MAINNET":"https://governance.vega.xyz"}'
|
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","STAGNET1":"https://governance.stagnet1.vega.rocks","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://explorer.stagnet1.vega.rocks
|
||||||
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/
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -7,5 +7,7 @@ NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","TESTNET":"https:/
|
|||||||
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://explorer.validators-testnet.vega.rocks/
|
||||||
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
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './multisig-incorrect-notice';
|
||||||
+52
@@ -0,0 +1,52 @@
|
|||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import { useEthereumConfig } from '@vegaprotocol/web3';
|
||||||
|
import { useEnvironment } from '@vegaprotocol/environment';
|
||||||
|
import { MultisigIncorrectNotice } from './multisig-incorrect-notice';
|
||||||
|
|
||||||
|
jest.mock('@vegaprotocol/web3', () => ({
|
||||||
|
useEthereumConfig: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.mock('@vegaprotocol/environment', () => ({
|
||||||
|
useEnvironment: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('MultisigIncorrectNotice', () => {
|
||||||
|
it('renders correctly when config is provided', () => {
|
||||||
|
(useEthereumConfig as jest.Mock).mockReturnValue({
|
||||||
|
config: {
|
||||||
|
multisig_control_contract: {
|
||||||
|
address: '0x1234',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
(useEnvironment as unknown as jest.Mock).mockReturnValue({
|
||||||
|
ETHERSCAN_URL: 'https://etherscan.io',
|
||||||
|
});
|
||||||
|
|
||||||
|
render(<MultisigIncorrectNotice />);
|
||||||
|
|
||||||
|
expect(screen.getByTestId('multisig-contract-link')).toHaveAttribute(
|
||||||
|
'href',
|
||||||
|
'https://etherscan.io/address/0x1234'
|
||||||
|
);
|
||||||
|
expect(screen.getByTestId('multisig-contract-link')).toHaveAttribute(
|
||||||
|
'title',
|
||||||
|
'0x1234'
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
screen.getByTestId('multisig-validators-learn-more')
|
||||||
|
).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not render when config is not provided', () => {
|
||||||
|
(useEthereumConfig as jest.Mock).mockReturnValue({
|
||||||
|
config: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { container } = render(<MultisigIncorrectNotice />);
|
||||||
|
|
||||||
|
expect(container.firstChild).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
+49
@@ -0,0 +1,49 @@
|
|||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { Callout, Intent, Link } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { useEthereumConfig } from '@vegaprotocol/web3';
|
||||||
|
import { useEnvironment, DocsLinks } from '@vegaprotocol/environment';
|
||||||
|
import type { EthereumConfig } from '@vegaprotocol/web3';
|
||||||
|
|
||||||
|
export const MultisigIncorrectNotice = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { config } = useEthereumConfig();
|
||||||
|
const { ETHERSCAN_URL } = useEnvironment();
|
||||||
|
|
||||||
|
if (!config) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const contract = config[
|
||||||
|
'multisig_control_contract' as keyof EthereumConfig
|
||||||
|
] as {
|
||||||
|
address: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mb-10">
|
||||||
|
<Callout intent={Intent.Warning}>
|
||||||
|
<div>
|
||||||
|
<Link
|
||||||
|
title={contract.address}
|
||||||
|
href={`${ETHERSCAN_URL}/address/${contract.address}`}
|
||||||
|
target="_blank"
|
||||||
|
data-testid="multisig-contract-link"
|
||||||
|
>
|
||||||
|
{t('multisigContractLink')}
|
||||||
|
</Link>{' '}
|
||||||
|
{t('multisigContractIncorrect')}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-2">
|
||||||
|
<Link
|
||||||
|
href={DocsLinks?.VALIDATOR_SCORES_REWARDS}
|
||||||
|
target="_blank"
|
||||||
|
data-testid="multisig-validators-learn-more"
|
||||||
|
>
|
||||||
|
{t('learnMore')}
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</Callout>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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')),
|
||||||
|
|||||||
@@ -3,32 +3,32 @@ import { usePendingBalancesStore } from './use-pending-balances-manager';
|
|||||||
import type { Contract } from 'ethers';
|
import type { Contract } from 'ethers';
|
||||||
import { useListenForPendingEthEvents } from './use-listen-for-pending-eth-events';
|
import { useListenForPendingEthEvents } from './use-listen-for-pending-eth-events';
|
||||||
import { prepend0x } from '@vegaprotocol/smart-contracts';
|
import { prepend0x } from '@vegaprotocol/smart-contracts';
|
||||||
|
import { useWeb3React } from '@web3-react/core';
|
||||||
|
|
||||||
export const useListenForStakingEvents = (
|
export const useListenForStakingEvents = (
|
||||||
contract: Contract | undefined,
|
contract: Contract | undefined,
|
||||||
vegaPublicKey: string | null,
|
vegaPublicKey: string | null,
|
||||||
numberOfConfirmations: number
|
numberOfConfirmations: number
|
||||||
) => {
|
) => {
|
||||||
|
const { account } = useWeb3React();
|
||||||
const { addPendingTxs, removePendingTx, resetPendingTxs } =
|
const { addPendingTxs, removePendingTx, resetPendingTxs } =
|
||||||
usePendingBalancesStore((state) => ({
|
usePendingBalancesStore((state) => ({
|
||||||
addPendingTxs: state.addPendingTxs,
|
addPendingTxs: state.addPendingTxs,
|
||||||
removePendingTx: state.removePendingTx,
|
removePendingTx: state.removePendingTx,
|
||||||
resetPendingTxs: state.resetPendingTxs,
|
resetPendingTxs: state.resetPendingTxs,
|
||||||
}));
|
}));
|
||||||
const addFilter = useMemo(
|
const addFilter = useMemo(() => {
|
||||||
() =>
|
if (!account || !vegaPublicKey || !contract) return null;
|
||||||
vegaPublicKey && contract
|
return contract.filters.Stake_Deposited(
|
||||||
? contract.filters.Stake_Deposited(null, null, prepend0x(vegaPublicKey))
|
null,
|
||||||
: null,
|
null,
|
||||||
[contract, vegaPublicKey]
|
prepend0x(vegaPublicKey)
|
||||||
);
|
);
|
||||||
const removeFilter = useMemo(
|
}, [contract, vegaPublicKey, account]);
|
||||||
() =>
|
const removeFilter = useMemo(() => {
|
||||||
vegaPublicKey && contract
|
if (!account || !vegaPublicKey || !contract) return null;
|
||||||
? contract.filters.Stake_Removed(null, null, prepend0x(vegaPublicKey))
|
return contract.filters.Stake_Removed(null, null, prepend0x(vegaPublicKey));
|
||||||
: null,
|
}, [contract, vegaPublicKey, account]);
|
||||||
[contract, vegaPublicKey]
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listen for all add stake events
|
* Listen for all add stake events
|
||||||
|
|||||||
@@ -116,7 +116,7 @@
|
|||||||
"Showing tranches with <{{trancheMinimum}} VEGA, click to hide these tranches": "Showing tranches with ≤{{trancheMinimum}} $VEGA, click to hide these tranches",
|
"Showing tranches with <{{trancheMinimum}} VEGA, click to hide these tranches": "Showing tranches with ≤{{trancheMinimum}} $VEGA, click to hide these tranches",
|
||||||
"Not showing tranches with <{{trancheMinimum}} VEGA, click to show all tranches": "Not showing tranches with ≤{{trancheMinimum}} $VEGA, click to show all tranches",
|
"Not showing tranches with <{{trancheMinimum}} VEGA, click to show all tranches": "Not showing tranches with ≤{{trancheMinimum}} $VEGA, click to show all tranches",
|
||||||
"the holder": "the holder",
|
"the holder": "the holder",
|
||||||
"We couldn't seem to load your data.": "We couldn't seem to load your data.",
|
"Your data couldn't be loaded": "Your data couldn't be loaded",
|
||||||
"Vesting VEGA": "Vesting VEGA",
|
"Vesting VEGA": "Vesting VEGA",
|
||||||
"All the tokens in this tranche are locked and can not be redeemed yet.": "All the tokens in this tranche are locked and can not be redeemed yet.",
|
"All the tokens in this tranche are locked and can not be redeemed yet.": "All the tokens in this tranche are locked and can not be redeemed yet.",
|
||||||
"Redeem unlocked VEGA from tranche {{id}}": "Redeem unlocked $VEGA from tranche {{id}}",
|
"Redeem unlocked VEGA from tranche {{id}}": "Redeem unlocked $VEGA from tranche {{id}}",
|
||||||
@@ -596,6 +596,8 @@
|
|||||||
"noPercentage": "No percentage",
|
"noPercentage": "No percentage",
|
||||||
"proposalJson": "Full proposal JSON",
|
"proposalJson": "Full proposal JSON",
|
||||||
"proposalDetails": "Proposal details",
|
"proposalDetails": "Proposal details",
|
||||||
|
"marketSpecification": "Market specification",
|
||||||
|
"viewMarketJson": "View market JSON",
|
||||||
"proposalDescription": "Description",
|
"proposalDescription": "Description",
|
||||||
"currentlySetTo": "Currently expected to ",
|
"currentlySetTo": "Currently expected to ",
|
||||||
"currently": "currently",
|
"currently": "currently",
|
||||||
@@ -728,8 +730,12 @@
|
|||||||
"ThisWillSetEnactmentDeadlineTo": "This will set the enactment date to",
|
"ThisWillSetEnactmentDeadlineTo": "This will set the enactment date to",
|
||||||
"ThisWillSetValidationDeadlineTo": "This will set the validation deadline to",
|
"ThisWillSetValidationDeadlineTo": "This will set the validation deadline to",
|
||||||
"Hours": "hours",
|
"Hours": "hours",
|
||||||
"ThisWillAdd2MinutesToAllowTimeToConfirmInWallet": "Note: we add 2 minutes of extra time when you choose the minimum value. This gives you time to confirm the proposal in your wallet.",
|
"ThisWillAdd2MinutesToAllowTimeToConfirmInWallet": "Note: 2 minutes of extra time are added when you choose the minimum value. This gives you time to confirm the proposal in your wallet.",
|
||||||
"ProposalWillFailIfEnactmentIsEarlierThanVotingDeadline": "Proposal will fail if enactment is earlier than the voting deadline",
|
"ProposalWillFailIfEnactmentIsEarlierThanVotingDeadline": "The proposal will fail if enactment is earlier than the voting deadline",
|
||||||
|
"ProposalWillFailIfEnactmentIsBelowTheMinimumDeadline": "The proposal will fail if enactment deadline is below the minimum",
|
||||||
|
"ProposalWillFailIfVotingIsBelowTheMinimumDeadline": "The proposal will fail if voting deadline is below the minimum",
|
||||||
|
"ProposalWillFailIfEnactmentIsAboveTheMaximumDeadline": "The proposal will fail if enactment deadline is above the maximum",
|
||||||
|
"ProposalWillFailIfVotingIsAboveTheMaximumDeadline": "The proposal will fail if voting deadline is above the maximum",
|
||||||
"SelectAMarketToChange": "Select a market to change",
|
"SelectAMarketToChange": "Select a market to change",
|
||||||
"MarketName": "Market name",
|
"MarketName": "Market name",
|
||||||
"MarketCode": "Market code",
|
"MarketCode": "Market code",
|
||||||
@@ -780,6 +786,7 @@
|
|||||||
"performancePenalty": "Performance penalty",
|
"performancePenalty": "Performance penalty",
|
||||||
"overstaked": "Overstaked",
|
"overstaked": "Overstaked",
|
||||||
"overstakedPenalty": "Overstaked penalty",
|
"overstakedPenalty": "Overstaked penalty",
|
||||||
|
"multisigPenalty": "Multisig penalty",
|
||||||
"homeProposalsIntro": "Decisions on the Vega network are on-chain, with tokenholders creating proposals that other tokenholders vote to approve or reject. Network upgrades are proposed and approved by validators.",
|
"homeProposalsIntro": "Decisions on the Vega network are on-chain, with tokenholders creating proposals that other tokenholders vote to approve or reject. Network upgrades are proposed and approved by validators.",
|
||||||
"homeProposalsButtonText": "Browse, vote, and propose",
|
"homeProposalsButtonText": "Browse, vote, and propose",
|
||||||
"homeValidatorsIntro": "Vega runs on a delegated proof of stake blockchain, where validators earn fees for validating block transactions. Tokenholders can nominate validators by staking tokens to them.",
|
"homeValidatorsIntro": "Vega runs on a delegated proof of stake blockchain, where validators earn fees for validating block transactions. Tokenholders can nominate validators by staking tokens to them.",
|
||||||
@@ -815,5 +822,16 @@
|
|||||||
"NoThanks": "No thanks",
|
"NoThanks": "No thanks",
|
||||||
"ShareData": "Share data",
|
"ShareData": "Share data",
|
||||||
"ContinueSharingData": "Continue sharing data",
|
"ContinueSharingData": "Continue sharing data",
|
||||||
"NodeUnsuitable": "Node: {{url}} is unsuitable"
|
"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.",
|
||||||
|
"multisigContractLink": "Ethereum Multisig Contract",
|
||||||
|
"multisigContractIncorrect": "is incorrectly configured. Validator and delegator rewards will be penalised until this is resolved.",
|
||||||
|
"learnMore": "Learn more",
|
||||||
|
"AllValidators": "All validators",
|
||||||
|
"AllProposals": "All proposals"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import classnames from 'classnames';
|
||||||
|
|
||||||
|
export const collapsibleToggleStyles = (toggleState: boolean) =>
|
||||||
|
classnames('mb-4 transition-transform ease-in-out duration-300', {
|
||||||
|
'rotate-180': toggleState,
|
||||||
|
});
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
import {
|
||||||
|
getMultisigStatusInfo,
|
||||||
|
MultisigStatus,
|
||||||
|
} from './get-multisig-status-info';
|
||||||
|
import type { PreviousEpochQuery } from '../routes/staking/__generated__/PreviousEpoch';
|
||||||
|
|
||||||
|
const createNode = (id: string, multisigScore: string) => ({
|
||||||
|
node: {
|
||||||
|
id,
|
||||||
|
stakedTotal: '1000',
|
||||||
|
rewardScore: { multisigScore },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getMultisigStatus', () => {
|
||||||
|
it('should return MultisigStatus.noNodes when no nodes are present', () => {
|
||||||
|
const result = getMultisigStatusInfo({
|
||||||
|
epoch: { id: '1', validatorsConnection: { edges: [] } },
|
||||||
|
} as PreviousEpochQuery);
|
||||||
|
expect(result).toEqual({
|
||||||
|
multisigStatus: MultisigStatus.noNodes,
|
||||||
|
showMultisigStatusError: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return MultisigStatus.correct when all nodes have multisigScore of 1', () => {
|
||||||
|
const result = getMultisigStatusInfo({
|
||||||
|
epoch: {
|
||||||
|
id: '1',
|
||||||
|
validatorsConnection: {
|
||||||
|
edges: [createNode('1', '1'), createNode('2', '1')],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as PreviousEpochQuery);
|
||||||
|
expect(result).toEqual({
|
||||||
|
multisigStatus: MultisigStatus.correct,
|
||||||
|
showMultisigStatusError: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return MultisigStatus.nodeNeedsRemoving when all nodes have multisigScore of 0', () => {
|
||||||
|
const result = getMultisigStatusInfo({
|
||||||
|
epoch: {
|
||||||
|
id: '1',
|
||||||
|
validatorsConnection: {
|
||||||
|
edges: [createNode('1', '0'), createNode('2', '0')],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as PreviousEpochQuery);
|
||||||
|
expect(result).toEqual({
|
||||||
|
multisigStatus: MultisigStatus.nodeNeedsRemoving,
|
||||||
|
showMultisigStatusError: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return MultisigStatus.nodeNeedsAdding when some nodes have multisigScore of 0 and others have 1', () => {
|
||||||
|
const result = getMultisigStatusInfo({
|
||||||
|
epoch: {
|
||||||
|
id: '1',
|
||||||
|
validatorsConnection: {
|
||||||
|
edges: [createNode('1', '0'), createNode('2', '1')],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as PreviousEpochQuery);
|
||||||
|
expect(result).toEqual({
|
||||||
|
multisigStatus: MultisigStatus.nodeNeedsAdding,
|
||||||
|
showMultisigStatusError: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import { removePaginationWrapper } from '@vegaprotocol/utils';
|
||||||
|
import type { PreviousEpochQuery } from '../routes/staking/__generated__/PreviousEpoch';
|
||||||
|
|
||||||
|
export enum MultisigStatus {
|
||||||
|
'correct' = 'correct',
|
||||||
|
'nodeNeedsAdding' = 'nodeNeedsAdding',
|
||||||
|
'nodeNeedsRemoving' = 'nodeNeedsRemoving ',
|
||||||
|
'noNodes' = 'noNodes',
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getMultisigStatusInfo = (
|
||||||
|
previousEpochData: PreviousEpochQuery
|
||||||
|
) => {
|
||||||
|
let status = MultisigStatus.noNodes;
|
||||||
|
|
||||||
|
const allNodesInPreviousEpoch = removePaginationWrapper(
|
||||||
|
previousEpochData?.epoch.validatorsConnection?.edges
|
||||||
|
);
|
||||||
|
|
||||||
|
const hasZero = allNodesInPreviousEpoch.some(
|
||||||
|
(node) => Number(node?.rewardScore?.multisigScore) === 0
|
||||||
|
);
|
||||||
|
const hasOne = allNodesInPreviousEpoch.some(
|
||||||
|
(node) => Number(node?.rewardScore?.multisigScore) === 1
|
||||||
|
);
|
||||||
|
|
||||||
|
if (hasZero && hasOne) {
|
||||||
|
// If any individual node has 0 it means that node is missing from the multisig and needs to be added
|
||||||
|
status = MultisigStatus.nodeNeedsAdding;
|
||||||
|
} else if (hasZero) {
|
||||||
|
// If all nodes have 0 it means there is an incorrect address in the multisig that needs to be removed
|
||||||
|
status = MultisigStatus.nodeNeedsRemoving;
|
||||||
|
} else if (allNodesInPreviousEpoch.length > 0) {
|
||||||
|
// If all nodes have 1 it means the multisig is correct
|
||||||
|
status = MultisigStatus.correct;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
showMultisigStatusError: status !== MultisigStatus.correct,
|
||||||
|
multisigStatus: status,
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -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;
|
||||||
@@ -27,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;
|
||||||
|
|
||||||
@@ -200,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) =>
|
||||||
@@ -221,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
|
||||||
);
|
);
|
||||||
|
|||||||
+2
-5
@@ -1,9 +1,9 @@
|
|||||||
import ReactMarkdown from 'react-markdown';
|
import ReactMarkdown from 'react-markdown';
|
||||||
import classnames from 'classnames';
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Icon, RoundedWrapper } from '@vegaprotocol/ui-toolkit';
|
import { Icon, RoundedWrapper } from '@vegaprotocol/ui-toolkit';
|
||||||
import { SubHeading } from '../../../../components/heading';
|
import { SubHeading } from '../../../../components/heading';
|
||||||
|
import { collapsibleToggleStyles } from '../../../../lib/collapsible-toggle-styles';
|
||||||
|
|
||||||
export const ProposalDescription = ({
|
export const ProposalDescription = ({
|
||||||
description,
|
description,
|
||||||
@@ -12,9 +12,6 @@ export const ProposalDescription = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [showDescription, setShowDescription] = useState(false);
|
const [showDescription, setShowDescription] = useState(false);
|
||||||
const showDescriptionIconClasses = classnames('mb-4', {
|
|
||||||
'rotate-180': showDescription,
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section data-testid="proposal-description">
|
<section data-testid="proposal-description">
|
||||||
@@ -24,7 +21,7 @@ export const ProposalDescription = ({
|
|||||||
>
|
>
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<SubHeading title={t('proposalDescription')} />
|
<SubHeading title={t('proposalDescription')} />
|
||||||
<div className={showDescriptionIconClasses}>
|
<div className={collapsibleToggleStyles(showDescription)}>
|
||||||
<Icon name="chevron-down" size={8} />
|
<Icon name="chevron-down" size={8} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+1
-1
@@ -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(
|
||||||
|
|||||||
+13
-2
@@ -21,6 +21,7 @@ export const ProposalHeader = ({
|
|||||||
|
|
||||||
let details: ReactNode;
|
let details: ReactNode;
|
||||||
let proposalType = '';
|
let proposalType = '';
|
||||||
|
let fallbackTitle = '';
|
||||||
|
|
||||||
const title = proposal?.rationale.title.trim();
|
const title = proposal?.rationale.title.trim();
|
||||||
|
|
||||||
@@ -29,6 +30,7 @@ export const ProposalHeader = ({
|
|||||||
switch (change?.__typename) {
|
switch (change?.__typename) {
|
||||||
case 'NewMarket': {
|
case 'NewMarket': {
|
||||||
proposalType = 'NewMarket';
|
proposalType = 'NewMarket';
|
||||||
|
fallbackTitle = t('NewMarketProposal');
|
||||||
details = (
|
details = (
|
||||||
<>
|
<>
|
||||||
<span>
|
<span>
|
||||||
@@ -50,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>{' '}
|
||||||
@@ -60,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>{' '}
|
||||||
@@ -81,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>{' '}
|
||||||
@@ -95,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>{' '}
|
||||||
@@ -115,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>
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import classnames from 'classnames';
|
|
||||||
import { useState } from 'react';
|
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 { collapsibleToggleStyles } from '../../../../lib/collapsible-toggle-styles';
|
||||||
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';
|
||||||
|
|
||||||
@@ -13,9 +13,6 @@ export const ProposalJson = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [showDetails, setShowDetails] = useState(false);
|
const [showDetails, setShowDetails] = useState(false);
|
||||||
const showDetailsIconClasses = classnames('mb-4', {
|
|
||||||
'rotate-180': showDetails,
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section data-testid="proposal-json">
|
<section data-testid="proposal-json">
|
||||||
@@ -25,7 +22,7 @@ export const ProposalJson = ({
|
|||||||
>
|
>
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<SubHeading title={t('proposalJson')} />
|
<SubHeading title={t('proposalJson')} />
|
||||||
<div className={showDetailsIconClasses}>
|
<div className={collapsibleToggleStyles(showDetails)}>
|
||||||
<Icon name="chevron-down" size={8} />
|
<Icon name="chevron-down" size={8} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './proposal-market-data';
|
||||||
+222
@@ -0,0 +1,222 @@
|
|||||||
|
import isEqual from 'lodash/isEqual';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import {
|
||||||
|
InstrumentInfoPanel,
|
||||||
|
KeyDetailsInfoPanel,
|
||||||
|
LiquidityMonitoringParametersInfoPanel,
|
||||||
|
LiquidityPriceRangeInfoPanel,
|
||||||
|
MetadataInfoPanel,
|
||||||
|
OracleInfoPanel,
|
||||||
|
PriceMonitoringBoundsInfoPanel,
|
||||||
|
RiskFactorsInfoPanel,
|
||||||
|
RiskModelInfoPanel,
|
||||||
|
RiskParametersInfoPanel,
|
||||||
|
SettlementAssetInfoPanel,
|
||||||
|
} from '@vegaprotocol/markets';
|
||||||
|
import {
|
||||||
|
Accordion,
|
||||||
|
AccordionItem,
|
||||||
|
Button,
|
||||||
|
CopyWithTooltip,
|
||||||
|
Dialog,
|
||||||
|
Icon,
|
||||||
|
SyntaxHighlighter,
|
||||||
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { SubHeading } from '../../../../components/heading';
|
||||||
|
import { collapsibleToggleStyles } from '../../../../lib/collapsible-toggle-styles';
|
||||||
|
import type { MarketInfoWithData } from '@vegaprotocol/markets';
|
||||||
|
import type { DataSourceDefinition } from '@vegaprotocol/types';
|
||||||
|
import { create } from 'zustand';
|
||||||
|
|
||||||
|
type MarketDataDialogState = {
|
||||||
|
isOpen: boolean;
|
||||||
|
open: () => void;
|
||||||
|
close: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useMarketDataDialogStore = create<MarketDataDialogState>(
|
||||||
|
(set) => ({
|
||||||
|
isOpen: false,
|
||||||
|
open: () => set({ isOpen: true }),
|
||||||
|
close: () => set({ isOpen: false }),
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
export const ProposalMarketData = ({
|
||||||
|
marketData,
|
||||||
|
}: {
|
||||||
|
marketData: MarketInfoWithData;
|
||||||
|
}) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { isOpen, open, close } = useMarketDataDialogStore();
|
||||||
|
const [showDetails, setShowDetails] = useState(false);
|
||||||
|
|
||||||
|
if (!marketData) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const settlementData = marketData.tradableInstrument.instrument.product
|
||||||
|
.dataSourceSpecForSettlementData.data as DataSourceDefinition;
|
||||||
|
const terminationData = marketData.tradableInstrument.instrument.product
|
||||||
|
.dataSourceSpecForTradingTermination.data as DataSourceDefinition;
|
||||||
|
|
||||||
|
const getSigners = (data: DataSourceDefinition) => {
|
||||||
|
if (data.sourceType.__typename === 'DataSourceDefinitionExternal') {
|
||||||
|
const signers = data.sourceType.sourceType.signers || [];
|
||||||
|
|
||||||
|
return signers.map(({ signer }) => {
|
||||||
|
return (
|
||||||
|
(signer.__typename === 'ETHAddress' && signer.address) ||
|
||||||
|
(signer.__typename === 'PubKey' && signer.key)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="relative" data-testid="proposal-market-data">
|
||||||
|
<button
|
||||||
|
onClick={() => setShowDetails(!showDetails)}
|
||||||
|
data-testid="proposal-market-data-toggle"
|
||||||
|
>
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<SubHeading title={t('marketSpecification')} />
|
||||||
|
<div className={collapsibleToggleStyles(showDetails)}>
|
||||||
|
<Icon name="chevron-down" size={8} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{showDetails && (
|
||||||
|
<>
|
||||||
|
<div className="float-right">
|
||||||
|
<Button onClick={open} data-testid="view-market-json">
|
||||||
|
{t('viewMarketJson')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div className="mb-10">
|
||||||
|
<Accordion>
|
||||||
|
<AccordionItem
|
||||||
|
itemId="key-details"
|
||||||
|
title={t('Key details')}
|
||||||
|
content={<KeyDetailsInfoPanel market={marketData} />}
|
||||||
|
/>
|
||||||
|
<AccordionItem
|
||||||
|
itemId="instrument"
|
||||||
|
title={t('Instrument')}
|
||||||
|
content={<InstrumentInfoPanel market={marketData} />}
|
||||||
|
/>
|
||||||
|
{isEqual(
|
||||||
|
getSigners(settlementData),
|
||||||
|
getSigners(terminationData)
|
||||||
|
) ? (
|
||||||
|
<AccordionItem
|
||||||
|
itemId="oracles"
|
||||||
|
title={t('Oracle')}
|
||||||
|
content={
|
||||||
|
<OracleInfoPanel
|
||||||
|
market={marketData}
|
||||||
|
type="settlementData"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<AccordionItem
|
||||||
|
itemId="settlement-oracle"
|
||||||
|
title={t('Settlement Oracle')}
|
||||||
|
content={
|
||||||
|
<OracleInfoPanel
|
||||||
|
market={marketData}
|
||||||
|
type="settlementData"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<AccordionItem
|
||||||
|
itemId="termination-oracle"
|
||||||
|
title={t('Termination Oracle')}
|
||||||
|
content={
|
||||||
|
<OracleInfoPanel market={marketData} type="termination" />
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<AccordionItem
|
||||||
|
itemId="settlement-asset"
|
||||||
|
title={t('Settlement asset')}
|
||||||
|
content={<SettlementAssetInfoPanel market={marketData} />}
|
||||||
|
/>
|
||||||
|
<AccordionItem
|
||||||
|
itemId="metadata"
|
||||||
|
title={t('Metadata')}
|
||||||
|
content={<MetadataInfoPanel market={marketData} />}
|
||||||
|
/>
|
||||||
|
<AccordionItem
|
||||||
|
itemId="risk-model"
|
||||||
|
title={t('Risk model')}
|
||||||
|
content={<RiskModelInfoPanel market={marketData} />}
|
||||||
|
/>
|
||||||
|
<AccordionItem
|
||||||
|
itemId="risk-parameters"
|
||||||
|
title={t('Risk parameters')}
|
||||||
|
content={<RiskParametersInfoPanel market={marketData} />}
|
||||||
|
/>
|
||||||
|
<AccordionItem
|
||||||
|
itemId="risk-factors"
|
||||||
|
title={t('Risk factors')}
|
||||||
|
content={<RiskFactorsInfoPanel market={marketData} />}
|
||||||
|
/>
|
||||||
|
{(
|
||||||
|
marketData.priceMonitoringSettings?.parameters?.triggers || []
|
||||||
|
).map((_, triggerIndex) => (
|
||||||
|
<AccordionItem
|
||||||
|
itemId={`trigger-${triggerIndex}`}
|
||||||
|
title={t(`Price monitoring bounds ${triggerIndex + 1}`)}
|
||||||
|
content={
|
||||||
|
<PriceMonitoringBoundsInfoPanel
|
||||||
|
market={marketData}
|
||||||
|
triggerIndex={triggerIndex}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
<AccordionItem
|
||||||
|
itemId="liqudity-monitoring-parameters"
|
||||||
|
title={t('Liquidity monitoring parameters')}
|
||||||
|
content={
|
||||||
|
<LiquidityMonitoringParametersInfoPanel market={marketData} />
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<AccordionItem
|
||||||
|
itemId="liquidity-price-range"
|
||||||
|
title={t('Liquidity price range')}
|
||||||
|
content={<LiquidityPriceRangeInfoPanel market={marketData} />}
|
||||||
|
/>
|
||||||
|
</Accordion>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Dialog
|
||||||
|
title={marketData.tradableInstrument.instrument.code}
|
||||||
|
open={isOpen}
|
||||||
|
onChange={(isOpen) => (isOpen ? open() : close())}
|
||||||
|
size="medium"
|
||||||
|
dataTestId="market-json-dialog"
|
||||||
|
>
|
||||||
|
<CopyWithTooltip text={JSON.stringify(marketData)}>
|
||||||
|
<button className="bg-vega-dark-100 rounded-sm py-2 px-3 mb-4 text-white">
|
||||||
|
<span>
|
||||||
|
<Icon name="duplicate" />
|
||||||
|
</span>
|
||||||
|
<span className="ml-2">Copy</span>
|
||||||
|
</button>
|
||||||
|
</CopyWithTooltip>
|
||||||
|
<SyntaxHighlighter data={marketData} />
|
||||||
|
</Dialog>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
+2
-6
@@ -1,4 +1,3 @@
|
|||||||
import classnames from 'classnames';
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import {
|
import {
|
||||||
@@ -13,6 +12,7 @@ import { SubHeading } from '../../../../components/heading';
|
|||||||
import { useVoteInformation } from '../../hooks';
|
import { useVoteInformation } from '../../hooks';
|
||||||
import { useAppState } from '../../../../contexts/app-state/app-state-context';
|
import { useAppState } from '../../../../contexts/app-state/app-state-context';
|
||||||
import { ProposalType } from '../proposal/proposal';
|
import { ProposalType } from '../proposal/proposal';
|
||||||
|
import { collapsibleToggleStyles } from '../../../../lib/collapsible-toggle-styles';
|
||||||
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';
|
||||||
|
|
||||||
@@ -57,10 +57,6 @@ export const ProposalVotesTable = ({
|
|||||||
? t('byTokenVote')
|
? t('byTokenVote')
|
||||||
: t('byLiquidityVote');
|
: t('byLiquidityVote');
|
||||||
|
|
||||||
const showDetailsIconClasses = classnames('mb-4', {
|
|
||||||
'rotate-180': showDetails,
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<button
|
<button
|
||||||
@@ -69,7 +65,7 @@ export const ProposalVotesTable = ({
|
|||||||
>
|
>
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<SubHeading title={t('voteBreakdown')} />
|
<SubHeading title={t('voteBreakdown')} />
|
||||||
<div className={showDetailsIconClasses}>
|
<div className={collapsibleToggleStyles(showDetails)}>
|
||||||
<Icon name="chevron-down" size={8} />
|
<Icon name="chevron-down" size={8} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
import { generateProposal } from '../../test-helpers/generate-proposals';
|
import { generateProposal } from '../../test-helpers/generate-proposals';
|
||||||
import { Proposal } from './proposal';
|
import { Proposal } from './proposal';
|
||||||
@@ -28,9 +29,6 @@ jest.mock('../proposal-change-table', () => ({
|
|||||||
jest.mock('../proposal-json', () => ({
|
jest.mock('../proposal-json', () => ({
|
||||||
ProposalJson: () => <div data-testid="proposal-json"></div>,
|
ProposalJson: () => <div data-testid="proposal-json"></div>,
|
||||||
}));
|
}));
|
||||||
jest.mock('../proposal-terms/proposal-terms', () => ({
|
|
||||||
ProposalTerms: () => <div data-testid="proposal-terms"></div>,
|
|
||||||
}));
|
|
||||||
jest.mock('../proposal-votes-table', () => ({
|
jest.mock('../proposal-votes-table', () => ({
|
||||||
ProposalVotesTable: () => <div data-testid="proposal-votes-table"></div>,
|
ProposalVotesTable: () => <div data-testid="proposal-votes-table"></div>,
|
||||||
}));
|
}));
|
||||||
@@ -41,19 +39,38 @@ jest.mock('../list-asset', () => ({
|
|||||||
ListAsset: () => <div data-testid="proposal-list-asset"></div>,
|
ListAsset: () => <div data-testid="proposal-list-asset"></div>,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const renderComponent = (proposal: ProposalQuery['proposal']) => {
|
||||||
|
render(
|
||||||
|
<MemoryRouter>
|
||||||
|
<Proposal
|
||||||
|
restData={{}}
|
||||||
|
proposal={proposal as ProposalQuery['proposal']}
|
||||||
|
/>
|
||||||
|
</MemoryRouter>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
it('Renders with data-testid', async () => {
|
it('Renders with data-testid', async () => {
|
||||||
const proposal = generateProposal();
|
const proposal = generateProposal();
|
||||||
render(<Proposal proposal={proposal as ProposalQuery['proposal']} />);
|
renderComponent(proposal);
|
||||||
|
|
||||||
expect(await screen.findByTestId('proposal')).toBeInTheDocument();
|
expect(await screen.findByTestId('proposal')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Renders with a link back to "all proposals"', async () => {
|
||||||
|
const proposal = generateProposal();
|
||||||
|
renderComponent(proposal);
|
||||||
|
|
||||||
|
expect(await screen.findByTestId('all-proposals-link')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
it('renders each section', async () => {
|
it('renders each section', async () => {
|
||||||
const proposal = generateProposal();
|
const proposal = generateProposal();
|
||||||
render(<Proposal proposal={proposal as ProposalQuery['proposal']} />);
|
renderComponent(proposal);
|
||||||
|
|
||||||
expect(await screen.findByTestId('proposal-header')).toBeInTheDocument();
|
expect(await screen.findByTestId('proposal-header')).toBeInTheDocument();
|
||||||
expect(screen.getByTestId('proposal-change-table')).toBeInTheDocument();
|
expect(screen.getByTestId('proposal-change-table')).toBeInTheDocument();
|
||||||
expect(screen.getByTestId('proposal-json')).toBeInTheDocument();
|
expect(screen.getByTestId('proposal-json')).toBeInTheDocument();
|
||||||
expect(screen.getByTestId('proposal-terms')).toBeInTheDocument();
|
|
||||||
expect(screen.getByTestId('proposal-votes-table')).toBeInTheDocument();
|
expect(screen.getByTestId('proposal-votes-table')).toBeInTheDocument();
|
||||||
expect(screen.getByTestId('proposal-vote-details')).toBeInTheDocument();
|
expect(screen.getByTestId('proposal-vote-details')).toBeInTheDocument();
|
||||||
expect(screen.queryByTestId('proposal-list-asset')).not.toBeInTheDocument();
|
expect(screen.queryByTestId('proposal-list-asset')).not.toBeInTheDocument();
|
||||||
@@ -76,6 +93,7 @@ it('renders whitelist section if proposal is new asset and source is erc20', asy
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
render(<Proposal proposal={proposal as ProposalQuery['proposal']} />);
|
renderComponent(proposal);
|
||||||
|
|
||||||
expect(screen.getByTestId('proposal-list-asset')).toBeInTheDocument();
|
expect(screen.getByTestId('proposal-list-asset')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,18 +1,22 @@
|
|||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
NetworkParams,
|
NetworkParams,
|
||||||
useNetworkParams,
|
useNetworkParams,
|
||||||
} from '@vegaprotocol/network-parameters';
|
} from '@vegaprotocol/network-parameters';
|
||||||
import { AsyncRenderer, RoundedWrapper } from '@vegaprotocol/ui-toolkit';
|
import { AsyncRenderer, Icon, RoundedWrapper } from '@vegaprotocol/ui-toolkit';
|
||||||
import { ProposalHeader } from '../proposal-detail-header/proposal-header';
|
import { ProposalHeader } from '../proposal-detail-header/proposal-header';
|
||||||
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
|
|
||||||
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
|
|
||||||
import { ProposalDescription } from '../proposal-description';
|
import { ProposalDescription } from '../proposal-description';
|
||||||
import { ProposalChangeTable } from '../proposal-change-table';
|
import { ProposalChangeTable } from '../proposal-change-table';
|
||||||
import { ProposalJson } from '../proposal-json';
|
import { ProposalJson } from '../proposal-json';
|
||||||
import { ProposalTerms } from '../proposal-terms';
|
|
||||||
import { ProposalVotesTable } from '../proposal-votes-table';
|
import { ProposalVotesTable } from '../proposal-votes-table';
|
||||||
import { VoteDetails } from '../vote-details';
|
import { VoteDetails } from '../vote-details';
|
||||||
import { ListAsset } from '../list-asset';
|
import { ListAsset } from '../list-asset';
|
||||||
|
import Routes from '../../../routes';
|
||||||
|
import { ProposalMarketData } from '../proposal-market-data';
|
||||||
|
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
|
||||||
|
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
|
||||||
|
import type { MarketInfoWithData } from '@vegaprotocol/markets';
|
||||||
|
|
||||||
export enum ProposalType {
|
export enum ProposalType {
|
||||||
PROPOSAL_NEW_MARKET = 'PROPOSAL_NEW_MARKET',
|
PROPOSAL_NEW_MARKET = 'PROPOSAL_NEW_MARKET',
|
||||||
@@ -24,9 +28,17 @@ export enum ProposalType {
|
|||||||
}
|
}
|
||||||
export interface ProposalProps {
|
export interface ProposalProps {
|
||||||
proposal: ProposalFieldsFragment | ProposalQuery['proposal'];
|
proposal: ProposalFieldsFragment | ProposalQuery['proposal'];
|
||||||
|
newMarketData?: MarketInfoWithData | null;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
restData: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Proposal = ({ proposal }: ProposalProps) => {
|
export const Proposal = ({
|
||||||
|
proposal,
|
||||||
|
restData,
|
||||||
|
newMarketData,
|
||||||
|
}: ProposalProps) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const { params, loading, error } = useNetworkParams([
|
const { params, loading, error } = useNetworkParams([
|
||||||
NetworkParams.governance_proposal_market_minVoterBalance,
|
NetworkParams.governance_proposal_market_minVoterBalance,
|
||||||
NetworkParams.governance_proposal_updateMarket_minVoterBalance,
|
NetworkParams.governance_proposal_updateMarket_minVoterBalance,
|
||||||
@@ -79,49 +91,69 @@ export const Proposal = ({ proposal }: ProposalProps) => {
|
|||||||
return (
|
return (
|
||||||
<AsyncRenderer data={params} loading={loading} error={error}>
|
<AsyncRenderer data={params} loading={loading} error={error}>
|
||||||
<section data-testid="proposal">
|
<section data-testid="proposal">
|
||||||
|
<div
|
||||||
|
className="flex items-center gap-1"
|
||||||
|
data-testid="all-proposals-link"
|
||||||
|
>
|
||||||
|
<Icon name={'chevron-left'} />
|
||||||
|
<Link className="underline" to={Routes.PROPOSALS}>
|
||||||
|
{t('AllProposals')}
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
<ProposalHeader proposal={proposal} isListItem={false} />
|
<ProposalHeader proposal={proposal} isListItem={false} />
|
||||||
|
|
||||||
<div className="my-10">
|
<div id="details">
|
||||||
<ProposalChangeTable proposal={proposal} />
|
<div className="my-10">
|
||||||
|
<ProposalChangeTable proposal={proposal} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{proposal.terms.change.__typename === 'NewAsset' &&
|
||||||
|
proposal.terms.change.source.__typename === 'ERC20' &&
|
||||||
|
proposal.id ? (
|
||||||
|
<ListAsset
|
||||||
|
assetId={proposal.id}
|
||||||
|
withdrawalThreshold={
|
||||||
|
proposal.terms.change.source.withdrawThreshold
|
||||||
|
}
|
||||||
|
lifetimeLimit={proposal.terms.change.source.lifetimeLimit}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
<div className="mb-4">
|
||||||
|
<ProposalDescription description={proposal.rationale.description} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{newMarketData && (
|
||||||
|
<div className="mb-4">
|
||||||
|
<ProposalMarketData marketData={newMarketData} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="mb-6">
|
||||||
|
<ProposalJson proposal={restData?.data?.proposal} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{proposal.terms.change.__typename === 'NewAsset' &&
|
<div id="voting">
|
||||||
proposal.terms.change.source.__typename === 'ERC20' &&
|
<div className="mb-10">
|
||||||
proposal.id ? (
|
<RoundedWrapper paddingBottom={true}>
|
||||||
<ListAsset
|
<VoteDetails
|
||||||
assetId={proposal.id}
|
proposal={proposal}
|
||||||
withdrawalThreshold={proposal.terms.change.source.withdrawThreshold}
|
proposalType={proposalType}
|
||||||
lifetimeLimit={proposal.terms.change.source.lifetimeLimit}
|
minVoterBalance={minVoterBalance}
|
||||||
/>
|
spamProtectionMinTokens={
|
||||||
) : null}
|
params?.spam_protection_voting_min_tokens
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</RoundedWrapper>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
<ProposalDescription description={proposal.rationale.description} />
|
<ProposalVotesTable
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mb-4">
|
|
||||||
<ProposalTerms data={proposal.terms} />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mb-6">
|
|
||||||
<ProposalJson proposal={proposal} />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mb-10">
|
|
||||||
<RoundedWrapper paddingBottom={true}>
|
|
||||||
<VoteDetails
|
|
||||||
proposal={proposal}
|
proposal={proposal}
|
||||||
proposalType={proposalType}
|
proposalType={proposalType}
|
||||||
minVoterBalance={minVoterBalance}
|
|
||||||
spamProtectionMinTokens={
|
|
||||||
params?.spam_protection_voting_min_tokens
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</RoundedWrapper>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mb-4">
|
|
||||||
<ProposalVotesTable proposal={proposal} proposalType={proposalType} />
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</AsyncRenderer>
|
</AsyncRenderer>
|
||||||
|
|||||||
-23
@@ -115,29 +115,6 @@ describe('Proposals list', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Orders proposals correctly by closingDateTime', () => {
|
|
||||||
render(
|
|
||||||
renderComponent([
|
|
||||||
failedProposalClosedLastMonth,
|
|
||||||
openProposalClosesNextMonth,
|
|
||||||
openProposalClosesNextWeek,
|
|
||||||
enactedProposalClosedLastWeek,
|
|
||||||
])
|
|
||||||
);
|
|
||||||
const openProposals = within(screen.getByTestId('open-proposals'));
|
|
||||||
const closedProposals = within(screen.getByTestId('closed-proposals'));
|
|
||||||
const openProposalsItems = openProposals.getAllByTestId(
|
|
||||||
'proposals-list-item'
|
|
||||||
);
|
|
||||||
const closedProposalsItems = closedProposals.getAllByTestId(
|
|
||||||
'proposals-list-item'
|
|
||||||
);
|
|
||||||
expect(openProposalsItems[0]).toHaveAttribute('id', 'proposal1');
|
|
||||||
expect(openProposalsItems[1]).toHaveAttribute('id', 'proposal2');
|
|
||||||
expect(closedProposalsItems[0]).toHaveAttribute('id', 'proposal4');
|
|
||||||
expect(closedProposalsItems[1]).toHaveAttribute('id', 'proposal3');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Displays info on no proposals', () => {
|
it('Displays info on no proposals', () => {
|
||||||
render(renderComponent([]));
|
render(renderComponent([]));
|
||||||
expect(screen.queryByTestId('open-proposals')).not.toBeInTheDocument();
|
expect(screen.queryByTestId('open-proposals')).not.toBeInTheDocument();
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
|
import orderBy from 'lodash/orderBy';
|
||||||
import { isFuture } from 'date-fns';
|
import { isFuture } from 'date-fns';
|
||||||
import { useState } from 'react';
|
import { useState, useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Heading, SubHeading } from '../../../../components/heading';
|
import { Heading, SubHeading } from '../../../../components/heading';
|
||||||
import { ProposalsListItem } from '../proposals-list-item';
|
import { ProposalsListItem } from '../proposals-list-item';
|
||||||
@@ -30,6 +31,29 @@ interface SortedProtocolUpgradeProposalsProps {
|
|||||||
closed: ProtocolUpgradeProposalFieldsFragment[];
|
closed: ProtocolUpgradeProposalFieldsFragment[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const orderByDate = (arr: ProposalFieldsFragment[]) =>
|
||||||
|
orderBy(
|
||||||
|
arr,
|
||||||
|
[
|
||||||
|
(p) =>
|
||||||
|
p?.terms?.enactmentDatetime
|
||||||
|
? new Date(p?.terms?.enactmentDatetime).getTime()
|
||||||
|
: // has to be defaulted to 0 because new Date(null).getTime() -> NaN which is first when ordered
|
||||||
|
new Date(p?.terms?.closingDatetime || 0).getTime(),
|
||||||
|
(p) => new Date(p?.datetime).getTime(),
|
||||||
|
],
|
||||||
|
['asc', 'asc']
|
||||||
|
);
|
||||||
|
|
||||||
|
export const orderByUpgradeBlockHeight = (
|
||||||
|
arr: ProtocolUpgradeProposalFieldsFragment[]
|
||||||
|
) =>
|
||||||
|
orderBy(
|
||||||
|
arr,
|
||||||
|
[(p) => p?.upgradeBlockHeight, (p) => p.vegaReleaseTag],
|
||||||
|
['desc', 'desc']
|
||||||
|
);
|
||||||
|
|
||||||
export const ProposalsList = ({
|
export const ProposalsList = ({
|
||||||
proposals,
|
proposals,
|
||||||
protocolUpgradeProposals,
|
protocolUpgradeProposals,
|
||||||
@@ -37,35 +61,57 @@ export const ProposalsList = ({
|
|||||||
}: ProposalsListProps) => {
|
}: ProposalsListProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [filterString, setFilterString] = useState('');
|
const [filterString, setFilterString] = useState('');
|
||||||
const sortedProposals = proposals.reduce(
|
|
||||||
(acc: SortedProposalsProps, proposal) => {
|
|
||||||
if (isFuture(new Date(proposal?.terms.closingDatetime))) {
|
|
||||||
acc.open.push(proposal);
|
|
||||||
} else {
|
|
||||||
acc.closed.push(proposal);
|
|
||||||
}
|
|
||||||
return acc;
|
|
||||||
},
|
|
||||||
{
|
|
||||||
open: [],
|
|
||||||
closed: [],
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const sortedProtocolUpgradeProposals = protocolUpgradeProposals.reduce(
|
const sortedProposals: SortedProposalsProps = useMemo(() => {
|
||||||
(acc: SortedProtocolUpgradeProposalsProps, proposal) => {
|
const initialSorting = proposals.reduce(
|
||||||
if (Number(proposal?.upgradeBlockHeight) > Number(lastBlockHeight)) {
|
(acc: SortedProposalsProps, proposal) => {
|
||||||
acc.open.push(proposal);
|
if (isFuture(new Date(proposal?.terms.closingDatetime))) {
|
||||||
} else {
|
acc.open.push(proposal);
|
||||||
acc.closed.push(proposal);
|
} else {
|
||||||
|
acc.closed.push(proposal);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
open: [],
|
||||||
|
closed: [],
|
||||||
}
|
}
|
||||||
return acc;
|
);
|
||||||
},
|
return {
|
||||||
{
|
open:
|
||||||
open: [],
|
initialSorting.open.length > 0
|
||||||
closed: [],
|
? orderByDate(initialSorting.open as ProposalFieldsFragment[])
|
||||||
}
|
: [],
|
||||||
);
|
closed:
|
||||||
|
initialSorting.closed.length > 0
|
||||||
|
? orderByDate(
|
||||||
|
initialSorting.closed as ProposalFieldsFragment[]
|
||||||
|
).reverse()
|
||||||
|
: [],
|
||||||
|
};
|
||||||
|
}, [proposals]);
|
||||||
|
|
||||||
|
const sortedProtocolUpgradeProposals: SortedProtocolUpgradeProposalsProps =
|
||||||
|
useMemo(() => {
|
||||||
|
const initialSorting = protocolUpgradeProposals.reduce(
|
||||||
|
(acc: SortedProtocolUpgradeProposalsProps, proposal) => {
|
||||||
|
if (Number(proposal?.upgradeBlockHeight) > Number(lastBlockHeight)) {
|
||||||
|
acc.open.push(proposal);
|
||||||
|
} else {
|
||||||
|
acc.closed.push(proposal);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
open: [],
|
||||||
|
closed: [],
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
open: orderByUpgradeBlockHeight(initialSorting.open),
|
||||||
|
closed: orderByUpgradeBlockHeight(initialSorting.closed).reverse(),
|
||||||
|
};
|
||||||
|
}, [protocolUpgradeProposals, lastBlockHeight]);
|
||||||
|
|
||||||
const filterPredicate = (
|
const filterPredicate = (
|
||||||
p: ProposalFieldsFragment | ProposalQuery['proposal']
|
p: ProposalFieldsFragment | ProposalQuery['proposal']
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user