Compare commits
84
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
@@ -48,7 +48,8 @@ jobs:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
id: ${{ github.event.release.id }}
|
||||
body: |
|
||||
---
|
||||
|
||||
___
|
||||
|
||||
# Deployments
|
||||
* https://explorer.vega.xyz
|
||||
|
||||
@@ -98,36 +98,37 @@ jobs:
|
||||
# See affected apps
|
||||
- name: See affected apps
|
||||
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 "NX_BASE: ${{ env.NX_BASE }}"
|
||||
echo "NX_HEAD: ${{ env.NX_HEAD }}"
|
||||
echo "Affected: ${affected}"
|
||||
echo "Branch slug: ${branch_slug}"
|
||||
echo ">>>> eof debug"
|
||||
|
||||
affected="$(yarn nx print-affected --base=${{ env.NX_BASE }} --head=${{ env.NX_HEAD }} --select=projects)"
|
||||
|
||||
branch_slug="$(echo '${{ github.head_ref || github.ref_name }}' | sed -r s/[^a-zA-Z0-9]+/-/g | sed -r s/^-+\|-+$//g | cut -c 1-50 )"
|
||||
projects_e2e=""
|
||||
preview_governance="not deployed"
|
||||
preview_trading="not deployed"
|
||||
preview_explorer="not deployed"
|
||||
if [[ $affected == *"governance"* ]]; then
|
||||
projects_e2e+='"governance-e2e" '
|
||||
preview_governance=$(printf "https://%s.%s.vega.rocks" "governance" "$branch_slug")
|
||||
fi
|
||||
if [[ $affected == *"trading"* ]]; then
|
||||
projects_e2e+='"trading-e2e" '
|
||||
preview_trading=$(printf "https://%s.%s.vega.rocks" "trading" "$branch_slug")
|
||||
fi
|
||||
if [[ $affected == *"explorer"* ]]; then
|
||||
projects_e2e+='"explorer-e2e" '
|
||||
preview_explorer=$(printf "https://%s.%s.vega.rocks" "explorer" "$branch_slug")
|
||||
fi
|
||||
if [[ -z "$projects_e2e" ]]; then
|
||||
projects_e2e+='"governance-e2e" "trading-e2e" "explorer-e2e" '
|
||||
preview_governance=$(printf "https://%s.%s.vega.rocks" "governance" "$branch_slug")
|
||||
preview_trading=$(printf "https://%s.%s.vega.rocks" "trading" "$branch_slug")
|
||||
preview_explorer=$(printf "https://%s.%s.vega.rocks" "explorer" "$branch_slug")
|
||||
else
|
||||
if [[ $affected == *"governance"* ]]; then
|
||||
projects_e2e+='"governance-e2e" '
|
||||
preview_governance=$(printf "https://%s.%s.vega.rocks" "governance" "$branch_slug")
|
||||
fi
|
||||
if [[ $affected == *"trading"* ]]; then
|
||||
projects_e2e+='"trading-e2e" '
|
||||
preview_trading=$(printf "https://%s.%s.vega.rocks" "trading" "$branch_slug")
|
||||
fi
|
||||
if [[ $affected == *"explorer"* ]]; then
|
||||
projects_e2e+='"explorer-e2e" '
|
||||
preview_explorer=$(printf "https://%s.%s.vega.rocks" "explorer" "$branch_slug")
|
||||
fi
|
||||
fi
|
||||
projects_e2e=${projects_e2e%?}
|
||||
projects_e2e=[${projects_e2e// /,}]
|
||||
|
||||
@@ -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
|
||||
@@ -59,24 +59,39 @@ jobs:
|
||||
key: ${{ runner.os }}-cache-node-modules-${{ hashFiles('yarn.lock') }}
|
||||
|
||||
# https://docs.github.com/en/actions/learn-github-actions/contexts
|
||||
- name: Define variables
|
||||
- name: Define dist variables
|
||||
if: ${{ github.event_name == 'push' }}
|
||||
run: |
|
||||
envName=''
|
||||
if [[ "${{ github.event_name }}" = "push" ]]; then
|
||||
domain="vega.rocks"
|
||||
if [[ "${{ github.ref }}" =~ .*release/.* ]]; then
|
||||
envName="$(echo ${{ github.ref }} | rev | cut -d '/' -f 1 | rev)"
|
||||
if [[ "${{ github.ref }}" =~ .*mainnet.* ]]; then
|
||||
domain="vega.community"
|
||||
fi
|
||||
elif [[ "${{ github.ref }}" =~ .*develop$ ]]; then
|
||||
envName="stagnet1"
|
||||
elif [[ "${{ matrix.app}}" = "trading" ]] && [[ ${{ startsWith(github.ref, 'refs/tags/v') && 'true' || 'false' }} = "true" ]]; then
|
||||
envName="mainnet"
|
||||
fi
|
||||
bucketName="${{ matrix.app }}.${envName}.${domain}"
|
||||
echo BUCKET_NAME=${bucketName} >> $GITHUB_ENV
|
||||
domain="vega.rocks"
|
||||
bucketName=''
|
||||
|
||||
if [[ "${{ github.ref }}" =~ .*release/.* ]]; then
|
||||
envName="$(echo ${{ github.ref }} | rev | cut -d '/' -f 1 | rev)"
|
||||
elif [[ "${{ github.ref }}" =~ .*develop$ ]]; then
|
||||
envName="stagnet1"
|
||||
elif [[ "${{ github.ref }}" =~ .*main$ ]]; then
|
||||
envName="mainnet"
|
||||
elif [[ "${{ matrix.app}}" = "trading" ]] && [[ "${{ startsWith(github.ref, 'refs/tags/v') && 'true' || 'false' }}" = "true" ]]; then
|
||||
envName="mainnet"
|
||||
fi
|
||||
|
||||
if [[ "${envName}" = "mainnet" ]]; then
|
||||
domain="vega.xyz"
|
||||
bucketName="${{ matrix.app }}.${domain}"
|
||||
elif [[ "${envName}" = "testnet" ]]; then
|
||||
domain="fairground.wtf"
|
||||
bucketName="${{ matrix.app }}.${domain}"
|
||||
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
|
||||
|
||||
- name: Build local dist
|
||||
@@ -153,7 +168,7 @@ jobs:
|
||||
# bucket creation in github.com/vegaprotocol/terraform//frontend
|
||||
- name: Publish dist to s3
|
||||
uses: jakejarvis/s3-sync-action@master
|
||||
if: ${{ github.event_name == 'push' && !startsWith(github.ref, 'refs/tags/v') }}
|
||||
if: ${{ github.event_name == 'push' && !startsWith(github.ref, 'refs/tags/v') && ( matrix.app != 'trading' || (matrix.app == 'trading' && !endsWith(github.ref, 'main') ) ) }}
|
||||
with:
|
||||
args: --acl private --follow-symlinks --delete
|
||||
env:
|
||||
@@ -185,8 +200,19 @@ jobs:
|
||||
-d '{"query": "mutation{triggerDeploy(siteId:\"f8f2e051-f18e-49e6-b876-0a39369dc0d8\"){id status}}"}' \
|
||||
https://api.fleek.co/graphql
|
||||
|
||||
- name: Check out ipfs-redirect
|
||||
if: ${{ matrix.app == 'trading' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: 'vegaprotocol/ipfs-redirect'
|
||||
path: 'ipfs-redirect'
|
||||
fetch-depth: '0'
|
||||
token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
|
||||
|
||||
- name: Update vega.trading DNS to redirect to the new console
|
||||
if: ${{ matrix.app == 'trading' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
|
||||
run: |
|
||||
curl -L https://dist.ipfs.tech/kubo/v0.20.0/kubo_v0.20.0_linux-amd64.tar.gz -o kubo.tgz
|
||||
tar -xzf kubo.tgz
|
||||
@@ -195,26 +221,52 @@ jobs:
|
||||
new_hash=$(cat ${{ matrix.app }}-ipfs-hash)
|
||||
new_cid=$(ipfs cid format -v 1 -b base32 $new_hash)
|
||||
|
||||
# Generate console URL
|
||||
new_console_url_type=ipfs
|
||||
# new_console_url_type=ipns
|
||||
new_console_url_domain=cf-ipfs.com
|
||||
# new_console_url_domain=dweb.link
|
||||
new_console_url="https://${new_cid}.${new_console_url_type}.${new_console_url_domain}/"
|
||||
echo "new_console_url=${new_console_url}"
|
||||
ls -al ipfs-redirect
|
||||
|
||||
# Update record in DNSimple
|
||||
# docs: https://developer.dnsimple.com/v2/zones/records/#updateZoneRecord
|
||||
dnsimple_account_id=84895
|
||||
dnsimple_zone_name=vega.trading
|
||||
dnsimple_record_id=44409591
|
||||
# see: https://dnsimple.com/a/84895/domains/vega.trading/records/44409591/edit
|
||||
echo $new_hash > ipfs-redirect/cidv0.txt
|
||||
echo $new_cid > ipfs-redirect/cidv1.txt
|
||||
|
||||
curl -H 'Authorization: Bearer ${{ secrets.DNSIMPLE_API_TOKEN }}' \
|
||||
-H 'Accept: application/json' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-X PATCH \
|
||||
-d "{
|
||||
\"content\": \"${new_console_url}\"
|
||||
}" \
|
||||
https://api.dnsimple.com/v2/${dnsimple_account_id}/zones/${dnsimple_zone_name}/records/${dnsimple_record_id}
|
||||
(
|
||||
cd ipfs-redirect
|
||||
|
||||
git status
|
||||
cat .git/config
|
||||
git config --global user.email "vega-ci-bot@vega.xyz"
|
||||
git config --global user.name "vega-ci-bot"
|
||||
|
||||
branch_name="update-hash-${{ github.ref }}"
|
||||
git checkout -b "$branch_name"
|
||||
commit_msg="Automated hash update from ${{ github.ref }}"
|
||||
git add cidv0.txt cidv1.txt
|
||||
git commit -m "$commit_msg"
|
||||
git push -u origin "$branch_name"
|
||||
pr_url="$(gh pr create --title "${commit_msg}" --body 'automated pull request to update CIDs')"
|
||||
echo $pr_url
|
||||
# once auto merge get's enabled on documentation repo let's do follow up
|
||||
sleep 5
|
||||
gh pr merge "${pr_url}" --delete-branch --squash --admin
|
||||
)
|
||||
|
||||
# # Generate console URL
|
||||
# new_console_url_type=ipfs
|
||||
# # new_console_url_type=ipns
|
||||
# new_console_url_domain=cf-ipfs.com
|
||||
# # new_console_url_domain=dweb.link
|
||||
# new_console_url="https://${new_cid}.${new_console_url_type}.${new_console_url_domain}/"
|
||||
# echo "new_console_url=${new_console_url}"
|
||||
|
||||
# # Update record in DNSimple
|
||||
# # docs: https://developer.dnsimple.com/v2/zones/records/#updateZoneRecord
|
||||
# dnsimple_account_id=84895
|
||||
# dnsimple_zone_name=vega.trading
|
||||
# dnsimple_record_id=44409591
|
||||
# # see: https://dnsimple.com/a/84895/domains/vega.trading/records/44409591/edit
|
||||
|
||||
# curl -H 'Authorization: Bearer ${{ secrets.DNSIMPLE_API_TOKEN }}' \
|
||||
# -H 'Accept: application/json' \
|
||||
# -H 'Content-Type: application/json' \
|
||||
# -X PATCH \
|
||||
# -d "{
|
||||
# \"content\": \"${new_console_url}\"
|
||||
# }" \
|
||||
# https://api.dnsimple.com/v2/${dnsimple_account_id}/zones/${dnsimple_zone_name}/records/${dnsimple_record_id}
|
||||
|
||||
+4
-3
@@ -3,17 +3,18 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
|
||||
NX_VEGA_ENV=STAGNET1
|
||||
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
|
||||
NX_VEGA_TOKEN_URL=https://stagnet1.governance.vega.xyz
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.stagnet1.vega.rocks
|
||||
NX_VEGA_TOKEN_URL=https://governance.stagnet1.vega.rocks
|
||||
NX_VEGA_WALLET_URL=http://localhost:1789
|
||||
NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.xyz
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
|
||||
NX_BLOCK_EXPLORER=https://be.stagnet1.vega.xyz/rest
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
NX_VEGA_GOVERNANCE_URL=https://stagnet1.governance.vega.xyz
|
||||
NX_VEGA_GOVERNANCE_URL=https://governance.stagnet1.vega.rocks
|
||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.jsoo
|
||||
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
|
||||
# App flags
|
||||
NX_EXPLORER_ASSETS=1
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# App configuration variables
|
||||
NX_TENDERMINT_URL=https://be.vega.community
|
||||
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_URL=https://api.vega.community/graphql
|
||||
NX_VEGA_ENV=MAINNET
|
||||
@@ -9,3 +10,4 @@ NX_ETHERSCAN_URL=https://etherscan.io
|
||||
NX_VEGA_GOVERNANCE_URL=https://governance.vega.xyz
|
||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz/
|
||||
NX_VEGA_CONSOLE_URL=https://vega.trading
|
||||
|
||||
@@ -10,3 +10,4 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_VEGA_GOVERNANCE_URL=https://governance.fairground.wtf
|
||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
||||
NX_VEGA_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_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_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/
|
||||
@@ -13,6 +13,7 @@ import { DEFAULT_CACHE_CONFIG } from '@vegaprotocol/apollo-client';
|
||||
import { RouterProvider } from 'react-router-dom';
|
||||
import { router } from './routes/router-config';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { Suspense } from 'react';
|
||||
|
||||
const splashLoading = (
|
||||
<Splash>
|
||||
@@ -32,7 +33,9 @@ function App() {
|
||||
skeleton={<div>{t('Loading')}</div>}
|
||||
failure={<AppFailure title={t(`Node: ${VEGA_URL} is unsuitable`)} />}
|
||||
>
|
||||
<RouterProvider router={router} fallbackElement={splashLoading} />
|
||||
<Suspense fallback={splashLoading}>
|
||||
<RouterProvider router={router} fallbackElement={splashLoading} />
|
||||
</Suspense>
|
||||
</NodeGuard>
|
||||
<NodeSwitcherDialog
|
||||
open={nodeSwitcherOpen}
|
||||
|
||||
@@ -4,9 +4,11 @@ import {
|
||||
} from '@vegaprotocol/environment';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
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 { ENV } from '../../config/env';
|
||||
import { Routes } from '../../routes/route-names';
|
||||
import { Link as RouteLink } from 'react-router-dom';
|
||||
|
||||
export const Footer = () => {
|
||||
const { VEGA_URL, GIT_COMMIT_HASH, GIT_ORIGIN_URL } = useEnvironment();
|
||||
@@ -21,7 +23,7 @@ export const Footer = () => {
|
||||
);
|
||||
|
||||
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">
|
||||
{GIT_COMMIT_HASH && (
|
||||
<div className="content-center flex border-r border-neutral-700 dark:border-neutral-300 pr-4">
|
||||
@@ -48,23 +50,26 @@ export const Footer = () => {
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div className="flex pl-2 content-center">
|
||||
<ExternalLink href={ENV.addresses.feedback}>
|
||||
{showFullFeedbackLabel ? t('Share your feedback') : t('Feedback')}
|
||||
</ExternalLink>
|
||||
</div>
|
||||
{ENV.addresses.feedback ? (
|
||||
<div className="flex pl-2 content-center">
|
||||
<ExternalLink href={ENV.addresses.feedback}>
|
||||
{showFullFeedbackLabel ? t('Share your feedback') : t('Feedback')}
|
||||
</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>
|
||||
</footer>
|
||||
);
|
||||
};
|
||||
|
||||
const NodeUrl = ({ url }: { url: string }) => {
|
||||
export const NodeUrl = ({ url }: { url: string }) => {
|
||||
// get base url from api url, api sub domain
|
||||
const urlObj = new URL(url);
|
||||
const nodeUrl = urlObj.origin.replace(/^[^.]+\./g, '');
|
||||
return (
|
||||
<Link href={'https://' + nodeUrl} target="_blank">
|
||||
{nodeUrl}
|
||||
</Link>
|
||||
);
|
||||
return <span className="cursor-default">{nodeUrl}</span>;
|
||||
};
|
||||
|
||||
@@ -20,12 +20,10 @@ import isEqual from 'lodash/isEqual';
|
||||
export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
|
||||
if (!market) return null;
|
||||
|
||||
const settlementData =
|
||||
market.tradableInstrument.instrument.product.dataSourceSpecForSettlementData
|
||||
.data;
|
||||
const terminationData =
|
||||
market.tradableInstrument.instrument.product
|
||||
.dataSourceSpecForTradingTermination.data;
|
||||
const settlementData = market.tradableInstrument.instrument.product
|
||||
.dataSourceSpecForSettlementData.data as DataSourceDefinition;
|
||||
const terminationData = market.tradableInstrument.instrument.product
|
||||
.dataSourceSpecForTradingTermination.data as DataSourceDefinition;
|
||||
|
||||
const getSigners = (data: DataSourceDefinition) => {
|
||||
if (data.sourceType.__typename === 'DataSourceDefinitionExternal') {
|
||||
|
||||
@@ -84,15 +84,17 @@ export const MarketsTable = ({ data }: MarketsTableProps) => {
|
||||
<AgGridColumn
|
||||
colId="asset"
|
||||
headerName={t('Settlement asset')}
|
||||
field="tradableInstrument.instrument.product.settlementAsset"
|
||||
field="tradableInstrument.instrument.product.settlementAsset.symbol"
|
||||
hide={window.innerWidth <= BREAKPOINT_MD}
|
||||
cellRenderer={({
|
||||
value,
|
||||
data,
|
||||
}: VegaICellRendererParams<
|
||||
MarketFieldsFragment,
|
||||
'tradableInstrument.instrument.product.settlementAsset'
|
||||
>) =>
|
||||
value ? (
|
||||
'tradableInstrument.instrument.product.settlementAsset.symbol'
|
||||
>) => {
|
||||
const value =
|
||||
data?.tradableInstrument.instrument.product.settlementAsset;
|
||||
return value ? (
|
||||
<ButtonLink
|
||||
onClick={(e) => {
|
||||
openAssetDetailsDialog(value.id, e.target as HTMLElement);
|
||||
@@ -102,8 +104,8 @@ export const MarketsTable = ({ data }: MarketsTableProps) => {
|
||||
</ButtonLink>
|
||||
) : (
|
||||
''
|
||||
)
|
||||
}
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<AgGridColumn
|
||||
flex={2}
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
export function proposalRequiresSignatureBundle(proposal?: Proposal): boolean {
|
||||
const proposalsThatRequireBundles = ['newAsset', 'updateAsset'];
|
||||
|
||||
if (!proposal?.terms) {
|
||||
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;
|
||||
|
||||
// This component is not rendered if no bundle is required
|
||||
const SignatureBundleComponent = proposal.terms?.newAsset
|
||||
? ProposalSignatureBundleNewAsset
|
||||
: ProposalSignatureBundleUpdateAsset;
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { render } from '@testing-library/react';
|
||||
import { OracleDetailsType } from './oracle-details-type';
|
||||
import type { SourceTypeName } from './oracle-details-type';
|
||||
import { OracleDetailsType, isInternalSourceType } from './oracle-details-type';
|
||||
import type { SourceType } from './oracle';
|
||||
import { PropertyKeyType } from '@vegaprotocol/types';
|
||||
|
||||
function renderComponent(type: SourceTypeName) {
|
||||
return <OracleDetailsType type={type} />;
|
||||
function renderComponent(type: SourceType) {
|
||||
return <OracleDetailsType sourceType={type} />;
|
||||
}
|
||||
|
||||
function renderWrappedComponent(type: SourceTypeName) {
|
||||
function renderWrappedComponent(type: SourceType) {
|
||||
return (
|
||||
<table>
|
||||
<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', () => {
|
||||
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();
|
||||
});
|
||||
|
||||
it('Renders Internal time for internal sources', () => {
|
||||
const res = render(renderWrappedComponent('DataSourceDefinitionInternal'));
|
||||
expect(res.getByText('Internal time')).toBeInTheDocument();
|
||||
it('Renders Internal time for internal sources - timestamp', () => {
|
||||
const s = mock('vegaprotocol.builtin.timestamp');
|
||||
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', () => {
|
||||
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();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,27 +1,51 @@
|
||||
import { TableRow, TableCell, TableHeader } from '../../../components/table';
|
||||
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 {
|
||||
type: SourceTypeName;
|
||||
sourceType: SourceType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
export function OracleDetailsType({ type }: OracleDetailsTypeProps) {
|
||||
if (!type) {
|
||||
export function OracleDetailsType({ sourceType }: OracleDetailsTypeProps) {
|
||||
if (!sourceType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const isInternal = isInternalSourceType(sourceType);
|
||||
|
||||
return (
|
||||
<TableRow modifier="bordered">
|
||||
<TableHeader scope="row">Type</TableHeader>
|
||||
<TableCell modifier="bordered">
|
||||
{type === 'DataSourceDefinitionInternal'
|
||||
? 'Internal time'
|
||||
: 'External data'}
|
||||
{isInternal ? 'Internal data' : 'External data'}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
|
||||
@@ -53,7 +53,7 @@ export const OracleDetails = ({
|
||||
<OracleLink id={id} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<OracleDetailsType type={sourceType.__typename} />
|
||||
<OracleDetailsType sourceType={sourceType} />
|
||||
<OracleSigners sourceType={sourceType} />
|
||||
<OracleMarkets id={id} />
|
||||
<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',
|
||||
ORACLES: 'oracles',
|
||||
NETWORK_PARAMETERS: 'network-parameters',
|
||||
DISCLAIMER: 'disclaimer',
|
||||
};
|
||||
|
||||
@@ -29,6 +29,7 @@ import { AssetLink, MarketLink } from '../components/links';
|
||||
import { truncateMiddle } from '@vegaprotocol/ui-toolkit';
|
||||
import { remove0x } from '@vegaprotocol/utils';
|
||||
import { PartyAccountsByAsset } from './parties/id/accounts';
|
||||
import { Disclaimer } from './pages/disclaimer';
|
||||
|
||||
export type Navigable = {
|
||||
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,
|
||||
...assetsRoutes,
|
||||
...genesisRoutes,
|
||||
|
||||
@@ -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_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||
NX_VEGA_REST_URL=http://localhost:3008/api/v2/
|
||||
|
||||
#Test configuration variables
|
||||
CYPRESS_FAIRGROUND=false
|
||||
|
||||
@@ -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,17 +7,12 @@ import {
|
||||
import {
|
||||
createRawProposal,
|
||||
createTenDigitUnixTimeStampForSpecifiedDays,
|
||||
enterUniqueFreeFormProposalBody,
|
||||
generateFreeFormProposalTitle,
|
||||
getDateFormatForSpecifiedDays,
|
||||
getProposalIdFromList,
|
||||
getProposalFromTitle,
|
||||
getProposalInformationFromTable,
|
||||
getSubmittedProposalFromProposalList,
|
||||
goToMakeNewProposal,
|
||||
governanceProposalType,
|
||||
submitUniqueRawProposal,
|
||||
voteForProposal,
|
||||
waitForProposalSubmitted,
|
||||
waitForProposalSync,
|
||||
} from '../../../../governance-e2e/src/support/governance.functions';
|
||||
import { ensureSpecifiedUnstakedTokensAreAssociated } from '../../../../governance-e2e/src/support/staking.functions';
|
||||
import { ethereumWalletConnect } from '../../../../governance-e2e/src/support/wallet-eth.functions';
|
||||
@@ -38,6 +33,9 @@ const proposalDetailsTitle = '[data-testid="proposal-title"]';
|
||||
const proposalDetailsDescription = '[data-testid="proposal-description"]';
|
||||
const openProposals = '[data-testid="open-proposals"]';
|
||||
const viewProposalButton = '[data-testid="view-proposal-btn"]';
|
||||
const proposalDescriptionToggle = 'proposal-description-toggle';
|
||||
const voteBreakdownToggle = 'vote-breakdown-toggle';
|
||||
const proposalTermsToggle = 'proposal-json-toggle';
|
||||
|
||||
describe(
|
||||
'Governance flow for proposal details',
|
||||
@@ -62,61 +60,61 @@ describe(
|
||||
|
||||
// 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 () {
|
||||
const proposalDescription =
|
||||
'I propose that everyone evaluate the following IPFS document and vote Yes if they agree. bafybeigwwctpv37xdcwacqxvekr6e4kaemqsrv34em6glkbiceo3fcy4si';
|
||||
|
||||
createRawProposal();
|
||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||
getProposalIdFromList(rawProposal.rationale.title);
|
||||
cy.get('@proposalIdText').then((proposalId) => {
|
||||
cy.get(openProposals).within(() => {
|
||||
cy.get(`#${proposalId}`).within(() => {
|
||||
cy.get(viewProposalButton).should('be.visible').click();
|
||||
});
|
||||
cy.get(openProposals).within(() => {
|
||||
getProposalFromTitle(rawProposal.rationale.title).within(() => {
|
||||
cy.get(viewProposalButton).should('be.visible').click();
|
||||
});
|
||||
});
|
||||
cy.get(proposalDetailsTitle)
|
||||
.should('contain', rawProposal.rationale.title)
|
||||
.and('be.visible');
|
||||
cy.get(proposalDetailsTitle).should(
|
||||
'contain.text',
|
||||
rawProposal.rationale.title
|
||||
);
|
||||
cy.getByTestId(proposalDescriptionToggle).click();
|
||||
cy.getByTestId('proposal-description-toggle');
|
||||
cy.get(proposalDetailsDescription)
|
||||
.should('contain', rawProposal.rationale.description)
|
||||
.and('be.visible');
|
||||
.find('p')
|
||||
.should('have.text', proposalDescription);
|
||||
});
|
||||
cy.getByTestId(proposalTermsToggle).click();
|
||||
// 3001-VOTE-052
|
||||
cy.get('code.language-json')
|
||||
.should('exist')
|
||||
.within(() => {
|
||||
cy.get('.hljs-string').eq(0).should('have.text', '"ProposalTerms"');
|
||||
cy.get('.hljs-attr').eq(0).should('have.text', '"id"');
|
||||
});
|
||||
});
|
||||
|
||||
// 3001-VOTE-043
|
||||
it('Newly created freeform proposal details - shows proposed and closing dates', function () {
|
||||
const closingVoteHrs = '72';
|
||||
const proposalTitle = generateFreeFormProposalTitle();
|
||||
const proposalTimeStamp = createTenDigitUnixTimeStampForSpecifiedDays(3);
|
||||
// const currentDate = new Date(createTenDigitUnixTimeStampForSpecifiedDays(0) * 1000)
|
||||
// const proposedDate = new Date(currentDate.getTime() + 60000)
|
||||
|
||||
goToMakeNewProposal(governanceProposalType.FREEFORM);
|
||||
enterUniqueFreeFormProposalBody(closingVoteHrs, proposalTitle);
|
||||
waitForProposalSubmitted();
|
||||
waitForProposalSync();
|
||||
submitUniqueRawProposal({
|
||||
proposalTitle: proposalTitle,
|
||||
closingTimestamp: proposalTimeStamp,
|
||||
});
|
||||
navigateTo(navigation.proposals);
|
||||
getSubmittedProposalFromProposalList(proposalTitle).within(() =>
|
||||
getProposalFromTitle(proposalTitle).within(() =>
|
||||
cy.get(viewProposalButton).click()
|
||||
);
|
||||
cy.wrap(
|
||||
formatDateWithLocalTimezone(new Date(proposalTimeStamp * 1000))
|
||||
).then((closingDate) => {
|
||||
getProposalInformationFromTable('Closes on')
|
||||
.contains(closingDate)
|
||||
.should('be.visible');
|
||||
});
|
||||
cy.wrap(
|
||||
formatDateWithLocalTimezone(
|
||||
new Date(createTenDigitUnixTimeStampForSpecifiedDays(0) * 1000)
|
||||
)
|
||||
).then((proposalDate) => {
|
||||
getProposalInformationFromTable('Proposed on')
|
||||
.contains(proposalDate)
|
||||
.should('be.visible');
|
||||
getProposalInformationFromTable('Closes on').should(
|
||||
'have.text',
|
||||
closingDate
|
||||
);
|
||||
});
|
||||
getProposalInformationFromTable('Proposed on')
|
||||
.invoke('text')
|
||||
.should('not.be.empty');
|
||||
});
|
||||
|
||||
it('Newly created proposal details - shows default status set to fail', function () {
|
||||
@@ -125,13 +123,14 @@ describe(
|
||||
// 3001-VOTE-067
|
||||
createRawProposal();
|
||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||
getSubmittedProposalFromProposalList(
|
||||
rawProposal.rationale.title
|
||||
).within(() => cy.get(viewProposalButton).click());
|
||||
getProposalFromTitle(rawProposal.rationale.title).within(() =>
|
||||
cy.get(viewProposalButton).click()
|
||||
);
|
||||
});
|
||||
cy.contains('Participation: Not Met 0.00 0.00%(0.00% Required)').should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.getByTestId(voteBreakdownToggle).click();
|
||||
getProposalInformationFromTable('Expected to pass')
|
||||
.contains('👎')
|
||||
.should('be.visible');
|
||||
@@ -151,9 +150,9 @@ describe(
|
||||
it('Newly created proposal details - ability to vote for and against proposal - with minimum required tokens associated', function () {
|
||||
createRawProposal();
|
||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||
getSubmittedProposalFromProposalList(
|
||||
rawProposal.rationale.title
|
||||
).within(() => cy.get(viewProposalButton).click());
|
||||
getProposalFromTitle(rawProposal.rationale.title).within(() =>
|
||||
cy.get(viewProposalButton).click()
|
||||
);
|
||||
});
|
||||
// 3001-VOTE-080
|
||||
cy.getByTestId('vote-buttons').contains('against').should('be.visible');
|
||||
@@ -179,6 +178,7 @@ describe(
|
||||
cy.get(proposalVoteProgressAgainstTokens)
|
||||
.contains('0.00')
|
||||
.and('be.visible');
|
||||
cy.getByTestId(voteBreakdownToggle).click();
|
||||
getProposalInformationFromTable('Tokens for proposal')
|
||||
.should('have.text', (1).toFixed(2))
|
||||
.and('be.visible');
|
||||
@@ -220,14 +220,15 @@ describe(
|
||||
vegaWalletSetSpecifiedApprovalAmount('1000');
|
||||
createRawProposal();
|
||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||
getSubmittedProposalFromProposalList(
|
||||
rawProposal.rationale.title
|
||||
).within(() => cy.get(viewProposalButton).click());
|
||||
getProposalFromTitle(rawProposal.rationale.title).within(() =>
|
||||
cy.get(viewProposalButton).click()
|
||||
);
|
||||
});
|
||||
voteForProposal('for');
|
||||
// 3001-VOTE-079
|
||||
cy.contains('You voted: For').should('be.visible');
|
||||
cy.get(proposalVoteProgressForTokens).contains('1').and('be.visible');
|
||||
cy.getByTestId(voteBreakdownToggle).click();
|
||||
getProposalInformationFromTable('Total Supply')
|
||||
.invoke('text')
|
||||
.then((totalSupply) => {
|
||||
@@ -235,14 +236,15 @@ describe(
|
||||
(Number(totalSupply.replace(/,/g, '')) * 0.001) /
|
||||
100
|
||||
).toFixed(2);
|
||||
ethereumWalletConnect();
|
||||
ensureSpecifiedUnstakedTokensAreAssociated(
|
||||
tokensRequiredToAchieveResult
|
||||
);
|
||||
navigateTo(navigation.proposals);
|
||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||
getSubmittedProposalFromProposalList(
|
||||
rawProposal.rationale.title
|
||||
).within(() => cy.get(viewProposalButton).click());
|
||||
getProposalFromTitle(rawProposal.rationale.title).within(() =>
|
||||
cy.get(viewProposalButton).click()
|
||||
);
|
||||
});
|
||||
cy.get(proposalVoteProgressForPercentage)
|
||||
.contains('100.00%')
|
||||
@@ -259,6 +261,7 @@ describe(
|
||||
cy.get(proposalVoteProgressAgainstTokens)
|
||||
.contains('0.00')
|
||||
.and('be.visible');
|
||||
cy.getByTestId(voteBreakdownToggle).click();
|
||||
getProposalInformationFromTable('Total tokens voted percentage')
|
||||
.should('have.text', '0.00%')
|
||||
.and('be.visible');
|
||||
|
||||
@@ -58,14 +58,12 @@ context(
|
||||
.parentsUntil(proposalListItem)
|
||||
.last()
|
||||
.within(() => {
|
||||
cy.get(proposalStatus).should('have.text', 'Enacted ');
|
||||
cy.get(proposalStatus).should('have.text', 'Enacted');
|
||||
cy.get(viewProposalButton).click();
|
||||
});
|
||||
});
|
||||
cy.getByTestId('proposal-type').should('have.text', 'New market');
|
||||
getProposalInformationFromTable('State')
|
||||
.contains('Enacted')
|
||||
.and('be.visible');
|
||||
cy.get(proposalStatus).should('have.text', 'Enacted');
|
||||
cy.get(votesTable).within(() => {
|
||||
cy.contains('Vote passed.').should('be.visible');
|
||||
cy.contains('Voting has ended.').should('be.visible');
|
||||
@@ -87,16 +85,10 @@ context(
|
||||
.last()
|
||||
.within(() => cy.get(viewProposalButton).click());
|
||||
});
|
||||
getProposalInformationFromTable('State')
|
||||
.contains('Open')
|
||||
.and('be.visible');
|
||||
cy.get(proposalStatus).should('have.text', 'Open');
|
||||
voteForProposal('for');
|
||||
getProposalInformationFromTable('State') // 3001-VOTE-047
|
||||
.contains('Passed', proposalTimeout)
|
||||
.and('be.visible');
|
||||
getProposalInformationFromTable('State')
|
||||
.contains('Enacted', proposalTimeout)
|
||||
.and('be.visible');
|
||||
cy.get(proposalStatus, proposalTimeout).should('have.text', 'Passed');
|
||||
cy.get(proposalStatus, proposalTimeout).should('have.text', 'Enacted');
|
||||
cy.get(votesTable).within(() => {
|
||||
cy.contains('Vote passed.').should('be.visible');
|
||||
cy.contains('Voting has ended.').should('be.visible');
|
||||
@@ -121,13 +113,9 @@ context(
|
||||
.last()
|
||||
.within(() => cy.get(viewProposalButton).click());
|
||||
});
|
||||
getProposalInformationFromTable('State')
|
||||
.contains('Open')
|
||||
.and('be.visible');
|
||||
cy.get(proposalStatus).should('have.text', 'Open');
|
||||
voteForProposal('for');
|
||||
getProposalInformationFromTable('State')
|
||||
.contains('Enacted', proposalTimeout)
|
||||
.and('be.visible');
|
||||
cy.get(proposalStatus, proposalTimeout).should('have.text', 'Enacted');
|
||||
});
|
||||
|
||||
// 3001-VOTE-048 3001-VOTE-049 3001-VOTE-050
|
||||
@@ -144,12 +132,8 @@ context(
|
||||
.last()
|
||||
.within(() => cy.get(viewProposalButton).click());
|
||||
});
|
||||
getProposalInformationFromTable('State')
|
||||
.contains('Open')
|
||||
.and('be.visible');
|
||||
getProposalInformationFromTable('State') // 3001-VOTE-047
|
||||
.contains('Declined', proposalTimeout)
|
||||
.and('be.visible');
|
||||
cy.get(proposalStatus).should('have.text', 'Open');
|
||||
cy.get(proposalStatus, proposalTimeout).should('have.text', 'Declined');
|
||||
getProposalInformationFromTable('Rejection reason')
|
||||
.contains('PROPOSAL_ERROR_PARTICIPATION_THRESHOLD_NOT_REACHED')
|
||||
.and('be.visible');
|
||||
|
||||
@@ -5,10 +5,11 @@ import {
|
||||
enterRawProposalBody,
|
||||
enterUniqueFreeFormProposalBody,
|
||||
generateFreeFormProposalTitle,
|
||||
getProposalFromTitle,
|
||||
getProposalInformationFromTable,
|
||||
getSubmittedProposalFromProposalList,
|
||||
goToMakeNewProposal,
|
||||
governanceProposalType,
|
||||
submitUniqueRawProposal,
|
||||
voteForProposal,
|
||||
waitForProposalSubmitted,
|
||||
waitForProposalSync,
|
||||
@@ -81,7 +82,6 @@ context(
|
||||
});
|
||||
|
||||
vegaWalletSetSpecifiedApprovalAmount('1000');
|
||||
cy.associateTokensToVegaWallet('1');
|
||||
});
|
||||
|
||||
beforeEach('visit governance tab', function () {
|
||||
@@ -95,7 +95,8 @@ context(
|
||||
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
|
||||
cy.get(noOpenProposals)
|
||||
.should('be.visible')
|
||||
@@ -107,7 +108,7 @@ context(
|
||||
|
||||
// 3002-PROP-002
|
||||
// 3002-PROP-003
|
||||
it('Submit a proposal form - shows how many vega tokens are required to make a proposal', function () {
|
||||
it('Proposal form - shows how many vega tokens are required to make a proposal', function () {
|
||||
// 3002-PROP-005
|
||||
goToMakeNewProposal(governanceProposalType.NEW_MARKET);
|
||||
cy.contains(
|
||||
@@ -115,8 +116,9 @@ context(
|
||||
).should('be.visible');
|
||||
});
|
||||
|
||||
// Skipping as currently unable to propose using forms other than raw
|
||||
// 3002-PROP-011
|
||||
it('Able to submit a valid freeform proposal - with minimum required tokens associated', function () {
|
||||
it.skip('Able to submit a valid freeform proposal - with minimum required tokens associated', function () {
|
||||
goToMakeNewProposal(governanceProposalType.FREEFORM);
|
||||
cy.get(minVoteButton).should('be.visible'); // 3002-PROP-008
|
||||
cy.get(maxVoteButton).should('be.visible');
|
||||
@@ -140,16 +142,13 @@ context(
|
||||
closeStakingDialog();
|
||||
|
||||
cy.get(vegaWalletStakedBalances, txTimeout).should('contain', '2');
|
||||
|
||||
navigateTo(navigation.proposals);
|
||||
goToMakeNewProposal(governanceProposalType.FREEFORM);
|
||||
enterUniqueFreeFormProposalBody('50', generateFreeFormProposalTitle());
|
||||
waitForProposalSubmitted();
|
||||
createRawProposal();
|
||||
});
|
||||
|
||||
it('Creating a proposal - proposal rejected - when closing time sooner than system default', function () {
|
||||
it.skip('Creating a proposal - proposal rejected - when closing time sooner than system default', function () {
|
||||
goToMakeNewProposal(governanceProposalType.FREEFORM);
|
||||
enterUniqueFreeFormProposalBody('0.1', generateFreeFormProposalTitle());
|
||||
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'not.exist'
|
||||
);
|
||||
@@ -158,7 +157,7 @@ context(
|
||||
.should('equal', 'Value must be greater than or equal to 1.');
|
||||
});
|
||||
|
||||
it('Creating a proposal - proposal rejected - when closing time later than system default', function () {
|
||||
it.skip('Creating a proposal - proposal rejected - when closing time later than system default', function () {
|
||||
goToMakeNewProposal(governanceProposalType.FREEFORM);
|
||||
enterUniqueFreeFormProposalBody(
|
||||
'100000',
|
||||
@@ -185,17 +184,13 @@ context(
|
||||
navigateTo(navigation.proposals);
|
||||
cy.get(rejectProposalsLink).click();
|
||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||
getSubmittedProposalFromProposalList(
|
||||
rawProposal.rationale.title
|
||||
).within(() => {
|
||||
getProposalFromTitle(rawProposal.rationale.title).within(() => {
|
||||
cy.contains('Rejected').should('be.visible');
|
||||
cy.contains('Close time too late').should('be.visible');
|
||||
cy.get(viewProposalButton).click();
|
||||
});
|
||||
});
|
||||
getProposalInformationFromTable('State')
|
||||
.contains('Rejected')
|
||||
.and('be.visible');
|
||||
cy.getByTestId('proposal-status').should('have.text', 'Rejected');
|
||||
getProposalInformationFromTable('Rejection reason')
|
||||
.contains('PROPOSAL_ERROR_CLOSE_TIME_TOO_LATE')
|
||||
.and('be.visible');
|
||||
@@ -290,18 +285,19 @@ context(
|
||||
const proposalTitle = generateFreeFormProposalTitle();
|
||||
|
||||
ensureSpecifiedUnstakedTokensAreAssociated('1');
|
||||
goToMakeNewProposal(governanceProposalType.FREEFORM);
|
||||
enterUniqueFreeFormProposalBody('50', proposalTitle);
|
||||
waitForProposalSubmitted();
|
||||
submitUniqueRawProposal({ proposalTitle: proposalTitle });
|
||||
ethereumWalletConnect();
|
||||
stakingPageDisassociateTokens('0.0001');
|
||||
cy.get(vegaWallet).within(() => {
|
||||
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
|
||||
'contain',
|
||||
'0.9999'
|
||||
);
|
||||
});
|
||||
cy.get(vegaWallet)
|
||||
.first()
|
||||
.within(() => {
|
||||
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
|
||||
'contain',
|
||||
'0.9999'
|
||||
);
|
||||
});
|
||||
navigateTo(navigation.proposals);
|
||||
getSubmittedProposalFromProposalList(proposalTitle).within(() =>
|
||||
getProposalFromTitle(proposalTitle).within(() =>
|
||||
cy.get(viewProposalButton).click()
|
||||
);
|
||||
cy.contains('Vote breakdown').should('be.visible', {
|
||||
@@ -319,9 +315,9 @@ context(
|
||||
cy.get('[data-testid="manage-vega-wallet"]:visible').click();
|
||||
cy.get('[data-testid="disconnect"]').click();
|
||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||
getSubmittedProposalFromProposalList(
|
||||
rawProposal.rationale.title
|
||||
).within(() => cy.get(viewProposalButton).click());
|
||||
getProposalFromTitle(rawProposal.rationale.title).within(() =>
|
||||
cy.get(viewProposalButton).click()
|
||||
);
|
||||
});
|
||||
// 3001-VOTE-075
|
||||
// 3001-VOTE-076
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
import {
|
||||
getProposalInformationFromTable,
|
||||
goToMakeNewProposal,
|
||||
governanceProposalType,
|
||||
voteForProposal,
|
||||
waitForProposalSubmitted,
|
||||
} from '../../support/governance.functions';
|
||||
@@ -56,18 +57,8 @@ const fUSDCId =
|
||||
const epochTimeout = Cypress.env('epochTimeout');
|
||||
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
|
||||
context(
|
||||
context.skip(
|
||||
'Governance flow - form validations for different governance proposals',
|
||||
{ tags: '@slow' },
|
||||
function () {
|
||||
|
||||
@@ -6,16 +6,15 @@ import {
|
||||
waitForSpinner,
|
||||
} from '../../support/common.functions';
|
||||
import {
|
||||
createFreeformProposal,
|
||||
createRawProposal,
|
||||
createTenDigitUnixTimeStampForSpecifiedDays,
|
||||
enterRawProposalBody,
|
||||
generateFreeFormProposalTitle,
|
||||
getProposalIdFromList,
|
||||
getProposalFromTitle,
|
||||
getProposalInformationFromTable,
|
||||
getSubmittedProposalFromProposalList,
|
||||
goToMakeNewProposal,
|
||||
governanceProposalType,
|
||||
submitUniqueRawProposal,
|
||||
voteForProposal,
|
||||
waitForProposalSubmitted,
|
||||
waitForProposalSync,
|
||||
@@ -24,10 +23,14 @@ import { ensureSpecifiedUnstakedTokensAreAssociated } from '../../support/stakin
|
||||
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
|
||||
import { vegaWalletSetSpecifiedApprovalAmount } from '../../support/wallet-teardown.functions';
|
||||
|
||||
const proposalListItem = 'proposals-list-item';
|
||||
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 viewProposalButton = '[data-testid="view-proposal-btn"]';
|
||||
const voteBreakDownToggle = 'vote-breakdown-toggle';
|
||||
|
||||
describe('Governance flow for proposal list', { tags: '@slow' }, 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);
|
||||
cy.get(openProposals).within(() => {
|
||||
cy.get(proposalClosingDate).first().should('contain.text', 'year');
|
||||
cy.get(proposalClosingDate).should('contain.text', 'months');
|
||||
cy.get(proposalClosingDate)
|
||||
.last()
|
||||
.first()
|
||||
.invoke('text')
|
||||
.should('match', /days|minutes/);
|
||||
cy.get(proposalClosingDate).should('contain.text', 'months');
|
||||
cy.get(proposalClosingDate).last().should('contain.text', 'year');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -73,36 +76,27 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
|
||||
const proposerId = Cypress.env('vegaWalletPublicKey');
|
||||
const proposalTitle = generateFreeFormProposalTitle();
|
||||
|
||||
createFreeformProposal(proposalTitle);
|
||||
getProposalIdFromList(proposalTitle);
|
||||
cy.get('@proposalIdText').then((proposalId) => {
|
||||
cy.get('[data-testid="set-proposals-filter-visible"]').click();
|
||||
cy.get('[data-testid="filter-input"]').type(proposerId);
|
||||
cy.get(`#${proposalId}`).should('contain', proposalId);
|
||||
});
|
||||
submitUniqueRawProposal({ proposalTitle: proposalTitle });
|
||||
cy.get('[data-testid="set-proposals-filter-visible"]').click();
|
||||
cy.get('[data-testid="filter-input"]').type(proposerId);
|
||||
// cy.get(`#${proposalId}`).should('contain', proposalId);
|
||||
cy.contains(proposalTitle).should('be.visible');
|
||||
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 () {
|
||||
createRawProposal(this.minProposerBalance); // 3001-VOTE-052
|
||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||
getProposalIdFromList(rawProposal.rationale.title);
|
||||
cy.get('@proposalIdText').then((proposalId) => {
|
||||
cy.get(openProposals).within(() => {
|
||||
// 3001-VOTE-008
|
||||
// 3001-VOTE-034
|
||||
cy.get(`#${proposalId}`)
|
||||
// 3001-VOTE-097
|
||||
.should('contain', rawProposal.rationale.title)
|
||||
.and('be.visible');
|
||||
cy.get(`#${proposalId}`)
|
||||
.should(
|
||||
'contain',
|
||||
rawProposal.rationale.description.substring(0, 59)
|
||||
)
|
||||
.and('be.visible');
|
||||
});
|
||||
});
|
||||
});
|
||||
const proposalPath = '/proposals/new-market-raw.json';
|
||||
const enactmentTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(3);
|
||||
submitUniqueRawProposal({
|
||||
proposalBody: proposalPath,
|
||||
enactmentTimestamp: enactmentTimestamp,
|
||||
}); // 3001-VOTE-052
|
||||
// 3001-VOTE-008
|
||||
// 3001-VOTE-034
|
||||
// 3001-VOTE-097
|
||||
cy.contains('New Market Proposal E2E submission');
|
||||
cy.contains('Code: TEST.24h. fBTC settled future.').should('be.visible');
|
||||
});
|
||||
|
||||
it('Newly created proposals list - shows open proposals in an open state', function () {
|
||||
@@ -110,23 +104,11 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
|
||||
// 3001-VOTE-035
|
||||
createRawProposal(this.minProposerBalance);
|
||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||
getSubmittedProposalFromProposalList(rawProposal.rationale.title).within(
|
||||
() => {
|
||||
cy.get(viewProposalButton).should('be.visible').click();
|
||||
}
|
||||
);
|
||||
|
||||
cy.get('@proposalIdText').then((proposalId) => {
|
||||
getProposalInformationFromTable('ID')
|
||||
.contains(String(proposalId))
|
||||
.and('be.visible');
|
||||
getProposalFromTitle(rawProposal.rationale.title).within(() => {
|
||||
cy.get(viewProposalButton).should('be.visible');
|
||||
cy.getByTestId(proposalType).should('have.text', 'Freeform');
|
||||
cy.getByTestId(proposalStatus).should('have.text', 'Open');
|
||||
});
|
||||
getProposalInformationFromTable('State')
|
||||
.contains('Open')
|
||||
.and('be.visible');
|
||||
getProposalInformationFromTable('Type')
|
||||
.contains('Freeform')
|
||||
.and('be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -134,18 +116,22 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
|
||||
it('Newly created freeform proposals list - shows proposal participation - both met and not', function () {
|
||||
const proposalTitle = generateFreeFormProposalTitle();
|
||||
|
||||
createFreeformProposal(proposalTitle);
|
||||
getSubmittedProposalFromProposalList(proposalTitle).within(() => {
|
||||
submitUniqueRawProposal({ proposalTitle: proposalTitle });
|
||||
getProposalFromTitle(proposalTitle).within(() => {
|
||||
// 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();
|
||||
});
|
||||
voteForProposal('for');
|
||||
navigateTo(navigation.proposals);
|
||||
getSubmittedProposalFromProposalList(proposalTitle).within(() => {
|
||||
cy.get(voteStatus).should('have.text', 'Set to pass');
|
||||
getProposalFromTitle(proposalTitle).within(() => {
|
||||
cy.getByTestId(voteStatus).should('have.text', 'Set to pass');
|
||||
cy.get(viewProposalButton).click();
|
||||
});
|
||||
cy.getByTestId(voteBreakDownToggle).click();
|
||||
getProposalInformationFromTable('Token participation met')
|
||||
.contains('👍')
|
||||
.should('be.visible');
|
||||
|
||||
@@ -31,7 +31,6 @@ context('rewards - flow', { tags: '@slow' }, function () {
|
||||
cy.visit('/');
|
||||
waitForSpinner();
|
||||
depositAsset(vegaAssetAddress, '1000', 18);
|
||||
cy.validatorsSelfDelegate();
|
||||
ethereumWalletConnect();
|
||||
cy.connectVegaWallet();
|
||||
cy.VegaWalletTopUpRewardsPool(30, 200);
|
||||
|
||||
@@ -96,7 +96,7 @@ context(
|
||||
navigateTo(navigation.validators);
|
||||
|
||||
// 2002-SINC-007
|
||||
validateValidatorListTotalStakeAndShare('0', '2.00', '100.00%');
|
||||
validateValidatorListTotalStakeAndShare('0', '3,002.00', '50.02%');
|
||||
});
|
||||
|
||||
it('Able to view validators staked by me', function () {
|
||||
@@ -146,7 +146,7 @@ context(
|
||||
verifyThisEpochValue(2.0);
|
||||
closeStakingDialog();
|
||||
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 () {
|
||||
@@ -166,10 +166,11 @@ context(
|
||||
verifyThisEpochValue(6.0);
|
||||
closeStakingDialog();
|
||||
navigateTo(navigation.validators);
|
||||
validateValidatorListTotalStakeAndShare('0', '6.00', '100.00%');
|
||||
validateValidatorListTotalStakeAndShare('0', '3,006.00', '50.05%');
|
||||
});
|
||||
|
||||
it('Able to stake against multiple validators', function () {
|
||||
vegaWalletTeardown();
|
||||
stakingPageAssociateTokens('5');
|
||||
verifyUnstakedBalance(5.0);
|
||||
cy.get('button').contains('Select a validator to nominate').click();
|
||||
@@ -197,14 +198,10 @@ context(
|
||||
.eq(1)
|
||||
.within(() => {
|
||||
cy.getByTestId(stakeValidatorListTotalStake)
|
||||
.should('have.text', '2.00')
|
||||
.should('have.text', '3,002.00')
|
||||
.and('be.visible');
|
||||
cy.getByTestId(stakeValidatorListTotalShare)
|
||||
.should('have.text', '66.67%')
|
||||
.and('be.visible');
|
||||
cy.getByTestId(stakeValidatorListTotalStake)
|
||||
.scrollIntoView()
|
||||
.should('have.text', '2.00')
|
||||
.should('have.text', '50.01%')
|
||||
.and('be.visible');
|
||||
});
|
||||
cy.get(`[row-id="${1}"]`)
|
||||
@@ -212,14 +209,10 @@ context(
|
||||
.within(() => {
|
||||
cy.getByTestId(stakeValidatorListTotalStake)
|
||||
.scrollIntoView()
|
||||
.should('have.text', '1.00')
|
||||
.should('have.text', '3,001.00')
|
||||
.and('be.visible');
|
||||
cy.getByTestId(stakeValidatorListTotalShare)
|
||||
.should('have.text', '33.33%')
|
||||
.and('be.visible');
|
||||
cy.getByTestId(stakeValidatorListTotalStake)
|
||||
.scrollIntoView()
|
||||
.should('have.text', '1.00')
|
||||
.should('have.text', '49.99%')
|
||||
.and('be.visible');
|
||||
});
|
||||
});
|
||||
@@ -282,7 +275,7 @@ context(
|
||||
txTimeout
|
||||
);
|
||||
navigateTo(navigation.validators);
|
||||
validateValidatorListTotalStakeAndShare('0', '0.00', '0.00%');
|
||||
validateValidatorListTotalStakeAndShare('0', '3,000.00', '50.00%');
|
||||
|
||||
cy.getByTestId(userStakeBtn).should('not.exist');
|
||||
cy.getByTestId(userStake).should('not.exist');
|
||||
@@ -354,7 +347,7 @@ context(
|
||||
txTimeout
|
||||
);
|
||||
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 () {
|
||||
@@ -382,7 +375,7 @@ context(
|
||||
txTimeout
|
||||
);
|
||||
navigateTo(navigation.validators);
|
||||
validateValidatorListTotalStakeAndShare('0', '0.00', '0.00%');
|
||||
validateValidatorListTotalStakeAndShare('0', '3,000.00', '50.00%');
|
||||
});
|
||||
|
||||
it('Disassociating some tokens - prioritizes unstaked tokens', function () {
|
||||
@@ -404,7 +397,7 @@ context(
|
||||
});
|
||||
verifyStakedBalance(2.0);
|
||||
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 () {
|
||||
|
||||
@@ -24,6 +24,7 @@ const ethWalletContainer = '[data-testid="ethereum-wallet"]';
|
||||
const vegaWalletAssociatedBalance = '[data-testid="currency-value"]';
|
||||
const vegaWalletUnstakedBalance =
|
||||
'[data-testid="vega-wallet-balance-unstaked"]';
|
||||
const currencyTitle = '[data-testid="currency-title"]:visible';
|
||||
const txTimeout = Cypress.env('txTimeout');
|
||||
const vegaWalletPublicKeyShort = Cypress.env('vegaWalletPublicKeyShort');
|
||||
const ethWalletAssociateButton = '[data-testid="associate-btn"]:visible';
|
||||
@@ -79,14 +80,11 @@ context(
|
||||
//0005-ETXN-005
|
||||
stakingPageAssociateTokens('2', { skipConfirmation: true });
|
||||
|
||||
cy.getByTestId('currency-title', txTimeout).should(
|
||||
'have.length.above',
|
||||
6
|
||||
);
|
||||
cy.get(currencyTitle, txTimeout).should('have.length.above', 4);
|
||||
validateWalletCurrency('Associated', '0.00');
|
||||
validateWalletCurrency('Pending association', '2.00');
|
||||
validateWalletCurrency('Total associated after pending', '2.00');
|
||||
cy.getByTestId('currency-title', txTimeout).should('have.length', 6);
|
||||
cy.get(currencyTitle, txTimeout).should('have.length.at.least', 6);
|
||||
|
||||
// 0005-ETXN-002
|
||||
verifyEthWalletAssociatedBalance('2.0');
|
||||
@@ -111,31 +109,29 @@ context(
|
||||
// 1004-ASSO-028
|
||||
// 1004-ASSO-029
|
||||
// 1004-ASSO-031
|
||||
|
||||
vegaWalletTeardown();
|
||||
stakingPageAssociateTokens('2');
|
||||
verifyEthWalletAssociatedBalance('2.0');
|
||||
verifyEthWalletTotalAssociatedBalance('2.0');
|
||||
verifyEthWalletTotalAssociatedBalance('6,002.00');
|
||||
cy.get('button').contains('Select a validator to nominate').click();
|
||||
stakingPageDisassociateTokens('2');
|
||||
cy.getByTestId('currency-title', txTimeout).should(
|
||||
'have.length.above',
|
||||
6
|
||||
);
|
||||
cy.get(currencyTitle, txTimeout).should('have.length.above', 4);
|
||||
validateWalletCurrency('Associated', '2.00');
|
||||
validateWalletCurrency('Pending association', '2.00');
|
||||
validateWalletCurrency('Total associated after pending', '0.00');
|
||||
cy.getByTestId('currency-title', txTimeout).should('have.length', 6);
|
||||
cy.getByTestId('eth-wallet-associated-balances', txTimeout).should(
|
||||
'not.exist'
|
||||
);
|
||||
verifyEthWalletTotalAssociatedBalance('0.00');
|
||||
cy.get(currencyTitle, txTimeout).should('have.length.at.least', 6);
|
||||
cy.get(
|
||||
'[data-testid="eth-wallet-associated-balances"]:visible',
|
||||
txTimeout
|
||||
).should('have.length', 2);
|
||||
verifyEthWalletTotalAssociatedBalance('6,000.00');
|
||||
});
|
||||
|
||||
it('Able to associate more tokens than the approved amount of 1000 - requires re-approval', function () {
|
||||
//1004-ASSO-011
|
||||
stakingPageAssociateTokens('1001', { approve: true });
|
||||
verifyEthWalletAssociatedBalance('1,001.00');
|
||||
verifyEthWalletTotalAssociatedBalance('1,001.00');
|
||||
verifyEthWalletTotalAssociatedBalance('7,001.00');
|
||||
cy.get(vegaWallet)
|
||||
.last()
|
||||
.within(() => {
|
||||
@@ -224,14 +220,11 @@ context(
|
||||
skipConfirmation: true,
|
||||
});
|
||||
|
||||
cy.getByTestId('currency-title', txTimeout).should(
|
||||
'have.length.above',
|
||||
6
|
||||
);
|
||||
cy.get(currencyTitle, txTimeout).should('have.length.above', 4);
|
||||
validateWalletCurrency('Associated', '0.00');
|
||||
validateWalletCurrency('Pending association', '2.00');
|
||||
validateWalletCurrency('Total associated after pending', '2.00');
|
||||
cy.getByTestId('currency-title', txTimeout).should('have.length', 6);
|
||||
cy.get(currencyTitle, txTimeout).should('have.length.at.least', 6);
|
||||
verifyEthWalletAssociatedBalance('2.0');
|
||||
verifyEthWalletTotalAssociatedBalance('2.0');
|
||||
cy.get(vegaWallet)
|
||||
@@ -247,14 +240,11 @@ context(
|
||||
type: 'contract',
|
||||
skipConfirmation: true,
|
||||
});
|
||||
cy.getByTestId('currency-title', txTimeout).should(
|
||||
'have.length.above',
|
||||
6
|
||||
);
|
||||
cy.get(currencyTitle, txTimeout).should('have.length.above', 4);
|
||||
validateWalletCurrency('Associated', '2.00');
|
||||
validateWalletCurrency('Pending association', '1.00');
|
||||
validateWalletCurrency('Total associated after pending', '1.00');
|
||||
cy.getByTestId('currency-title', txTimeout).should('have.length', 6);
|
||||
cy.get(currencyTitle, txTimeout).should('have.length.at.least', 6);
|
||||
verifyEthWalletAssociatedBalance('1.0');
|
||||
verifyEthWalletTotalAssociatedBalance('1.0');
|
||||
});
|
||||
@@ -338,14 +328,11 @@ context(
|
||||
// 1004-ASSO-004
|
||||
it('Pending association outside of app is shown', function () {
|
||||
vegaWalletAssociate('2');
|
||||
cy.getByTestId('currency-title', txTimeout).should(
|
||||
'have.length.above',
|
||||
6
|
||||
);
|
||||
cy.get(currencyTitle, txTimeout).should('have.length.above', 4);
|
||||
validateWalletCurrency('Associated', '0.00');
|
||||
validateWalletCurrency('Pending association', '2.00');
|
||||
validateWalletCurrency('Total associated after pending', '2.00');
|
||||
cy.getByTestId('currency-title', txTimeout).should('have.length', 6);
|
||||
cy.get(currencyTitle, txTimeout).should('have.length.at.least', 6);
|
||||
validateWalletCurrency('Associated', '2.00');
|
||||
});
|
||||
|
||||
@@ -354,14 +341,11 @@ context(
|
||||
cy.wrap(validateWalletCurrency('Associated', '2.00')).then(() => {
|
||||
vegaWalletDisassociate('2');
|
||||
});
|
||||
cy.getByTestId('currency-title', txTimeout).should(
|
||||
'have.length.above',
|
||||
6
|
||||
);
|
||||
cy.get(currencyTitle, txTimeout).should('have.length.above', 4);
|
||||
validateWalletCurrency('Associated', '2.00');
|
||||
validateWalletCurrency('Pending association', '2.00');
|
||||
validateWalletCurrency('Total associated after pending', '0.00');
|
||||
cy.getByTestId('currency-title', txTimeout).should('have.length', 6);
|
||||
cy.get(currencyTitle, txTimeout).should('have.length.at.least', 6);
|
||||
validateWalletCurrency('Associated', '0.00');
|
||||
});
|
||||
|
||||
|
||||
@@ -15,13 +15,7 @@ const balanceAvailable = 'BALANCE_AVAILABLE_value';
|
||||
const withdrawalThreshold = 'WITHDRAWAL_THRESHOLD_value';
|
||||
const delayTime = 'DELAY_TIME_value';
|
||||
const submitWithdrawalButton = 'submit-withdrawal';
|
||||
const dialogTitle = 'dialog-title';
|
||||
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 tableTxHash = '[col-id="txHash"]';
|
||||
const tableAssetSymbol = '[col-id="asset.symbol"]';
|
||||
@@ -30,14 +24,16 @@ const tableReceiverAddress = '[col-id="details.receiverAddress"]';
|
||||
const tableWithdrawnTimeStamp = '[col-id="withdrawnTimestamp"]';
|
||||
const tableWithdrawnStatus = '[col-id="status"]';
|
||||
const tableCreatedTimeStamp = '[col-id="createdTimestamp"]';
|
||||
const toastContent = 'toast-content';
|
||||
const toast = 'toast';
|
||||
const toastPanel = 'toast-panel';
|
||||
const toastClose = 'toast-close';
|
||||
const withdrawalDialogContent = 'dialog-content';
|
||||
const toastCompleteWithdrawal = 'toast-complete-withdrawal';
|
||||
const usdtName = 'USDC (local)';
|
||||
const usdcEthAddress = '0x1b8a1B6CBE5c93609b46D1829Cc7f3Cb8eeE23a0';
|
||||
const usdcSymbol = 'tUSDC';
|
||||
const usdtSelectValue =
|
||||
'993ed98f4f770d91a796faab1738551193ba45c62341d20597df70fea6704ede';
|
||||
const truncatedWithdrawalEthAddress = '0xEe7D…22d94F';
|
||||
const formValidationError = 'input-error-text';
|
||||
const txTimeout = Cypress.env('txTimeout');
|
||||
|
||||
@@ -47,11 +43,8 @@ context(
|
||||
function () {
|
||||
before('visit withdrawals and connect vega wallet', function () {
|
||||
cy.visit('/');
|
||||
// When running tests locally, will fail if run without restarting capsule
|
||||
cy.updateCapsuleMultiSig().then(() => {
|
||||
ethereumWalletConnect();
|
||||
depositAsset(usdcEthAddress, '1000', 5);
|
||||
});
|
||||
ethereumWalletConnect();
|
||||
depositAsset(usdcEthAddress, '1000', 5);
|
||||
});
|
||||
|
||||
beforeEach('Navigate to withdrawal page', function () {
|
||||
@@ -110,29 +103,35 @@ context(
|
||||
cy.getByTestId(amountInput).click().type('120');
|
||||
cy.getByTestId(submitWithdrawalButton).click();
|
||||
});
|
||||
|
||||
cy.contains('Awaiting network confirmation').should('be.visible');
|
||||
// assert withdrawal request
|
||||
cy.getByTestId(dialogTitle, txTimeout).should(
|
||||
'have.text',
|
||||
'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();
|
||||
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(dialogTitle, txTimeout).should(
|
||||
'have.text',
|
||||
'Withdraw asset complete'
|
||||
);
|
||||
cy.getByTestId(dialogClose).click();
|
||||
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)
|
||||
@@ -171,13 +170,17 @@ context(
|
||||
cy.getByTestId(submitWithdrawalButton).click();
|
||||
});
|
||||
|
||||
cy.contains('Awaiting network confirmation').should('be.visible');
|
||||
// assert withdrawal request
|
||||
cy.getByTestId(dialogTitle, txTimeout).should(
|
||||
'have.text',
|
||||
'Transaction complete'
|
||||
);
|
||||
cy.getByTestId(dialogClose).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 110.00 tUSDC'
|
||||
);
|
||||
cy.getByTestId(toastClose).click();
|
||||
});
|
||||
cy.get(tableTxHash)
|
||||
.eq(1)
|
||||
.should('have.text', 'Complete withdrawal')
|
||||
@@ -192,28 +195,75 @@ context(
|
||||
cy.get(tableCreatedTimeStamp).should('not.be.empty');
|
||||
});
|
||||
ethereumWalletConnect();
|
||||
cy.getByTestId(completeWithdrawalButton).click();
|
||||
cy.getByTestId(toastContent)
|
||||
.last()
|
||||
cy.getByTestId(completeWithdrawalButton).first().click();
|
||||
cy.getByTestId(toast)
|
||||
.last(txTimeout)
|
||||
.should('contain.text', 'Awaiting confirmation')
|
||||
.within(() => {
|
||||
cy.getByTestId('external-link').should('exist');
|
||||
});
|
||||
cy.getByTestId(toastContent)
|
||||
.first()
|
||||
cy.getByTestId(toast)
|
||||
.first(txTimeout)
|
||||
.should('contain.text', 'The withdrawal has been approved.')
|
||||
.within(() => {
|
||||
cy.getByTestId(toastPanel).should('contain.text', '110.00', 'tUSDC');
|
||||
});
|
||||
cy.getByTestId(toastContent)
|
||||
.last()
|
||||
cy.getByTestId(toast)
|
||||
.last(txTimeout)
|
||||
.should('contain.text', 'Transaction confirmed')
|
||||
.within(() => {
|
||||
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.get('select').select(usdtSelectValue, { force: true });
|
||||
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 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.`;
|
||||
|
||||
@@ -227,10 +277,11 @@ context(
|
||||
cy.get('select').select(usdtSelectValue, { force: true });
|
||||
cy.getByTestId(balanceAvailable, txTimeout).should('exist');
|
||||
cy.getByTestId(amountInput).click().type('100');
|
||||
cy.pause();
|
||||
cy.getByTestId(submitWithdrawalButton).click();
|
||||
});
|
||||
|
||||
cy.getByTestId('dialog-content')
|
||||
cy.getByTestId(withdrawalDialogContent)
|
||||
.last()
|
||||
.within(() => {
|
||||
cy.get('h1').should('have.text', 'Transaction failed');
|
||||
|
||||
@@ -128,6 +128,7 @@ context(
|
||||
.first()
|
||||
.find('[data-testid="view-proposal-btn"]')
|
||||
.click();
|
||||
cy.url().should('contain', '/protocol-upgrades/v1');
|
||||
cy.getByTestId('protocol-upgrade-proposal').within(() => {
|
||||
cy.get('h1').should('have.text', 'Vega Release v1');
|
||||
cy.getByTestId('protocol-upgrade-block-height').should(
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
import {
|
||||
enterUniqueFreeFormProposalBody,
|
||||
goToMakeNewProposal,
|
||||
governanceProposalType,
|
||||
} from '../../support/governance.functions';
|
||||
import { vegaWalletFaucetAssetsWithoutCheck } from '../../support/wallet-vega.functions';
|
||||
|
||||
@@ -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.`;
|
||||
|
||||
navigateTo(navigation.proposals);
|
||||
goToMakeNewProposal('Freeform');
|
||||
goToMakeNewProposal(governanceProposalType.FREEFORM);
|
||||
enterUniqueFreeFormProposalBody('50', 'pub key proposal test');
|
||||
cy.getByTestId('dialog-content')
|
||||
.first()
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
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';
|
||||
|
||||
const newProposalButton = '[data-testid="new-proposal-link"]';
|
||||
const proposalInformationTableRows = '[data-testid="key-value-table-row"]';
|
||||
const proposalListItem = '[data-testid="proposals-list-item"]';
|
||||
const newProposalTitle = '[data-testid="proposal-title"]';
|
||||
@@ -46,6 +50,53 @@ export function enterRawProposalBody(timestamp: number) {
|
||||
});
|
||||
}
|
||||
|
||||
export function submitUniqueRawProposal(proposalFields: {
|
||||
proposalBody?: string;
|
||||
proposalTitle?: string;
|
||||
proposalDescription?: string;
|
||||
closingTimestamp?: number;
|
||||
enactmentTimestamp?: number;
|
||||
submit?: boolean;
|
||||
}) {
|
||||
goToMakeNewProposal(governanceProposalType.RAW);
|
||||
let proposalBodyPath = '/proposals/raw.json';
|
||||
if (proposalFields.proposalBody) {
|
||||
proposalBodyPath = proposalFields.proposalBody;
|
||||
}
|
||||
cy.fixture(proposalBodyPath).then((rawProposal) => {
|
||||
if (proposalFields.proposalTitle) {
|
||||
rawProposal.rationale.title = proposalFields.proposalTitle;
|
||||
cy.wrap(proposalFields.proposalTitle).as('proposalTitle');
|
||||
}
|
||||
if (proposalFields.proposalDescription) {
|
||||
rawProposal.rationale.description = proposalFields.proposalDescription;
|
||||
}
|
||||
if (proposalFields.closingTimestamp) {
|
||||
rawProposal.terms.closingTimestamp = proposalFields.closingTimestamp;
|
||||
} else {
|
||||
const minTimeStamp = createTenDigitUnixTimeStampForSpecifiedDays(2);
|
||||
rawProposal.terms.closingTimestamp = minTimeStamp;
|
||||
}
|
||||
if (proposalFields.enactmentTimestamp) {
|
||||
rawProposal.terms.enactmentTimestamp = proposalFields.enactmentTimestamp;
|
||||
}
|
||||
|
||||
const proposalPayload = JSON.stringify(rawProposal);
|
||||
cy.get(rawProposalData).type(proposalPayload, {
|
||||
parseSpecialCharSequences: false,
|
||||
delay: 2,
|
||||
});
|
||||
|
||||
if (proposalFields.submit !== false) {
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.wrap(rawProposal).as('rawProposal');
|
||||
waitForProposalSubmitted();
|
||||
waitForProposalSync();
|
||||
navigateTo(navigation.proposals);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function enterUniqueFreeFormProposalBody(
|
||||
timestamp: string,
|
||||
proposalTitle: string
|
||||
@@ -58,6 +109,10 @@ export function enterUniqueFreeFormProposalBody(
|
||||
cy.getByTestId('proposal-submit').should('be.visible').click();
|
||||
}
|
||||
|
||||
export function getProposalFromTitle(proposalTitle: string) {
|
||||
return cy.contains(proposalTitle).parentsUntil(proposalListItem).last();
|
||||
}
|
||||
|
||||
export function getSubmittedProposalFromProposalList(proposalTitle: string) {
|
||||
getProposalIdFromList(proposalTitle);
|
||||
cy.get('@proposalIdText').then((proposalId) => {
|
||||
@@ -120,13 +175,17 @@ export function waitForProposalSync() {
|
||||
});
|
||||
}
|
||||
|
||||
export function goToMakeNewProposal(proposalType: string) {
|
||||
navigateTo(navigation.proposals);
|
||||
cy.get(newProposalButton).should('be.visible').click();
|
||||
export function goToMakeNewProposal(proposalType: governanceProposalType) {
|
||||
cy.visit('/proposals/propose');
|
||||
waitForSpinner();
|
||||
cy.url().should('include', '/proposals/propose');
|
||||
cy.get(navigation.pageSpinner, { timeout: 20000 }).should('not.exist');
|
||||
cy.get('li').should('contain.text', proposalType).and('be.visible');
|
||||
cy.get('li').contains(proposalType).click();
|
||||
if (proposalType == governanceProposalType.RAW) {
|
||||
cy.get('[href="/proposals/propose/raw"]').click();
|
||||
} else {
|
||||
cy.get('li').should('contain.text', proposalType).and('be.visible');
|
||||
cy.get('li').contains(proposalType).click();
|
||||
}
|
||||
}
|
||||
|
||||
export function waitForProposalSubmitted() {
|
||||
@@ -163,11 +222,12 @@ export function createFreeformProposal(proposalTitle: string) {
|
||||
navigateTo(navigation.proposals);
|
||||
}
|
||||
|
||||
export const governanceProposalType = {
|
||||
NETWORK_PARAMETER: 'Network parameter',
|
||||
NEW_MARKET: 'New market',
|
||||
UPDATE_MARKET: 'Update market',
|
||||
NEW_ASSET: 'New asset',
|
||||
FREEFORM: 'Freeform',
|
||||
RAW: 'raw proposal',
|
||||
};
|
||||
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',
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
cy.mockGQL((req) => {
|
||||
aliasGQLQuery(req, 'Nodes', nodeData);
|
||||
|
||||
@@ -5,7 +5,7 @@ const capsuleWalletConnectButton = '[data-testid="web3-connector-Unknown"]';
|
||||
|
||||
export function ethereumWalletConnect() {
|
||||
cy.highlight('Connecting Eth Wallet');
|
||||
cy.get(connectToEthButton).within(() => {
|
||||
cy.get(connectToEthButton, { timeout: 60000 }).within(() => {
|
||||
cy.contains('Connect Ethereum wallet to associate $VEGA')
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
@@ -67,7 +67,6 @@ export async function faucetAsset(assetEthAddress: string) {
|
||||
|
||||
export async function vegaWalletTeardown() {
|
||||
cy.get(associatedAmountInWallet)
|
||||
.should('be.visible')
|
||||
.invoke('text')
|
||||
.then((associatedAmount) => {
|
||||
cy.get('body').then(($body) => {
|
||||
@@ -82,9 +81,11 @@ export async function vegaWalletTeardown() {
|
||||
cy.get(vegaWalletContainer).within(() => {
|
||||
cy.get(associatedAmountInWallet, {
|
||||
timeout: transactionTimeout,
|
||||
}).contains('0.00', {
|
||||
timeout: transactionTimeout,
|
||||
});
|
||||
})
|
||||
.should('have.length', 1, { timeout: transactionTimeout })
|
||||
.contains('0.00', {
|
||||
timeout: transactionTimeout,
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
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_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_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||
NX_DELEGATIONS_PAGINATION=50
|
||||
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_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||
NX_VEGA_REST_URL=https://api.n00.stagnet1.vega.xyz/api/v2/
|
||||
|
||||
#Test configuration variables
|
||||
CYPRESS_FAIRGROUND=false
|
||||
|
||||
@@ -17,6 +17,7 @@ NX_VEGA_WALLET_URL=http://localhost:1789
|
||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||
NX_DELEGATIONS_PAGINATION=50
|
||||
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
|
||||
NX_VEGA_REST_URL=http://localhost:3008/api/v2/
|
||||
|
||||
#Test configuration variables
|
||||
CYPRESS_FAIRGROUND=false
|
||||
|
||||
@@ -11,3 +11,5 @@ NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||
NX_DELEGATIONS_PAGINATION=50
|
||||
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_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_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_ETHEREUM_PROVIDER_URL=https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHEREUM_PROVIDER_URL=https://eth-mainnet.gateway.pokt.network/v1/lb/6684b914570bbfa533ba9324
|
||||
NX_ETHERSCAN_URL=https://etherscan.io
|
||||
NX_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_DOCS_URL=https://docs.vega.xyz/mainnet
|
||||
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40:87edc2605e544f888305d7fc4a9141bd@o286262.ingest.sentry.io/5882996
|
||||
NX_DELEGATIONS_PAGINATION=50
|
||||
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_VEGA_REST_URL=https://api.vega.community/api/v2/
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
# App configuration variables
|
||||
NX_VEGA_URL=https://api.n00.stagnet1.vega.xyz/graphql
|
||||
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_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_DELEGATIONS_PAGINATION=50
|
||||
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_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_TRANCHES_SERVICE_URL=https://tranches-testnet-k8s.ops.vega.xyz
|
||||
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
|
||||
|
||||
@@ -9,3 +9,5 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
|
||||
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,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,
|
||||
} from '../../contexts/app-state/app-state-context';
|
||||
import { Connectors } from '../../lib/vega-connectors';
|
||||
import { RiskMessage } from './risk-message';
|
||||
|
||||
export const VegaWalletDialogs = () => {
|
||||
const { appState, appDispatch } = useAppState();
|
||||
|
||||
return (
|
||||
<>
|
||||
<VegaConnectDialog
|
||||
@@ -17,6 +19,7 @@ export const VegaWalletDialogs = () => {
|
||||
isOpen: open,
|
||||
})
|
||||
}
|
||||
riskMessage={<RiskMessage />}
|
||||
/>
|
||||
|
||||
<VegaManageDialog
|
||||
|
||||
@@ -62,6 +62,7 @@ export const ENV = {
|
||||
ethWalletMnemonic: windowOrDefault('NX_ETH_WALLET_MNEMONIC'),
|
||||
localProviderUrl: windowOrDefault('NX_LOCAL_PROVIDER_URL'),
|
||||
delegationsPagination: windowOrDefault('NX_DELEGATIONS_PAGINATION'),
|
||||
rest: windowOrDefault('NX_VEGA_REST_URL'),
|
||||
flags: {
|
||||
NETWORK_DOWN: TRUTHY.includes(windowOrDefault('NX_NETWORK_DOWN')),
|
||||
MOCK: TRUTHY.includes(windowOrDefault('NX_MOCKED')),
|
||||
|
||||
@@ -815,5 +815,11 @@
|
||||
"NoThanks": "No thanks",
|
||||
"ShareData": "Share 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."
|
||||
}
|
||||
|
||||
@@ -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 { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals';
|
||||
import { useProtocolUpgradeProposalsQuery } from '@vegaprotocol/proposals';
|
||||
import {
|
||||
orderByDate,
|
||||
orderByUpgradeBlockHeight,
|
||||
} from '../proposals/components/proposals-list/proposals-list';
|
||||
|
||||
const nodesToShow = 6;
|
||||
|
||||
@@ -200,17 +204,20 @@ const GovernanceHome = ({ name }: RouteChildProps) => {
|
||||
const proposals = useMemo(
|
||||
() =>
|
||||
proposalsData
|
||||
? getNotRejectedProposals<ProposalFieldsFragment>(
|
||||
proposalsData.proposalsConnection
|
||||
)
|
||||
? getNotRejectedProposals(proposalsData.proposalsConnection)
|
||||
: [],
|
||||
[proposalsData]
|
||||
);
|
||||
|
||||
const sortedProposals = useMemo(
|
||||
() => orderByDate(proposals).reverse(),
|
||||
[proposals]
|
||||
);
|
||||
|
||||
const protocolUpgradeProposals = useMemo(
|
||||
() =>
|
||||
protocolUpgradesData
|
||||
? getNotRejectedProtocolUpgradeProposals<ProtocolUpgradeProposalFieldsFragment>(
|
||||
? getNotRejectedProtocolUpgradeProposals(
|
||||
protocolUpgradesData.protocolUpgradeProposals
|
||||
).filter(
|
||||
(p) =>
|
||||
@@ -221,15 +228,20 @@ const GovernanceHome = ({ name }: RouteChildProps) => {
|
||||
[protocolUpgradesData]
|
||||
);
|
||||
|
||||
const sortedProtocolUpgradeProposals = useMemo(
|
||||
() => orderByUpgradeBlockHeight(protocolUpgradeProposals),
|
||||
[protocolUpgradeProposals]
|
||||
);
|
||||
|
||||
const totalProposalsDesired = 4;
|
||||
const protocolUpgradeProposalsToShow = protocolUpgradeProposals.slice(
|
||||
const protocolUpgradeProposalsToShow = sortedProtocolUpgradeProposals.slice(
|
||||
0,
|
||||
totalProposalsDesired
|
||||
);
|
||||
const proposalsToShow =
|
||||
protocolUpgradeProposalsToShow.length === totalProposalsDesired
|
||||
? []
|
||||
: proposals.slice(
|
||||
: sortedProposals.slice(
|
||||
0,
|
||||
totalProposalsDesired - protocolUpgradeProposalsToShow.length
|
||||
);
|
||||
|
||||
+1
-1
@@ -124,7 +124,7 @@ describe('Proposal header', () => {
|
||||
})
|
||||
);
|
||||
expect(screen.getByTestId('proposal-title')).toHaveTextContent(
|
||||
'Unknown proposal'
|
||||
'New asset proposal'
|
||||
);
|
||||
expect(screen.getByTestId('proposal-type')).toHaveTextContent('New asset');
|
||||
expect(screen.getByTestId('proposal-details')).toHaveTextContent(
|
||||
|
||||
+13
-2
@@ -21,6 +21,7 @@ export const ProposalHeader = ({
|
||||
|
||||
let details: ReactNode;
|
||||
let proposalType = '';
|
||||
let fallbackTitle = '';
|
||||
|
||||
const title = proposal?.rationale.title.trim();
|
||||
|
||||
@@ -29,6 +30,7 @@ export const ProposalHeader = ({
|
||||
switch (change?.__typename) {
|
||||
case 'NewMarket': {
|
||||
proposalType = 'NewMarket';
|
||||
fallbackTitle = t('NewMarketProposal');
|
||||
details = (
|
||||
<>
|
||||
<span>
|
||||
@@ -50,6 +52,7 @@ export const ProposalHeader = ({
|
||||
}
|
||||
case 'UpdateMarket': {
|
||||
proposalType = 'UpdateMarket';
|
||||
fallbackTitle = t('UpdateMarketProposal');
|
||||
details = (
|
||||
<>
|
||||
<span>{t('Market change')}:</span>{' '}
|
||||
@@ -60,6 +63,7 @@ export const ProposalHeader = ({
|
||||
}
|
||||
case 'NewAsset': {
|
||||
proposalType = 'NewAsset';
|
||||
fallbackTitle = t('NewAssetProposal');
|
||||
details = (
|
||||
<>
|
||||
<span>{t('Symbol')}:</span> <Lozenge>{change.symbol}.</Lozenge>{' '}
|
||||
@@ -81,6 +85,7 @@ export const ProposalHeader = ({
|
||||
}
|
||||
case 'UpdateNetworkParameter': {
|
||||
proposalType = 'NetworkParameter';
|
||||
fallbackTitle = t('NetworkParameterProposal');
|
||||
details = (
|
||||
<>
|
||||
<span>{t('Change')}:</span>{' '}
|
||||
@@ -95,11 +100,13 @@ export const ProposalHeader = ({
|
||||
}
|
||||
case 'NewFreeform': {
|
||||
proposalType = 'Freeform';
|
||||
fallbackTitle = t('FreeformProposal');
|
||||
details = <span />;
|
||||
break;
|
||||
}
|
||||
case 'UpdateAsset': {
|
||||
proposalType = 'UpdateAsset';
|
||||
fallbackTitle = t('UpdateAssetProposal');
|
||||
details = (
|
||||
<>
|
||||
<span>{t('AssetID')}:</span>{' '}
|
||||
@@ -115,10 +122,14 @@ export const ProposalHeader = ({
|
||||
<div data-testid="proposal-title">
|
||||
{isListItem ? (
|
||||
<header>
|
||||
<SubHeading title={titleContent || t('Unknown proposal')} />
|
||||
<SubHeading
|
||||
title={titleContent || fallbackTitle || t('Unknown proposal')}
|
||||
/>
|
||||
</header>
|
||||
) : (
|
||||
<Heading title={titleContent || t('Unknown proposal')} />
|
||||
<Heading
|
||||
title={titleContent || fallbackTitle || t('Unknown proposal')}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -43,13 +43,17 @@ jest.mock('../list-asset', () => ({
|
||||
|
||||
it('Renders with data-testid', async () => {
|
||||
const proposal = generateProposal();
|
||||
render(<Proposal proposal={proposal as ProposalQuery['proposal']} />);
|
||||
render(
|
||||
<Proposal restData={{}} proposal={proposal as ProposalQuery['proposal']} />
|
||||
);
|
||||
expect(await screen.findByTestId('proposal')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders each section', async () => {
|
||||
const proposal = generateProposal();
|
||||
render(<Proposal proposal={proposal as ProposalQuery['proposal']} />);
|
||||
render(
|
||||
<Proposal restData={{}} proposal={proposal as ProposalQuery['proposal']} />
|
||||
);
|
||||
expect(await screen.findByTestId('proposal-header')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('proposal-change-table')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('proposal-json')).toBeInTheDocument();
|
||||
@@ -76,6 +80,8 @@ it('renders whitelist section if proposal is new asset and source is erc20', asy
|
||||
},
|
||||
},
|
||||
});
|
||||
render(<Proposal proposal={proposal as ProposalQuery['proposal']} />);
|
||||
render(
|
||||
<Proposal restData={{}} proposal={proposal as ProposalQuery['proposal']} />
|
||||
);
|
||||
expect(screen.getByTestId('proposal-list-asset')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
@@ -24,9 +24,11 @@ export enum ProposalType {
|
||||
}
|
||||
export interface ProposalProps {
|
||||
proposal: ProposalFieldsFragment | ProposalQuery['proposal'];
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
restData: any;
|
||||
}
|
||||
|
||||
export const Proposal = ({ proposal }: ProposalProps) => {
|
||||
export const Proposal = ({ proposal, restData }: ProposalProps) => {
|
||||
const { params, loading, error } = useNetworkParams([
|
||||
NetworkParams.governance_proposal_market_minVoterBalance,
|
||||
NetworkParams.governance_proposal_updateMarket_minVoterBalance,
|
||||
@@ -99,12 +101,15 @@ export const Proposal = ({ proposal }: ProposalProps) => {
|
||||
<ProposalDescription description={proposal.rationale.description} />
|
||||
</div>
|
||||
|
||||
<div className="mb-4">
|
||||
<ProposalTerms data={proposal.terms} />
|
||||
</div>
|
||||
{proposal.terms.change.__typename !== 'NewMarket' &&
|
||||
proposal.terms.change.__typename !== 'UpdateMarket' && (
|
||||
<div className="mb-4">
|
||||
<ProposalTerms data={proposal.terms} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="mb-6">
|
||||
<ProposalJson proposal={proposal} />
|
||||
<ProposalJson proposal={restData?.data?.proposal} />
|
||||
</div>
|
||||
|
||||
<div className="mb-10">
|
||||
|
||||
-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', () => {
|
||||
render(renderComponent([]));
|
||||
expect(screen.queryByTestId('open-proposals')).not.toBeInTheDocument();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import orderBy from 'lodash/orderBy';
|
||||
import { isFuture } from 'date-fns';
|
||||
import { useState } from 'react';
|
||||
import { useState, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Heading, SubHeading } from '../../../../components/heading';
|
||||
import { ProposalsListItem } from '../proposals-list-item';
|
||||
@@ -30,6 +31,29 @@ interface SortedProtocolUpgradeProposalsProps {
|
||||
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 = ({
|
||||
proposals,
|
||||
protocolUpgradeProposals,
|
||||
@@ -37,35 +61,57 @@ export const ProposalsList = ({
|
||||
}: ProposalsListProps) => {
|
||||
const { t } = useTranslation();
|
||||
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(
|
||||
(acc: SortedProtocolUpgradeProposalsProps, proposal) => {
|
||||
if (Number(proposal?.upgradeBlockHeight) > Number(lastBlockHeight)) {
|
||||
acc.open.push(proposal);
|
||||
} else {
|
||||
acc.closed.push(proposal);
|
||||
const sortedProposals: SortedProposalsProps = useMemo(() => {
|
||||
const initialSorting = 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: [],
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{
|
||||
open: [],
|
||||
closed: [],
|
||||
}
|
||||
);
|
||||
);
|
||||
return {
|
||||
open:
|
||||
initialSorting.open.length > 0
|
||||
? 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 = (
|
||||
p: ProposalFieldsFragment | ProposalQuery['proposal']
|
||||
|
||||
+1
-1
@@ -107,7 +107,7 @@ export const ProtocolUpgradeProposalsListItem = ({
|
||||
<div className="grid grid-cols-1 mt-3">
|
||||
<div className="justify-self-end">
|
||||
<Link
|
||||
to={`${Routes.PROPOSALS}/protocol-upgrade/${stripFullStops(
|
||||
to={`${Routes.PROTOCOL_UPGRADES}/${stripFullStops(
|
||||
proposal.vegaReleaseTag
|
||||
)}`}
|
||||
>
|
||||
|
||||
@@ -5,9 +5,14 @@ import { useParams } from 'react-router-dom';
|
||||
import { Proposal } from '../components/proposal';
|
||||
import { ProposalNotFound } from '../components/proposal-not-found';
|
||||
import { useProposalQuery } from './__generated__/Proposal';
|
||||
import { useFetch } from '@vegaprotocol/react-helpers';
|
||||
import { ENV } from '../../../config';
|
||||
|
||||
export const ProposalContainer = () => {
|
||||
const params = useParams<{ proposalId: string }>();
|
||||
const {
|
||||
state: { data: restData },
|
||||
} = useFetch(`${ENV.rest}governance?proposalId=${params.proposalId}`);
|
||||
const { data, loading, error, refetch } = useProposalQuery({
|
||||
fetchPolicy: 'network-only',
|
||||
errorPolicy: 'ignore',
|
||||
@@ -23,7 +28,7 @@ export const ProposalContainer = () => {
|
||||
return (
|
||||
<AsyncRenderer loading={loading} error={error} data={data}>
|
||||
{data?.proposal ? (
|
||||
<Proposal proposal={data.proposal} />
|
||||
<Proposal proposal={data.proposal} restData={restData} />
|
||||
) : (
|
||||
<ProposalNotFound />
|
||||
)}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import flow from 'lodash/flow';
|
||||
import { Callout, Intent, Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -6,36 +7,15 @@ import { SplashLoader } from '../../../components/splash-loader';
|
||||
import { ProposalsList } from '../components/proposals-list';
|
||||
import { useProposalsQuery } from './__generated__/Proposals';
|
||||
import { getNodes } from '@vegaprotocol/utils';
|
||||
import flow from 'lodash/flow';
|
||||
import {
|
||||
ProposalState,
|
||||
ProtocolUpgradeProposalStatus,
|
||||
} from '@vegaprotocol/types';
|
||||
import type { NodeConnection, NodeEdge } from '@vegaprotocol/utils';
|
||||
import type { ProposalFieldsFragment } from './__generated__/Proposals';
|
||||
import orderBy from 'lodash/orderBy';
|
||||
import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals';
|
||||
import { useProtocolUpgradeProposalsQuery } from '@vegaprotocol/proposals';
|
||||
|
||||
const orderByDate = (arr: ProposalFieldsFragment[]) =>
|
||||
orderBy(
|
||||
arr,
|
||||
[
|
||||
(p) => new Date(p?.terms?.closingDatetime).getTime(),
|
||||
(p) => new Date(p?.datetime).getTime(),
|
||||
],
|
||||
['asc', 'asc']
|
||||
);
|
||||
|
||||
const orderByUpgradeBlockHeight = (
|
||||
arr: ProtocolUpgradeProposalFieldsFragment[]
|
||||
) =>
|
||||
orderBy(
|
||||
arr,
|
||||
[(p) => p?.upgradeBlockHeight, (p) => p.vegaReleaseTag],
|
||||
['desc', 'desc']
|
||||
);
|
||||
|
||||
export function getNotRejectedProposals<T extends ProposalFieldsFragment>(
|
||||
data?: NodeConnection<NodeEdge<T>> | null
|
||||
): T[] {
|
||||
@@ -44,7 +24,6 @@ export function getNotRejectedProposals<T extends ProposalFieldsFragment>(
|
||||
getNodes<ProposalFieldsFragment>(data, (p) =>
|
||||
p ? p.state !== ProposalState.STATE_REJECTED : false
|
||||
),
|
||||
orderByDate,
|
||||
])(data);
|
||||
}
|
||||
|
||||
@@ -59,7 +38,6 @@ export function getNotRejectedProtocolUpgradeProposals<
|
||||
ProtocolUpgradeProposalStatus.PROTOCOL_UPGRADE_PROPOSAL_STATUS_REJECTED
|
||||
: false
|
||||
),
|
||||
orderByUpgradeBlockHeight,
|
||||
])(data);
|
||||
}
|
||||
|
||||
@@ -82,17 +60,14 @@ export const ProposalsContainer = () => {
|
||||
});
|
||||
|
||||
const proposals = useMemo(
|
||||
() =>
|
||||
getNotRejectedProposals<ProposalFieldsFragment>(
|
||||
data?.proposalsConnection
|
||||
),
|
||||
() => getNotRejectedProposals(data?.proposalsConnection),
|
||||
[data]
|
||||
);
|
||||
|
||||
const protocolUpgradeProposals = useMemo(
|
||||
() =>
|
||||
protocolUpgradesData
|
||||
? getNotRejectedProtocolUpgradeProposals<ProtocolUpgradeProposalFieldsFragment>(
|
||||
? getNotRejectedProtocolUpgradeProposals(
|
||||
protocolUpgradesData.protocolUpgradeProposals
|
||||
)
|
||||
: [],
|
||||
|
||||
@@ -49,6 +49,7 @@ export const ProposeFreeform = () => {
|
||||
formState: { errors },
|
||||
setValue,
|
||||
watch,
|
||||
trigger,
|
||||
} = useForm<FreeformProposalFormFields>();
|
||||
const { finalizedProposal, submit, Dialog } = useProposalSubmit();
|
||||
|
||||
@@ -85,7 +86,13 @@ export const ProposeFreeform = () => {
|
||||
await submit(assembleProposal(fields));
|
||||
};
|
||||
|
||||
const viewJson = () => {
|
||||
const viewJson = async () => {
|
||||
const isValid = await trigger();
|
||||
|
||||
if (!isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = watch();
|
||||
downloadJson(
|
||||
JSON.stringify(assembleProposal(formData)),
|
||||
|
||||
+8
-1
@@ -89,6 +89,7 @@ export const ProposeNetworkParameter = () => {
|
||||
formState: { errors },
|
||||
setValue,
|
||||
watch,
|
||||
trigger,
|
||||
} = useForm<NetworkParameterProposalFormFields>();
|
||||
const { finalizedProposal, submit, Dialog } = useProposalSubmit();
|
||||
|
||||
@@ -148,7 +149,13 @@ export const ProposeNetworkParameter = () => {
|
||||
await submit(assembleProposal(fields));
|
||||
};
|
||||
|
||||
const viewJson = () => {
|
||||
const viewJson = async () => {
|
||||
const isValid = await trigger();
|
||||
|
||||
if (!isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = watch();
|
||||
downloadJson(
|
||||
JSON.stringify(assembleProposal(formData)),
|
||||
|
||||
@@ -61,6 +61,7 @@ export const ProposeNewAsset = () => {
|
||||
formState: { errors },
|
||||
setValue,
|
||||
watch,
|
||||
trigger,
|
||||
} = useForm<NewAssetProposalFormFields>();
|
||||
const { finalizedProposal, submit, Dialog } = useProposalSubmit();
|
||||
|
||||
@@ -117,7 +118,13 @@ export const ProposeNewAsset = () => {
|
||||
await submit(assembleProposal(fields));
|
||||
};
|
||||
|
||||
const viewJson = () => {
|
||||
const viewJson = async () => {
|
||||
const isValid = await trigger();
|
||||
|
||||
if (!isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = watch();
|
||||
downloadJson(
|
||||
JSON.stringify(assembleProposal(formData)),
|
||||
|
||||
@@ -59,6 +59,7 @@ export const ProposeNewMarket = () => {
|
||||
formState: { errors },
|
||||
setValue,
|
||||
watch,
|
||||
trigger,
|
||||
} = useForm<NewMarketProposalFormFields>();
|
||||
const { finalizedProposal, submit, Dialog } = useProposalSubmit();
|
||||
|
||||
@@ -107,7 +108,13 @@ export const ProposeNewMarket = () => {
|
||||
await submit(assembleProposal(fields));
|
||||
};
|
||||
|
||||
const viewJson = () => {
|
||||
const viewJson = async () => {
|
||||
const isValid = await trigger();
|
||||
|
||||
if (!isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = watch();
|
||||
downloadJson(
|
||||
JSON.stringify(assembleProposal(formData)),
|
||||
|
||||
@@ -59,6 +59,7 @@ export const ProposeUpdateAsset = () => {
|
||||
formState: { errors },
|
||||
setValue,
|
||||
watch,
|
||||
trigger,
|
||||
} = useForm<UpdateAssetProposalFormFields>();
|
||||
const { finalizedProposal, submit, Dialog } = useProposalSubmit();
|
||||
|
||||
@@ -107,7 +108,13 @@ export const ProposeUpdateAsset = () => {
|
||||
await submit(assembleProposal(fields));
|
||||
};
|
||||
|
||||
const viewJson = () => {
|
||||
const viewJson = async () => {
|
||||
const isValid = await trigger();
|
||||
|
||||
if (!isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = watch();
|
||||
downloadJson(
|
||||
JSON.stringify(assembleProposal(formData)),
|
||||
|
||||
+8
-1
@@ -106,6 +106,7 @@ export const ProposeUpdateMarket = () => {
|
||||
formState: { errors },
|
||||
setValue,
|
||||
watch,
|
||||
trigger,
|
||||
} = useForm<UpdateMarketProposalFormFields>();
|
||||
const { finalizedProposal, submit, Dialog } = useProposalSubmit();
|
||||
|
||||
@@ -157,7 +158,13 @@ export const ProposeUpdateMarket = () => {
|
||||
await submit(assembleProposal(fields));
|
||||
};
|
||||
|
||||
const viewJson = () => {
|
||||
const viewJson = async () => {
|
||||
const isValid = await trigger();
|
||||
|
||||
if (!isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = watch();
|
||||
downloadJson(
|
||||
JSON.stringify(assembleProposal(formData)),
|
||||
|
||||
@@ -5,6 +5,9 @@ import { ProtocolUpgradeProposalDetailInfo } from '../components/protocol-upgrad
|
||||
import { getNormalisedVotingPower } from '../../staking/shared';
|
||||
import type { NodesFragmentFragment } from '../../staking/home/__generated__/Nodes';
|
||||
import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals';
|
||||
import { useVegaRelease } from '@vegaprotocol/environment';
|
||||
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export interface ProtocolUpgradeProposalProps {
|
||||
proposal: ProtocolUpgradeProposalFieldsFragment;
|
||||
@@ -42,6 +45,9 @@ export const ProtocolUpgradeProposal = ({
|
||||
lastBlockHeight,
|
||||
consensusValidators,
|
||||
}: ProtocolUpgradeProposalProps) => {
|
||||
const { t } = useTranslation();
|
||||
const releaseInfo = useVegaRelease(proposal.vegaReleaseTag);
|
||||
|
||||
const consensusApprovals = useMemo(
|
||||
() => getConsensusApprovals(consensusValidators || [], proposal),
|
||||
[consensusValidators, proposal]
|
||||
@@ -78,6 +84,14 @@ export const ProtocolUpgradeProposal = ({
|
||||
totalConsensusValidators={consensusValidators.length}
|
||||
/>
|
||||
)}
|
||||
|
||||
{releaseInfo && releaseInfo.htmlUrl && (
|
||||
<div className="mb-10">
|
||||
<ExternalLink href={releaseInfo.htmlUrl}>
|
||||
{t('Explore release on GitHub')}
|
||||
</ExternalLink>
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -16,11 +16,10 @@ const orderByDate = (arr: ProposalFieldsFragment[]) =>
|
||||
orderBy(
|
||||
arr,
|
||||
[
|
||||
(p) => new Date(p?.terms?.enactmentDatetime || 0).getTime(), // has to be defaulted to 0 because new Date(null).getTime() -> NaN which is first when ordered.
|
||||
(p) => new Date(p?.terms?.closingDatetime).getTime(),
|
||||
(p) => new Date(p?.terms?.closingDatetime || 0).getTime(), // has to be defaulted to 0 because new Date(null).getTime() -> NaN which is first when ordered
|
||||
(p) => p.id,
|
||||
],
|
||||
['desc', 'desc', 'desc']
|
||||
['desc', 'desc']
|
||||
);
|
||||
|
||||
export function getRejectedProposals<T extends ProposalFieldsFragment>(
|
||||
|
||||
@@ -207,6 +207,13 @@ const LazyWithdrawals = React.lazy(
|
||||
)
|
||||
);
|
||||
|
||||
const LazyDisclaimer = React.lazy(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "route-disclaimer", webpackPrefetch: true */ './disclaimer'
|
||||
)
|
||||
);
|
||||
|
||||
const redirects = [
|
||||
{
|
||||
path: Routes.VALIDATORS,
|
||||
@@ -224,6 +231,10 @@ const redirects = [
|
||||
path: '/vesting',
|
||||
element: <Navigate to={Routes.REDEEM} replace />,
|
||||
},
|
||||
{
|
||||
path: Routes.PROTOCOL_UPGRADES,
|
||||
element: <Navigate to={Routes.PROPOSALS} replace />,
|
||||
},
|
||||
];
|
||||
|
||||
const routerConfig = [
|
||||
@@ -264,13 +275,13 @@ const routerConfig = [
|
||||
},
|
||||
{ path: 'proposals', element: <LazyProposalsList /> },
|
||||
{ path: ':proposalId', element: <LazyProposal /> },
|
||||
{
|
||||
path: 'protocol-upgrade/:proposalReleaseTag',
|
||||
element: <LazyProtocolUpgradeProposal />,
|
||||
},
|
||||
{ path: 'rejected', element: <LazyRejectedProposalsList /> },
|
||||
],
|
||||
},
|
||||
{
|
||||
path: `${Routes.PROTOCOL_UPGRADES}/:proposalReleaseTag`,
|
||||
element: <LazyProtocolUpgradeProposal />,
|
||||
},
|
||||
{
|
||||
path: Routes.VALIDATORS,
|
||||
element: <LazyStaking name="Staking" />,
|
||||
@@ -345,6 +356,10 @@ const routerConfig = [
|
||||
path: Routes.CONTRACTS,
|
||||
element: <LazyContracts name="Contracts" />,
|
||||
},
|
||||
{
|
||||
path: Routes.DISCLAIMER,
|
||||
element: <LazyDisclaimer name="Disclaimer" />,
|
||||
},
|
||||
{
|
||||
path: '*',
|
||||
// Not lazy as loaded when a user first hits the site
|
||||
|
||||
@@ -5,6 +5,7 @@ const Routes = {
|
||||
REWARDS: '/rewards',
|
||||
PROPOSALS: '/proposals',
|
||||
PROPOSALS_REJECTED: '/proposals/rejected',
|
||||
PROTOCOL_UPGRADES: '/protocol-upgrades',
|
||||
NOT_PERMITTED: '/not-permitted',
|
||||
NOT_FOUND: '/not-found',
|
||||
CONTRACTS: '/contracts',
|
||||
@@ -14,6 +15,7 @@ const Routes = {
|
||||
SUPPLY: '/token/tranches',
|
||||
ASSOCIATE: '/token/associate',
|
||||
DISASSOCIATE: '/token/disassociate',
|
||||
DISCLAIMER: '/disclaimer',
|
||||
};
|
||||
|
||||
export default Routes;
|
||||
|
||||
@@ -5,12 +5,22 @@ query PreviousEpoch($epochId: ID) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
stakedTotal
|
||||
rewardScore {
|
||||
rawValidatorScore
|
||||
performanceScore
|
||||
multisigScore
|
||||
validatorScore
|
||||
normalisedScore
|
||||
validatorStatus
|
||||
}
|
||||
rankingScore {
|
||||
status
|
||||
previousStatus
|
||||
rankingScore
|
||||
stakeScore
|
||||
performanceScore
|
||||
votingPower
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ export type PreviousEpochQueryVariables = Types.Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type PreviousEpochQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string, validatorsConnection?: { __typename?: 'NodesConnection', edges?: Array<{ __typename?: 'NodeEdge', node: { __typename?: 'Node', id: string, rewardScore?: { __typename?: 'RewardScore', rawValidatorScore: string, performanceScore: string } | null, rankingScore: { __typename?: 'RankingScore', stakeScore: string } } } | null> | null } | null } };
|
||||
export type PreviousEpochQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string, validatorsConnection?: { __typename?: 'NodesConnection', edges?: Array<{ __typename?: 'NodeEdge', node: { __typename?: 'Node', id: string, stakedTotal: string, rewardScore?: { __typename?: 'RewardScore', rawValidatorScore: string, performanceScore: string, multisigScore: string, validatorScore: string, normalisedScore: string, validatorStatus: Types.ValidatorStatus } | null, rankingScore: { __typename?: 'RankingScore', status: Types.ValidatorStatus, previousStatus: Types.ValidatorStatus, rankingScore: string, stakeScore: string, performanceScore: string, votingPower: string } } } | null> | null } | null } };
|
||||
|
||||
|
||||
export const PreviousEpochDocument = gql`
|
||||
@@ -19,12 +19,22 @@ export const PreviousEpochDocument = gql`
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
stakedTotal
|
||||
rewardScore {
|
||||
rawValidatorScore
|
||||
performanceScore
|
||||
multisigScore
|
||||
validatorScore
|
||||
normalisedScore
|
||||
validatorStatus
|
||||
}
|
||||
rankingScore {
|
||||
status
|
||||
previousStatus
|
||||
rankingScore
|
||||
stakeScore
|
||||
performanceScore
|
||||
votingPower
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+36
@@ -79,36 +79,72 @@ const MOCK_PREVIOUS_EPOCH: PreviousEpochQuery = {
|
||||
{
|
||||
node: {
|
||||
id: 'ccc022b7e63a4d0a6d3a193c3940c88574060e58a184964c994998d86835a1b4',
|
||||
stakedTotal: '14182454495731682635157',
|
||||
rewardScore: {
|
||||
rawValidatorScore: '0.25',
|
||||
performanceScore: '0.9998677767864936',
|
||||
multisigScore: '',
|
||||
validatorScore: '',
|
||||
normalisedScore: '',
|
||||
validatorStatus:
|
||||
Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
},
|
||||
rankingScore: {
|
||||
stakeScore: '0.2499583402766206',
|
||||
performanceScore: '0.9998677767864936',
|
||||
status: Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
previousStatus:
|
||||
Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
rankingScore: '',
|
||||
votingPower: '',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
node: {
|
||||
id: '966438c6bffac737cfb08173ffcb3f393c4692b099ad80cb45a82e2dc0a8cf99',
|
||||
stakedTotal: '9618711883996159534058',
|
||||
rewardScore: {
|
||||
rawValidatorScore: '0.3',
|
||||
performanceScore: '1',
|
||||
multisigScore: '',
|
||||
validatorScore: '0.31067',
|
||||
normalisedScore: '',
|
||||
validatorStatus:
|
||||
Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
},
|
||||
rankingScore: {
|
||||
stakeScore: '0.25',
|
||||
performanceScore: '0.9998677767864936',
|
||||
status: Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
previousStatus:
|
||||
Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
rankingScore: '',
|
||||
votingPower: '',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
node: {
|
||||
id: '12c81b738e8051152e1afe44376ec37bca9216466e6d44cdd772194bad0ada81',
|
||||
stakedTotal: '4041343338923442976709',
|
||||
rewardScore: {
|
||||
rawValidatorScore: '0.35',
|
||||
performanceScore: '0.999629748500531',
|
||||
multisigScore: '',
|
||||
validatorScore: '',
|
||||
normalisedScore: '',
|
||||
validatorStatus:
|
||||
Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
},
|
||||
rankingScore: {
|
||||
stakeScore: '0.2312',
|
||||
performanceScore: '0.9998677767864936',
|
||||
status: Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
previousStatus:
|
||||
Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
rankingScore: '',
|
||||
votingPower: '',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
+23
-23
@@ -7,12 +7,12 @@ import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { useAppState } from '../../../../contexts/app-state/app-state-context';
|
||||
import { BigNumber } from '../../../../lib/bignumber';
|
||||
import {
|
||||
calculateOverallPenalty,
|
||||
calculateOverstakedPenalty,
|
||||
calculatesPerformancePenalty,
|
||||
getFormattedPerformanceScore,
|
||||
getLastEpochScoreAndPerformance,
|
||||
getNormalisedVotingPower,
|
||||
getOverstakingPenalty,
|
||||
getPerformancePenalty,
|
||||
getTotalPenalties,
|
||||
getUnnormalisedVotingPower,
|
||||
} from '../../shared';
|
||||
import {
|
||||
@@ -32,6 +32,7 @@ import type { ValidatorsTableProps } from './shared';
|
||||
import {
|
||||
formatNumber,
|
||||
formatNumberPercentage,
|
||||
removePaginationWrapper,
|
||||
toBigNum,
|
||||
} from '@vegaprotocol/utils';
|
||||
import { VALIDATOR_LOGO_MAP } from './logo-map';
|
||||
@@ -136,6 +137,10 @@ export const ConsensusValidatorsTable = ({
|
||||
[totalStake]
|
||||
);
|
||||
|
||||
const allNodesInPreviousEpoch = removePaginationWrapper(
|
||||
previousEpochData?.epoch.validatorsConnection?.edges
|
||||
);
|
||||
|
||||
const nodes = useMemo(() => {
|
||||
if (!data) return [];
|
||||
let canonisedNodes = data
|
||||
@@ -160,7 +165,7 @@ export const ConsensusValidatorsTable = ({
|
||||
stakedByDelegates,
|
||||
stakedByOperator,
|
||||
stakedTotal,
|
||||
rankingScore: { stakeScore, votingPower },
|
||||
rankingScore: { stakeScore, votingPower, performanceScore },
|
||||
pendingStake,
|
||||
stakedTotalRanking,
|
||||
stakedByUser,
|
||||
@@ -172,11 +177,8 @@ export const ConsensusValidatorsTable = ({
|
||||
: avatarUrl
|
||||
? avatarUrl
|
||||
: null;
|
||||
const {
|
||||
rawValidatorScore: previousEpochValidatorScore,
|
||||
performanceScore: previousEpochPerformanceScore,
|
||||
stakeScore: previousEpochStakeScore,
|
||||
} = getLastEpochScoreAndPerformance(previousEpochData, id);
|
||||
const { rawValidatorScore: previousEpochValidatorScore } =
|
||||
getLastEpochScoreAndPerformance(previousEpochData, id);
|
||||
|
||||
return {
|
||||
id,
|
||||
@@ -199,21 +201,19 @@ export const ConsensusValidatorsTable = ({
|
||||
toBigNum(stakedByOperator, decimals),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.PERFORMANCE_SCORE]: getFormattedPerformanceScore(
|
||||
previousEpochPerformanceScore
|
||||
).toString(),
|
||||
[ValidatorFields.PERFORMANCE_PENALTY]: getPerformancePenalty(
|
||||
previousEpochPerformanceScore
|
||||
[ValidatorFields.PERFORMANCE_SCORE]:
|
||||
getFormattedPerformanceScore(performanceScore).toString(),
|
||||
[ValidatorFields.PERFORMANCE_PENALTY]: formatNumberPercentage(
|
||||
calculatesPerformancePenalty(performanceScore),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.OVERSTAKING_PENALTY]: getOverstakingPenalty(
|
||||
previousEpochValidatorScore,
|
||||
previousEpochStakeScore
|
||||
[ValidatorFields.OVERSTAKING_PENALTY]: formatNumberPercentage(
|
||||
calculateOverstakedPenalty(id, allNodesInPreviousEpoch),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.TOTAL_PENALTIES]: getTotalPenalties(
|
||||
previousEpochValidatorScore,
|
||||
previousEpochPerformanceScore,
|
||||
stakedTotal,
|
||||
totalStake
|
||||
[ValidatorFields.TOTAL_PENALTIES]: formatNumberPercentage(
|
||||
calculateOverallPenalty(id, allNodesInPreviousEpoch),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.PENDING_STAKE]: pendingStake,
|
||||
[ValidatorFields.STAKED_BY_USER]: stakedByUser
|
||||
@@ -328,12 +328,12 @@ export const ConsensusValidatorsTable = ({
|
||||
...remaining,
|
||||
];
|
||||
}, [
|
||||
allNodesInPreviousEpoch,
|
||||
data,
|
||||
decimals,
|
||||
hideTopThird,
|
||||
previousEpochData,
|
||||
thirdOfTotalStake,
|
||||
totalStake,
|
||||
validatorsView,
|
||||
]);
|
||||
|
||||
|
||||
+33
-34
@@ -5,15 +5,14 @@ import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { useAppState } from '../../../../contexts/app-state/app-state-context';
|
||||
import { BigNumber } from '../../../../lib/bignumber';
|
||||
import {
|
||||
calculatesPerformancePenalty,
|
||||
calculateOverallPenalty,
|
||||
calculateOverstakedPenalty,
|
||||
getFormattedPerformanceScore,
|
||||
getLastEpochScoreAndPerformance,
|
||||
getOverstakingPenalty,
|
||||
getPerformancePenalty,
|
||||
getTotalPenalties,
|
||||
} from '../../shared';
|
||||
import {
|
||||
defaultColDef,
|
||||
StakeNeededForPromotionRenderer,
|
||||
stakedTotalPercentage,
|
||||
ValidatorFields,
|
||||
ValidatorRenderer,
|
||||
@@ -28,6 +27,7 @@ import type { ValidatorsTableProps } from './shared';
|
||||
import {
|
||||
formatNumber,
|
||||
formatNumberPercentage,
|
||||
removePaginationWrapper,
|
||||
toBigNum,
|
||||
} from '@vegaprotocol/utils';
|
||||
|
||||
@@ -52,6 +52,10 @@ export const StandbyPendingValidatorsTable = ({
|
||||
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
|
||||
const allNodesInPreviousEpoch = removePaginationWrapper(
|
||||
previousEpochData?.epoch.validatorsConnection?.edges
|
||||
);
|
||||
|
||||
let nodes = useMemo(() => {
|
||||
if (!data) return [];
|
||||
|
||||
@@ -77,18 +81,15 @@ export const StandbyPendingValidatorsTable = ({
|
||||
stakedByDelegates,
|
||||
stakedByOperator,
|
||||
stakedTotal,
|
||||
rankingScore: { stakeScore },
|
||||
rankingScore: { stakeScore, performanceScore },
|
||||
pendingStake,
|
||||
stakedTotalRanking,
|
||||
stakedByUser,
|
||||
pendingUserStake,
|
||||
userStakeShare,
|
||||
}) => {
|
||||
const {
|
||||
rawValidatorScore: previousEpochValidatorScore,
|
||||
performanceScore: previousEpochPerformanceScore,
|
||||
stakeScore: previousEpochStakeScore,
|
||||
} = getLastEpochScoreAndPerformance(previousEpochData, id);
|
||||
const { performanceScore: previousEpochPerformanceScore } =
|
||||
getLastEpochScoreAndPerformance(previousEpochData, id);
|
||||
|
||||
let individualStakeNeededForPromotion,
|
||||
individualStakeNeededForPromotionDescription;
|
||||
@@ -144,21 +145,19 @@ export const StandbyPendingValidatorsTable = ({
|
||||
toBigNum(stakedByOperator, decimals),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.PERFORMANCE_SCORE]: getFormattedPerformanceScore(
|
||||
previousEpochPerformanceScore
|
||||
).toString(),
|
||||
[ValidatorFields.PERFORMANCE_PENALTY]: getPerformancePenalty(
|
||||
previousEpochPerformanceScore
|
||||
[ValidatorFields.PERFORMANCE_SCORE]:
|
||||
getFormattedPerformanceScore(performanceScore).toString(),
|
||||
[ValidatorFields.PERFORMANCE_PENALTY]: formatNumberPercentage(
|
||||
calculatesPerformancePenalty(performanceScore),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.OVERSTAKING_PENALTY]: getOverstakingPenalty(
|
||||
previousEpochValidatorScore,
|
||||
previousEpochStakeScore
|
||||
[ValidatorFields.OVERSTAKING_PENALTY]: formatNumberPercentage(
|
||||
calculateOverstakedPenalty(id, allNodesInPreviousEpoch),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.TOTAL_PENALTIES]: getTotalPenalties(
|
||||
previousEpochValidatorScore,
|
||||
previousEpochPerformanceScore,
|
||||
stakedTotal,
|
||||
totalStake
|
||||
[ValidatorFields.TOTAL_PENALTIES]: formatNumberPercentage(
|
||||
calculateOverallPenalty(id, allNodesInPreviousEpoch),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.PENDING_STAKE]: pendingStake,
|
||||
[ValidatorFields.STAKED_BY_USER]: stakedByUser
|
||||
@@ -172,13 +171,13 @@ export const StandbyPendingValidatorsTable = ({
|
||||
}
|
||||
);
|
||||
}, [
|
||||
allNodesInPreviousEpoch,
|
||||
data,
|
||||
decimals,
|
||||
previousEpochData,
|
||||
stakeNeededForPromotion,
|
||||
stakeNeededForPromotionDescription,
|
||||
t,
|
||||
totalStake,
|
||||
]);
|
||||
|
||||
if (validatorsView === 'myStake') {
|
||||
@@ -226,21 +225,21 @@ export const StandbyPendingValidatorsTable = ({
|
||||
cellRenderer: StakeShareRenderer,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
field: ValidatorFields.STAKE_NEEDED_FOR_PROMOTION,
|
||||
headerName: t(ValidatorFields.STAKE_NEEDED_FOR_PROMOTION).toString(),
|
||||
headerTooltip: t(stakeNeededForPromotionDescription, {
|
||||
prefix: t('The'),
|
||||
}),
|
||||
cellRenderer: StakeNeededForPromotionRenderer,
|
||||
width: 210,
|
||||
},
|
||||
// {
|
||||
// field: ValidatorFields.STAKE_NEEDED_FOR_PROMOTION,
|
||||
// headerName: t(ValidatorFields.STAKE_NEEDED_FOR_PROMOTION).toString(),
|
||||
// headerTooltip: t(stakeNeededForPromotionDescription, {
|
||||
// prefix: t('The'),
|
||||
// }),
|
||||
// cellRenderer: StakeNeededForPromotionRenderer,
|
||||
// width: 210,
|
||||
// },
|
||||
{
|
||||
field: ValidatorFields.TOTAL_PENALTIES,
|
||||
headerName: t(ValidatorFields.TOTAL_PENALTIES).toString(),
|
||||
headerTooltip: t('TotalPenaltiesDescription').toString(),
|
||||
cellRenderer: TotalPenaltiesRenderer,
|
||||
width: 120,
|
||||
width: 120 + 210,
|
||||
},
|
||||
],
|
||||
[]
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
useEnvironment,
|
||||
DocsLinks,
|
||||
ExternalLinks,
|
||||
} from '@vegaprotocol/environment';
|
||||
import { toBigNum } from '@vegaprotocol/utils';
|
||||
import {
|
||||
formatNumberPercentage,
|
||||
removePaginationWrapper,
|
||||
toBigNum,
|
||||
} from '@vegaprotocol/utils';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import {
|
||||
Link as UTLink,
|
||||
@@ -24,11 +28,11 @@ import { SubHeading } from '../../../components/heading';
|
||||
import {
|
||||
getLastEpochScoreAndPerformance,
|
||||
getNormalisedVotingPower,
|
||||
getOverstakingPenalty,
|
||||
getPerformancePenalty,
|
||||
getTotalPenalties,
|
||||
getUnnormalisedVotingPower,
|
||||
getStakePercentage,
|
||||
calculatesPerformancePenalty,
|
||||
calculateOverstakedPenalty,
|
||||
calculateOverallPenalty,
|
||||
} from '../shared';
|
||||
import type { ReactNode } from 'react';
|
||||
import type { StakingNodeFieldsFragment } from '../__generated__/Staking';
|
||||
@@ -78,17 +82,27 @@ export const ValidatorTable = ({
|
||||
|
||||
const stakedOnNode = toBigNum(node.stakedTotal, decimals);
|
||||
|
||||
const { rawValidatorScore, performanceScore, stakeScore } =
|
||||
getLastEpochScoreAndPerformance(previousEpochData, node.id);
|
||||
const { rawValidatorScore } = getLastEpochScoreAndPerformance(
|
||||
previousEpochData,
|
||||
node.id
|
||||
);
|
||||
|
||||
const stakePercentage = getStakePercentage(total, stakedOnNode);
|
||||
|
||||
const totalPenaltiesAmount = getTotalPenalties(
|
||||
rawValidatorScore,
|
||||
performanceScore,
|
||||
stakedOnNode.toString(),
|
||||
total.toString()
|
||||
);
|
||||
const penalties = useMemo(() => {
|
||||
const allNodesInPreviousEpoch = removePaginationWrapper(
|
||||
previousEpochData?.epoch.validatorsConnection?.edges
|
||||
);
|
||||
return {
|
||||
// current epoch
|
||||
performance: calculatesPerformancePenalty(
|
||||
node.rankingScore.performanceScore
|
||||
),
|
||||
// previous epoch
|
||||
overstaked: calculateOverstakedPenalty(node.id, allNodesInPreviousEpoch),
|
||||
overall: calculateOverallPenalty(node.id, allNodesInPreviousEpoch),
|
||||
};
|
||||
}, [node, previousEpochData?.epoch.validatorsConnection?.edges]);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -242,7 +256,7 @@ export const ValidatorTable = ({
|
||||
|
||||
<Tooltip description={t('OverstakedPenaltyDescription')}>
|
||||
<span data-testid="overstaking-penalty">
|
||||
{getOverstakingPenalty(rawValidatorScore, stakeScore)}
|
||||
{formatNumberPercentage(penalties.overstaked, 2)}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</KeyValueTableRow>
|
||||
@@ -251,7 +265,7 @@ export const ValidatorTable = ({
|
||||
|
||||
<Tooltip description={t('PerformancePenaltyDescription')}>
|
||||
<span data-testid="performance-penalty">
|
||||
{getPerformancePenalty(performanceScore)}
|
||||
{formatNumberPercentage(penalties.performance, 2)}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</KeyValueTableRow>
|
||||
@@ -260,7 +274,7 @@ export const ValidatorTable = ({
|
||||
<strong>{t('TOTAL PENALTIES')}</strong>
|
||||
</span>
|
||||
<span data-testid="total-penalties">
|
||||
<strong>{totalPenaltiesAmount}</strong>
|
||||
<strong>{formatNumberPercentage(penalties.overall, 2)}</strong>
|
||||
</span>
|
||||
</KeyValueTableRow>
|
||||
</KeyValueTable>
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
getTotalPenalties,
|
||||
getStakePercentage,
|
||||
} from './shared';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
|
||||
describe('getLastEpochScoreAndPerformance', () => {
|
||||
const mockPreviousEpochData = {
|
||||
@@ -19,24 +20,48 @@ describe('getLastEpochScoreAndPerformance', () => {
|
||||
{
|
||||
node: {
|
||||
id: '0x123',
|
||||
stakedTotal: '',
|
||||
rewardScore: {
|
||||
rawValidatorScore: '0.25',
|
||||
performanceScore: '0.75',
|
||||
multisigScore: '',
|
||||
validatorScore: '',
|
||||
normalisedScore: '',
|
||||
validatorStatus:
|
||||
Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
},
|
||||
rankingScore: {
|
||||
stakeScore: '0.25',
|
||||
performanceScore: '0.75',
|
||||
status: Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
previousStatus:
|
||||
Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
rankingScore: '',
|
||||
votingPower: '',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
node: {
|
||||
id: '0x234',
|
||||
stakedTotal: '',
|
||||
rewardScore: {
|
||||
rawValidatorScore: '0.35',
|
||||
performanceScore: '0.85',
|
||||
multisigScore: '',
|
||||
validatorScore: '',
|
||||
normalisedScore: '',
|
||||
validatorStatus:
|
||||
Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
},
|
||||
rankingScore: {
|
||||
stakeScore: '0.25',
|
||||
performanceScore: '0.85',
|
||||
status: Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
previousStatus:
|
||||
Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
rankingScore: '',
|
||||
votingPower: '',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -4,6 +4,86 @@ import {
|
||||
} from '@vegaprotocol/utils';
|
||||
import type { PreviousEpochQuery } from './__generated__/PreviousEpoch';
|
||||
import { BigNumber } from '../../lib/bignumber';
|
||||
import type { LastArrayElement } from 'type-fest';
|
||||
|
||||
type Node = NonNullable<
|
||||
LastArrayElement<
|
||||
NonNullable<
|
||||
NonNullable<PreviousEpochQuery['epoch']['validatorsConnection']>['edges']
|
||||
>
|
||||
>
|
||||
>['node'];
|
||||
|
||||
/**
|
||||
* Calculates theoretical stake score for a given node
|
||||
* @param nodeId Id of a node for which a score is calculated
|
||||
* @param nodes A collection of all nodes
|
||||
* @returns Theoretical stake score for given node based on the staked total
|
||||
* of all node of the same type (status)
|
||||
*/
|
||||
const calculateTheoreticalStakeScore = (nodeId: string, nodes: Node[]) => {
|
||||
const node = nodes.find((n) => n.id === nodeId);
|
||||
if (!node) {
|
||||
return new BigNumber(0);
|
||||
}
|
||||
const all = nodes
|
||||
.filter((n) => n.rankingScore.status === node.rankingScore.status)
|
||||
.map((n) => new BigNumber(n.stakedTotal));
|
||||
const sumOfSameType = all.reduce((acc, a) => acc.plus(a), new BigNumber(0));
|
||||
if (sumOfSameType.isZero()) {
|
||||
return new BigNumber(0);
|
||||
}
|
||||
return new BigNumber(node.stakedTotal).dividedBy(sumOfSameType);
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates overall penalty for a given node
|
||||
* @param nodeId Id of a node for which a penalty is calculated
|
||||
* @param nodes A collection of all nodes - needed to calculate theoretical stake score
|
||||
* @returns %
|
||||
*/
|
||||
export const calculateOverallPenalty = (nodeId: string, nodes: Node[]) => {
|
||||
const node = nodes.find((n) => n.id === nodeId);
|
||||
const tts = calculateTheoreticalStakeScore(nodeId, nodes);
|
||||
if (!node || tts.isZero()) {
|
||||
return new BigNumber(0);
|
||||
}
|
||||
const penalty = new BigNumber(1)
|
||||
.minus(new BigNumber(node.rewardScore?.validatorScore || 0).dividedBy(tts))
|
||||
.times(100);
|
||||
return penalty.isLessThan(0) ? new BigNumber(0) : penalty;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates over-staked penalty for a given node
|
||||
* @param nodeId Id of a node for which a penalty is calculated
|
||||
* @param nodes A collection of all nodes - needed to calculate theoretical stake score
|
||||
* @returns %
|
||||
*/
|
||||
export const calculateOverstakedPenalty = (nodeId: string, nodes: Node[]) => {
|
||||
const node = nodes.find((n) => n.id === nodeId);
|
||||
const tts = calculateTheoreticalStakeScore(nodeId, nodes);
|
||||
if (!node || tts.isZero()) {
|
||||
return new BigNumber(0);
|
||||
}
|
||||
const penalty = new BigNumber(1)
|
||||
.minus(
|
||||
new BigNumber(node.rewardScore?.rawValidatorScore || 0).dividedBy(tts)
|
||||
)
|
||||
.times(100);
|
||||
return penalty.isLessThan(0) ? new BigNumber(0) : penalty;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates performance penalty based on the given performance score.
|
||||
* @returns %
|
||||
*/
|
||||
export const calculatesPerformancePenalty = (performanceScore: string) => {
|
||||
const penalty = new BigNumber(1)
|
||||
.minus(new BigNumber(performanceScore))
|
||||
.times(100);
|
||||
return penalty.isLessThan(0) ? new BigNumber(0) : penalty;
|
||||
};
|
||||
|
||||
export const getLastEpochScoreAndPerformance = (
|
||||
previousEpochData: PreviousEpochQuery | undefined,
|
||||
@@ -15,7 +95,7 @@ export const getLastEpochScoreAndPerformance = (
|
||||
|
||||
return {
|
||||
rawValidatorScore: validator?.rewardScore?.rawValidatorScore,
|
||||
performanceScore: validator?.rewardScore?.performanceScore,
|
||||
performanceScore: validator?.rankingScore?.performanceScore,
|
||||
stakeScore: validator?.rankingScore?.stakeScore,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -23,5 +23,6 @@ NX_VEGA_URL="https://api.n07.testnet.vega.xyz/graphql"
|
||||
NX_VEGA_WALLET_URL=http://localhost:1789
|
||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\"}
|
||||
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://trading.stagnet1.vega.rocks\"}
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
||||
NX_VEGA_CONSOLE_URL=https://console.fairground.wtf
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
|
||||
NX_VEGA_URL=https://api.n04.d.vega.xyz/graphql
|
||||
NX_VEGA_ENV=DEVNET
|
||||
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\"}
|
||||
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://trading.stagnet1.vega.rocks\"}
|
||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/mainnet1/mainnet1.toml
|
||||
NX_VEGA_URL=https://api.vega.community/graphql
|
||||
NX_VEGA_ENV=MAINNET
|
||||
NX_VEGA_NETWORKS={\"MAINNET\":\"https://alpha.console.vega.xyz\",\"TESTNET\":\"https://console.fairground.wtf\"}
|
||||
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\"}
|
||||
NX_ETHEREUM_PROVIDER_URL=https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://etherscan.io
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz
|
||||
NX_VEGA_CONSOLE_URL=https://vega.trading
|
||||
|
||||
@@ -4,5 +4,6 @@ NX_VEGA_URL=https://api.n00.stagnet1.vega.xyz/graphql
|
||||
NX_VEGA_ENV=STAGNET1
|
||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
|
||||
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\"}
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.stagnet1.vega.rocks
|
||||
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://trading.stagnet1.vega.rocks\"}
|
||||
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/fairground/vegawallet-fairground.toml
|
||||
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
|
||||
NX_VEGA_ENV=TESTNET
|
||||
NX_VEGA_NETWORKS={\"MAINNET\":\"https://alpha.console.vega.xyz\",\"TESTNET\":\"https://console.fairground.wtf\"}
|
||||
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\"}
|
||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
||||
NX_VEGA_CONSOLE_URL=https://console.fairground.wtf
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
# App configuration variables
|
||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/testnet2/testnet2.tom
|
||||
NX_VEGA_URL=https://api-validators-testnet.vega.rocks/graphql
|
||||
NX_VEGA_NETWORKS='{"TESTNET":"https://multisig-signer.fairground.wtf","MAINNET":"https://multisig-signer.vega.xyz"}'
|
||||
NX_VEGA_NETWORKS={'{"TESTNET":"https://multisig-signer.fairground.wtf","MAINNET":"https://multisig-signer.vega.xyz"}'
|
||||
NX_VEGA_ENV=VALIDATOR_TESTNET
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,8 @@ NX_VEGA_CONFIG_URL=''
|
||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||
NX_VEGA_ENV=CUSTOM
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
||||
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\"}
|
||||
NX_VEGA_CONSOLE_URL=https://console.fairground.wtf
|
||||
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://trading.stagnet1.vega.rocks\"}
|
||||
NX_VEGA_TOKEN_URL=https://governance.fairground.wtf
|
||||
NX_VEGA_URL=http://localhost:3008/graphql
|
||||
NX_VEGA_WALLET_URL=http://localhost:1789
|
||||
@@ -19,6 +20,7 @@ CYPRESS_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit
|
||||
CYPRESS_ETHEREUM_WALLET_ADDRESS=0xEe7D375bcB50C26d52E1A4a472D8822A2A22d94F
|
||||
CYPRESS_ETHEREUM_PROVIDER_URL=http://localhost:8545
|
||||
CYPRESS_EXPLORER_URL=https://explorer.fairground.wtf
|
||||
CYPRESS_CONSOLE_URL=https://console.fairground.wtf
|
||||
CYPRESS_FAUCET_URL=http://localhost:1790/api/v1/mint
|
||||
CYPRESS_ORACLE_PUBKEY=6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61
|
||||
CYPRESS_TRUNCATED_VEGA_PUBLIC_KEY=02ecea…342f65
|
||||
|
||||
@@ -5,7 +5,8 @@ NX_VEGA_CONFIG_URL=''
|
||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||
NX_VEGA_ENV=CUSTOM
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
||||
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\"}
|
||||
NX_VEGA_CONSOLE_URL=https://console.fairground.wtf
|
||||
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://trading.stagnet1.vega.rocks\"}
|
||||
NX_VEGA_TOKEN_URL=https://governance.fairground.wtf
|
||||
NX_VEGA_URL=http://localhost:3008/graphql
|
||||
NX_VEGA_WALLET_URL=http://localhost:1789
|
||||
@@ -17,6 +18,7 @@ CYPRESS_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit
|
||||
CYPRESS_ETHEREUM_WALLET_ADDRESS=0xEe7D375bcB50C26d52E1A4a472D8822A2A22d94F
|
||||
CYPRESS_ETHEREUM_PROVIDER_URL=http://localhost:8545
|
||||
CYPRESS_EXPLORER_URL=https://explorer.fairground.wtf
|
||||
CYPRESS_CONSOLE_URL=https://console.fairground.wtf
|
||||
CYPRESS_FAUCET_URL=http://localhost:1790/api/v1/mint
|
||||
CYPRESS_TRUNCATED_VEGA_PUBLIC_KEY=02ecea…342f65
|
||||
CYPRESS_TRUNCATED_VEGA_PUBLIC_KEY2=7f9cf0…c25535
|
||||
|
||||
@@ -24,7 +24,7 @@ module.exports = defineConfig({
|
||||
viewportHeight: 900,
|
||||
responseTimeout: 50000,
|
||||
requestTimeout: 20000,
|
||||
retries: 2,
|
||||
retries: 1,
|
||||
testIsolation: false,
|
||||
},
|
||||
env: {
|
||||
|
||||
@@ -50,10 +50,7 @@ describe('capsule - without MultiSign', { tags: '@slow' }, () => {
|
||||
cy.wrap(markets[0]).as('market');
|
||||
});
|
||||
cy.visit('/#/portfolio');
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.setVegaWallet();
|
||||
cy.connectVegaWallet();
|
||||
});
|
||||
|
||||
it('can deposit', function () {
|
||||
@@ -172,7 +169,6 @@ describe('capsule - without MultiSign', { tags: '@slow' }, () => {
|
||||
'contain.text',
|
||||
'Error occurredcannot estimate gas'
|
||||
);
|
||||
cy.getByTestId(toastCloseBtn).click({ multiple: true });
|
||||
cy.getByTestId(completeWithdrawalBtn).should(
|
||||
'contain.text',
|
||||
'Complete withdrawal'
|
||||
@@ -194,6 +190,7 @@ describe('capsule', { tags: '@slow', testIsolation: true }, () => {
|
||||
});
|
||||
|
||||
it('shows node health', function () {
|
||||
// 0006-NETW-010
|
||||
const market = this.market;
|
||||
cy.visit(`/#/markets/${market.id}`);
|
||||
cy.getByTestId('node-health')
|
||||
@@ -375,10 +372,14 @@ describe('capsule', { tags: '@slow', testIsolation: true }, () => {
|
||||
'contain.text',
|
||||
'Transaction confirmed'
|
||||
);
|
||||
cy.getByTestId(toastContent, txTimeout).should(
|
||||
'contain.text',
|
||||
'Funds unlockedYour funds have been unlocked for withdrawalView in block explorerWithdraw 1.00 tBTCComplete withdrawal'
|
||||
);
|
||||
cy.getByTestId(toastContent, txTimeout)
|
||||
.should('contain.text', 'Funds unlocked')
|
||||
.and('contain.text', 'Your funds have been unlocked for withdrawal.')
|
||||
.and(
|
||||
'contain.text',
|
||||
'View in block explorerYou can save your withdrawal details for extra security.'
|
||||
)
|
||||
.and('contain.text', 'Withdraw 1.00 tBTCComplete withdrawal');
|
||||
|
||||
cy.get('.ag-center-cols-container')
|
||||
.find('[col-id="status"]')
|
||||
@@ -406,7 +407,7 @@ describe('capsule', { tags: '@slow', testIsolation: true }, () => {
|
||||
});
|
||||
|
||||
cy.getByTestId('withdraw-dialog-button').click({ force: true });
|
||||
cy.getByTestId('BALANCE_AVAILABLE_value').should('have.text', '7.999');
|
||||
// cy.getByTestId('BALANCE_AVAILABLE_value').should('have.text', '6.999');
|
||||
});
|
||||
|
||||
it('approved amount is less than deposit', function () {
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import { aliasGQLQuery } from '@vegaprotocol/cypress';
|
||||
import { MarketState, MarketStateMapping } from '@vegaprotocol/types';
|
||||
import type { DataSourceDefinition } from '@vegaprotocol/types';
|
||||
import {
|
||||
MarketState,
|
||||
MarketStateMapping,
|
||||
PropertyKeyType,
|
||||
} from '@vegaprotocol/types';
|
||||
import { addDays, subDays } from 'date-fns';
|
||||
import {
|
||||
chainIdQuery,
|
||||
@@ -20,6 +25,25 @@ import {
|
||||
} from '@vegaprotocol/utils';
|
||||
|
||||
describe('Closed markets', { tags: '@smoke' }, () => {
|
||||
const settlementDataProperty = 'settlement-data-property';
|
||||
const settlementDataPropertyKey = {
|
||||
__typename: 'PropertyKey' as const,
|
||||
name: settlementDataProperty,
|
||||
type: PropertyKeyType.TYPE_INTEGER,
|
||||
numberDecimalPlaces: 2,
|
||||
};
|
||||
const settlementDataSourceData: DataSourceDefinition = {
|
||||
sourceType: {
|
||||
sourceType: {
|
||||
filters: [
|
||||
{
|
||||
__typename: 'Filter',
|
||||
key: settlementDataPropertyKey,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
const rowSelector =
|
||||
'[data-testid="tab-closed-markets"] .ag-center-cols-container .ag-row';
|
||||
|
||||
@@ -37,11 +61,15 @@ describe('Closed markets', { tags: '@smoke' }, () => {
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
product: {
|
||||
dataSourceSpecBinding: {
|
||||
settlementDataProperty,
|
||||
},
|
||||
dataSourceSpecForTradingTermination: {
|
||||
id: 'market-1-trading-termination-oracle-id',
|
||||
},
|
||||
dataSourceSpecForSettlementData: {
|
||||
id: 'market-1-settlement-data-oracle-id',
|
||||
data: settlementDataSourceData,
|
||||
},
|
||||
settlementAsset,
|
||||
},
|
||||
@@ -63,6 +91,15 @@ describe('Closed markets', { tags: '@smoke' }, () => {
|
||||
`settlement-expiry-date:${addDays(new Date(), 4).toISOString()}`,
|
||||
],
|
||||
},
|
||||
product: {
|
||||
dataSourceSpecBinding: {
|
||||
settlementDataProperty,
|
||||
},
|
||||
dataSourceSpecForSettlementData: {
|
||||
id: 'market-1-settlement-data-oracle-id',
|
||||
data: settlementDataSourceData,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -81,6 +118,15 @@ describe('Closed markets', { tags: '@smoke' }, () => {
|
||||
`settlement-expiry-date:${subDays(new Date(), 2).toISOString()}`,
|
||||
],
|
||||
},
|
||||
product: {
|
||||
dataSourceSpecBinding: {
|
||||
settlementDataProperty,
|
||||
},
|
||||
dataSourceSpecForSettlementData: {
|
||||
id: 'market-1-settlement-data-oracle-id',
|
||||
data: settlementDataSourceData,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -301,7 +347,7 @@ describe('Closed markets', { tags: '@smoke' }, () => {
|
||||
addDecimalsFormatNumber(
|
||||
// @ts-ignore cannot deep un-partial
|
||||
specDataConnection.externalData.data.data[0].value,
|
||||
settledMarket.decimalPlaces
|
||||
settlementDataPropertyKey.numberDecimalPlaces
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
const dialogContent = 'dialog-content';
|
||||
const nodeHealth = 'node-health';
|
||||
|
||||
describe.skip('home', { tags: '@regression' }, () => {
|
||||
before(() => {
|
||||
cy.clearAllLocalStorage();
|
||||
cy.mockTradingPage();
|
||||
cy.mockSubscription();
|
||||
cy.visit('/');
|
||||
});
|
||||
|
||||
describe('footer', () => {
|
||||
it('shows current block height', () => {
|
||||
// 0006-NETW-004
|
||||
// 0006-NETW-005
|
||||
// 0006-NETW-008
|
||||
// 0006-NETW-009
|
||||
// 0006-NETW-011
|
||||
|
||||
cy.intercept('POST', 'http://localhost:3008/graphql', (req) => {
|
||||
req.on('response', (res) => {
|
||||
res.setDelay(3001);
|
||||
});
|
||||
});
|
||||
|
||||
cy.getByTestId(nodeHealth)
|
||||
.children()
|
||||
.first()
|
||||
.should('contain.text', 'Warning delay ( >3 sec)');
|
||||
|
||||
cy.intercept('POST', 'http://localhost:3008/graphql', (req) => {
|
||||
req.on('response', (res) => {
|
||||
res.setDelay(1);
|
||||
});
|
||||
});
|
||||
|
||||
cy.getByTestId(nodeHealth)
|
||||
.children()
|
||||
.first()
|
||||
.should('contain.text', 'Operational', { timeout: 10000 })
|
||||
.next()
|
||||
.should('contain.text', new URL(Cypress.env('VEGA_URL')).origin)
|
||||
.next()
|
||||
.should('contain.text', '100'); // all mocked queries have x-block-height header set to 100
|
||||
});
|
||||
|
||||
it('shows node switcher details', () => {
|
||||
// 0006-NETW-012
|
||||
// 0006-NETW-013
|
||||
// 0006-NETW-014
|
||||
// 0006-NETW-015
|
||||
// 0006-NETW-016
|
||||
cy.getByTestId(nodeHealth).click();
|
||||
cy.getByTestId(dialogContent).should('contain.text', 'Connected node');
|
||||
cy.getByTestId(dialogContent).should(
|
||||
'contain.text',
|
||||
'This app will only work on CUSTOM. Select a node to connect to.'
|
||||
);
|
||||
cy.getByTestId('node')
|
||||
.first()
|
||||
.should('contain.text', new URL(Cypress.env('VEGA_URL')).origin)
|
||||
.next()
|
||||
.should('contain.text', 'Response time')
|
||||
.next()
|
||||
.should('contain.text', 'Block')
|
||||
.next()
|
||||
.should('contain.text', 'Subscription');
|
||||
cy.getByTestId('custom-row').should('contain.text', 'Other');
|
||||
cy.getByTestId('dialog-close').click();
|
||||
});
|
||||
|
||||
it('switch to other node', () => {
|
||||
// 0006-NETW-017
|
||||
// 0006-NETW-018
|
||||
// 0006-NETW-019
|
||||
// 0006-NETW-020
|
||||
cy.getByTestId(nodeHealth).click();
|
||||
cy.getByTestId('connect').should('be.disabled');
|
||||
cy.getByTestId('node-url-custom').click();
|
||||
cy.getByTestId('connect').should('be.disabled');
|
||||
cy.get("input[placeholder='https://']")
|
||||
.focus()
|
||||
.type(new URL(Cypress.env('VEGA_URL')).origin + '/graphql');
|
||||
cy.getByTestId('connect').click();
|
||||
cy.getByTestId(nodeHealth)
|
||||
.children()
|
||||
.first()
|
||||
.should('contain.text', 'Operational');
|
||||
});
|
||||
});
|
||||
describe('Network switcher', () => {
|
||||
before(() => {
|
||||
cy.mockTradingPage();
|
||||
cy.mockSubscription();
|
||||
cy.visit('/');
|
||||
});
|
||||
|
||||
// 0006-NETW-002
|
||||
// 0006-NETW-003
|
||||
it('switch to fairground network', () => {
|
||||
cy.getByTestId('network-switcher').click();
|
||||
cy.getByTestId('network-item').contains('Fairground testnet').click();
|
||||
cy.get('[aria-haspopup="menu"]').should('contain.text', 'Fairground');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,9 +1,8 @@
|
||||
import { aliasGQLQuery } from '@vegaprotocol/cypress';
|
||||
import type { ProposalListFieldsFragment } from '@vegaprotocol/proposals';
|
||||
import { marketsDataQuery } from '@vegaprotocol/mock';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
|
||||
const selectMarketOverlay = 'select-market-list';
|
||||
const dialogContent = 'dialog-content';
|
||||
|
||||
const generateProposal = (code: string): ProposalListFieldsFragment => ({
|
||||
__typename: 'Proposal',
|
||||
@@ -81,20 +80,12 @@ const generateProposal = (code: string): ProposalListFieldsFragment => ({
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
dataSourceSpecForTradingTermination: {
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -117,77 +108,12 @@ describe('home', { tags: '@regression' }, () => {
|
||||
|
||||
cy.get('main[data-testid^="/markets/"]');
|
||||
|
||||
// Overlay should be shown
|
||||
cy.getByTestId(selectMarketOverlay).should('exist');
|
||||
cy.contains('Select a market to get started').should('be.visible');
|
||||
|
||||
// I expect the market overlay table to contain at least 3 rows (one header row)
|
||||
cy.getByTestId(selectMarketOverlay)
|
||||
.get('table tr')
|
||||
.then((row) => {
|
||||
expect(row.length >= 3).to.be.true;
|
||||
});
|
||||
|
||||
// each market shown in overlay table contains content under the last price and change fields
|
||||
cy.getByTestId(selectMarketOverlay)
|
||||
.get('table tr')
|
||||
.each(($element, index) => {
|
||||
if (index > 0) {
|
||||
// skip header row
|
||||
cy.root().within(() => {
|
||||
cy.getByTestId('price').should('not.be.empty');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
cy.getByTestId('welcome-notice-proposed-markets')
|
||||
.children('div.pt-1.flex.justify-between')
|
||||
.should('have.length', 3)
|
||||
.each((item) => {
|
||||
cy.wrap(item).getByTestId('external-link').should('exist');
|
||||
});
|
||||
|
||||
cy.getByTestId('dialog-close').click();
|
||||
cy.getByTestId(selectMarketOverlay).should('not.exist');
|
||||
|
||||
// the choose market overlay is no longer showing
|
||||
cy.contains('Select a market to get started').should('not.exist');
|
||||
cy.contains('Loading...').should('not.exist');
|
||||
cy.url().should('eq', Cypress.config().baseUrl + '/#/markets/market-0');
|
||||
});
|
||||
});
|
||||
|
||||
describe('market table should be properly rendered', () => {
|
||||
it('redirects to a default market with the landing dialog open', () => {
|
||||
const override = {
|
||||
marketsConnection: {
|
||||
edges: [
|
||||
{
|
||||
node: {
|
||||
data: {
|
||||
markPrice: '46126900581221212121212121212121212121212121212',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
// @ts-ignore partial deep check failing
|
||||
const data = marketsDataQuery(override);
|
||||
cy.mockGQL((req) => {
|
||||
aliasGQLQuery(req, 'MarketsData', data);
|
||||
});
|
||||
cy.visit('/');
|
||||
cy.wait('@Markets');
|
||||
cy.getByTestId(selectMarketOverlay)
|
||||
.get('table')
|
||||
.invoke('outerWidth')
|
||||
.then((value) => {
|
||||
expect(value).to.be.closeTo(554, 10);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('no markets found', () => {
|
||||
beforeEach(() => {
|
||||
cy.mockGQL((req) => {
|
||||
@@ -213,40 +139,13 @@ describe('home', { tags: '@regression' }, () => {
|
||||
cy.wait('@Markets');
|
||||
cy.wait('@MarketsData');
|
||||
});
|
||||
it('redirects to a the empty market page and displays welcome notice', () => {
|
||||
cy.url().should('eq', Cypress.config().baseUrl + `/#/markets`);
|
||||
|
||||
it('redirects to market/all and displays welcome notice', () => {
|
||||
cy.url().should('eq', Cypress.config().baseUrl + `/#/markets/all`);
|
||||
cy.getByTestId('welcome-notice-title').should(
|
||||
'contain.text',
|
||||
'Welcome to Console'
|
||||
);
|
||||
cy.getByTestId('welcome-notice-proposed-markets').should(
|
||||
'contain.text',
|
||||
'AAAZZZ'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('no proposal found', () => {
|
||||
it('there is a link to propose market', () => {
|
||||
cy.mockGQL((req) => {
|
||||
aliasGQLQuery(req, 'ProposalsList', {
|
||||
proposalsConnection: {
|
||||
__typename: 'ProposalsConnection',
|
||||
edges: null,
|
||||
},
|
||||
});
|
||||
});
|
||||
cy.visit('/');
|
||||
cy.wait('@Markets');
|
||||
cy.wait('@MarketsData');
|
||||
cy.getByTestId(selectMarketOverlay)
|
||||
.get('table tr')
|
||||
.then((row) => {
|
||||
expect(row.length >= 3).to.be.true;
|
||||
});
|
||||
cy.getByTestId('external-link')
|
||||
.contains('Propose a market')
|
||||
.should('exist');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -288,7 +187,7 @@ describe('home', { tags: '@regression' }, () => {
|
||||
cy.visit('/');
|
||||
cy.wait('@Markets');
|
||||
cy.location('hash').should('equal', '#/markets/market-1');
|
||||
cy.getByTestId('dialog-content').should('not.exist');
|
||||
cy.getByTestId(dialogContent).should('not.exist');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -301,22 +200,8 @@ describe('home', { tags: '@regression' }, () => {
|
||||
cy.visit('/');
|
||||
cy.wait('@Markets');
|
||||
cy.location('hash').should('equal', '#/markets/market-not-existing');
|
||||
cy.getByTestId('dialog-content').should('not.exist');
|
||||
cy.getByTestId(dialogContent).should('not.exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('footer', () => {
|
||||
it('shows current block height', () => {
|
||||
cy.visit('/');
|
||||
cy.getByTestId('node-health')
|
||||
.children()
|
||||
.first()
|
||||
.should('contain.text', 'Operational')
|
||||
.next()
|
||||
.should('contain.text', new URL(Cypress.env('VEGA_URL')).origin)
|
||||
.next()
|
||||
.should('contain.text', '100'); // all mocked queries have x-block-height header set to 100
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
const selectMarketOverlay = 'select-market-list';
|
||||
const marketInfoBtn = 'Info';
|
||||
const marketInfoSubtitle = 'accordion-title';
|
||||
const marketSummaryBlock = 'header-summary';
|
||||
@@ -14,45 +13,6 @@ const itemHeader = 'item-header';
|
||||
const itemValue = 'item-value';
|
||||
const marketListContent = 'popover-content';
|
||||
|
||||
describe(
|
||||
'Console - market list - live env',
|
||||
{ tags: '@live', testIsolation: true },
|
||||
() => {
|
||||
beforeEach(() => {
|
||||
cy.visit('/');
|
||||
});
|
||||
|
||||
it('shows the market list page', () => {
|
||||
cy.get('main', { timeout: 20000 });
|
||||
|
||||
// Overlay should be shown
|
||||
cy.getByTestId(selectMarketOverlay).should('exist');
|
||||
cy.contains('Select a market to get started').should('be.visible');
|
||||
|
||||
// I expect the market overlay table to contain at least one row
|
||||
cy.getByTestId(selectMarketOverlay)
|
||||
.get('table tr')
|
||||
.should('have.length.greaterThan', 1);
|
||||
|
||||
// each market shown in overlay table contains content under the last price and change fields
|
||||
cy.getByTestId(selectMarketOverlay)
|
||||
.get('table tr')
|
||||
.getByTestId('price')
|
||||
.should('not.be.empty');
|
||||
});
|
||||
|
||||
it('redirects to a default market', () => {
|
||||
cy.getByTestId('dialog-close').click();
|
||||
cy.getByTestId(selectMarketOverlay).should('not.exist');
|
||||
|
||||
// the choose market overlay is no longer showing
|
||||
cy.contains('Select a market to get started').should('not.exist');
|
||||
cy.contains('Loading...').should('not.exist');
|
||||
cy.getByTestId('popover-trigger').should('not.be.empty');
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
describe(
|
||||
'Console - market info - live env',
|
||||
{ tags: '@live', testIsolation: true },
|
||||
|
||||
@@ -38,28 +38,28 @@ describe('markets selector', { tags: '@smoke' }, () => {
|
||||
// TODO: load data from mocks in. Using alias and wrap intermittently fails
|
||||
const data = [
|
||||
{
|
||||
code: 'AAPL.MF21',
|
||||
name: 'Apple Monthly (30 Jun 2022)',
|
||||
markPrice: '46,126.90058',
|
||||
change: '+200.00%',
|
||||
},
|
||||
{
|
||||
code: 'BTCUSD.MF21',
|
||||
name: 'ACTIVE MARKET',
|
||||
markPrice: '46,126.90058',
|
||||
code: 'SOLUSD',
|
||||
markPrice: '84.41XYZalpha',
|
||||
change: '+200.00%',
|
||||
vol: '324h vol',
|
||||
},
|
||||
{
|
||||
code: 'ETHBTC.QM21',
|
||||
name: 'ETHBTC Quarterly (30 Jun 2022)',
|
||||
markPrice: '46,126.90058',
|
||||
markPrice: '46,126.90058tBTC',
|
||||
change: '+200.00%',
|
||||
vol: '324h vol',
|
||||
},
|
||||
{
|
||||
code: 'SOLUSD',
|
||||
name: 'SUSPENDED MARKET',
|
||||
markPrice: '84.41',
|
||||
code: 'BTCUSD.MF21',
|
||||
markPrice: '46,126.90058tDAI',
|
||||
change: '+200.00%',
|
||||
vol: '324h vol',
|
||||
},
|
||||
{
|
||||
code: 'AAPL.MF21',
|
||||
markPrice: '46,126.90058tUSDC',
|
||||
change: '+200.00%',
|
||||
vol: '324h vol',
|
||||
},
|
||||
];
|
||||
cy.getByTestId(list)
|
||||
@@ -68,12 +68,13 @@ describe('markets selector', { tags: '@smoke' }, () => {
|
||||
const market = data[i];
|
||||
// 6001-MARK-021
|
||||
expect(item.find('h3').text()).equals(market.code);
|
||||
// 6001-MARK-022
|
||||
expect(item.find('h4').text()).equals(market.name);
|
||||
expect(
|
||||
item.find('[data-testid="market-selector-data-row"]').eq(0).text()
|
||||
).contains(market.vol);
|
||||
// 6001-MARK-024
|
||||
expect(item.find('[data-testid="market-item-price"]').text()).equals(
|
||||
market.markPrice
|
||||
);
|
||||
expect(
|
||||
item.find('[data-testid="market-selector-data-row"]').eq(1).text()
|
||||
).contains(market.markPrice);
|
||||
// 6001-MARK-023
|
||||
expect(item.find('[data-testid="market-item-change"]').text()).equals(
|
||||
market.change
|
||||
@@ -96,8 +97,8 @@ describe('markets selector', { tags: '@smoke' }, () => {
|
||||
// 6001-MARK-29
|
||||
cy.getByTestId(searchInput).clear().type('btc');
|
||||
cy.getByTestId(list).find('a').should('have.length', 2);
|
||||
cy.getByTestId(list).find('a').eq(0).contains('BTCUSD.MF21');
|
||||
cy.getByTestId(list).find('a').eq(1).contains('ETHBTC.QM21');
|
||||
cy.getByTestId(list).find('a').eq(1).contains('BTCUSD.MF21');
|
||||
cy.getByTestId(list).find('a').eq(0).contains('ETHBTC.QM21');
|
||||
|
||||
cy.getByTestId(searchInput).clear();
|
||||
cy.getByTestId(list).find('a').should('have.length', 4);
|
||||
|
||||
@@ -3,8 +3,6 @@ import { aliasGQLQuery, checkSorting } from '@vegaprotocol/cypress';
|
||||
import { marketsQuery } from '@vegaprotocol/mock';
|
||||
import { getDateTimeFormat } from '@vegaprotocol/utils';
|
||||
|
||||
const dialogCloseBtn = 'dialog-close';
|
||||
|
||||
describe('markets table', { tags: '@smoke' }, () => {
|
||||
beforeEach(() => {
|
||||
cy.clearLocalStorage().then(() => {
|
||||
@@ -14,20 +12,18 @@ describe('markets table', { tags: '@smoke' }, () => {
|
||||
Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY_TARGET_NOT_MET
|
||||
);
|
||||
cy.mockSubscription();
|
||||
cy.visit('/');
|
||||
cy.wait('@Markets');
|
||||
cy.wait('@MarketsData');
|
||||
cy.wait('@MarketsCandles');
|
||||
cy.visit('/#/markets/all');
|
||||
});
|
||||
});
|
||||
|
||||
it('renders markets correctly', () => {
|
||||
cy.wait('@Markets');
|
||||
cy.wait('@MarketsData');
|
||||
cy.get('[data-testid^="market-link-"]').should('not.be.empty');
|
||||
cy.getByTestId('price').invoke('text').should('not.be.empty');
|
||||
cy.getByTestId('settlement-asset').should('not.be.empty');
|
||||
cy.getByTestId('price-change-percentage').should('not.be.empty');
|
||||
cy.getByTestId('price-change').should('not.be.empty');
|
||||
cy.getByTestId('sparkline-svg').should('be.visible');
|
||||
});
|
||||
|
||||
it('able to open and sort full market list - market page', () => {
|
||||
@@ -37,9 +33,6 @@ describe('markets table', { tags: '@smoke' }, () => {
|
||||
'ETHBTC.QM21',
|
||||
'SOLUSD',
|
||||
];
|
||||
cy.getByTestId('view-market-list-link')
|
||||
.should('have.attr', 'href', '#/markets/all')
|
||||
.click();
|
||||
cy.url().should('eq', Cypress.config('baseUrl') + '/#/markets/all');
|
||||
cy.contains('AAPL.MF21').should('be.visible');
|
||||
cy.get('.ag-header-cell-label').contains('Market').click(); // sort by market name
|
||||
@@ -51,10 +44,6 @@ describe('markets table', { tags: '@smoke' }, () => {
|
||||
});
|
||||
|
||||
it('proposed markets tab should be rendered properly', () => {
|
||||
cy.getByTestId('view-market-list-link')
|
||||
.should('have.attr', 'href', '#/markets/all')
|
||||
.click();
|
||||
|
||||
cy.get('[data-testid="All markets"]').should(
|
||||
'have.attr',
|
||||
'data-state',
|
||||
@@ -87,8 +76,8 @@ describe('markets table', { tags: '@smoke' }, () => {
|
||||
`${Cypress.env('VEGA_TOKEN_URL')}/proposals/propose/new-market`
|
||||
);
|
||||
});
|
||||
|
||||
it('proposed markets tab should be sorted properly', () => {
|
||||
cy.getByTestId('view-market-list-link').click();
|
||||
cy.get('[data-testid="Proposed markets"]').click();
|
||||
const marketColDefault = [
|
||||
'ETHUSD',
|
||||
@@ -167,7 +156,7 @@ describe('markets table', { tags: '@smoke' }, () => {
|
||||
checkSorting('state', stateColDefault, stateColAsc, stateColDesc);
|
||||
});
|
||||
|
||||
it('opening auction subsets should be properly displayed', () => {
|
||||
it.skip('opening auction subsets should be properly displayed', () => {
|
||||
cy.mockTradingPage(
|
||||
Schema.MarketState.STATE_ACTIVE,
|
||||
Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION
|
||||
@@ -200,7 +189,6 @@ describe('markets table', { tags: '@smoke' }, () => {
|
||||
});
|
||||
cy.visit('#/markets/market-0');
|
||||
cy.url().should('contain', 'market-0');
|
||||
cy.getByTestId(dialogCloseBtn).click();
|
||||
cy.getByTestId('item-value').contains('Opening auction').realHover();
|
||||
cy.getByTestId('opening-auction-sub-status').should(
|
||||
'contain.text',
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
import { mockConnectWallet } from '@vegaprotocol/cypress';
|
||||
|
||||
describe('Navbar', { tags: '@smoke' }, () => {
|
||||
before(() => {
|
||||
beforeEach(() => {
|
||||
cy.clearAllLocalStorage();
|
||||
cy.mockTradingPage();
|
||||
cy.mockSubscription();
|
||||
cy.visit('/');
|
||||
cy.wait('@Markets');
|
||||
cy.wait('@MarketsData');
|
||||
cy.wait('@MarketsCandles');
|
||||
// close welcome dialog
|
||||
cy.getByTestId('dialog-close').click();
|
||||
});
|
||||
|
||||
const pages = [
|
||||
@@ -47,6 +44,18 @@ describe('Navbar', { tags: '@smoke' }, () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Disclaimer should be presented after choosing from menu', () => {
|
||||
cy.get('nav')
|
||||
.find('ul li:contains(Resources)')
|
||||
.contains('Resources')
|
||||
.click();
|
||||
cy.getByTestId('Disclaimer').eq(0).click();
|
||||
cy.location('hash').should('equal', '#/disclaimer');
|
||||
cy.get('p').contains(
|
||||
'Vega is a decentralised peer-to-peer protocol that can be used to trade derivatives with cryptoassets.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('mobile view', () => {
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import { closeWelcomeDialog } from '../support/helpers';
|
||||
|
||||
describe('Settings page', { tags: '@smoke' }, () => {
|
||||
beforeEach(() => {
|
||||
cy.clearLocalStorage().then(() => {
|
||||
cy.mockTradingPage();
|
||||
cy.mockSubscription();
|
||||
cy.visit('/');
|
||||
closeWelcomeDialog();
|
||||
cy.get('[aria-label="cog icon"]').click();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -482,7 +482,7 @@ describe('amend and cancel order', { tags: '@smoke' }, () => {
|
||||
testOrderCancellation(order);
|
||||
});
|
||||
});
|
||||
it('must be able to cancel all orders on a market', () => {
|
||||
it('must be able to cancel all orders on all markets', () => {
|
||||
// 7003-MORD-009
|
||||
// 7003-MORD-010
|
||||
// 7003-MORD-011
|
||||
@@ -496,9 +496,7 @@ describe('amend and cancel order', { tags: '@smoke' }, () => {
|
||||
.should('have.text', 'Cancel all')
|
||||
.then(($btn) => {
|
||||
cy.wrap($btn).click({ force: true });
|
||||
const order: OrderCancellation = {
|
||||
marketId: 'market-0',
|
||||
};
|
||||
const order: OrderCancellation = {};
|
||||
testOrderCancellation(order);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,8 +9,3 @@ export const selectAsset = (assetIndex: number) => {
|
||||
// eslint-disable-next-line
|
||||
cy.wait(100);
|
||||
};
|
||||
|
||||
export const closeWelcomeDialog = () => {
|
||||
cy.getByTestId('select-market-list').should('exist');
|
||||
cy.getByTestId('dialog-close').click();
|
||||
};
|
||||
|
||||
@@ -85,7 +85,7 @@ const mockTradingPage = (
|
||||
trigger?: Schema.AuctionTrigger
|
||||
) => {
|
||||
aliasGQLQuery(req, 'ChainId', chainIdQuery());
|
||||
aliasGQLQuery(req, 'Statistics', statisticsQuery());
|
||||
aliasGQLQuery(req, 'NodeCheck', statisticsQuery());
|
||||
aliasGQLQuery(req, 'NodeGuard', nodeGuardQuery());
|
||||
aliasGQLQuery(
|
||||
req,
|
||||
|
||||
+2
-2
@@ -5,8 +5,8 @@ NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
|
||||
NX_VEGA_ENV=STAGNET1
|
||||
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
|
||||
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\"}
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.stagnet1.vega.rocks
|
||||
NX_VEGA_NETWORKS={\"MAINNET\":\"https://vega.trading\",\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://trading.stagnet1.vega.rocks\"}
|
||||
NX_VEGA_TOKEN_URL=https://governance.fairground.wtf
|
||||
NX_VEGA_WALLET_URL=http://localhost:1789
|
||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user