Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e50c42182 |
@@ -21,6 +21,7 @@ jobs:
|
|||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||||
|
|
||||||
- name: Cache node modules
|
- name: Cache node modules
|
||||||
id: cache
|
id: cache
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
@@ -38,6 +39,7 @@ jobs:
|
|||||||
node-version-file: '.nvmrc'
|
node-version-file: '.nvmrc'
|
||||||
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
|
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
|
||||||
cache: yarn
|
cache: yarn
|
||||||
|
|
||||||
- name: yarn install
|
- name: yarn install
|
||||||
if: steps.cache.outputs.cache-hit != 'true'
|
if: steps.cache.outputs.cache-hit != 'true'
|
||||||
run: yarn install --pure-lockfile
|
run: yarn install --pure-lockfile
|
||||||
@@ -49,11 +51,11 @@ jobs:
|
|||||||
uses: ./.github/workflows/lint-pr.yml
|
uses: ./.github/workflows/lint-pr.yml
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
lint-format:
|
lint-test-build:
|
||||||
timeout-minutes: 20
|
timeout-minutes: 60
|
||||||
needs: node-modules
|
needs: node-modules
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
name: '(CI) lint + format check'
|
name: '(CI) lint + unit test + build'
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
@@ -79,76 +81,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
main-branch-name: develop
|
main-branch-name: develop
|
||||||
|
|
||||||
- name: Check formatting
|
|
||||||
run: yarn nx format:check
|
|
||||||
|
|
||||||
- name: Lint affected
|
|
||||||
run: yarn nx affected:lint --max-warnings=0
|
|
||||||
|
|
||||||
- name: Build affected spec
|
|
||||||
run: yarn nx affected --target=build-spec
|
|
||||||
|
|
||||||
test-affected:
|
|
||||||
timeout-minutes: 30
|
|
||||||
needs: build-sources
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
name: 'run unit test of affected apps'
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
|
||||||
|
|
||||||
- name: Setup node
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version-file: '.nvmrc'
|
|
||||||
cache: yarn
|
|
||||||
|
|
||||||
- name: Cache node modules
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: node_modules
|
|
||||||
key: ${{ runner.os }}-cache-node-modules-${{ hashFiles('yarn.lock') }}
|
|
||||||
|
|
||||||
- name: Derive appropriate SHAs for base and head for `nx affected` commands
|
|
||||||
uses: nrwl/nx-set-shas@v3
|
|
||||||
with:
|
|
||||||
main-branch-name: develop
|
|
||||||
|
|
||||||
- name: Test affected
|
|
||||||
run: yarn nx affected:test
|
|
||||||
|
|
||||||
build-sources:
|
|
||||||
timeout-minutes: 30
|
|
||||||
needs: lint-format
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
name: 'Build sources of affected apps'
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
|
||||||
|
|
||||||
- name: Setup node
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version-file: '.nvmrc'
|
|
||||||
cache: yarn
|
|
||||||
|
|
||||||
- name: Cache node modules
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: node_modules
|
|
||||||
key: ${{ runner.os }}-cache-node-modules-${{ hashFiles('yarn.lock') }}
|
|
||||||
|
|
||||||
- name: Derive appropriate SHAs for base and head for `nx affected` commands
|
|
||||||
uses: nrwl/nx-set-shas@v3
|
|
||||||
with:
|
|
||||||
main-branch-name: develop
|
|
||||||
|
|
||||||
# See affected apps
|
# See affected apps
|
||||||
- name: See affected apps
|
- name: See affected apps
|
||||||
run: |
|
run: |
|
||||||
@@ -165,8 +97,21 @@ jobs:
|
|||||||
echo "preview_explorer: ${{ env.PREVIEW_EXPLORER }}"
|
echo "preview_explorer: ${{ env.PREVIEW_EXPLORER }}"
|
||||||
echo "preview_tools: ${{ env.PREVIEW_TOOLS }}"
|
echo "preview_tools: ${{ env.PREVIEW_TOOLS }}"
|
||||||
|
|
||||||
|
- name: Check formatting
|
||||||
|
run: yarn nx format:check
|
||||||
|
|
||||||
|
- name: Lint affected
|
||||||
|
run: yarn nx affected:lint --max-warnings=0
|
||||||
|
|
||||||
|
- name: Build affected spec
|
||||||
|
run: yarn nx affected --target=build-spec
|
||||||
|
|
||||||
|
- name: Test affected
|
||||||
|
run: yarn nx affected:test
|
||||||
|
|
||||||
- name: Build affected
|
- name: Build affected
|
||||||
run: yarn nx affected:build || (yarn install && yarn nx affected:build)
|
run: yarn nx affected:build || (yarn install && yarn nx affected:build)
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
projects: ${{ env.PROJECTS }}
|
projects: ${{ env.PROJECTS }}
|
||||||
projects-e2e: ${{ env.PROJECTS_E2E }}
|
projects-e2e: ${{ env.PROJECTS_E2E }}
|
||||||
@@ -176,38 +121,38 @@ jobs:
|
|||||||
preview_tools: ${{ env.PREVIEW_TOOLS }}
|
preview_tools: ${{ env.PREVIEW_TOOLS }}
|
||||||
|
|
||||||
console-e2e:
|
console-e2e:
|
||||||
needs: build-sources
|
needs: lint-test-build
|
||||||
name: '(CI) console python'
|
name: '(CI) console python'
|
||||||
uses: ./.github/workflows/console-test-run.yml
|
uses: ./.github/workflows/console-test-run.yml
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
if: ${{ contains(fromJSON(needs.build-sources.outputs.projects), 'trading') && github.event_name == 'pull_request' }}
|
if: ${{ contains(fromJSON(needs.lint-test-build.outputs.projects), 'trading') && github.event_name == 'pull_request' }}
|
||||||
with:
|
with:
|
||||||
github-sha: ${{ github.event.pull_request.head.sha || github.sha }}
|
github-sha: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||||
|
|
||||||
cypress:
|
cypress:
|
||||||
needs: build-sources
|
needs: lint-test-build
|
||||||
name: '(CI) cypress'
|
name: '(CI) cypress'
|
||||||
# if: ${{ needs.build-sources.outputs.projects-e2e != '[]' }}
|
# if: ${{ needs.lint-test-build.outputs.projects-e2e != '[]' }}
|
||||||
uses: ./.github/workflows/cypress-run.yml
|
uses: ./.github/workflows/cypress-run.yml
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
with:
|
with:
|
||||||
projects: ${{ needs.build-sources.outputs.projects-e2e }}
|
projects: ${{ needs.lint-test-build.outputs.projects-e2e }}
|
||||||
tags: '@smoke'
|
tags: '@smoke'
|
||||||
|
|
||||||
publish-dist:
|
publish-dist:
|
||||||
needs: build-sources
|
needs: lint-test-build
|
||||||
name: '(CD) publish dist'
|
name: '(CD) publish dist'
|
||||||
if: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == 'vegaprotocol/frontend-monorepo') || github.event_name == 'push' }}
|
if: ${{ (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == 'vegaprotocol/frontend-monorepo') || github.event_name == 'push' }}
|
||||||
uses: ./.github/workflows/publish-dist.yml
|
uses: ./.github/workflows/publish-dist.yml
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
with:
|
with:
|
||||||
projects: ${{ needs.build-sources.outputs.projects }}
|
projects: ${{ needs.lint-test-build.outputs.projects }}
|
||||||
|
|
||||||
dist-check:
|
dist-check:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
- publish-dist
|
- publish-dist
|
||||||
- build-sources
|
- lint-test-build
|
||||||
if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == 'vegaprotocol/frontend-monorepo' }}
|
if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == 'vegaprotocol/frontend-monorepo' }}
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
name: '(CD) comment preview links'
|
name: '(CD) comment preview links'
|
||||||
@@ -223,27 +168,27 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
# https://stackoverflow.com/questions/3183444/check-for-valid-link-url
|
# https://stackoverflow.com/questions/3183444/check-for-valid-link-url
|
||||||
regex='(https?|ftp|file)://[-[:alnum:]\+&@#/%?=~_|!:,.;]*[-[:alnum:]\+&@#/%=~_|]'
|
regex='(https?|ftp|file)://[-[:alnum:]\+&@#/%?=~_|!:,.;]*[-[:alnum:]\+&@#/%=~_|]'
|
||||||
if [[ "${{ needs.build-sources.outputs.preview_governance }}" =~ $regex ]]; then
|
if [[ "${{ needs.lint-test-build.outputs.preview_governance }}" =~ $regex ]]; then
|
||||||
until curl --insecure --location --fail "${{ needs.build-sources.outputs.preview_governance }}"; do
|
until curl --insecure --location --fail "${{ needs.lint-test-build.outputs.preview_governance }}"; do
|
||||||
echo "waiting for governance preview: ${{ needs.build-sources.outputs.preview_governance }}"
|
echo "waiting for governance preview: ${{ needs.lint-test-build.outputs.preview_governance }}"
|
||||||
sleep 5
|
sleep 5
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
if [[ "${{ needs.build-sources.outputs.preview_explorer }}" =~ $regex ]]; then
|
if [[ "${{ needs.lint-test-build.outputs.preview_explorer }}" =~ $regex ]]; then
|
||||||
until curl --insecure --location --fail "${{ needs.build-sources.outputs.preview_explorer }}"; do
|
until curl --insecure --location --fail "${{ needs.lint-test-build.outputs.preview_explorer }}"; do
|
||||||
echo "waiting for explorer preview: ${{ needs.build-sources.outputs.preview_explorer }}"
|
echo "waiting for explorer preview: ${{ needs.lint-test-build.outputs.preview_explorer }}"
|
||||||
sleep 5
|
sleep 5
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
if [[ "${{ needs.build-sources.outputs.preview_trading }}" =~ $regex ]]; then
|
if [[ "${{ needs.lint-test-build.outputs.preview_trading }}" =~ $regex ]]; then
|
||||||
until curl --insecure --location --fail "${{ needs.build-sources.outputs.preview_trading }}"; do
|
until curl --insecure --location --fail "${{ needs.lint-test-build.outputs.preview_trading }}"; do
|
||||||
echo "waiting for trading preview: ${{ needs.build-sources.outputs.preview_trading }}"
|
echo "waiting for trading preview: ${{ needs.lint-test-build.outputs.preview_trading }}"
|
||||||
sleep 5
|
sleep 5
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
if [[ "${{ needs.build-sources.outputs.preview_tools }}" =~ $regex ]]; then
|
if [[ "${{ needs.lint-test-build.outputs.preview_tools }}" =~ $regex ]]; then
|
||||||
until curl --insecure --location --fail "${{ needs.build-sources.outputs.preview_tools }}"; do
|
until curl --insecure --location --fail "${{ needs.lint-test-build.outputs.preview_tools }}"; do
|
||||||
echo "waiting for tools preview: ${{ needs.build-sources.outputs.preview_tools }}"
|
echo "waiting for tools preview: ${{ needs.lint-test-build.outputs.preview_tools }}"
|
||||||
sleep 5
|
sleep 5
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
@@ -255,10 +200,10 @@ jobs:
|
|||||||
issue-number: ${{ github.event.pull_request.number }}
|
issue-number: ${{ github.event.pull_request.number }}
|
||||||
body: |
|
body: |
|
||||||
Previews
|
Previews
|
||||||
* governance: ${{ needs.build-sources.outputs.preview_governance }}
|
* governance: ${{ needs.lint-test-build.outputs.preview_governance }}
|
||||||
* explorer: ${{ needs.build-sources.outputs.preview_explorer }}
|
* explorer: ${{ needs.lint-test-build.outputs.preview_explorer }}
|
||||||
* trading: ${{ needs.build-sources.outputs.preview_trading }}
|
* trading: ${{ needs.lint-test-build.outputs.preview_trading }}
|
||||||
* tools: ${{ needs.build-sources.outputs.preview_tools }}
|
* tools: ${{ needs.lint-test-build.outputs.preview_tools }}
|
||||||
|
|
||||||
# Report single result at the end, to avoid mess with required checks in PR
|
# Report single result at the end, to avoid mess with required checks in PR
|
||||||
cypress-check:
|
cypress-check:
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
name: (CI) Console tests
|
name: (CI) Console tests
|
||||||
|
|
||||||
env:
|
|
||||||
VEGA_VERSION: v0.72.14
|
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_call:
|
workflow_call:
|
||||||
inputs:
|
inputs:
|
||||||
@@ -13,8 +10,8 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
run-tests:
|
run-tests:
|
||||||
name: run-tests
|
name: run-tests
|
||||||
runs-on: console-test
|
runs-on: 8-cores
|
||||||
timeout-minutes: 40
|
timeout-minutes: 20
|
||||||
steps:
|
steps:
|
||||||
#----------------------------------------------
|
#----------------------------------------------
|
||||||
# check-out frontend-monorepo
|
# check-out frontend-monorepo
|
||||||
@@ -36,6 +33,15 @@ jobs:
|
|||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-cache-node-modules-
|
${{ runner.os }}-cache-node-modules-
|
||||||
#----------------------------------------------
|
#----------------------------------------------
|
||||||
|
# setup node
|
||||||
|
#----------------------------------------------
|
||||||
|
- name: Setup node
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version-file: '.nvmrc'
|
||||||
|
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
|
||||||
|
cache: yarn
|
||||||
|
#----------------------------------------------
|
||||||
# install deps if cache missing
|
# install deps if cache missing
|
||||||
#----------------------------------------------
|
#----------------------------------------------
|
||||||
- name: yarn install
|
- name: yarn install
|
||||||
@@ -70,46 +76,56 @@ jobs:
|
|||||||
repository: vegaprotocol/console-test
|
repository: vegaprotocol/console-test
|
||||||
path: './console-test'
|
path: './console-test'
|
||||||
#----------------------------------------------
|
#----------------------------------------------
|
||||||
# install dependencies
|
# set-up python
|
||||||
|
#----------------------------------------------
|
||||||
|
- name: Set up python
|
||||||
|
id: setup-python
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.10.11'
|
||||||
|
#----------------------------------------------
|
||||||
|
# ----- install & configure poetry -----
|
||||||
|
#----------------------------------------------
|
||||||
|
- name: Install Poetry
|
||||||
|
uses: snok/install-poetry@v1
|
||||||
|
with:
|
||||||
|
virtualenvs-create: true
|
||||||
|
virtualenvs-in-project: true
|
||||||
|
virtualenvs-path: console-test/.venv
|
||||||
|
#----------------------------------------------
|
||||||
|
# load cached venv if cache exists
|
||||||
|
#----------------------------------------------
|
||||||
|
- name: Load cached venv
|
||||||
|
id: cached-poetry-dependencies
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: console-test/.venv
|
||||||
|
key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }}
|
||||||
|
#----------------------------------------------
|
||||||
|
# install dependencies if cache does not exist
|
||||||
#----------------------------------------------
|
#----------------------------------------------
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
working-directory: ./console-test
|
working-directory: ./console-test
|
||||||
|
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
|
||||||
run: poetry install --no-interaction --no-root
|
run: poetry install --no-interaction --no-root
|
||||||
#----------------------------------------------
|
#----------------------------------------------
|
||||||
# find vega binaries path
|
# install vega binaries
|
||||||
#----------------------------------------------
|
|
||||||
- name: Find vega binaries path
|
|
||||||
id: vega_bin_path
|
|
||||||
working-directory: ./console-test
|
|
||||||
run: echo path=$(poetry run python -c "import vega_sim; print(vega_sim.vega_bin_path)") >> $GITHUB_OUTPUT
|
|
||||||
#----------------------------------------------
|
|
||||||
# vega binaries cache
|
|
||||||
#----------------------------------------------
|
|
||||||
- name: Vega binaries cache
|
|
||||||
uses: actions/cache@v3
|
|
||||||
id: vega_binaries_cache
|
|
||||||
with:
|
|
||||||
path: ${{ steps.vega_bin_path.outputs.path }}
|
|
||||||
key: ${{ runner.os }}-vega-binaries-${{ env.VEGA_VERSION }}
|
|
||||||
#----------------------------------------------
|
|
||||||
# install vega binaries
|
|
||||||
#----------------------------------------------
|
#----------------------------------------------
|
||||||
- name: Install vega binaries
|
- name: Install vega binaries
|
||||||
working-directory: ./console-test
|
working-directory: ./console-test
|
||||||
if: steps.vega_binaries_cache.outputs.cache-hit != 'true'
|
run: poetry run python -m vega_sim.tools.load_binaries --force
|
||||||
run: poetry run python -m vega_sim.tools.load_binaries --force --version $VEGA_VERSION
|
|
||||||
#----------------------------------------------
|
#----------------------------------------------
|
||||||
# install playwright
|
# install playwright
|
||||||
#----------------------------------------------
|
#----------------------------------------------
|
||||||
- name: install playwright
|
- name: install playwright
|
||||||
run: poetry run playwright install --with-deps chromium
|
run: poetry run playwright install
|
||||||
working-directory: ./console-test
|
working-directory: ./console-test
|
||||||
#----------------------------------------------
|
#----------------------------------------------
|
||||||
# run tests
|
# run tests
|
||||||
#----------------------------------------------
|
#----------------------------------------------
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
working-directory: ./console-test
|
working-directory: ./console-test
|
||||||
run: poetry run pytest -v -s --numprocesses 2 --dist loadfile --durations=20
|
run: poetry run pytest -s --numprocesses auto --dist loadfile
|
||||||
- name: Check files
|
- name: Check files
|
||||||
run: |
|
run: |
|
||||||
ls -al .
|
ls -al .
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ jobs:
|
|||||||
|
|
||||||
# Restore node_modules from cache if possible
|
# Restore node_modules from cache if possible
|
||||||
- name: Restore node_modules from cache
|
- name: Restore node_modules from cache
|
||||||
id: cache-node-modules
|
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
@@ -47,7 +46,6 @@ jobs:
|
|||||||
|
|
||||||
# Install frontend dependencies
|
# Install frontend dependencies
|
||||||
- name: Install root dependencies
|
- name: Install root dependencies
|
||||||
if: steps.cache-node-modules.outputs.cache-hit != 'true'
|
|
||||||
run: yarn install --frozen-lockfile
|
run: yarn install --frozen-lockfile
|
||||||
working-directory: frontend-monorepo
|
working-directory: frontend-monorepo
|
||||||
|
|
||||||
@@ -69,7 +67,7 @@ jobs:
|
|||||||
######
|
######
|
||||||
|
|
||||||
- name: Run Cypress tests
|
- name: Run Cypress tests
|
||||||
run: yarn nx run ${{ matrix.project }}:e2e ${{ env.SKIP_CACHE }} --browser chrome --env.grepTags="${{ inputs.tags }}"
|
run: yarn nx run ${{ matrix.project }}:e2e ${{ env.SKIP_CACHE }} --browser chrome --env.grepTags="${{ inputs.tags }}"
|
||||||
working-directory: frontend-monorepo
|
working-directory: frontend-monorepo
|
||||||
env:
|
env:
|
||||||
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
|
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
|
||||||
|
|||||||
@@ -155,10 +155,10 @@ jobs:
|
|||||||
- name: Sanity check docker image
|
- name: Sanity check docker image
|
||||||
run: |
|
run: |
|
||||||
echo "Check ipfs-hash"
|
echo "Check ipfs-hash"
|
||||||
docker run --rm --entrypoint /bin/sh ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local -c 'cat /ipfs-hash'
|
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local cat /ipfs-hash
|
||||||
docker run --rm --entrypoint /bin/sh ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local -c 'cat /ipfs-hash' > ${{ matrix.app }}-ipfs-hash
|
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local cat /ipfs-hash > ${{ matrix.app }}-ipfs-hash
|
||||||
echo "List html directory"
|
echo "List html directory"
|
||||||
docker run --rm --entrypoint /bin/sh ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local -c 'apk add --update tree; tree /usr/share/nginx/html'
|
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local sh -c 'apk add --update tree; tree /usr/share/nginx/html'
|
||||||
|
|
||||||
- name: Publish dist as docker image (ghcr)
|
- name: Publish dist as docker image (ghcr)
|
||||||
uses: docker/build-push-action@v3
|
uses: docker/build-push-action@v3
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ on:
|
|||||||
- types
|
- types
|
||||||
- utils
|
- utils
|
||||||
- i18n
|
- i18n
|
||||||
- wallet
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
publish:
|
publish:
|
||||||
|
|||||||
@@ -3,3 +3,6 @@
|
|||||||
|
|
||||||
# Lint commit messages to ensure they follow conventional commit standards
|
# Lint commit messages to ensure they follow conventional commit standards
|
||||||
yarn commitlint --edit "${1}"
|
yarn commitlint --edit "${1}"
|
||||||
|
|
||||||
|
# Lint all staged files
|
||||||
|
yarn lint-staged
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
. "$(dirname "$0")/_/husky.sh"
|
|
||||||
|
|
||||||
# Lint all staged files
|
|
||||||
yarn lint-staged
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
. "$(dirname "$0")/_/husky.sh"
|
|
||||||
|
|
||||||
# Lint all staged files
|
|
||||||
yarn nx format:check
|
|
||||||
|
|
||||||
# Test all projects with changes
|
|
||||||
yarn nx affected -t test --exclude trading
|
|
||||||
@@ -1,3 +1,2 @@
|
|||||||
* @vegaprotocol/frontend
|
* @vegaprotocol/frontend
|
||||||
* @vegaprotocol/frontend-qa
|
|
||||||
*.graphql @vegaprotocol/core
|
*.graphql @vegaprotocol/core
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ recalculate-ipfs:
|
|||||||
echo "ipfs hash inside the image"
|
echo "ipfs hash inside the image"
|
||||||
docker run --rm ${TAG} cat /ipfs-hash
|
docker run --rm ${TAG} cat /ipfs-hash
|
||||||
echo "recalculating ipfs hash"
|
echo "recalculating ipfs hash"
|
||||||
docker run --rm ${TAG} ipfs add -rQ /usr/share/nginx/html
|
docker run --rm ${TAG} ipfs add -r /usr/share/nginx/html
|
||||||
|
|
||||||
.PHONY: eject-ipfs-hash
|
.PHONY: eject-ipfs-hash
|
||||||
unpack:
|
unpack:
|
||||||
|
|||||||
@@ -113,47 +113,13 @@ In order to run a container on port 3000:
|
|||||||
docker run -p 3000:80 [TAG]
|
docker run -p 3000:80 [TAG]
|
||||||
```
|
```
|
||||||
|
|
||||||
On top of that there are two possible scenarios for running docker image - using nginx server (default) of ipfs daemon.
|
|
||||||
|
|
||||||
to run ipfs on port 3000:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker run -p 3000:80 [TAG] ipfs
|
|
||||||
```
|
|
||||||
|
|
||||||
to run nginx on port 3000:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker run -p 3000:80 [TAG]
|
|
||||||
```
|
|
||||||
|
|
||||||
## Build instructions
|
## Build instructions
|
||||||
|
|
||||||
The [`docker`](./docker) subfolder has some docker configurations for easily setting up your own hosted version of Console either for the web, or ready for pinning on IPFS.
|
The [`docker`](./docker) subfolder has some docker configurations for easily setting up your own hosted version of console either for the web, or ready for pinning on IPFS
|
||||||
|
|
||||||
### nx build inside the docker
|
|
||||||
|
|
||||||
Using multistage dockerfile dist is compiled using [node](https://hub.docker.com/_/node) image and later packed to nginx as in [dist build](#dist-build). The multistage builds ensures consistent CPU architecture and build toolchains are used so that the result will be identical.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker build --build-arg APP=[YOUR APP] --build-arg NODE_VERSION=16.5.1 --build-arg ENV_NAME=mainnet -t [TAG] -f docker/node-inside-docker.Dockerfile .
|
|
||||||
```
|
|
||||||
|
|
||||||
### Computing ipfs-hash of the build
|
|
||||||
|
|
||||||
At the moment this feature is important only for Console releases.
|
|
||||||
|
|
||||||
Each docker build finishes with hash calculation for ` dist`` directory. Resulting hash is added to file named as `/ipfs-hash`. Once docker image is produced you can run following commad to display ipfs-hash:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
make recalculate-ipfs TAG=vegaprotocol/trading:{YOUR_VERSION}
|
|
||||||
```
|
|
||||||
|
|
||||||
**updating hash:** recompiling dist directory (even if there are no changed to source code) results in different hash computed by ipfs command.
|
|
||||||
|
|
||||||
### nx build outside the docker
|
### nx build outside the docker
|
||||||
|
|
||||||
This Docker image packages a pre-built `dist` folder into an [`nginx`](https://hub.docker.com/_/nginx)([server configuration](./nginx/nginx.conf)) docker image. In this case, the application on docker host machine from source.
|
Packaging prepared dist into [`nginx`](https://hub.docker.com/_/nginx)([server configuration](./nginx/nginx.conf)) docker image involves building the application on docker host machine from source.
|
||||||
|
|
||||||
As a prerequisite you need to perform build of `dist` directory and move its content for specific application to `dist-result` directory. Use following script to do it with a single command:
|
As a prerequisite you need to perform build of `dist` directory and move its content for specific application to `dist-result` directory. Use following script to do it with a single command:
|
||||||
|
|
||||||
@@ -164,21 +130,41 @@ As a prerequisite you need to perform build of `dist` directory and move its con
|
|||||||
You can build any of the containers locally with the following command:
|
You can build any of the containers locally with the following command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker build -f docker/node-outside-docker.Dockerfile . --tag=[TAG]
|
docker build --dockerfile docker/node-outside-docker.Dockerfile . --tag=[TAG]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### nx build inside the docker
|
||||||
|
|
||||||
|
Using multistage dockerfile dist is compiled using [node](https://hub.docker.com/_/node) image and later packed to nginx as in [dist build](#dist-build) example.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build --build-arg APP=[YOUR APP] --build-arg NODE_VERSION=$(cat .nvmrc) --build-arg ENV_NAME=mainnet -t [TAG] -f docker/node-inside-docker.Dockerfile .
|
||||||
|
```
|
||||||
|
|
||||||
|
### Computing ipfs-hash of the build
|
||||||
|
|
||||||
|
At the moment this feature is important only for `trading` (console) releases.
|
||||||
|
|
||||||
|
Each docker build finishes with hash calculation for dist directory. Resulting hash is added to file named as `/ipfs-hash`. Once docker image is produced you can run following commad to display ipfs-hash:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make recalculate-ipfs TAG=vegaprotocol/trading:{YOUR_VERSION}
|
||||||
|
```
|
||||||
|
|
||||||
|
**updating hash:** recompiling dist directory (even if there are no changed to source code) results in different hash computed by ipfs command.
|
||||||
|
|
||||||
### Verifying ipfs-hash of existing current application version
|
### Verifying ipfs-hash of existing current application version
|
||||||
|
|
||||||
An IPFS CID will be attached to every [release](https://github.com/vegaprotocol/frontend-monorepo/releases). If you are intending to pin an application on IPFS, you can check that your build matches by running the following steps:
|
An IPFS CID will be attached to every [release](https://github.com/vegaprotocol/frontend-monorepo/releases). If you are intending to pin an application on IPFS, you can check that your build matches by running the following steps:
|
||||||
|
|
||||||
1. Show latest release by running: `make latest-release`. You need to configure [`gh`](https://cli.github.com/) for this step to work, otherwise please provide release manually from [github](https://github.com/vegaprotocol/frontend-monorepo/releases) or [dockerhub](https://hub.docker.com/r/vegaprotocol/trading)
|
1. Show latest release by runnning: `make latest-release`. You need to configure [`gh`](https://cli.github.com/) for this step to work, otherwise please provide release manually from [github](https://github.com/vegaprotocol/frontend-monorepo/releases) or [dockerhub](https://hub.docker.com/r/vegaprotocol/trading)
|
||||||
2. Set RELEASE environment variable to value that you want to validate: `export RELEASE=$(make latest-release)` or `export RELEASE=vXX.XX.XX`
|
2. Set RELEASE environment variable to value that you want to validate: `export RELEASE=$(make latest-release)` or `export RELEASE=vXX.XX.XX`
|
||||||
3. Set TAG environment variable to image that you want to validate: `export TAG=vegaprotocol/trading:$RELEASE`
|
3. Set TAG environment variable to image that you want to validate: `export TAG=vegaprotocol/trading:$RELEASE`
|
||||||
4. Download docker image with the desired release `docker pull $TAG`.
|
4. Download docker image with the desired release `docker pull $TAG`.
|
||||||
5. Recalculate hash: `make recalculate-ipfs`
|
5. Recalculate hash: `make recalculate-ipfs`
|
||||||
6. You should see exactly same hash produced by ipfs command as one placed with the release notes: `make show-latest-release`
|
6. You should see exactly same hash produced by ipfs command as one placed with the release notes: `make show-latest-release`
|
||||||
7. If you want to extract dist from docker image to your local filesystem you can run following command: `make unpack`
|
7. If you want to extract dist from docker image to your local filesystem you can run following command: `make unpack`
|
||||||
8. Now `dist` directory contains valid application build
|
8. Now `dist` directory contains valid application build. **it is not possible to calculate same ipfs hash on files that are result of copy operation**
|
||||||
|
|
||||||
## Config
|
## Config
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://n04.d.vega.xyz/tm/websocket
|
|||||||
NX_VEGA_URL=https://api.n04.d.vega.xyz/graphql
|
NX_VEGA_URL=https://api.n04.d.vega.xyz/graphql
|
||||||
NX_VEGA_ENV=DEVNET
|
NX_VEGA_ENV=DEVNET
|
||||||
NX_BLOCK_EXPLORER=https://be.devnet1.vega.xyz/rest
|
NX_BLOCK_EXPLORER=https://be.devnet1.vega.xyz/rest
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
|
||||||
|
|
||||||
|
|
||||||
# App flags
|
# App flags
|
||||||
NX_EXPLORER_ASSETS=1
|
NX_EXPLORER_ASSETS=1
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://mainnet-observer-proxy01.ops.vega.xyz/websocke
|
|||||||
NX_VEGA_URL=https://api.vega.community/graphql
|
NX_VEGA_URL=https://api.vega.community/graphql
|
||||||
NX_VEGA_ENV=MAINNET
|
NX_VEGA_ENV=MAINNET
|
||||||
NX_BLOCK_EXPLORER=https://be.explorer.vega.xyz/rest
|
NX_BLOCK_EXPLORER=https://be.explorer.vega.xyz/rest
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
|
||||||
|
|
||||||
# App flags
|
# App flags
|
||||||
NX_EXPLORER_ASSETS=1
|
NX_EXPLORER_ASSETS=1
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://lb.testnet.vega.xyz/tm/websocket
|
|||||||
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
|
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
|
||||||
NX_VEGA_ENV=TESTNET
|
NX_VEGA_ENV=TESTNET
|
||||||
NX_BLOCK_EXPLORER=https://be.testnet.vega.xyz/rest
|
NX_BLOCK_EXPLORER=https://be.testnet.vega.xyz/rest
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
|
||||||
|
|
||||||
# App flags
|
# App flags
|
||||||
NX_EXPLORER_ASSETS=1
|
NX_EXPLORER_ASSETS=1
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
{
|
|
||||||
"proposalSubmission": {
|
|
||||||
"rationale": {
|
|
||||||
"title": "Test new asset proposal",
|
|
||||||
"description": "E2E test for proposals"
|
|
||||||
},
|
|
||||||
"terms": {
|
|
||||||
"newAsset": {
|
|
||||||
"changes": {
|
|
||||||
"name": "USDT Coin",
|
|
||||||
"symbol": "USDT",
|
|
||||||
"decimals": "18",
|
|
||||||
"quantum": "1",
|
|
||||||
"erc20": {
|
|
||||||
"contractAddress": "0xb404c51bbc10dcbe948077f18a4b8e553d160084",
|
|
||||||
"withdrawThreshold": "10",
|
|
||||||
"lifetimeLimit": "10"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"closingTimestamp": 1724339572,
|
|
||||||
"enactmentTimestamp": 1724339572,
|
|
||||||
"validationTimestamp": 1692799617
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
context('Network parameters page', { tags: '@smoke' }, function () {
|
context('Network parameters page', { tags: '@smoke' }, function () {
|
||||||
before('navigate to network parameter page', function () {
|
before('navigate to network parameter page', function () {
|
||||||
cy.fixture('net_parameter_format_lookup').as('networkParameterFormat');
|
cy.fixture('net_parameter_format_lookup').as('networkParameterFormat');
|
||||||
cy.visit('/network-parameters');
|
|
||||||
});
|
});
|
||||||
describe('Verify elements on page', function () {
|
describe('Verify elements on page', function () {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.visit('/network-parameters');
|
||||||
|
});
|
||||||
|
|
||||||
const networkParametersHeader = '[data-testid="network-param-header"]';
|
const networkParametersHeader = '[data-testid="network-param-header"]';
|
||||||
const tableRows = '[data-testid="key-value-table-row"]';
|
const tableRows = '[data-testid="key-value-table-row"]';
|
||||||
|
|
||||||
@@ -13,7 +16,6 @@ context('Network parameters page', { tags: '@smoke' }, function () {
|
|||||||
.and('be.visible');
|
.and('be.visible');
|
||||||
});
|
});
|
||||||
|
|
||||||
// 0006-NETW-021
|
|
||||||
it('should list each of the network parameters available', function () {
|
it('should list each of the network parameters available', function () {
|
||||||
cy.get_network_parameters().then((network_parameters) => {
|
cy.get_network_parameters().then((network_parameters) => {
|
||||||
const numberOfNetworkParametersInSystem =
|
const numberOfNetworkParametersInSystem =
|
||||||
@@ -196,19 +198,6 @@ context('Network parameters page', { tags: '@smoke' }, function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// 0006-NETW-022 0006-NETW-023
|
|
||||||
it('governance assets should be correctly grouped', function () {
|
|
||||||
cy.getByTestId('governance')
|
|
||||||
.should('exist')
|
|
||||||
.parent()
|
|
||||||
.should('have.attr', 'href', '/network-parameters#governance');
|
|
||||||
cy.get('[id="governance-proposal-asset"]')
|
|
||||||
.parent()
|
|
||||||
.within(() => {
|
|
||||||
cy.getByTestId('key-value-table-row').should('have.length', 8);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be able to see network parameters - on mobile', function () {
|
it('should be able to see network parameters - on mobile', function () {
|
||||||
cy.switchToMobile();
|
cy.switchToMobile();
|
||||||
cy.get_network_parameters().then((network_parameters) => {
|
cy.get_network_parameters().then((network_parameters) => {
|
||||||
|
|||||||
@@ -1,68 +0,0 @@
|
|||||||
context('Oracle page', { tags: '@smoke' }, () => {
|
|
||||||
describe('Verify elements on page', () => {
|
|
||||||
before('create market and navigate to oracle page', () => {
|
|
||||||
cy.createMarket();
|
|
||||||
cy.visit('/oracles');
|
|
||||||
});
|
|
||||||
it('should see oracle data', () => {
|
|
||||||
cy.getByTestId('oracle-details').should('have.length.at.least', 2);
|
|
||||||
cy.getByTestId('oracle-details')
|
|
||||||
.should('exist')
|
|
||||||
.eq(0)
|
|
||||||
.within(() => {
|
|
||||||
cy.get('tr')
|
|
||||||
.eq(0)
|
|
||||||
.within(() => {
|
|
||||||
cy.get('th').should('have.text', 'ID');
|
|
||||||
cy.get('a').invoke('text').should('have.length', 64);
|
|
||||||
cy.get('a')
|
|
||||||
.should('have.attr', 'href')
|
|
||||||
.and('contain', '/oracles/');
|
|
||||||
});
|
|
||||||
cy.get('tr')
|
|
||||||
.eq(1)
|
|
||||||
.within(() => {
|
|
||||||
cy.get('th').should('have.text', 'Type');
|
|
||||||
cy.get('td').should('have.text', 'External data');
|
|
||||||
});
|
|
||||||
cy.get('tr')
|
|
||||||
.eq(2)
|
|
||||||
.within(() => {
|
|
||||||
cy.get('th').should('have.text', 'Signer');
|
|
||||||
cy.getByTestId('keytype').should('have.text', 'Vega');
|
|
||||||
cy.get('a').invoke('text').should('have.length', 64);
|
|
||||||
cy.get('a')
|
|
||||||
.should('have.attr', 'href')
|
|
||||||
.and('contain', '/parties/');
|
|
||||||
});
|
|
||||||
cy.get('tr')
|
|
||||||
.eq(3)
|
|
||||||
.within(() => {
|
|
||||||
cy.get('th').should('have.text', 'Settlement for');
|
|
||||||
cy.get('a').invoke('text').should('have.length', 64);
|
|
||||||
cy.get('a')
|
|
||||||
.should('have.attr', 'href')
|
|
||||||
.and('contain', '/markets/');
|
|
||||||
});
|
|
||||||
cy.get('tr')
|
|
||||||
.eq(4)
|
|
||||||
.within(() => {
|
|
||||||
cy.get('th').should('have.text', 'Matched data');
|
|
||||||
cy.get('td').should('have.text', '❌');
|
|
||||||
});
|
|
||||||
cy.get('details')
|
|
||||||
.eq(0)
|
|
||||||
.within(() => {
|
|
||||||
cy.contains('Filter').click();
|
|
||||||
cy.get('.language-json').should('exist');
|
|
||||||
});
|
|
||||||
cy.get('details')
|
|
||||||
.eq(1)
|
|
||||||
.within(() => {
|
|
||||||
cy.contains('JSON').click();
|
|
||||||
cy.get('.language-json').should('exist');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
import { getNewAssetTxBody } from '../support/governance.functions';
|
|
||||||
|
|
||||||
context('Proposal page', { tags: '@smoke' }, function () {
|
context('Proposal page', { tags: '@smoke' }, function () {
|
||||||
describe('Verify elements on page', function () {
|
describe('Verify elements on page', function () {
|
||||||
const proposalHeading = 'proposals-heading';
|
const proposalHeading = 'proposals-heading';
|
||||||
const dateTimeRegex =
|
const dateTimeRegex =
|
||||||
/(\d{1,2})\/(\d{1,2})\/(\d{4}), (\d{1,2}):(\d{1,2}):(\d{1,2})/gm;
|
/(\d{1,2})\/(\d{1,2})\/(\d{4}), (\d{1,2}):(\d{1,2}):(\d{1,2})/gm;
|
||||||
|
const proposalTitle = 'Add Lorem Ipsum market';
|
||||||
|
|
||||||
before('Create market proposal', function () {
|
before('Create market proposal', function () {
|
||||||
cy.visit('/');
|
cy.visit('/');
|
||||||
@@ -12,8 +11,6 @@ context('Proposal page', { tags: '@smoke' }, function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('Able to view proposal', function () {
|
it('Able to view proposal', function () {
|
||||||
const proposalTitle = 'Add Lorem Ipsum market';
|
|
||||||
|
|
||||||
cy.navigate_to('governanceProposals');
|
cy.navigate_to('governanceProposals');
|
||||||
cy.getByTestId(proposalHeading).should('be.visible');
|
cy.getByTestId(proposalHeading).should('be.visible');
|
||||||
cy.contains(proposalTitle)
|
cy.contains(proposalTitle)
|
||||||
@@ -25,9 +22,6 @@ context('Proposal page', { tags: '@smoke' }, function () {
|
|||||||
cy.get_element_by_col_id('type').should('have.text', 'NewMarket');
|
cy.get_element_by_col_id('type').should('have.text', 'NewMarket');
|
||||||
cy.get_element_by_col_id('state').should('have.text', 'Enacted');
|
cy.get_element_by_col_id('state').should('have.text', 'Enacted');
|
||||||
cy.getByTestId('vote-progress').should('be.visible');
|
cy.getByTestId('vote-progress').should('be.visible');
|
||||||
cy.getByTestId('vote-progress-bar-for')
|
|
||||||
.invoke('attr', 'style')
|
|
||||||
.should('eq', 'width: 100%;');
|
|
||||||
cy.get('[col-id="cDate"]')
|
cy.get('[col-id="cDate"]')
|
||||||
.invoke('text')
|
.invoke('text')
|
||||||
.should('match', dateTimeRegex);
|
.should('match', dateTimeRegex);
|
||||||
@@ -41,12 +35,9 @@ context('Proposal page', { tags: '@smoke' }, function () {
|
|||||||
});
|
});
|
||||||
cy.getByTestId('dialog-title').should('have.text', proposalTitle);
|
cy.getByTestId('dialog-title').should('have.text', proposalTitle);
|
||||||
cy.get('.language-json').should('exist');
|
cy.get('.language-json').should('exist');
|
||||||
cy.getByTestId('icon-cross').click();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip('Proposal page displayed on mobile', function () {
|
it.skip('Proposal page displayed on mobile', function () {
|
||||||
const proposalTitle = 'Add Lorem Ipsum market';
|
|
||||||
|
|
||||||
cy.common_switch_to_mobile_and_click_toggle();
|
cy.common_switch_to_mobile_and_click_toggle();
|
||||||
cy.navigate_to('governanceProposals', true);
|
cy.navigate_to('governanceProposals', true);
|
||||||
cy.getByTestId(proposalHeading).should('be.visible');
|
cy.getByTestId(proposalHeading).should('be.visible');
|
||||||
@@ -54,40 +45,5 @@ context('Proposal page', { tags: '@smoke' }, function () {
|
|||||||
cy.get_element_by_col_id('title').should('have.text', proposalTitle);
|
cy.get_element_by_col_id('title').should('have.text', proposalTitle);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Able to view new asset proposal', function () {
|
|
||||||
const proposalTitle = 'Test new asset proposal';
|
|
||||||
const newAssetProposalBody = getNewAssetTxBody();
|
|
||||||
cy.VegaWalletSubmitProposal(newAssetProposalBody);
|
|
||||||
|
|
||||||
cy.visit('/');
|
|
||||||
cy.navigate_to('governanceProposals');
|
|
||||||
cy.contains(proposalTitle)
|
|
||||||
.parent()
|
|
||||||
.parent()
|
|
||||||
.parent()
|
|
||||||
.within(() => {
|
|
||||||
cy.get_element_by_col_id('title').should('have.text', proposalTitle);
|
|
||||||
cy.get_element_by_col_id('type').should('have.text', 'NewAsset');
|
|
||||||
cy.get_element_by_col_id('state').should(
|
|
||||||
'have.text',
|
|
||||||
'Waiting for Node Vote'
|
|
||||||
);
|
|
||||||
cy.getByTestId('vote-progress').should('be.visible');
|
|
||||||
cy.getByTestId('vote-progress-bar-against')
|
|
||||||
.invoke('attr', 'style')
|
|
||||||
.should('eq', 'width: 100%;');
|
|
||||||
cy.get('[col-id="cDate"]')
|
|
||||||
.invoke('text')
|
|
||||||
.should('match', dateTimeRegex);
|
|
||||||
cy.get('[col-id="eDate"]')
|
|
||||||
.invoke('text')
|
|
||||||
.should('match', dateTimeRegex);
|
|
||||||
cy.getByTestId('external-link')
|
|
||||||
.should('have.attr', 'href')
|
|
||||||
.and('contains', 'https://governance.fairground.wtf/proposals/');
|
|
||||||
cy.contains('View terms').should('exist').click();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,18 +1,8 @@
|
|||||||
import { addSeconds, millisecondsToSeconds } from 'date-fns';
|
|
||||||
|
|
||||||
export function createSuccessorMarketProposal(parentMarketId) {
|
export function createSuccessorMarketProposal(parentMarketId) {
|
||||||
cy.VegaWalletSubmitProposal(getSuccessorTxBody(parentMarketId));
|
cy.VegaWalletSubmitProposal(getSuccessorTxBody(parentMarketId));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSuccessorTxBody(parentMarketId) {
|
function getSuccessorTxBody(parentMarketId) {
|
||||||
const MIN_CLOSE_SEC = 500;
|
|
||||||
const MIN_ENACT_SEC = 700;
|
|
||||||
|
|
||||||
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 {
|
return {
|
||||||
proposalSubmission: {
|
proposalSubmission: {
|
||||||
rationale: {
|
rationale: {
|
||||||
@@ -132,49 +122,8 @@ function getSuccessorTxBody(parentMarketId) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
closingTimestamp,
|
closingTimestamp: 1695666618,
|
||||||
enactmentTimestamp,
|
enactmentTimestamp: 1695666618,
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getNewAssetTxBody() {
|
|
||||||
const MIN_CLOSE_SEC = 500;
|
|
||||||
const MIN_ENACT_SEC = 700;
|
|
||||||
const MIN_VALID_SEC = 60;
|
|
||||||
|
|
||||||
const closingDate = addSeconds(new Date(), MIN_CLOSE_SEC);
|
|
||||||
const enactmentDate = addSeconds(closingDate, MIN_ENACT_SEC);
|
|
||||||
const validationDate = addSeconds(new Date(), MIN_VALID_SEC);
|
|
||||||
|
|
||||||
const closingTimestamp = millisecondsToSeconds(closingDate.getTime());
|
|
||||||
const enactmentTimestamp = millisecondsToSeconds(enactmentDate.getTime());
|
|
||||||
const validationTimestamp = millisecondsToSeconds(validationDate.getTime());
|
|
||||||
|
|
||||||
return {
|
|
||||||
proposalSubmission: {
|
|
||||||
rationale: {
|
|
||||||
title: 'Test new asset proposal',
|
|
||||||
description: 'E2E test for proposals',
|
|
||||||
},
|
|
||||||
terms: {
|
|
||||||
newAsset: {
|
|
||||||
changes: {
|
|
||||||
name: 'USDT Coin',
|
|
||||||
symbol: 'USDT',
|
|
||||||
decimals: '18',
|
|
||||||
quantum: '1',
|
|
||||||
erc20: {
|
|
||||||
contractAddress: '0xb404c51bbc10dcbe948077f18a4b8e553d160084',
|
|
||||||
withdrawThreshold: '10',
|
|
||||||
lifetimeLimit: '10',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
closingTimestamp,
|
|
||||||
enactmentTimestamp,
|
|
||||||
validationTimestamp,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ NX_VEGA_ENV=CUSTOM
|
|||||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
|
||||||
NX_VEGA_EXPLORER_URL=/
|
NX_VEGA_EXPLORER_URL=/
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
|
||||||
|
|
||||||
# App flags
|
# App flags
|
||||||
NX_EXPLORER_TXS_LIST=0
|
NX_EXPLORER_TXS_LIST=0
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ NX_VEGA_URL=https://api.devnet1.vega.xyz/graphql
|
|||||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
|
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
|
||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||||
NX_VEGA_EXPLORER_URL=/
|
NX_VEGA_EXPLORER_URL=/
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
|
||||||
|
|
||||||
NX_TENDERMINT_URL=https://tm.be.devnet1.vega.xyz/
|
NX_TENDERMINT_URL=https://tm.be.devnet1.vega.xyz/
|
||||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.devnet1.vega.xyz/websocket
|
NX_TENDERMINT_WEBSOCKET_URL=wss://be.devnet1.vega.xyz/websocket
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ NX_VEGA_GOVERNANCE_URL=https://governance.vega.xyz
|
|||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
|
||||||
NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz/
|
NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz/
|
||||||
NX_VEGA_CONSOLE_URL=https://console.vega.xyz
|
NX_VEGA_CONSOLE_URL=https://console.vega.xyz
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
|
||||||
|
|
||||||
NX_TENDERMINT_URL=https://be.vega.community
|
NX_TENDERMINT_URL=https://be.vega.community
|
||||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket
|
NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ NX_VEGA_GOVERNANCE_URL=https://governance.mainnet-mirror.vega.rocks
|
|||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
|
||||||
NX_VEGA_EXPLORER_URL=https://explorer.mainnet-mirror.vega.rocks/
|
NX_VEGA_EXPLORER_URL=https://explorer.mainnet-mirror.vega.rocks/
|
||||||
NX_VEGA_CONSOLE_URL=https://console.mainnet-mirror.vega.rocks
|
NX_VEGA_CONSOLE_URL=https://console.mainnet-mirror.vega.rocks
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
|
||||||
|
|
||||||
NX_TENDERMINT_URL=https://be.mainnet-mirror.vega.rocks
|
NX_TENDERMINT_URL=https://be.mainnet-mirror.vega.rocks
|
||||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.mainnet-mirror.vega.rocks/websocket
|
NX_TENDERMINT_WEBSOCKET_URL=wss://be.mainnet-mirror.vega.rocks/websocket
|
||||||
|
|||||||
@@ -1,3 +1,2 @@
|
|||||||
# .env is stagnet1, so there are no overrides required
|
# .env is stagnet1, so there are no overrides required
|
||||||
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz","STAGNET1":"https://stagnet1.explorer.vega.xyz"}'
|
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz","STAGNET1":"https://stagnet1.explorer.vega.xyz"}'
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ NX_VEGA_GOVERNANCE_URL=https://governance.fairground.wtf
|
|||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||||
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
||||||
NX_VEGA_CONSOLE_URL=https://console.fairground.wtf
|
NX_VEGA_CONSOLE_URL=https://console.fairground.wtf
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
|
||||||
|
|
||||||
NX_TENDERMINT_URL=https://tm.be.testnet.vega.xyz
|
NX_TENDERMINT_URL=https://tm.be.testnet.vega.xyz
|
||||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.testnet.vega.xyz/websocket
|
NX_TENDERMINT_WEBSOCKET_URL=wss://be.testnet.vega.xyz/websocket
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ NX_BLOCK_EXPLORER=https://be.validators-testnet.vega.rocks/rest
|
|||||||
NX_VEGA_GOVERNANCE_URL=https://governance.validators-testnet.vega.rocks
|
NX_VEGA_GOVERNANCE_URL=https://governance.validators-testnet.vega.rocks
|
||||||
NX_VEGA_EXPLORER_URL=https://explorer.validators-testnet.vega.rocks/
|
NX_VEGA_EXPLORER_URL=https://explorer.validators-testnet.vega.rocks/
|
||||||
NX_VEGA_CONSOLE_URL=https://trading.validators-testnet.vega.rocks/
|
NX_VEGA_CONSOLE_URL=https://trading.validators-testnet.vega.rocks/
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
|
||||||
|
|
||||||
NX_TENDERMINT_URL=https://tm.be.validators-testnet.vega.rocks
|
NX_TENDERMINT_URL=https://tm.be.validators-testnet.vega.rocks
|
||||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.xyz/websocket
|
NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.xyz/websocket
|
||||||
|
|||||||
@@ -5,5 +5,4 @@ NX_VEGA_ENV=CUSTOM
|
|||||||
NX_BLOCK_EXPLORER=
|
NX_BLOCK_EXPLORER=
|
||||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
|
||||||
NX_VEGA_EXPLORER_URL=/
|
NX_VEGA_EXPLORER_URL=/
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
|
||||||
@@ -77,7 +77,7 @@
|
|||||||
"executor": "nx:run-commands",
|
"executor": "nx:run-commands",
|
||||||
"options": {
|
"options": {
|
||||||
"commands": [
|
"commands": [
|
||||||
"npx openapi-typescript https://raw.githubusercontent.com/vegaprotocol/documentation/main/specs/v0.72.3/blockexplorer.openapi.json --output apps/explorer/src/types/explorer.d.ts --immutable-types"
|
"npx openapi-typescript https://raw.githubusercontent.com/vegaprotocol/documentation/spec-update-v0.72.0-preview.2/specs/v0.72.0-preview.2/blockexplorer.openapi.json --output apps/explorer/src/types/explorer.d.ts --immutable-types"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
fragment ExplorerStopOrderFields on StopOrder {
|
|
||||||
id
|
|
||||||
status
|
|
||||||
createdAt
|
|
||||||
trigger {
|
|
||||||
... on StopOrderPrice {
|
|
||||||
price
|
|
||||||
}
|
|
||||||
... on StopOrderTrailingPercentOffset {
|
|
||||||
trailingPercentOffset
|
|
||||||
}
|
|
||||||
}
|
|
||||||
createdAt
|
|
||||||
ocoLinkId
|
|
||||||
triggerDirection
|
|
||||||
order {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
query ExplorerStopOrder($stopOrderId: ID!) {
|
|
||||||
stopOrder(id: $stopOrderId) {
|
|
||||||
...ExplorerStopOrderFields
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
import * as Types from '@vegaprotocol/types';
|
|
||||||
|
|
||||||
import { gql } from '@apollo/client';
|
|
||||||
import * as Apollo from '@apollo/client';
|
|
||||||
const defaultOptions = {} as const;
|
|
||||||
export type ExplorerStopOrderFieldsFragment = { __typename?: 'StopOrder', id: string, status: Types.StopOrderStatus, createdAt: any, ocoLinkId?: string | null, triggerDirection: Types.StopOrderTriggerDirection, trigger: { __typename?: 'StopOrderPrice', price: string } | { __typename?: 'StopOrderTrailingPercentOffset', trailingPercentOffset: string }, order?: { __typename?: 'Order', id: string } | null };
|
|
||||||
|
|
||||||
export type ExplorerStopOrderQueryVariables = Types.Exact<{
|
|
||||||
stopOrderId: Types.Scalars['ID'];
|
|
||||||
}>;
|
|
||||||
|
|
||||||
|
|
||||||
export type ExplorerStopOrderQuery = { __typename?: 'Query', stopOrder?: { __typename?: 'StopOrder', id: string, status: Types.StopOrderStatus, createdAt: any, ocoLinkId?: string | null, triggerDirection: Types.StopOrderTriggerDirection, trigger: { __typename?: 'StopOrderPrice', price: string } | { __typename?: 'StopOrderTrailingPercentOffset', trailingPercentOffset: string }, order?: { __typename?: 'Order', id: string } | null } | null };
|
|
||||||
|
|
||||||
export const ExplorerStopOrderFieldsFragmentDoc = gql`
|
|
||||||
fragment ExplorerStopOrderFields on StopOrder {
|
|
||||||
id
|
|
||||||
status
|
|
||||||
createdAt
|
|
||||||
trigger {
|
|
||||||
... on StopOrderPrice {
|
|
||||||
price
|
|
||||||
}
|
|
||||||
... on StopOrderTrailingPercentOffset {
|
|
||||||
trailingPercentOffset
|
|
||||||
}
|
|
||||||
}
|
|
||||||
createdAt
|
|
||||||
ocoLinkId
|
|
||||||
triggerDirection
|
|
||||||
order {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
export const ExplorerStopOrderDocument = gql`
|
|
||||||
query ExplorerStopOrder($stopOrderId: ID!) {
|
|
||||||
stopOrder(id: $stopOrderId) {
|
|
||||||
...ExplorerStopOrderFields
|
|
||||||
}
|
|
||||||
}
|
|
||||||
${ExplorerStopOrderFieldsFragmentDoc}`;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* __useExplorerStopOrderQuery__
|
|
||||||
*
|
|
||||||
* To run a query within a React component, call `useExplorerStopOrderQuery` and pass it any options that fit your needs.
|
|
||||||
* When your component renders, `useExplorerStopOrderQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
|
||||||
* you can use to render your UI.
|
|
||||||
*
|
|
||||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* const { data, loading, error } = useExplorerStopOrderQuery({
|
|
||||||
* variables: {
|
|
||||||
* stopOrderId: // value for 'stopOrderId'
|
|
||||||
* },
|
|
||||||
* });
|
|
||||||
*/
|
|
||||||
export function useExplorerStopOrderQuery(baseOptions: Apollo.QueryHookOptions<ExplorerStopOrderQuery, ExplorerStopOrderQueryVariables>) {
|
|
||||||
const options = {...defaultOptions, ...baseOptions}
|
|
||||||
return Apollo.useQuery<ExplorerStopOrderQuery, ExplorerStopOrderQueryVariables>(ExplorerStopOrderDocument, options);
|
|
||||||
}
|
|
||||||
export function useExplorerStopOrderLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ExplorerStopOrderQuery, ExplorerStopOrderQueryVariables>) {
|
|
||||||
const options = {...defaultOptions, ...baseOptions}
|
|
||||||
return Apollo.useLazyQuery<ExplorerStopOrderQuery, ExplorerStopOrderQueryVariables>(ExplorerStopOrderDocument, options);
|
|
||||||
}
|
|
||||||
export type ExplorerStopOrderQueryHookResult = ReturnType<typeof useExplorerStopOrderQuery>;
|
|
||||||
export type ExplorerStopOrderLazyQueryHookResult = ReturnType<typeof useExplorerStopOrderLazyQuery>;
|
|
||||||
export type ExplorerStopOrderQueryResult = Apollo.QueryResult<ExplorerStopOrderQuery, ExplorerStopOrderQueryVariables>;
|
|
||||||
@@ -33,7 +33,7 @@ describe('Order TX Summary component', () => {
|
|||||||
expect(res.queryByTestId('order-summary')).not.toBeInTheDocument();
|
expect(res.queryByTestId('order-summary')).not.toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Renders "Market Price" if the order passed lacks a price', () => {
|
it('Renders nothing if the order passed lacks a price', () => {
|
||||||
const o: Order = {
|
const o: Order = {
|
||||||
marketId: '123',
|
marketId: '123',
|
||||||
side: 'SIDE_BUY',
|
side: 'SIDE_BUY',
|
||||||
@@ -41,7 +41,7 @@ describe('Order TX Summary component', () => {
|
|||||||
size: '10',
|
size: '10',
|
||||||
};
|
};
|
||||||
const res = renderComponent(o);
|
const res = renderComponent(o);
|
||||||
expect(res.queryByText('Market Price')).toBeInTheDocument();
|
expect(res.queryByTestId('order-summary')).not.toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Renders nothing if the order has an unspecified side', () => {
|
it('Renders nothing if the order has an unspecified side', () => {
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import type { components } from '../../../types/explorer';
|
|||||||
import PriceInMarket from '../price-in-market/price-in-market';
|
import PriceInMarket from '../price-in-market/price-in-market';
|
||||||
import { sideText } from '../order-details/lib/order-labels';
|
import { sideText } from '../order-details/lib/order-labels';
|
||||||
import SizeInMarket from '../size-in-market/size-in-market';
|
import SizeInMarket from '../size-in-market/size-in-market';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
|
||||||
|
|
||||||
export type OrderSummaryProps = {
|
export type OrderSummaryProps = {
|
||||||
order: components['schemas']['v1OrderSubmission'];
|
order: components['schemas']['v1OrderSubmission'];
|
||||||
@@ -21,6 +20,7 @@ const OrderTxSummary = ({ order }: OrderSummaryProps) => {
|
|||||||
if (
|
if (
|
||||||
!order ||
|
!order ||
|
||||||
!order.marketId ||
|
!order.marketId ||
|
||||||
|
!order.price ||
|
||||||
!order.side ||
|
!order.side ||
|
||||||
order.side === 'SIDE_UNSPECIFIED'
|
order.side === 'SIDE_UNSPECIFIED'
|
||||||
) {
|
) {
|
||||||
@@ -36,14 +36,10 @@ const OrderTxSummary = ({ order }: OrderSummaryProps) => {
|
|||||||
'-'
|
'-'
|
||||||
)}
|
)}
|
||||||
<i className="text-xs">@</i>
|
<i className="text-xs">@</i>
|
||||||
{order.price ? (
|
<PriceInMarket
|
||||||
<PriceInMarket
|
marketId={order.marketId}
|
||||||
marketId={order.marketId}
|
price={order.price}
|
||||||
price={order.price}
|
></PriceInMarket>
|
||||||
></PriceInMarket>
|
|
||||||
) : (
|
|
||||||
t('Market Price')
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export const ProposalsTable = ({ data }: ProposalsTableProps) => {
|
|||||||
const { params } = useNetworkParams([
|
const { params } = useNetworkParams([
|
||||||
NetworkParams.governance_proposal_market_requiredMajority,
|
NetworkParams.governance_proposal_market_requiredMajority,
|
||||||
]);
|
]);
|
||||||
const tokenLink = useLinks(DApp.Governance);
|
const tokenLink = useLinks(DApp.Token);
|
||||||
const requiredMajorityPercentage = useMemo(() => {
|
const requiredMajorityPercentage = useMemo(() => {
|
||||||
const requiredMajority =
|
const requiredMajority =
|
||||||
params?.governance_proposal_market_requiredMajority ?? 1;
|
params?.governance_proposal_market_requiredMajority ?? 1;
|
||||||
|
|||||||
@@ -1,139 +0,0 @@
|
|||||||
import { t } from '@vegaprotocol/i18n';
|
|
||||||
import type { components } from '../../../../../types/explorer';
|
|
||||||
import { formatNumberPercentage } from '@vegaprotocol/utils';
|
|
||||||
import BigNumber from 'bignumber.js';
|
|
||||||
import PriceInMarket from '../../../price-in-market/price-in-market';
|
|
||||||
import StopOrderTriggerSummary from './stop-order-trigger';
|
|
||||||
import { Tooltip } from '@vegaprotocol/ui-toolkit';
|
|
||||||
import fromUnixTime from 'date-fns/fromUnixTime';
|
|
||||||
|
|
||||||
const wrapperClasses =
|
|
||||||
'flex-1 max-w-xs items-center border border-vega-light-200 dark:border-vega-dark-150 rounded-md pv-2 ph-5 mb-5';
|
|
||||||
|
|
||||||
export type StopOrderType = 'RisesAbove' | 'FallsBelow' | 'OCO';
|
|
||||||
type V1OrderSetup = components['schemas']['v1StopOrderSetup'];
|
|
||||||
|
|
||||||
interface StopOrderSetupProps extends V1OrderSetup {
|
|
||||||
type: StopOrderType;
|
|
||||||
deterministicId: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getExpiryTypeLabel(
|
|
||||||
expiryStrategy: V1OrderSetup['expiryStrategy']
|
|
||||||
): string {
|
|
||||||
switch (expiryStrategy) {
|
|
||||||
case 'EXPIRY_STRATEGY_CANCELS':
|
|
||||||
return t('Cancels');
|
|
||||||
case 'EXPIRY_STRATEGY_SUBMIT':
|
|
||||||
return t('Submit');
|
|
||||||
}
|
|
||||||
|
|
||||||
return expiryStrategy || t('Unknown');
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ExpiryTriggerProps {
|
|
||||||
trailingPercentOffset?: string;
|
|
||||||
price?: string;
|
|
||||||
marketId?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function ExpiryTrigger({
|
|
||||||
trailingPercentOffset,
|
|
||||||
price,
|
|
||||||
marketId,
|
|
||||||
}: ExpiryTriggerProps) {
|
|
||||||
if (price && marketId) {
|
|
||||||
return <PriceInMarket price={price} marketId={marketId} />;
|
|
||||||
}
|
|
||||||
if (trailingPercentOffset) {
|
|
||||||
return (
|
|
||||||
<span>
|
|
||||||
{formatNumberPercentage(new BigNumber(trailingPercentOffset))}{' '}
|
|
||||||
(trailing)
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getMovePrefix(
|
|
||||||
type: StopOrderType,
|
|
||||||
trailingPercentOffset?: string
|
|
||||||
): string {
|
|
||||||
if (type === 'RisesAbove') {
|
|
||||||
if (trailingPercentOffset) {
|
|
||||||
return '+';
|
|
||||||
} else {
|
|
||||||
return '>';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (trailingPercentOffset) {
|
|
||||||
return '-';
|
|
||||||
} else {
|
|
||||||
return '<';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const TypeLabel = {
|
|
||||||
RisesAbove: t('Rises above ↗'),
|
|
||||||
FallsBelow: t('Falls below ↘'),
|
|
||||||
OCO: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
export const StopOrderSetup = ({
|
|
||||||
type,
|
|
||||||
price,
|
|
||||||
orderSubmission,
|
|
||||||
expiresAt,
|
|
||||||
expiryStrategy,
|
|
||||||
trailingPercentOffset,
|
|
||||||
deterministicId,
|
|
||||||
}: StopOrderSetupProps) => {
|
|
||||||
let d = 'Unknown';
|
|
||||||
try {
|
|
||||||
d = expiresAt
|
|
||||||
? fromUnixTime(parseInt(expiresAt) / 1000000000).toLocaleString()
|
|
||||||
: t('Unknown');
|
|
||||||
} catch (e) {
|
|
||||||
d = t('Unknown');
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={wrapperClasses}>
|
|
||||||
<div className="mb-12 lg:mb-0">
|
|
||||||
<div className="bg-slate-100 text-slate-900 px-6 py-2 md:px-6 flex">
|
|
||||||
<div className="flex-1">
|
|
||||||
<strong className="font-bold mb-1">{TypeLabel[type]} </strong>
|
|
||||||
<p className=" font-xs mb-0">
|
|
||||||
{getMovePrefix(type, trailingPercentOffset)}
|
|
||||||
<ExpiryTrigger
|
|
||||||
trailingPercentOffset={trailingPercentOffset}
|
|
||||||
price={price}
|
|
||||||
marketId={orderSubmission?.marketId}
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{expiresAt && expiryStrategy ? (
|
|
||||||
<div className="flex-1">
|
|
||||||
<strong className="font-bold mb-1">{t('Expiry Type')}</strong>
|
|
||||||
<p className=" font-xs mb-0">
|
|
||||||
<Tooltip description={<span>{d}</span>}>
|
|
||||||
<span>{getExpiryTypeLabel(expiryStrategy)}</span>
|
|
||||||
</Tooltip>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
<StopOrderTriggerSummary
|
|
||||||
id={deterministicId}
|
|
||||||
orderSubmission={orderSubmission}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
import { StopOrderStatus } from '@vegaprotocol/types';
|
|
||||||
import { useExplorerStopOrderQuery } from '../../../order-details/__generated__/StopOrder';
|
|
||||||
import type { ExplorerStopOrderQuery } from '../../../order-details/__generated__/StopOrder';
|
|
||||||
import { t } from '@vegaprotocol/i18n';
|
|
||||||
import { Icon } from '@vegaprotocol/ui-toolkit';
|
|
||||||
import type { IconName } from '@vegaprotocol/ui-toolkit';
|
|
||||||
import OrderTxSummary from '../../../order-summary/order-tx-summary';
|
|
||||||
import type { components } from '../../../../../types/explorer';
|
|
||||||
import type { ApolloError } from '@apollo/client';
|
|
||||||
|
|
||||||
export const StatusLabel: Record<StopOrderStatus, string> = {
|
|
||||||
[StopOrderStatus.STATUS_CANCELLED]: t('Cancelled'),
|
|
||||||
[StopOrderStatus.STATUS_EXPIRED]: t('Expired'),
|
|
||||||
[StopOrderStatus.STATUS_PENDING]: t('Pending'),
|
|
||||||
[StopOrderStatus.STATUS_REJECTED]: t('Rejected'),
|
|
||||||
[StopOrderStatus.STATUS_STOPPED]: t('Stopped'),
|
|
||||||
[StopOrderStatus.STATUS_TRIGGERED]: t('Triggered'),
|
|
||||||
[StopOrderStatus.STATUS_UNSPECIFIED]: t('Status unknown'),
|
|
||||||
};
|
|
||||||
|
|
||||||
export const StatusIcon: Record<StopOrderStatus, IconName> = {
|
|
||||||
[StopOrderStatus.STATUS_CANCELLED]: 'disable',
|
|
||||||
[StopOrderStatus.STATUS_EXPIRED]: 'outdated',
|
|
||||||
[StopOrderStatus.STATUS_PENDING]: 'circle',
|
|
||||||
[StopOrderStatus.STATUS_REJECTED]: 'cross',
|
|
||||||
[StopOrderStatus.STATUS_STOPPED]: 'stop',
|
|
||||||
[StopOrderStatus.STATUS_TRIGGERED]: 'tick',
|
|
||||||
[StopOrderStatus.STATUS_UNSPECIFIED]: 'help',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const StatusMidColor: Record<StopOrderStatus, string> = {
|
|
||||||
[StopOrderStatus.STATUS_CANCELLED]: 'bg-red-100 text-red-900',
|
|
||||||
[StopOrderStatus.STATUS_EXPIRED]: 'bg-red-100 text-red-900',
|
|
||||||
[StopOrderStatus.STATUS_PENDING]: 'bg-yellow-100 text-yellow-900',
|
|
||||||
[StopOrderStatus.STATUS_REJECTED]: 'bg-red-100 text-red-900',
|
|
||||||
[StopOrderStatus.STATUS_STOPPED]: 'bg-red-100 text-red-900',
|
|
||||||
[StopOrderStatus.STATUS_TRIGGERED]: 'bg-green-100 text-green-900',
|
|
||||||
[StopOrderStatus.STATUS_UNSPECIFIED]: 'bg-yellow-100 text-yellow-900',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const StatusBottomColor: Record<StopOrderStatus, string> = {
|
|
||||||
[StopOrderStatus.STATUS_CANCELLED]: 'bg-red-50 text-red-900 line-through',
|
|
||||||
[StopOrderStatus.STATUS_EXPIRED]: 'bg-red-50 text-red-900 line-through',
|
|
||||||
[StopOrderStatus.STATUS_PENDING]: 'bg-yellow-50 text-yellow-900',
|
|
||||||
[StopOrderStatus.STATUS_REJECTED]: 'bg-red-50 text-red-900 line-through',
|
|
||||||
[StopOrderStatus.STATUS_STOPPED]: 'bg-red-50 text-red-900 line-through',
|
|
||||||
[StopOrderStatus.STATUS_TRIGGERED]: 'bg-green-50 text-green-900',
|
|
||||||
[StopOrderStatus.STATUS_UNSPECIFIED]:
|
|
||||||
'bg-yellow-50 text-yellow-900 line-through',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function getStopOrderTriggerStatus(
|
|
||||||
data?: ExplorerStopOrderQuery,
|
|
||||||
error?: ApolloError
|
|
||||||
) {
|
|
||||||
if (data && data.stopOrder) {
|
|
||||||
return data.stopOrder.status;
|
|
||||||
}
|
|
||||||
|
|
||||||
return StopOrderStatus.STATUS_UNSPECIFIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface StopOrderTriggerSummaryProps {
|
|
||||||
id: string;
|
|
||||||
orderSubmission?: components['schemas']['v1OrderSubmission'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
const StopOrderTriggerSummary = ({
|
|
||||||
id,
|
|
||||||
orderSubmission,
|
|
||||||
}: StopOrderTriggerSummaryProps) => {
|
|
||||||
const { data, error } = useExplorerStopOrderQuery({
|
|
||||||
variables: { stopOrderId: id },
|
|
||||||
});
|
|
||||||
|
|
||||||
const status = getStopOrderTriggerStatus(data, error);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div
|
|
||||||
className={`${StatusMidColor[status]} px-3 py-2 md:px-6 flex space-x-4`}
|
|
||||||
>
|
|
||||||
<p className="m-0 p-0 align-top">
|
|
||||||
<Icon
|
|
||||||
size={6}
|
|
||||||
name={StatusIcon[status]}
|
|
||||||
className="inline-block mr-2"
|
|
||||||
/>
|
|
||||||
<span className="align-top">{StatusLabel[status]}</span>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
className={`${StatusBottomColor[status]} px-3 py-2 md:px-6 flex space-x-4`}
|
|
||||||
>
|
|
||||||
{orderSubmission && (
|
|
||||||
<p className="text-vega-grey-400 strike">
|
|
||||||
<OrderTxSummary order={orderSubmission} />
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default StopOrderTriggerSummary;
|
|
||||||
@@ -1,12 +1,10 @@
|
|||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import type { components } from '../../../../../types/explorer';
|
import type { components } from '../../../../../types/explorer';
|
||||||
import { Tooltip } from '@vegaprotocol/ui-toolkit';
|
import { Tooltip } from '@vegaprotocol/ui-toolkit';
|
||||||
import SizeInMarket from '../../../size-in-market/size-in-market';
|
|
||||||
|
|
||||||
export interface TxDetailsOrderIcebergDetailsProps {
|
export interface TxDetailsOrderIcebergDetailsProps {
|
||||||
iceberg: components['schemas']['v1IcebergOpts'];
|
iceberg: components['schemas']['v1IcebergOpts'];
|
||||||
size: components['schemas']['v1OrderSubmission']['size'];
|
size: components['schemas']['v1OrderSubmission']['size'];
|
||||||
marketId?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,7 +28,6 @@ export interface TxDetailsOrderIcebergDetailsProps {
|
|||||||
export const TxOrderIcebergDetails = ({
|
export const TxOrderIcebergDetails = ({
|
||||||
iceberg,
|
iceberg,
|
||||||
size,
|
size,
|
||||||
marketId,
|
|
||||||
}: TxDetailsOrderIcebergDetailsProps) => {
|
}: TxDetailsOrderIcebergDetailsProps) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -39,28 +36,15 @@ export const TxOrderIcebergDetails = ({
|
|||||||
>
|
>
|
||||||
<Tooltip description={t('Iceberg: Minimum visible size')}>
|
<Tooltip description={t('Iceberg: Minimum visible size')}>
|
||||||
<span className="align-bottom text-vega-orange-650">
|
<span className="align-bottom text-vega-orange-650">
|
||||||
{marketId ? (
|
{iceberg.minimumVisibleSize || '-'}
|
||||||
<SizeInMarket
|
|
||||||
size={iceberg.minimumVisibleSize}
|
|
||||||
marketId={marketId}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
iceberg.minimumVisibleSize
|
|
||||||
)}
|
|
||||||
</span>
|
</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip description={t('Iceberg: Total size')}>
|
<Tooltip description={t('Iceberg: Total size')}>
|
||||||
<span className="text-sm text-vega-blue-600 mx-3">
|
<span className="text-sm text-vega-blue-600 mx-3">{size}</span>
|
||||||
{marketId ? <SizeInMarket size={size} marketId={marketId} /> : size}
|
|
||||||
</span>
|
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip description={t('Iceberg: Visible peak')}>
|
<Tooltip description={t('Iceberg: Visible peak')}>
|
||||||
<span className="align-top text-vega-yellow-600">
|
<span className="align-top text-vega-yellow-600">
|
||||||
{marketId ? (
|
{iceberg.peakSize || '-'}
|
||||||
<SizeInMarket size={iceberg.peakSize} marketId={marketId} />
|
|
||||||
) : (
|
|
||||||
iceberg.peakSize
|
|
||||||
)}
|
|
||||||
</span>
|
</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+1
-1
@@ -35,7 +35,7 @@ export const BundleSigners = ({
|
|||||||
tx,
|
tx,
|
||||||
id,
|
id,
|
||||||
}: BundleSignersProps) => {
|
}: BundleSignersProps) => {
|
||||||
const tokenLink = useLinks(DApp.Governance);
|
const tokenLink = useLinks(DApp.Token);
|
||||||
|
|
||||||
const bridgeFunction: BridgeFunction =
|
const bridgeFunction: BridgeFunction =
|
||||||
tx?.changes?.erc20 && 'contractAddress' in tx.changes.erc20
|
tx?.changes?.erc20 && 'contractAddress' in tx.changes.erc20
|
||||||
|
|||||||
@@ -26,11 +26,6 @@ export const sharedHeaderProps = {
|
|||||||
className: 'align-top',
|
className: 'align-top',
|
||||||
};
|
};
|
||||||
|
|
||||||
const Labels: Record<BlockExplorerTransactionResult['type'], string> = {
|
|
||||||
'Stop Orders Submission': 'Stop Order',
|
|
||||||
'Stop Orders Cancellation': 'Cancel Stop Order',
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* These rows are shown for every transaction type, providing a consistent set of rows for the top
|
* These rows are shown for every transaction type, providing a consistent set of rows for the top
|
||||||
* of a transaction details row. The order is relatively arbitrary but felt right - it might need to
|
* of a transaction details row. The order is relatively arbitrary but felt right - it might need to
|
||||||
@@ -49,14 +44,12 @@ export const TxDetailsShared = ({
|
|||||||
const time: string = blockData?.result.block.header.time || '';
|
const time: string = blockData?.result.block.header.time || '';
|
||||||
const height: string = blockData?.result.block.header.height || txData.block;
|
const height: string = blockData?.result.block.header.height || txData.block;
|
||||||
|
|
||||||
const type = Labels[txData.type] || txData.type;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{hideTypeRow === false ? (
|
{hideTypeRow === false ? (
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell {...sharedHeaderProps}>{t('Type')}</TableCell>
|
<TableCell {...sharedHeaderProps}>{t('Type')}</TableCell>
|
||||||
<TableCell>{type}</TableCell>
|
<TableCell>{txData.type}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
) : null}
|
) : null}
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
|
|||||||
@@ -31,8 +31,6 @@ const AccountType: Record<AccountTypes, string> = {
|
|||||||
ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES: 'LP Received Fees',
|
ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES: 'LP Received Fees',
|
||||||
ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS: 'Market Proposers',
|
ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS: 'Market Proposers',
|
||||||
ACCOUNT_TYPE_HOLDING: 'Holding',
|
ACCOUNT_TYPE_HOLDING: 'Holding',
|
||||||
ACCOUNT_TYPE_LIQUIDITY_FEES_BONUS_DISTRIBUTION: 'Bonus Distribution',
|
|
||||||
ACCOUNT_TYPE_LP_LIQUIDITY_FEES: 'LP Liquidity Fees',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
interface TransferParticipantsProps {
|
interface TransferParticipantsProps {
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import { TxDetailsNodeAnnounce } from './tx-node-announce';
|
|||||||
import { TxDetailsStateVariable } from './tx-state-variable-proposal';
|
import { TxDetailsStateVariable } from './tx-state-variable-proposal';
|
||||||
import { TxProposal } from './tx-proposal';
|
import { TxProposal } from './tx-proposal';
|
||||||
import { TxDetailsTransfer } from './tx-transfer';
|
import { TxDetailsTransfer } from './tx-transfer';
|
||||||
import { TxDetailsStopOrderSubmission } from './tx-stop-order-submission';
|
|
||||||
|
|
||||||
interface TxDetailsWrapperProps {
|
interface TxDetailsWrapperProps {
|
||||||
txData: BlockExplorerTransactionResult | undefined;
|
txData: BlockExplorerTransactionResult | undefined;
|
||||||
@@ -117,8 +116,6 @@ function getTransactionComponent(txData?: BlockExplorerTransactionResult) {
|
|||||||
return TxDetailsUndelegate;
|
return TxDetailsUndelegate;
|
||||||
case 'State Variable Proposal':
|
case 'State Variable Proposal':
|
||||||
return TxDetailsStateVariable;
|
return TxDetailsStateVariable;
|
||||||
case 'Stop Orders Submission':
|
|
||||||
return TxDetailsStopOrderSubmission;
|
|
||||||
case 'Transfer Funds':
|
case 'Transfer Funds':
|
||||||
return TxDetailsTransfer;
|
return TxDetailsTransfer;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -81,11 +81,7 @@ export const TxDetailsOrder = ({
|
|||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableCell>{t('Iceberg details')}</TableCell>
|
<TableCell>{t('Iceberg details')}</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<TxOrderIcebergDetails
|
<TxOrderIcebergDetails iceberg={iceberg} size={size} />
|
||||||
iceberg={iceberg}
|
|
||||||
size={size}
|
|
||||||
marketId={marketId}
|
|
||||||
/>
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
) : null}
|
) : null}
|
||||||
|
|||||||
@@ -1,148 +0,0 @@
|
|||||||
import { t } from '@vegaprotocol/i18n';
|
|
||||||
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
|
|
||||||
import { MarketLink } from '../../links/';
|
|
||||||
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
|
|
||||||
import { TxDetailsShared } from './shared/tx-details-shared';
|
|
||||||
import { TableCell, TableRow, TableWithTbody } from '../../table';
|
|
||||||
import {
|
|
||||||
getStopOrderIds,
|
|
||||||
stopOrdersSignatureToDeterministicId,
|
|
||||||
} from '../lib/deterministic-ids';
|
|
||||||
import type { components } from '../../../../types/explorer';
|
|
||||||
import { StopOrderSetup } from './order/stop-order-setup';
|
|
||||||
|
|
||||||
type StopOrderSetup = components['schemas']['v1StopOrderSetup'];
|
|
||||||
|
|
||||||
interface TxDetailsOrderProps {
|
|
||||||
txData: BlockExplorerTransactionResult | undefined;
|
|
||||||
pubKey: string | undefined;
|
|
||||||
blockData: TendermintBlocksResponse | undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getStopTypeLabel(
|
|
||||||
risesAbove: StopOrderSetup | undefined,
|
|
||||||
fallsBelow: StopOrderSetup | undefined
|
|
||||||
): string {
|
|
||||||
if (risesAbove && fallsBelow) {
|
|
||||||
return t('OCO (One Cancels Other)');
|
|
||||||
} else if (fallsBelow) {
|
|
||||||
return t('Falls Below ↘');
|
|
||||||
} else if (risesAbove) {
|
|
||||||
return t('Rises Above ↗');
|
|
||||||
} else {
|
|
||||||
return t('Stop Order');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface StopMarketIdProps {
|
|
||||||
risesAbove: StopOrderSetup | undefined;
|
|
||||||
fallsBelow: StopOrderSetup | undefined;
|
|
||||||
showMarketName?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function StopMarketId({
|
|
||||||
risesAbove,
|
|
||||||
fallsBelow,
|
|
||||||
showMarketName = false,
|
|
||||||
}: StopMarketIdProps) {
|
|
||||||
const raMarketId = risesAbove?.orderSubmission?.marketId;
|
|
||||||
const fbMarketId = fallsBelow?.orderSubmission?.marketId;
|
|
||||||
|
|
||||||
if (raMarketId && fbMarketId) {
|
|
||||||
if (raMarketId === fbMarketId) {
|
|
||||||
return <MarketLink id={raMarketId} showMarketName={showMarketName} />;
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<MarketLink id={raMarketId} showMarketName={showMarketName} />,
|
|
||||||
<MarketLink id={fbMarketId} showMarketName={showMarketName} />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if (raMarketId) {
|
|
||||||
return <MarketLink id={raMarketId} showMarketName={showMarketName} />;
|
|
||||||
} else if (fbMarketId) {
|
|
||||||
return <MarketLink id={fbMarketId} showMarketName={showMarketName} />;
|
|
||||||
} else {
|
|
||||||
return '-';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
export const TxDetailsStopOrderSubmission = ({
|
|
||||||
txData,
|
|
||||||
pubKey,
|
|
||||||
blockData,
|
|
||||||
}: TxDetailsOrderProps) => {
|
|
||||||
if (!txData || !txData.command.stopOrdersSubmission) {
|
|
||||||
return <>{t('Awaiting Block Explorer transaction details')}</>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const tx: components['schemas']['v1StopOrdersSubmission'] =
|
|
||||||
txData.command.stopOrdersSubmission;
|
|
||||||
|
|
||||||
const orderIds = stopOrdersSignatureToDeterministicId(
|
|
||||||
txData?.signature?.value
|
|
||||||
);
|
|
||||||
|
|
||||||
const { risesAboveId, fallsBelowId } = getStopOrderIds(
|
|
||||||
orderIds,
|
|
||||||
tx.risesAbove,
|
|
||||||
tx.fallsBelow
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<TableWithTbody className="mb-8" allowWrap={true}>
|
|
||||||
<TxDetailsShared
|
|
||||||
txData={txData}
|
|
||||||
pubKey={pubKey}
|
|
||||||
blockData={blockData}
|
|
||||||
/>
|
|
||||||
<TableRow modifier="bordered">
|
|
||||||
<TableCell>{t('Market ID')}</TableCell>
|
|
||||||
<TableCell>
|
|
||||||
<StopMarketId
|
|
||||||
risesAbove={tx.risesAbove}
|
|
||||||
fallsBelow={tx.fallsBelow}
|
|
||||||
/>
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
<TableRow modifier="bordered">
|
|
||||||
<TableCell>{t('Market')}</TableCell>
|
|
||||||
<TableCell>
|
|
||||||
<StopMarketId
|
|
||||||
risesAbove={tx.risesAbove}
|
|
||||||
fallsBelow={tx.fallsBelow}
|
|
||||||
showMarketName={true}
|
|
||||||
/>
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
<TableRow modifier="bordered">
|
|
||||||
<TableCell>{t('Trigger')}</TableCell>
|
|
||||||
<TableCell>
|
|
||||||
{getStopTypeLabel(tx.risesAbove, tx.fallsBelow)}
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
</TableWithTbody>
|
|
||||||
<div className="flex gap-2">
|
|
||||||
{tx.fallsBelow && fallsBelowId && (
|
|
||||||
<StopOrderSetup
|
|
||||||
type={'FallsBelow'}
|
|
||||||
{...tx.fallsBelow}
|
|
||||||
deterministicId={fallsBelowId}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{tx.risesAbove && risesAboveId && (
|
|
||||||
<StopOrderSetup
|
|
||||||
type={'RisesAbove'}
|
|
||||||
{...tx.risesAbove}
|
|
||||||
deterministicId={risesAboveId}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -1,8 +1,4 @@
|
|||||||
import {
|
import { hexToString, txSignatureToDeterministicId } from './deterministic-ids';
|
||||||
hexToString,
|
|
||||||
txSignatureToDeterministicId,
|
|
||||||
stopOrdersSignatureToDeterministicId,
|
|
||||||
} from './deterministic-ids';
|
|
||||||
|
|
||||||
it('txSignatureToDeterministicId Turns a known signature in to a known deterministic ID', () => {
|
it('txSignatureToDeterministicId Turns a known signature in to a known deterministic ID', () => {
|
||||||
const signature =
|
const signature =
|
||||||
@@ -24,24 +20,3 @@ it('hexToString encodes a known good value as bytes', () => {
|
|||||||
const res = hexToString(hex);
|
const res = hexToString(hex);
|
||||||
expect(res).toEqual([14, 221]);
|
expect(res).toEqual([14, 221]);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('stopOrdersSignatureToDeterministicId', () => {
|
|
||||||
it('should return empty object if no signature is provided', () => {
|
|
||||||
const result = stopOrdersSignatureToDeterministicId();
|
|
||||||
expect(result.length).toEqual(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return valid deterministic ids if a signature is provided', () => {
|
|
||||||
const signature = 'deadb33f';
|
|
||||||
const result = stopOrdersSignatureToDeterministicId(signature);
|
|
||||||
|
|
||||||
expect(result.length).toEqual(2);
|
|
||||||
|
|
||||||
expect(result[0]).toBe(
|
|
||||||
'4c45b67a8c08cbf1982883a75beaf309bf172461d04bd427623d6cd3d9ab0e91'
|
|
||||||
);
|
|
||||||
expect(result[1]).toBe(
|
|
||||||
'afe7509ff90d8f26339a0ab81e4d3e1fb6c4d44e94419aa5e13ae7659d894da1'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
import type { components } from '../../../../types/explorer';
|
|
||||||
import { sha3_256 } from 'js-sha3';
|
import { sha3_256 } from 'js-sha3';
|
||||||
type StopOrderSetup = components['schemas']['v1StopOrderSetup'];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes a string as bytes
|
* Encodes a string as bytes
|
||||||
@@ -39,58 +37,3 @@ export function txSignatureToDeterministicId(signature: string): string {
|
|||||||
|
|
||||||
return hash.hex();
|
return hash.hex();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Given a stop order signature string, returns the deterministic IDs of both potential
|
|
||||||
* Stop Orders. A stop order is not an order per se, but a trigger for an order. The order
|
|
||||||
* created by the stop order will have another ID based on the market event that hit the
|
|
||||||
* trigger, and as such is not deterministic.
|
|
||||||
*
|
|
||||||
* @param signature
|
|
||||||
* @returns string[]
|
|
||||||
*/
|
|
||||||
export function stopOrdersSignatureToDeterministicId(
|
|
||||||
signature?: string
|
|
||||||
): string[] {
|
|
||||||
if (!signature) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
const firstId = txSignatureToDeterministicId(signature);
|
|
||||||
return [firstId, txSignatureToDeterministicId(firstId)];
|
|
||||||
}
|
|
||||||
|
|
||||||
export type stopSignatures = {
|
|
||||||
risesAboveId: string | undefined;
|
|
||||||
fallsBelowId: string | undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* In 0.72.10 the way stop order IDs are determined is a little tricky. It will be stabilised
|
|
||||||
* in a future release.
|
|
||||||
* @param deterministicIds Output of stopORdersSignatureToDeterministicId
|
|
||||||
* @param risesAbove Stop order setup
|
|
||||||
* @param fallsBelow Stop order setup
|
|
||||||
* @returns Object containing the deterministic IDs of the stop orders
|
|
||||||
*/
|
|
||||||
export function getStopOrderIds(
|
|
||||||
deterministicIds: string[],
|
|
||||||
risesAbove: StopOrderSetup | undefined,
|
|
||||||
fallsBelow: StopOrderSetup | undefined
|
|
||||||
) {
|
|
||||||
if (risesAbove && fallsBelow) {
|
|
||||||
return {
|
|
||||||
risesAboveId: deterministicIds[0],
|
|
||||||
fallsBelowId: deterministicIds[1],
|
|
||||||
};
|
|
||||||
} else if (!fallsBelow && risesAbove) {
|
|
||||||
return {
|
|
||||||
risesAboveId: deterministicIds[0],
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
fallsBelowId: deterministicIds[0] || undefined,
|
|
||||||
risesAboveId: deterministicIds[1] || undefined,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ export type FilterOption =
|
|||||||
| 'Protocol Upgrade'
|
| 'Protocol Upgrade'
|
||||||
| 'Register new Node'
|
| 'Register new Node'
|
||||||
| 'State Variable Proposal'
|
| 'State Variable Proposal'
|
||||||
| 'Stop Orders Submission'
|
|
||||||
| 'Stop Orders Cancellation'
|
| 'Stop Orders Cancellation'
|
||||||
| 'Submit Oracle Data'
|
| 'Submit Oracle Data'
|
||||||
| 'Submit Order'
|
| 'Submit Order'
|
||||||
@@ -55,7 +54,6 @@ export const PrimaryFilterOptions: FilterOption[] = [
|
|||||||
'Delegate',
|
'Delegate',
|
||||||
'Liquidity Provision Order',
|
'Liquidity Provision Order',
|
||||||
'Proposal',
|
'Proposal',
|
||||||
'Stop Orders Submission',
|
|
||||||
'Stop Orders Cancellation',
|
'Stop Orders Cancellation',
|
||||||
'Submit Oracle Data',
|
'Submit Oracle Data',
|
||||||
'Submit Order',
|
'Submit Order',
|
||||||
|
|||||||
@@ -50,25 +50,6 @@ const displayString: StringMap = {
|
|||||||
'Stop Orders Cancellation': 'Cancel stop',
|
'Stop Orders Cancellation': 'Cancel stop',
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getLabelForStopOrderType(
|
|
||||||
orderType: string,
|
|
||||||
command: components['schemas']['v1InputData']
|
|
||||||
): string {
|
|
||||||
if (command.stopOrdersSubmission) {
|
|
||||||
if (
|
|
||||||
command.stopOrdersSubmission.risesAbove &&
|
|
||||||
command.stopOrdersSubmission.fallsBelow
|
|
||||||
) {
|
|
||||||
return 'Stop ⇅';
|
|
||||||
} else if (command.stopOrdersSubmission.risesAbove) {
|
|
||||||
return 'Stop ↗';
|
|
||||||
} else if (command.stopOrdersSubmission.fallsBelow) {
|
|
||||||
return 'Stop ↘';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 'Stop';
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getLabelForOrderType(
|
export function getLabelForOrderType(
|
||||||
orderType: string,
|
orderType: string,
|
||||||
command: components['schemas']['v1InputData']
|
command: components['schemas']['v1InputData']
|
||||||
@@ -204,9 +185,6 @@ export const TxOrderType = ({ orderType, command }: TxOrderTypeProps) => {
|
|||||||
} else if (type === 'Order' && command) {
|
} else if (type === 'Order' && command) {
|
||||||
type = getLabelForOrderType(orderType, command);
|
type = getLabelForOrderType(orderType, command);
|
||||||
colours = 'text-white dark-text-white bg-vega-blue dark:bg-vega-blue';
|
colours = 'text-white dark-text-white bg-vega-blue dark:bg-vega-blue';
|
||||||
} else if (type === 'Stop' && command) {
|
|
||||||
type = getLabelForStopOrderType(orderType, command);
|
|
||||||
colours = 'text-white dark-text-white bg-vega-blue dark:bg-vega-blue';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type === 'Vote on Proposal') {
|
if (type === 'Vote on Proposal') {
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export const TxsInfiniteList = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="overflow-scroll">
|
||||||
<table className={className} data-testid="transactions-list">
|
<table className={className} data-testid="transactions-list">
|
||||||
<thead>
|
<thead>
|
||||||
<tr className="w-full mb-3 text-vega-dark-300 uppercase text-left">
|
<tr className="w-full mb-3 text-vega-dark-300 uppercase text-left">
|
||||||
|
|||||||
@@ -1,2 +1 @@
|
|||||||
export * from './network-parameters';
|
export * from './network-parameters';
|
||||||
export * from './structure-network-params';
|
|
||||||
|
|||||||
@@ -1,105 +1,82 @@
|
|||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
import type { NetworkParamsQuery } from '@vegaprotocol/network-parameters';
|
import type { NetworkParamsQuery } from '@vegaprotocol/network-parameters';
|
||||||
import { NetworkParametersTable } from './network-parameters';
|
import { NetworkParametersTable } from './network-parameters';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
|
||||||
|
|
||||||
const renderComponent = (data: NetworkParamsQuery | undefined) => {
|
|
||||||
return render(
|
|
||||||
<MemoryRouter>
|
|
||||||
<NetworkParametersTable data={data} loading={false} />
|
|
||||||
</MemoryRouter>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const mockData = {
|
|
||||||
networkParametersConnection: {
|
|
||||||
edges: [
|
|
||||||
{
|
|
||||||
node: {
|
|
||||||
key: 'spam.protection.delegation.min.tokens',
|
|
||||||
value: '3',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
node: {
|
|
||||||
key: 'spam.protection.voting.min.tokens',
|
|
||||||
value: '1',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
node: {
|
|
||||||
key: 'reward.staking.delegation.minimumValidatorStake',
|
|
||||||
value: '2',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
node: {
|
|
||||||
key: 'reward.asset',
|
|
||||||
value:
|
|
||||||
'fc7fd956078fb1fc9db5c19b88f0874c4299b2a7639ad05a47a28c0aef291b55',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('NetworkParametersTable', () => {
|
describe('NetworkParametersTable', () => {
|
||||||
it('renders headers correctly', () => {
|
it('renders correctly when it has network params', () => {
|
||||||
renderComponent(mockData);
|
const data: NetworkParamsQuery = {
|
||||||
|
networkParametersConnection: {
|
||||||
const allHeadings = screen.getAllByRole('heading');
|
edges: [
|
||||||
expect(
|
{
|
||||||
allHeadings.map((h) => {
|
node: {
|
||||||
return {
|
__typename: 'NetworkParameter',
|
||||||
text: h.textContent,
|
key: 'market.liquidityProvision.minLpStakeQuantumMultiple',
|
||||||
level: h.tagName,
|
value: '1',
|
||||||
testId: h.getAttribute('data-testid'),
|
},
|
||||||
};
|
},
|
||||||
})
|
{
|
||||||
).toEqual([
|
node: {
|
||||||
{
|
__typename: 'NetworkParameter',
|
||||||
text: 'Network Parameters',
|
key: 'market.fee.factors.infrastructureFee',
|
||||||
level: 'H1',
|
value: '0.0005',
|
||||||
testId: 'network-param-header',
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{ text: 'Spam', level: 'H1', testId: 'spam' },
|
};
|
||||||
{ text: 'Protection', level: 'H2', testId: 'spam-protection' },
|
render(<NetworkParametersTable data={data} loading={false} />);
|
||||||
{ text: 'Delegation', level: 'H3', testId: 'spam-protection-delegation' },
|
expect(screen.getByTestId('network-param-header')).toHaveTextContent(
|
||||||
{ text: 'Min', level: 'H4', testId: 'spam-protection-delegation-min' },
|
'Network Parameters'
|
||||||
{ text: 'Voting', level: 'H3', testId: 'spam-protection-voting' },
|
);
|
||||||
{ text: 'Min', level: 'H4', testId: 'spam-protection-voting-min' },
|
const rows = screen.getAllByTestId('key-value-table-row');
|
||||||
{ text: 'Reward', level: 'H1', testId: 'reward' },
|
expect(rows[0].children[0]).toHaveTextContent(
|
||||||
{ text: 'Staking', level: 'H2', testId: 'reward-staking' },
|
'market.fee.factors.infrastructureFee'
|
||||||
{ text: 'Delegation', level: 'H3', testId: 'reward-staking-delegation' },
|
);
|
||||||
]);
|
expect(rows[1].children[0]).toHaveTextContent(
|
||||||
|
'market.liquidityProvision.minLpStakeQuantumMultiple'
|
||||||
|
);
|
||||||
|
expect(rows[0].children[1]).toHaveTextContent('0.0005');
|
||||||
|
expect(rows[1].children[1]).toHaveTextContent('1');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders network params correctly', () => {
|
it('renders the rows in ascending order', () => {
|
||||||
renderComponent(mockData);
|
const data: NetworkParamsQuery = {
|
||||||
|
networkParametersConnection: {
|
||||||
const delegationMinTokensRow = screen.getByTestId(
|
edges: [
|
||||||
'spam-protection-delegation-min-tokens'
|
{
|
||||||
|
node: {
|
||||||
|
__typename: 'NetworkParameter',
|
||||||
|
key: 'market.fee.factors.infrastructureFee',
|
||||||
|
value: '0.0005',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
node: {
|
||||||
|
__typename: 'NetworkParameter',
|
||||||
|
key: 'market.liquidityProvision.minLpStakeQuantumMultiple',
|
||||||
|
value: '1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
render(<NetworkParametersTable data={data} loading={false} />);
|
||||||
|
expect(screen.getByTestId('network-param-header')).toHaveTextContent(
|
||||||
|
'Network Parameters'
|
||||||
);
|
);
|
||||||
expect(delegationMinTokensRow).toHaveTextContent('0.000000000000000003');
|
const rows = screen.getAllByTestId('key-value-table-row');
|
||||||
|
expect(rows[0].children[0]).toHaveTextContent(
|
||||||
const votingMinTokensRow = screen.getByTestId(
|
'market.fee.factors.infrastructureFee'
|
||||||
'spam-protection-voting-min-tokens'
|
|
||||||
);
|
);
|
||||||
expect(votingMinTokensRow).toHaveTextContent('0.000000000000000001');
|
expect(rows[1].children[0]).toHaveTextContent(
|
||||||
|
'market.liquidityProvision.minLpStakeQuantumMultiple'
|
||||||
const minimumValidatorStakeRow = screen.getByTestId(
|
|
||||||
'reward-staking-delegation-minimumValidatorStake'
|
|
||||||
);
|
|
||||||
expect(minimumValidatorStakeRow).toHaveTextContent('2');
|
|
||||||
|
|
||||||
const assetRow = screen.getByTestId('reward-asset');
|
|
||||||
expect(assetRow).toHaveTextContent(
|
|
||||||
'fc7fd956078fb1fc9db5c19b88f0874c4299b2a7639ad05a47a28c0aef291b55'
|
|
||||||
);
|
);
|
||||||
|
expect(rows[0].children[1]).toHaveTextContent('0.0005');
|
||||||
|
expect(rows[1].children[1]).toHaveTextContent('1');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not render rows when is loading', () => {
|
it('does not render rows when is loading', () => {
|
||||||
renderComponent(undefined);
|
render(<NetworkParametersTable data={undefined} loading={true} />);
|
||||||
expect(screen.getByTestId('network-param-header')).toHaveTextContent(
|
expect(screen.getByTestId('network-param-header')).toHaveTextContent(
|
||||||
'Network Parameters'
|
'Network Parameters'
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import startCase from 'lodash/startCase';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import {
|
import {
|
||||||
AsyncRenderer,
|
AsyncRenderer,
|
||||||
|
KeyValueTable,
|
||||||
KeyValueTableRow,
|
KeyValueTableRow,
|
||||||
SyntaxHighlighter,
|
SyntaxHighlighter,
|
||||||
} from '@vegaprotocol/ui-toolkit';
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
@@ -14,12 +12,11 @@ import {
|
|||||||
} from '@vegaprotocol/utils';
|
} from '@vegaprotocol/utils';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import { RouteTitle } from '../../components/route-title';
|
import { RouteTitle } from '../../components/route-title';
|
||||||
|
import orderBy from 'lodash/orderBy';
|
||||||
import { useNetworkParamsQuery } from '@vegaprotocol/network-parameters';
|
import { useNetworkParamsQuery } from '@vegaprotocol/network-parameters';
|
||||||
|
import type { NetworkParamsQuery } from '@vegaprotocol/network-parameters';
|
||||||
import { useScrollToLocation } from '../../hooks/scroll-to-location';
|
import { useScrollToLocation } from '../../hooks/scroll-to-location';
|
||||||
import { useDocumentTitle } from '../../hooks/use-document-title';
|
import { useDocumentTitle } from '../../hooks/use-document-title';
|
||||||
import { structureNetworkParams } from './structure-network-params';
|
|
||||||
import type { NetworkParamsQuery } from '@vegaprotocol/network-parameters';
|
|
||||||
import type { GroupedParams } from './structure-network-params';
|
|
||||||
|
|
||||||
const PERCENTAGE_PARAMS = [
|
const PERCENTAGE_PARAMS = [
|
||||||
'governance.proposal.asset.requiredMajority',
|
'governance.proposal.asset.requiredMajority',
|
||||||
@@ -61,54 +58,6 @@ const BIG_NUMBER_PARAMS = [
|
|||||||
'governance.proposal.updateAsset.minVoterBalance',
|
'governance.proposal.updateAsset.minVoterBalance',
|
||||||
];
|
];
|
||||||
|
|
||||||
export const renderGroupedParams = (
|
|
||||||
group: GroupedParams,
|
|
||||||
level: number,
|
|
||||||
parentKeys: string[] = []
|
|
||||||
) => {
|
|
||||||
const Header = `h${level}` as keyof JSX.IntrinsicElements;
|
|
||||||
const headerStyles = classNames('uppercase font-semibold', {
|
|
||||||
'pt-6 text-3xl underline': level === 1,
|
|
||||||
'pt-3 text-2xl': level === 2,
|
|
||||||
'pt-2 text-lg': level === 3,
|
|
||||||
'pt-2 text-default': level === 4,
|
|
||||||
});
|
|
||||||
|
|
||||||
return Object.entries(group).map(([key, value]) => {
|
|
||||||
const fullPath = [...parentKeys, key].join('.');
|
|
||||||
const isLeafNode = typeof value !== 'object';
|
|
||||||
const id = parentKeys.concat([key]).join('-');
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div key={key}>
|
|
||||||
{!isLeafNode && (
|
|
||||||
<div id={id}>
|
|
||||||
<Link to={`#${id}`}>
|
|
||||||
<Header className={headerStyles} data-testid={id}>
|
|
||||||
{startCase(key)}
|
|
||||||
</Header>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{isLeafNode ? (
|
|
||||||
typeof value === 'string' ? (
|
|
||||||
<div data-testid={id}>
|
|
||||||
<NetworkParameterRow
|
|
||||||
key={fullPath}
|
|
||||||
row={{ key: fullPath, value: value }}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) : null
|
|
||||||
) : (
|
|
||||||
<div className="pb-1">
|
|
||||||
{renderGroupedParams(value, level + 1, [...parentKeys, key])}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const NetworkParameterRow = ({
|
export const NetworkParameterRow = ({
|
||||||
row: { key, value },
|
row: { key, value },
|
||||||
}: {
|
}: {
|
||||||
@@ -128,9 +77,7 @@ export const NetworkParameterRow = ({
|
|||||||
>
|
>
|
||||||
{key}
|
{key}
|
||||||
{isSyntaxRow ? (
|
{isSyntaxRow ? (
|
||||||
<div className="pb-2">
|
<SyntaxHighlighter data={JSON.parse(value)} />
|
||||||
<SyntaxHighlighter data={JSON.parse(value)} />
|
|
||||||
</div>
|
|
||||||
) : isNaN(Number(value)) ? (
|
) : isNaN(Number(value)) ? (
|
||||||
value
|
value
|
||||||
) : BIG_NUMBER_PARAMS.includes(key) ? (
|
) : BIG_NUMBER_PARAMS.includes(key) ? (
|
||||||
@@ -166,12 +113,17 @@ export const NetworkParametersTable = ({
|
|||||||
loading={loading}
|
loading={loading}
|
||||||
error={error}
|
error={error}
|
||||||
render={(data) => {
|
render={(data) => {
|
||||||
const flatParams = removePaginationWrapper(
|
const ascParams = orderBy(
|
||||||
data.networkParametersConnection.edges
|
removePaginationWrapper(data.networkParametersConnection.edges),
|
||||||
|
(param) => param.key,
|
||||||
|
'asc'
|
||||||
);
|
);
|
||||||
const groupedParams = structureNetworkParams(flatParams);
|
|
||||||
return (
|
return (
|
||||||
<div className="-mt-6">{renderGroupedParams(groupedParams, 1)}</div>
|
<KeyValueTable data-testid="parameters">
|
||||||
|
{(ascParams || []).map((row) => (
|
||||||
|
<NetworkParameterRow key={row.key} row={row} />
|
||||||
|
))}
|
||||||
|
</KeyValueTable>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,109 +0,0 @@
|
|||||||
import type { GroupedParams } from './structure-network-params';
|
|
||||||
import {
|
|
||||||
structureParams,
|
|
||||||
sortGroupedParams,
|
|
||||||
structureNetworkParams,
|
|
||||||
} from './structure-network-params';
|
|
||||||
|
|
||||||
describe('structureParams', () => {
|
|
||||||
it('should correctly structure params', () => {
|
|
||||||
const input = [
|
|
||||||
{ key: 'spam.protection.delegation.min.tokens', value: '10' },
|
|
||||||
{ key: 'spam.protection.voting.min.tokens', value: '5' },
|
|
||||||
];
|
|
||||||
const output: GroupedParams = {
|
|
||||||
spam: {
|
|
||||||
protection: {
|
|
||||||
delegation: {
|
|
||||||
min: {
|
|
||||||
tokens: '10',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
voting: {
|
|
||||||
min: {
|
|
||||||
tokens: '5',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
expect(structureParams(input)).toEqual(output);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle top-level keys correctly', () => {
|
|
||||||
const input = [{ key: 'levelOne', value: '10' }];
|
|
||||||
const output = {
|
|
||||||
levelOne: '10',
|
|
||||||
};
|
|
||||||
expect(structureParams(input)).toEqual(output);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('sortGroupedParams', () => {
|
|
||||||
it('should correctly sort grouped params', () => {
|
|
||||||
const input: GroupedParams = {
|
|
||||||
spam: {
|
|
||||||
protection: {
|
|
||||||
delegation: {
|
|
||||||
min: {
|
|
||||||
tokens: '10',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
reward: '50',
|
|
||||||
};
|
|
||||||
const output: GroupedParams = {
|
|
||||||
reward: '50',
|
|
||||||
spam: {
|
|
||||||
protection: {
|
|
||||||
delegation: {
|
|
||||||
min: {
|
|
||||||
tokens: '10',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
expect(sortGroupedParams(input)).toEqual(output);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should handle already sorted keys', () => {
|
|
||||||
const input = {
|
|
||||||
a: '10',
|
|
||||||
b: {
|
|
||||||
c: '5',
|
|
||||||
d: '6',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
expect(sortGroupedParams(input)).toEqual(input);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('structureNetworkParams', () => {
|
|
||||||
it('should structure and sort network params correctly', () => {
|
|
||||||
const input = [
|
|
||||||
{ key: 'spam.protection.delegation.min.tokens', value: '10' },
|
|
||||||
{ key: 'reward.asset', value: '50' },
|
|
||||||
];
|
|
||||||
const output: GroupedParams = {
|
|
||||||
reward: {
|
|
||||||
asset: '50',
|
|
||||||
},
|
|
||||||
spam: {
|
|
||||||
protection: {
|
|
||||||
delegation: {
|
|
||||||
min: {
|
|
||||||
tokens: '10',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
expect(structureNetworkParams(input)).toEqual(output);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return an empty object if no params are provided', () => {
|
|
||||||
expect(structureNetworkParams([])).toEqual({});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
/**
|
|
||||||
* Categorizes and sorts an array of key-value pairs of network params into a nested object structure.
|
|
||||||
*
|
|
||||||
* The function takes an array of network params where keys are dot-delimited
|
|
||||||
* strings representing nested categories (e.g., 'spam.protection.delegation.min.tokens').
|
|
||||||
*
|
|
||||||
* Why this is necessary:
|
|
||||||
* A flat key-value structure wouldn't provide the hierarchical information needed.
|
|
||||||
* Organizing network parameters like this allows the rendering of nested headers
|
|
||||||
* and their corresponding network params.
|
|
||||||
*
|
|
||||||
* It also ensures that items with the minimum amount of nesting are ordered first. This
|
|
||||||
* allows us to render these items first, before more deeply nested items are rendered with
|
|
||||||
* subheaders. This creates a more intuitive UI.
|
|
||||||
*
|
|
||||||
* For example, given the input:
|
|
||||||
* [
|
|
||||||
* { key: 'spam.protection.delegation.min.tokens', value: '10' },
|
|
||||||
* { key: 'spam.protection.voting.min.tokens', value: '5' },
|
|
||||||
* { key: 'reward.staking.delegation.minimumValidatorStake', value: '2' }
|
|
||||||
* { key: 'reward.asset', value: 'fc7fd956078fb1fc9db5c19b88f0874c4299b2a7639ad05a47a28c0aef291b55' }
|
|
||||||
* ]
|
|
||||||
*
|
|
||||||
* The output will be:
|
|
||||||
* {
|
|
||||||
* spam: {
|
|
||||||
* protection: {
|
|
||||||
* delegation: {
|
|
||||||
* min: {
|
|
||||||
* tokens: '10'
|
|
||||||
* }
|
|
||||||
* },
|
|
||||||
* voting: {
|
|
||||||
* min: {
|
|
||||||
* tokens: '5'
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* },
|
|
||||||
* reward: {
|
|
||||||
* asset: 'fc7fd956078fb1fc9db5c19b88f0874c4299b2a7639ad05a47a28c0aef291b55',
|
|
||||||
* staking: {
|
|
||||||
* delegation: {
|
|
||||||
* minimumValidatorStake: '2'
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* @param {Array} params - An array of key-value pairs to categorize and sort.
|
|
||||||
* @returns {GroupedParams} - A nested object that groups the key-value pairs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
export type GroupedParams = {
|
|
||||||
[key: string]: string | GroupedParams;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const structureParams = (
|
|
||||||
params: { key: string; value: string }[]
|
|
||||||
): GroupedParams => {
|
|
||||||
const grouped: GroupedParams = {};
|
|
||||||
|
|
||||||
params.forEach(({ key, value }) => {
|
|
||||||
const parts = key.split('.');
|
|
||||||
let node: GroupedParams = grouped;
|
|
||||||
|
|
||||||
parts.forEach((part, i) => {
|
|
||||||
if (typeof node[part] === 'undefined') {
|
|
||||||
node[part] = i === parts.length - 1 ? value : {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof node[part] === 'object') {
|
|
||||||
node = node[part] as GroupedParams;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return grouped;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const sortGroupedParams = (
|
|
||||||
groupedParams: GroupedParams
|
|
||||||
): GroupedParams => {
|
|
||||||
const sorted: GroupedParams = {};
|
|
||||||
|
|
||||||
// Sort top-level keys first
|
|
||||||
Object.entries(groupedParams).forEach(([key, value]) => {
|
|
||||||
if (typeof value === 'string') {
|
|
||||||
sorted[key] = value;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Object.entries(groupedParams).forEach(([key, value]) => {
|
|
||||||
if (typeof value === 'object') {
|
|
||||||
sorted[key] = sortGroupedParams(value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return sorted;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const structureNetworkParams = (
|
|
||||||
params: { key: string; value: string }[]
|
|
||||||
) => {
|
|
||||||
const grouped = structureParams(params);
|
|
||||||
return sortGroupedParams(grouped);
|
|
||||||
};
|
|
||||||
@@ -1,34 +1,4 @@
|
|||||||
fragment ExplorerOracleDataConnection on OracleSpec {
|
|
||||||
dataConnection {
|
|
||||||
edges {
|
|
||||||
node {
|
|
||||||
externalData {
|
|
||||||
data {
|
|
||||||
signers {
|
|
||||||
signer {
|
|
||||||
... on ETHAddress {
|
|
||||||
address
|
|
||||||
}
|
|
||||||
... on PubKey {
|
|
||||||
key
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data {
|
|
||||||
name
|
|
||||||
value
|
|
||||||
}
|
|
||||||
matchedSpecIds
|
|
||||||
broadcastAt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fragment ExplorerOracleDataSource on OracleSpec {
|
fragment ExplorerOracleDataSource on OracleSpec {
|
||||||
...ExplorerOracleDataConnection
|
|
||||||
dataSourceSpec {
|
dataSourceSpec {
|
||||||
spec {
|
spec {
|
||||||
id
|
id
|
||||||
@@ -64,7 +34,6 @@ fragment ExplorerOracleDataSource on OracleSpec {
|
|||||||
key {
|
key {
|
||||||
name
|
name
|
||||||
type
|
type
|
||||||
numberDecimalPlaces
|
|
||||||
}
|
}
|
||||||
conditions {
|
conditions {
|
||||||
value
|
value
|
||||||
@@ -80,6 +49,38 @@ fragment ExplorerOracleDataSource on OracleSpec {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fragment ExplorerOracleDataConnection on OracleSpec {
|
||||||
|
dataConnection {
|
||||||
|
pageInfo {
|
||||||
|
hasNextPage
|
||||||
|
}
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
externalData {
|
||||||
|
data {
|
||||||
|
signers {
|
||||||
|
signer {
|
||||||
|
... on ETHAddress {
|
||||||
|
address
|
||||||
|
}
|
||||||
|
... on PubKey {
|
||||||
|
key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data {
|
||||||
|
name
|
||||||
|
value
|
||||||
|
}
|
||||||
|
matchedSpecIds
|
||||||
|
broadcastAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
query ExplorerOracleSpecs {
|
query ExplorerOracleSpecs {
|
||||||
oracleSpecsConnection(pagination: { first: 50 }) {
|
oracleSpecsConnection(pagination: { first: 50 }) {
|
||||||
pageInfo {
|
pageInfo {
|
||||||
@@ -96,5 +97,6 @@ query ExplorerOracleSpecs {
|
|||||||
query ExplorerOracleSpecById($id: ID!) {
|
query ExplorerOracleSpecById($id: ID!) {
|
||||||
oracleSpec(oracleSpecId: $id) {
|
oracleSpec(oracleSpecId: $id) {
|
||||||
...ExplorerOracleDataSource
|
...ExplorerOracleDataSource
|
||||||
|
...ExplorerOracleDataConnection
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+41
-38
@@ -3,55 +3,24 @@ import * as Types from '@vegaprotocol/types';
|
|||||||
import { gql } from '@apollo/client';
|
import { gql } from '@apollo/client';
|
||||||
import * as Apollo from '@apollo/client';
|
import * as Apollo from '@apollo/client';
|
||||||
const defaultOptions = {} as const;
|
const defaultOptions = {} as const;
|
||||||
export type ExplorerOracleDataConnectionFragment = { __typename?: 'OracleSpec', dataConnection: { __typename?: 'OracleDataConnection', edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } };
|
export type ExplorerOracleDataSourceFragment = { __typename?: 'OracleSpec', dataSourceSpec: { __typename?: 'ExternalDataSourceSpec', spec: { __typename?: 'DataSourceSpec', id: string, createdAt: any, updatedAt?: any | null, status: Types.DataSourceSpecStatus, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } } } } } };
|
||||||
|
|
||||||
export type ExplorerOracleDataSourceFragment = { __typename?: 'OracleSpec', dataSourceSpec: { __typename?: 'ExternalDataSourceSpec', spec: { __typename?: 'DataSourceSpec', id: string, createdAt: any, updatedAt?: any | null, status: Types.DataSourceSpecStatus, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } } } } }, dataConnection: { __typename?: 'OracleDataConnection', edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } };
|
export type ExplorerOracleDataConnectionFragment = { __typename?: 'OracleSpec', dataConnection: { __typename?: 'OracleDataConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } };
|
||||||
|
|
||||||
export type ExplorerOracleSpecsQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
export type ExplorerOracleSpecsQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||||
|
|
||||||
|
|
||||||
export type ExplorerOracleSpecsQuery = { __typename?: 'Query', oracleSpecsConnection?: { __typename?: 'OracleSpecsConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, edges?: Array<{ __typename?: 'OracleSpecEdge', node: { __typename?: 'OracleSpec', dataSourceSpec: { __typename?: 'ExternalDataSourceSpec', spec: { __typename?: 'DataSourceSpec', id: string, createdAt: any, updatedAt?: any | null, status: Types.DataSourceSpecStatus, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } } } } }, dataConnection: { __typename?: 'OracleDataConnection', edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } } } | null> | null } | null };
|
export type ExplorerOracleSpecsQuery = { __typename?: 'Query', oracleSpecsConnection?: { __typename?: 'OracleSpecsConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, edges?: Array<{ __typename?: 'OracleSpecEdge', node: { __typename?: 'OracleSpec', dataSourceSpec: { __typename?: 'ExternalDataSourceSpec', spec: { __typename?: 'DataSourceSpec', id: string, createdAt: any, updatedAt?: any | null, status: Types.DataSourceSpecStatus, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } } } } } } } | null> | null } | null };
|
||||||
|
|
||||||
export type ExplorerOracleSpecByIdQueryVariables = Types.Exact<{
|
export type ExplorerOracleSpecByIdQueryVariables = Types.Exact<{
|
||||||
id: Types.Scalars['ID'];
|
id: Types.Scalars['ID'];
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type ExplorerOracleSpecByIdQuery = { __typename?: 'Query', oracleSpec?: { __typename?: 'OracleSpec', dataSourceSpec: { __typename?: 'ExternalDataSourceSpec', spec: { __typename?: 'DataSourceSpec', id: string, createdAt: any, updatedAt?: any | null, status: Types.DataSourceSpecStatus, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } } } } }, dataConnection: { __typename?: 'OracleDataConnection', edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } } | null };
|
export type ExplorerOracleSpecByIdQuery = { __typename?: 'Query', oracleSpec?: { __typename?: 'OracleSpec', dataSourceSpec: { __typename?: 'ExternalDataSourceSpec', spec: { __typename?: 'DataSourceSpec', id: string, createdAt: any, updatedAt?: any | null, status: Types.DataSourceSpecStatus, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } } } } }, dataConnection: { __typename?: 'OracleDataConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } } | null };
|
||||||
|
|
||||||
export const ExplorerOracleDataConnectionFragmentDoc = gql`
|
|
||||||
fragment ExplorerOracleDataConnection on OracleSpec {
|
|
||||||
dataConnection {
|
|
||||||
edges {
|
|
||||||
node {
|
|
||||||
externalData {
|
|
||||||
data {
|
|
||||||
signers {
|
|
||||||
signer {
|
|
||||||
... on ETHAddress {
|
|
||||||
address
|
|
||||||
}
|
|
||||||
... on PubKey {
|
|
||||||
key
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data {
|
|
||||||
name
|
|
||||||
value
|
|
||||||
}
|
|
||||||
matchedSpecIds
|
|
||||||
broadcastAt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
export const ExplorerOracleDataSourceFragmentDoc = gql`
|
export const ExplorerOracleDataSourceFragmentDoc = gql`
|
||||||
fragment ExplorerOracleDataSource on OracleSpec {
|
fragment ExplorerOracleDataSource on OracleSpec {
|
||||||
...ExplorerOracleDataConnection
|
|
||||||
dataSourceSpec {
|
dataSourceSpec {
|
||||||
spec {
|
spec {
|
||||||
id
|
id
|
||||||
@@ -87,7 +56,6 @@ export const ExplorerOracleDataSourceFragmentDoc = gql`
|
|||||||
key {
|
key {
|
||||||
name
|
name
|
||||||
type
|
type
|
||||||
numberDecimalPlaces
|
|
||||||
}
|
}
|
||||||
conditions {
|
conditions {
|
||||||
value
|
value
|
||||||
@@ -102,7 +70,40 @@ export const ExplorerOracleDataSourceFragmentDoc = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
${ExplorerOracleDataConnectionFragmentDoc}`;
|
`;
|
||||||
|
export const ExplorerOracleDataConnectionFragmentDoc = gql`
|
||||||
|
fragment ExplorerOracleDataConnection on OracleSpec {
|
||||||
|
dataConnection {
|
||||||
|
pageInfo {
|
||||||
|
hasNextPage
|
||||||
|
}
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
externalData {
|
||||||
|
data {
|
||||||
|
signers {
|
||||||
|
signer {
|
||||||
|
... on ETHAddress {
|
||||||
|
address
|
||||||
|
}
|
||||||
|
... on PubKey {
|
||||||
|
key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data {
|
||||||
|
name
|
||||||
|
value
|
||||||
|
}
|
||||||
|
matchedSpecIds
|
||||||
|
broadcastAt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
export const ExplorerOracleSpecsDocument = gql`
|
export const ExplorerOracleSpecsDocument = gql`
|
||||||
query ExplorerOracleSpecs {
|
query ExplorerOracleSpecs {
|
||||||
oracleSpecsConnection(pagination: {first: 50}) {
|
oracleSpecsConnection(pagination: {first: 50}) {
|
||||||
@@ -148,9 +149,11 @@ export const ExplorerOracleSpecByIdDocument = gql`
|
|||||||
query ExplorerOracleSpecById($id: ID!) {
|
query ExplorerOracleSpecById($id: ID!) {
|
||||||
oracleSpec(oracleSpecId: $id) {
|
oracleSpec(oracleSpecId: $id) {
|
||||||
...ExplorerOracleDataSource
|
...ExplorerOracleDataSource
|
||||||
|
...ExplorerOracleDataConnection
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
${ExplorerOracleDataSourceFragmentDoc}`;
|
${ExplorerOracleDataSourceFragmentDoc}
|
||||||
|
${ExplorerOracleDataConnectionFragmentDoc}`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __useExplorerOracleSpecByIdQuery__
|
* __useExplorerOracleSpecByIdQuery__
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
import { render } from '@testing-library/react';
|
import { render } from '@testing-library/react';
|
||||||
import { OracleData } from './oracle-data';
|
import { OracleData } from './oracle-data';
|
||||||
import { type ExplorerOracleDataConnectionFragment } from '../__generated__/Oracles';
|
import type { ExplorerOracleDataConnectionFragment } from '../__generated__/Oracles';
|
||||||
|
|
||||||
type DataConnection = ExplorerOracleDataConnectionFragment['dataConnection'];
|
function renderComponent(data: ExplorerOracleDataConnectionFragment) {
|
||||||
|
|
||||||
function renderComponent(
|
|
||||||
data: ExplorerOracleDataConnectionFragment['dataConnection']
|
|
||||||
) {
|
|
||||||
return <OracleData data={data} />;
|
return <OracleData data={data} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('Oracle Data view', () => {
|
describe('Oracle Data view', () => {
|
||||||
it('Renders nothing when data is null', () => {
|
it('Renders nothing when data is null', () => {
|
||||||
const res = render(renderComponent(null as unknown as DataConnection));
|
const res = render(
|
||||||
|
renderComponent(null as unknown as ExplorerOracleDataConnectionFragment)
|
||||||
|
);
|
||||||
expect(res.container).toBeEmptyDOMElement();
|
expect(res.container).toBeEmptyDOMElement();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Renders nothing when dataConnection is empty', () => {
|
it('Renders nothing when dataConnection is empty', () => {
|
||||||
const res = render(renderComponent({} as DataConnection));
|
const res = render(
|
||||||
|
renderComponent({} as ExplorerOracleDataConnectionFragment)
|
||||||
|
);
|
||||||
expect(res.container).toBeEmptyDOMElement();
|
expect(res.container).toBeEmptyDOMElement();
|
||||||
});
|
});
|
||||||
it('Renders nothing when dataConnection has no edges', () => {
|
it('Renders nothing when dataConnection has no edges', () => {
|
||||||
@@ -26,7 +26,7 @@ describe('Oracle Data view', () => {
|
|||||||
dataConnection: {
|
dataConnection: {
|
||||||
edges: null,
|
edges: null,
|
||||||
},
|
},
|
||||||
} as DataConnection)
|
} as ExplorerOracleDataConnectionFragment)
|
||||||
);
|
);
|
||||||
expect(res.container).toBeEmptyDOMElement();
|
expect(res.container).toBeEmptyDOMElement();
|
||||||
});
|
});
|
||||||
@@ -37,7 +37,7 @@ describe('Oracle Data view', () => {
|
|||||||
dataConnection: {
|
dataConnection: {
|
||||||
edges: [],
|
edges: [],
|
||||||
},
|
},
|
||||||
} as unknown as DataConnection)
|
} as unknown as ExplorerOracleDataConnectionFragment)
|
||||||
);
|
);
|
||||||
expect(res.container).toBeEmptyDOMElement();
|
expect(res.container).toBeEmptyDOMElement();
|
||||||
});
|
});
|
||||||
@@ -47,18 +47,20 @@ describe('Oracle Data view', () => {
|
|||||||
it('Renders details component when there is data', () => {
|
it('Renders details component when there is data', () => {
|
||||||
const res = render(
|
const res = render(
|
||||||
renderComponent({
|
renderComponent({
|
||||||
edges: [
|
dataConnection: {
|
||||||
{
|
edges: [
|
||||||
node: {
|
{
|
||||||
externalData: {
|
node: {
|
||||||
data: {
|
externalData: {
|
||||||
broadcastAt: '2022-01-01',
|
data: {
|
||||||
|
broadcastAt: '2022-01-01',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
],
|
||||||
],
|
},
|
||||||
} as DataConnection)
|
} as ExplorerOracleDataConnectionFragment)
|
||||||
);
|
);
|
||||||
expect(res.getByText('Broadcast data')).toBeInTheDocument();
|
expect(res.getByText('Broadcast data')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import filter from 'recursive-key-filter';
|
|||||||
import type { ExplorerOracleDataConnectionFragment } from '../__generated__/Oracles';
|
import type { ExplorerOracleDataConnectionFragment } from '../__generated__/Oracles';
|
||||||
|
|
||||||
interface OracleDataTypeProps {
|
interface OracleDataTypeProps {
|
||||||
data: ExplorerOracleDataConnectionFragment['dataConnection'];
|
data: ExplorerOracleDataConnectionFragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -14,7 +14,12 @@ interface OracleDataTypeProps {
|
|||||||
* that Does The Job, rather than because it's good.
|
* that Does The Job, rather than because it's good.
|
||||||
*/
|
*/
|
||||||
export function OracleData({ data }: OracleDataTypeProps) {
|
export function OracleData({ data }: OracleDataTypeProps) {
|
||||||
if (!data || !data.edges?.length || data.edges.length > 1) {
|
if (
|
||||||
|
!data ||
|
||||||
|
!data.dataConnection ||
|
||||||
|
!data.dataConnection.edges?.length ||
|
||||||
|
data.dataConnection.edges.length > 1
|
||||||
|
) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,7 +27,7 @@ export function OracleData({ data }: OracleDataTypeProps) {
|
|||||||
<details data-testid="oracle-data">
|
<details data-testid="oracle-data">
|
||||||
<summary>{t('Broadcast data')}</summary>
|
<summary>{t('Broadcast data')}</summary>
|
||||||
<ul>
|
<ul>
|
||||||
{data.edges.map((d) => {
|
{data.dataConnection.edges.map((d) => {
|
||||||
if (!d) {
|
if (!d) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ export function OracleMarkets({ id }: OracleMarketsProps) {
|
|||||||
const m = markets.find((m) => {
|
const m = markets.find((m) => {
|
||||||
const p = m.tradableInstrument.instrument.product;
|
const p = m.tradableInstrument.instrument.product;
|
||||||
if (
|
if (
|
||||||
p?.dataSourceSpecForSettlementData?.id === id ||
|
p.dataSourceSpecForSettlementData.id === id ||
|
||||||
p?.dataSourceSpecForTradingTermination?.id === id
|
p.dataSourceSpecForTradingTermination.id === id
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -36,9 +36,15 @@ export function OracleMarkets({ id }: OracleMarketsProps) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (m && m.id) {
|
if (m && m.id) {
|
||||||
|
const type =
|
||||||
|
id ===
|
||||||
|
m.tradableInstrument.instrument.product.dataSourceSpecForSettlementData
|
||||||
|
.id
|
||||||
|
? 'Settlement for'
|
||||||
|
: 'Termination for';
|
||||||
return (
|
return (
|
||||||
<TableRow modifier="bordered">
|
<TableRow modifier="bordered">
|
||||||
<TableHeader scope="row">{getLabel(id, m)}</TableHeader>
|
<TableHeader scope="row">{type}</TableHeader>
|
||||||
<TableCell modifier="bordered" data-testid={`m-${m.id}`}>
|
<TableCell modifier="bordered" data-testid={`m-${m.id}`}>
|
||||||
<MarketLink id={m.id} />
|
<MarketLink id={m.id} />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
@@ -55,14 +61,3 @@ export function OracleMarkets({ id }: OracleMarketsProps) {
|
|||||||
</TableRow>
|
</TableRow>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getLabel(
|
|
||||||
id: string,
|
|
||||||
m: ExplorerOracleForMarketsMarketFragment | null
|
|
||||||
): string {
|
|
||||||
const settlementId =
|
|
||||||
m?.tradableInstrument?.instrument?.product?.dataSourceSpecForSettlementData
|
|
||||||
?.id || null;
|
|
||||||
|
|
||||||
return id === settlementId ? 'Settlement for' : 'Termination for';
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export type SourceType =
|
|||||||
interface OracleDetailsProps {
|
interface OracleDetailsProps {
|
||||||
id: string;
|
id: string;
|
||||||
dataSource: ExplorerOracleDataSourceFragment;
|
dataSource: ExplorerOracleDataSourceFragment;
|
||||||
dataConnection: ExplorerOracleDataConnectionFragment['dataConnection'];
|
dataConnection?: ExplorerOracleDataConnectionFragment;
|
||||||
// Defaults to false. Hides the count of 'broadcasts' this oracle has seen
|
// Defaults to false. Hides the count of 'broadcasts' this oracle has seen
|
||||||
showBroadcasts?: boolean;
|
showBroadcasts?: boolean;
|
||||||
}
|
}
|
||||||
@@ -41,7 +41,8 @@ export const OracleDetails = ({
|
|||||||
showBroadcasts = false,
|
showBroadcasts = false,
|
||||||
}: OracleDetailsProps) => {
|
}: OracleDetailsProps) => {
|
||||||
const sourceType = dataSource.dataSourceSpec.spec.data.sourceType;
|
const sourceType = dataSource.dataSourceSpec.spec.data.sourceType;
|
||||||
const reportsCount: number = dataConnection.edges?.length || 0;
|
const reportsCount: number =
|
||||||
|
dataConnection?.dataConnection.edges?.length || 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -34,20 +34,11 @@ const Oracles = () => {
|
|||||||
if (!id) {
|
if (!id) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dataConnection = o?.node.dataConnection;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div id={id} key={id} className="mb-10">
|
||||||
id={id}
|
|
||||||
key={id}
|
|
||||||
className="mb-10"
|
|
||||||
data-testid="oracle-details"
|
|
||||||
>
|
|
||||||
<OracleDetails
|
<OracleDetails
|
||||||
id={id}
|
id={id}
|
||||||
dataSource={o?.node}
|
dataSource={o?.node}
|
||||||
dataConnection={dataConnection}
|
|
||||||
showBroadcasts={false}
|
showBroadcasts={false}
|
||||||
/>
|
/>
|
||||||
<details>
|
<details>
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export const Oracle = () => {
|
|||||||
<OracleDetails
|
<OracleDetails
|
||||||
id={id || ''}
|
id={id || ''}
|
||||||
dataSource={data?.oracleSpec}
|
dataSource={data?.oracleSpec}
|
||||||
dataConnection={data?.oracleSpec.dataConnection}
|
dataConnection={data?.oracleSpec}
|
||||||
showBroadcasts={true}
|
showBroadcasts={true}
|
||||||
/>
|
/>
|
||||||
<details>
|
<details>
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ export const ValidatorsPage = () => {
|
|||||||
const [vegaDialog, setVegaDialog] = useState<boolean>(false);
|
const [vegaDialog, setVegaDialog] = useState<boolean>(false);
|
||||||
const [tmDialog, setTmDialog] = useState<boolean>(false);
|
const [tmDialog, setTmDialog] = useState<boolean>(false);
|
||||||
|
|
||||||
const tokenLink = useLinks(DApp.Governance);
|
const tokenLink = useLinks(DApp.Token);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
+1
-5
@@ -920,8 +920,6 @@ export interface components {
|
|||||||
* - ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES: Per asset reward account for fees received by liquidity providers
|
* - ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES: Per asset reward account for fees received by liquidity providers
|
||||||
* - ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS: Per asset reward account for market proposers when the market goes above some trading threshold
|
* - ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS: Per asset reward account for market proposers when the market goes above some trading threshold
|
||||||
* - ACCOUNT_TYPE_HOLDING: Per asset account for holding in-flight unfilled orders' funds
|
* - ACCOUNT_TYPE_HOLDING: Per asset account for holding in-flight unfilled orders' funds
|
||||||
* - ACCOUNT_TYPE_LP_LIQUIDITY_FEES: Network controlled liquidity provider's account, per market, to hold accrued liquidity fees.
|
|
||||||
* - ACCOUNT_TYPE_LIQUIDITY_FEES_BONUS_DISTRIBUTION: Network controlled liquidity fees bonus distribution account, per market.
|
|
||||||
* @default ACCOUNT_TYPE_UNSPECIFIED
|
* @default ACCOUNT_TYPE_UNSPECIFIED
|
||||||
* @enum {string}
|
* @enum {string}
|
||||||
*/
|
*/
|
||||||
@@ -943,9 +941,7 @@ export interface components {
|
|||||||
| 'ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES'
|
| 'ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES'
|
||||||
| 'ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES'
|
| 'ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES'
|
||||||
| 'ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS'
|
| 'ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS'
|
||||||
| 'ACCOUNT_TYPE_HOLDING'
|
| 'ACCOUNT_TYPE_HOLDING';
|
||||||
| 'ACCOUNT_TYPE_LP_LIQUIDITY_FEES'
|
|
||||||
| 'ACCOUNT_TYPE_LIQUIDITY_FEES_BONUS_DISTRIBUTION';
|
|
||||||
/** Vega representation of an external asset */
|
/** Vega representation of an external asset */
|
||||||
readonly vegaAssetDetails: {
|
readonly vegaAssetDetails: {
|
||||||
/** @description Vega built-in asset. */
|
/** @description Vega built-in asset. */
|
||||||
|
|||||||
@@ -14,18 +14,12 @@ NX_ETH_LOCAL_PROVIDER_URL=http://localhost:8545/
|
|||||||
NX_VEGA_WALLET_URL=http://localhost:1789
|
NX_VEGA_WALLET_URL=http://localhost:1789
|
||||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
|
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
|
||||||
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
|
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
|
||||||
|
|
||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
|
||||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||||
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||||
NX_VEGA_REST_URL=http://localhost:3008/api/v2/
|
NX_VEGA_REST_URL=http://localhost:3008/api/v2/
|
||||||
NX_SUCCESSOR_MARKETS=true
|
NX_SUCCESSOR_MARKETS=true
|
||||||
|
|
||||||
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
|
||||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
|
||||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/pl/firefox/addon/vega-wallet
|
|
||||||
|
|
||||||
#Test configuration variables
|
#Test configuration variables
|
||||||
CYPRESS_FAIRGROUND=false
|
CYPRESS_FAIRGROUND=false
|
||||||
CYPRESS_VEGA_URL=http://localhost:3008/graphql
|
CYPRESS_VEGA_URL=http://localhost:3008/graphql
|
||||||
|
|||||||
@@ -3,4 +3,3 @@ NX_VEGA_ENV=DEVNET
|
|||||||
NX_VEGA_URL=https://api.n04.d.vega.xyz/graphql
|
NX_VEGA_URL=https://api.n04.d.vega.xyz/graphql
|
||||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
|
||||||
|
|||||||
@@ -3,4 +3,3 @@ NX_VEGA_ENV=MAINNET
|
|||||||
NX_VEGA_URL=https://api.vega.community/graphql
|
NX_VEGA_URL=https://api.vega.community/graphql
|
||||||
NX_ETHEREUM_PROVIDER_URL=https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
NX_ETHEREUM_PROVIDER_URL=https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||||
NX_ETHERSCAN_URL=https://etherscan.io
|
NX_ETHERSCAN_URL=https://etherscan.io
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
|
||||||
|
|||||||
@@ -3,4 +3,3 @@ NX_VEGA_ENV=TESTNET
|
|||||||
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
|
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
|
||||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
|
||||||
|
|||||||
@@ -19,22 +19,7 @@ export const upgradeProposalsData = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
node: {
|
node: {
|
||||||
upgradeBlockHeight: '10001',
|
upgradeBlockHeight: '1955065',
|
||||||
vegaReleaseTag: 'v0.71.0+dev-12156-bca1d57e',
|
|
||||||
approvers: [
|
|
||||||
'02a6531716b7a6d82779b7793c3ad2fcb47290ea2ff0912c56f61219bd9675ff',
|
|
||||||
'121934387281812a2d5e6913e5d57c0f85a8f169e2752347ee2e23b52d46623c',
|
|
||||||
'65c80e2f5f84e2109eec30810f137ba04cbbecaba8f27706c146cc6c6f90db29',
|
|
||||||
'bd6339d2428c79ac3bc9011771236d17bac92bcb1806423388d52fb440043aef',
|
|
||||||
],
|
|
||||||
status: 'PROTOCOL_UPGRADE_PROPOSAL_STATUS_APPROVED',
|
|
||||||
__typename: 'ProtocolUpgradeProposal',
|
|
||||||
},
|
|
||||||
__typename: 'ProtocolUpgradeProposalEdge',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
node: {
|
|
||||||
upgradeBlockHeight: '20',
|
|
||||||
vegaReleaseTag: 'v0.71.0+dev-12156-bca1d57e',
|
vegaReleaseTag: 'v0.71.0+dev-12156-bca1d57e',
|
||||||
approvers: [
|
approvers: [
|
||||||
'02a6531716b7a6d82779b7793c3ad2fcb47290ea2ff0912c56f61219bd9675ff',
|
'02a6531716b7a6d82779b7793c3ad2fcb47290ea2ff0912c56f61219bd9675ff',
|
||||||
|
|||||||
@@ -11,9 +11,6 @@ import {
|
|||||||
getDateFormatForSpecifiedDays,
|
getDateFormatForSpecifiedDays,
|
||||||
getProposalFromTitle,
|
getProposalFromTitle,
|
||||||
getProposalInformationFromTable,
|
getProposalInformationFromTable,
|
||||||
goToMakeNewProposal,
|
|
||||||
governanceProposalType,
|
|
||||||
longProposalDescription,
|
|
||||||
proposalChangeType,
|
proposalChangeType,
|
||||||
submitUniqueRawProposal,
|
submitUniqueRawProposal,
|
||||||
validateProposalDetailsDiff,
|
validateProposalDetailsDiff,
|
||||||
@@ -34,20 +31,20 @@ import { formatDateWithLocalTimezone } from '@vegaprotocol/utils';
|
|||||||
import { createSuccessorMarketProposalTxBody } from '../../support/proposal.functions';
|
import { createSuccessorMarketProposalTxBody } from '../../support/proposal.functions';
|
||||||
|
|
||||||
const proposalListItem = '[data-testid="proposals-list-item"]';
|
const proposalListItem = '[data-testid="proposals-list-item"]';
|
||||||
const participationNotMet = 'token-participation-not-met';
|
const proposalVoteProgressForPercentage =
|
||||||
const voteStatus = 'vote-status';
|
'vote-progress-indicator-percentage-for';
|
||||||
const voteMajorityNotMet = 'token-majority-not-met';
|
const proposalVoteProgressAgainstPercentage =
|
||||||
const numberOfVotesFor = 'num-votes-for';
|
'vote-progress-indicator-percentage-against';
|
||||||
const votesForPercentage = 'votes-for-percentage';
|
const proposalVoteProgressForTokens = 'vote-progress-indicator-tokens-for';
|
||||||
const numberOfVotesAgainst = 'num-votes-against';
|
const proposalVoteProgressAgainstTokens =
|
||||||
const votesAgainstPercentage = 'votes-against-percentage';
|
'vote-progress-indicator-tokens-against';
|
||||||
const totalVotedNumber = 'total-voted';
|
|
||||||
const totalVotedPercentage = 'total-voted-percentage';
|
|
||||||
const changeVoteButton = 'change-vote-button';
|
const changeVoteButton = 'change-vote-button';
|
||||||
const proposalDetailsTitle = 'proposal-title';
|
const proposalDetailsTitle = 'proposal-title';
|
||||||
const proposalDetailsDescription = 'proposal-description';
|
const proposalDetailsDescription = 'proposal-description';
|
||||||
const openProposals = 'open-proposals';
|
const openProposals = 'open-proposals';
|
||||||
const viewProposalButton = 'view-proposal-btn';
|
const viewProposalButton = 'view-proposal-btn';
|
||||||
|
const proposalDescriptionToggle = 'proposal-description-toggle';
|
||||||
|
const voteBreakdownToggle = 'vote-breakdown-toggle';
|
||||||
const proposalTermsToggle = 'proposal-json-toggle';
|
const proposalTermsToggle = 'proposal-json-toggle';
|
||||||
const marketDataToggle = 'proposal-market-data-toggle';
|
const marketDataToggle = 'proposal-market-data-toggle';
|
||||||
|
|
||||||
@@ -74,13 +71,10 @@ describe(
|
|||||||
|
|
||||||
// 3001-VOTE-050 3001-VOTE-054 3001-VOTE-055 3002-PROP-019
|
// 3001-VOTE-050 3001-VOTE-054 3001-VOTE-055 3002-PROP-019
|
||||||
it('Newly created raw proposal details - shows proposal title and full description', function () {
|
it('Newly created raw proposal details - shows proposal title and full description', function () {
|
||||||
const proposalDetails = longProposalDescription;
|
const proposalDescription =
|
||||||
|
'I propose that everyone evaluate the following IPFS document and vote Yes if they agree. bafybeigwwctpv37xdcwacqxvekr6e4kaemqsrv34em6glkbiceo3fcy4si';
|
||||||
|
|
||||||
goToMakeNewProposal(governanceProposalType.RAW);
|
createRawProposal();
|
||||||
submitUniqueRawProposal({
|
|
||||||
proposalTitle: 'raw proposal with long description',
|
|
||||||
proposalDescription: proposalDetails,
|
|
||||||
});
|
|
||||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||||
cy.getByTestId(openProposals).within(() => {
|
cy.getByTestId(openProposals).within(() => {
|
||||||
getProposalFromTitle(rawProposal.rationale.title).within(() => {
|
getProposalFromTitle(rawProposal.rationale.title).within(() => {
|
||||||
@@ -91,17 +85,12 @@ describe(
|
|||||||
'contain.text',
|
'contain.text',
|
||||||
rawProposal.rationale.title
|
rawProposal.rationale.title
|
||||||
);
|
);
|
||||||
|
cy.getByTestId(proposalDescriptionToggle).click();
|
||||||
|
cy.getByTestId('proposal-description-toggle');
|
||||||
|
cy.getByTestId(proposalDetailsDescription)
|
||||||
|
.find('p')
|
||||||
|
.should('have.text', proposalDescription);
|
||||||
});
|
});
|
||||||
cy.getByTestId(proposalDetailsDescription).within(() => {
|
|
||||||
cy.get('p').should('not.have.text', 'Hyperlink text');
|
|
||||||
cy.getByTestId('show-more-btn').click();
|
|
||||||
cy.get('p')
|
|
||||||
.invoke('text')
|
|
||||||
.should('have.have.length', 2194) // Full description is displayed
|
|
||||||
.and('contain', 'Hyperlink text');
|
|
||||||
cy.get('a').should('have.attr', 'href');
|
|
||||||
});
|
|
||||||
|
|
||||||
// 3001-VOTE-008
|
// 3001-VOTE-008
|
||||||
getProposalInformationFromTable('ID')
|
getProposalInformationFromTable('ID')
|
||||||
.invoke('text')
|
.invoke('text')
|
||||||
@@ -151,32 +140,29 @@ describe(
|
|||||||
// 3001-VOTE-037
|
// 3001-VOTE-037
|
||||||
// 3001-VOTE-040
|
// 3001-VOTE-040
|
||||||
// 3001-VOTE-067
|
// 3001-VOTE-067
|
||||||
// 3001-VOTE-023
|
|
||||||
createRawProposal();
|
createRawProposal();
|
||||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||||
getProposalFromTitle(rawProposal.rationale.title).within(() =>
|
getProposalFromTitle(rawProposal.rationale.title).within(() =>
|
||||||
cy.getByTestId(viewProposalButton).click()
|
cy.getByTestId(viewProposalButton).click()
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
cy.getByTestId(participationNotMet).should(
|
cy.contains('Participation: Not Met 0.00 0.00%(0.00% Required)').should(
|
||||||
'have.text',
|
'be.visible'
|
||||||
'0.000000000000000000000015% participation threshold not met'
|
|
||||||
);
|
|
||||||
cy.getByTestId(voteMajorityNotMet).should(
|
|
||||||
'have.text',
|
|
||||||
'66% majority threshold not met'
|
|
||||||
);
|
|
||||||
cy.getByTestId(voteStatus).should(
|
|
||||||
'have.text',
|
|
||||||
'Currently expected to fail'
|
|
||||||
);
|
);
|
||||||
|
cy.getByTestId(voteBreakdownToggle).click();
|
||||||
|
getProposalInformationFromTable('Expected to pass')
|
||||||
|
.contains('👎')
|
||||||
|
.should('be.visible');
|
||||||
// 3001-VOTE-062
|
// 3001-VOTE-062
|
||||||
// 3001-VOTE-040
|
// 3001-VOTE-040
|
||||||
// 3001-VOTE-070
|
// 3001-VOTE-070
|
||||||
|
getProposalInformationFromTable('Token majority met')
|
||||||
|
.contains('👎')
|
||||||
|
.should('be.visible');
|
||||||
// 3001-VOTE-068
|
// 3001-VOTE-068
|
||||||
cy.getByTestId(numberOfVotesFor).should('have.text', '0.0M');
|
getProposalInformationFromTable('Token participation met')
|
||||||
cy.getByTestId(numberOfVotesAgainst).should('have.text', '0.0M');
|
.contains('👎')
|
||||||
cy.getByTestId(totalVotedNumber).should('have.text', '0.0M');
|
.should('be.visible');
|
||||||
});
|
});
|
||||||
|
|
||||||
// 3001-VOTE-080 3001-VOTE-090 3001-VOTE-069 3001-VOTE-072 3001-VOTE-073
|
// 3001-VOTE-080 3001-VOTE-090 3001-VOTE-069 3001-VOTE-072 3001-VOTE-073
|
||||||
@@ -201,16 +187,43 @@ describe(
|
|||||||
.contains(votedDate)
|
.contains(votedDate)
|
||||||
.should('be.visible');
|
.should('be.visible');
|
||||||
});
|
});
|
||||||
cy.getByTestId(votesForPercentage) // 3001-VOTE-072
|
cy.getByTestId(proposalVoteProgressForPercentage) // 3001-VOTE-072
|
||||||
.should('have.text', '100%');
|
.contains('100.00%')
|
||||||
cy.getByTestId(votesAgainstPercentage).should('have.text', '0%');
|
.and('be.visible');
|
||||||
cy.getByTestId('token-majority-progress')
|
cy.getByTestId(proposalVoteProgressAgainstPercentage)
|
||||||
.should('have.attr', 'style')
|
.contains('0.00%')
|
||||||
.and('eq', 'width: 100%;'); // 3001-VOTE-024
|
.and('be.visible');
|
||||||
|
cy.getByTestId(proposalVoteProgressForTokens)
|
||||||
|
.contains('1.00')
|
||||||
|
.and('be.visible');
|
||||||
|
cy.getByTestId(proposalVoteProgressAgainstTokens)
|
||||||
|
.contains('0.00')
|
||||||
|
.and('be.visible');
|
||||||
|
cy.getByTestId(voteBreakdownToggle).click();
|
||||||
|
getProposalInformationFromTable('Tokens for proposal')
|
||||||
|
.should('have.text', (1).toFixed(2))
|
||||||
|
.and('be.visible');
|
||||||
|
getProposalInformationFromTable('Tokens against proposal')
|
||||||
|
.should('have.text', '0.00')
|
||||||
|
.and('be.visible');
|
||||||
|
// 3001-VOTE-061
|
||||||
|
getProposalInformationFromTable('Participation required')
|
||||||
|
.contains('0.00%')
|
||||||
|
.should('be.visible');
|
||||||
|
// 3001-VOTE-066
|
||||||
|
getProposalInformationFromTable('Majority Required') // 3001-VOTE-073
|
||||||
|
.contains(`${(66).toFixed(2)}%`)
|
||||||
|
.should('be.visible');
|
||||||
|
getProposalInformationFromTable('Number of voting parties')
|
||||||
|
.should('have.text', '1')
|
||||||
|
.and('be.visible');
|
||||||
cy.getByTestId(changeVoteButton).should('be.visible').click();
|
cy.getByTestId(changeVoteButton).should('be.visible').click();
|
||||||
voteForProposal('for');
|
voteForProposal('for');
|
||||||
// 3001-VOTE-064
|
// 3001-VOTE-064
|
||||||
cy.getByTestId('user-voted-yes').should('exist');
|
cy.getByTestId('user-voted-yes').should('exist');
|
||||||
|
getProposalInformationFromTable('Tokens for proposal')
|
||||||
|
.should('have.text', (1).toFixed(2))
|
||||||
|
.and('be.visible');
|
||||||
navigateTo(navigation.proposals);
|
navigateTo(navigation.proposals);
|
||||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||||
getProposalFromTitle(rawProposal.rationale.title).within(() => {
|
getProposalFromTitle(rawProposal.rationale.title).within(() => {
|
||||||
@@ -221,7 +234,16 @@ describe(
|
|||||||
});
|
});
|
||||||
cy.getByTestId(changeVoteButton).should('be.visible').click();
|
cy.getByTestId(changeVoteButton).should('be.visible').click();
|
||||||
voteForProposal('against');
|
voteForProposal('against');
|
||||||
cy.getByTestId(votesAgainstPercentage).should('have.text', '100%');
|
cy.getByTestId(proposalVoteProgressAgainstPercentage)
|
||||||
|
.contains('100.00%')
|
||||||
|
.and('be.visible');
|
||||||
|
cy.getByTestId(voteBreakdownToggle).click();
|
||||||
|
getProposalInformationFromTable('Tokens against proposal')
|
||||||
|
.should('have.text', (1).toFixed(2))
|
||||||
|
.and('be.visible');
|
||||||
|
getProposalInformationFromTable('Number of voting parties')
|
||||||
|
.should('have.text', '1')
|
||||||
|
.and('be.visible');
|
||||||
navigateTo(navigation.proposals);
|
navigateTo(navigation.proposals);
|
||||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||||
getProposalFromTitle(rawProposal.rationale.title).within(() => {
|
getProposalFromTitle(rawProposal.rationale.title).within(() => {
|
||||||
@@ -233,7 +255,6 @@ describe(
|
|||||||
|
|
||||||
// 3001-VOTE-042, 3001-VOTE-057, 3001-VOTE-058, 3001-VOTE-059, 3001-VOTE-060
|
// 3001-VOTE-042, 3001-VOTE-057, 3001-VOTE-058, 3001-VOTE-059, 3001-VOTE-060
|
||||||
it('Newly created proposal details - ability to increase associated tokens - by voting again after association', function () {
|
it('Newly created proposal details - ability to increase associated tokens - by voting again after association', function () {
|
||||||
ensureSpecifiedUnstakedTokensAreAssociated('1');
|
|
||||||
vegaWalletSetSpecifiedApprovalAmount('1000');
|
vegaWalletSetSpecifiedApprovalAmount('1000');
|
||||||
createRawProposal();
|
createRawProposal();
|
||||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||||
@@ -244,28 +265,69 @@ describe(
|
|||||||
voteForProposal('for');
|
voteForProposal('for');
|
||||||
// 3001-VOTE-079
|
// 3001-VOTE-079
|
||||||
cy.contains('You voted: For').should('be.visible');
|
cy.contains('You voted: For').should('be.visible');
|
||||||
cy.getByTestId(numberOfVotesFor).should('have.text', '0.0M');
|
cy.getByTestId(proposalVoteProgressForTokens)
|
||||||
cy.getByTestId(votesForPercentage).should('have.text', '100%');
|
.contains('1')
|
||||||
cy.getByTestId(totalVotedNumber).should('have.text', '0.0M');
|
.and('be.visible');
|
||||||
cy.getByTestId(totalVotedPercentage).should('have.text', '(0.00%)');
|
cy.getByTestId(voteBreakdownToggle).click();
|
||||||
ethereumWalletConnect();
|
getProposalInformationFromTable('Total Supply')
|
||||||
stakingPageAssociateTokens('1000000', { approve: true });
|
.invoke('text')
|
||||||
navigateTo(navigation.proposals);
|
.then((totalSupply) => {
|
||||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
const tokensRequiredToAchieveResult = (
|
||||||
getProposalFromTitle(rawProposal.rationale.title).within(() =>
|
(Number(totalSupply.replace(/,/g, '')) * 0.001) /
|
||||||
cy.getByTestId(viewProposalButton).click()
|
100
|
||||||
);
|
).toFixed(2);
|
||||||
});
|
ethereumWalletConnect();
|
||||||
cy.getByTestId(votesForPercentage).should('have.text', '100%');
|
ensureSpecifiedUnstakedTokensAreAssociated(
|
||||||
cy.getByTestId(numberOfVotesFor).should('have.text', '0.0M');
|
tokensRequiredToAchieveResult
|
||||||
cy.getByTestId(totalVotedNumber).should('have.text', '0.0M');
|
);
|
||||||
cy.getByTestId(totalVotedPercentage).should('have.text', '(0.00%)');
|
navigateTo(navigation.proposals);
|
||||||
// 3001-VOTE-065
|
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||||
cy.getByTestId(changeVoteButton).should('be.visible').click();
|
getProposalFromTitle(rawProposal.rationale.title).within(() =>
|
||||||
voteForProposal('for');
|
cy.getByTestId(viewProposalButton).click()
|
||||||
cy.getByTestId(numberOfVotesFor).should('have.text', '1.0M');
|
);
|
||||||
cy.getByTestId(totalVotedNumber).should('have.text', '1.0M');
|
});
|
||||||
cy.getByTestId(totalVotedPercentage).should('have.text', '(1.54%)');
|
cy.getByTestId(proposalVoteProgressForPercentage)
|
||||||
|
.contains('100.00%')
|
||||||
|
.and('be.visible');
|
||||||
|
cy.getByTestId(proposalVoteProgressAgainstPercentage)
|
||||||
|
.contains('0.00%')
|
||||||
|
.and('be.visible');
|
||||||
|
// 3001-VOTE-065
|
||||||
|
cy.getByTestId(changeVoteButton).should('be.visible').click();
|
||||||
|
voteForProposal('for');
|
||||||
|
cy.getByTestId(proposalVoteProgressForTokens)
|
||||||
|
.contains(tokensRequiredToAchieveResult)
|
||||||
|
.and('be.visible');
|
||||||
|
cy.getByTestId(proposalVoteProgressAgainstTokens)
|
||||||
|
.contains('0.00')
|
||||||
|
.and('be.visible');
|
||||||
|
cy.getByTestId(voteBreakdownToggle).click();
|
||||||
|
getProposalInformationFromTable('Total tokens voted percentage')
|
||||||
|
.should('have.text', '0.00%')
|
||||||
|
.and('be.visible');
|
||||||
|
getProposalInformationFromTable('Tokens for proposal')
|
||||||
|
.should('have.text', tokensRequiredToAchieveResult)
|
||||||
|
.and('be.visible');
|
||||||
|
getProposalInformationFromTable('Tokens against proposal')
|
||||||
|
.should('have.text', '0.00')
|
||||||
|
.and('be.visible');
|
||||||
|
getProposalInformationFromTable('Number of voting parties')
|
||||||
|
.should('have.text', '1')
|
||||||
|
.and('be.visible');
|
||||||
|
getProposalInformationFromTable('Expected to pass')
|
||||||
|
.contains('👍')
|
||||||
|
.should('be.visible');
|
||||||
|
// 3001-VOTE-062
|
||||||
|
getProposalInformationFromTable('Token majority met')
|
||||||
|
.contains('👍')
|
||||||
|
.should('be.visible');
|
||||||
|
getProposalInformationFromTable('Token participation met')
|
||||||
|
.contains('👍')
|
||||||
|
.should('be.visible');
|
||||||
|
getProposalInformationFromTable('Tokens for proposal')
|
||||||
|
.contains(tokensRequiredToAchieveResult)
|
||||||
|
.and('be.visible');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Able to vote for proposal twice by switching public key', function () {
|
it('Able to vote for proposal twice by switching public key', function () {
|
||||||
@@ -288,6 +350,10 @@ describe(
|
|||||||
voteForProposal('against');
|
voteForProposal('against');
|
||||||
cy.contains('You voted: Against').should('be.visible');
|
cy.contains('You voted: Against').should('be.visible');
|
||||||
switchVegaWalletPubKey();
|
switchVegaWalletPubKey();
|
||||||
|
cy.getByTestId(proposalVoteProgressForTokens).should(
|
||||||
|
'contain.text',
|
||||||
|
'1.00'
|
||||||
|
);
|
||||||
// Checking vote status for different public keys is displayed correctly
|
// Checking vote status for different public keys is displayed correctly
|
||||||
cy.contains('You voted: For').should('be.visible');
|
cy.contains('You voted: For').should('be.visible');
|
||||||
});
|
});
|
||||||
@@ -295,6 +361,34 @@ describe(
|
|||||||
stakingPageDisassociateAllTokens();
|
stakingPageDisassociateAllTokens();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Error message should be displayed if error returned from wallet when voting', function () {
|
||||||
|
const errorMsg =
|
||||||
|
'Application error: party has already submitted the maximum number of transactions of this type per epoch (3)';
|
||||||
|
|
||||||
|
createRawProposal();
|
||||||
|
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||||
|
getProposalFromTitle(rawProposal.rationale.title).within(() =>
|
||||||
|
cy.getByTestId(viewProposalButton).click()
|
||||||
|
);
|
||||||
|
cy.intercept('POST', '/api/v2/requests', {
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
error: {
|
||||||
|
code: 2001,
|
||||||
|
message: 'Application error',
|
||||||
|
data: 'party has already submitted the maximum number of transactions of this type per epoch (3)',
|
||||||
|
},
|
||||||
|
id: '-PK5EGmErnjLhAmzMeclC',
|
||||||
|
});
|
||||||
|
cy.contains('Vote breakdown').should('be.visible', { timeout: 10000 });
|
||||||
|
cy.getByTestId('vote-buttons').contains('for').click();
|
||||||
|
cy.getByTestId('dialog-title').should(
|
||||||
|
'have.text',
|
||||||
|
'Transaction failed'
|
||||||
|
);
|
||||||
|
cy.getByTestId('Error').should('have.text', errorMsg);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('Able to see successor market details with new and updated values', function () {
|
it('Able to see successor market details with new and updated values', function () {
|
||||||
cy.createMarket();
|
cy.createMarket();
|
||||||
cy.reload();
|
cy.reload();
|
||||||
@@ -331,8 +425,7 @@ describe(
|
|||||||
// 3003-PMAN-011 3003-PMAN-012
|
// 3003-PMAN-011 3003-PMAN-012
|
||||||
cy.getByTestId(marketDataToggle).click();
|
cy.getByTestId(marketDataToggle).click();
|
||||||
cy.getByTestId('proposal-market-data').within(() => {
|
cy.getByTestId('proposal-market-data').within(() => {
|
||||||
// Assert that all toggles are removed
|
cy.contains('Key details').click();
|
||||||
cy.getByTestId('accordion-toggle').should('not.exist');
|
|
||||||
validateProposalDetailsDiff(
|
validateProposalDetailsDiff(
|
||||||
'Name',
|
'Name',
|
||||||
proposalChangeType.UPDATED,
|
proposalChangeType.UPDATED,
|
||||||
@@ -356,6 +449,7 @@ describe(
|
|||||||
'Opening auction'
|
'Opening auction'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
cy.contains('Instrument').click();
|
||||||
validateProposalDetailsDiff(
|
validateProposalDetailsDiff(
|
||||||
'Market Name',
|
'Market Name',
|
||||||
proposalChangeType.UPDATED,
|
proposalChangeType.UPDATED,
|
||||||
@@ -363,6 +457,7 @@ describe(
|
|||||||
'Test market 1'
|
'Test market 1'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
cy.contains('Metadata').click();
|
||||||
validateProposalDetailsDiff(
|
validateProposalDetailsDiff(
|
||||||
'Sector',
|
'Sector',
|
||||||
proposalChangeType.UPDATED,
|
proposalChangeType.UPDATED,
|
||||||
|
|||||||
@@ -22,10 +22,12 @@ const proposalListItem = '[data-testid="proposals-list-item"]';
|
|||||||
const closedProposals = 'closed-proposals';
|
const closedProposals = 'closed-proposals';
|
||||||
const proposalStatus = 'proposal-status';
|
const proposalStatus = 'proposal-status';
|
||||||
const viewProposalButton = 'view-proposal-btn';
|
const viewProposalButton = 'view-proposal-btn';
|
||||||
const votesTable = 'user-vote';
|
const votesTable = 'votes-table';
|
||||||
const openProposals = 'open-proposals';
|
const openProposals = 'open-proposals';
|
||||||
const majorityVoteReached = 'token-majority-met';
|
const proposalVoteProgressForPercentage =
|
||||||
const minParticipationReached = 'token-participation-met';
|
'vote-progress-indicator-percentage-for';
|
||||||
|
const majorityVoteReached = 'majority-reached';
|
||||||
|
const minParticipationReached = 'participation-reached';
|
||||||
const proposalTimeout = { timeout: 8000 };
|
const proposalTimeout = { timeout: 8000 };
|
||||||
|
|
||||||
context(
|
context(
|
||||||
@@ -68,6 +70,7 @@ context(
|
|||||||
cy.getByTestId('proposal-type').should('have.text', 'New market');
|
cy.getByTestId('proposal-type').should('have.text', 'New market');
|
||||||
cy.getByTestId(proposalStatus).should('have.text', 'Enacted');
|
cy.getByTestId(proposalStatus).should('have.text', 'Enacted');
|
||||||
cy.getByTestId(votesTable).within(() => {
|
cy.getByTestId(votesTable).within(() => {
|
||||||
|
cy.contains('Vote passed.').should('be.visible');
|
||||||
cy.contains('Voting has ended.').should('be.visible');
|
cy.contains('Voting has ended.').should('be.visible');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -89,7 +92,7 @@ context(
|
|||||||
// 3001-VOTE-019 time to vote is highlighted red
|
// 3001-VOTE-019 time to vote is highlighted red
|
||||||
cy.getByTestId('vote-details')
|
cy.getByTestId('vote-details')
|
||||||
.find('span')
|
.find('span')
|
||||||
.should('have.class', 'text-vega-orange');
|
.should('have.class', 'text-vega-pink');
|
||||||
cy.getByTestId(viewProposalButton).click();
|
cy.getByTestId(viewProposalButton).click();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -106,9 +109,12 @@ context(
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
cy.getByTestId(votesTable).within(() => {
|
cy.getByTestId(votesTable).within(() => {
|
||||||
|
cy.contains('Vote passed.').should('be.visible');
|
||||||
cy.contains('Voting has ended.').should('be.visible');
|
cy.contains('Voting has ended.').should('be.visible');
|
||||||
});
|
});
|
||||||
cy.getByTestId('votes-for-percentage').should('have.text', '100%');
|
cy.getByTestId(proposalVoteProgressForPercentage)
|
||||||
|
.contains('100.00%')
|
||||||
|
.and('be.visible');
|
||||||
navigateTo(navigation.proposals);
|
navigateTo(navigation.proposals);
|
||||||
cy.contains(proposalTitle)
|
cy.contains(proposalTitle)
|
||||||
.parentsUntil(proposalListItem)
|
.parentsUntil(proposalListItem)
|
||||||
|
|||||||
@@ -298,6 +298,9 @@ context(
|
|||||||
getProposalFromTitle(proposalTitle).within(() =>
|
getProposalFromTitle(proposalTitle).within(() =>
|
||||||
cy.getByTestId(viewProposalButton).click()
|
cy.getByTestId(viewProposalButton).click()
|
||||||
);
|
);
|
||||||
|
cy.contains('Vote breakdown').should('be.visible', {
|
||||||
|
timeout: 10000,
|
||||||
|
});
|
||||||
cy.getByTestId(voteButtons).should('not.exist');
|
cy.getByTestId(voteButtons).should('not.exist');
|
||||||
cy.getByTestId('min-proposal-requirements').should(
|
cy.getByTestId('min-proposal-requirements').should(
|
||||||
'have.text',
|
'have.text',
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ const enactmentDeadlineError = 'enactment-before-voting-deadline';
|
|||||||
const proposalDownloadBtn = 'proposal-download-json';
|
const proposalDownloadBtn = 'proposal-download-json';
|
||||||
const feedbackError = '[data-testid="Error"]';
|
const feedbackError = '[data-testid="Error"]';
|
||||||
const viewProposalBtn = 'view-proposal-btn';
|
const viewProposalBtn = 'view-proposal-btn';
|
||||||
|
const liquidityVoteStatus = 'liquidity-votes-status';
|
||||||
|
const tokenVoteStatus = 'token-votes-status';
|
||||||
const proposalJsonToggle = 'proposal-json-toggle';
|
const proposalJsonToggle = 'proposal-json-toggle';
|
||||||
const proposalJsonSection = 'proposal-json';
|
const proposalJsonSection = 'proposal-json';
|
||||||
const vegaWalletPublicKey = Cypress.env('vegaWalletPublicKey');
|
const vegaWalletPublicKey = Cypress.env('vegaWalletPublicKey');
|
||||||
@@ -419,28 +421,27 @@ context(
|
|||||||
cy.getByTestId(viewProposalBtn).click();
|
cy.getByTestId(viewProposalBtn).click();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
cy.getByTestId('lp-majority-not-met').should(
|
cy.getByTestId(liquidityVoteStatus).should(
|
||||||
'have.text',
|
'contain.text',
|
||||||
'66% majority threshold not met'
|
'Currently expected to fail'
|
||||||
);
|
);
|
||||||
|
cy.getByTestId(tokenVoteStatus).should(
|
||||||
cy.getByTestId('token-majority-not-met').should(
|
'contain.text',
|
||||||
'have.text',
|
'Currently expected to fail'
|
||||||
'66% majority threshold not met'
|
|
||||||
);
|
);
|
||||||
voteForProposal('for');
|
voteForProposal('for');
|
||||||
cy.getByTestId('lp-majority-met').should(
|
cy.getByTestId(liquidityVoteStatus).should(
|
||||||
'have.text',
|
'contain.text',
|
||||||
'66% majority threshold met'
|
'Currently expected to pass'
|
||||||
);
|
);
|
||||||
cy.getByTestId('token-majority-met').should(
|
cy.getByTestId(tokenVoteStatus).should(
|
||||||
'have.text',
|
'contain.text',
|
||||||
'66% majority threshold met'
|
'Currently expected to pass'
|
||||||
);
|
|
||||||
cy.getByTestId('vote-status').should(
|
|
||||||
'have.text',
|
|
||||||
'Currently expected to pass by token vote'
|
|
||||||
);
|
);
|
||||||
|
cy.getByTestId('vote-breakdown-toggle').click();
|
||||||
|
getProposalInformationFromTable('Expected to pass')
|
||||||
|
.contains('👍 by token vote')
|
||||||
|
.should('be.visible');
|
||||||
});
|
});
|
||||||
|
|
||||||
// 3001-VOTE-026 3001-VOTE-027 3001-VOTE-028 3001-VOTE-095 3001-VOTE-096 3005-PASN-001
|
// 3001-VOTE-026 3001-VOTE-027 3001-VOTE-028 3001-VOTE-095 3001-VOTE-096 3005-PASN-001
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
enterRawProposalBody,
|
enterRawProposalBody,
|
||||||
generateFreeFormProposalTitle,
|
generateFreeFormProposalTitle,
|
||||||
getProposalFromTitle,
|
getProposalFromTitle,
|
||||||
|
getProposalInformationFromTable,
|
||||||
goToMakeNewProposal,
|
goToMakeNewProposal,
|
||||||
governanceProposalType,
|
governanceProposalType,
|
||||||
submitUniqueRawProposal,
|
submitUniqueRawProposal,
|
||||||
@@ -29,9 +30,7 @@ const proposalType = 'proposal-type';
|
|||||||
const proposalStatus = 'proposal-status';
|
const proposalStatus = 'proposal-status';
|
||||||
const proposalClosingDate = 'vote-details';
|
const proposalClosingDate = 'vote-details';
|
||||||
const viewProposalButton = 'view-proposal-btn';
|
const viewProposalButton = 'view-proposal-btn';
|
||||||
const voteMajorityNotMet = 'token-majority-not-met';
|
const voteBreakDownToggle = 'vote-breakdown-toggle';
|
||||||
const voteMajorityMet = 'token-majority-met';
|
|
||||||
const votesForPercentage = 'votes-for-percentage';
|
|
||||||
|
|
||||||
describe('Governance flow for proposal list', { tags: '@slow' }, function () {
|
describe('Governance flow for proposal list', { tags: '@slow' }, function () {
|
||||||
before('connect wallets and set approval limit', function () {
|
before('connect wallets and set approval limit', function () {
|
||||||
@@ -122,15 +121,10 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
|
|||||||
submitUniqueRawProposal({ proposalTitle: proposalTitle });
|
submitUniqueRawProposal({ proposalTitle: proposalTitle });
|
||||||
getProposalFromTitle(proposalTitle).within(() => {
|
getProposalFromTitle(proposalTitle).within(() => {
|
||||||
// 3001-VOTE-039
|
// 3001-VOTE-039
|
||||||
cy.getByTestId(voteMajorityNotMet).should(
|
cy.getByTestId('participation-not-reached').should(
|
||||||
'have.text',
|
'have.text',
|
||||||
'66% majority threshold not met'
|
'Min. participation not reached'
|
||||||
);
|
);
|
||||||
cy.getByTestId('token-participation-not-met').should(
|
|
||||||
'have.text',
|
|
||||||
'0.000000000000000000000015% participation threshold not met'
|
|
||||||
);
|
|
||||||
cy.getByTestId(votesForPercentage).should('have.text', '0%');
|
|
||||||
cy.getByTestId(viewProposalButton).click();
|
cy.getByTestId(viewProposalButton).click();
|
||||||
});
|
});
|
||||||
voteForProposal('for');
|
voteForProposal('for');
|
||||||
@@ -140,15 +134,16 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
|
|||||||
'have.text',
|
'have.text',
|
||||||
'Currently expected to pass'
|
'Currently expected to pass'
|
||||||
);
|
);
|
||||||
cy.getByTestId(voteMajorityMet).should(
|
cy.getByTestId('user-voted-yes').should('exist');
|
||||||
|
cy.getByTestId('participation-reached').should(
|
||||||
'have.text',
|
'have.text',
|
||||||
'66% majority threshold met'
|
'Min. participation reached'
|
||||||
);
|
|
||||||
cy.getByTestId(votesForPercentage).should('have.text', '100%');
|
|
||||||
cy.getByTestId('token-participation-met').should(
|
|
||||||
'have.text',
|
|
||||||
'0.000000000000000000000015% participation threshold met'
|
|
||||||
);
|
);
|
||||||
|
cy.getByTestId(viewProposalButton).click();
|
||||||
});
|
});
|
||||||
|
cy.getByTestId(voteBreakDownToggle).click();
|
||||||
|
getProposalInformationFromTable('Token participation met')
|
||||||
|
.contains('👍')
|
||||||
|
.should('be.visible');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ context(
|
|||||||
closeStakingDialog();
|
closeStakingDialog();
|
||||||
navigateTo(navigation.validators);
|
navigateTo(navigation.validators);
|
||||||
cy.get(`[row-id="${0}"]`)
|
cy.get(`[row-id="${0}"]`)
|
||||||
.first()
|
.eq(1)
|
||||||
.within(() => {
|
.within(() => {
|
||||||
cy.getByTestId(stakeValidatorListTotalStake)
|
cy.getByTestId(stakeValidatorListTotalStake)
|
||||||
.should('have.text', '3,002.00')
|
.should('have.text', '3,002.00')
|
||||||
@@ -222,7 +222,7 @@ context(
|
|||||||
.and('be.visible');
|
.and('be.visible');
|
||||||
});
|
});
|
||||||
cy.get(`[row-id="${1}"]`)
|
cy.get(`[row-id="${1}"]`)
|
||||||
.first()
|
.eq(1)
|
||||||
.within(() => {
|
.within(() => {
|
||||||
cy.getByTestId(stakeValidatorListTotalStake)
|
cy.getByTestId(stakeValidatorListTotalStake)
|
||||||
.scrollIntoView()
|
.scrollIntoView()
|
||||||
@@ -262,10 +262,10 @@ context(
|
|||||||
'2'
|
'2'
|
||||||
);
|
);
|
||||||
waitForBeginningOfEpoch();
|
waitForBeginningOfEpoch();
|
||||||
cy.getByTestId(
|
cy.getByTestId(stakeValidatorListStakePercentage).should(
|
||||||
stakeValidatorListStakePercentage,
|
'have.text',
|
||||||
epochTimeout
|
'50.02%'
|
||||||
).should('have.text', '50.02%');
|
);
|
||||||
navigateTo(navigation.validators);
|
navigateTo(navigation.validators);
|
||||||
validateValidatorListTotalStakeAndShare('0', '3,002.00', '50.02%');
|
validateValidatorListTotalStakeAndShare('0', '3,002.00', '50.02%');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ const proposalDocumentationLink = 'proposal-documentation-link';
|
|||||||
const connectToVegaWalletButton = 'connect-to-vega-wallet-btn';
|
const connectToVegaWalletButton = 'connect-to-vega-wallet-btn';
|
||||||
const governanceDocsUrl = 'https://vega.xyz/governance';
|
const governanceDocsUrl = 'https://vega.xyz/governance';
|
||||||
const networkUpgradeProposalListItem = 'protocol-upgrade-proposals-list-item';
|
const networkUpgradeProposalListItem = 'protocol-upgrade-proposals-list-item';
|
||||||
const proposalUpgradeBlockHeight = 'protocol-upgrade-proposal-block-height';
|
|
||||||
const closedProposals = 'closed-proposals';
|
const closedProposals = 'closed-proposals';
|
||||||
const closedProposalToggle = 'closed-proposals-toggle-networkUpgrades';
|
const closedProposalToggle = 'closed-proposals-toggle-networkUpgrades';
|
||||||
const protocolUpgradeTime = 'protocol-upgrade-time';
|
const protocolUpgradeTime = 'protocol-upgrade-time';
|
||||||
@@ -38,39 +37,11 @@ context(
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 3002-PROP-023 3004-PMAC-002 3005-PASN-002 3006-PASC-002 3007-PNEC-002 3008-PFRO-003
|
// 3002-PROP-023 3004-PMAC-002 3005-PASN-002 3006-PASC-002 3007-PNEC-002 3008-PFRO-003
|
||||||
it('new proposal page should have button for link to more information on proposals', function () {
|
it('should have button for link to more information on proposals', function () {
|
||||||
cy.getByTestId('new-proposal-link').click();
|
const proposalsUrl = 'https://docs.vega.xyz/mainnet/tutorials/proposals';
|
||||||
cy.url().should('include', '/proposals/propose/raw');
|
cy.getByTestId('new-proposal-link')
|
||||||
cy.contains('To see Explorer data on proposals visit').within(() => {
|
.find('a')
|
||||||
cy.getByTestId('external-link').should(
|
.should('have.attr', 'href', proposalsUrl);
|
||||||
'have.attr',
|
|
||||||
'href',
|
|
||||||
'https://explorer.fairground.wtf/governance'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
cy.contains(
|
|
||||||
'1. Sense check your proposal with the community on the forum:'
|
|
||||||
).within(() => {
|
|
||||||
cy.getByTestId('external-link').should(
|
|
||||||
'have.attr',
|
|
||||||
'href',
|
|
||||||
'https://community.vega.xyz/c/governance/25'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
cy.contains(
|
|
||||||
'2. Use the appropriate proposal template in the docs:'
|
|
||||||
).within(() => {
|
|
||||||
cy.getByTestId('external-link').should(
|
|
||||||
'have.attr',
|
|
||||||
'href',
|
|
||||||
'https://docs.vega.xyz/mainnet/tutorials/proposals'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
cy.contains('Connect your wallet to submit a proposal').should(
|
|
||||||
'be.visible'
|
|
||||||
);
|
|
||||||
cy.getByTestId('connect-to-vega-wallet-btn').should('exist');
|
|
||||||
navigateTo(navigation.proposals);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to see a working link for - find out more about Vega governance', function () {
|
it('should be able to see a working link for - find out more about Vega governance', function () {
|
||||||
@@ -185,7 +156,7 @@ context(
|
|||||||
'have.text',
|
'have.text',
|
||||||
'Vega release tag: v1'
|
'Vega release tag: v1'
|
||||||
);
|
);
|
||||||
cy.getByTestId(proposalUpgradeBlockHeight).should(
|
cy.getByTestId('protocol-upgrade-proposal-block-height').should(
|
||||||
'have.text',
|
'have.text',
|
||||||
'Upgrade block height: 2015942'
|
'Upgrade block height: 2015942'
|
||||||
);
|
);
|
||||||
@@ -200,15 +171,7 @@ context(
|
|||||||
});
|
});
|
||||||
cy.getByTestId(closedProposalToggle).click();
|
cy.getByTestId(closedProposalToggle).click();
|
||||||
cy.getByTestId(closedProposals).within(() => {
|
cy.getByTestId(closedProposals).within(() => {
|
||||||
cy.getByTestId(networkUpgradeProposalListItem).should('have.length', 2);
|
cy.getByTestId(networkUpgradeProposalListItem).should('have.length', 1);
|
||||||
cy.getByTestId(networkUpgradeProposalListItem)
|
|
||||||
.first()
|
|
||||||
.within(() => {
|
|
||||||
cy.getByTestId(proposalUpgradeBlockHeight).should(
|
|
||||||
'contain.text',
|
|
||||||
'10001'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -220,7 +183,7 @@ context(
|
|||||||
.first()
|
.first()
|
||||||
.find('[data-testid="view-proposal-btn"]')
|
.find('[data-testid="view-proposal-btn"]')
|
||||||
.click();
|
.click();
|
||||||
cy.url().should('contain', '/protocol-upgrades/v1/2015942');
|
cy.url().should('contain', '/protocol-upgrades/v1');
|
||||||
cy.getByTestId('protocol-upgrade-proposal').within(() => {
|
cy.getByTestId('protocol-upgrade-proposal').within(() => {
|
||||||
cy.get('h1').should('have.text', 'Vega Release v1');
|
cy.get('h1').should('have.text', 'Vega Release v1');
|
||||||
cy.getByTestId('protocol-upgrade-block-height').should(
|
cy.getByTestId('protocol-upgrade-block-height').should(
|
||||||
@@ -280,7 +243,7 @@ context(
|
|||||||
);
|
);
|
||||||
cy.getByTestId('external-link')
|
cy.getByTestId('external-link')
|
||||||
.should('have.attr', 'href')
|
.should('have.attr', 'href')
|
||||||
.and('contain', '/proposals/protocol-upgrade/v1/2015942');
|
.and('contain', '/proposals/protocol-upgrade/v1');
|
||||||
});
|
});
|
||||||
|
|
||||||
// estimate does not display possibly due to mocks or Cypress unless the proposal is clicked on several times
|
// estimate does not display possibly due to mocks or Cypress unless the proposal is clicked on several times
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ export function getProposalInformationFromTable(heading: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function voteForProposal(vote: string) {
|
export function voteForProposal(vote: string) {
|
||||||
cy.get(voteButtons).should('be.visible', { timeout: 10000 });
|
cy.contains('Vote breakdown').should('be.visible', { timeout: 10000 });
|
||||||
cy.get(voteButtons).contains(vote).click();
|
cy.get(voteButtons).contains(vote).click();
|
||||||
cy.get(dialogTitle, proposalTimeout).should(
|
cy.get(dialogTitle, proposalTimeout).should(
|
||||||
'have.text',
|
'have.text',
|
||||||
@@ -274,6 +274,3 @@ export enum proposalChangeType {
|
|||||||
UPDATED = 'Updated',
|
UPDATED = 'Updated',
|
||||||
ADDED = 'Added',
|
ADDED = 'Added',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const longProposalDescription =
|
|
||||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam bibendum orci augue, vel imperdiet augue ultrices sed. In hac habitasse platea dictumst. Sed eget elit vitae nisl tincidunt faucibus. Donec pellentesque mauris nec viverra blandit. Aenean eros diam, tempor eu luctus nec, rhoncus non massa. Mauris libero diam, mattis et enim ut, lobortis pharetra elit. Phasellus vel metus accumsan, rhoncus tellus finibus, blandit mi. In sollicitudin ex ac tortor ornare interdum. Sed est ipsum, vestibulum eget dolor vel, porta luctus elit. Fusce justo nibh, placerat eget sollicitudin eleifend, rhoncus id lorem. Fusce vitae magna vel urna faucibus accumsan quis id purus.\nPraesent convallis dolor sed ante ultricies tempor. Proin sed risus ut libero euismod semper. Duis quis quam sed lacus viverra blandit vel scelerisque diam. Donec interdum, ipsum eget imperdiet ornare, risus augue faucibus lectus, ullamcorper scelerisque erat sapien in purus. Nunc molestie tincidunt felis dignissim vestibulum. Quisque quis ornare enim, non dignissim lectus. Mauris mollis, massa ut maximus consectetur, sem mi lobortis quam, vel malesuada eros tortor nec ex. Cras ac nunc sed erat malesuada varius a quis nulla. Curabitur cursus nec sem sit amet aliquet. Ut tristique tortor neque, a dignissim lectus dictum vel. Praesent sollicitudin bibendum vulputate.\nAenean bibendum tristique diam laoreet posuere. Curabitur ornare lectus ut diam ultricies, ut sodales eros lacinia. Maecenas mauris turpis, gravida non arcu ac, interdum auctor sapien. Vestibulum sed tortor quam. Interdum et malesuada fames ac ante ipsum primis in faucibus. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec finibus pulvinar magna, non laoreet lectus molestie nec. Vestibulum tempus mattis vehicula. Praesent in orci lectus. In commodo sollicitudin lacus, et lobortis eros placerat vitae. Proin mi libero, feugiat id pretium posuere, rhoncus ut augue. Cras massa tortor, rutrum sed ex vitae, posuere pretium augue. Donec pellentesque suscipit dignissim. Vivamus convallis a odio vitae sodales. Nullam non eleifend mauris, sed iaculis lectus. Cras facilisis justo at ante.\n[Hyperlink text](https://dweb.link/ipfs/bafybeigwwctpv37xdcwacqxvekr6e4kaemqsrv34em6glkbiceo3fcy4si)';
|
|
||||||
|
|||||||
@@ -170,20 +170,21 @@ export function clickOnValidatorFromList(
|
|||||||
validatorName = null
|
validatorName = null
|
||||||
) {
|
) {
|
||||||
cy.contains('Loading...', epochTimeout).should('not.exist');
|
cy.contains('Loading...', epochTimeout).should('not.exist');
|
||||||
|
waitForBeginningOfEpoch();
|
||||||
// below is to ensure validator list is shown
|
// below is to ensure validator list is shown
|
||||||
cy.get(stakeValidatorListName, { timeout: 10000 }).should('exist');
|
cy.get(stakeValidatorListName, { timeout: 10000 }).should('exist');
|
||||||
cy.get(stakeValidatorListPendingStake, txTimeout).should(
|
cy.get(stakeValidatorListPendingStake, txTimeout).should(
|
||||||
'not.contain',
|
'not.contain',
|
||||||
'2,000,000,000,000,000,000.00' // number due to bug #936
|
'2,000,000,000,000,000,000.00' // number due to bug #936
|
||||||
);
|
);
|
||||||
waitForBeginningOfEpoch();
|
|
||||||
if (validatorName) {
|
if (validatorName) {
|
||||||
cy.contains(validatorName).click();
|
cy.contains(validatorName).click();
|
||||||
} else {
|
} else {
|
||||||
cy.get(`[row-id="${validatorNumber}"]`)
|
cy.get(`[row-id="${validatorNumber}"]`)
|
||||||
.should('be.visible')
|
.should('be.visible')
|
||||||
.first()
|
.first()
|
||||||
.click();
|
.as('validatorOnList');
|
||||||
|
cy.get('@validatorOnList').click();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,7 +196,7 @@ export function validateValidatorListTotalStakeAndShare(
|
|||||||
cy.contains('Loading...', epochTimeout).should('not.exist');
|
cy.contains('Loading...', epochTimeout).should('not.exist');
|
||||||
waitForBeginningOfEpoch();
|
waitForBeginningOfEpoch();
|
||||||
cy.get(`[row-id="${positionOnList}"]`)
|
cy.get(`[row-id="${positionOnList}"]`)
|
||||||
.first()
|
.eq(1)
|
||||||
.within(() => {
|
.within(() => {
|
||||||
cy.getByTestId(stakeValidatorListTotalStake, epochTimeout).should(
|
cy.getByTestId(stakeValidatorListTotalStake, epochTimeout).should(
|
||||||
'have.text',
|
'have.text',
|
||||||
@@ -218,9 +219,7 @@ export function ensureSpecifiedUnstakedTokensAreAssociated(
|
|||||||
.eq(1)
|
.eq(1)
|
||||||
.invoke('text')
|
.invoke('text')
|
||||||
.then((unstakedBalance) => {
|
.then((unstakedBalance) => {
|
||||||
const tokenFloat = parseFloat(tokenAmount);
|
if (parseFloat(unstakedBalance) != parseFloat(tokenAmount)) {
|
||||||
const unstakedFloat = parseFloat(unstakedBalance.replace(/,/g, ''));
|
|
||||||
if (tokenFloat != unstakedFloat) {
|
|
||||||
vegaWalletTeardown();
|
vegaWalletTeardown();
|
||||||
cy.get(vegaWalletAssociatedBalance, txTimeout).contains(
|
cy.get(vegaWalletAssociatedBalance, txTimeout).contains(
|
||||||
'0.00',
|
'0.00',
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.rocks
|
|||||||
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
|
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
|
||||||
|
|
||||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/pl/firefox/addon/vega-wallet
|
||||||
|
|
||||||
#Test configuration variables
|
#Test configuration variables
|
||||||
CYPRESS_FAIRGROUND=false
|
CYPRESS_FAIRGROUND=false
|
||||||
@@ -31,4 +31,3 @@ LC_ALL="en_US.UTF-8"
|
|||||||
|
|
||||||
# Cosmic elevator flags
|
# Cosmic elevator flags
|
||||||
NX_SUCCESSOR_MARKETS=true
|
NX_SUCCESSOR_MARKETS=true
|
||||||
NX_METAMASK_SNAPS=true
|
|
||||||
|
|||||||
@@ -19,11 +19,6 @@ NX_DELEGATIONS_PAGINATION=50
|
|||||||
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
|
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
|
||||||
NX_VEGA_REST_URL=http://localhost:3008/api/v2/
|
NX_VEGA_REST_URL=http://localhost:3008/api/v2/
|
||||||
|
|
||||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
|
||||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
|
||||||
|
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
|
||||||
|
|
||||||
NX_TENDERMINT_URL=http://localhost:26617
|
NX_TENDERMINT_URL=http://localhost:26617
|
||||||
NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
|
NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
|
||||||
|
|
||||||
@@ -31,5 +26,4 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
|
|||||||
CYPRESS_FAIRGROUND=false
|
CYPRESS_FAIRGROUND=false
|
||||||
|
|
||||||
# Cosmic elevator flags
|
# Cosmic elevator flags
|
||||||
NX_SUCCESSOR_MARKETS=false
|
NX_SUCCESSOR_MARKETS=false
|
||||||
NX_METAMASK_SNAPS=false
|
|
||||||
@@ -14,14 +14,8 @@ NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/annou
|
|||||||
NX_VEGA_REST_URL=https://api.n00.devnet1.vega.xyz/api/v2/
|
NX_VEGA_REST_URL=https://api.n00.devnet1.vega.xyz/api/v2/
|
||||||
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996
|
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996
|
||||||
|
|
||||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
|
||||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
|
||||||
|
|
||||||
NX_TENDERMINT_URL=https://tm.be.devnet1.vega.xyz/
|
NX_TENDERMINT_URL=https://tm.be.devnet1.vega.xyz/
|
||||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.devnet1.vega.xyz/websocket
|
NX_TENDERMINT_WEBSOCKET_URL=wss://be.devnet1.vega.xyz/websocket
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
|
||||||
|
|
||||||
|
|
||||||
# Cosmic elevator flags
|
# Cosmic elevator flags
|
||||||
NX_SUCCESSOR_MARKETS=true
|
NX_SUCCESSOR_MARKETS=true
|
||||||
NX_METAMASK_SNAPS=true
|
|
||||||
@@ -14,13 +14,9 @@ NX_DELEGATIONS_PAGINATION=50
|
|||||||
NX_TRANCHES_SERVICE_URL=https://tranches-mainnet-k8s.ops.vega.xyz
|
NX_TRANCHES_SERVICE_URL=https://tranches-mainnet-k8s.ops.vega.xyz
|
||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
|
||||||
NX_VEGA_REST_URL=https://api.vega.community/api/v2/
|
NX_VEGA_REST_URL=https://api.vega.community/api/v2/
|
||||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
|
||||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-mainnet
|
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
|
||||||
|
|
||||||
NX_TENDERMINT_URL=https://be.vega.community
|
NX_TENDERMINT_URL=https://be.vega.community
|
||||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket
|
NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket
|
||||||
|
|
||||||
# Cosmic elevator flags
|
# Cosmic elevator flags
|
||||||
NX_SUCCESSOR_MARKETS=false
|
NX_SUCCESSOR_MARKETS=false
|
||||||
NX_METAMASK_SNAPS=false
|
|
||||||
@@ -13,13 +13,9 @@ NX_DELEGATIONS_PAGINATION=50
|
|||||||
NX_TRANCHES_SERVICE_URL=https://tranches-mainnet-mirror-k8s.ops.vega.xyz
|
NX_TRANCHES_SERVICE_URL=https://tranches-mainnet-mirror-k8s.ops.vega.xyz
|
||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
|
||||||
NX_VEGA_REST_URL=https://api.mainnet-mirror.vega.rocks/api/v2/
|
NX_VEGA_REST_URL=https://api.mainnet-mirror.vega.rocks/api/v2/
|
||||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
|
||||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-mainnet
|
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
|
||||||
|
|
||||||
NX_TENDERMINT_URL=https://be.mainnet-mirror.vega.rocks
|
NX_TENDERMINT_URL=https://be.mainnet-mirror.vega.rocks
|
||||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.mainnet-mirror.vega.rocks/websocket
|
NX_TENDERMINT_WEBSOCKET_URL=wss://be.mainnet-mirror.vega.rocks/websocket
|
||||||
|
|
||||||
# Cosmic elevator flags
|
# Cosmic elevator flags
|
||||||
NX_SUCCESSOR_MARKETS=false
|
NX_SUCCESSOR_MARKETS=false
|
||||||
NX_METAMASK_SNAPS=false
|
|
||||||
@@ -9,14 +9,9 @@ NX_DELEGATIONS_PAGINATION=50
|
|||||||
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
|
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
|
||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||||
NX_VEGA_REST_URL=https://api.n00.stagnet1.vega.xyz/api/v2/
|
NX_VEGA_REST_URL=https://api.n00.stagnet1.vega.xyz/api/v2/
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
|
||||||
|
|
||||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
|
||||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
|
||||||
|
|
||||||
NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.rocks
|
NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.rocks
|
||||||
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
|
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
|
||||||
|
|
||||||
# Cosmic elevator flags
|
# Cosmic elevator flags
|
||||||
NX_SUCCESSOR_MARKETS=true
|
NX_SUCCESSOR_MARKETS=true
|
||||||
NX_METAMASK_SNAPS=true
|
|
||||||
@@ -14,14 +14,9 @@ NX_TRANCHES_SERVICE_URL=https://tranches-testnet-k8s.ops.vega.xyz
|
|||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||||
NX_VEGA_REST_URL=https://api.n07.testnet.vega.xyz/api/v2/
|
NX_VEGA_REST_URL=https://api.n07.testnet.vega.xyz/api/v2/
|
||||||
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996
|
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
|
||||||
|
|
||||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
|
||||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
|
||||||
|
|
||||||
NX_TENDERMINT_URL=https://tm.be.testnet.vega.xyz
|
NX_TENDERMINT_URL=https://tm.be.testnet.vega.xyz
|
||||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.testnet.vega.xyz/websocket
|
NX_TENDERMINT_WEBSOCKET_URL=wss://be.testnet.vega.xyz/websocket
|
||||||
|
|
||||||
# Cosmic elevator flags
|
# Cosmic elevator flags
|
||||||
NX_SUCCESSOR_MARKETS=true
|
NX_SUCCESSOR_MARKETS=true
|
||||||
NX_METAMASK_SNAPS=true
|
|
||||||
@@ -11,14 +11,9 @@ NX_VEGA_EXPLORER_URL=https://explorer.validators-testnet.vega.rocks/
|
|||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||||
NX_VEGA_REST_URL=https://api-validators-testnet.vega.rocks/api/v2/
|
NX_VEGA_REST_URL=https://api-validators-testnet.vega.rocks/api/v2/
|
||||||
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996
|
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
|
||||||
|
|
||||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
|
||||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
|
||||||
|
|
||||||
NX_TENDERMINT_URL=https://tm.be.validators-testnet.vega.rocks
|
NX_TENDERMINT_URL=https://tm.be.validators-testnet.vega.rocks
|
||||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.
|
NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.
|
||||||
|
|
||||||
# Cosmic elevator flags
|
# Cosmic elevator flags
|
||||||
NX_SUCCESSOR_MARKETS=false
|
NX_SUCCESSOR_MARKETS=false
|
||||||
NX_METAMASK_SNAPS=false
|
|
||||||
@@ -41,7 +41,6 @@ import {
|
|||||||
AppFailure,
|
AppFailure,
|
||||||
NodeSwitcherDialog,
|
NodeSwitcherDialog,
|
||||||
useNodeSwitcherStore,
|
useNodeSwitcherStore,
|
||||||
DocsLinks,
|
|
||||||
} from '@vegaprotocol/environment';
|
} from '@vegaprotocol/environment';
|
||||||
import { ENV } from './config';
|
import { ENV } from './config';
|
||||||
import type { InMemoryCacheConfig } from '@apollo/client';
|
import type { InMemoryCacheConfig } from '@apollo/client';
|
||||||
@@ -110,17 +109,8 @@ const Web3Container = ({
|
|||||||
store.connectors,
|
store.connectors,
|
||||||
store.initialize,
|
store.initialize,
|
||||||
]);
|
]);
|
||||||
const {
|
const { ETHEREUM_PROVIDER_URL, ETH_LOCAL_PROVIDER_URL, ETH_WALLET_MNEMONIC } =
|
||||||
ETHEREUM_PROVIDER_URL,
|
useEnvironment();
|
||||||
ETH_LOCAL_PROVIDER_URL,
|
|
||||||
ETH_WALLET_MNEMONIC,
|
|
||||||
VEGA_ENV,
|
|
||||||
VEGA_URL,
|
|
||||||
VEGA_EXPLORER_URL,
|
|
||||||
CHROME_EXTENSION_URL,
|
|
||||||
MOZILLA_EXTENSION_URL,
|
|
||||||
VEGA_WALLET_URL,
|
|
||||||
} = useEnvironment();
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (chainId) {
|
if (chainId) {
|
||||||
return initializeConnectors(
|
return initializeConnectors(
|
||||||
@@ -149,33 +139,10 @@ const Web3Container = ({
|
|||||||
return <SplashLoader />;
|
return <SplashLoader />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
|
||||||
!VEGA_URL ||
|
|
||||||
!VEGA_WALLET_URL ||
|
|
||||||
!VEGA_EXPLORER_URL ||
|
|
||||||
!DocsLinks ||
|
|
||||||
!CHROME_EXTENSION_URL ||
|
|
||||||
!MOZILLA_EXTENSION_URL
|
|
||||||
) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Web3Provider connectors={connectors}>
|
<Web3Provider connectors={connectors}>
|
||||||
<Web3Connector connectors={connectors} chainId={Number(chainId)}>
|
<Web3Connector connectors={connectors} chainId={Number(chainId)}>
|
||||||
<VegaWalletProvider
|
<VegaWalletProvider>
|
||||||
config={{
|
|
||||||
network: VEGA_ENV,
|
|
||||||
vegaUrl: VEGA_URL,
|
|
||||||
vegaWalletServiceUrl: VEGA_WALLET_URL,
|
|
||||||
links: {
|
|
||||||
explorer: VEGA_EXPLORER_URL,
|
|
||||||
concepts: DocsLinks?.VEGA_WALLET_CONCEPTS_URL,
|
|
||||||
chromeExtensionUrl: CHROME_EXTENSION_URL,
|
|
||||||
mozillaExtensionUrl: MOZILLA_EXTENSION_URL,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ContractsProvider>
|
<ContractsProvider>
|
||||||
<AppLoader>
|
<AppLoader>
|
||||||
<BalanceManager>
|
<BalanceManager>
|
||||||
@@ -184,7 +151,7 @@ const Web3Container = ({
|
|||||||
<TemplateSidebar sidebar={sideBar}>
|
<TemplateSidebar sidebar={sideBar}>
|
||||||
<AppRouter />
|
<AppRouter />
|
||||||
</TemplateSidebar>
|
</TemplateSidebar>
|
||||||
<footer className="p-4 border-t border-neutral-700 break-all">
|
<footer className="p-4 border-t border-neutral-700">
|
||||||
<NetworkInfo />
|
<NetworkInfo />
|
||||||
</footer>
|
</footer>
|
||||||
</AppLayout>
|
</AppLayout>
|
||||||
@@ -308,7 +275,7 @@ const AppContainer = () => {
|
|||||||
<Router>
|
<Router>
|
||||||
<ScrollToTop />
|
<ScrollToTop />
|
||||||
<AppStateProvider>
|
<AppStateProvider>
|
||||||
<div className="min-h-full text-white">
|
<div className="grid min-h-full text-white">
|
||||||
<NodeGuard
|
<NodeGuard
|
||||||
skeleton={<div>{t('Loading')}</div>}
|
skeleton={<div>{t('Loading')}</div>}
|
||||||
failure={
|
failure={
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ export const WalletCardRow = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const ref = React.useRef<HTMLDivElement | null>(null);
|
const ref = React.useRef<HTMLDivElement | null>(null);
|
||||||
useAnimateValue(ref, value);
|
useAnimateValue(ref, value);
|
||||||
const [integers, decimalsPlaces, separator] = useNumberParts(value, decimals);
|
const [integers, decimalsPlaces] = useNumberParts(value, decimals);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -75,10 +75,7 @@ export const WalletCardRow = ({
|
|||||||
className="font-mono flex-1 text-right"
|
className="font-mono flex-1 text-right"
|
||||||
data-testid="associated-amount"
|
data-testid="associated-amount"
|
||||||
>
|
>
|
||||||
<span>
|
<span>{integers}.</span>
|
||||||
{integers}
|
|
||||||
{separator}
|
|
||||||
</span>
|
|
||||||
<span>{decimalsPlaces}</span>
|
<span>{decimalsPlaces}</span>
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
@@ -113,10 +110,7 @@ export const WalletCardAsset = ({
|
|||||||
border,
|
border,
|
||||||
subheading,
|
subheading,
|
||||||
}: WalletCardAssetProps) => {
|
}: WalletCardAssetProps) => {
|
||||||
const [integers, decimalsPlaces, separator] = useNumberParts(
|
const [integers, decimalsPlaces] = useNumberParts(balance, decimals);
|
||||||
balance,
|
|
||||||
decimals
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-nowrap mt-2 mb-4">
|
<div className="flex flex-nowrap mt-2 mb-4">
|
||||||
@@ -138,10 +132,7 @@ export const WalletCardAsset = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="px-2 basis-full font-mono" data-testid="currency-value">
|
<div className="px-2 basis-full font-mono" data-testid="currency-value">
|
||||||
<span>
|
<span>{integers}.</span>
|
||||||
{integers}
|
|
||||||
{separator}
|
|
||||||
</span>
|
|
||||||
<span className="text-neutral-400">{decimalsPlaces}</span>
|
<span className="text-neutral-400">{decimalsPlaces}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -201,8 +201,6 @@
|
|||||||
"STATE_WAITING_FOR_NODE_VOTE": "Waiting for node vote",
|
"STATE_WAITING_FOR_NODE_VOTE": "Waiting for node vote",
|
||||||
"UpdateNetworkParameter": "Network parameter",
|
"UpdateNetworkParameter": "Network parameter",
|
||||||
"NewFreeform": "Freeform",
|
"NewFreeform": "Freeform",
|
||||||
"setToPass": "Set to pass",
|
|
||||||
"setToFail": "Set to fail",
|
|
||||||
"tokenVotes": "Token votes",
|
"tokenVotes": "Token votes",
|
||||||
"liquidityVotes": "Liquidity votes",
|
"liquidityVotes": "Liquidity votes",
|
||||||
"castYourVote": "Cast your vote",
|
"castYourVote": "Cast your vote",
|
||||||
@@ -211,23 +209,13 @@
|
|||||||
"against": "Against",
|
"against": "Against",
|
||||||
"majorityRequired": "Majority Required",
|
"majorityRequired": "Majority Required",
|
||||||
"participation": "Participation",
|
"participation": "Participation",
|
||||||
"majorityThreshold": "majority threshold",
|
"met": "Met",
|
||||||
"participationThreshold": "participation threshold",
|
"notMet": "Not Met",
|
||||||
"met": "met",
|
|
||||||
"notMet": "not met",
|
|
||||||
"governanceRequired": "Required",
|
"governanceRequired": "Required",
|
||||||
"daysLeft": "{{daysLeft}} left to vote.",
|
"daysLeft": "{{daysLeft}} left to vote.",
|
||||||
"toVote": "to vote",
|
"toVote": "to vote",
|
||||||
"voteFor": "Vote for",
|
"voteFor": "Vote for",
|
||||||
"voteAgainst": "Vote against",
|
"voteAgainst": "Vote against",
|
||||||
"tokenVote": "Token vote",
|
|
||||||
"tokenVotesFor": "Token votes for",
|
|
||||||
"tokenVotesAgainst": "Token votes against",
|
|
||||||
"totalTokensVoted": "Total tokens voted",
|
|
||||||
"liquidityProviderVote": "Liquidity provider vote",
|
|
||||||
"liquidityProviderVotesFor": "LP votes for",
|
|
||||||
"liquidityProviderVotesAgainst": "LP votes against",
|
|
||||||
"totalLiquidityProviderTokensVoted": "Total LP tokens voted",
|
|
||||||
"votingThresholdInfo": "If the token vote passes the participation threshold it will be the deciding vote. If not, the outcome will be determined by liquidity providers on this market.",
|
"votingThresholdInfo": "If the token vote passes the participation threshold it will be the deciding vote. If not, the outcome will be determined by liquidity providers on this market.",
|
||||||
"noGovernanceTokens": "You need some VEGA tokens to participate in governance",
|
"noGovernanceTokens": "You need some VEGA tokens to participate in governance",
|
||||||
"youVoted": "You voted",
|
"youVoted": "You voted",
|
||||||
@@ -474,7 +462,7 @@
|
|||||||
"rewardsColLiquidityProvisionHeader": "LIQUIDITY PROVISION",
|
"rewardsColLiquidityProvisionHeader": "LIQUIDITY PROVISION",
|
||||||
"rewardsColLiquidityProvisionTooltip": "Liquidity provision rewards are distributed based on how much you have earned in liquidity fees, funded by a liquidity reward pool for that market",
|
"rewardsColLiquidityProvisionTooltip": "Liquidity provision rewards are distributed based on how much you have earned in liquidity fees, funded by a liquidity reward pool for that market",
|
||||||
"rewardsColMarketCreationHeader": "MARKET CREATION",
|
"rewardsColMarketCreationHeader": "MARKET CREATION",
|
||||||
"rewardsColMarketCreationTooltip": "Market creation rewards are paid out to the creator of any market that exceeds a set threshold of cumulative volume in a given epoch, currently {{marketCreationQuantumMultiple}}",
|
"rewardsColMarketCreationTooltip": "Market creation rewards are paid out to the creator of any market that exceeds a set threshold of cumulative volume in a given epoch, currently [rewards.marketCreationQuantumMultiple]",
|
||||||
"rewardsColTotalHeader": "TOTAL",
|
"rewardsColTotalHeader": "TOTAL",
|
||||||
"ofTotalDistributed": "of total distributed",
|
"ofTotalDistributed": "of total distributed",
|
||||||
"checkBackSoon": "Check back soon",
|
"checkBackSoon": "Check back soon",
|
||||||
@@ -708,7 +696,7 @@
|
|||||||
"NewAssetProposal": "New asset proposal",
|
"NewAssetProposal": "New asset proposal",
|
||||||
"UpdateAssetProposal": "Update asset proposal",
|
"UpdateAssetProposal": "Update asset proposal",
|
||||||
"NewFreeformProposal": "New freeform proposal",
|
"NewFreeformProposal": "New freeform proposal",
|
||||||
"NewRawProposal": "New proposal",
|
"NewRawProposal": "New raw proposal",
|
||||||
"MinProposalRequirements": "You must have at least {{value}} VEGA associated to make a proposal",
|
"MinProposalRequirements": "You must have at least {{value}} VEGA associated to make a proposal",
|
||||||
"MinProposalVoteRequirements": "You must have at least {{value}} VEGA associated to vote on this proposal",
|
"MinProposalVoteRequirements": "You must have at least {{value}} VEGA associated to vote on this proposal",
|
||||||
"totalSupply": "Total Supply",
|
"totalSupply": "Total Supply",
|
||||||
@@ -870,9 +858,5 @@
|
|||||||
"Upgraded at": "Upgraded at",
|
"Upgraded at": "Upgraded at",
|
||||||
"dataIsIdentical": "Data is identical",
|
"dataIsIdentical": "Data is identical",
|
||||||
"updatesToMarket": "Updates to market",
|
"updatesToMarket": "Updates to market",
|
||||||
"viewAsParty": "View as party",
|
"viewAsParty": "View as party"
|
||||||
"HowToPropose": "How to make a proposal",
|
|
||||||
"HowToProposeRawStep1": "1. Sense check your proposal with the community on the forum:",
|
|
||||||
"HowToProposeRawStep2": "2. Use the appropriate proposal template in the docs:",
|
|
||||||
"HowToProposeRawStep3": "3. Submit on-chain below"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,17 @@
|
|||||||
import { FLAGS } from '@vegaprotocol/environment';
|
|
||||||
import {
|
import {
|
||||||
JsonRpcConnector,
|
JsonRpcConnector,
|
||||||
ViewConnector,
|
ViewConnector,
|
||||||
InjectedConnector,
|
InjectedConnector,
|
||||||
SnapConnector,
|
|
||||||
DEFAULT_SNAP_ID,
|
|
||||||
} from '@vegaprotocol/wallet';
|
} from '@vegaprotocol/wallet';
|
||||||
|
|
||||||
const urlParams = new URLSearchParams(window.location.search);
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
|
||||||
export const jsonRpc = new JsonRpcConnector();
|
|
||||||
export const injected = new InjectedConnector();
|
export const injected = new InjectedConnector();
|
||||||
|
export const jsonRpc = new JsonRpcConnector();
|
||||||
export const view = new ViewConnector(urlParams.get('address'));
|
export const view = new ViewConnector(urlParams.get('address'));
|
||||||
|
|
||||||
export const snap = FLAGS.METAMASK_SNAPS
|
|
||||||
? new SnapConnector(DEFAULT_SNAP_ID)
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
export const Connectors = {
|
export const Connectors = {
|
||||||
injected,
|
injected,
|
||||||
jsonRpc,
|
jsonRpc,
|
||||||
view,
|
view,
|
||||||
snap,
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -31,6 +31,10 @@ import {
|
|||||||
orderByDate,
|
orderByDate,
|
||||||
orderByUpgradeBlockHeight,
|
orderByUpgradeBlockHeight,
|
||||||
} from '../proposals/components/proposals-list/proposals-list';
|
} from '../proposals/components/proposals-list/proposals-list';
|
||||||
|
import {
|
||||||
|
NetworkParams,
|
||||||
|
useNetworkParams,
|
||||||
|
} from '@vegaprotocol/network-parameters';
|
||||||
import { BigNumber } from '../../lib/bignumber';
|
import { BigNumber } from '../../lib/bignumber';
|
||||||
|
|
||||||
const nodesToShow = 6;
|
const nodesToShow = 6;
|
||||||
@@ -43,34 +47,57 @@ const HomeProposals = ({
|
|||||||
protocolUpgradeProposals: ProtocolUpgradeProposalFieldsFragment[];
|
protocolUpgradeProposals: ProtocolUpgradeProposalFieldsFragment[];
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const {
|
||||||
|
params: networkParams,
|
||||||
|
loading: networkParamsLoading,
|
||||||
|
error: networkParamsError,
|
||||||
|
} = useNetworkParams([
|
||||||
|
NetworkParams.governance_proposal_market_requiredMajority,
|
||||||
|
NetworkParams.governance_proposal_updateMarket_requiredMajority,
|
||||||
|
NetworkParams.governance_proposal_updateMarket_requiredMajorityLP,
|
||||||
|
NetworkParams.governance_proposal_asset_requiredMajority,
|
||||||
|
NetworkParams.governance_proposal_updateAsset_requiredMajority,
|
||||||
|
NetworkParams.governance_proposal_updateNetParam_requiredMajority,
|
||||||
|
NetworkParams.governance_proposal_freeform_requiredMajority,
|
||||||
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="mb-16 break-all" data-testid="home-proposals">
|
<AsyncRenderer
|
||||||
<Heading title={t('vegaGovernance')} />
|
loading={networkParamsLoading}
|
||||||
<h3 className="mb-6">{t('homeProposalsIntro')}</h3>
|
error={networkParamsError}
|
||||||
<div className="mb-8">
|
data={networkParams}
|
||||||
<ExternalLink href={ExternalLinks.GOVERNANCE_PAGE}>
|
>
|
||||||
{t(`readMoreGovernance`)}
|
<section className="mb-16" data-testid="home-proposals">
|
||||||
</ExternalLink>
|
<Heading title={t('vegaGovernance')} />
|
||||||
</div>
|
<h3 className="mb-6">{t('homeProposalsIntro')}</h3>
|
||||||
|
<div className="mb-8">
|
||||||
|
<ExternalLink href={ExternalLinks.GOVERNANCE_PAGE}>
|
||||||
|
{t(`readMoreGovernance`)}
|
||||||
|
</ExternalLink>
|
||||||
|
</div>
|
||||||
|
|
||||||
<SubHeading title={t('latestProposals')} />
|
<SubHeading title={t('latestProposals')} />
|
||||||
<ul data-testid="home-proposal-list" className="grid gap-6">
|
<ul data-testid="home-proposal-list" className="grid gap-6">
|
||||||
{protocolUpgradeProposals.map((proposal, index) => (
|
{protocolUpgradeProposals.map((proposal, index) => (
|
||||||
<ProtocolUpgradeProposalsListItem key={index} proposal={proposal} />
|
<ProtocolUpgradeProposalsListItem key={index} proposal={proposal} />
|
||||||
))}
|
))}
|
||||||
|
|
||||||
{proposals.map((proposal) => (
|
{proposals.map((proposal) => (
|
||||||
<ProposalsListItem key={proposal.id} proposal={proposal} />
|
<ProposalsListItem
|
||||||
))}
|
key={proposal.id}
|
||||||
</ul>
|
proposal={proposal}
|
||||||
|
networkParams={networkParams}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
|
||||||
<div className="mt-6">
|
<div className="mt-6">
|
||||||
<Link to={`${Routes.PROPOSALS}`}>
|
<Link to={`${Routes.PROPOSALS}`}>
|
||||||
<Button size="md">{t('homeProposalsButtonText')}</Button>
|
<Button size="md">{t('homeProposalsButtonText')}</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
</AsyncRenderer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -279,8 +306,8 @@ const GovernanceHome = ({ name }: RouteChildProps) => {
|
|||||||
trimmedActiveNodes={trimmedActiveNodes}
|
trimmedActiveNodes={trimmedActiveNodes}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<section className="flex justify-between flex-wrap gap-12 mb-16">
|
<section className="grid grid-cols-2 gap-12 mb-16">
|
||||||
<div className="min-w-[360px] flex-1" data-testid="home-rewards">
|
<div data-testid="home-rewards">
|
||||||
<Heading title={t('Rewards')} marginTop={false} />
|
<Heading title={t('Rewards')} marginTop={false} />
|
||||||
<h3 className="mb-6">{t('homeRewardsIntro')}</h3>
|
<h3 className="mb-6">{t('homeRewardsIntro')}</h3>
|
||||||
<div className="flex items-center mb-8 gap-4">
|
<div className="flex items-center mb-8 gap-4">
|
||||||
@@ -290,7 +317,7 @@ const GovernanceHome = ({ name }: RouteChildProps) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="min-w-[360px] flex-1" data-testid="home-vega-token">
|
<div data-testid="home-vega-token">
|
||||||
<Heading title={t('vegaToken')} marginTop={false} />
|
<Heading title={t('vegaToken')} marginTop={false} />
|
||||||
<h3 className="mb-6">{t('homeVegaTokenIntro')}</h3>
|
<h3 className="mb-6">{t('homeVegaTokenIntro')}</h3>
|
||||||
<div className="flex items-center mb-8 gap-4">
|
<div className="flex items-center mb-8 gap-4">
|
||||||
|
|||||||
+38
-21
@@ -1,27 +1,44 @@
|
|||||||
import ReactMarkdown from 'react-markdown';
|
import ReactMarkdown from 'react-markdown';
|
||||||
import { RoundedWrapper, ShowMore } from '@vegaprotocol/ui-toolkit';
|
import { useState } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { RoundedWrapper } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { SubHeading } from '../../../../components/heading';
|
||||||
|
import { CollapsibleToggle } from '../../../../components/collapsible-toggle';
|
||||||
|
|
||||||
export const ProposalDescription = ({
|
export const ProposalDescription = ({
|
||||||
description,
|
description,
|
||||||
}: {
|
}: {
|
||||||
description: string;
|
description: string;
|
||||||
}) => (
|
}) => {
|
||||||
<section data-testid="proposal-description">
|
const { t } = useTranslation();
|
||||||
<RoundedWrapper paddingBottom={true} marginBottomLarge={true}>
|
const [showDescription, setShowDescription] = useState(false);
|
||||||
<div className="p-2">
|
|
||||||
<ShowMore>
|
return (
|
||||||
<ReactMarkdown
|
<section data-testid="proposal-description">
|
||||||
className="react-markdown-container"
|
<CollapsibleToggle
|
||||||
/* Prevents HTML embedded in the description from rendering */
|
toggleState={showDescription}
|
||||||
skipHtml={true}
|
setToggleState={setShowDescription}
|
||||||
/* Stops users embedding images which could be used for tracking */
|
dataTestId={'proposal-description-toggle'}
|
||||||
disallowedElements={['img']}
|
>
|
||||||
linkTarget="_blank"
|
<SubHeading title={t('proposalDescription')} />
|
||||||
>
|
</CollapsibleToggle>
|
||||||
{description}
|
|
||||||
</ReactMarkdown>
|
{showDescription && (
|
||||||
</ShowMore>
|
<RoundedWrapper paddingBottom={true} marginBottomLarge={true}>
|
||||||
</div>
|
<div className="p-2">
|
||||||
</RoundedWrapper>
|
<ReactMarkdown
|
||||||
</section>
|
className="react-markdown-container"
|
||||||
);
|
/* Prevents HTML embedded in the description from rendering */
|
||||||
|
skipHtml={true}
|
||||||
|
/* Stops users embedding images which could be used for tracking */
|
||||||
|
disallowedElements={['img']}
|
||||||
|
linkTarget="_blank"
|
||||||
|
>
|
||||||
|
{description}
|
||||||
|
</ReactMarkdown>
|
||||||
|
</div>
|
||||||
|
</RoundedWrapper>
|
||||||
|
)}
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|||||||
+2
@@ -16,6 +16,7 @@ import { ProposalHeader } from './proposal-header';
|
|||||||
import {
|
import {
|
||||||
lastWeek,
|
lastWeek,
|
||||||
nextWeek,
|
nextWeek,
|
||||||
|
mockNetworkParams,
|
||||||
mockWalletContext,
|
mockWalletContext,
|
||||||
createUserVoteQueryMock,
|
createUserVoteQueryMock,
|
||||||
} from '../../test-helpers/mocks';
|
} from '../../test-helpers/mocks';
|
||||||
@@ -47,6 +48,7 @@ const renderComponent = (
|
|||||||
<ProposalHeader
|
<ProposalHeader
|
||||||
proposal={proposal}
|
proposal={proposal}
|
||||||
isListItem={isListItem}
|
isListItem={isListItem}
|
||||||
|
networkParams={mockNetworkParams}
|
||||||
voteState={voteState}
|
voteState={voteState}
|
||||||
/>
|
/>
|
||||||
</VegaWalletContext.Provider>
|
</VegaWalletContext.Provider>
|
||||||
|
|||||||
+7
-4
@@ -8,19 +8,22 @@ import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
|
|||||||
import { truncateMiddle } from '../../../../lib/truncate-middle';
|
import { truncateMiddle } from '../../../../lib/truncate-middle';
|
||||||
import { CurrentProposalState } from '../current-proposal-state';
|
import { CurrentProposalState } from '../current-proposal-state';
|
||||||
import { ProposalInfoLabel } from '../proposal-info-label';
|
import { ProposalInfoLabel } from '../proposal-info-label';
|
||||||
|
import { ProposalVotingStatus } from '../proposal-voting-status';
|
||||||
|
import type { NetworkParamsResult } from '@vegaprotocol/network-parameters';
|
||||||
import { useSuccessorMarketProposalDetails } from '@vegaprotocol/proposals';
|
import { useSuccessorMarketProposalDetails } from '@vegaprotocol/proposals';
|
||||||
import { FLAGS } from '@vegaprotocol/environment';
|
import { FLAGS } from '@vegaprotocol/environment';
|
||||||
import Routes from '../../../routes';
|
import Routes from '../../../routes';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import type { VoteState } from '../vote-details/use-user-vote';
|
import type { VoteState } from '../vote-details/use-user-vote';
|
||||||
import { VoteBreakdown } from '../vote-breakdown';
|
|
||||||
|
|
||||||
export const ProposalHeader = ({
|
export const ProposalHeader = ({
|
||||||
proposal,
|
proposal,
|
||||||
|
networkParams,
|
||||||
isListItem = true,
|
isListItem = true,
|
||||||
voteState,
|
voteState,
|
||||||
}: {
|
}: {
|
||||||
proposal: ProposalFieldsFragment | ProposalQuery['proposal'];
|
proposal: ProposalFieldsFragment | ProposalQuery['proposal'];
|
||||||
|
networkParams: Partial<NetworkParamsResult>;
|
||||||
isListItem?: boolean;
|
isListItem?: boolean;
|
||||||
voteState?: VoteState | null;
|
voteState?: VoteState | null;
|
||||||
}) => {
|
}) => {
|
||||||
@@ -143,7 +146,7 @@ export const ProposalHeader = ({
|
|||||||
className="flex items-center gap-2"
|
className="flex items-center gap-2"
|
||||||
data-testid={`user-voted-${voteState.toLowerCase()}`}
|
data-testid={`user-voted-${voteState.toLowerCase()}`}
|
||||||
>
|
>
|
||||||
<div data-testid="you-voted-icon">
|
<div className="text-vega-green" data-testid="you-voted-icon">
|
||||||
<VegaIcon name={VegaIconNames.VOTE} size={24} />
|
<VegaIcon name={VegaIconNames.VOTE} size={24} />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -159,7 +162,7 @@ export const ProposalHeader = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div data-testid="proposal-title" className="break-all">
|
<div data-testid="proposal-title">
|
||||||
{isListItem ? (
|
{isListItem ? (
|
||||||
<header>
|
<header>
|
||||||
<SubHeading
|
<SubHeading
|
||||||
@@ -182,7 +185,7 @@ export const ProposalHeader = ({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<VoteBreakdown proposal={proposal} />
|
<ProposalVotingStatus proposal={proposal} networkParams={networkParams} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
+152
-138
@@ -15,6 +15,8 @@ import {
|
|||||||
SettlementAssetInfoPanel,
|
SettlementAssetInfoPanel,
|
||||||
} from '@vegaprotocol/markets';
|
} from '@vegaprotocol/markets';
|
||||||
import {
|
import {
|
||||||
|
Accordion,
|
||||||
|
AccordionItem,
|
||||||
Button,
|
Button,
|
||||||
CopyWithTooltip,
|
CopyWithTooltip,
|
||||||
Dialog,
|
Dialog,
|
||||||
@@ -41,9 +43,6 @@ export const useMarketDataDialogStore = create<MarketDataDialogState>(
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const marketDataHeaderStyles =
|
|
||||||
'font-alpha calt text-base border-b border-vega-dark-200 mt-2 py-2';
|
|
||||||
|
|
||||||
export const ProposalMarketData = ({
|
export const ProposalMarketData = ({
|
||||||
marketData,
|
marketData,
|
||||||
parentMarketData,
|
parentMarketData,
|
||||||
@@ -77,14 +76,6 @@ export const ProposalMarketData = ({
|
|||||||
parentTerminationData !== undefined &&
|
parentTerminationData !== undefined &&
|
||||||
isEqual(terminationData, parentTerminationData);
|
isEqual(terminationData, parentTerminationData);
|
||||||
|
|
||||||
const showParentPriceMonitoringBounds =
|
|
||||||
parentMarketData?.priceMonitoringSettings?.parameters?.triggers !==
|
|
||||||
undefined &&
|
|
||||||
!isEqual(
|
|
||||||
marketData.priceMonitoringSettings?.parameters?.triggers,
|
|
||||||
parentMarketData?.priceMonitoringSettings?.parameters?.triggers
|
|
||||||
);
|
|
||||||
|
|
||||||
const getSigners = (data: DataSourceDefinition) => {
|
const getSigners = (data: DataSourceDefinition) => {
|
||||||
if (data.sourceType.__typename === 'DataSourceDefinitionExternal') {
|
if (data.sourceType.__typename === 'DataSourceDefinitionExternal') {
|
||||||
const signers = data.sourceType.sourceType.signers || [];
|
const signers = data.sourceType.sourceType.signers || [];
|
||||||
@@ -117,141 +108,164 @@ export const ProposalMarketData = ({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-10">
|
<div className="mb-10">
|
||||||
<h2 className={marketDataHeaderStyles}>{t('Key details')}</h2>
|
<Accordion>
|
||||||
<KeyDetailsInfoPanel
|
<AccordionItem
|
||||||
market={marketData}
|
itemId="key-details"
|
||||||
parentMarket={parentMarketData}
|
title={t('Key details')}
|
||||||
/>
|
content={
|
||||||
|
<KeyDetailsInfoPanel
|
||||||
<h2 className={marketDataHeaderStyles}>{t('Instrument')}</h2>
|
market={marketData}
|
||||||
<InstrumentInfoPanel
|
parentMarket={parentMarketData}
|
||||||
market={marketData}
|
/>
|
||||||
parentMarket={parentMarketData}
|
}
|
||||||
/>
|
/>
|
||||||
|
<AccordionItem
|
||||||
{isEqual(
|
itemId="instrument"
|
||||||
getSigners(settlementData),
|
title={t('Instrument')}
|
||||||
getSigners(terminationData)
|
content={
|
||||||
) ? (
|
<InstrumentInfoPanel
|
||||||
<>
|
market={marketData}
|
||||||
<h2 className={marketDataHeaderStyles}>{t('Oracle')}</h2>
|
parentMarket={parentMarketData}
|
||||||
|
/>
|
||||||
<OracleInfoPanel
|
}
|
||||||
market={marketData}
|
/>
|
||||||
type="settlementData"
|
{isEqual(
|
||||||
parentMarket={
|
getSigners(settlementData),
|
||||||
isParentSettlementDataEqual ? undefined : parentMarketData
|
getSigners(terminationData)
|
||||||
|
) ? (
|
||||||
|
<AccordionItem
|
||||||
|
itemId="oracles"
|
||||||
|
title={t('Oracle')}
|
||||||
|
content={
|
||||||
|
<OracleInfoPanel
|
||||||
|
market={marketData}
|
||||||
|
type="settlementData"
|
||||||
|
parentMarket={
|
||||||
|
isParentSettlementDataEqual
|
||||||
|
? undefined
|
||||||
|
: parentMarketData
|
||||||
|
}
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</>
|
) : (
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<h2 className={marketDataHeaderStyles}>
|
|
||||||
{t('Settlement Oracle')}
|
|
||||||
</h2>
|
|
||||||
<OracleInfoPanel
|
|
||||||
market={marketData}
|
|
||||||
type="settlementData"
|
|
||||||
parentMarket={
|
|
||||||
isParentSettlementDataEqual ? undefined : parentMarketData
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<h2 className={marketDataHeaderStyles}>
|
|
||||||
{t('Termination Oracle')}
|
|
||||||
</h2>
|
|
||||||
<OracleInfoPanel
|
|
||||||
market={marketData}
|
|
||||||
type="termination"
|
|
||||||
parentMarket={
|
|
||||||
isParentTerminationDataEqual ? undefined : parentMarketData
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/*Note: successor markets will not differ in their settlement*/}
|
|
||||||
{/*assets, so no need to pass in parent market data for comparison.*/}
|
|
||||||
|
|
||||||
<h2 className={marketDataHeaderStyles}>{t('Settlement assets')}</h2>
|
|
||||||
<SettlementAssetInfoPanel
|
|
||||||
market={marketData}
|
|
||||||
parentMarket={parentMarketData}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<h2 className={marketDataHeaderStyles}>{t('Metadata')}</h2>
|
|
||||||
<MetadataInfoPanel
|
|
||||||
market={marketData}
|
|
||||||
parentMarket={parentMarketData}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<h2 className={marketDataHeaderStyles}>{t('Risk model')}</h2>
|
|
||||||
<RiskModelInfoPanel
|
|
||||||
market={marketData}
|
|
||||||
parentMarket={parentMarketData}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<h2 className={marketDataHeaderStyles}>{t('Risk parameters')}</h2>
|
|
||||||
<RiskParametersInfoPanel
|
|
||||||
market={marketData}
|
|
||||||
parentMarket={parentMarketData}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<h2 className={marketDataHeaderStyles}>{t('Risk factors')}</h2>
|
|
||||||
<RiskFactorsInfoPanel
|
|
||||||
market={marketData}
|
|
||||||
parentMarket={parentMarketData}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{showParentPriceMonitoringBounds &&
|
|
||||||
(
|
|
||||||
parentMarketData?.priceMonitoringSettings?.parameters
|
|
||||||
?.triggers || []
|
|
||||||
).map((_, triggerIndex) => (
|
|
||||||
<>
|
<>
|
||||||
<h2 className={marketDataHeaderStyles}>
|
<AccordionItem
|
||||||
{t(`Parent price monitoring bounds ${triggerIndex + 1}`)}
|
itemId="settlement-oracle"
|
||||||
</h2>
|
title={t('Settlement Oracle')}
|
||||||
|
content={
|
||||||
|
<OracleInfoPanel
|
||||||
|
market={marketData}
|
||||||
|
type="settlementData"
|
||||||
|
parentMarket={
|
||||||
|
isParentSettlementDataEqual
|
||||||
|
? undefined
|
||||||
|
: parentMarketData
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
<div className="text-vega-dark-300 line-through">
|
<AccordionItem
|
||||||
|
itemId="termination-oracle"
|
||||||
|
title={t('Termination Oracle')}
|
||||||
|
content={
|
||||||
|
<OracleInfoPanel
|
||||||
|
market={marketData}
|
||||||
|
type="termination"
|
||||||
|
parentMarket={
|
||||||
|
isParentTerminationDataEqual
|
||||||
|
? undefined
|
||||||
|
: parentMarketData
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{/*Note: successor markets will not differ in their settlement*/}
|
||||||
|
{/*assets, so no need to pass in parent market data for comparison.*/}
|
||||||
|
<AccordionItem
|
||||||
|
itemId="settlement-asset"
|
||||||
|
title={t('Settlement asset')}
|
||||||
|
content={<SettlementAssetInfoPanel market={marketData} />}
|
||||||
|
/>
|
||||||
|
<AccordionItem
|
||||||
|
itemId="metadata"
|
||||||
|
title={t('Metadata')}
|
||||||
|
content={
|
||||||
|
<MetadataInfoPanel
|
||||||
|
market={marketData}
|
||||||
|
parentMarket={parentMarketData}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<AccordionItem
|
||||||
|
itemId="risk-model"
|
||||||
|
title={t('Risk model')}
|
||||||
|
content={
|
||||||
|
<RiskModelInfoPanel
|
||||||
|
market={marketData}
|
||||||
|
parentMarket={parentMarketData}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<AccordionItem
|
||||||
|
itemId="risk-parameters"
|
||||||
|
title={t('Risk parameters')}
|
||||||
|
content={
|
||||||
|
<RiskParametersInfoPanel
|
||||||
|
market={marketData}
|
||||||
|
parentMarket={parentMarketData}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<AccordionItem
|
||||||
|
itemId="risk-factors"
|
||||||
|
title={t('Risk factors')}
|
||||||
|
content={
|
||||||
|
<RiskFactorsInfoPanel
|
||||||
|
market={marketData}
|
||||||
|
parentMarket={parentMarketData}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
{(
|
||||||
|
marketData.priceMonitoringSettings?.parameters?.triggers || []
|
||||||
|
).map((_, triggerIndex) => (
|
||||||
|
<AccordionItem
|
||||||
|
itemId={`trigger-${triggerIndex}`}
|
||||||
|
title={t(`Price monitoring bounds ${triggerIndex + 1}`)}
|
||||||
|
content={
|
||||||
<PriceMonitoringBoundsInfoPanel
|
<PriceMonitoringBoundsInfoPanel
|
||||||
market={parentMarketData}
|
market={marketData}
|
||||||
|
parentMarket={parentMarketData}
|
||||||
triggerIndex={triggerIndex}
|
triggerIndex={triggerIndex}
|
||||||
/>
|
/>
|
||||||
</div>
|
}
|
||||||
</>
|
|
||||||
))}
|
|
||||||
|
|
||||||
{(
|
|
||||||
marketData.priceMonitoringSettings?.parameters?.triggers || []
|
|
||||||
).map((_, triggerIndex) => (
|
|
||||||
<>
|
|
||||||
<h2 className={marketDataHeaderStyles}>
|
|
||||||
{t(`Price monitoring bounds ${triggerIndex + 1}`)}
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<PriceMonitoringBoundsInfoPanel
|
|
||||||
market={marketData}
|
|
||||||
triggerIndex={triggerIndex}
|
|
||||||
/>
|
/>
|
||||||
</>
|
))}
|
||||||
))}
|
<AccordionItem
|
||||||
|
itemId="liqudity-monitoring-parameters"
|
||||||
<h2 className={marketDataHeaderStyles}>
|
title={t('Liquidity monitoring parameters')}
|
||||||
{t('Liquidity monitoring parameters')}
|
content={
|
||||||
</h2>
|
<LiquidityMonitoringParametersInfoPanel
|
||||||
<LiquidityMonitoringParametersInfoPanel
|
market={marketData}
|
||||||
market={marketData}
|
parentMarket={parentMarketData}
|
||||||
parentMarket={parentMarketData}
|
/>
|
||||||
/>
|
}
|
||||||
|
/>
|
||||||
<h2 className={marketDataHeaderStyles}>
|
<AccordionItem
|
||||||
{t('Liquidity price range')}
|
itemId="liquidity-price-range"
|
||||||
</h2>
|
title={t('Liquidity price range')}
|
||||||
<LiquidityPriceRangeInfoPanel
|
content={
|
||||||
market={marketData}
|
<LiquidityPriceRangeInfoPanel
|
||||||
parentMarket={parentMarketData}
|
market={marketData}
|
||||||
/>
|
parentMarket={parentMarketData}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Accordion>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export { ProposalVotesTable } from './proposal-votes-table';
|
||||||
+119
@@ -0,0 +1,119 @@
|
|||||||
|
import { render, screen, fireEvent } from '@testing-library/react';
|
||||||
|
import { MockedProvider } from '@apollo/client/testing';
|
||||||
|
import { AppStateProvider } from '../../../../contexts/app-state/app-state-provider';
|
||||||
|
import { ProposalVotesTable } from './proposal-votes-table';
|
||||||
|
import { ProposalType } from '../proposal/proposal';
|
||||||
|
import {
|
||||||
|
generateNoVotes,
|
||||||
|
generateProposal,
|
||||||
|
generateYesVotes,
|
||||||
|
} from '../../test-helpers/generate-proposals';
|
||||||
|
|
||||||
|
const defaultProposal = generateProposal();
|
||||||
|
const defaultProposalType = ProposalType.PROPOSAL_NETWORK_PARAMETER;
|
||||||
|
const updateMarketProposal = generateProposal({
|
||||||
|
terms: {
|
||||||
|
change: {
|
||||||
|
__typename: 'UpdateMarket',
|
||||||
|
marketId: '12345',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
votes: {
|
||||||
|
__typename: 'ProposalVotes',
|
||||||
|
yes: generateYesVotes(10),
|
||||||
|
no: generateNoVotes(0),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const updateMarketProposalType = ProposalType.PROPOSAL_UPDATE_MARKET;
|
||||||
|
|
||||||
|
const renderComponent = (
|
||||||
|
proposal = defaultProposal,
|
||||||
|
proposalType = defaultProposalType
|
||||||
|
) =>
|
||||||
|
render(
|
||||||
|
<MockedProvider>
|
||||||
|
<AppStateProvider>
|
||||||
|
<ProposalVotesTable proposal={proposal} proposalType={proposalType} />
|
||||||
|
</AppStateProvider>
|
||||||
|
</MockedProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
describe('Proposal Votes Table', () => {
|
||||||
|
it('should render successfully', () => {
|
||||||
|
const { baseElement } = renderComponent();
|
||||||
|
expect(baseElement).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show vote breakdown fields, excluding custom update market fields', () => {
|
||||||
|
renderComponent();
|
||||||
|
fireEvent.click(screen.getByTestId('vote-breakdown-toggle'));
|
||||||
|
expect(screen.getByText('Expected to pass')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Token majority met')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Token participation met')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Tokens for proposal')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Total Supply')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Tokens against proposal')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Participation required')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Majority Required')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Number of voting parties')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Total tokens voted')).toBeInTheDocument();
|
||||||
|
expect(
|
||||||
|
screen.getByText('Total tokens voted percentage')
|
||||||
|
).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Number of votes for')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Number of votes against')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Yes percentage')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('No percentage')).toBeInTheDocument();
|
||||||
|
expect(screen.queryByText('Liquidity majority met')).toBeNull();
|
||||||
|
expect(screen.queryByText('Liquidity participation met')).toBeNull();
|
||||||
|
expect(screen.queryByText('Liquidity shares for proposal')).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('displays different breakdown fields for update market proposal', () => {
|
||||||
|
renderComponent(updateMarketProposal, updateMarketProposalType);
|
||||||
|
fireEvent.click(screen.getByTestId('vote-breakdown-toggle'));
|
||||||
|
expect(screen.getByText('Liquidity majority met')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Liquidity participation met')).toBeInTheDocument();
|
||||||
|
expect(
|
||||||
|
screen.getByText('Liquidity shares for proposal')
|
||||||
|
).toBeInTheDocument();
|
||||||
|
expect(screen.queryByText('Number of voting parties')).toBeNull();
|
||||||
|
expect(screen.queryByText('Total tokens voted')).toBeNull();
|
||||||
|
expect(screen.queryByText('Total tokens voted percentage')).toBeNull();
|
||||||
|
expect(screen.queryByText('Number of votes for')).toBeNull();
|
||||||
|
expect(screen.queryByText('Number of votes against')).toBeNull();
|
||||||
|
expect(screen.queryByText('Yes percentage')).toBeNull();
|
||||||
|
expect(screen.queryByText('No percentage')).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('displays if an update market proposal will pass by token vote', () => {
|
||||||
|
renderComponent(updateMarketProposal, updateMarketProposalType);
|
||||||
|
fireEvent.click(screen.getByTestId('vote-breakdown-toggle'));
|
||||||
|
expect(screen.getByText('👍 by token vote')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('displays if an update market proposal will pass by LP vote', () => {
|
||||||
|
renderComponent(
|
||||||
|
generateProposal({
|
||||||
|
terms: {
|
||||||
|
change: {
|
||||||
|
__typename: 'UpdateMarket',
|
||||||
|
marketId: '12345',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
votes: {
|
||||||
|
__typename: 'ProposalVotes',
|
||||||
|
yes: {
|
||||||
|
...generateYesVotes(0, 1, '10'),
|
||||||
|
},
|
||||||
|
no: {
|
||||||
|
...generateNoVotes(0, 1, '0'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
updateMarketProposalType
|
||||||
|
);
|
||||||
|
fireEvent.click(screen.getByTestId('vote-breakdown-toggle'));
|
||||||
|
expect(screen.getByText('👍 by liquidity vote')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
+177
@@ -0,0 +1,177 @@
|
|||||||
|
import { useState } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import {
|
||||||
|
KeyValueTable,
|
||||||
|
KeyValueTableRow,
|
||||||
|
Thumbs,
|
||||||
|
RoundedWrapper,
|
||||||
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { formatNumber, formatNumberPercentage } from '@vegaprotocol/utils';
|
||||||
|
import { SubHeading } from '../../../../components/heading';
|
||||||
|
import { useVoteInformation } from '../../hooks';
|
||||||
|
import { useAppState } from '../../../../contexts/app-state/app-state-context';
|
||||||
|
import { ProposalType } from '../proposal/proposal';
|
||||||
|
import { CollapsibleToggle } from '../../../../components/collapsible-toggle';
|
||||||
|
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
|
||||||
|
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
|
||||||
|
|
||||||
|
interface ProposalVotesTableProps {
|
||||||
|
proposal: ProposalFieldsFragment | ProposalQuery['proposal'];
|
||||||
|
proposalType: ProposalType | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ProposalVotesTable = ({
|
||||||
|
proposal,
|
||||||
|
proposalType,
|
||||||
|
}: ProposalVotesTableProps) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const {
|
||||||
|
appState: { totalSupply },
|
||||||
|
} = useAppState();
|
||||||
|
const [showDetails, setShowDetails] = useState(false);
|
||||||
|
const {
|
||||||
|
willPassByTokenVote,
|
||||||
|
willPassByLPVote,
|
||||||
|
totalTokensPercentage,
|
||||||
|
participationMet,
|
||||||
|
participationLPMet,
|
||||||
|
totalTokensVoted,
|
||||||
|
noPercentage,
|
||||||
|
yesPercentage,
|
||||||
|
noTokens,
|
||||||
|
yesTokens,
|
||||||
|
yesEquityLikeShareWeight,
|
||||||
|
yesVotes,
|
||||||
|
noVotes,
|
||||||
|
totalVotes,
|
||||||
|
requiredMajorityPercentage,
|
||||||
|
requiredParticipation,
|
||||||
|
majorityMet,
|
||||||
|
majorityLPMet,
|
||||||
|
} = useVoteInformation({ proposal });
|
||||||
|
|
||||||
|
const isUpdateMarket = proposalType === ProposalType.PROPOSAL_UPDATE_MARKET;
|
||||||
|
const updateMarketWillPass = willPassByTokenVote || willPassByLPVote;
|
||||||
|
const updateMarketVotePassMethod = willPassByTokenVote
|
||||||
|
? t('byTokenVote')
|
||||||
|
: t('byLiquidityVote');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<CollapsibleToggle
|
||||||
|
toggleState={showDetails}
|
||||||
|
setToggleState={setShowDetails}
|
||||||
|
dataTestId="vote-breakdown-toggle"
|
||||||
|
>
|
||||||
|
<SubHeading title={t('voteBreakdown')} />
|
||||||
|
</CollapsibleToggle>
|
||||||
|
|
||||||
|
{showDetails && (
|
||||||
|
<RoundedWrapper marginBottomLarge={true} paddingBottom={true}>
|
||||||
|
<KeyValueTable
|
||||||
|
data-testid="proposal-votes-table"
|
||||||
|
numerical={true}
|
||||||
|
headingLevel={4}
|
||||||
|
>
|
||||||
|
<KeyValueTableRow>
|
||||||
|
{t('expectedToPass')}
|
||||||
|
{isUpdateMarket ? (
|
||||||
|
updateMarketWillPass ? (
|
||||||
|
<Thumbs up={true} text={updateMarketVotePassMethod} />
|
||||||
|
) : (
|
||||||
|
<Thumbs up={false} />
|
||||||
|
)
|
||||||
|
) : willPassByTokenVote ? (
|
||||||
|
<Thumbs up={true} />
|
||||||
|
) : (
|
||||||
|
<Thumbs up={false} />
|
||||||
|
)}
|
||||||
|
</KeyValueTableRow>
|
||||||
|
<KeyValueTableRow>
|
||||||
|
{t('majorityMet')}
|
||||||
|
{majorityMet ? <Thumbs up={true} /> : <Thumbs up={false} />}
|
||||||
|
</KeyValueTableRow>
|
||||||
|
{isUpdateMarket && (
|
||||||
|
<KeyValueTableRow>
|
||||||
|
{t('majorityLPMet')}
|
||||||
|
{majorityLPMet ? <Thumbs up={true} /> : <Thumbs up={false} />}
|
||||||
|
</KeyValueTableRow>
|
||||||
|
)}
|
||||||
|
<KeyValueTableRow>
|
||||||
|
{t('participationMet')}
|
||||||
|
{participationMet ? <Thumbs up={true} /> : <Thumbs up={false} />}
|
||||||
|
</KeyValueTableRow>
|
||||||
|
{isUpdateMarket && (
|
||||||
|
<KeyValueTableRow>
|
||||||
|
{t('participationLPMet')}
|
||||||
|
{participationLPMet ? (
|
||||||
|
<Thumbs up={true} />
|
||||||
|
) : (
|
||||||
|
<Thumbs up={false} />
|
||||||
|
)}
|
||||||
|
</KeyValueTableRow>
|
||||||
|
)}
|
||||||
|
<KeyValueTableRow>
|
||||||
|
{t('tokenForProposal')}
|
||||||
|
{formatNumber(yesTokens, 2)}
|
||||||
|
</KeyValueTableRow>
|
||||||
|
{isUpdateMarket && (
|
||||||
|
<KeyValueTableRow>
|
||||||
|
{t('tokenLPForProposal')}
|
||||||
|
{formatNumber(yesEquityLikeShareWeight, 2)}
|
||||||
|
</KeyValueTableRow>
|
||||||
|
)}
|
||||||
|
<KeyValueTableRow>
|
||||||
|
{t('totalSupply')}
|
||||||
|
{formatNumber(totalSupply, 2)}
|
||||||
|
</KeyValueTableRow>
|
||||||
|
<KeyValueTableRow>
|
||||||
|
{t('tokensAgainstProposal')}
|
||||||
|
{formatNumber(noTokens, 2)}
|
||||||
|
</KeyValueTableRow>
|
||||||
|
<KeyValueTableRow>
|
||||||
|
{t('participationRequired')}
|
||||||
|
{formatNumberPercentage(requiredParticipation)}
|
||||||
|
</KeyValueTableRow>
|
||||||
|
<KeyValueTableRow>
|
||||||
|
{t('majorityRequired')}
|
||||||
|
{formatNumberPercentage(requiredMajorityPercentage)}
|
||||||
|
</KeyValueTableRow>
|
||||||
|
{!isUpdateMarket && (
|
||||||
|
<>
|
||||||
|
<KeyValueTableRow>
|
||||||
|
{t('numberOfVotingParties')}
|
||||||
|
{formatNumber(totalVotes, 0)}
|
||||||
|
</KeyValueTableRow>
|
||||||
|
<KeyValueTableRow>
|
||||||
|
{t('totalTokensVotes')}
|
||||||
|
{formatNumber(totalTokensVoted, 2)}
|
||||||
|
</KeyValueTableRow>
|
||||||
|
<KeyValueTableRow>
|
||||||
|
{t('totalTokenVotedPercentage')}
|
||||||
|
{formatNumberPercentage(totalTokensPercentage, 2)}
|
||||||
|
</KeyValueTableRow>
|
||||||
|
<KeyValueTableRow>
|
||||||
|
{t('numberOfForVotes')}
|
||||||
|
{formatNumber(yesVotes, 0)}
|
||||||
|
</KeyValueTableRow>
|
||||||
|
<KeyValueTableRow>
|
||||||
|
{t('numberOfAgainstVotes')}
|
||||||
|
{formatNumber(noVotes, 0)}
|
||||||
|
</KeyValueTableRow>
|
||||||
|
<KeyValueTableRow>
|
||||||
|
{t('yesPercentage')}
|
||||||
|
{formatNumberPercentage(yesPercentage, 2)}
|
||||||
|
</KeyValueTableRow>
|
||||||
|
<KeyValueTableRow noBorder={true}>
|
||||||
|
{t('noPercentage')}
|
||||||
|
{formatNumberPercentage(noPercentage, 2)}
|
||||||
|
</KeyValueTableRow>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</KeyValueTable>
|
||||||
|
</RoundedWrapper>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from './proposal-voting-status';
|
||||||
+153
@@ -0,0 +1,153 @@
|
|||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import { BrowserRouter as Router } from 'react-router-dom';
|
||||||
|
import { MockedProvider } from '@apollo/client/testing';
|
||||||
|
import { VegaWalletContext } from '@vegaprotocol/wallet';
|
||||||
|
import {
|
||||||
|
lastWeek,
|
||||||
|
mockWalletContext,
|
||||||
|
networkParamsQueryMock,
|
||||||
|
nextWeek,
|
||||||
|
mockNetworkParams,
|
||||||
|
} from '../../test-helpers/mocks';
|
||||||
|
import { ProposalVotingStatus } from './proposal-voting-status';
|
||||||
|
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
|
||||||
|
import type { MockedResponse } from '@apollo/client/testing';
|
||||||
|
import {
|
||||||
|
generateNoVotes,
|
||||||
|
generateProposal,
|
||||||
|
generateYesVotes,
|
||||||
|
} from '../../test-helpers/generate-proposals';
|
||||||
|
import { ProposalState } from '@vegaprotocol/types';
|
||||||
|
import { BigNumber } from '../../../../lib/bignumber';
|
||||||
|
import type { AppState } from '../../../../contexts/app-state/app-state-context';
|
||||||
|
|
||||||
|
const mockTotalSupply = new BigNumber(100);
|
||||||
|
// Note - giving a fixedTokenValue of 1 means a ratio of 1:1 votes to tokens, making sums easier :)
|
||||||
|
const fixedTokenValue = 1000000000000000000;
|
||||||
|
|
||||||
|
const mockAppState: AppState = {
|
||||||
|
totalAssociated: new BigNumber('50063005'),
|
||||||
|
decimals: 18,
|
||||||
|
totalSupply: mockTotalSupply,
|
||||||
|
vegaWalletManageOverlay: false,
|
||||||
|
transactionOverlay: false,
|
||||||
|
bannerMessage: '',
|
||||||
|
disconnectNotice: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
jest.mock('../../../../contexts/app-state/app-state-context', () => ({
|
||||||
|
useAppState: () => ({
|
||||||
|
appState: mockAppState,
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const renderComponent = (
|
||||||
|
proposal: ProposalQuery['proposal'],
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
mocks: MockedResponse<any>[] = [networkParamsQueryMock]
|
||||||
|
) =>
|
||||||
|
render(
|
||||||
|
<Router>
|
||||||
|
<MockedProvider mocks={mocks}>
|
||||||
|
<VegaWalletContext.Provider value={mockWalletContext}>
|
||||||
|
<ProposalVotingStatus
|
||||||
|
proposal={proposal}
|
||||||
|
networkParams={mockNetworkParams}
|
||||||
|
/>
|
||||||
|
</VegaWalletContext.Provider>
|
||||||
|
</MockedProvider>
|
||||||
|
</Router>
|
||||||
|
);
|
||||||
|
|
||||||
|
describe('ProposalVotingStatus', () => {
|
||||||
|
beforeAll(() => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
jest.setSystemTime(0);
|
||||||
|
});
|
||||||
|
afterAll(() => {
|
||||||
|
jest.useRealTimers();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders majority reached', () => {
|
||||||
|
const yesVotes = 100;
|
||||||
|
const noVotes = 0;
|
||||||
|
|
||||||
|
renderComponent(
|
||||||
|
generateProposal({
|
||||||
|
state: ProposalState.STATE_PASSED,
|
||||||
|
terms: {
|
||||||
|
closingDatetime: lastWeek.toString(),
|
||||||
|
enactmentDatetime: nextWeek.toString(),
|
||||||
|
},
|
||||||
|
votes: {
|
||||||
|
__typename: 'ProposalVotes',
|
||||||
|
yes: generateYesVotes(yesVotes, fixedTokenValue),
|
||||||
|
no: generateNoVotes(noVotes, fixedTokenValue),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
expect(screen.getByTestId('majority-reached')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders majority not reached', () => {
|
||||||
|
const yesVotes = 20;
|
||||||
|
const noVotes = 80;
|
||||||
|
|
||||||
|
renderComponent(
|
||||||
|
generateProposal({
|
||||||
|
state: ProposalState.STATE_PASSED,
|
||||||
|
terms: {
|
||||||
|
closingDatetime: lastWeek.toString(),
|
||||||
|
enactmentDatetime: nextWeek.toString(),
|
||||||
|
},
|
||||||
|
votes: {
|
||||||
|
__typename: 'ProposalVotes',
|
||||||
|
yes: generateYesVotes(yesVotes, fixedTokenValue),
|
||||||
|
no: generateNoVotes(noVotes, fixedTokenValue),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
expect(screen.getByTestId('majority-not-reached')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders participation reached', () => {
|
||||||
|
const yesVotes = 1000;
|
||||||
|
const noVotes = 0;
|
||||||
|
|
||||||
|
renderComponent(
|
||||||
|
generateProposal({
|
||||||
|
state: ProposalState.STATE_PASSED,
|
||||||
|
terms: {
|
||||||
|
closingDatetime: lastWeek.toString(),
|
||||||
|
enactmentDatetime: nextWeek.toString(),
|
||||||
|
},
|
||||||
|
votes: {
|
||||||
|
__typename: 'ProposalVotes',
|
||||||
|
yes: generateYesVotes(yesVotes, fixedTokenValue),
|
||||||
|
no: generateNoVotes(noVotes, fixedTokenValue),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
expect(screen.getByTestId('participation-reached')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Renders participation not reached', () => {
|
||||||
|
const yesVotes = 0;
|
||||||
|
const noVotes = 0;
|
||||||
|
|
||||||
|
renderComponent(
|
||||||
|
generateProposal({
|
||||||
|
terms: {
|
||||||
|
closingDatetime: lastWeek.toString(),
|
||||||
|
enactmentDatetime: nextWeek.toString(),
|
||||||
|
},
|
||||||
|
votes: {
|
||||||
|
__typename: 'ProposalVotes',
|
||||||
|
yes: generateYesVotes(yesVotes, fixedTokenValue),
|
||||||
|
no: generateNoVotes(noVotes, fixedTokenValue),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
expect(screen.getByTestId('participation-not-reached')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
+174
@@ -0,0 +1,174 @@
|
|||||||
|
import classNames from 'classnames';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { Icon } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { useVoteInformation } from '../../hooks';
|
||||||
|
import { BigNumber } from '../../../../lib/bignumber';
|
||||||
|
import type { NetworkParamsResult } from '@vegaprotocol/network-parameters';
|
||||||
|
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
|
||||||
|
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
|
||||||
|
|
||||||
|
const statusClasses = (reached: boolean) =>
|
||||||
|
classNames('flex items-center gap-2 px-4 py-2 rounded-md', {
|
||||||
|
'bg-vega-green-700': reached,
|
||||||
|
'bg-vega-red-700': !reached,
|
||||||
|
});
|
||||||
|
|
||||||
|
const MajorityStatus = ({
|
||||||
|
reached,
|
||||||
|
requiredMajority,
|
||||||
|
}: {
|
||||||
|
reached: boolean;
|
||||||
|
requiredMajority: string | null | undefined;
|
||||||
|
}) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={statusClasses(reached)}
|
||||||
|
data-testid="proposal-majority-status"
|
||||||
|
>
|
||||||
|
{reached ? <Icon name="tick" /> : <Icon name="cross" />}
|
||||||
|
{reached ? (
|
||||||
|
<div data-testid="majority-reached">
|
||||||
|
{requiredMajority ? (
|
||||||
|
<>
|
||||||
|
{new BigNumber(requiredMajority).times(100).toString()}%{' '}
|
||||||
|
{t('majorityVotedForProposal')}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
t('requiredMajorityVotedForProposal')
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div data-testid="majority-not-reached">
|
||||||
|
{requiredMajority ? (
|
||||||
|
<>
|
||||||
|
{new BigNumber(requiredMajority).times(100).toString()}%{' '}
|
||||||
|
{t('majorityNotVotedForProposal')}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
t('requiredMajorityNotVotedForProposal')
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const ParticipationStatus = ({ reached }: { reached: boolean }) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={statusClasses(reached)}>
|
||||||
|
{reached ? (
|
||||||
|
<>
|
||||||
|
<Icon name="tick" />
|
||||||
|
<div data-testid="participation-reached">
|
||||||
|
{t('minParticipationReached')}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Icon name="cross" />
|
||||||
|
<div data-testid="participation-not-reached">
|
||||||
|
{t('minParticipationNotReached')}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ProposalVotingStatus = ({
|
||||||
|
proposal,
|
||||||
|
networkParams,
|
||||||
|
}: {
|
||||||
|
proposal: ProposalFieldsFragment | ProposalQuery['proposal'];
|
||||||
|
networkParams: Partial<NetworkParamsResult>;
|
||||||
|
}) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { majorityMet, majorityLPMet, participationMet, participationLPMet } =
|
||||||
|
useVoteInformation({
|
||||||
|
proposal,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!proposal) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isUpdateMarket = proposal?.terms.change.__typename === 'UpdateMarket';
|
||||||
|
|
||||||
|
let requiredVotingMajority = null;
|
||||||
|
let requiredVotingMajorityLP = null;
|
||||||
|
|
||||||
|
if (networkParams) {
|
||||||
|
switch (proposal.terms.change.__typename) {
|
||||||
|
case 'NewMarket':
|
||||||
|
requiredVotingMajority =
|
||||||
|
networkParams.governance_proposal_market_requiredMajority;
|
||||||
|
break;
|
||||||
|
case 'UpdateMarket':
|
||||||
|
requiredVotingMajority =
|
||||||
|
networkParams.governance_proposal_updateMarket_requiredMajority;
|
||||||
|
requiredVotingMajorityLP =
|
||||||
|
networkParams.governance_proposal_updateMarket_requiredMajorityLP;
|
||||||
|
break;
|
||||||
|
case 'NewAsset':
|
||||||
|
requiredVotingMajority =
|
||||||
|
networkParams.governance_proposal_asset_requiredMajority;
|
||||||
|
break;
|
||||||
|
case 'UpdateAsset':
|
||||||
|
requiredVotingMajority =
|
||||||
|
networkParams.governance_proposal_updateAsset_requiredMajority;
|
||||||
|
break;
|
||||||
|
case 'UpdateNetworkParameter':
|
||||||
|
requiredVotingMajority =
|
||||||
|
networkParams.governance_proposal_updateNetParam_requiredMajority;
|
||||||
|
break;
|
||||||
|
case 'NewFreeform':
|
||||||
|
requiredVotingMajority =
|
||||||
|
networkParams.governance_proposal_freeform_requiredMajority;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isUpdateMarket) {
|
||||||
|
return (
|
||||||
|
<div className="mb-6">
|
||||||
|
<p>{t('Token vote')}</p>
|
||||||
|
<div
|
||||||
|
className="grid grid-cols-2 gap-4 items-center"
|
||||||
|
data-testid="token-vote-statuses"
|
||||||
|
>
|
||||||
|
<MajorityStatus
|
||||||
|
reached={majorityMet}
|
||||||
|
requiredMajority={requiredVotingMajority}
|
||||||
|
/>{' '}
|
||||||
|
<ParticipationStatus reached={participationMet} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p className="mt-4">{t('Liquidity provider vote')}</p>
|
||||||
|
<div
|
||||||
|
className="grid grid-cols-2 gap-4 items-center"
|
||||||
|
data-testid="lp-vote-statuses"
|
||||||
|
>
|
||||||
|
<MajorityStatus
|
||||||
|
reached={majorityLPMet}
|
||||||
|
requiredMajority={requiredVotingMajorityLP}
|
||||||
|
/>{' '}
|
||||||
|
<ParticipationStatus reached={participationLPMet} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="grid grid-cols-2 gap-4 items-center mb-6">
|
||||||
|
<MajorityStatus
|
||||||
|
reached={majorityMet}
|
||||||
|
requiredMajority={requiredVotingMajority}
|
||||||
|
/>{' '}
|
||||||
|
<ParticipationStatus reached={participationMet} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user