Compare commits

...
Author SHA1 Message Date
asiaznik c183fa39f8 fix(trading): missing wallet connect button 2023-10-03 10:38:44 +02:00
Joe Tsang 14928d318d chore(governance): add e2e tests for market update proposals (#4945) 2023-10-02 20:50:47 +01:00
m.ray a19ea1c939 fix(trading): update filter for market selector to include suspended via governance (#4957) 2023-10-02 18:00:49 +01:00
m.rayandMatthew Russell c65c296db2 feat(trading): ethereum oracle spec in oracle panels (#4914)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-10-02 17:48:12 +01:00
Maciek 6c5cd85d96 fix(deal-ticket): prevent empty call estimate position (#4950) 2023-10-02 18:26:10 +02:00
m.ray 8efadda98c fix(trading): remove market value proxy and formatting (#4916) 2023-10-02 16:00:55 +01:00
Maciek 0872a14f44 feat(positions): close position with max possible size (#4940) 2023-10-02 16:38:22 +02:00
Ben 13817e4d57 chore(trading): delete duplicate asset details test (#4954) 2023-10-02 13:57:54 +00:00
Matthew Russell 9da704c117 Merge pull request #4943 from vegaprotocol/chore/merge-main
chore(ci): merge main to develop
2023-09-29 12:11:25 -04:00
Rado d262650258 chore: merge main to develop 2023-09-29 17:46:20 +02:00
Radosław Szpiech 30da1663eb chore(ci): add main develop merge condition to runner (#4941) 2023-09-29 17:36:18 +02:00
Radosław Szpiech 79cbe62774 chore(ci): add mainnet compatible runner to release mainnet branch push actions (#4939) 2023-09-29 11:00:20 -04:00
Matthew Russell df11401b69 Merge pull request #4932 from vegaprotocol/main
chore(ci,trading): update develop with mainnet fixes
2023-09-29 10:33:42 -04:00
Maciek 2f0be0bf34 chore(trading): 4774 put connect dialog inside onboarding dialog - main branch (#4920) 2023-09-29 15:07:18 +02:00
Radosław Szpiech 5b5802104e chore(ci): trigger lint-pr on repoened and sync (#4937) 2023-09-29 15:03:58 +02:00
Radosław Szpiech 3a149ddfb2 chore(ci): add mainnet compatible runner to release mainnet branch push actions (#4936) 2023-09-29 14:01:04 +02:00
Sam Keen 0e519f4d0e feat(governance): market state update proposals (#4935) 2023-09-29 10:11:02 +01:00
Maciek ff2e2574f6 chore(trading): add handle of autosizing selected columns - main branch (#4888) 2023-09-28 15:14:32 -04:00
Joe Tsang 9b52cecf21 chore(governance): remove explorer market diff test (#4928) 2023-09-28 17:24:05 +01:00
Radosław Szpiech 478cc9e753 chore(ci): publish main image in dockerhub (#4930) 2023-09-28 17:38:00 +02:00
Ben 18f1fbd56d chore(trading): deal ticket order tests move (#4927) 2023-09-28 17:16:00 +02:00
Matthew Russell ccb22f02c3 chore(ci): fix conflict in vegacapsule genesis file 2023-09-28 10:44:22 -04:00
Radosław Szpiech 015d8f51c0 chore(ci): sync main to develop (#4924) 2023-09-28 14:43:02 +02:00
Radosław Szpiech e2a72cb395 chore(ci): separate lint pr (main) (#4917) 2023-09-28 14:01:36 +02:00
Radosław Szpiech 0669696b6f chore(ci): fix node version (develop) (#4910) 2023-09-28 13:30:50 +02:00
Joe Tsang 56c662e5ba test(governance): perpetual market e2e test (#4892) 2023-09-28 11:35:46 +02:00
Radosław Szpiech 7fe269fad6 chore(ci): fix node version (main) (#4911) 2023-09-28 11:26:15 +02:00
Radosław Szpiech b761023069 chore(ci): add logic for choosing correct runner for cypress tests depending on base branch (#4918) 2023-09-28 11:25:44 +02:00
Radosław Szpiech 7453acd632 chore(trading): separate workflow for lint-pr (#4904) 2023-09-27 14:44:57 -04:00
Sam Keen 1f507facba feat(governance): show perp or future pills (#4863) 2023-09-27 14:55:43 +01:00
Radosław Szpiech 9d6b34963a chore(trading): add possibility to manualy trigger console-test (#4899) (#4908) 2023-09-27 15:46:49 +02:00
Radosław Szpiech 7ac3a68ac9 chore(trading): add possibility to manualy trigger console-test (#4899) 2023-09-27 15:18:32 +02:00
Radosław Szpiech 2640ccb20a chore(trading): change runner for mainnet compatible vega version (#4907) 2023-09-27 14:42:12 +02:00
Matthew Russell 77c0894501 Merge pull request #4905 from vegaprotocol/chore/update-develop-with-mainnet-fixes
chore(trading,deal-ticket,market-depth,ci): update develop with mainnet fixes
2023-09-26 16:30:10 -04:00
Matthew Russell 60d7cf3029 Merge branch 'main' into chore/update-develop-with-mainnet-fixes 2023-09-26 15:06:07 -04:00
Matthew Russell 2b8abde938 Merge pull request #4880 from vegaprotocol/chore/update-develop-with-mainnet-fixes
chore(trading,governance): update develop with mainnet fixes
2023-09-26 14:06:20 -04:00
Matthew Russell 2005f19d50 fix(trading): prevent deposit sidebar showing on corresponding standalone page (#4840) 2023-09-26 13:47:47 -04:00
Maciek d78de10855 chore(trading): remove underlines on tooltips (#4884) 2023-09-26 13:45:33 -04:00
Matthew Russell bb402c02f6 chore(trading): make volume bars color match candle color (#4881) 2023-09-26 12:08:12 -04:00
Bartłomiej Głownia 8a9b1c7874 feat(deal-ticket): amend fee estimates for postOnly orders and when market is in auction (#4843) 2023-09-26 11:57:47 -04:00
Matthew Russell a7e8b0eb01 fix(market-depth): ensure scroll bar doesn't show on orderbook (#4882) 2023-09-26 11:54:42 -04:00
Bartłomiej Głownia 89b3c06107 feat(deal-ticket): show worst case instead of ranges in estimated values (#4870) 2023-09-26 11:53:45 -04:00
Radosław Szpiech cd5c73d3fd chore(trading): temporary disable console-test to unblock CI queue (#4885) 2023-09-26 10:45:27 +01:00
Joe Tsang b3a5ab022d chore(ci): update genesis file (#4887) 2023-09-26 10:44:55 +01:00
Matthew Russell ba438549bc Merge branch 'main' into chore/update-develop-with-mainnet-fixes 2023-09-25 21:30:40 -04:00
Mikołaj Młodzikowski 496d1f5c68 feat(ci): parse if there are any changes 2023-09-25 18:10:01 -04:00
Mikołaj Młodzikowski e914e7bb70 fix(ci): provide proper ipfs process 2023-09-25 18:09:31 -04:00
Matthew Russell 71a36c2382 fix(trading): remove upgrade banner [main] (#4877) 2023-09-25 17:27:01 -04:00
Matthew Russell 1c6a307bcd fix(wallet): reduce time to check for wallet running [main] (#4876) 2023-09-25 17:26:40 -04:00
Matthew Russell ef4a740b91 fix(trading): allotment breaking [main] (#4875) 2023-09-25 17:26:06 -04:00
a6303456c5 feat(trading): liquidity SLA in market info (#4649)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
Co-authored-by: candida-d <62548908+candida-d@users.noreply.github.com>
Co-authored-by: Bartłomiej Głownia <bglownia@gmail.com>
Co-authored-by: Joe Tsang <30622993+jtsang586@users.noreply.github.com>
Co-authored-by: Joe <joe@vega.xyz>
2023-09-25 14:44:55 +01:00
Sam Keen 2d4be5fcb3 fix(governance): mainnet rewards query looping (#4865) 2023-09-25 09:59:38 +00:00
Sam Keen 9cbd6baccd fix(governance): removed loop caused by rewards epoch refresh (#4864) 2023-09-25 09:34:47 +00:00
Maciek 525773773a chore(trading): 4811 make market table columns resizable (#4856) 2023-09-25 10:14:18 +02:00
Ben 45d6f43e74 chore(trading): deal ticket test to jest (#4842) 2023-09-22 15:25:50 +01:00
Art 41760f2956 chore(trading): disable apply code when applied (#4855) 2023-09-22 12:06:02 +01:00
Maciek 3d2b171de7 chore(trading): 4774 put connect dialog inside onboarding dialog (#4845) 2023-09-22 11:04:02 +02:00
Joe Tsang 39a041332b chore(governance): fix failing proposal submission (#4835) 2023-09-22 09:40:35 +01:00
Bartłomiej Głownia 4c0d05844e feat(trading): improve funding rate formatting (#4847) 2023-09-22 09:39:56 +01:00
Matthew Russell bf8480fed4 chore(trading): remove upgrade banner (#4852) 2023-09-22 09:39:26 +01:00
ArtandMatthew Russell 44434a7d39 feat(trading): referrals (Mk1) (#4816)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-09-21 14:25:19 +01:00
m.ray b818e9b2a1 fix(trading): ignore conditions list empty (#4848) 2023-09-21 14:24:21 +01:00
Radosław Szpiech 775835c667 chore(trading): disable console-test run until CI fixed (#4846) 2023-09-21 14:32:17 +02:00
Matthew Russell 3e30f053ff chore(trading): routing and link changes (#4738) 2023-09-20 13:28:34 -07:00
Bartłomiej GłowniaandMatthew Russell 5db3453ba5 fix(accounts): hide no rows label when there is only pinned row (#4833)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-09-20 20:03:07 +00:00
Matthew Russell 0b1987d4ce chore(trading,governance,explorer): prevent jobs if PR is in draft (#4827) 2023-09-20 11:13:43 -07:00
290b7ae856 feat(trading): browse perpetuals [stagnet1] (#4590)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
Co-authored-by: Bartłomiej Głownia <bglownia@gmail.com>
Co-authored-by: Joe Tsang <30622993+jtsang586@users.noreply.github.com>
Co-authored-by: Joe <joe@vega.xyz>
2023-09-20 10:11:03 +01:00
m.rayandMatthew Russell 835f2b793f chore(trading): remove static assets console coming from vega.xyz (#4825)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-09-19 23:54:07 -07:00
Mikołaj Młodzikowski e1557f51ce feat(ci): parse if there are any changes 2023-09-19 10:05:00 +02:00
Mikołaj Młodzikowski c98e53a984 fix(ci): provide proper ipfs process 2023-09-19 09:55:21 +02:00
MaciekandMatthew Russell 95a51fd152 chore(withdraws): standalone pages for withdraw and transfer (#4728)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-09-19 08:15:36 +02:00
Matthew Russell d50b988b4a Merge branch 'release/mainnet-trading' of github.com:vegaprotocol/frontend-monorepo into release/mainnet-trading 2023-09-18 09:03:44 -07:00
m.ray 76ee58e473 chore(trading): update tag metamask snaps to true (#4815) 2023-09-18 15:19:48 +01:00
Madalina Raicu a6aec899c8 chore: update tag metamask snaps to true 2023-09-18 15:08:46 +01:00
Mikołaj Młodzikowski a6672d213f fix(ci): provide better endpoint 2023-09-18 13:17:37 +02:00
Radosław Szpiech 62f368da10 chore(trading): cache console test vega binaries (#4752) 2023-09-18 09:28:15 +00:00
daro-maj f3e2fe746d test(trading): fix test for release v0.21.2 (#4806) 2023-09-18 08:40:35 +02:00
Mikołaj Młodzikowski 8b19572dc9 feat(ci): proper run 2023-09-15 13:07:55 -07:00
Mikołaj Młodzikowski 80399d04f7 feat(ci): patch releasing to ipfs 2023-09-15 17:03:50 +02:00
m.ray 8322fc7edd chore: bump version (#4805) 2023-09-15 15:46:02 +01:00
46752816ec chore(trading): get started section for deposit (#4783)
Co-authored-by: maciek <maciek@vegaprotocol.io>
Co-authored-by: Madalina Raicu <madalina@raygroup.uk>
2023-09-15 15:10:38 +01:00
Sam Keen f99f78780c fix(markets): market info for liquidity is showing "added" tags (#4796) 2023-09-15 13:54:17 +01:00
Maciek f7037bca80 chore(deal-ticket): 4743 preserve estimate position cache in deal ticket (#4770) 2023-09-15 13:53:24 +01:00
Matthew RussellandMadalina Raicu ba39720f05 fix(trading,web3): prevent deposit toasts reappearing (#4797)
Co-authored-by: Madalina Raicu <madalina@raygroup.uk>
2023-09-15 13:51:28 +01:00
MaciekandMadalina Raicu 6d35f2b39d chore(trading): 4764 remember closed sidebar (#4799)
Co-authored-by: Madalina Raicu <madalina@raygroup.uk>
2023-09-15 13:36:08 +01:00
Matthew Russell 78afecc2e5 chore(trading): layout adjustments to accomodate default 13 inch screens (#4798) 2023-09-15 13:24:47 +01:00
Bartłomiej Głownia 3de5b07495 fix(trading): add overflow hidden to candles tab container (#4803) 2023-09-15 13:13:05 +01:00
Matthew Russell e944d3e37c fix(trading): correct link for get started prompt (#4782) 2023-09-15 13:12:39 +01:00
Joe Tsang 5596392835 chore(governance): fix failing staking test (#4801) 2023-09-15 13:04:42 +01:00
Ben 5c57106c04 chore(trading): delete market info tests (#4804) 2023-09-15 14:45:52 +03:00
Ben 2fc688f477 chore(trading): fix wallet test (#4802) 2023-09-15 14:45:15 +03:00
Mikołaj Młodzikowski 9ea8c839db feat(ci): use ipfs daemon in dockerfiles (#4786) 2023-09-15 08:48:25 +02:00
Matthew Russell d7e2da7a54 fix(trading): missing styles for tooltip in positions table (#4780) 2023-09-14 14:00:59 -07:00
m.ray b29c268257 chore(trading): add oracle proofs url to all envs (#4793) 2023-09-14 13:57:28 -07:00
m.rayandMatthew Russell 01ca05a313 chore(trading): update governance variables (#4766)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-09-14 13:57:15 -07:00
Matthew Russell e3c6dd41c9 fix(trading): simplify onboarding and explore button to use top traded (#4781) 2023-09-14 12:10:33 -07:00
Bartłomiej GłowniaandMatthew Russell fbd01dc1bd fix(trading): use asset decimals to format liquidation price in posions table (#4787)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-09-14 11:18:58 -07:00
m.rayandMatthew Russell af6719cc9d chore(trading): add governance link to top level nav (#4765)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-09-13 14:25:31 -07:00
Sam KeenandJoe c433a4ee06 feat(governance): more mobile view improvements (#4751)
Co-authored-by: Joe <joe@vega.xyz>
2023-09-13 19:01:33 +01:00
Matthew Russell e3a00ada05 chore(trading,governance,explorer): update pr template to ensure issues get linked 2023-09-13 08:30:06 -07:00
Joe Tsang aa38e0c001 test(governance): add assert for numerical sort (#4742) 2023-09-13 13:02:47 +01:00
Joe Tsang 86da521da5 test(governance): flaky test fixes (#4760) 2023-09-13 11:53:22 +01:00
Matthew Russell c6df34fe95 chore(trading): bump app version and enable snaps 2023-09-12 13:40:08 -07:00
Matthew Russell c7d0803164 chore(trading): make closed market table rows the correct height 2023-09-12 12:47:47 -07:00
m.ray 250a654544 feat(trading): margin required progressive disclosure (#4755) 2023-09-12 12:06:47 -07:00
Matthew Russell 7f5e8ebb15 chore(trading): replace successor cols with market code cell (#4722) 2023-09-12 11:52:03 -07:00
Art ccbe34e172 chore(trading): make deal ticket open on market change (#4749) 2023-09-12 11:26:54 -07:00
Maciek 27e8ce88bf chore(trading): adjust onboarding experience (#4754) 2023-09-12 11:10:17 -07:00
ArtandMatthew Russell 41804d9869 chore(trading): market list tweaks (#4756)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-09-12 10:41:45 -07:00
Maciek 293288286b chore(trading): adjust gap between candles (#4753) 2023-09-12 09:59:13 -07:00
Matthew Russell a77765b1e9 feat(trading): store study sizes, reduce candles gap (#4708) 2023-09-12 09:56:43 -07:00
401 changed files with 10380 additions and 4986 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
# Related issues 🔗 # Related issues 🔗
Issue: #[Issue number here] Closes #[Issue number here]
# Description # Description
+10 -16
View File
@@ -10,10 +10,11 @@ on:
- opened - opened
- ready_for_review - ready_for_review
- reopened - reopened
- edited
- synchronize - synchronize
jobs: jobs:
node-modules: node-modules:
# All jobs depend on node_modules, so none should run if the PR is in draft
if: github.event.pull_request.draft == false
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
name: 'Cache yarn modules' name: 'Cache yarn modules'
steps: steps:
@@ -42,13 +43,6 @@ jobs:
if: steps.cache.outputs.cache-hit != 'true' if: steps.cache.outputs.cache-hit != 'true'
run: yarn install --pure-lockfile run: yarn install --pure-lockfile
lint-pr-title:
needs: node-modules
if: ${{ github.event_name == 'pull_request' }}
name: Verify PR title
uses: ./.github/workflows/lint-pr.yml
secrets: inherit
lint-format: lint-format:
timeout-minutes: 20 timeout-minutes: 20
needs: node-modules needs: node-modules
@@ -175,14 +169,14 @@ jobs:
preview_explorer: ${{ env.PREVIEW_EXPLORER }} preview_explorer: ${{ env.PREVIEW_EXPLORER }}
preview_tools: ${{ env.PREVIEW_TOOLS }} preview_tools: ${{ env.PREVIEW_TOOLS }}
console-e2e: # console-e2e:
needs: build-sources # needs: build-sources
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.build-sources.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: build-sources
+62 -9
View File
@@ -1,28 +1,45 @@
name: (CI) Console tests name: (CI) Console tests
env:
VEGA_VERSION: v0.72.14
on: on:
workflow_call: workflow_call:
inputs: inputs:
github-sha: github-sha:
required: true required: true
type: string type: string
workflow_dispatch:
inputs:
console-test-branch:
type: choice
description: 'main: v0.72.14, develop: v0.73.0-preview7'
options:
- main
- develop
jobs: jobs:
run-tests: run-tests:
name: run-tests name: run-tests
runs-on: console-test runs-on: 8-cores
timeout-minutes: 20 timeout-minutes: 20
steps: steps:
#---------------------------------------------- #----------------------------------------------
# check-out frontend-monorepo # check-out frontend-monorepo
#---------------------------------------------- #----------------------------------------------
- name: Checkout console test repo - name: Checkout frontend-monorepo
uses: actions/checkout@v3 uses: actions/checkout@v3
with: with:
ref: ${{ inputs.github-sha }} ref: ${{ inputs.github-sha || github.sha }}
#---------------------------------------------- #----------------------------------------------
# cache node modules # cache node modules
#---------------------------------------------- #----------------------------------------------
- name: setup node
uses: actions/setup-node@v3
with:
node-version: '16'
cache: yarn
- name: Cache node modules - name: Cache node modules
id: cache id: cache
uses: actions/cache@v3 uses: actions/cache@v3
@@ -65,32 +82,58 @@ jobs:
uses: actions/checkout@v3 uses: actions/checkout@v3
with: with:
repository: vegaprotocol/console-test repository: vegaprotocol/console-test
ref: ${{ inputs.console-test-branch }}
path: './console-test' path: './console-test'
- name: Load console test envs
id: console-test-env
uses: falti/dotenv-action@v1.0.4
with:
path: './console-test/.env.${{ inputs.console-test-branch }}'
export-variables: true
keys-case: upper
log-variables: true
#---------------------------------------------- #----------------------------------------------
# install dependencies if cache does not exist # install dependencies
#---------------------------------------------- #----------------------------------------------
- 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
#---------------------------------------------- #----------------------------------------------
# install vega binaries # find vega binaries path
#----------------------------------------------
- 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
run: poetry run python -m vega_sim.tools.load_binaries --force run: poetry run python -m vega_sim.tools.load_binaries --force --version ${{ env.VEGA_VERSION }}
#---------------------------------------------- #----------------------------------------------
# install playwright # install playwright
#---------------------------------------------- #----------------------------------------------
- name: install playwright - name: install playwright
run: poetry run playwright install run: poetry run playwright install --with-deps chromium
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 -v -s --numprocesses 4 --dist loadfile --durations=15
- name: Check files - name: Check files
run: | run: |
ls -al . ls -al .
@@ -105,3 +148,13 @@ jobs:
name: playwright-trace name: playwright-trace
path: ./traces/ path: ./traces/
retention-days: 15 retention-days: 15
#----------------------------------------------
# ----- upload logs -----
#----------------------------------------------
- name: Upload worker logs
uses: actions/upload-artifact@v3
if: always()
with:
name: worker-logs
path: ./logs/
retention-days: 15
+23 -1
View File
@@ -13,13 +13,35 @@ on:
type: string type: string
jobs: jobs:
runner-choice:
runs-on: ubuntu-latest
outputs:
runner: ${{ steps.step.outputs.runner }}
steps:
- name: Check branch
id: step
run: |
if [ ${{ github.base_ref }} == 'main' ]; then
echo "runner=mainnet-compatible-runner" >> $GITHUB_OUTPUT
elif [ ${{ github.base_ref }} == 'develop' ] && [ ${{ github.ref_name }} == 'main' ]; then
echo "runner=mainnet-compatible-runner" >> $GITHUB_OUTPUT
elif [ ${{ github.event_name }} == 'push' ] && [ ${{ contains(github.ref_name, 'release/mainnet') }} ]; then
echo "runner=mainnet-compatible-runner" >> $GITHUB_OUTPUT
else
echo "runner=self-hosted-runner" >> $GITHUB_OUTPUT
fi
- name: Print runner
run: echo ${{ steps.step.outputs.runner }}
e2e: e2e:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
project: ${{ fromJSON(inputs.projects) }} project: ${{ fromJSON(inputs.projects) }}
name: ${{ matrix.project }} name: ${{ matrix.project }}
runs-on: self-hosted-runner needs: runner-choice
runs-on: ${{ needs.runner-choice.outputs.runner }}
timeout-minutes: 120 timeout-minutes: 120
steps: steps:
# Checks if skip cache was requested # Checks if skip cache was requested
+11 -11
View File
@@ -2,7 +2,12 @@
name: Verify PR title name: Verify PR title
on: on:
workflow_call: pull_request:
types:
- opened
- edited
- reopened
- synchronize
jobs: jobs:
lint_pr: lint_pr:
@@ -11,21 +16,16 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- name: Setup node - name: Setup node
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version-file: '.nvmrc' node-version: 16
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
cache: yarn
- name: Cache node modules - name: Install dependencies
uses: actions/cache@v3 run: |
with: rm package.json
path: node_modules npm install --no-save @commitlint/cli @commitlint/config-conventional @commitlint/config-nx-scopes nx
key: ${{ runner.os }}-cache-node-modules-${{ hashFiles('yarn.lock') }}
- name: Check PR title - name: Check PR title
run: echo "${{ github.event.pull_request.title }}" | npx commitlint --config ./commitlint.config-ci.js run: echo "${{ github.event.pull_request.title }}" | npx commitlint --config ./commitlint.config-ci.js
+19 -11
View File
@@ -30,12 +30,18 @@ jobs:
echo IS_IPFS_RELEASE=false >> $GITHUB_ENV echo IS_IPFS_RELEASE=false >> $GITHUB_ENV
echo IS_S3_RELEASE=false >> $GITHUB_ENV echo IS_S3_RELEASE=false >> $GITHUB_ENV
echo IS_DEV_IMAGE=false >> $GITHUB_ENV echo IS_DEV_IMAGE=false >> $GITHUB_ENV
echo IS_MAIN_IMAGE=false >> $GITHUB_ENV
- name: Is dev image - name: Is dev image
if: ${{ contains(github.ref, 'develop') && github.event_name == 'push' && matrix.app == 'trading' }} if: ${{ github.ref_name == 'develop' && github.event_name == 'push' && matrix.app == 'trading' }}
run: | run: |
echo IS_DEV_IMAGE=true >> $GITHUB_ENV echo IS_DEV_IMAGE=true >> $GITHUB_ENV
- name: Is main image
if: ${{ github.ref_name == 'main' && github.event_name == 'push' && matrix.app == 'trading' }}
run: |
echo IS_MAIN_IMAGE=true >> $GITHUB_ENV
- name: Is PR - name: Is PR
if: ${{ github.event_name == 'pull_request' }} if: ${{ github.event_name == 'pull_request' }}
run: | run: |
@@ -81,7 +87,7 @@ jobs:
- name: Log in to the Container registry (docker hub) - name: Log in to the Container registry (docker hub)
uses: docker/login-action@v2 uses: docker/login-action@v2
if: ${{ env.IS_IPFS_RELEASE == 'true' || env.IS_DEV_IMAGE == 'true' }} if: ${{ env.IS_IPFS_RELEASE == 'true' || env.IS_DEV_IMAGE == 'true' || env.IS_MAIN_IMAGE == 'true' }}
with: with:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
@@ -155,10 +161,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 ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local cat /ipfs-hash docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local /bin/sh -c 'cat /ipfs-hash'
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local cat /ipfs-hash > ${{ matrix.app }}-ipfs-hash docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local /bin/sh -c 'cat /ipfs-hash' > ${{ matrix.app }}-ipfs-hash
echo "List html directory" echo "List html directory"
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local sh -c 'apk add --update tree; tree /usr/share/nginx/html' docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local /bin/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
@@ -179,7 +185,7 @@ jobs:
uses: docker/build-push-action@v3 uses: docker/build-push-action@v3
continue-on-error: true continue-on-error: true
id: dockerhub-push id: dockerhub-push
if: ${{ env.IS_IPFS_RELEASE == 'true' || env.IS_DEV_IMAGE == 'true' }} if: ${{ env.IS_IPFS_RELEASE == 'true' || env.IS_DEV_IMAGE == 'true' || env.IS_MAIN_IMAGE == 'true' }}
with: with:
context: . context: .
file: docker/node-outside-docker.Dockerfile file: docker/node-outside-docker.Dockerfile
@@ -189,7 +195,7 @@ jobs:
ENV_NAME=${{ env.ENV_NAME }} ENV_NAME=${{ env.ENV_NAME }}
tags: | tags: |
vegaprotocol/${{ matrix.app }}:${{ github.sha }} vegaprotocol/${{ matrix.app }}:${{ github.sha }}
vegaprotocol/${{ matrix.app }}:${{ env.IS_MAINNET_RELEASE == 'true' && 'mainnet' || env.IS_TESTNET_RELEASE == 'true' && 'testnet' || env.IS_DEV_IMAGE == 'true' && 'develop' || '' }} vegaprotocol/${{ matrix.app }}:${{ env.IS_MAINNET_RELEASE == 'true' && 'mainnet' || env.IS_TESTNET_RELEASE == 'true' && 'testnet' || env.IS_DEV_IMAGE == 'true' && 'develop' || env.IS_MAIN_IMAGE == 'true && main' || '' }}
- name: Publish dist as docker image (ghcr - retry) - name: Publish dist as docker image (ghcr - retry)
uses: docker/build-push-action@v3 uses: docker/build-push-action@v3
@@ -216,7 +222,7 @@ jobs:
ENV_NAME=${{ env.ENV_NAME }} ENV_NAME=${{ env.ENV_NAME }}
tags: | tags: |
vegaprotocol/${{ matrix.app }}:${{ github.sha }} vegaprotocol/${{ matrix.app }}:${{ github.sha }}
vegaprotocol/${{ matrix.app }}:${{ env.IS_MAINNET_RELEASE == 'true' && 'mainnet' || env.IS_TESTNET_RELEASE == 'true' && 'testnet' || '' }} vegaprotocol/${{ matrix.app }}:${{ env.IS_MAINNET_RELEASE == 'true' && 'mainnet' || env.IS_TESTNET_RELEASE == 'true' && 'testnet' || env.IS_DEV_IMAGE == 'true' && 'develop' || env.IS_MAIN_IMAGE == 'true && main' || '' }}
# bucket creation in github.com/vegaprotocol/terraform//frontend # bucket creation in github.com/vegaprotocol/terraform//frontend
- name: Publish dist to s3 - name: Publish dist to s3
@@ -329,7 +335,9 @@ jobs:
fi fi
# create commit # create commit
commit_msg="Automated hash update from ${{ github.ref }}" if ! git diff --cached --exit-code; then
git commit -m "$commit_msg" commit_msg="Automated hash update from ${{ github.ref }}"
git push -u origin "main" git commit -m "$commit_msg"
git push -u origin "main"
fi
) )
+15 -1
View File
@@ -113,6 +113,20 @@ 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] /run-ipfs.sh
```
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.
@@ -150,7 +164,7 @@ 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 --dockerfile docker/node-outside-docker.Dockerfile . --tag=[TAG] docker build -f docker/node-outside-docker.Dockerfile . --tag=[TAG]
``` ```
### Verifying ipfs-hash of existing current application version ### Verifying ipfs-hash of existing current application version
+2
View File
@@ -4,6 +4,8 @@ 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
+1
View File
@@ -4,6 +4,7 @@ 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
+1
View File
@@ -4,6 +4,7 @@ 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
@@ -87,7 +87,6 @@ context('Market page', { tags: '@regression' }, function () {
// Liquidity // Liquidity
cy.validate_element_from_table('Target Stake', '0.00 fUSDC'); cy.validate_element_from_table('Target Stake', '0.00 fUSDC');
cy.validate_element_from_table('Supplied Stake', '0.00 fUSDC'); cy.validate_element_from_table('Supplied Stake', '0.00 fUSDC');
cy.validate_element_from_table('Market Value Proxy', '0.00 fUSDC');
// Liquidity price range // Liquidity price range
cy.validate_element_from_table( cy.validate_element_from_table(
'Liquidity Price Range', 'Liquidity Price Range',
@@ -95,7 +94,6 @@ context('Market page', { tags: '@regression' }, function () {
); );
cy.validate_element_from_table('Lowest Price', '0.00 fUSDC'); cy.validate_element_from_table('Lowest Price', '0.00 fUSDC');
cy.validate_element_from_table('Highest Price', '0.00 fUSDC'); cy.validate_element_from_table('Highest Price', '0.00 fUSDC');
cy.getByTestId('oracle-spec-links') cy.getByTestId('oracle-spec-links')
.should('have.attr', 'href') .should('have.attr', 'href')
.and( .and(
@@ -144,11 +142,8 @@ context('Market page', { tags: '@regression' }, function () {
.as('successorMarketId'); .as('successorMarketId');
cy.contains('Token test market').click(); cy.contains('Token test market').click();
cy.getByTestId(marketHeaders).should('have.text', 'Token test market'); cy.getByTestId(marketHeaders).should('have.text', 'Token test market');
cy.validate_proposal_change_type('Triggering Ratio', 'Added');
cy.validate_element_from_table('Triggering Ratio', '0.7'); cy.validate_element_from_table('Triggering Ratio', '0.7');
cy.validate_proposal_change_type('Time Window', 'Added');
cy.validate_element_from_table('Time Window', '3,600'); cy.validate_element_from_table('Time Window', '3,600');
cy.validate_proposal_change_type('Scaling Factor', 'Added');
cy.validate_element_from_table('Scaling Factor', '10'); cy.validate_element_from_table('Scaling Factor', '10');
cy.getByTestId(successionLineItem) cy.getByTestId(successionLineItem)
@@ -26,7 +26,6 @@ function getSuccessorTxBody(parentMarketId) {
positionDecimalPlaces: '5', positionDecimalPlaces: '5',
linearSlippageFactor: '0.001', linearSlippageFactor: '0.001',
quadraticSlippageFactor: '0', quadraticSlippageFactor: '0',
lpPriceRange: '10',
instrument: { instrument: {
name: 'Token test market', name: 'Token test market',
code: 'TEST.24h', code: 'TEST.24h',
@@ -130,6 +129,12 @@ function getSuccessorTxBody(parentMarketId) {
parentMarketId: parentMarketId, parentMarketId: parentMarketId,
insurancePoolFraction: '0.75', insurancePoolFraction: '0.75',
}, },
liquiditySlaParameters: {
priceRange: '0.95',
commitmentMinTimeFraction: '0.5',
performanceHysteresisEpochs: 2,
slaCompetitionFactor: '0.75',
},
}, },
}, },
closingTimestamp, closingTimestamp,
+1
View File
@@ -3,6 +3,7 @@ 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
+1
View File
@@ -8,6 +8,7 @@ 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
+1
View File
@@ -9,6 +9,7 @@ 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
+1
View File
@@ -9,6 +9,7 @@ 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
View File
@@ -1,2 +1,3 @@
# .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
+1
View File
@@ -9,6 +9,7 @@ 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
+1
View File
@@ -11,6 +11,7 @@ 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
+2 -1
View File
@@ -5,4 +5,5 @@ 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
@@ -4,7 +4,7 @@ import { AssetTypeMapping, AssetStatusMapping } from '@vegaprotocol/assets';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/i18n';
import { ButtonLink } from '@vegaprotocol/ui-toolkit'; import { ButtonLink } from '@vegaprotocol/ui-toolkit';
import type { AgGridReact } from 'ag-grid-react'; import type { AgGridReact } from 'ag-grid-react';
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid'; import { AgGrid } from '@vegaprotocol/datagrid';
import type { VegaICellRendererParams } from '@vegaprotocol/datagrid'; import type { VegaICellRendererParams } from '@vegaprotocol/datagrid';
import { useRef, useLayoutEffect } from 'react'; import { useRef, useLayoutEffect } from 'react';
import { BREAKPOINT_MD } from '../../config/breakpoints'; import { BREAKPOINT_MD } from '../../config/breakpoints';
@@ -13,6 +13,12 @@ query ExplorerMarket($id: ID!) {
decimals decimals
} }
} }
... on Perpetual {
quoteName
settlementAsset {
decimals
}
}
} }
} }
} }
@@ -8,7 +8,7 @@ export type ExplorerMarketQueryVariables = Types.Exact<{
}>; }>;
export type ExplorerMarketQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', decimals: number } } } } } | null }; export type ExplorerMarketQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', decimals: number } } | { __typename?: 'Perpetual', quoteName: string, settlementAsset: { __typename?: 'Asset', decimals: number } } | { __typename?: 'Spot' } } } } | null };
export const ExplorerMarketDocument = gql` export const ExplorerMarketDocument = gql`
@@ -27,6 +27,12 @@ export const ExplorerMarketDocument = gql`
decimals decimals
} }
} }
... on Perpetual {
quoteName
settlementAsset {
decimals
}
}
} }
} }
} }
@@ -61,6 +61,7 @@ describe('Market link component', () => {
instrument: { instrument: {
name: 'test-label', name: 'test-label',
product: { product: {
__typename: 'Future',
quoteName: 'dai', quoteName: 'dai',
}, },
}, },
@@ -1,15 +1,18 @@
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/i18n';
import type { MarketInfoWithData } from '@vegaprotocol/markets'; import type { MarketInfoWithData } from '@vegaprotocol/markets';
import { import {
LiquidityPriceRangeInfoPanel,
LiquiditySLAParametersInfoPanel,
PriceMonitoringBoundsInfoPanel, PriceMonitoringBoundsInfoPanel,
SuccessionLineInfoPanel, SuccessionLineInfoPanel,
getDataSourceSpecForSettlementData,
getDataSourceSpecForTradingTermination,
} from '@vegaprotocol/markets'; } from '@vegaprotocol/markets';
import { import {
LiquidityInfoPanel, LiquidityInfoPanel,
LiquidityMonitoringParametersInfoPanel, LiquidityMonitoringParametersInfoPanel,
InstrumentInfoPanel, InstrumentInfoPanel,
KeyDetailsInfoPanel, KeyDetailsInfoPanel,
LiquidityPriceRangeInfoPanel,
MetadataInfoPanel, MetadataInfoPanel,
OracleInfoPanel, OracleInfoPanel,
RiskFactorsInfoPanel, RiskFactorsInfoPanel,
@@ -18,20 +21,21 @@ import {
SettlementAssetInfoPanel, SettlementAssetInfoPanel,
} from '@vegaprotocol/markets'; } from '@vegaprotocol/markets';
import { MarketInfoTable } from '@vegaprotocol/markets'; import { MarketInfoTable } from '@vegaprotocol/markets';
import type { DataSourceDefinition } from '@vegaprotocol/types'; import type { DataSourceFragment } from '@vegaprotocol/markets';
import isEqual from 'lodash/isEqual'; import isEqual from 'lodash/isEqual';
export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => { export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
if (!market) return null; if (!market) return null;
const { product } = market.tradableInstrument.instrument;
const settlementDataSource = getDataSourceSpecForSettlementData(product);
const terminationDataSource = getDataSourceSpecForTradingTermination(product);
const settlementData = market.tradableInstrument.instrument.product const getSigners = ({ data }: DataSourceFragment) => {
.dataSourceSpecForSettlementData.data as DataSourceDefinition;
const terminationData = market.tradableInstrument.instrument.product
.dataSourceSpecForTradingTermination.data as DataSourceDefinition;
const getSigners = (data: DataSourceDefinition) => {
if (data.sourceType.__typename === 'DataSourceDefinitionExternal') { if (data.sourceType.__typename === 'DataSourceDefinitionExternal') {
const signers = data.sourceType.sourceType.signers || []; const signers =
('signers' in data.sourceType.sourceType &&
data.sourceType.sourceType.signers) ||
[];
return signers.map(({ signer }, i) => { return signers.map(({ signer }, i) => {
return ( return (
@@ -43,10 +47,13 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
return []; return [];
}; };
const showTwoOracles = isEqual( const showTwoOracles =
getSigners(settlementData), settlementDataSource &&
getSigners(terminationData) terminationDataSource &&
); isEqual(
getSigners(settlementDataSource),
getSigners(terminationDataSource)
);
const headerClassName = 'font-alpha calt text-xl mt-4 border-b-2 pb-2'; const headerClassName = 'font-alpha calt text-xl mt-4 border-b-2 pb-2';
@@ -89,10 +96,12 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
)} )}
<h2 className={headerClassName}>{t('Liquidity monitoring')}</h2> <h2 className={headerClassName}>{t('Liquidity monitoring')}</h2>
<LiquidityMonitoringParametersInfoPanel market={market} /> <LiquidityMonitoringParametersInfoPanel market={market} />
<h2 className={headerClassName}>{t('Liquidity')}</h2>
<LiquidityInfoPanel market={market} />
<h2 className={headerClassName}>{t('Liquidity price range')}</h2> <h2 className={headerClassName}>{t('Liquidity price range')}</h2>
<LiquidityPriceRangeInfoPanel market={market} /> <LiquidityPriceRangeInfoPanel market={market} />
<h2 className={headerClassName}>{t('Liquidity SLA protocol')}</h2>
<LiquiditySLAParametersInfoPanel market={market} />
<h2 className={headerClassName}>{t('Liquidity')}</h2>
<LiquidityInfoPanel market={market} />
{showTwoOracles ? ( {showTwoOracles ? (
<> <>
<h2 className={headerClassName}>{t('Settlement oracle')}</h2> <h2 className={headerClassName}>{t('Settlement oracle')}</h2>
@@ -1,10 +1,10 @@
import { useMemo } from 'react'; import { useMemo } from 'react';
import type { MarketFieldsFragment } from '@vegaprotocol/markets'; import { getAsset, type MarketFieldsFragment } from '@vegaprotocol/markets';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/i18n';
import { ButtonLink } from '@vegaprotocol/ui-toolkit'; import { ButtonLink } from '@vegaprotocol/ui-toolkit';
import type { AgGridReact } from 'ag-grid-react'; import type { AgGridReact } from 'ag-grid-react';
import type { ColDef } from 'ag-grid-community'; import type { ColDef } from 'ag-grid-community';
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid'; import { AgGrid } from '@vegaprotocol/datagrid';
import type { import type {
VegaICellRendererParams, VegaICellRendererParams,
VegaValueGetterParams, VegaValueGetterParams,
@@ -73,8 +73,7 @@ export const MarketsTable = ({ data }: MarketsTableProps) => {
MarketFieldsFragment, MarketFieldsFragment,
'tradableInstrument.instrument.product.settlementAsset.symbol' 'tradableInstrument.instrument.product.settlementAsset.symbol'
>) => { >) => {
const value = const value = data && getAsset(data);
data?.tradableInstrument.instrument.product.settlementAsset;
return value ? ( return value ? (
<ButtonLink <ButtonLink
onClick={(e) => { onClick={(e) => {
@@ -31,6 +31,9 @@ fragment ExplorerDeterministicOrderFields on Order {
... on Future { ... on Future {
quoteName quoteName
} }
... on Perpetual {
quoteName
}
} }
} }
} }
@@ -3,7 +3,7 @@ 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 ExplorerDeterministicOrderFieldsFragment = { __typename?: 'Order', id: string, type?: Types.OrderType | null, reference: string, status: Types.OrderStatus, version: string, createdAt: any, updatedAt?: any | null, expiresAt?: any | null, timeInForce: Types.OrderTimeInForce, price: string, side: Types.Side, remaining: string, size: string, rejectionReason?: Types.OrderRejectionReason | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null, party: { __typename?: 'Party', id: string }, market: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } } } } }; export type ExplorerDeterministicOrderFieldsFragment = { __typename?: 'Order', id: string, type?: Types.OrderType | null, reference: string, status: Types.OrderStatus, version: string, createdAt: any, updatedAt?: any | null, expiresAt?: any | null, timeInForce: Types.OrderTimeInForce, price: string, side: Types.Side, remaining: string, size: string, rejectionReason?: Types.OrderRejectionReason | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null, party: { __typename?: 'Party', id: string }, market: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } | { __typename?: 'Perpetual', quoteName: string } | { __typename?: 'Spot' } } } } };
export type ExplorerDeterministicOrderQueryVariables = Types.Exact<{ export type ExplorerDeterministicOrderQueryVariables = Types.Exact<{
orderId: Types.Scalars['ID']; orderId: Types.Scalars['ID'];
@@ -11,7 +11,7 @@ export type ExplorerDeterministicOrderQueryVariables = Types.Exact<{
}>; }>;
export type ExplorerDeterministicOrderQuery = { __typename?: 'Query', orderByID: { __typename?: 'Order', id: string, type?: Types.OrderType | null, reference: string, status: Types.OrderStatus, version: string, createdAt: any, updatedAt?: any | null, expiresAt?: any | null, timeInForce: Types.OrderTimeInForce, price: string, side: Types.Side, remaining: string, size: string, rejectionReason?: Types.OrderRejectionReason | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null, party: { __typename?: 'Party', id: string }, market: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } } } } } }; export type ExplorerDeterministicOrderQuery = { __typename?: 'Query', orderByID: { __typename?: 'Order', id: string, type?: Types.OrderType | null, reference: string, status: Types.OrderStatus, version: string, createdAt: any, updatedAt?: any | null, expiresAt?: any | null, timeInForce: Types.OrderTimeInForce, price: string, side: Types.Side, remaining: string, size: string, rejectionReason?: Types.OrderRejectionReason | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null, party: { __typename?: 'Party', id: string }, market: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } | { __typename?: 'Perpetual', quoteName: string } | { __typename?: 'Spot' } } } } } };
export const ExplorerDeterministicOrderFieldsFragmentDoc = gql` export const ExplorerDeterministicOrderFieldsFragmentDoc = gql`
fragment ExplorerDeterministicOrderFields on Order { fragment ExplorerDeterministicOrderFields on Order {
@@ -47,6 +47,9 @@ export const ExplorerDeterministicOrderFieldsFragmentDoc = gql`
... on Future { ... on Future {
quoteName quoteName
} }
... on Perpetual {
quoteName
}
} }
} }
} }
@@ -150,6 +150,7 @@ function renderExistingAmend(
instrument: { instrument: {
name: 'test-label', name: 'test-label',
product: { product: {
__typename: 'Future',
quoteName: 'dai', quoteName: 'dai',
}, },
}, },
@@ -33,6 +33,8 @@ const PriceInMarket = ({
label = addDecimalsFormatNumber(price, data.market.decimalPlaces); label = addDecimalsFormatNumber(price, data.market.decimalPlaces);
} else if ( } else if (
decimalSource === 'SETTLEMENT_ASSET' && decimalSource === 'SETTLEMENT_ASSET' &&
data.market &&
'settlementAsset' in data.market.tradableInstrument.instrument.product &&
data.market?.tradableInstrument.instrument.product.settlementAsset data.market?.tradableInstrument.instrument.product.settlementAsset
) { ) {
label = addDecimalsFormatNumber( label = addDecimalsFormatNumber(
@@ -2,7 +2,7 @@ import type { ProposalListFieldsFragment } from '@vegaprotocol/proposals';
import { VoteProgress } from '@vegaprotocol/proposals'; import { VoteProgress } from '@vegaprotocol/proposals';
import type { AgGridReact } from 'ag-grid-react'; import type { AgGridReact } from 'ag-grid-react';
import { ExternalLink } from '@vegaprotocol/ui-toolkit'; import { ExternalLink } from '@vegaprotocol/ui-toolkit';
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid'; import { AgGrid } from '@vegaprotocol/datagrid';
import type { import type {
VegaICellRendererParams, VegaICellRendererParams,
VegaValueFormatterParams, VegaValueFormatterParams,
@@ -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.Token); const tokenLink = useLinks(DApp.Governance);
const requiredMajorityPercentage = useMemo(() => { const requiredMajorityPercentage = useMemo(() => {
const requiredMajority = const requiredMajority =
params?.governance_proposal_market_requiredMajority ?? 1; params?.governance_proposal_market_requiredMajority ?? 1;
@@ -105,7 +105,7 @@ export const ProposalsTable = ({ data }: ProposalsTableProps) => {
? new BigNumber(0) ? new BigNumber(0)
: yesTokens.multipliedBy(100).dividedBy(totalTokensVoted); : yesTokens.multipliedBy(100).dividedBy(totalTokensVoted);
return ( return (
<div className="uppercase flex h-full items-center justify-center pt-2"> <div className="flex items-center justify-center h-full pt-2 uppercase">
<VoteProgress <VoteProgress
threshold={requiredMajorityPercentage} threshold={requiredMajorityPercentage}
progress={yesPercentage} progress={yesPercentage}
@@ -35,7 +35,7 @@ export const BundleSigners = ({
tx, tx,
id, id,
}: BundleSignersProps) => { }: BundleSignersProps) => {
const tokenLink = useLinks(DApp.Token); const tokenLink = useLinks(DApp.Governance);
const bridgeFunction: BridgeFunction = const bridgeFunction: BridgeFunction =
tx?.changes?.erc20 && 'contractAddress' in tx.changes.erc20 tx?.changes?.erc20 && 'contractAddress' in tx.changes.erc20
@@ -49,6 +49,37 @@ fragment ExplorerOracleDataSource on OracleSpec {
} }
... on DataSourceDefinitionExternal { ... on DataSourceDefinitionExternal {
sourceType { sourceType {
... on EthCallSpec {
abi
args
method
requiredConfirmations
address
normalisers {
name
expression
}
trigger {
trigger {
... on EthTimeTrigger {
initial
every
until
}
}
}
filters {
key {
name
type
numberDecimalPlaces
}
conditions {
value
operator
}
}
}
... on DataSourceSpecConfiguration { ... on DataSourceSpecConfiguration {
signers { signers {
signer { signer {
@@ -11,6 +11,14 @@ fragment ExplorerOracleForMarketsMarket on Market {
id id
} }
} }
... on Perpetual {
dataSourceSpecForSettlementData {
id
}
dataSourceSpecForSettlementSchedule {
id
}
}
} }
} }
} }
+34 -3
View File
@@ -5,19 +5,19 @@ 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 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, 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 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?: 'EthCallSpec', abi?: Array<string> | null, args?: Array<string> | null, method: string, requiredConfirmations: number, address: string, normalisers?: Array<{ __typename?: 'Normaliser', name: string, expression: string }> | null, trigger: { __typename?: 'EthCallTrigger', trigger: { __typename?: 'EthTimeTrigger', initial?: any | null, every?: number | null, until?: any | 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> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger' } } } } }, 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 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, numberDecimalPlaces?: number | null }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } | { __typename?: 'EthCallSpec', abi?: Array<string> | null, args?: Array<string> | null, method: string, requiredConfirmations: number, address: string, normalisers?: Array<{ __typename?: 'Normaliser', name: string, expression: string }> | null, trigger: { __typename?: 'EthCallTrigger', trigger: { __typename?: 'EthTimeTrigger', initial?: any | null, every?: number | null, until?: any | 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> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger' } } } } }, 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 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, numberDecimalPlaces?: number | null }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } | { __typename?: 'EthCallSpec', abi?: Array<string> | null, args?: Array<string> | null, method: string, requiredConfirmations: number, address: string, normalisers?: Array<{ __typename?: 'Normaliser', name: string, expression: string }> | null, trigger: { __typename?: 'EthCallTrigger', trigger: { __typename?: 'EthTimeTrigger', initial?: any | null, every?: number | null, until?: any | 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> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger' } } } } }, 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 const ExplorerOracleDataConnectionFragmentDoc = gql` export const ExplorerOracleDataConnectionFragmentDoc = gql`
fragment ExplorerOracleDataConnection on OracleSpec { fragment ExplorerOracleDataConnection on OracleSpec {
@@ -72,6 +72,37 @@ export const ExplorerOracleDataSourceFragmentDoc = gql`
} }
... on DataSourceDefinitionExternal { ... on DataSourceDefinitionExternal {
sourceType { sourceType {
... on EthCallSpec {
abi
args
method
requiredConfirmations
address
normalisers {
name
expression
}
trigger {
trigger {
... on EthTimeTrigger {
initial
every
until
}
}
}
filters {
key {
name
type
numberDecimalPlaces
}
conditions {
value
operator
}
}
}
... on DataSourceSpecConfiguration { ... on DataSourceSpecConfiguration {
signers { signers {
signer { signer {
@@ -3,12 +3,12 @@ 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 ExplorerOracleForMarketsMarketFragment = { __typename?: 'Market', id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', product: { __typename?: 'Future', dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string } } } } }; export type ExplorerOracleForMarketsMarketFragment = { __typename?: 'Market', id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', product: { __typename?: 'Future', dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string } } | { __typename?: 'Perpetual', dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecForSettlementSchedule: { __typename?: 'DataSourceSpec', id: string } } | { __typename?: 'Spot' } } } };
export type ExplorerOracleFormMarketsQueryVariables = Types.Exact<{ [key: string]: never; }>; export type ExplorerOracleFormMarketsQueryVariables = Types.Exact<{ [key: string]: never; }>;
export type ExplorerOracleFormMarketsQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', product: { __typename?: 'Future', dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string } } } } } }> } | null }; export type ExplorerOracleFormMarketsQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', product: { __typename?: 'Future', dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string } } | { __typename?: 'Perpetual', dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecForSettlementSchedule: { __typename?: 'DataSourceSpec', id: string } } | { __typename?: 'Spot' } } } } }> } | null };
export const ExplorerOracleForMarketsMarketFragmentDoc = gql` export const ExplorerOracleForMarketsMarketFragmentDoc = gql`
fragment ExplorerOracleForMarketsMarket on Market { fragment ExplorerOracleForMarketsMarket on Market {
@@ -24,6 +24,14 @@ export const ExplorerOracleForMarketsMarketFragmentDoc = gql`
id id
} }
} }
... on Perpetual {
dataSourceSpecForSettlementData {
id
}
dataSourceSpecForSettlementSchedule {
id
}
}
} }
} }
} }
@@ -10,7 +10,7 @@ interface OracleMarketsProps {
} }
/** /**
* Slightly misleadlingly names, OracleMarkets lists the market (almost always singular) * Slightly misleading names, OracleMarkets lists the market (almost always singular)
* to which an oracle is attached. It also checks what it triggers, by checking on the * to which an oracle is attached. It also checks what it triggers, by checking on the
* market whether it is attached to the dataSourceSpecForSettlementData or ..TradingTermination * market whether it is attached to the dataSourceSpecForSettlementData or ..TradingTermination
*/ */
@@ -27,8 +27,10 @@ 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.__typename === 'Future' || p.__typename === 'Perpetual') &&
p?.dataSourceSpecForTradingTermination?.id === id p.dataSourceSpecForSettlementData.id === id) ||
('dataSourceSpecForTradingTermination' in p &&
p.dataSourceSpecForTradingTermination.id === id)
) { ) {
return true; return true;
} }
@@ -61,8 +63,32 @@ export function getLabel(
m: ExplorerOracleForMarketsMarketFragment | null m: ExplorerOracleForMarketsMarketFragment | null
): string { ): string {
const settlementId = const settlementId =
m?.tradableInstrument?.instrument?.product?.dataSourceSpecForSettlementData ((m?.tradableInstrument?.instrument?.product?.__typename === 'Future' ||
?.id || null; m?.tradableInstrument?.instrument?.product?.__typename === 'Perpetual') &&
m?.tradableInstrument?.instrument?.product
?.dataSourceSpecForSettlementData?.id) ||
null;
return id === settlementId ? 'Settlement for' : 'Termination for'; const terminationId =
(m?.tradableInstrument?.instrument?.product?.__typename === 'Future' &&
m?.tradableInstrument?.instrument?.product
?.dataSourceSpecForTradingTermination?.id) ||
null;
const settlementScheduleId =
(m?.tradableInstrument?.instrument?.product?.__typename === 'Perpetual' &&
m?.tradableInstrument?.instrument?.product
?.dataSourceSpecForSettlementSchedule?.id) ||
null;
switch (id) {
case settlementId:
return 'Settlement for';
case terminationId:
return 'Termination for';
case settlementScheduleId:
return 'Settlement schedule for';
default:
return 'Unknown';
}
} }
@@ -67,6 +67,9 @@ export function OracleSigners({ sourceType }: OracleDetailsSignersProps) {
if (sourceType.__typename !== 'DataSourceDefinitionExternal') { if (sourceType.__typename !== 'DataSourceDefinitionExternal') {
return null; return null;
} }
if (!('signers' in sourceType.sourceType)) {
return null;
}
const signers = sourceType.sourceType.signers; const signers = sourceType.sourceType.signers;
if (!signers || signers.length === 0) { if (!signers || signers.length === 0) {
@@ -23,6 +23,9 @@ fragment ExplorerPartyAssetsAccounts on AccountBalance {
... on Future { ... on Future {
quoteName quoteName
} }
... on Perpetual {
quoteName
}
} }
} }
} }
@@ -3,14 +3,14 @@ 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 ExplorerPartyAssetsAccountsFragment = { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', name: string, id: string, decimals: number, symbol: string, source: { __typename: 'BuiltinAsset' } | { __typename: 'ERC20', contractAddress: string } }, market?: { __typename?: 'Market', id: string, decimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } } } } | null }; export type ExplorerPartyAssetsAccountsFragment = { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', name: string, id: string, decimals: number, symbol: string, source: { __typename: 'BuiltinAsset' } | { __typename: 'ERC20', contractAddress: string } }, market?: { __typename?: 'Market', id: string, decimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } | { __typename?: 'Perpetual', quoteName: string } | { __typename?: 'Spot' } } } } | null };
export type ExplorerPartyAssetsQueryVariables = Types.Exact<{ export type ExplorerPartyAssetsQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID']; partyId: Types.Scalars['ID'];
}>; }>;
export type ExplorerPartyAssetsQuery = { __typename?: 'Query', partiesConnection?: { __typename?: 'PartyConnection', edges: Array<{ __typename?: 'PartyEdge', node: { __typename?: 'Party', id: string, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string, name: string } } } | null> | null } | null, stakingSummary: { __typename?: 'StakingSummary', currentStakeAvailable: string, linkings: { __typename?: 'StakesConnection', edges?: Array<{ __typename?: 'StakeLinkingEdge', node: { __typename?: 'StakeLinking', type: Types.StakeLinkingType, status: Types.StakeLinkingStatus, amount: string } } | null> | null } }, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', name: string, id: string, decimals: number, symbol: string, source: { __typename: 'BuiltinAsset' } | { __typename: 'ERC20', contractAddress: string } }, market?: { __typename?: 'Market', id: string, decimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } } } } | null } } | null> | null } | null } }> } | null }; export type ExplorerPartyAssetsQuery = { __typename?: 'Query', partiesConnection?: { __typename?: 'PartyConnection', edges: Array<{ __typename?: 'PartyEdge', node: { __typename?: 'Party', id: string, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string, name: string } } } | null> | null } | null, stakingSummary: { __typename?: 'StakingSummary', currentStakeAvailable: string, linkings: { __typename?: 'StakesConnection', edges?: Array<{ __typename?: 'StakeLinkingEdge', node: { __typename?: 'StakeLinking', type: Types.StakeLinkingType, status: Types.StakeLinkingStatus, amount: string } } | null> | null } }, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', name: string, id: string, decimals: number, symbol: string, source: { __typename: 'BuiltinAsset' } | { __typename: 'ERC20', contractAddress: string } }, market?: { __typename?: 'Market', id: string, decimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } | { __typename?: 'Perpetual', quoteName: string } | { __typename?: 'Spot' } } } } | null } } | null> | null } | null } }> } | null };
export const ExplorerPartyAssetsAccountsFragmentDoc = gql` export const ExplorerPartyAssetsAccountsFragmentDoc = gql`
fragment ExplorerPartyAssetsAccounts on AccountBalance { fragment ExplorerPartyAssetsAccounts on AccountBalance {
@@ -38,6 +38,9 @@ export const ExplorerPartyAssetsAccountsFragmentDoc = gql`
... on Future { ... on Future {
quoteName quoteName
} }
... on Perpetual {
quoteName
}
} }
} }
} }
@@ -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.Token); const tokenLink = useLinks(DApp.Governance);
return ( return (
<> <>
-10
View File
@@ -1453,11 +1453,6 @@ export interface components {
readonly liquidityMonitoringParameters?: components['schemas']['vegaLiquidityMonitoringParameters']; readonly liquidityMonitoringParameters?: components['schemas']['vegaLiquidityMonitoringParameters'];
/** @description Log normal risk model parameters, valid only if MODEL_LOG_NORMAL is selected. */ /** @description Log normal risk model parameters, valid only if MODEL_LOG_NORMAL is selected. */
readonly logNormal?: components['schemas']['vegaLogNormalRiskModel']; readonly logNormal?: components['schemas']['vegaLogNormalRiskModel'];
/**
* @description Percentage move up and down from the mid price which specifies the range of
* price levels over which automated liquidity provision orders will be deployed.
*/
readonly lpPriceRange?: string;
/** @description Optional new futures market metadata, tags. */ /** @description Optional new futures market metadata, tags. */
readonly metadata?: readonly string[]; readonly metadata?: readonly string[];
/** /**
@@ -1853,11 +1848,6 @@ export interface components {
readonly liquidityMonitoringParameters?: components['schemas']['vegaLiquidityMonitoringParameters']; readonly liquidityMonitoringParameters?: components['schemas']['vegaLiquidityMonitoringParameters'];
/** @description Log normal risk model parameters, valid only if MODEL_LOG_NORMAL is selected. */ /** @description Log normal risk model parameters, valid only if MODEL_LOG_NORMAL is selected. */
readonly logNormal?: components['schemas']['vegaLogNormalRiskModel']; readonly logNormal?: components['schemas']['vegaLogNormalRiskModel'];
/**
* @description Percentage move up and down from the mid price which specifies the range of
* price levels over which automated liquidity provision orders will be deployed.
*/
readonly lpPriceRange?: string;
/** @description Optional futures market metadata, tags. */ /** @description Optional futures market metadata, tags. */
readonly metadata?: readonly string[]; readonly metadata?: readonly string[];
/** @description Price monitoring parameters. */ /** @description Price monitoring parameters. */
+4
View File
@@ -14,11 +14,15 @@ 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_PRODUCT_PERPETUALS=true
NX_UPDATE_MARKET_STATE=true
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
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
+3
View File
@@ -3,3 +3,6 @@ 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
NX_PRODUCT_PERPETUALS=true
NX_UPDATE_MARKET_STATE=true
+3
View File
@@ -3,3 +3,6 @@ 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
NX_PRODUCT_PERPETUALS=false
NX_UPDATE_MARKET_STATE=false
+3
View File
@@ -3,3 +3,6 @@ NX_VEGA_ENV=TESTNET
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
NX_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
NX_PRODUCT_PERPETUALS=true
NX_UPDATE_MARKET_STATE=true
@@ -19,7 +19,22 @@ export const upgradeProposalsData = {
}, },
{ {
node: { node: {
upgradeBlockHeight: '1955065', upgradeBlockHeight: '10001',
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',
@@ -1,21 +0,0 @@
{
"rationale": {
"title": "Add USDT Coin (USDT)",
"description": "Proposal to add USDT Coin (USDT) as an asset"
},
"terms": {
"newAsset": {
"changes": {
"name": "USDT Coin",
"symbol": "USDT",
"decimals": "18",
"quantum": "1",
"erc20": {
"contractAddress": "0xb404c51bbc10dcbe948077f18a4b8e553d160084"
}
}
},
"closingTimestamp": 1662374250,
"enactmentTimestamp": 1662460650
}
}
@@ -0,0 +1,138 @@
{
"rationale": {
"description": "## Summary\n\nThis proposal requests to list BTC PERPS Incentive as a market with USD-P as a settlement asset on the Vega Network as discussed in: https://community.vega.xyz/.\n\n## Rationale\n\n- BTC is the largest Crypto asset with the highest volume and Marketcap.\n- Given the price, 1 decimal places will be used for price due to the number of valid digits in asset price. \n- Position decimal places will be set to 4 considering the value per contract\n- USDT is chosen as settlement asset due to its stability.",
"title": "perpetual market proposal"
},
"terms": {
"closingTimestamp": 0,
"enactmentTimestamp": 0,
"newMarket": {
"changes": {
"instrument": {
"name": "Token test market",
"code": "TEST.24h",
"perpetual": {
"clampLowerBound": "0",
"clampUpperBound": "0",
"interestRate": "0",
"marginFundingFactor": "0.1",
"settlementAsset": "73174a6fb1d5802ba0ac7bd7ab79e0a3a4837b262de0a4e80815a55442692bd0",
"quoteName": "fBTC",
"dataSourceSpecForSettlementData": {
"external": {
"ethOracle": {
"address": "0x1b44F3514812d835EB1BDB0acB33d3fA3351Ee43",
"abi": "[{\"inputs\":[],\"name\":\"latestAnswer\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]",
"method": "latestAnswer",
"normalisers": [
{
"name": "btc.price",
"expression": "$[0]"
}
],
"requiredConfirmations": 3,
"trigger": {
"timeTrigger": {
"every": 30
}
},
"filters": [
{
"key": {
"name": "btc.price",
"type": "TYPE_INTEGER",
"numberDecimalPlaces": 8
},
"conditions": [
{
"operator": "OPERATOR_GREATER_THAN_OR_EQUAL",
"value": "0"
}
]
}
]
}
}
},
"dataSourceSpecForSettlementSchedule": {
"internal": {
"timeTrigger": {
"conditions": [
{
"operator": "OPERATOR_GREATER_THAN_OR_EQUAL",
"value": "0"
}
],
"triggers": [
{
"every": 1800
}
]
}
}
},
"dataSourceSpecBinding": {
"settlementDataProperty": "btc.price",
"settlementScheduleProperty": "vegaprotocol.builtin.timetrigger"
}
}
},
"metadata": [
"base:BTC",
"quote:USD-P",
"class:fx/crypto",
"quarterly",
"sector:defi",
"enactment:2023-06-15T14:00:00Z",
"settlement:2023-09-30T08:00:00Z"
],
"priceMonitoringParameters": {
"triggers": [
{
"horizon": "3600",
"probability": "0.9999",
"auctionExtension": "120"
},
{
"horizon": "14400",
"probability": "0.9999",
"auctionExtension": "180"
},
{
"horizon": "43200",
"probability": "0.9999",
"auctionExtension": "300"
}
]
},
"liquidityMonitoringParameters": {
"targetStakeParameters": {
"timeWindow": "3600",
"scalingFactor": 1
},
"triggeringRatio": "0.7",
"auctionExtension": "1"
},
"liquiditySlaParameters": {
"priceRange": "0.05",
"commitmentMinTimeFraction": "0.95",
"performanceHysteresisEpochs": 1,
"slaCompetitionFactor": "0.95"
},
"logNormal": {
"riskAversionParameter": 0.000001,
"tau": 0.0001140771161,
"params": {
"sigma": 1.5
}
},
"decimalPlaces": "1",
"positionDecimalPlaces": "4",
"linearSlippageFactor": "0.001",
"quadraticSlippageFactor": "0.0"
}
}
}
}
@@ -10,7 +10,6 @@
"positionDecimalPlaces": "5", "positionDecimalPlaces": "5",
"linearSlippageFactor": "0.001", "linearSlippageFactor": "0.001",
"quadraticSlippageFactor": "0", "quadraticSlippageFactor": "0",
"lpPriceRange": "10",
"instrument": { "instrument": {
"name": "Token test market", "name": "Token test market",
"code": "TEST.24h", "code": "TEST.24h",
@@ -104,6 +103,12 @@
"r": 0.016, "r": 0.016,
"sigma": 0.5 "sigma": 0.5
} }
},
"liquiditySlaParameters": {
"priceRange": "0.95",
"commitmentMinTimeFraction": "0.5",
"performanceHysteresisEpochs": 2,
"slaCompetitionFactor": "0.75"
} }
} }
}, },
@@ -4,7 +4,6 @@
"positionDecimalPlaces": "5", "positionDecimalPlaces": "5",
"linearSlippageFactor": "0.001", "linearSlippageFactor": "0.001",
"quadraticSlippageFactor": "0", "quadraticSlippageFactor": "0",
"lpPriceRange": "10",
"instrument": { "instrument": {
"name": "Token test market", "name": "Token test market",
"code": "Token.24h", "code": "Token.24h",
@@ -98,6 +97,12 @@
"r": 0.016, "r": 0.016,
"sigma": 0.8 "sigma": 0.8
} }
},
"liquiditySlaParameters": {
"priceRange": "0.95",
"commitmentMinTimeFraction": "0.5",
"performanceHysteresisEpochs": 2,
"slaCompetitionFactor": "0.75"
} }
} }
} }
@@ -0,0 +1,16 @@
{
"rationale": {
"title": "Market resume test",
"description": "E2E test for market resume proposal"
},
"terms": {
"updateMarketState": {
"changes": {
"marketId": "b33bb4157e12355db22e41f277ddd0c10104dec29a4d6960bbcb96d186c40cbd",
"updateType": "MARKET_STATE_UPDATE_TYPE_RESUME"
}
},
"closingTimestamp": 0,
"enactmentTimestamp": 0
}
}
@@ -4,7 +4,6 @@
"positionDecimalPlaces": "5", "positionDecimalPlaces": "5",
"linearSlippageFactor": "0.001", "linearSlippageFactor": "0.001",
"quadraticSlippageFactor": "0", "quadraticSlippageFactor": "0",
"lpPriceRange": "10",
"instrument": { "instrument": {
"name": "Token test market", "name": "Token test market",
"code": "Token.24h", "code": "Token.24h",
@@ -99,6 +98,12 @@
"sigma": 0.8 "sigma": 0.8
} }
}, },
"liquiditySlaParameters": {
"priceRange": "0.95",
"commitmentMinTimeFraction": "0.5",
"performanceHysteresisEpochs": 2,
"slaCompetitionFactor": "0.75"
},
"successor": { "successor": {
"parentMarketId": "", "parentMarketId": "",
"insurancePoolFraction": "0.75" "insurancePoolFraction": "0.75"
@@ -0,0 +1,16 @@
{
"rationale": {
"title": "Market suspended test",
"description": "E2E test for market suspended proposal"
},
"terms": {
"updateMarketState": {
"changes": {
"marketId": "",
"updateType": "MARKET_STATE_UPDATE_TYPE_SUSPEND"
}
},
"closingTimestamp": 0,
"enactmentTimestamp": 0
}
}
@@ -0,0 +1,17 @@
{
"rationale": {
"title": "Market terminate test",
"description": "E2E test for market terminate proposal"
},
"terms": {
"updateMarketState": {
"changes": {
"marketId": "",
"updateType": "MARKET_STATE_UPDATE_TYPE_TERMINATE",
"price": "100"
}
},
"closingTimestamp": 0,
"enactmentTimestamp": 0
}
}
@@ -1,86 +0,0 @@
{
"lpPriceRange": "11",
"instrument": {
"code": "Token.24h",
"future": {
"quoteName": "fBTC",
"dataSourceSpecForSettlementData": {
"external": {
"oracle": {
"signers": [
{
"pubKey": {
"key": "70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680"
}
}
],
"filters": [
{
"key": {
"name": "prices.BTC.value",
"type": "TYPE_INTEGER"
},
"conditions": [
{
"operator": "OPERATOR_GREATER_THAN",
"value": "0"
}
]
}
]
}
}
},
"dataSourceSpecForTradingTermination": {
"external": {
"oracle": {
"signers": [
{
"pubKey": {
"key": "70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680"
}
}
],
"filters": [
{
"key": {
"name": "trading.terminated.ETH5",
"type": "TYPE_BOOLEAN"
},
"conditions": [
{
"operator": "OPERATOR_GREATER_THAN_OR_EQUAL",
"value": "1648684800000000000"
}
]
}
]
}
}
},
"dataSourceSpecBinding": {
"settlementDataProperty": "prices.BTC.value",
"tradingTerminationProperty": "trading.terminated.ETH5"
}
}
},
"metadata": ["sector:energy", "sector:food", "source:docs.vega.xyz"],
"priceMonitoringParameters": {
"triggers": [
{
"horizon": "43200",
"probability": "0.9999999",
"auctionExtension": "600"
}
]
},
"logNormal": {
"tau": 0.0001140771161,
"riskAversionParameter": 0.001,
"params": {
"mu": 0,
"r": 0.016,
"sigma": 0.3
}
}
}
@@ -1,5 +1,4 @@
{ {
"lpPriceRange": "10",
"linearSlippageFactor": "0.001", "linearSlippageFactor": "0.001",
"quadraticSlippageFactor": "0", "quadraticSlippageFactor": "0",
"instrument": { "instrument": {
@@ -98,5 +97,11 @@
"r": 0.016, "r": 0.016,
"sigma": 0.3 "sigma": 0.3
} }
},
"liquiditySlaParameters": {
"priceRange": "0.95",
"commitmentMinTimeFraction": "0.5",
"performanceHysteresisEpochs": 2,
"slaCompetitionFactor": "0.75"
} }
} }
@@ -9,6 +9,7 @@ import {
createTenDigitUnixTimeStampForSpecifiedDays, createTenDigitUnixTimeStampForSpecifiedDays,
generateFreeFormProposalTitle, generateFreeFormProposalTitle,
getDateFormatForSpecifiedDays, getDateFormatForSpecifiedDays,
getProposalDetailsValue,
getProposalFromTitle, getProposalFromTitle,
getProposalInformationFromTable, getProposalInformationFromTable,
goToMakeNewProposal, goToMakeNewProposal,
@@ -50,6 +51,7 @@ const openProposals = 'open-proposals';
const viewProposalButton = 'view-proposal-btn'; const viewProposalButton = 'view-proposal-btn';
const proposalTermsToggle = 'proposal-json-toggle'; const proposalTermsToggle = 'proposal-json-toggle';
const marketDataToggle = 'proposal-market-data-toggle'; const marketDataToggle = 'proposal-market-data-toggle';
const marketProposalType = 'proposal-type';
describe( describe(
'Governance flow for proposal details', 'Governance flow for proposal details',
@@ -58,6 +60,17 @@ describe(
before('connect wallets and set approval limit', function () { before('connect wallets and set approval limit', function () {
cy.visit('/'); cy.visit('/');
ethereumWalletConnect(); ethereumWalletConnect();
cy.createMarket();
navigateTo(navigation.proposals);
cy.getByTestId('closed-proposals').within(() => {
cy.contains('Add Lorem Ipsum market')
.parentsUntil(proposalListItem)
.last()
.within(() => {
cy.getByTestId(viewProposalButton).click();
});
});
getProposalInformationFromTable('ID').invoke('text').as('parentMarketId');
}); });
beforeEach('visit proposals tab', function () { beforeEach('visit proposals tab', function () {
@@ -296,9 +309,6 @@ describe(
}); });
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.reload();
waitForSpinner();
cy.getByTestId('closed-proposals').within(() => { cy.getByTestId('closed-proposals').within(() => {
cy.contains('Add Lorem Ipsum market') cy.contains('Add Lorem Ipsum market')
.parentsUntil(proposalListItem) .parentsUntil(proposalListItem)
@@ -307,14 +317,9 @@ describe(
cy.getByTestId(viewProposalButton).click(); cy.getByTestId(viewProposalButton).click();
}); });
}); });
getProposalInformationFromTable('ID') cy.VegaWalletSubmitProposal(
.invoke('text') createSuccessorMarketProposalTxBody(this.parentMarketId)
.as('parentMarketId') );
.then(() => {
cy.VegaWalletSubmitProposal(
createSuccessorMarketProposalTxBody(this.parentMarketId)
);
});
navigateTo(navigation.proposals); navigateTo(navigation.proposals);
cy.reload(); cy.reload();
getProposalFromTitle('Test successor market proposal details').within( getProposalFromTitle('Test successor market proposal details').within(
@@ -372,19 +377,147 @@ describe(
}); });
// 3003-PMAN-011 // 3003-PMAN-011
cy.get('.underline').contains('Parent Market ID').realHover(); cy.contains('Parent Market ID').realHover();
cy.getByTestId('tooltip-content', { timeout: 8000 }).should( cy.getByTestId('tooltip-content', { timeout: 8000 }).should(
'contain.text', 'contain.text',
'The ID of the market this market succeeds.' 'The ID of the market this market succeeds.'
); );
cy.get('.underline') cy.contains('Insurance Pool Fraction').realMouseUp().realHover();
.contains('Insurance Pool Fraction')
.realMouseUp()
.realHover();
cy.getByTestId('tooltip-content', { timeout: 8000 }).should( cy.getByTestId('tooltip-content', { timeout: 8000 }).should(
'contain.text', 'contain.text',
'The fraction of the insurance pool balance that is carried over from the parent market to the successor.' 'The fraction of the insurance pool balance that is carried over from the parent market to the successor.'
); );
}); });
it('Able to see perpetual market', function () {
const proposalPath =
'src/fixtures/proposals/new-market-perpetual-raw.json';
const enactmentTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(3);
const closingTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(2);
submitUniqueRawProposal({
proposalBody: proposalPath,
enactmentTimestamp: enactmentTimestamp,
closingTimestamp: closingTimestamp,
});
getProposalFromTitle('perpetual market proposal').within(() => {
cy.getByTestId(marketProposalType).should(
'have.text',
'New market - perpetual'
);
cy.getByTestId(viewProposalButton).click();
});
cy.getByTestId(marketDataToggle).click();
getProposalDetailsValue('Product Type').should(
'contain.text',
'Perpetual'
);
cy.getByTestId(marketProposalType).should(
'have.text',
'New market - perpetual'
);
// Liquidity SLA protocols
getProposalDetailsValue('Performance Hysteresis Epochs').should(
'contain.text',
'1'
);
getProposalDetailsValue('SLA Competition Factor').should(
'contain.text',
'95.00%'
);
getProposalDetailsValue('Epoch Length').should('contain.text', '5s');
getProposalDetailsValue('Non Performance Bond Penalty Max').should(
'contain.text',
'0.05'
);
getProposalDetailsValue('Stake To CCY Volume').should(
'contain.text',
'0.3'
);
getProposalDetailsValue(
'Minimum Probability Of Trading LP Orders'
).should('contain.text', '1e-8');
});
it('Able to see suspended market proposal', function () {
const proposalPath = 'src/fixtures/proposals/suspend-market-raw.json';
const enactmentTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(3);
const closingTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(2);
submitUniqueRawProposal({
proposalBody: proposalPath,
updateMarketId: this.parentMarketId,
enactmentTimestamp: enactmentTimestamp,
closingTimestamp: closingTimestamp,
});
getProposalFromTitle('Market suspended test').within(() => {
cy.getByTestId(marketProposalType).should(
'have.text',
'Suspend market'
);
cy.getByTestId(viewProposalButton).click();
});
cy.getByTestId(marketProposalType).should('have.text', 'Suspend market');
cy.getByTestId(marketDataToggle).click();
cy.getByTestId('proposal-update-market-state').within(() => {
getProposalInformationFromTable('Market ID')
.invoke('text')
.and('eq', this.parentMarketId);
});
});
it('Able to see resume market proposal', function () {
const proposalPath = 'src/fixtures/proposals/resume-market-raw.json';
const enactmentTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(3);
const closingTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(2);
submitUniqueRawProposal({
proposalBody: proposalPath,
updateMarketId: this.parentMarketId,
enactmentTimestamp: enactmentTimestamp,
closingTimestamp: closingTimestamp,
});
getProposalFromTitle('Market resume test').within(() => {
cy.getByTestId(marketProposalType).should('have.text', 'Resume market');
cy.getByTestId(viewProposalButton).click();
});
cy.getByTestId(marketProposalType).should('have.text', 'Resume market');
cy.getByTestId(marketDataToggle).click();
cy.getByTestId('proposal-update-market-state').within(() => {
getProposalInformationFromTable('Market ID')
.invoke('text')
.and('eq', this.parentMarketId);
});
});
it('Able to see terminate market proposal', function () {
const proposalPath = 'src/fixtures/proposals/terminate-market-raw.json';
const enactmentTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(3);
const closingTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(2);
submitUniqueRawProposal({
proposalBody: proposalPath,
updateMarketId: this.parentMarketId,
enactmentTimestamp: enactmentTimestamp,
closingTimestamp: closingTimestamp,
});
getProposalFromTitle('Market terminate test').within(() => {
cy.getByTestId(marketProposalType).should(
'have.text',
'Terminate market'
);
cy.getByTestId(viewProposalButton).click();
});
cy.getByTestId(marketProposalType).should(
'have.text',
'Terminate market'
);
cy.getByTestId(marketDataToggle).click();
cy.getByTestId('proposal-update-market-state').within(() => {
getProposalInformationFromTable('Market ID')
.invoke('text')
.and('eq', this.parentMarketId);
getProposalDetailsValue('Termination Price').should(
'contain.text',
'0.001 fUSDC'
);
});
});
} }
); );
@@ -65,7 +65,10 @@ context(
cy.getByTestId(viewProposalButton).click(); cy.getByTestId(viewProposalButton).click();
}); });
}); });
cy.getByTestId('proposal-type').should('have.text', 'New market'); cy.getByTestId('proposal-type').should(
'have.text',
'New market - future'
);
cy.getByTestId(proposalStatus).should('have.text', 'Enacted'); cy.getByTestId(proposalStatus).should('have.text', 'Enacted');
cy.getByTestId(votesTable).within(() => { cy.getByTestId(votesTable).within(() => {
cy.contains('Voting has ended.').should('be.visible'); cy.contains('Voting has ended.').should('be.visible');
@@ -36,6 +36,7 @@ const proposalType = 'proposal-type';
const proposalDetails = 'proposal-details'; const proposalDetails = 'proposal-details';
const newProposalSubmitButton = 'proposal-submit'; const newProposalSubmitButton = 'proposal-submit';
const proposalVoteDeadline = 'proposal-vote-deadline'; const proposalVoteDeadline = 'proposal-vote-deadline';
const proposalEnactmentDeadline = 'proposal-enactment-deadline';
const proposalParameterSelect = 'proposal-parameter-select'; const proposalParameterSelect = 'proposal-parameter-select';
const proposalMarketSelect = 'proposal-market-select'; const proposalMarketSelect = 'proposal-market-select';
const newProposalTitle = 'proposal-title'; const newProposalTitle = 'proposal-title';
@@ -227,6 +228,8 @@ context(
parseSpecialCharSequences: false, parseSpecialCharSequences: false,
delay: 2, delay: 2,
}); });
cy.getByTestId(proposalVoteDeadline).clear().type('2');
cy.getByTestId(proposalEnactmentDeadline).clear().type('3');
}); });
cy.getByTestId(proposalDownloadBtn) cy.getByTestId(proposalDownloadBtn)
.should('be.visible') .should('be.visible')
@@ -634,6 +637,8 @@ context(
parseSpecialCharSequences: false, parseSpecialCharSequences: false,
delay: 2, delay: 2,
}); });
cy.getByTestId(proposalVoteDeadline).clear().type('2');
cy.getByTestId(proposalEnactmentDeadline).clear().type('3');
}); });
cy.getByTestId(proposalDownloadBtn) cy.getByTestId(proposalDownloadBtn)
.should('be.visible') .should('be.visible')
@@ -89,11 +89,12 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
it('Newly created proposals list - shows title and portion of summary', function () { it('Newly created proposals list - shows title and portion of summary', function () {
const proposalPath = 'src/fixtures/proposals/new-market-raw.json'; const proposalPath = 'src/fixtures/proposals/new-market-raw.json';
const proposalTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(3); const enactmentTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(3);
const closingTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(2);
submitUniqueRawProposal({ submitUniqueRawProposal({
proposalBody: proposalPath, proposalBody: proposalPath,
enactmentTimestamp: proposalTimestamp, enactmentTimestamp: enactmentTimestamp,
closingTimestamp: proposalTimestamp, closingTimestamp: closingTimestamp,
}); // 3001-VOTE-052 }); // 3001-VOTE-052
// 3001-VOTE-008 // 3001-VOTE-008
// 3001-VOTE-034 // 3001-VOTE-034
@@ -212,7 +212,7 @@ context(
closeStakingDialog(); closeStakingDialog();
navigateTo(navigation.validators); navigateTo(navigation.validators);
cy.get(`[row-id="${0}"]`) cy.get(`[row-id="${0}"]`)
.eq(1) .first()
.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}"]`)
.eq(1) .first()
.within(() => { .within(() => {
cy.getByTestId(stakeValidatorListTotalStake) cy.getByTestId(stakeValidatorListTotalStake)
.scrollIntoView() .scrollIntoView()
@@ -262,10 +262,10 @@ context(
'2' '2'
); );
waitForBeginningOfEpoch(); waitForBeginningOfEpoch();
cy.getByTestId(stakeValidatorListStakePercentage).should( cy.getByTestId(
'have.text', stakeValidatorListStakePercentage,
'50.02%' epochTimeout
); ).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,6 +15,7 @@ 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';
@@ -184,7 +185,7 @@ context(
'have.text', 'have.text',
'Vega release tag: v1' 'Vega release tag: v1'
); );
cy.getByTestId('protocol-upgrade-proposal-block-height').should( cy.getByTestId(proposalUpgradeBlockHeight).should(
'have.text', 'have.text',
'Upgrade block height: 2015942' 'Upgrade block height: 2015942'
); );
@@ -199,7 +200,15 @@ context(
}); });
cy.getByTestId(closedProposalToggle).click(); cy.getByTestId(closedProposalToggle).click();
cy.getByTestId(closedProposals).within(() => { cy.getByTestId(closedProposals).within(() => {
cy.getByTestId(networkUpgradeProposalListItem).should('have.length', 1); cy.getByTestId(networkUpgradeProposalListItem).should('have.length', 2);
cy.getByTestId(networkUpgradeProposalListItem)
.first()
.within(() => {
cy.getByTestId(proposalUpgradeBlockHeight).should(
'contain.text',
'10001'
);
});
}); });
}); });
@@ -54,6 +54,7 @@ export function submitUniqueRawProposal(proposalFields: {
proposalBody?: string; proposalBody?: string;
proposalTitle?: string; proposalTitle?: string;
proposalDescription?: string; proposalDescription?: string;
updateMarketId?: string;
closingTimestamp?: number; closingTimestamp?: number;
enactmentTimestamp?: number; enactmentTimestamp?: number;
submit?: boolean; submit?: boolean;
@@ -71,6 +72,10 @@ export function submitUniqueRawProposal(proposalFields: {
if (proposalFields.proposalDescription) { if (proposalFields.proposalDescription) {
rawProposal.rationale.description = proposalFields.proposalDescription; rawProposal.rationale.description = proposalFields.proposalDescription;
} }
if (proposalFields.updateMarketId) {
rawProposal.terms.updateMarketState.changes.marketId =
proposalFields.updateMarketId;
}
if (proposalFields.closingTimestamp) { if (proposalFields.closingTimestamp) {
rawProposal.terms.closingTimestamp = proposalFields.closingTimestamp; rawProposal.terms.closingTimestamp = proposalFields.closingTimestamp;
} else if ( } else if (
@@ -232,21 +237,25 @@ export function getDownloadedProposalJsonPath(proposalType: string) {
return filepath; return filepath;
} }
export function getProposalDetailsValue(RowName: string) {
return cy
.contains(RowName)
.parentsUntil(proposalInformationTableRows)
.parent()
.first();
}
export function validateProposalDetailsDiff( export function validateProposalDetailsDiff(
RowName: string, RowName: string,
changeType: proposalChangeType, changeType: proposalChangeType,
newValue: string, newValue: string,
oldValue?: string oldValue?: string
) { ) {
cy.contains(RowName) getProposalDetailsValue(RowName).within(() => {
.parentsUntil(proposalInformationTableRows) cy.contains(changeType).should('be.visible');
.parent() cy.contains(newValue).should('be.visible');
.first() if (oldValue) cy.contains(oldValue).should('have.class', 'line-through');
.within(() => { });
cy.contains(changeType).should('be.visible');
cy.contains(newValue).should('be.visible');
if (oldValue) cy.contains(oldValue).should('have.class', 'line-through');
});
} }
function getFormattedTime() { function getFormattedTime() {
@@ -105,8 +105,13 @@ export function createNewMarketProposalTxBody(): ProposalSubmissionBody {
decimalPlaces: '5', decimalPlaces: '5',
positionDecimalPlaces: '5', positionDecimalPlaces: '5',
linearSlippageFactor: '0.001', linearSlippageFactor: '0.001',
liquiditySlaParameters: {
priceRange: '0.5',
commitmentMinTimeFraction: '0.1',
performanceHysteresisEpochs: 2,
slaCompetitionFactor: '0.1',
},
quadraticSlippageFactor: '0', quadraticSlippageFactor: '0',
lpPriceRange: '10',
instrument: { instrument: {
name: 'Token test market', name: 'Token test market',
code: 'TEST.24h', code: 'TEST.24h',
@@ -235,7 +240,12 @@ export function createSuccessorMarketProposalTxBody(
positionDecimalPlaces: '5', positionDecimalPlaces: '5',
linearSlippageFactor: '0.001', linearSlippageFactor: '0.001',
quadraticSlippageFactor: '0', quadraticSlippageFactor: '0',
lpPriceRange: '10', liquiditySlaParameters: {
priceRange: '0.5',
commitmentMinTimeFraction: '0.1',
performanceHysteresisEpochs: 2,
slaCompetitionFactor: '0.1',
},
instrument: { instrument: {
name: 'Token test market', name: 'Token test market',
code: 'TEST.24h', code: 'TEST.24h',
@@ -170,21 +170,20 @@ 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()
.as('validatorOnList'); .click();
cy.get('@validatorOnList').click();
} }
} }
@@ -196,7 +195,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}"]`)
.eq(1) .first()
.within(() => { .within(() => {
cy.getByTestId(stakeValidatorListTotalStake, epochTimeout).should( cy.getByTestId(stakeValidatorListTotalStake, epochTimeout).should(
'have.text', 'have.text',
+2
View File
@@ -32,3 +32,5 @@ LC_ALL="en_US.UTF-8"
# Cosmic elevator flags # Cosmic elevator flags
NX_SUCCESSOR_MARKETS=true NX_SUCCESSOR_MARKETS=true
NX_METAMASK_SNAPS=true NX_METAMASK_SNAPS=true
NX_PRODUCT_PERPETUALS=false
NX_UPDATE_MARKET_STATE=false
+4
View File
@@ -22,6 +22,8 @@ NX_VEGA_REST_URL=http://localhost:3008/api/v2/
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/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,3 +33,5 @@ CYPRESS_FAIRGROUND=false
# Cosmic elevator flags # Cosmic elevator flags
NX_SUCCESSOR_MARKETS=false NX_SUCCESSOR_MARKETS=false
NX_METAMASK_SNAPS=false NX_METAMASK_SNAPS=false
NX_PRODUCT_PERPETUALS=true
NX_UPDATE_MARKET_STATE=true
+4
View File
@@ -19,7 +19,11 @@ NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fa
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 NX_METAMASK_SNAPS=true
NX_PRODUCT_PERPETUALS=true
NX_UPDATE_MARKET_STATE=true
+3
View File
@@ -16,6 +16,7 @@ NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/annou
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_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_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
@@ -23,3 +24,5 @@ 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 NX_METAMASK_SNAPS=false
NX_PRODUCT_PERPETUALS=false
NX_UPDATE_MARKET_STATE=false
+3
View File
@@ -15,6 +15,7 @@ NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/annou
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_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_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
@@ -22,3 +23,5 @@ 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 NX_METAMASK_SNAPS=false
NX_PRODUCT_PERPETUALS=false
NX_UPDATE_MARKET_STATE=false
+3
View File
@@ -9,6 +9,7 @@ NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/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_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/firefox/addon/vega-wallet-fairground
@@ -19,3 +20,5 @@ 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 NX_METAMASK_SNAPS=true
NX_PRODUCT_PERPETUALS=true
NX_UPDATE_MARKET_STATE=true
+3
View File
@@ -14,6 +14,7 @@ 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_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/firefox/addon/vega-wallet-fairground
@@ -24,3 +25,5 @@ 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 NX_METAMASK_SNAPS=true
NX_PRODUCT_PERPETUALS=true
NX_UPDATE_MARKET_STATE=true
+3
View File
@@ -11,6 +11,7 @@ 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_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/firefox/addon/vega-wallet-fairground
@@ -21,3 +22,5 @@ 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 NX_METAMASK_SNAPS=false
NX_PRODUCT_PERPETUALS=false
NX_UPDATE_MARKET_STATE=false
+1 -1
View File
@@ -308,7 +308,7 @@ const AppContainer = () => {
<Router> <Router>
<ScrollToTop /> <ScrollToTop />
<AppStateProvider> <AppStateProvider>
<div className="min-h-full text-white"> <div className="min-h-full text-white grid">
<NodeGuard <NodeGuard
skeleton={<div>{t('Loading')}</div>} skeleton={<div>{t('Loading')}</div>}
failure={ failure={
@@ -613,6 +613,9 @@
"proposalDetails": "Proposal details", "proposalDetails": "Proposal details",
"marketSpecification": "Market specification", "marketSpecification": "Market specification",
"viewMarketJson": "View market JSON", "viewMarketJson": "View market JSON",
"marketId": "Market ID",
"marketName": "Market name",
"marketCode": "Market code",
"proposalDescription": "Description", "proposalDescription": "Description",
"currentlySetTo": "Currently expected to ", "currentlySetTo": "Currently expected to ",
"currently": "currently", "currently": "currently",
@@ -705,10 +708,17 @@
"parameter": "parameter", "parameter": "parameter",
"NewMarketProposal": "New market proposal", "NewMarketProposal": "New market proposal",
"UpdateMarketProposal": "Update market proposal", "UpdateMarketProposal": "Update market proposal",
"UpdateMarketStateProposal": "Update market state proposal",
"MarketChange": "Market change",
"MarketStateChange": "Market state change",
"MarketDetails": "Market details",
"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 proposal",
"MARKET_STATE_UPDATE_TYPE_RESUME": "Resume market",
"MARKET_STATE_UPDATE_TYPE_SUSPEND": "Suspend market",
"MARKET_STATE_UPDATE_TYPE_TERMINATE": "Terminate market",
"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",
@@ -717,7 +727,11 @@
"ProposalDocsPrefix": "For guidance on how to make proposals, see", "ProposalDocsPrefix": "For guidance on how to make proposals, see",
"NetworkParameter": "Network parameter", "NetworkParameter": "Network parameter",
"NewMarket": "New market", "NewMarket": "New market",
"NewMarketPerpetualProduct": "New market - perpetual",
"NewMarketFutureProduct": "New market - future",
"NewMarketSpotProduct": "New market - spot",
"UpdateMarket": "Update market", "UpdateMarket": "Update market",
"UpdateMarketState": "Update market state",
"NewAsset": "New asset", "NewAsset": "New asset",
"UpdateAsset": "Update asset", "UpdateAsset": "Update asset",
"AssetID": "Asset ID", "AssetID": "Asset ID",
+17 -8
View File
@@ -12,7 +12,7 @@ import { useRefreshAfterEpoch } from '../../hooks/use-refresh-after-epoch';
import { ProposalsListItem } from '../proposals/components/proposals-list-item'; import { ProposalsListItem } from '../proposals/components/proposals-list-item';
import { ProtocolUpgradeProposalsListItem } from '../proposals/components/protocol-upgrade-proposals-list-item/protocol-upgrade-proposals-list-item'; import { ProtocolUpgradeProposalsListItem } from '../proposals/components/protocol-upgrade-proposals-list-item/protocol-upgrade-proposals-list-item';
import Routes from '../routes'; import Routes from '../routes';
import { ExternalLinks } from '@vegaprotocol/environment'; import { ExternalLinks, FLAGS } from '@vegaprotocol/environment';
import { removePaginationWrapper } from '@vegaprotocol/utils'; import { removePaginationWrapper } from '@vegaprotocol/utils';
import { useNodesQuery } from '../staking/home/__generated__/Nodes'; import { useNodesQuery } from '../staking/home/__generated__/Nodes';
import { useProposalsQuery } from '../proposals/proposals/__generated__/Proposals'; import { useProposalsQuery } from '../proposals/proposals/__generated__/Proposals';
@@ -23,7 +23,6 @@ import {
import { Heading, SubHeading } from '../../components/heading'; import { Heading, SubHeading } from '../../components/heading';
import * as Schema from '@vegaprotocol/types'; import * as Schema from '@vegaprotocol/types';
import type { RouteChildProps } from '..'; import type { RouteChildProps } from '..';
import type { ProposalFieldsFragment } from '../proposals/proposals/__generated__/Proposals';
import type { NodesFragmentFragment } from '../staking/home/__generated__/Nodes'; import type { NodesFragmentFragment } from '../staking/home/__generated__/Nodes';
import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals'; import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals';
import { useProtocolUpgradeProposalsQuery } from '@vegaprotocol/proposals'; import { useProtocolUpgradeProposalsQuery } from '@vegaprotocol/proposals';
@@ -32,6 +31,7 @@ import {
orderByUpgradeBlockHeight, orderByUpgradeBlockHeight,
} from '../proposals/components/proposals-list/proposals-list'; } from '../proposals/components/proposals-list/proposals-list';
import { BigNumber } from '../../lib/bignumber'; import { BigNumber } from '../../lib/bignumber';
import type { ProposalQuery } from '../proposals/proposal/__generated__/Proposal';
const nodesToShow = 6; const nodesToShow = 6;
@@ -39,13 +39,13 @@ const HomeProposals = ({
proposals, proposals,
protocolUpgradeProposals, protocolUpgradeProposals,
}: { }: {
proposals: ProposalFieldsFragment[]; proposals: ProposalQuery['proposal'][];
protocolUpgradeProposals: ProtocolUpgradeProposalFieldsFragment[]; protocolUpgradeProposals: ProtocolUpgradeProposalFieldsFragment[];
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<section className="mb-16" data-testid="home-proposals"> <section className="mb-16 break-all" data-testid="home-proposals">
<Heading title={t('vegaGovernance')} /> <Heading title={t('vegaGovernance')} />
<h3 className="mb-6">{t('homeProposalsIntro')}</h3> <h3 className="mb-6">{t('homeProposalsIntro')}</h3>
<div className="mb-8"> <div className="mb-8">
@@ -60,9 +60,12 @@ const HomeProposals = ({
<ProtocolUpgradeProposalsListItem key={index} proposal={proposal} /> <ProtocolUpgradeProposalsListItem key={index} proposal={proposal} />
))} ))}
{proposals.map((proposal) => ( {proposals.map(
<ProposalsListItem key={proposal.id} proposal={proposal} /> (proposal) =>
))} proposal?.id && (
<ProposalsListItem key={proposal.id} proposal={proposal} />
)
)}
</ul> </ul>
<div className="mt-6"> <div className="mt-6">
@@ -182,6 +185,10 @@ const GovernanceHome = ({ name }: RouteChildProps) => {
pollInterval: 5000, pollInterval: 5000,
fetchPolicy: 'network-only', fetchPolicy: 'network-only',
errorPolicy: 'ignore', errorPolicy: 'ignore',
variables: {
includeNewMarketProductFields: !!FLAGS.PRODUCT_PERPETUALS,
includeUpdateMarketStates: !!FLAGS.UPDATE_MARKET_STATE,
},
}); });
const { const {
@@ -206,7 +213,9 @@ const GovernanceHome = ({ name }: RouteChildProps) => {
const proposals = useMemo( const proposals = useMemo(
() => () =>
proposalsData proposalsData
? getNotRejectedProposals(proposalsData.proposalsConnection) ? getNotRejectedProposals(
removePaginationWrapper(proposalsData.proposalsConnection?.edges)
)
: [], : [],
[proposalsData] [proposalsData]
); );
@@ -3,7 +3,6 @@ import { Lozenge, VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit';
import { shorten } from '@vegaprotocol/utils'; import { shorten } from '@vegaprotocol/utils';
import { Heading, SubHeading } from '../../../../components/heading'; import { Heading, SubHeading } from '../../../../components/heading';
import type { ReactNode } from 'react'; import type { ReactNode } from 'react';
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
import type { ProposalQuery } from '../../proposal/__generated__/Proposal'; 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';
@@ -20,7 +19,7 @@ export const ProposalHeader = ({
isListItem = true, isListItem = true,
voteState, voteState,
}: { }: {
proposal: ProposalFieldsFragment | ProposalQuery['proposal']; proposal: ProposalQuery['proposal'];
isListItem?: boolean; isListItem?: boolean;
voteState?: VoteState | null; voteState?: VoteState | null;
}) => { }) => {
@@ -37,7 +36,10 @@ export const ProposalHeader = ({
switch (change?.__typename) { switch (change?.__typename) {
case 'NewMarket': { case 'NewMarket': {
proposalType = 'NewMarket'; proposalType =
FLAGS.PRODUCT_PERPETUALS && change?.instrument?.product?.__typename
? `NewMarket${change?.instrument?.product?.__typename}`
: 'NewMarket';
fallbackTitle = t('NewMarketProposal'); fallbackTitle = t('NewMarketProposal');
details = ( details = (
<> <>
@@ -61,12 +63,31 @@ export const ProposalHeader = ({
); );
break; break;
} }
case 'UpdateMarketState': {
proposalType =
FLAGS.UPDATE_MARKET_STATE && change?.updateType
? t(change.updateType)
: 'UpdateMarketState';
fallbackTitle = t('UpdateMarketStateProposal');
details = (
<span>
{FLAGS.UPDATE_MARKET_STATE &&
change?.market?.id &&
change.updateType ? (
<>
{t(change.updateType)}: {truncateMiddle(change.market.id)}
</>
) : null}
</span>
);
break;
}
case 'UpdateMarket': { case 'UpdateMarket': {
proposalType = 'UpdateMarket'; proposalType = 'UpdateMarket';
fallbackTitle = t('UpdateMarketProposal'); fallbackTitle = t('UpdateMarketProposal');
details = ( details = (
<> <>
<span>{t('Market change')}:</span>{' '} <span>{t('MarketChange')}:</span>{' '}
<span>{truncateMiddle(change.marketId)}</span> <span>{truncateMiddle(change.marketId)}</span>
</> </>
); );
@@ -6,6 +6,7 @@ import {
KeyDetailsInfoPanel, KeyDetailsInfoPanel,
LiquidityMonitoringParametersInfoPanel, LiquidityMonitoringParametersInfoPanel,
LiquidityPriceRangeInfoPanel, LiquidityPriceRangeInfoPanel,
LiquiditySLAParametersInfoPanel,
MetadataInfoPanel, MetadataInfoPanel,
OracleInfoPanel, OracleInfoPanel,
PriceMonitoringBoundsInfoPanel, PriceMonitoringBoundsInfoPanel,
@@ -13,6 +14,10 @@ import {
RiskModelInfoPanel, RiskModelInfoPanel,
RiskParametersInfoPanel, RiskParametersInfoPanel,
SettlementAssetInfoPanel, SettlementAssetInfoPanel,
getDataSourceSpecForSettlementSchedule,
getDataSourceSpecForSettlementData,
getDataSourceSpecForTradingTermination,
getSigners,
} from '@vegaprotocol/markets'; } from '@vegaprotocol/markets';
import { import {
Button, Button,
@@ -24,7 +29,6 @@ import {
import { SubHeading } from '../../../../components/heading'; import { SubHeading } from '../../../../components/heading';
import { CollapsibleToggle } from '../../../../components/collapsible-toggle'; import { CollapsibleToggle } from '../../../../components/collapsible-toggle';
import type { MarketInfo } from '@vegaprotocol/markets'; import type { MarketInfo } from '@vegaprotocol/markets';
import type { DataSourceDefinition } from '@vegaprotocol/types';
import { create } from 'zustand'; import { create } from 'zustand';
type MarketDataDialogState = { type MarketDataDialogState = {
@@ -59,20 +63,31 @@ export const ProposalMarketData = ({
return null; return null;
} }
const settlementData = marketData.tradableInstrument.instrument.product const { product } = marketData.tradableInstrument.instrument;
.dataSourceSpecForSettlementData.data as DataSourceDefinition;
const settlementData = getDataSourceSpecForSettlementData(product);
const settlementScheduleData =
getDataSourceSpecForSettlementSchedule(product);
const terminationData = getDataSourceSpecForTradingTermination(product);
const parentProduct = parentMarketData?.tradableInstrument.instrument.product;
const parentSettlementData = const parentSettlementData =
parentMarketData?.tradableInstrument.instrument?.product parentProduct && getDataSourceSpecForSettlementData(parentProduct);
?.dataSourceSpecForSettlementData?.data; const parentSettlementScheduleData =
const terminationData = marketData.tradableInstrument.instrument.product parentProduct && getDataSourceSpecForSettlementSchedule(parentProduct);
.dataSourceSpecForTradingTermination.data as DataSourceDefinition;
const parentTerminationData = const parentTerminationData =
parentMarketData?.tradableInstrument.instrument?.product parentProduct && getDataSourceSpecForTradingTermination(parentProduct);
?.dataSourceSpecForTradingTermination?.data;
// TODO add settlementScheduleData for Perp Proposal
const isParentSettlementDataEqual = const isParentSettlementDataEqual =
parentSettlementData !== undefined && parentSettlementData !== undefined &&
isEqual(settlementData, parentSettlementData); isEqual(settlementData, parentSettlementData);
const isParentSettlementScheduleDataEqual =
parentSettlementData !== undefined &&
isEqual(settlementScheduleData, parentSettlementScheduleData);
const isParentTerminationDataEqual = const isParentTerminationDataEqual =
parentTerminationData !== undefined && parentTerminationData !== undefined &&
isEqual(terminationData, parentTerminationData); isEqual(terminationData, parentTerminationData);
@@ -85,20 +100,6 @@ export const ProposalMarketData = ({
parentMarketData?.priceMonitoringSettings?.parameters?.triggers parentMarketData?.priceMonitoringSettings?.parameters?.triggers
); );
const getSigners = (data: DataSourceDefinition) => {
if (data.sourceType.__typename === 'DataSourceDefinitionExternal') {
const signers = data.sourceType.sourceType.signers || [];
return signers.map(({ signer }) => {
return (
(signer.__typename === 'ETHAddress' && signer.address) ||
(signer.__typename === 'PubKey' && signer.key)
);
});
}
return [];
};
return ( return (
<section className="relative" data-testid="proposal-market-data"> <section className="relative" data-testid="proposal-market-data">
<CollapsibleToggle <CollapsibleToggle
@@ -129,10 +130,9 @@ export const ProposalMarketData = ({
parentMarket={parentMarketData} parentMarket={parentMarketData}
/> />
{isEqual( {settlementData &&
getSigners(settlementData), terminationData &&
getSigners(terminationData) isEqual(getSigners(settlementData), getSigners(terminationData)) ? (
) ? (
<> <>
<h2 className={marketDataHeaderStyles}>{t('Oracle')}</h2> <h2 className={marketDataHeaderStyles}>{t('Oracle')}</h2>
@@ -140,14 +140,17 @@ export const ProposalMarketData = ({
market={marketData} market={marketData}
type="settlementData" type="settlementData"
parentMarket={ parentMarket={
isParentSettlementDataEqual ? undefined : parentMarketData isParentSettlementDataEqual ||
isParentSettlementScheduleDataEqual
? undefined
: parentMarketData
} }
/> />
</> </>
) : ( ) : (
<> <>
<h2 className={marketDataHeaderStyles}> <h2 className={marketDataHeaderStyles}>
{t('Settlement Oracle')} {t('Settlement oracle')}
</h2> </h2>
<OracleInfoPanel <OracleInfoPanel
market={marketData} market={marketData}
@@ -157,16 +160,41 @@ export const ProposalMarketData = ({
} }
/> />
<h2 className={marketDataHeaderStyles}> {marketData.tradableInstrument.instrument.product.__typename ===
{t('Termination Oracle')} 'Future' && (
</h2> <div>
<OracleInfoPanel <h2 className={marketDataHeaderStyles}>
market={marketData} {t('Termination oracle')}
type="termination" </h2>
parentMarket={ <OracleInfoPanel
isParentTerminationDataEqual ? undefined : parentMarketData market={marketData}
} type="termination"
/> parentMarket={
isParentTerminationDataEqual
? undefined
: parentMarketData
}
/>
</div>
)}
{marketData.tradableInstrument.instrument.product.__typename ===
'Perpetual' && (
<div>
<h2 className={marketDataHeaderStyles}>
{t('Settlement schedule oracle')}
</h2>
<OracleInfoPanel
market={marketData}
type="settlementSchedule"
parentMarket={
isParentSettlementScheduleDataEqual
? undefined
: parentMarketData
}
/>
</div>
)}
</> </>
)} )}
@@ -244,7 +272,6 @@ export const ProposalMarketData = ({
market={marketData} market={marketData}
parentMarket={parentMarketData} parentMarket={parentMarketData}
/> />
<h2 className={marketDataHeaderStyles}> <h2 className={marketDataHeaderStyles}>
{t('Liquidity price range')} {t('Liquidity price range')}
</h2> </h2>
@@ -252,6 +279,14 @@ export const ProposalMarketData = ({
market={marketData} market={marketData}
parentMarket={parentMarketData} parentMarket={parentMarketData}
/> />
<h2 className={marketDataHeaderStyles}>
{t('Liquidity SLA protocol')}
</h2>
<LiquiditySLAParametersInfoPanel
market={marketData}
parentMarket={parentMarketData}
/>
</div> </div>
</> </>
)} )}
@@ -0,0 +1 @@
export * from './proposal-update-market-state';
@@ -0,0 +1,123 @@
import { fireEvent, render, screen } from '@testing-library/react';
import { ProposalUpdateMarketState } from './proposal-update-market-state';
import { generateProposal } from '../../test-helpers/generate-proposals';
import { MarketUpdateType } from '@vegaprotocol/types';
describe('<ProposalUpdateMarketState />', () => {
const suspendProposal = generateProposal({
terms: {
change: {
__typename: 'UpdateMarketState',
market: {
id: '1',
decimalPlaces: 0,
tradableInstrument: {
instrument: {
name: 'suspendProposal Name',
code: 'suspendProposal Code',
product: {
__typename: 'Future',
quoteName: 'USD',
},
},
},
},
updateType: MarketUpdateType.MARKET_STATE_UPDATE_TYPE_SUSPEND,
},
},
});
const resumeProposal = generateProposal({
terms: {
change: {
__typename: 'UpdateMarketState',
market: {
id: '1',
decimalPlaces: 0,
tradableInstrument: {
instrument: {
name: 'resumeProposal Name',
code: 'resumeProposal Code',
product: {
__typename: 'Future',
quoteName: 'USD',
},
},
},
},
updateType: MarketUpdateType.MARKET_STATE_UPDATE_TYPE_RESUME,
},
},
});
const terminateProposal = generateProposal({
terms: {
change: {
__typename: 'UpdateMarketState',
market: {
id: '1',
decimalPlaces: 0,
tradableInstrument: {
instrument: {
name: 'terminateProposal Name',
code: 'terminateProposal Code',
product: {
__typename: 'Future',
quoteName: 'USD',
},
},
},
},
updateType: MarketUpdateType.MARKET_STATE_UPDATE_TYPE_TERMINATE,
price: '123',
},
},
});
it('should render nothing if proposal is null', () => {
render(<ProposalUpdateMarketState proposal={null} />);
expect(screen.queryByTestId('proposal-update-market-state')).toBeNull();
});
it('should toggle details when CollapsibleToggle is clicked', () => {
render(<ProposalUpdateMarketState proposal={suspendProposal} />);
expect(
screen.queryByTestId('proposal-update-market-state-table')
).toBeNull();
fireEvent.click(screen.getByTestId('proposal-market-data-toggle'));
expect(
screen.getByTestId('proposal-update-market-state-table')
).toBeInTheDocument();
});
it('should display suspend market information when showDetails is true', () => {
render(<ProposalUpdateMarketState proposal={suspendProposal} />);
fireEvent.click(screen.getByTestId('proposal-market-data-toggle'));
expect(screen.getByText('suspendProposal Name')).toBeInTheDocument();
expect(screen.getByText('suspendProposal Code')).toBeInTheDocument();
});
it('should display resume market information when showDetails is true', () => {
render(<ProposalUpdateMarketState proposal={resumeProposal} />);
fireEvent.click(screen.getByTestId('proposal-market-data-toggle'));
expect(screen.getByText('resumeProposal Name')).toBeInTheDocument();
expect(screen.getByText('resumeProposal Code')).toBeInTheDocument();
});
it('should display terminate market information when showDetails is true', () => {
render(<ProposalUpdateMarketState proposal={terminateProposal} />);
fireEvent.click(screen.getByTestId('proposal-market-data-toggle'));
expect(screen.getByText('terminateProposal Name')).toBeInTheDocument();
expect(screen.getByText('terminateProposal Code')).toBeInTheDocument();
expect(screen.getByText('123 USD')).toBeInTheDocument();
});
});
@@ -0,0 +1,84 @@
import { useTranslation } from 'react-i18next';
import {
KeyValueTable,
KeyValueTableRow,
RoundedWrapper,
} from '@vegaprotocol/ui-toolkit';
import { Row } from '@vegaprotocol/markets';
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
import { useState } from 'react';
import { CollapsibleToggle } from '../../../../components/collapsible-toggle';
import { SubHeading } from '../../../../components/heading';
interface ProposalUpdateMarketStateProps {
proposal: ProposalQuery['proposal'];
}
export const ProposalUpdateMarketState = ({
proposal,
}: ProposalUpdateMarketStateProps) => {
const { t } = useTranslation();
const [showDetails, setShowDetails] = useState(false);
let market;
let isTerminate = false;
if (!proposal) {
return null;
}
if (proposal?.terms.change.__typename === 'UpdateMarketState') {
market = proposal?.terms?.change?.market;
isTerminate =
proposal?.terms?.change?.updateType ===
'MARKET_STATE_UPDATE_TYPE_TERMINATE';
}
return (
<section className="relative" data-testid="proposal-update-market-state">
<CollapsibleToggle
toggleState={showDetails}
setToggleState={setShowDetails}
dataTestId="proposal-market-data-toggle"
>
<SubHeading title={t('MarketDetails')} />
</CollapsibleToggle>
{showDetails && (
<RoundedWrapper paddingBottom={true} marginBottomLarge={true}>
{proposal?.terms.change.__typename === 'UpdateMarketState' && (
<KeyValueTable data-testid="proposal-update-market-state-table">
<KeyValueTableRow>
{t('marketId')}
{market?.id}
</KeyValueTableRow>
<KeyValueTableRow>
{t('marketName')}
{market?.tradableInstrument?.instrument?.name}
</KeyValueTableRow>
<KeyValueTableRow noBorder={!isTerminate}>
{t('marketCode')}
{market?.tradableInstrument?.instrument?.code}
</KeyValueTableRow>
{isTerminate && (
<Row
field="termination-price"
value={proposal?.terms?.change?.price}
assetSymbol={
market?.tradableInstrument?.instrument?.product
?.__typename === 'Future' ||
market?.tradableInstrument?.instrument?.product
?.__typename === 'Perpetual'
? market?.tradableInstrument?.instrument?.product
?.quoteName
: undefined
}
decimalPlaces={market?.decimalPlaces}
/>
)}
</KeyValueTable>
)}
</RoundedWrapper>
)}
</section>
);
};
@@ -10,21 +10,21 @@ import { UserVote } from '../vote-details';
import { ListAsset } from '../list-asset'; import { ListAsset } from '../list-asset';
import Routes from '../../../routes'; import Routes from '../../../routes';
import { ProposalMarketData } from '../proposal-market-data'; import { ProposalMarketData } from '../proposal-market-data';
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
import type { ProposalQuery } from '../../proposal/__generated__/Proposal'; import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
import type { MarketInfo } from '@vegaprotocol/markets'; import type { MarketInfo } from '@vegaprotocol/markets';
import type { AssetQuery } from '@vegaprotocol/assets'; import type { AssetQuery } from '@vegaprotocol/assets';
import { removePaginationWrapper } from '@vegaprotocol/utils'; import { removePaginationWrapper } from '@vegaprotocol/utils';
import { ProposalState } from '@vegaprotocol/types'; import { ProposalState } from '@vegaprotocol/types';
import { ProposalMarketChanges } from '../proposal-market-changes'; import { ProposalMarketChanges } from '../proposal-market-changes';
import { ProposalUpdateMarketState } from '../proposal-update-market-state';
import type { NetworkParamsResult } from '@vegaprotocol/network-parameters'; import type { NetworkParamsResult } from '@vegaprotocol/network-parameters';
import { useVoteSubmit } from '@vegaprotocol/proposals'; import { useVoteSubmit } from '@vegaprotocol/proposals';
import { useUserVote } from '../vote-details/use-user-vote'; import { useUserVote } from '../vote-details/use-user-vote';
export interface ProposalProps { export interface ProposalProps {
proposal: ProposalFieldsFragment | ProposalQuery['proposal']; proposal: ProposalQuery['proposal'];
networkParams: Partial<NetworkParamsResult>; networkParams: Partial<NetworkParamsResult>;
newMarketData?: MarketInfo | null; marketData?: MarketInfo | null;
parentMarketData?: MarketInfo | null; parentMarketData?: MarketInfo | null;
assetData?: AssetQuery | null; assetData?: AssetQuery | null;
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -39,7 +39,7 @@ export const Proposal = ({
proposal, proposal,
networkParams, networkParams,
restData, restData,
newMarketData, marketData,
parentMarketData, parentMarketData,
assetData, assetData,
originalMarketProposalRestData, originalMarketProposalRestData,
@@ -74,14 +74,15 @@ export const Proposal = ({
if (networkParams) { if (networkParams) {
switch (proposal.terms.change.__typename) { switch (proposal.terms.change.__typename) {
case 'UpdateMarket':
case 'UpdateMarketState':
minVoterBalance =
networkParams.governance_proposal_updateMarket_minVoterBalance;
break;
case 'NewMarket': case 'NewMarket':
minVoterBalance = minVoterBalance =
networkParams.governance_proposal_market_minVoterBalance; networkParams.governance_proposal_market_minVoterBalance;
break; break;
case 'UpdateMarket':
minVoterBalance =
networkParams.governance_proposal_updateMarket_minVoterBalance;
break;
case 'NewAsset': case 'NewAsset':
minVoterBalance = minVoterBalance =
networkParams.governance_proposal_asset_minVoterBalance; networkParams.governance_proposal_asset_minVoterBalance;
@@ -127,7 +128,7 @@ export const Proposal = ({
voteState={voteState} voteState={voteState}
/> />
<div className="my-10"> <div className="my-10 break-all">
<ProposalChangeTable proposal={proposal} /> <ProposalChangeTable proposal={proposal} />
</div> </div>
@@ -145,15 +146,21 @@ export const Proposal = ({
<ProposalDescription description={proposal.rationale.description} /> <ProposalDescription description={proposal.rationale.description} />
</div> </div>
{newMarketData && ( {marketData && (
<div className="mb-4"> <div className="mb-4">
<ProposalMarketData <ProposalMarketData
marketData={newMarketData} marketData={marketData}
parentMarketData={parentMarketData ? parentMarketData : undefined} parentMarketData={parentMarketData ? parentMarketData : undefined}
/> />
</div> </div>
)} )}
{proposal.terms.change.__typename === 'UpdateMarketState' && (
<div className="mb-4">
<ProposalUpdateMarketState proposal={proposal} />
</div>
)}
{proposal.terms.change.__typename === 'UpdateMarket' && ( {proposal.terms.change.__typename === 'UpdateMarket' && (
<div className="mb-4"> <div className="mb-4">
<ProposalMarketChanges <ProposalMarketChanges
@@ -2,11 +2,10 @@ import { RoundedWrapper } from '@vegaprotocol/ui-toolkit';
import { ProposalHeader } from '../proposal-detail-header/proposal-header'; import { ProposalHeader } from '../proposal-detail-header/proposal-header';
import { ProposalsListItemDetails } from './proposals-list-item-details'; import { ProposalsListItemDetails } from './proposals-list-item-details';
import { useUserVote } from '../vote-details/use-user-vote'; import { useUserVote } from '../vote-details/use-user-vote';
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
import type { ProposalQuery } from '../../proposal/__generated__/Proposal'; import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
interface ProposalsListItemProps { interface ProposalsListItemProps {
proposal?: ProposalFieldsFragment | ProposalQuery['proposal'] | null; proposal?: ProposalQuery['proposal'] | null;
} }
export const ProposalsListItem = ({ proposal }: ProposalsListItemProps) => { export const ProposalsListItem = ({ proposal }: ProposalsListItemProps) => {
@@ -16,14 +16,14 @@ import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/propos
import { ExternalLinks } from '@vegaprotocol/environment'; import { ExternalLinks } from '@vegaprotocol/environment';
interface ProposalsListProps { interface ProposalsListProps {
proposals: Array<ProposalFieldsFragment | ProposalQuery['proposal']>; proposals: Array<ProposalQuery['proposal']>;
protocolUpgradeProposals: ProtocolUpgradeProposalFieldsFragment[]; protocolUpgradeProposals: ProtocolUpgradeProposalFieldsFragment[];
lastBlockHeight?: string; lastBlockHeight?: string;
} }
interface SortedProposalsProps { interface SortedProposalsProps {
open: Array<ProposalFieldsFragment | ProposalQuery['proposal']>; open: ProposalQuery['proposal'][];
closed: Array<ProposalFieldsFragment | ProposalQuery['proposal']>; closed: ProposalQuery['proposal'][];
} }
interface SortedProtocolUpgradeProposalsProps { interface SortedProtocolUpgradeProposalsProps {
@@ -31,7 +31,7 @@ interface SortedProtocolUpgradeProposalsProps {
closed: ProtocolUpgradeProposalFieldsFragment[]; closed: ProtocolUpgradeProposalFieldsFragment[];
} }
export const orderByDate = (arr: ProposalFieldsFragment[]) => export const orderByDate = (arr: ProposalQuery['proposal'][]) =>
orderBy( orderBy(
arr, arr,
[ [
@@ -92,12 +92,12 @@ export const ProposalsList = ({
return { return {
open: open:
initialSorting.open.length > 0 initialSorting.open.length > 0
? orderByDate(initialSorting.open as ProposalFieldsFragment[]) ? orderByDate(initialSorting.open as ProposalQuery['proposal'][])
: [], : [],
closed: closed:
initialSorting.closed.length > 0 initialSorting.closed.length > 0
? orderByDate( ? orderByDate(
initialSorting.closed as ProposalFieldsFragment[] initialSorting.closed as ProposalQuery['proposal'][]
).reverse() ).reverse()
: [], : [],
}; };
@@ -3,20 +3,17 @@ import { useTranslation } from 'react-i18next';
import { Heading } from '../../../../components/heading'; import { Heading } from '../../../../components/heading';
import { ProposalsListItem } from '../proposals-list-item'; import { ProposalsListItem } from '../proposals-list-item';
import { ProposalsListFilter } from '../proposals-list-filter'; import { ProposalsListFilter } from '../proposals-list-filter';
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
import type { ProposalQuery } from '../../proposal/__generated__/Proposal'; import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
interface ProposalsListProps { interface ProposalsListProps {
proposals: Array<ProposalQuery['proposal'] | ProposalFieldsFragment>; proposals: ProposalQuery['proposal'][];
} }
export const RejectedProposalsList = ({ proposals }: ProposalsListProps) => { export const RejectedProposalsList = ({ proposals }: ProposalsListProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const [filterString, setFilterString] = useState(''); const [filterString, setFilterString] = useState('');
const filterPredicate = ( const filterPredicate = (p: ProposalQuery['proposal']) =>
p: ProposalFieldsFragment | ProposalQuery['proposal']
) =>
p?.id?.includes(filterString) || p?.id?.includes(filterString) ||
p?.party?.id?.toString().includes(filterString); p?.party?.id?.toString().includes(filterString);
@@ -28,17 +28,20 @@ export const useProposalNetworkParams = ({
NetworkParams.governance_proposal_freeform_requiredParticipation, NetworkParams.governance_proposal_freeform_requiredParticipation,
]); ]);
const fallback = {
requiredMajority: new BigNumber(1),
requiredMajorityLP: new BigNumber(0),
requiredParticipation: new BigNumber(1),
requiredParticipationLP: new BigNumber(0),
};
if (!params) { if (!params) {
return { return fallback;
requiredMajority: new BigNumber(1),
requiredMajorityLP: new BigNumber(0),
requiredParticipation: new BigNumber(1),
requiredParticipationLP: new BigNumber(0),
};
} }
switch (proposal?.terms.change.__typename) { switch (proposal?.terms.change.__typename) {
case 'UpdateMarket': case 'UpdateMarket':
case 'UpdateMarketState':
return { return {
requiredMajority: requiredMajority:
params.governance_proposal_updateMarket_requiredMajority, params.governance_proposal_updateMarket_requiredMajority,
@@ -89,6 +92,6 @@ export const useProposalNetworkParams = ({
), ),
}; };
default: default:
throw new Error('Unknown proposal type'); return fallback;
} }
}; };
@@ -1,4 +1,53 @@
query Proposal($proposalId: ID!) { fragment NewMarketProductField on Proposal {
terms {
change {
... on NewMarket {
instrument {
product {
__typename
}
}
}
}
}
}
fragment UpdateMarketState on Proposal {
terms {
change {
... on UpdateMarketState {
updateType
market {
decimalPlaces
id
tradableInstrument {
instrument {
product {
__typename
... on Future {
quoteName
}
... on Perpetual {
quoteName
}
}
name
code
}
}
}
updateType
price
}
}
}
}
query Proposal(
$proposalId: ID!
$includeNewMarketProductField: Boolean!
$includeUpdateMarketState: Boolean!
) {
proposal(id: $proposalId) { proposal(id: $proposalId) {
id id
rationale { rationale {
@@ -13,6 +62,8 @@ query Proposal($proposalId: ID!) {
id id
} }
errorDetails errorDetails
...NewMarketProductField @include(if: $includeNewMarketProductField)
...UpdateMarketState @include(if: $includeUpdateMarketState)
terms { terms {
closingDatetime closingDatetime
enactmentDatetime enactmentDatetime
@@ -20,7 +71,6 @@ query Proposal($proposalId: ID!) {
... on NewMarket { ... on NewMarket {
decimalPlaces decimalPlaces
metadata metadata
lpPriceRange
riskParameters { riskParameters {
... on LogNormalRiskModel { ... on LogNormalRiskModel {
riskAversionParameter riskAversionParameter
@@ -152,7 +202,6 @@ query Proposal($proposalId: ID!) {
} }
} }
positionDecimalPlaces positionDecimalPlaces
lpPriceRange
linearSlippageFactor linearSlippageFactor
quadraticSlippageFactor quadraticSlippageFactor
} }
@@ -162,37 +211,13 @@ query Proposal($proposalId: ID!) {
instrument { instrument {
code code
product { product {
quoteName ... on UpdateFutureProduct {
dataSourceSpecForSettlementData { quoteName
sourceType { dataSourceSpecForSettlementData {
... on DataSourceDefinitionInternal { sourceType {
sourceType { ... on DataSourceDefinitionInternal {
... on DataSourceSpecConfigurationTime { sourceType {
conditions { ... on DataSourceSpecConfigurationTime {
operator
value
}
}
}
}
... on DataSourceDefinitionExternal {
sourceType {
... on DataSourceSpecConfiguration {
signers {
signer {
... on PubKey {
key
}
... on ETHAddress {
address
}
}
}
filters {
key {
name
type
}
conditions { conditions {
operator operator
value value
@@ -200,52 +225,125 @@ query Proposal($proposalId: ID!) {
} }
} }
} }
... on DataSourceDefinitionExternal {
sourceType {
... on DataSourceSpecConfiguration {
signers {
signer {
... on PubKey {
key
}
... on ETHAddress {
address
}
}
}
filters {
key {
name
type
}
conditions {
operator
value
}
}
}
}
}
} }
} }
# dataSourceSpecForTradingTermination {
# sourceType {
# ... on DataSourceDefinitionInternal {
# sourceType {
# ... on DataSourceSpecConfigurationTime {
# conditions {
# operator
# value
# }
# }
# }
# }
# ... on DataSourceDefinitionExternal {
# sourceType {
# ... on DataSourceSpecConfiguration {
# signers {
# signer {
# ... on PubKey {
# key
# }
# ... on ETHAddress {
# address
# }
# }
# }
# filters {
# key {
# name
# type
# }
# conditions {
# operator
# value
# }
# }
# }
# }
# }
# }
# }
dataSourceSpecBinding {
settlementDataProperty
tradingTerminationProperty
}
} }
# dataSourceSpecForTradingTermination { ... on UpdatePerpetualProduct {
# sourceType { quoteName
# ... on DataSourceDefinitionInternal { dataSourceSpecForSettlementData {
# sourceType { sourceType {
# ... on DataSourceSpecConfigurationTime { ... on DataSourceDefinitionInternal {
# conditions { sourceType {
# operator ... on DataSourceSpecConfigurationTime {
# value conditions {
# } operator
# } value
# } }
# } }
# ... on DataSourceDefinitionExternal { }
# sourceType { }
# ... on DataSourceSpecConfiguration { ... on DataSourceDefinitionExternal {
# signers { sourceType {
# signer { ... on DataSourceSpecConfiguration {
# ... on PubKey { signers {
# key signer {
# } ... on PubKey {
# ... on ETHAddress { key
# address }
# } ... on ETHAddress {
# } address
# } }
# filters { }
# key { }
# name filters {
# type key {
# } name
# conditions { type
# operator }
# value conditions {
# } operator
# } value
# } }
# } }
# } }
# } }
# } }
dataSourceSpecBinding { }
settlementDataProperty }
tradingTerminationProperty dataSourceSpecBinding {
settlementDataProperty
settlementScheduleProperty
}
} }
} }
} }
File diff suppressed because one or more lines are too long
@@ -6,6 +6,11 @@ import { MockedProvider } from '@apollo/client/testing';
import { MemoryRouter, Route, Routes } from 'react-router-dom'; import { MemoryRouter, Route, Routes } from 'react-router-dom';
import { ProposalDocument } from './__generated__/Proposal'; import { ProposalDocument } from './__generated__/Proposal';
jest.mock('@vegaprotocol/data-provider', () => ({
...jest.requireActual('@vegaprotocol/data-provider'),
useDataProvider: jest.fn(() => ({ data: [], loading: false })),
}));
jest.mock('../components/proposal', () => ({ jest.mock('../components/proposal', () => ({
Proposal: () => <div data-testid="proposal" />, Proposal: () => <div data-testid="proposal" />,
})); }));
@@ -44,7 +49,9 @@ const renderComponent = (
); );
}; };
describe('Proposal container', () => { // These tests are broken due to schema changes. NewMarket.futureProduct -> NewMarket.product union
// eslint-disable-next-line jest/no-disabled-tests
describe.skip('Proposal container', () => {
it('Renders not found if the proposal is not found', async () => { it('Renders not found if the proposal is not found', async () => {
render(renderComponent(null, 'foo')); render(renderComponent(null, 'foo'));
await waitFor(() => { await waitFor(() => {
@@ -53,7 +53,11 @@ export const ProposalContainer = () => {
const { data, loading, error, refetch } = useProposalQuery({ const { data, loading, error, refetch } = useProposalQuery({
fetchPolicy: 'network-only', fetchPolicy: 'network-only',
errorPolicy: 'ignore', errorPolicy: 'ignore',
variables: { proposalId: params.proposalId || '' }, variables: {
proposalId: params.proposalId || '',
includeNewMarketProductField: !!FLAGS.PRODUCT_PERPETUALS,
includeUpdateMarketState: !!FLAGS.UPDATE_MARKET_STATE,
},
skip: !params.proposalId, skip: !params.proposalId,
}); });
@@ -91,9 +95,9 @@ export const ProposalContainer = () => {
); );
const { const {
data: newMarketData, data: marketData,
loading: newMarketLoading, loading: marketLoading,
error: newMarketError, error: marketError,
} = useDataProvider({ } = useDataProvider({
dataProvider: marketInfoProvider, dataProvider: marketInfoProvider,
skipUpdates: true, skipUpdates: true,
@@ -109,9 +113,9 @@ export const ProposalContainer = () => {
error: parentMarketIdError, error: parentMarketIdError,
} = useParentMarketIdQuery({ } = useParentMarketIdQuery({
variables: { variables: {
marketId: newMarketData?.id || '', marketId: marketData?.id || '',
}, },
skip: !FLAGS.SUCCESSOR_MARKETS || !isSuccessor || !newMarketData?.id, skip: !FLAGS.SUCCESSOR_MARKETS || !isSuccessor || !marketData?.id,
}); });
const { const {
@@ -191,7 +195,7 @@ export const ProposalContainer = () => {
<AsyncRenderer <AsyncRenderer
loading={ loading={
loading || loading ||
newMarketLoading || marketLoading ||
assetLoading || assetLoading ||
networkParamsLoading || networkParamsLoading ||
parentMarketIdLoading || parentMarketIdLoading ||
@@ -206,7 +210,7 @@ export const ProposalContainer = () => {
} }
error={ error={
error || error ||
newMarketError || marketError ||
assetError || assetError ||
networkParamsError || networkParamsError ||
parentMarketIdError || parentMarketIdError ||
@@ -218,7 +222,7 @@ export const ProposalContainer = () => {
data={{ data={{
...data, ...data,
...networkParams, ...networkParams,
...(newMarketData ? { newMarketData } : {}), ...(marketData ? { newMarketData: marketData } : {}),
...(parentMarketData ? { parentMarketData } : {}), ...(parentMarketData ? { parentMarketData } : {}),
...(assetData ? { assetData } : {}), ...(assetData ? { assetData } : {}),
...(restData ? { restData } : {}), ...(restData ? { restData } : {}),
@@ -235,7 +239,7 @@ export const ProposalContainer = () => {
proposal={data.proposal} proposal={data.proposal}
networkParams={networkParams} networkParams={networkParams}
restData={restData} restData={restData}
newMarketData={newMarketData} marketData={marketData}
parentMarketData={parentMarketData} parentMarketData={parentMarketData}
assetData={assetData} assetData={assetData}
originalMarketProposalRestData={originalMarketProposalRestData} originalMarketProposalRestData={originalMarketProposalRestData}
@@ -1,3 +1,48 @@
fragment NewMarketProductFields on Proposal {
terms {
change {
... on NewMarket {
instrument {
product {
__typename
}
}
}
}
}
}
fragment UpdateMarketStates on Proposal {
terms {
change {
... on UpdateMarketState {
updateType
market {
decimalPlaces
id
tradableInstrument {
instrument {
product {
__typename
... on Future {
quoteName
}
... on Perpetual {
quoteName
}
}
name
code
}
}
}
updateType
price
}
}
}
}
fragment ProposalFields on Proposal { fragment ProposalFields on Proposal {
id id
rationale { rationale {
@@ -79,11 +124,16 @@ fragment ProposalFields on Proposal {
} }
} }
query Proposals { query Proposals(
$includeNewMarketProductFields: Boolean!
$includeUpdateMarketStates: Boolean!
) {
proposalsConnection { proposalsConnection {
edges { edges {
node { node {
...ProposalFields ...ProposalFields
...NewMarketProductFields @include(if: $includeNewMarketProductFields)
...UpdateMarketStates @include(if: $includeUpdateMarketStates)
} }
} }
} }
@@ -3,13 +3,67 @@ 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 ProposalFieldsFragment = { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: any, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string }, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: any, enactmentDatetime?: any | null, change: { __typename?: 'CancelTransfer' } | { __typename: 'NewAsset', name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string, withdrawThreshold: string, lifetimeLimit: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null } } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset', quantum: string, assetId: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string } } }; export type NewMarketProductFieldsFragment = { __typename?: 'Proposal', terms: { __typename?: 'ProposalTerms', change: { __typename?: 'CancelTransfer' } | { __typename?: 'NewAsset' } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', product?: { __typename: 'FutureProduct' } | { __typename: 'PerpetualProduct' } | { __typename: 'SpotProduct' } | null } } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset' } | { __typename?: 'UpdateMarket' } | { __typename?: 'UpdateMarketState' } | { __typename?: 'UpdateNetworkParameter' } | { __typename?: 'UpdateReferralProgram' } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram' } } };
export type ProposalsQueryVariables = Types.Exact<{ [key: string]: never; }>; export type UpdateMarketStatesFragment = { __typename?: 'Proposal', terms: { __typename?: 'ProposalTerms', change: { __typename?: 'CancelTransfer' } | { __typename?: 'NewAsset' } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket' } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset' } | { __typename?: 'UpdateMarket' } | { __typename?: 'UpdateMarketState', updateType: Types.MarketUpdateType, price?: string | null, market: { __typename?: 'Market', decimalPlaces: number, id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, code: string, product: { __typename: 'Future', quoteName: string } | { __typename: 'Perpetual', quoteName: string } | { __typename: 'Spot' } } } } } | { __typename?: 'UpdateNetworkParameter' } | { __typename?: 'UpdateReferralProgram' } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram' } } };
export type ProposalFieldsFragment = { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: any, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string }, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: any, enactmentDatetime?: any | null, change: { __typename?: 'CancelTransfer' } | { __typename: 'NewAsset', name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string, withdrawThreshold: string, lifetimeLimit: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null } } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset', quantum: string, assetId: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateMarketState' } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } | { __typename?: 'UpdateReferralProgram' } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram' } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string } } };
export type ProposalsQueryVariables = Types.Exact<{
includeNewMarketProductFields: Types.Scalars['Boolean'];
includeUpdateMarketStates: Types.Scalars['Boolean'];
}>;
export type ProposalsQuery = { __typename?: 'Query', proposalsConnection?: { __typename?: 'ProposalsConnection', edges?: Array<{ __typename?: 'ProposalEdge', node: { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: any, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string }, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: any, enactmentDatetime?: any | null, change: { __typename?: 'CancelTransfer' } | { __typename: 'NewAsset', name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string, withdrawThreshold: string, lifetimeLimit: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null } } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset', quantum: string, assetId: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string } } } } | null> | null } | null }; export type ProposalsQuery = { __typename?: 'Query', proposalsConnection?: { __typename?: 'ProposalsConnection', edges?: Array<{ __typename?: 'ProposalEdge', node: { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: any, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string }, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: any, enactmentDatetime?: any | null, change: { __typename?: 'CancelTransfer' } | { __typename: 'NewAsset', name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string, withdrawThreshold: string, lifetimeLimit: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null, product?: { __typename: 'FutureProduct' } | { __typename: 'PerpetualProduct' } | { __typename: 'SpotProduct' } | null } } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset', quantum: string, assetId: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateMarketState', updateType: Types.MarketUpdateType, price?: string | null, market: { __typename?: 'Market', decimalPlaces: number, id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, code: string, product: { __typename: 'Future', quoteName: string } | { __typename: 'Perpetual', quoteName: string } | { __typename: 'Spot' } } } } } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } | { __typename?: 'UpdateReferralProgram' } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram' } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string } } } } | null> | null } | null };
export const NewMarketProductFieldsFragmentDoc = gql`
fragment NewMarketProductFields on Proposal {
terms {
change {
... on NewMarket {
instrument {
product {
__typename
}
}
}
}
}
}
`;
export const UpdateMarketStatesFragmentDoc = gql`
fragment UpdateMarketStates on Proposal {
terms {
change {
... on UpdateMarketState {
updateType
market {
decimalPlaces
id
tradableInstrument {
instrument {
product {
__typename
... on Future {
quoteName
}
... on Perpetual {
quoteName
}
}
name
code
}
}
}
updateType
price
}
}
}
}
`;
export const ProposalFieldsFragmentDoc = gql` export const ProposalFieldsFragmentDoc = gql`
fragment ProposalFields on Proposal { fragment ProposalFields on Proposal {
id id
@@ -93,16 +147,20 @@ export const ProposalFieldsFragmentDoc = gql`
} }
`; `;
export const ProposalsDocument = gql` export const ProposalsDocument = gql`
query Proposals { query Proposals($includeNewMarketProductFields: Boolean!, $includeUpdateMarketStates: Boolean!) {
proposalsConnection { proposalsConnection {
edges { edges {
node { node {
...ProposalFields ...ProposalFields
...NewMarketProductFields @include(if: $includeNewMarketProductFields)
...UpdateMarketStates @include(if: $includeUpdateMarketStates)
} }
} }
} }
} }
${ProposalFieldsFragmentDoc}`; ${ProposalFieldsFragmentDoc}
${NewMarketProductFieldsFragmentDoc}
${UpdateMarketStatesFragmentDoc}`;
/** /**
* __useProposalsQuery__ * __useProposalsQuery__
@@ -116,10 +174,12 @@ export const ProposalsDocument = gql`
* @example * @example
* const { data, loading, error } = useProposalsQuery({ * const { data, loading, error } = useProposalsQuery({
* variables: { * variables: {
* includeNewMarketProductFields: // value for 'includeNewMarketProductFields'
* includeUpdateMarketStates: // value for 'includeUpdateMarketStates'
* }, * },
* }); * });
*/ */
export function useProposalsQuery(baseOptions?: Apollo.QueryHookOptions<ProposalsQuery, ProposalsQueryVariables>) { export function useProposalsQuery(baseOptions: Apollo.QueryHookOptions<ProposalsQuery, ProposalsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions} const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<ProposalsQuery, ProposalsQueryVariables>(ProposalsDocument, options); return Apollo.useQuery<ProposalsQuery, ProposalsQueryVariables>(ProposalsDocument, options);
} }
@@ -6,7 +6,7 @@ import { useTranslation } from 'react-i18next';
import { SplashLoader } from '../../../components/splash-loader'; import { SplashLoader } from '../../../components/splash-loader';
import { ProposalsList } from '../components/proposals-list'; import { ProposalsList } from '../components/proposals-list';
import { useProposalsQuery } from './__generated__/Proposals'; import { useProposalsQuery } from './__generated__/Proposals';
import { getNodes } from '@vegaprotocol/utils'; import { getNodes, removePaginationWrapper } from '@vegaprotocol/utils';
import { import {
ProposalState, ProposalState,
ProtocolUpgradeProposalStatus, ProtocolUpgradeProposalStatus,
@@ -15,14 +15,13 @@ import type { NodeConnection, NodeEdge } from '@vegaprotocol/utils';
import type { ProposalFieldsFragment } from './__generated__/Proposals'; import type { ProposalFieldsFragment } from './__generated__/Proposals';
import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals'; import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals';
import { useProtocolUpgradeProposalsQuery } from '@vegaprotocol/proposals'; import { useProtocolUpgradeProposalsQuery } from '@vegaprotocol/proposals';
import { FLAGS } from '@vegaprotocol/environment';
export function getNotRejectedProposals<T extends ProposalFieldsFragment>( export function getNotRejectedProposals(data?: ProposalFieldsFragment[]) {
data?: NodeConnection<NodeEdge<T>> | null
): T[] {
return flow([ return flow([
(data) => (data) =>
getNodes<ProposalFieldsFragment>(data, (p) => data.filter(
p ? p.state !== ProposalState.STATE_REJECTED : false (p: ProposalFieldsFragment) => p?.state !== ProposalState.STATE_REJECTED
), ),
])(data); ])(data);
} }
@@ -47,6 +46,10 @@ export const ProposalsContainer = () => {
pollInterval: 5000, pollInterval: 5000,
fetchPolicy: 'network-only', fetchPolicy: 'network-only',
errorPolicy: 'ignore', errorPolicy: 'ignore',
variables: {
includeNewMarketProductFields: !!FLAGS.PRODUCT_PERPETUALS,
includeUpdateMarketStates: !!FLAGS.UPDATE_MARKET_STATE,
},
}); });
const { const {
@@ -60,7 +63,10 @@ export const ProposalsContainer = () => {
}); });
const proposals = useMemo( const proposals = useMemo(
() => getNotRejectedProposals(data?.proposalsConnection), () =>
getNotRejectedProposals(
removePaginationWrapper(data?.proposalsConnection?.edges)
),
[data] [data]
); );
@@ -6,11 +6,11 @@ import { SplashLoader } from '../../../components/splash-loader';
import { RejectedProposalsList } from '../components/proposals-list'; import { RejectedProposalsList } from '../components/proposals-list';
import type { ProposalFieldsFragment } from '../proposals/__generated__/Proposals'; import type { ProposalFieldsFragment } from '../proposals/__generated__/Proposals';
import { useProposalsQuery } from '../proposals/__generated__/Proposals'; import { useProposalsQuery } from '../proposals/__generated__/Proposals';
import type { NodeConnection, NodeEdge } from '@vegaprotocol/utils'; import { removePaginationWrapper } from '@vegaprotocol/utils';
import { getNodes } from '@vegaprotocol/utils';
import flow from 'lodash/flow'; import flow from 'lodash/flow';
import orderBy from 'lodash/orderBy'; import orderBy from 'lodash/orderBy';
import { ProposalState } from '@vegaprotocol/types'; import { ProposalState } from '@vegaprotocol/types';
import { FLAGS } from '@vegaprotocol/environment';
const orderByDate = (arr: ProposalFieldsFragment[]) => const orderByDate = (arr: ProposalFieldsFragment[]) =>
orderBy( orderBy(
@@ -22,13 +22,11 @@ const orderByDate = (arr: ProposalFieldsFragment[]) =>
['desc', 'desc'] ['desc', 'desc']
); );
export function getRejectedProposals<T extends ProposalFieldsFragment>( export function getRejectedProposals(data?: ProposalFieldsFragment[] | null) {
data?: NodeConnection<NodeEdge<ProposalFieldsFragment>> | null
): T[] {
return flow([ return flow([
(data) => (data) =>
getNodes<ProposalFieldsFragment>(data, (p) => data.filter(
p ? p?.state === ProposalState.STATE_REJECTED : false (p: ProposalFieldsFragment) => p?.state === ProposalState.STATE_REJECTED
), ),
orderByDate, orderByDate,
])(data); ])(data);
@@ -36,11 +34,21 @@ export function getRejectedProposals<T extends ProposalFieldsFragment>(
export const RejectedProposalsContainer = () => { export const RejectedProposalsContainer = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { data, loading, error } = useProposalsQuery(); const { data, loading, error } = useProposalsQuery({
pollInterval: 5000,
fetchPolicy: 'network-only',
errorPolicy: 'ignore',
variables: {
includeNewMarketProductFields: !!FLAGS.PRODUCT_PERPETUALS,
includeUpdateMarketStates: !!FLAGS.UPDATE_MARKET_STATE,
},
});
const proposals = useMemo( const proposals = useMemo(
() => () =>
getRejectedProposals<ProposalFieldsFragment>(data?.proposalsConnection), getRejectedProposals(
removePaginationWrapper(data?.proposalsConnection?.edges)
),
[data] [data]
); );
@@ -1,4 +1,4 @@
import { useMemo, useEffect, useState, useCallback } from 'react'; import { useMemo, useEffect, useState, useCallback, useRef } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { AsyncRenderer, Pagination } from '@vegaprotocol/ui-toolkit'; import { AsyncRenderer, Pagination } from '@vegaprotocol/ui-toolkit';
import { removePaginationWrapper } from '@vegaprotocol/utils'; import { removePaginationWrapper } from '@vegaprotocol/utils';
@@ -86,12 +86,18 @@ export const EpochIndividualRewards = ({
[epochId, page, refetch, delegationsPagination, pubKey] [epochId, page, refetch, delegationsPagination, pubKey]
); );
const prevEpochIdRef = useRef<number | null>(null);
useEffect(() => { useEffect(() => {
// when the epoch changes, we want to refetch the data to update the current page if (prevEpochIdRef.current === null) {
if (data) { prevEpochIdRef.current = epochId;
} else if (epochId !== prevEpochIdRef.current) {
// When the epoch changes, we want to refetch the data to update the current page
refetchData(); refetchData();
} }
}, [epochId, data, refetchData]);
prevEpochIdRef.current = epochId;
}, [epochId, refetchData]);
return ( return (
<AsyncRenderer <AsyncRenderer
@@ -3,7 +3,7 @@ import { forwardRef, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { Button, Icon } from '@vegaprotocol/ui-toolkit'; import { Button, Icon } from '@vegaprotocol/ui-toolkit';
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid'; import { AgGrid } from '@vegaprotocol/datagrid';
import { useAppState } from '../../../../contexts/app-state/app-state-context'; import { useAppState } from '../../../../contexts/app-state/app-state-context';
import { BigNumber } from '../../../../lib/bignumber'; import { BigNumber } from '../../../../lib/bignumber';
import { import {
@@ -85,17 +85,17 @@ const TopThirdCellRenderer = (
}} }}
className="grid grid-cols-[60px_1fr] w-full h-full py-4 px-0 text-sm text-white text-center overflow-scroll" className="grid grid-cols-[60px_1fr] w-full h-full py-4 px-0 text-sm text-white text-center overflow-scroll"
> >
<div className="text-xs text-left px-3"> <div className="px-3 text-xs text-left">
{params?.data?.rankingDisplay} {params?.data?.rankingDisplay}
</div> </div>
<div className="whitespace-normal px-3"> <div className="px-3 whitespace-normal">
<div className="mb-4"> <div className="mb-4">
<Button <Button
data-testid="show-all-validators" data-testid="show-all-validators"
rightIcon={ rightIcon={
<Icon <Icon
name="arrow-right" name="arrow-right"
className="fill-current mr-2 align-text-top" className="mr-2 align-text-top fill-current"
/> />
} }
className="inline-flex items-center" className="inline-flex items-center"
@@ -103,7 +103,7 @@ const TopThirdCellRenderer = (
{t('Reveal top validators')} {t('Reveal top validators')}
</Button> </Button>
</div> </div>
<p className="font-semibold text-white mb-0"> <p className="mb-0 font-semibold text-white">
{t( {t(
'Validators with too great a stake share will have the staking rewards for their delegators penalised.' 'Validators with too great a stake share will have the staking rewards for their delegators penalised.'
)} )}
@@ -352,7 +352,6 @@ export const ConsensusValidatorsTable = ({
field: ValidatorFields.RANKING_INDEX, field: ValidatorFields.RANKING_INDEX,
headerName: '#', headerName: '#',
width: 60, width: 60,
pinned: 'left',
}, },
{ {
field: ValidatorFields.VALIDATOR, field: ValidatorFields.VALIDATOR,
@@ -362,7 +361,6 @@ export const ConsensusValidatorsTable = ({
if (a === b) return 0; if (a === b) return 0;
return a > b ? 1 : -1; return a > b ? 1 : -1;
}, },
pinned: 'left',
width: 260, width: 260,
}, },
{ {
@@ -1,7 +1,7 @@
import { forwardRef, useMemo, useRef } from 'react'; import { forwardRef, useMemo, useRef } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid'; import { AgGrid } from '@vegaprotocol/datagrid';
import { useAppState } from '../../../../contexts/app-state/app-state-context'; import { useAppState } from '../../../../contexts/app-state/app-state-context';
import { BigNumber } from '../../../../lib/bignumber'; import { BigNumber } from '../../../../lib/bignumber';
import { import {
@@ -195,14 +195,12 @@ export const StandbyPendingValidatorsTable = ({
field: ValidatorFields.RANKING_INDEX, field: ValidatorFields.RANKING_INDEX,
headerName: '#', headerName: '#',
width: 60, width: 60,
pinned: 'left',
}, },
{ {
field: ValidatorFields.VALIDATOR, field: ValidatorFields.VALIDATOR,
headerName: t(ValidatorFields.VALIDATOR).toString(), headerName: t(ValidatorFields.VALIDATOR).toString(),
cellRenderer: ValidatorRenderer, cellRenderer: ValidatorRenderer,
comparator: ({ name: a }, { name: b }) => Math.sign(a - b), comparator: ({ name: a }, { name: b }) => Math.sign(a - b),
pinned: 'left',
width: 260, width: 260,
}, },
{ {
@@ -122,38 +122,43 @@ export const ValidatorTable = ({
<div className="my-12" data-testid="validator-table"> <div className="my-12" data-testid="validator-table">
<SubHeading title={t('profile')} /> <SubHeading title={t('profile')} />
<RoundedWrapper paddingBottom={true}> <div className="break-all">
<KeyValueTable data-testid="validator-table-profile"> <RoundedWrapper paddingBottom={true}>
<KeyValueTableRow> <KeyValueTable data-testid="validator-table-profile">
<span>{t('id')}</span> <KeyValueTableRow>
<ValidatorTableCell dataTestId="validator-id"> <span>{t('id')}</span>
{node.id} <ValidatorTableCell dataTestId="validator-id">
</ValidatorTableCell> {node.id}
</KeyValueTableRow> </ValidatorTableCell>
<KeyValueTableRow> </KeyValueTableRow>
<span>{t('ABOUT THIS VALIDATOR')}</span> <KeyValueTableRow>
<span>{t('ABOUT THIS VALIDATOR')}</span>
<Tooltip description={t('AboutThisValidatorDescription')}> <Tooltip description={t('AboutThisValidatorDescription')}>
<a data-testid="validator-description-url" href={node.infoUrl}> <a
{node.infoUrl} data-testid="validator-description-url"
</a> href={node.infoUrl}
</Tooltip> >
</KeyValueTableRow> {node.infoUrl}
<KeyValueTableRow noBorder={true}> </a>
<span> </Tooltip>
<strong>{t('STATUS')}</strong> </KeyValueTableRow>
</span> <KeyValueTableRow noBorder={true}>
<span>
<Tooltip description={t('ValidatorStatusDescription')}> <strong>{t('STATUS')}</strong>
<span data-testid="validator-status">
<strong>
{t(statusTranslationKey(node.rankingScore.status))}
</strong>
</span> </span>
</Tooltip>
</KeyValueTableRow> <Tooltip description={t('ValidatorStatusDescription')}>
</KeyValueTable> <span data-testid="validator-status">
</RoundedWrapper> <strong>
{t(statusTranslationKey(node.rankingScore.status))}
</strong>
</span>
</Tooltip>
</KeyValueTableRow>
</KeyValueTable>
</RoundedWrapper>
</div>
<div className="mb-10"> <div className="mb-10">
{t('validatorTableIntro')}{' '} {t('validatorTableIntro')}{' '}
@@ -167,144 +172,154 @@ export const ValidatorTable = ({
</div> </div>
<SubHeading title={t('ADDRESS')} /> <SubHeading title={t('ADDRESS')} />
<RoundedWrapper marginBottomLarge={true} paddingBottom={true}> <div className="break-all">
<KeyValueTable data-testid="validator-table-address"> <RoundedWrapper marginBottomLarge={true} paddingBottom={true}>
<KeyValueTableRow> <KeyValueTable data-testid="validator-table-address">
<span>{t('VEGA ADDRESS / PUBLIC KEY')}</span> <KeyValueTableRow>
<ValidatorTableCell dataTestId="validator-public-key"> <span>{t('VEGA ADDRESS / PUBLIC KEY')}</span>
{node.pubkey} <ValidatorTableCell dataTestId="validator-public-key">
</ValidatorTableCell> {node.pubkey}
</KeyValueTableRow> </ValidatorTableCell>
<KeyValueTableRow> </KeyValueTableRow>
<span>{t('SERVER LOCATION')}</span> <KeyValueTableRow>
<ValidatorTableCell dataTestId="validator-server-location"> <span>{t('SERVER LOCATION')}</span>
{countryData.find((c) => c.code === node.location)?.name || <ValidatorTableCell dataTestId="validator-server-location">
t('not available')} {countryData.find((c) => c.code === node.location)?.name ||
</ValidatorTableCell> t('not available')}
</KeyValueTableRow> </ValidatorTableCell>
<KeyValueTableRow noBorder={true}> </KeyValueTableRow>
<span>{t('ETHEREUM ADDRESS')}</span> <KeyValueTableRow noBorder={true}>
<span data-testid="validator-eth-address"> <span>{t('ETHEREUM ADDRESS')}</span>
<Link <span data-testid="validator-eth-address">
title={t('View on Etherscan (opens in a new tab)')} <Link
href={`${ETHERSCAN_URL}/address/${node.ethereumAddress}`} title={t('View on Etherscan (opens in a new tab)')}
target="_blank" href={`${ETHERSCAN_URL}/address/${node.ethereumAddress}`}
> target="_blank"
{node.ethereumAddress} >
</Link> {node.ethereumAddress}
</span> </Link>
</KeyValueTableRow> </span>
</KeyValueTable> </KeyValueTableRow>
</RoundedWrapper> </KeyValueTable>
</RoundedWrapper>
</div>
<SubHeading title={t('STAKE')} /> <SubHeading title={t('STAKE')} />
<RoundedWrapper marginBottomLarge={true} paddingBottom={true}> <div className="break-all">
<KeyValueTable data-testid="validator-table-stake"> <RoundedWrapper marginBottomLarge={true} paddingBottom={true}>
<KeyValueTableRow> <KeyValueTable data-testid="validator-table-stake">
<span>{t('STAKED BY OPERATOR')}</span> <KeyValueTableRow>
<span>{t('STAKED BY OPERATOR')}</span>
<Tooltip description={t('StakedByOperatorDescription')}> <Tooltip description={t('StakedByOperatorDescription')}>
<span data-testid="staked-by-operator"> <span data-testid="staked-by-operator">
{formatNumber(toBigNum(node.stakedByOperator, decimals))} {formatNumber(toBigNum(node.stakedByOperator, decimals))}
</span>
</Tooltip>
</KeyValueTableRow>
<KeyValueTableRow>
<span>{t('STAKED BY DELEGATES')}</span>
<Tooltip description={t('StakedByDelegatesDescription')}>
<span data-testid="staked-by-delegates">
{formatNumber(toBigNum(node.stakedByDelegates, decimals))}
</span>
</Tooltip>
</KeyValueTableRow>
<KeyValueTableRow>
<span>
<strong>{t('TOTAL STAKE')}</strong>
</span> </span>
</Tooltip>
</KeyValueTableRow>
<KeyValueTableRow>
<span>{t('STAKED BY DELEGATES')}</span>
<Tooltip description={t('StakedByDelegatesDescription')}> <span data-testid="total-stake">
<span data-testid="staked-by-delegates"> <strong>
{formatNumber(toBigNum(node.stakedByDelegates, decimals))} {formatNumber(toBigNum(node.stakedTotal, decimals))}
</strong>
</span> </span>
</Tooltip> </KeyValueTableRow>
</KeyValueTableRow> <KeyValueTableRow>
<KeyValueTableRow> <span>{t('PENDING STAKE')}</span>
<span>
<strong>{t('TOTAL STAKE')}</strong>
</span>
<span data-testid="total-stake"> <Tooltip description={t('PendingStakeDescription')}>
<strong> <span data-testid="pending-stake">
{formatNumber(toBigNum(node.stakedTotal, decimals))} {formatNumber(toBigNum(node.pendingStake, decimals))}
</strong> </span>
</span> </Tooltip>
</KeyValueTableRow> </KeyValueTableRow>
<KeyValueTableRow> <KeyValueTableRow noBorder={true}>
<span>{t('PENDING STAKE')}</span> <span>{t('STAKE SHARE')}</span>
<Tooltip description={t('PendingStakeDescription')}> <Tooltip description={t('StakeShareDescription')}>
<span data-testid="pending-stake"> <span data-testid="stake-percentage">{stakePercentage}</span>
{formatNumber(toBigNum(node.pendingStake, decimals))} </Tooltip>
</span> </KeyValueTableRow>
</Tooltip> </KeyValueTable>
</KeyValueTableRow> </RoundedWrapper>
<KeyValueTableRow noBorder={true}> </div>
<span>{t('STAKE SHARE')}</span>
<Tooltip description={t('StakeShareDescription')}>
<span data-testid="stake-percentage">{stakePercentage}</span>
</Tooltip>
</KeyValueTableRow>
</KeyValueTable>
</RoundedWrapper>
<SubHeading title={t('PENALTIES')} /> <SubHeading title={t('PENALTIES')} />
<RoundedWrapper marginBottomLarge={true} paddingBottom={true}> <div className="break-all">
<KeyValueTable data-testid="validator-table-penalties"> <RoundedWrapper marginBottomLarge={true} paddingBottom={true}>
<KeyValueTableRow> <KeyValueTable data-testid="validator-table-penalties">
<span>{t('OVERSTAKED PENALTY')}</span> <KeyValueTableRow>
<span>{t('OVERSTAKED PENALTY')}</span>
<Tooltip description={t('OverstakedPenaltyDescription')}> <Tooltip description={t('OverstakedPenaltyDescription')}>
<span data-testid="overstaking-penalty"> <span data-testid="overstaking-penalty">
{formatNumberPercentage(penalties.overstaked, 2)} {formatNumberPercentage(penalties.overstaked, 2)}
</span> </span>
</Tooltip> </Tooltip>
</KeyValueTableRow> </KeyValueTableRow>
<KeyValueTableRow> <KeyValueTableRow>
<span>{t('PERFORMANCE PENALTY')}</span> <span>{t('PERFORMANCE PENALTY')}</span>
<Tooltip description={t('PerformancePenaltyDescription')}> <Tooltip description={t('PerformancePenaltyDescription')}>
<span data-testid="performance-penalty"> <span data-testid="performance-penalty">
{formatNumberPercentage(penalties.performance, 2)} {formatNumberPercentage(penalties.performance, 2)}
</span>
</Tooltip>
</KeyValueTableRow>
<KeyValueTableRow noBorder={true}>
<span>
<strong>{t('TOTAL PENALTIES')}</strong>
</span> </span>
</Tooltip> <span data-testid="total-penalties">
</KeyValueTableRow> <strong>
<KeyValueTableRow noBorder={true}> {formatNumberPercentage(penalties.overall, 2)}
<span> </strong>
<strong>{t('TOTAL PENALTIES')}</strong> </span>
</span> </KeyValueTableRow>
<span data-testid="total-penalties"> </KeyValueTable>
<strong>{formatNumberPercentage(penalties.overall, 2)}</strong> </RoundedWrapper>
</span> </div>
</KeyValueTableRow>
</KeyValueTable>
</RoundedWrapper>
<SubHeading title={t('VOTING POWER')} /> <SubHeading title={t('VOTING POWER')} />
<RoundedWrapper marginBottomLarge={true} paddingBottom={true}> <div className="break-all">
<KeyValueTable data-testid="validator-table-voting-power"> <RoundedWrapper marginBottomLarge={true} paddingBottom={true}>
<KeyValueTableRow> <KeyValueTable data-testid="validator-table-voting-power">
<span>{t('UNNORMALISED VOTING POWER')}</span> <KeyValueTableRow>
<span>{t('UNNORMALISED VOTING POWER')}</span>
<Tooltip description={t('UnnormalisedVotingPowerDescription')}> <Tooltip description={t('UnnormalisedVotingPowerDescription')}>
<span data-testid="unnormalised-voting-power"> <span data-testid="unnormalised-voting-power">
{getUnnormalisedVotingPower(rawValidatorScore)} {getUnnormalisedVotingPower(rawValidatorScore)}
</span>
</Tooltip>
</KeyValueTableRow>
<KeyValueTableRow noBorder={true}>
<span>
<strong>{t('NORMALISED VOTING POWER')}</strong>
</span> </span>
</Tooltip>
</KeyValueTableRow>
<KeyValueTableRow noBorder={true}>
<span>
<strong>{t('NORMALISED VOTING POWER')}</strong>
</span>
<Tooltip description={t('NormalisedVotingPowerDescription')}> <Tooltip description={t('NormalisedVotingPowerDescription')}>
<strong data-testid="normalised-voting-power"> <strong data-testid="normalised-voting-power">
{getNormalisedVotingPower(node.rankingScore.votingPower)} {getNormalisedVotingPower(node.rankingScore.votingPower)}
</strong> </strong>
</Tooltip> </Tooltip>
</KeyValueTableRow> </KeyValueTableRow>
</KeyValueTable> </KeyValueTable>
</RoundedWrapper> </RoundedWrapper>
</div>
</div> </div>
</> </>
); );
@@ -54,7 +54,7 @@ export const TokenDetails = ({
config.token_vesting_contract?.address || ENV.addresses.tokenVestingAddress; config.token_vesting_contract?.address || ENV.addresses.tokenVestingAddress;
return ( return (
<div className="token-details"> <div className="token-details break-all">
<RoundedWrapper> <RoundedWrapper>
<KeyValueTable> <KeyValueTable>
<KeyValueTableRow> <KeyValueTableRow>

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