Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c183fa39f8 |
@@ -82,38 +82,3 @@ jobs:
|
||||
https://${{ env.IPFS_V1 }}.ipfs.dweb.link/
|
||||
https://${{ env.IPFS_V1 }}.ipfs.cf-ipfs.com/
|
||||
ipfs://${{ env.IPFS_V0 }}/
|
||||
|
||||
- name: Ensure 'Released' label exists
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
REPO="${{ github.repository }}"
|
||||
LABEL_EXIST=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
"https://api.github.com/repos/$REPO/labels/Released")
|
||||
if [[ "$LABEL_EXIST" == *"Not Found"* ]]; then
|
||||
curl -s -H "Authorization: token $GITHUB_TOKEN" \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
-X POST "https://api.github.com/repos/$REPO/labels" \
|
||||
-d '{"name": "Released", "color": "FFFFFF"}'
|
||||
fi
|
||||
|
||||
- name: Extract issues from release notes
|
||||
id: extract-issues
|
||||
run: |
|
||||
ISSUES=$(echo "${{ github.event.release.body }}" | grep -o -E '#[0-9]+' | tr -d '#' | jq -R . | jq -cs .)
|
||||
echo "Issues to label: $ISSUES"
|
||||
echo "::set-output name=issue_numbers::$ISSUES"
|
||||
|
||||
- name: Add 'Released' label to issues
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
ISSUE_NUMBERS="${{ steps.extract-issues.outputs.issue_numbers }}"
|
||||
REPO="${{ github.repository }}"
|
||||
for ISSUE in $(echo "$ISSUE_NUMBERS" | jq -r '.[]'); do
|
||||
curl -s -H "Authorization: token $GITHUB_TOKEN" \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
-X POST "https://api.github.com/repos/$REPO/issues/$ISSUE/labels" \
|
||||
-d '{"labels": ["Released"]}'
|
||||
done
|
||||
|
||||
@@ -5,7 +5,6 @@ on:
|
||||
branches:
|
||||
- release/*
|
||||
- develop
|
||||
- main
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
@@ -170,48 +169,25 @@ jobs:
|
||||
preview_explorer: ${{ env.PREVIEW_EXPLORER }}
|
||||
preview_tools: ${{ env.PREVIEW_TOOLS }}
|
||||
|
||||
check-e2e-needed:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-sources
|
||||
name: '(CI) check if e2e needed'
|
||||
outputs:
|
||||
run-tests: ${{ steps.check-test.outputs.e2e-needed }}
|
||||
steps:
|
||||
- name: Check branch
|
||||
id: check-test
|
||||
run: |
|
||||
if [[ "${{ github.base_ref }}" == "develop" ]]; then
|
||||
echo "e2e-needed=true" >> $GITHUB_OUTPUT
|
||||
elif [[ "${{ github.base_ref }}" == "main" ]]; then
|
||||
echo "e2e-needed=true" >> $GITHUB_OUTPUT
|
||||
elif [[ "${{ github.event_name }}" == "push" && "${{ github.ref_name }}" == *"release/"* ]]; then
|
||||
echo "e2e-needed=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "e2e-needed=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- name: Print result
|
||||
run: |
|
||||
echo "e2e-needed: ${{ steps.check-test.outputs.e2e-needed }}"
|
||||
# console-e2e:
|
||||
# needs: build-sources
|
||||
# name: '(CI) console python'
|
||||
# uses: ./.github/workflows/console-test-run.yml
|
||||
# secrets: inherit
|
||||
# if: ${{ contains(fromJSON(needs.build-sources.outputs.projects), 'trading') && github.event_name == 'pull_request' }}
|
||||
# with:
|
||||
# github-sha: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
cypress:
|
||||
needs: [build-sources, check-e2e-needed]
|
||||
needs: build-sources
|
||||
name: '(CI) cypress'
|
||||
if: ${{ needs.check-e2e-needed.outputs.run-tests == 'true' }}
|
||||
# if: ${{ needs.build-sources.outputs.projects-e2e != '[]' }}
|
||||
uses: ./.github/workflows/cypress-run.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
projects: ${{ needs.build-sources.outputs.projects-e2e }}
|
||||
tags: '@smoke'
|
||||
|
||||
console-e2e:
|
||||
needs: [build-sources, check-e2e-needed]
|
||||
name: '(CI) console python'
|
||||
uses: ./.github/workflows/console-test-run.yml
|
||||
secrets: inherit
|
||||
if: needs.check-e2e-needed.outputs.run-tests == 'true' && contains(needs.build-sources.outputs.projects, 'trading')
|
||||
with:
|
||||
github-sha: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
publish-dist:
|
||||
needs: build-sources
|
||||
name: '(CD) publish dist'
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
# https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#managing-caches
|
||||
name: cleanup caches by a branch
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- closed
|
||||
jobs:
|
||||
cleanup:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Cleanup
|
||||
run: |
|
||||
gh extension install actions/gh-actions-cache
|
||||
|
||||
echo "Fetching list of cache key"
|
||||
cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH -L 100 | cut -f 1 )
|
||||
|
||||
## Setting this to not fail the workflow while deleting cache keys.
|
||||
set +e
|
||||
echo "Deleting caches..."
|
||||
for cacheKey in $cacheKeysForPR
|
||||
do
|
||||
gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
|
||||
done
|
||||
echo "Done"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
REPO: ${{ github.repository }}
|
||||
BRANCH: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||
@@ -1,5 +1,8 @@
|
||||
name: (CI) Console tests
|
||||
|
||||
env:
|
||||
VEGA_VERSION: v0.72.14
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
@@ -16,9 +19,9 @@ on:
|
||||
- develop
|
||||
|
||||
jobs:
|
||||
create-docker-image:
|
||||
name: Create docker image for console-test
|
||||
runs-on: ubuntu-22.04
|
||||
run-tests:
|
||||
name: run-tests
|
||||
runs-on: 8-cores
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
#----------------------------------------------
|
||||
@@ -55,105 +58,23 @@ jobs:
|
||||
#----------------------------------------------
|
||||
# build trading
|
||||
#----------------------------------------------
|
||||
- name: Build trading app
|
||||
- name: Build affected spec
|
||||
run: |
|
||||
yarn env-cmd -f ./apps/trading/.env.stagnet1 yarn nx export trading
|
||||
DIST_LOCATION=dist/apps/trading/exported
|
||||
mv $DIST_LOCATION dist-result
|
||||
tree dist-result
|
||||
|
||||
#----------------------------------------------
|
||||
# export trading app docker image
|
||||
# run trading server
|
||||
#----------------------------------------------
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Build and export to local Docker
|
||||
id: docker_build
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: docker/node-outside-docker.Dockerfile
|
||||
load: true
|
||||
build-args: |
|
||||
APP=trading
|
||||
ENV_NAME=stagnet1
|
||||
tags: ci/trading:local
|
||||
outputs: type=docker,dest=/tmp/console-image.tar
|
||||
|
||||
- name: Verify docker image created
|
||||
- name: Run trading server
|
||||
run: |
|
||||
echo ${{ steps.docker_build.outputs.digest }}
|
||||
echo ${{ steps.docker_build.outputs.imageid }}
|
||||
|
||||
- name: Upload docker image for console-test usage
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: console-image
|
||||
path: /tmp/console-image.tar
|
||||
|
||||
console-test-branch:
|
||||
name: Choose console-test branch to run on
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 5
|
||||
outputs:
|
||||
console-branch: ${{ steps.output-step.outputs.branch }}
|
||||
steps:
|
||||
- name: Workflow dispatch input
|
||||
id: dispatch-step
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
run: echo "branch=${{ inputs.console-test-branch }}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Print Workflow dispatch input
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
run: echo ${{ steps.dispatch-step.outputs.branch }}
|
||||
|
||||
- name: Workflow_call input
|
||||
id: workflow_call-step
|
||||
if: github.event_name != 'workflow_dispatch'
|
||||
run: |
|
||||
if [[ "${{ github.base_ref }}" == "main" ]]; then
|
||||
echo "branch=main" >> $GITHUB_OUTPUT
|
||||
elif [[ "${{ github.base_ref }}" == "develop" && "${{ github.ref_name }}" == "main" ]]; then
|
||||
echo "branch=main" >> $GITHUB_OUTPUT
|
||||
elif [[ "${{ github.event_name }}" == "push" && "${{ github.ref_name }}" == *"release/mainnet"* ]]; then
|
||||
echo "branch=main" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "branch=develop" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Print Workflow_call input
|
||||
if: github.event_name != 'workflow_dispatch'
|
||||
run: echo ${{ steps.workflow_call-step.outputs.branch }}
|
||||
|
||||
- name: Set output
|
||||
id: output-step
|
||||
run: echo "branch=${{ steps.dispatch-step.outputs.branch || steps.workflow_call-step.outputs.branch }}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Print final output
|
||||
run: echo ${{ steps.output-step.outputs.branch }}
|
||||
|
||||
run-tests:
|
||||
name: run-tests
|
||||
runs-on: 8-cores
|
||||
needs: [create-docker-image, console-test-branch]
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
docker run -d -p 80:4200 -v $PWD/docker/nginx.conf:/etc/nginx/conf.d/default.conf -v $PWD/dist/apps/trading/exported:/usr/share/nginx/html nginx:1.23-alpine@sha256:6318314189b40e73145a48060bff4783a116c34cc7241532d0d94198fb2c9629
|
||||
sleep 5
|
||||
docker ps
|
||||
#----------------------------------------------
|
||||
# load docker image
|
||||
# check if container persists between runs
|
||||
#----------------------------------------------
|
||||
- name: Download docker image from previous job
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: console-image
|
||||
path: /tmp
|
||||
|
||||
- name: Load Docker image
|
||||
- name: Check server
|
||||
run: |
|
||||
docker load --input /tmp/console-image.tar
|
||||
docker image ls -a
|
||||
|
||||
docker ps
|
||||
#----------------------------------------------
|
||||
# check-out tests repo
|
||||
#----------------------------------------------
|
||||
@@ -161,55 +82,62 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: vegaprotocol/console-test
|
||||
ref: ${{ needs.console-test-branch.outputs.console-branch }}
|
||||
ref: ${{ inputs.console-test-branch }}
|
||||
path: './console-test'
|
||||
|
||||
- name: Load console test envs
|
||||
id: console-test-env
|
||||
uses: falti/dotenv-action@v1.0.4
|
||||
with:
|
||||
path: '.env.${{ needs.console-test-branch.outputs.console-branch }}'
|
||||
path: './console-test/.env.${{ inputs.console-test-branch }}'
|
||||
export-variables: true
|
||||
keys-case: upper
|
||||
log-variables: true
|
||||
|
||||
#----------------------------------------------
|
||||
# ----- Setup python -----
|
||||
#----------------------------------------------
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.10'
|
||||
#----------------------------------------------
|
||||
# ----- install & configure poetry -----
|
||||
#----------------------------------------------
|
||||
- name: Install Poetry
|
||||
uses: snok/install-poetry@v1
|
||||
with:
|
||||
virtualenvs-create: true
|
||||
virtualenvs-in-project: true
|
||||
virtualenvs-path: .venv
|
||||
|
||||
#----------------------------------------------
|
||||
# install python dependencies
|
||||
# install dependencies
|
||||
#----------------------------------------------
|
||||
- name: Install dependencies
|
||||
working-directory: ./console-test
|
||||
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
|
||||
working-directory: ./console-test
|
||||
run: poetry run python -m vega_sim.tools.load_binaries --force --version ${{ env.VEGA_VERSION }}
|
||||
#----------------------------------------------
|
||||
# install playwright
|
||||
#----------------------------------------------
|
||||
- name: install playwright
|
||||
run: poetry run playwright install --with-deps chromium
|
||||
working-directory: ./console-test
|
||||
#----------------------------------------------
|
||||
# run tests
|
||||
#----------------------------------------------
|
||||
- name: Run tests
|
||||
run: CONSOLE_IMAGE_NAME=ci/trading:local poetry run pytest -v -s --numprocesses 4 --dist loadfile --durations=15
|
||||
|
||||
working-directory: ./console-test
|
||||
run: poetry run pytest -v -s --numprocesses 4 --dist loadfile --durations=15
|
||||
- name: Check files
|
||||
run: |
|
||||
ls -al .
|
||||
ls -al console-test
|
||||
#----------------------------------------------
|
||||
# upload traces
|
||||
#----------------------------------------------
|
||||
|
||||
@@ -21,11 +21,11 @@ jobs:
|
||||
- name: Check branch
|
||||
id: step
|
||||
run: |
|
||||
if [[ "${{ github.base_ref }}" == "main" ]]; then
|
||||
if [ ${{ github.base_ref }} == 'main' ]; then
|
||||
echo "runner=mainnet-compatible-runner" >> $GITHUB_OUTPUT
|
||||
elif [[ "${{ github.base_ref }}" == "develop" && "${{ github.ref_name }}" == "main" ]]; then
|
||||
elif [ ${{ github.base_ref }} == 'develop' ] && [ ${{ github.ref_name }} == 'main' ]; then
|
||||
echo "runner=mainnet-compatible-runner" >> $GITHUB_OUTPUT
|
||||
elif [[ "${{ github.event_name }}" == "push" && "${{ github.ref_name }}" == *"release/mainnet"* ]]; then
|
||||
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
|
||||
@@ -85,7 +85,6 @@ jobs:
|
||||
- name: Run Vegacapsule network and Vega wallet
|
||||
id: setup-vega
|
||||
uses: ./frontend-monorepo/.github/actions/run-vegacapsule
|
||||
timeout-minutes: 10
|
||||
|
||||
######
|
||||
## Run some tests
|
||||
|
||||
@@ -63,7 +63,7 @@ jobs:
|
||||
echo IS_IPFS_RELEASE=true >> $GITHUB_ENV
|
||||
|
||||
- name: Is S3 Release
|
||||
if: ${{ env.IS_IPFS_RELEASE == 'false' && github.event_name == 'push' && github.ref_name != 'main'}}
|
||||
if: ${{ env.IS_IPFS_RELEASE == 'false' && github.event_name == 'push' }}
|
||||
run: |
|
||||
echo IS_S3_RELEASE=true >> $GITHUB_ENV
|
||||
|
||||
@@ -195,7 +195,7 @@ jobs:
|
||||
ENV_NAME=${{ env.ENV_NAME }}
|
||||
tags: |
|
||||
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' || env.IS_MAIN_IMAGE == 'true' && 'main' || '' }}
|
||||
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)
|
||||
uses: docker/build-push-action@v3
|
||||
@@ -222,7 +222,7 @@ jobs:
|
||||
ENV_NAME=${{ env.ENV_NAME }}
|
||||
tags: |
|
||||
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' || env.IS_MAIN_IMAGE == 'true' && 'main' || '' }}
|
||||
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
|
||||
- name: Publish dist to s3
|
||||
|
||||
@@ -36,7 +36,7 @@ context('Market page', { tags: '@regression' }, function () {
|
||||
|
||||
it('Able to go to market details page', function () {
|
||||
cy.navigate_to('markets');
|
||||
cy.contains('Test market 1').click();
|
||||
cy.get_element_by_col_id('actions').eq(1).click();
|
||||
cy.getByTestId(marketHeaders).should('have.text', 'Test market 1');
|
||||
cy.validate_element_from_table('Name', 'Test market 1');
|
||||
cy.validate_element_from_table('Market ID', this.createdMarketId);
|
||||
@@ -90,7 +90,7 @@ context('Market page', { tags: '@regression' }, function () {
|
||||
// Liquidity price range
|
||||
cy.validate_element_from_table(
|
||||
'Liquidity Price Range',
|
||||
'95.00% of mid price'
|
||||
'1,000.00% of mid price'
|
||||
);
|
||||
cy.validate_element_from_table('Lowest Price', '0.00 fUSDC');
|
||||
cy.validate_element_from_table('Highest Price', '0.00 fUSDC');
|
||||
|
||||
@@ -40,7 +40,7 @@ context.skip('Node switcher', { tags: '@regression' }, function () {
|
||||
const errorTypeTxt = 'Error: invalid url';
|
||||
const nodeErrorTxt = 'fakeUrl is not a valid url.';
|
||||
|
||||
cy.getByTestId('node-url-custom').click({ force: true });
|
||||
cy.getByTestId('node-url-custom').click();
|
||||
|
||||
cy.getByTestId(customNodeBtn).within(() => {
|
||||
cy.get('input').clear().type('fakeUrl');
|
||||
|
||||
@@ -3,7 +3,6 @@ import type { MarketInfoWithData } from '@vegaprotocol/markets';
|
||||
import {
|
||||
LiquidityPriceRangeInfoPanel,
|
||||
LiquiditySLAParametersInfoPanel,
|
||||
MarginScalingFactorsPanel,
|
||||
PriceMonitoringBoundsInfoPanel,
|
||||
SuccessionLineInfoPanel,
|
||||
getDataSourceSpecForSettlementData,
|
||||
@@ -18,6 +17,7 @@ import {
|
||||
OracleInfoPanel,
|
||||
RiskFactorsInfoPanel,
|
||||
RiskModelInfoPanel,
|
||||
RiskParametersInfoPanel,
|
||||
SettlementAssetInfoPanel,
|
||||
} from '@vegaprotocol/markets';
|
||||
import { MarketInfoTable } from '@vegaprotocol/markets';
|
||||
@@ -69,8 +69,8 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
|
||||
<MetadataInfoPanel market={market} />
|
||||
<h2 className={headerClassName}>{t('Risk model')}</h2>
|
||||
<RiskModelInfoPanel market={market} />
|
||||
<h2 className={headerClassName}>{t('Margin scaling factors')}</h2>
|
||||
<MarginScalingFactorsPanel market={market} />
|
||||
<h2 className={headerClassName}>{t('Risk parameters')}</h2>
|
||||
<RiskParametersInfoPanel market={market} />
|
||||
<h2 className={headerClassName}>{t('Risk factors')}</h2>
|
||||
<RiskFactorsInfoPanel market={market} />
|
||||
{(market.data?.priceMonitoringBounds || []).map((trigger, i) => (
|
||||
|
||||
@@ -8,9 +8,7 @@ import { useScrollToLocation } from '../../../hooks/scroll-to-location';
|
||||
import filter from 'recursive-key-filter';
|
||||
|
||||
const Oracles = () => {
|
||||
const { data, loading, error } = useExplorerOracleSpecsQuery({
|
||||
errorPolicy: 'ignore',
|
||||
});
|
||||
const { data, loading, error } = useExplorerOracleSpecsQuery();
|
||||
|
||||
useDocumentTitle(['Oracles']);
|
||||
useScrollToLocation();
|
||||
|
||||
@@ -22,11 +22,7 @@ NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||
NX_VEGA_REST_URL=http://localhost:3008/api/v2/
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
NX_PRODUCT_PERPETUALS=true
|
||||
NX_REFERRALS=true
|
||||
NX_UPDATE_MARKET_STATE=true
|
||||
NX_GOVERNANCE_TRANSFERS=true
|
||||
NX_VOLUME_DISCOUNTS=true
|
||||
|
||||
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||
|
||||
@@ -6,5 +6,3 @@ 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
|
||||
NX_REFERRALS=true
|
||||
NX_VOLUME_DISCOUNTS=true
|
||||
|
||||
@@ -6,5 +6,3 @@ 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
|
||||
NX_REFERRALS=false
|
||||
NX_VOLUME_DISCOUNTS=false
|
||||
|
||||
@@ -6,5 +6,3 @@ 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
|
||||
NX_REFERRALS=true
|
||||
NX_VOLUME_DISCOUNTS=true
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"rationale": {
|
||||
"title": "Governance cancel transfer proposal",
|
||||
"description": "Rejected cancel transfer proposal"
|
||||
},
|
||||
"terms": {
|
||||
"cancelTransfer": {
|
||||
"changes": {
|
||||
"transferId": "invalid transfer id"
|
||||
}
|
||||
},
|
||||
"closingTimestamp": 0,
|
||||
"enactmentTimestamp": 0
|
||||
}
|
||||
}
|
||||
@@ -27,16 +27,12 @@ import {
|
||||
} from '../../../../governance-e2e/src/support/staking.functions';
|
||||
import { ethereumWalletConnect } from '../../../../governance-e2e/src/support/wallet-eth.functions';
|
||||
import {
|
||||
depositAsset,
|
||||
switchVegaWalletPubKey,
|
||||
vegaWalletSetSpecifiedApprovalAmount,
|
||||
} from '../../support/wallet-functions';
|
||||
import type { testFreeformProposal } from '../../support/common-interfaces';
|
||||
import { formatDateWithLocalTimezone } from '@vegaprotocol/utils';
|
||||
import {
|
||||
createGovernanceTransferProposalTxBody,
|
||||
createSuccessorMarketProposalTxBody,
|
||||
} from '../../support/proposal.functions';
|
||||
import { createSuccessorMarketProposalTxBody } from '../../support/proposal.functions';
|
||||
|
||||
const proposalListItem = '[data-testid="proposals-list-item"]';
|
||||
const participationNotMet = 'token-participation-not-met';
|
||||
@@ -55,7 +51,6 @@ const openProposals = 'open-proposals';
|
||||
const viewProposalButton = 'view-proposal-btn';
|
||||
const proposalTermsToggle = 'proposal-json-toggle';
|
||||
const marketDataToggle = 'proposal-market-data-toggle';
|
||||
const governanceTransferToggle = 'proposal-transfer-details';
|
||||
const marketProposalType = 'proposal-type';
|
||||
|
||||
describe(
|
||||
@@ -438,10 +433,9 @@ describe(
|
||||
'contain.text',
|
||||
'0.3'
|
||||
);
|
||||
getProposalDetailsValue('Min Probability Of Trading LP Orders').should(
|
||||
'contain.text',
|
||||
'1e-8'
|
||||
);
|
||||
getProposalDetailsValue(
|
||||
'Minimum Probability Of Trading LP Orders'
|
||||
).should('contain.text', '1e-8');
|
||||
});
|
||||
|
||||
it('Able to see suspended market proposal', function () {
|
||||
@@ -525,78 +519,5 @@ describe(
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('Able to see governance transfer proposal', function () {
|
||||
const vegaAssetAddress = '0x67175Da1D5e966e40D11c4B2519392B2058373de';
|
||||
depositAsset(vegaAssetAddress, '1000', 18);
|
||||
cy.getByTestId('currency-title', Cypress.env('txTimeout')).should(
|
||||
'contain.text',
|
||||
'Collateral'
|
||||
);
|
||||
cy.VegaWalletTopUpNetworkAccount('100');
|
||||
cy.VegaWalletSubmitProposal(createGovernanceTransferProposalTxBody());
|
||||
cy.reload();
|
||||
getProposalFromTitle('Governance transfer proposal').within(() => {
|
||||
cy.getByTestId(marketProposalType).should('have.text', 'NewTransfer');
|
||||
cy.getByTestId(viewProposalButton).click();
|
||||
});
|
||||
cy.getByTestId(marketProposalType).should('have.text', 'NewTransfer');
|
||||
cy.getByTestId(governanceTransferToggle).click();
|
||||
cy.getByTestId('proposal-transfer-details-table').within(() => {
|
||||
getProposalInformationFromTable('Source Type')
|
||||
.invoke('text')
|
||||
.and('eq', 'Network Treasury');
|
||||
getProposalInformationFromTable('Destination')
|
||||
.invoke('text')
|
||||
.and('eq', Cypress.env('vegaWalletPublicKey'));
|
||||
getProposalInformationFromTable('Asset')
|
||||
.invoke('text')
|
||||
.and('eq', 'VEGA');
|
||||
getProposalInformationFromTable('Fraction Of Balance')
|
||||
.invoke('text')
|
||||
.and('eq', '50%');
|
||||
getProposalInformationFromTable('Amount')
|
||||
.invoke('text')
|
||||
.and('eq', '100.00');
|
||||
getProposalInformationFromTable('Transfer Type')
|
||||
.invoke('text')
|
||||
.and('eq', 'All or nothing');
|
||||
getProposalInformationFromTable('Kind')
|
||||
.invoke('text')
|
||||
.and('eq', 'One off');
|
||||
});
|
||||
});
|
||||
|
||||
it(' Able to see cancel transfer proposal - rejected', function () {
|
||||
const proposalPath = 'src/fixtures/proposals/cancel-transfer-raw.json';
|
||||
const enactmentTimestamp =
|
||||
createTenDigitUnixTimeStampForSpecifiedDays(11);
|
||||
const closingTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(10);
|
||||
submitUniqueRawProposal({
|
||||
proposalBody: proposalPath,
|
||||
enactmentTimestamp: enactmentTimestamp,
|
||||
closingTimestamp: closingTimestamp,
|
||||
submit: false,
|
||||
});
|
||||
cy.getByTestId('proposal-submit').should('be.visible').click();
|
||||
cy.getByTestId('dialog-title').should('have.text', 'Proposal rejected');
|
||||
cy.getByTestId('icon-cross').last().click();
|
||||
navigateTo(navigation.proposals);
|
||||
cy.get('[href="/proposals/rejected"]').click();
|
||||
getProposalFromTitle('Governance cancel transfer proposal').within(() => {
|
||||
cy.getByTestId(marketProposalType).should(
|
||||
'have.text',
|
||||
'CancelTransfer'
|
||||
);
|
||||
cy.getByTestId(viewProposalButton).click();
|
||||
});
|
||||
cy.getByTestId(marketProposalType).should('have.text', 'CancelTransfer');
|
||||
getProposalInformationFromTable('Error details')
|
||||
.invoke('text')
|
||||
.and('eq', 'Governance transfer invalid transfer id not found');
|
||||
getProposalInformationFromTable('transferId')
|
||||
.invoke('text')
|
||||
.and('eq', 'invalid transfer id');
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
@@ -310,9 +310,7 @@ context(
|
||||
closeStakingDialog();
|
||||
navigateTo(navigation.validators);
|
||||
clickOnValidatorFromList(0);
|
||||
cy.getByTestId(stakeRemoveStakeRadioButton, txTimeout).click({
|
||||
force: true,
|
||||
});
|
||||
cy.getByTestId(stakeRemoveStakeRadioButton, txTimeout).click();
|
||||
cy.getByTestId(stakeTokenAmountInputBox).type('-0.1');
|
||||
cy.contains('Waiting for next epoch to start', epochTimeout);
|
||||
cy.getByTestId(stakeTokenSubmitButton)
|
||||
@@ -333,7 +331,7 @@ context(
|
||||
closeStakingDialog();
|
||||
navigateTo(navigation.validators);
|
||||
clickOnValidatorFromList(0);
|
||||
cy.getByTestId(stakeRemoveStakeRadioButton).click({ force: true });
|
||||
cy.getByTestId(stakeRemoveStakeRadioButton).click();
|
||||
cy.getByTestId(stakeTokenAmountInputBox).type('4');
|
||||
cy.contains('Waiting for next epoch to start', epochTimeout);
|
||||
cy.getByTestId(stakeTokenSubmitButton)
|
||||
@@ -424,7 +422,7 @@ context(
|
||||
validateValidatorListTotalStakeAndShare('0', '3,002.00', '50.02%');
|
||||
});
|
||||
|
||||
it.skip('Associating wallet tokens - when some already staked - auto stakes tokens to staked validator', function () {
|
||||
it('Associating wallet tokens - when some already staked - auto stakes tokens to staked validator', function () {
|
||||
// 1002-STKE-004
|
||||
stakingPageAssociateTokens('3');
|
||||
verifyUnstakedBalance(3.0);
|
||||
@@ -438,7 +436,7 @@ context(
|
||||
verifyStakedBalance(7.0);
|
||||
});
|
||||
|
||||
it.skip('Associating vesting contract tokens - when some already staked - auto stakes tokens to staked validator', function () {
|
||||
it('Associating vesting contract tokens - when some already staked - auto stakes tokens to staked validator', function () {
|
||||
// 1002-STKE-004
|
||||
stakingPageAssociateTokens('3', { type: 'contract' });
|
||||
verifyUnstakedBalance(3.0);
|
||||
@@ -452,7 +450,7 @@ context(
|
||||
verifyStakedBalance(7.0);
|
||||
});
|
||||
|
||||
it.skip('Associating vesting contract tokens - when wallet tokens already staked - auto stakes tokens to staked validator', function () {
|
||||
it('Associating vesting contract tokens - when wallet tokens already staked - auto stakes tokens to staked validator', function () {
|
||||
// 1002-STKE-004
|
||||
stakingPageAssociateTokens('3', { type: 'wallet' });
|
||||
verifyUnstakedBalance(3.0);
|
||||
@@ -466,7 +464,7 @@ context(
|
||||
verifyStakedBalance(7.0);
|
||||
});
|
||||
|
||||
it.skip('Associating tokens - with multiple validators already staked - auto stakes to staked validators - abiding by existing stake ratio', function () {
|
||||
it('Associating tokens - with multiple validators already staked - auto stakes to staked validators - abiding by existing stake ratio', function () {
|
||||
// 1002-STKE-004
|
||||
stakingPageAssociateTokens('6');
|
||||
verifyUnstakedBalance(6.0);
|
||||
|
||||
@@ -156,7 +156,7 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
|
||||
cy.getByTestId('subscription-cell').should('have.text', 'Yes');
|
||||
});
|
||||
cy.getByTestId('connect').should('be.disabled');
|
||||
cy.getByTestId('node-url-custom').click({ force: true });
|
||||
cy.getByTestId('node-url-custom').click();
|
||||
cy.get('input').should('exist');
|
||||
cy.getByTestId('connect').should('be.disabled');
|
||||
cy.getByTestId('icon-cross').click();
|
||||
|
||||
@@ -74,12 +74,25 @@ context(
|
||||
});
|
||||
|
||||
it('should be able to see a working link for - find out more about Vega governance', function () {
|
||||
// 3001-VOTE-001 // 3002-PROP-001
|
||||
// 3001-VOTE-001
|
||||
cy.getByTestId(proposalDocumentationLink)
|
||||
.should('be.visible')
|
||||
.and('have.text', 'Find out more about Vega governance')
|
||||
.and('have.attr', 'href')
|
||||
.and('equal', governanceDocsUrl);
|
||||
|
||||
// 3002-PROP-001
|
||||
cy.request(governanceDocsUrl)
|
||||
.its('body')
|
||||
.then((body) => {
|
||||
if (!body.includes('Govern the network')) {
|
||||
assert.include(
|
||||
body,
|
||||
'Govern the network',
|
||||
`Checking that governance link destination includes 'Govern the network' text`
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 3007-PNE-021
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
waitForBeginningOfEpoch,
|
||||
} from '../../support/staking.functions';
|
||||
import { previousEpochData } from '../../fixtures/mocks/previous-epoch';
|
||||
import { chainIdQuery, statisticsQuery } from '@vegaprotocol/mock';
|
||||
|
||||
const guideLink = 'staking-guide-link';
|
||||
const validatorTitle = 'validator-node-title';
|
||||
@@ -37,11 +38,17 @@ const txTimeout = Cypress.env('txTimeout');
|
||||
|
||||
context('Validators Page - verify elements on page', function () {
|
||||
before('navigate to validators page', () => {
|
||||
cy.mockChainId();
|
||||
cy.mockGQL((req) => {
|
||||
aliasGQLQuery(req, 'ChainId', chainIdQuery());
|
||||
aliasGQLQuery(req, 'Statistics', statisticsQuery());
|
||||
});
|
||||
cy.visit('/validators');
|
||||
});
|
||||
beforeEach(() => {
|
||||
cy.mockChainId();
|
||||
cy.mockGQL((req) => {
|
||||
aliasGQLQuery(req, 'ChainId', chainIdQuery());
|
||||
aliasGQLQuery(req, 'Statistics', statisticsQuery());
|
||||
});
|
||||
});
|
||||
|
||||
describe('with wallets disconnected', { tags: '@smoke' }, function () {
|
||||
@@ -182,7 +189,10 @@ context('Validators Page - verify elements on page', function () {
|
||||
{ tags: '@smoke' },
|
||||
function () {
|
||||
before('connect wallets and click on validator', function () {
|
||||
cy.mockChainId();
|
||||
cy.mockGQL((req) => {
|
||||
aliasGQLQuery(req, 'ChainId', chainIdQuery());
|
||||
aliasGQLQuery(req, 'Statistics', statisticsQuery());
|
||||
});
|
||||
cy.visit('/validators');
|
||||
cy.connectVegaWallet();
|
||||
clickOnValidatorFromList(0);
|
||||
|
||||
@@ -4,6 +4,8 @@ import {
|
||||
vegaWalletFaucetAssetsWithoutCheck,
|
||||
vegaWalletTeardown,
|
||||
} from '../../support/wallet-functions';
|
||||
import { aliasGQLQuery } from '@vegaprotocol/cypress';
|
||||
import { chainIdQuery, statisticsQuery } from '@vegaprotocol/mock';
|
||||
|
||||
const walletContainer = 'aside [data-testid="vega-wallet"]';
|
||||
const walletHeader = '[data-testid="wallet-header"] h1';
|
||||
@@ -86,7 +88,10 @@ context(
|
||||
|
||||
describe('when vega wallet connected', function () {
|
||||
before('connect vega wallet', function () {
|
||||
cy.mockChainId();
|
||||
cy.mockGQL((req) => {
|
||||
aliasGQLQuery(req, 'ChainId', chainIdQuery());
|
||||
aliasGQLQuery(req, 'Statistics', statisticsQuery());
|
||||
});
|
||||
cy.visit('/');
|
||||
cy.wait('@ChainId');
|
||||
cy.connectVegaWallet();
|
||||
@@ -271,7 +276,10 @@ context(
|
||||
];
|
||||
|
||||
before('faucet assets to connected vega wallet', function () {
|
||||
cy.mockChainId();
|
||||
cy.mockGQL((req) => {
|
||||
aliasGQLQuery(req, 'ChainId', chainIdQuery());
|
||||
aliasGQLQuery(req, 'Statistics', statisticsQuery());
|
||||
});
|
||||
for (const { id, amount } of assets) {
|
||||
vegaWalletFaucetAssetsWithoutCheck(id, amount, vegaWalletPublicKey);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ import './wallet-functions.ts';
|
||||
import './proposal.functions.ts';
|
||||
import 'cypress-mochawesome-reporter/register';
|
||||
import registerCypressGrep from '@cypress/grep';
|
||||
import { aliasGQLQuery } from '@vegaprotocol/cypress';
|
||||
import { chainIdQuery, statisticsQuery } from '@vegaprotocol/mock';
|
||||
import { turnTelemetryOff } from './common.functions.ts';
|
||||
registerCypressGrep();
|
||||
|
||||
@@ -27,7 +29,10 @@ before(() => {
|
||||
// // Ensuring the telemetry modal doesn't disrupt the tests
|
||||
turnTelemetryOff();
|
||||
// Mock chainId fetch which happens on every page for wallet connection
|
||||
cy.mockChainId();
|
||||
cy.mockGQL((req) => {
|
||||
aliasGQLQuery(req, 'ChainId', chainIdQuery());
|
||||
aliasGQLQuery(req, 'Statistics', statisticsQuery());
|
||||
});
|
||||
// Self stake validators so they are displayed
|
||||
cy.validatorsSelfDelegate();
|
||||
});
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { addDays, addSeconds, millisecondsToSeconds } from 'date-fns';
|
||||
import { addSeconds, millisecondsToSeconds } from 'date-fns';
|
||||
import type { ProposalSubmissionBody } from '@vegaprotocol/wallet';
|
||||
import { aliasGQLQuery } from '@vegaprotocol/cypress';
|
||||
import { upgradeProposalsData } from '../fixtures/mocks/network-upgrade';
|
||||
import { proposalsData } from '../fixtures/mocks/proposals';
|
||||
import { nodeData } from '../fixtures/mocks/nodes';
|
||||
import { AccountType, GovernanceTransferType } from '@vegaprotocol/types';
|
||||
|
||||
export function createUpdateNetworkProposalTxBody(): ProposalSubmissionBody {
|
||||
const MIN_CLOSE_SEC = 5;
|
||||
@@ -359,46 +358,6 @@ export function createSuccessorMarketProposalTxBody(
|
||||
};
|
||||
}
|
||||
|
||||
export function createGovernanceTransferProposalTxBody(): ProposalSubmissionBody {
|
||||
const MIN_CLOSE_SEC = 5;
|
||||
const MIN_ENACT_SEC = 7;
|
||||
|
||||
const closingDate = addDays(new Date(), MIN_CLOSE_SEC);
|
||||
const enactmentDate = addDays(closingDate, MIN_ENACT_SEC);
|
||||
const closingTimestamp = millisecondsToSeconds(closingDate.getTime());
|
||||
const enactmentTimestamp = millisecondsToSeconds(enactmentDate.getTime());
|
||||
const destination = Cypress.env('vegaWalletPublicKey');
|
||||
return {
|
||||
proposalSubmission: {
|
||||
rationale: {
|
||||
title: 'Governance transfer proposal',
|
||||
description: 'E2E test for transfer proposal test',
|
||||
},
|
||||
terms: {
|
||||
newTransfer: {
|
||||
changes: {
|
||||
fractionOfBalance: '0.5',
|
||||
amount: '100' + '0'.repeat(18),
|
||||
sourceType: AccountType.ACCOUNT_TYPE_NETWORK_TREASURY,
|
||||
source: '',
|
||||
transferType:
|
||||
GovernanceTransferType.GOVERNANCE_TRANSFER_TYPE_ALL_OR_NOTHING,
|
||||
destinationType: AccountType.ACCOUNT_TYPE_GENERAL,
|
||||
destination,
|
||||
asset:
|
||||
'b4f2726571fbe8e33b442dc92ed2d7f0d810e21835b7371a7915a365f07ccd9b',
|
||||
oneOff: {
|
||||
deliverOn: '0',
|
||||
},
|
||||
},
|
||||
},
|
||||
closingTimestamp,
|
||||
enactmentTimestamp,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function mockNetworkUpgradeProposal() {
|
||||
cy.mockGQL((req) => {
|
||||
aliasGQLQuery(req, 'Nodes', nodeData);
|
||||
|
||||
@@ -46,7 +46,7 @@ export function stakingValidatorPageAddStake(stake: string) {
|
||||
|
||||
export function stakingValidatorPageRemoveStake(stake: string) {
|
||||
cy.highlight(`Removing a stake of ${stake}`);
|
||||
cy.get(removeStakeRadioButton, epochTimeout).click({ force: true });
|
||||
cy.get(removeStakeRadioButton, epochTimeout).click();
|
||||
cy.get(tokenAmountInputBox).type(stake);
|
||||
waitForBeginningOfEpoch();
|
||||
cy.get(tokenSubmitButton)
|
||||
@@ -70,13 +70,9 @@ export function stakingPageAssociateTokens(
|
||||
cy.highlight(`Associating ${amount} tokens from ${type}`);
|
||||
cy.get(ethWalletAssociateButton).first().click();
|
||||
if (type === 'wallet') {
|
||||
cy.get(associateWalletRadioButton, { timeout: 30000 }).click({
|
||||
force: true,
|
||||
});
|
||||
cy.get(associateWalletRadioButton, { timeout: 30000 }).click();
|
||||
} else if (type === 'contract') {
|
||||
cy.get(associateContractRadioButton, { timeout: 30000 }).click({
|
||||
force: true,
|
||||
});
|
||||
cy.get(associateContractRadioButton, { timeout: 30000 }).click();
|
||||
} else {
|
||||
cy.highlight(`${type} is not association option`);
|
||||
}
|
||||
|
||||
@@ -41,9 +41,6 @@ export async function depositAsset(
|
||||
) {
|
||||
// Approve asset
|
||||
const faucet = new Token(assetEthAddress, signer);
|
||||
// Wait needed to allow Eth chain to catch up
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(4000);
|
||||
cy.wrap(
|
||||
faucet.approve(Erc20BridgeAddress, amount + '0'.repeat(decimalPlaces + 1)),
|
||||
transactionTimeout
|
||||
|
||||
@@ -8,7 +8,6 @@ NX_FAIRGROUND=false
|
||||
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","STAGNET1":"https://governance.stagnet1.vega.rocks","TESTNET":"https://governance.fairground.wtf","MAINNET":"https://governance.vega.xyz"}'
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_VEGA_WALLET_URL=http://localhost:1789
|
||||
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.stagnet1.vega.rocks
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
|
||||
@@ -35,6 +34,3 @@ NX_SUCCESSOR_MARKETS=true
|
||||
NX_METAMASK_SNAPS=true
|
||||
NX_PRODUCT_PERPETUALS=false
|
||||
NX_UPDATE_MARKET_STATE=false
|
||||
NX_REFERRALS=false
|
||||
NX_GOVERNANCE_TRANSFERS=false
|
||||
NX_VOLUME_DISCOUNTS=false
|
||||
|
||||
@@ -35,5 +35,3 @@ NX_SUCCESSOR_MARKETS=false
|
||||
NX_METAMASK_SNAPS=false
|
||||
NX_PRODUCT_PERPETUALS=true
|
||||
NX_UPDATE_MARKET_STATE=true
|
||||
NX_REFERRALS=true
|
||||
NX_VOLUME_DISCOUNTS=true
|
||||
|
||||
@@ -27,5 +27,3 @@ NX_SUCCESSOR_MARKETS=true
|
||||
NX_METAMASK_SNAPS=true
|
||||
NX_PRODUCT_PERPETUALS=true
|
||||
NX_UPDATE_MARKET_STATE=true
|
||||
NX_REFERRALS=true
|
||||
NX_VOLUME_DISCOUNTS=true
|
||||
|
||||
@@ -17,7 +17,7 @@ NX_VEGA_REST_URL=https://api.vega.community/api/v2/
|
||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-mainnet
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||
|
||||
NX_TENDERMINT_URL=https://be.vega.community
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket
|
||||
|
||||
@@ -26,5 +26,3 @@ NX_SUCCESSOR_MARKETS=false
|
||||
NX_METAMASK_SNAPS=false
|
||||
NX_PRODUCT_PERPETUALS=false
|
||||
NX_UPDATE_MARKET_STATE=false
|
||||
NX_REFERRALS=false
|
||||
NX_VOLUME_DISCOUNTS=false
|
||||
|
||||
@@ -25,5 +25,3 @@ NX_SUCCESSOR_MARKETS=false
|
||||
NX_METAMASK_SNAPS=false
|
||||
NX_PRODUCT_PERPETUALS=false
|
||||
NX_UPDATE_MARKET_STATE=false
|
||||
NX_REFERRALS=false
|
||||
NX_VOLUME_DISCOUNTS=false
|
||||
|
||||
@@ -10,7 +10,6 @@ NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
|
||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||
NX_VEGA_REST_URL=https://api.n00.stagnet1.vega.xyz/api/v2/
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||
|
||||
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
|
||||
@@ -23,6 +22,3 @@ NX_SUCCESSOR_MARKETS=true
|
||||
NX_METAMASK_SNAPS=true
|
||||
NX_PRODUCT_PERPETUALS=true
|
||||
NX_UPDATE_MARKET_STATE=true
|
||||
NX_REFERRALS=true
|
||||
NX_GOVERNANCE_TRANSFERS=true
|
||||
NX_VOLUME_DISCOUNTS=true
|
||||
|
||||
@@ -15,7 +15,6 @@ NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/annou
|
||||
NX_VEGA_REST_URL=https://api.n07.testnet.vega.xyz/api/v2/
|
||||
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_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||
|
||||
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
|
||||
@@ -28,5 +27,3 @@ NX_SUCCESSOR_MARKETS=true
|
||||
NX_METAMASK_SNAPS=true
|
||||
NX_PRODUCT_PERPETUALS=true
|
||||
NX_UPDATE_MARKET_STATE=true
|
||||
NX_REFERRALS=true
|
||||
NX_VOLUME_DISCOUNTS=true
|
||||
|
||||
@@ -24,5 +24,3 @@ NX_SUCCESSOR_MARKETS=false
|
||||
NX_METAMASK_SNAPS=false
|
||||
NX_PRODUCT_PERPETUALS=false
|
||||
NX_UPDATE_MARKET_STATE=false
|
||||
NX_REFERRALS=false
|
||||
NX_VOLUME_DISCOUNTS=false
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
/* eslint-disable */
|
||||
process.env.TZ = 'GMT';
|
||||
export default {
|
||||
displayName: 'governance',
|
||||
preset: '../../jest.preset.js',
|
||||
|
||||
@@ -26,11 +26,11 @@ import {
|
||||
} from '@vegaprotocol/web3';
|
||||
import { Web3Provider } from '@vegaprotocol/web3';
|
||||
import { VegaWalletDialogs } from './components/vega-wallet-dialogs';
|
||||
import { VegaWalletProvider } from '@vegaprotocol/wallet';
|
||||
import {
|
||||
useVegaTransactionManager,
|
||||
useVegaTransactionUpdater,
|
||||
} from '@vegaprotocol/web3';
|
||||
VegaWalletProvider,
|
||||
} from '@vegaprotocol/wallet';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import { useEthereumConfig } from '@vegaprotocol/web3';
|
||||
import {
|
||||
|
||||
@@ -709,8 +709,6 @@
|
||||
"NewMarketProposal": "New market proposal",
|
||||
"UpdateMarketProposal": "Update market proposal",
|
||||
"UpdateMarketStateProposal": "Update market state proposal",
|
||||
"UpdateReferralProgramProposal": "Update referral program proposal",
|
||||
"UpdateVolumeDiscountProgramProposal": "Update volume discount program proposal",
|
||||
"MarketChange": "Market change",
|
||||
"MarketStateChange": "Market state change",
|
||||
"MarketDetails": "Market details",
|
||||
@@ -734,8 +732,6 @@
|
||||
"NewMarketSpotProduct": "New market - spot",
|
||||
"UpdateMarket": "Update market",
|
||||
"UpdateMarketState": "Update market state",
|
||||
"UpdateReferralProgram": "Update referral program",
|
||||
"UpdateVolumeDiscountProgram": "Update volume discount program",
|
||||
"NewAsset": "New asset",
|
||||
"UpdateAsset": "Update asset",
|
||||
"AssetID": "Asset ID",
|
||||
@@ -892,27 +888,5 @@
|
||||
"HowToPropose": "How to make a proposal",
|
||||
"HowToProposeRawStep1": "1. Sense check your proposal with the community on the forum:",
|
||||
"HowToProposeRawStep2": "2. Use the appropriate proposal template in the docs:",
|
||||
"HowToProposeRawStep3": "3. Submit on-chain below",
|
||||
"proposalTransferDetails": "New governance transfer details",
|
||||
"proposalCancelTransferDetails": "Cancel governance transfer details",
|
||||
"BenefitTiers": "Benefit tiers",
|
||||
"BenefitTierMinimumEpochs": "Minimum epochs",
|
||||
"BenefitTierMinimumEpochsDescription": "The minimum number of epochs the party needs to be in the referral set to be eligible for the benefit",
|
||||
"BenefitTierMinimumRunningNotionalTakerVolume": "Minimum running notional taker volume",
|
||||
"BenefitTierMinimumRunningNotionalTakerVolumeDescription": "The minimum running notional for the given benefit tier",
|
||||
"BenefitTierReferralDiscountFactor": "Referral discount factor",
|
||||
"BenefitTierReferralDiscountFactorDescription": "The proportion of the referee's taker fees to be discounted",
|
||||
"BenefitTierReferralRewardFactor": "Referral reward factor",
|
||||
"BenefitTierReferralRewardFactorDescription": "The proportion of the referee's taker fees to be rewarded to the referrer",
|
||||
"StakingTiers": "Staking tiers",
|
||||
"StakingTierMinimumStakedTokens": "Minimum staked tokens",
|
||||
"StakingTierMinimumStakedTokensDescription": "Required number of governance tokens ($VEGA) a referrer must have staked to receive the multiplier",
|
||||
"StakingTierReferralRewardMultiplier": "Referral reward multiplier",
|
||||
"StakingTierReferralRewardMultiplierDescription": "Multiplier applied to the referral reward factor when calculating referral rewards due to the referrer",
|
||||
"WindowLength": "Window length",
|
||||
"WindowLengthDescription": "Number of epochs over which to evaluate a referral set's running volume",
|
||||
"EndOfProgramTimestamp": "End of program",
|
||||
"EndOfProgramTimestampDescription": "Time after which when the current epoch ends, the programs will end and benefits will be disabled.",
|
||||
"BenefitTierVolumeDiscountFactor": "Volume discount factor",
|
||||
"BenefitTierVolumeDiscountFactorDescription": "Discount given to those in this benefit tier"
|
||||
"HowToProposeRawStep3": "3. Submit on-chain below"
|
||||
}
|
||||
|
||||
@@ -188,8 +188,6 @@ const GovernanceHome = ({ name }: RouteChildProps) => {
|
||||
variables: {
|
||||
includeNewMarketProductFields: !!FLAGS.PRODUCT_PERPETUALS,
|
||||
includeUpdateMarketStates: !!FLAGS.UPDATE_MARKET_STATE,
|
||||
includeUpdateReferralPrograms: !!FLAGS.REFERRALS,
|
||||
includeUpdateVolumeDiscountPrograms: !!FLAGS.VOLUME_DISCOUNTS,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
+1
-63
@@ -7,17 +7,12 @@ import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
|
||||
import { truncateMiddle } from '../../../../lib/truncate-middle';
|
||||
import { CurrentProposalState } from '../current-proposal-state';
|
||||
import { ProposalInfoLabel } from '../proposal-info-label';
|
||||
import {
|
||||
useCancelTransferProposalDetails,
|
||||
useNewTransferProposalDetails,
|
||||
useSuccessorMarketProposalDetails,
|
||||
} from '@vegaprotocol/proposals';
|
||||
import { useSuccessorMarketProposalDetails } from '@vegaprotocol/proposals';
|
||||
import { FLAGS } from '@vegaprotocol/environment';
|
||||
import Routes from '../../../routes';
|
||||
import { Link } from 'react-router-dom';
|
||||
import type { VoteState } from '../vote-details/use-user-vote';
|
||||
import { VoteBreakdown } from '../vote-breakdown';
|
||||
import { GovernanceTransferKindMapping } from '@vegaprotocol/types';
|
||||
|
||||
export const ProposalHeader = ({
|
||||
proposal,
|
||||
@@ -98,16 +93,6 @@ export const ProposalHeader = ({
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'UpdateReferralProgram': {
|
||||
proposalType = 'UpdateReferralProgram';
|
||||
fallbackTitle = t('UpdateReferralProgramProposal');
|
||||
break;
|
||||
}
|
||||
case 'UpdateVolumeDiscountProgram': {
|
||||
proposalType = 'UpdateVolumeDiscountProgram';
|
||||
fallbackTitle = t('UpdateVolumeDiscountProgramProposal');
|
||||
break;
|
||||
}
|
||||
case 'NewAsset': {
|
||||
proposalType = 'NewAsset';
|
||||
fallbackTitle = t('NewAssetProposal');
|
||||
@@ -162,20 +147,6 @@ export const ProposalHeader = ({
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'NewTransfer':
|
||||
proposalType = 'NewTransfer';
|
||||
fallbackTitle = t('NewTransferProposal');
|
||||
details = FLAGS.GOVERNANCE_TRANSFERS ? (
|
||||
<NewTransferSummary proposalId={proposal?.id} />
|
||||
) : null;
|
||||
break;
|
||||
case 'CancelTransfer':
|
||||
proposalType = 'CancelTransfer';
|
||||
fallbackTitle = t('CancelTransferProposal');
|
||||
details = FLAGS.GOVERNANCE_TRANSFERS ? (
|
||||
<CancelTransferSummary proposalId={proposal?.id} />
|
||||
) : null;
|
||||
break;
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -253,36 +224,3 @@ const SuccessorCode = ({ proposalId }: { proposalId?: string | null }) => {
|
||||
</span>
|
||||
) : null;
|
||||
};
|
||||
|
||||
const NewTransferSummary = ({ proposalId }: { proposalId?: string | null }) => {
|
||||
const { t } = useTranslation();
|
||||
const details = useNewTransferProposalDetails(proposalId);
|
||||
|
||||
if (!details) return null;
|
||||
|
||||
return (
|
||||
<span>
|
||||
{GovernanceTransferKindMapping[details.kind.__typename]}{' '}
|
||||
{t('transfer from')} <Lozenge>{truncateMiddle(details.source)}</Lozenge>{' '}
|
||||
{t('to')} <Lozenge>{truncateMiddle(details.destination)}</Lozenge>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
const CancelTransferSummary = ({
|
||||
proposalId,
|
||||
}: {
|
||||
proposalId?: string | null;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const details = useCancelTransferProposalDetails(proposalId);
|
||||
|
||||
if (!details) return null;
|
||||
|
||||
return (
|
||||
<span>
|
||||
{t('Cancel transfer: ')}{' '}
|
||||
<Lozenge>{truncateMiddle(details.transferId)}</Lozenge>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
+3
-5
@@ -12,12 +12,12 @@ import {
|
||||
PriceMonitoringBoundsInfoPanel,
|
||||
RiskFactorsInfoPanel,
|
||||
RiskModelInfoPanel,
|
||||
RiskParametersInfoPanel,
|
||||
SettlementAssetInfoPanel,
|
||||
getDataSourceSpecForSettlementSchedule,
|
||||
getDataSourceSpecForSettlementData,
|
||||
getDataSourceSpecForTradingTermination,
|
||||
getSigners,
|
||||
MarginScalingFactorsPanel,
|
||||
} from '@vegaprotocol/markets';
|
||||
import {
|
||||
Button,
|
||||
@@ -219,10 +219,8 @@ export const ProposalMarketData = ({
|
||||
parentMarket={parentMarketData}
|
||||
/>
|
||||
|
||||
<h2 className={marketDataHeaderStyles}>
|
||||
{t('Margin scaling factors')}
|
||||
</h2>
|
||||
<MarginScalingFactorsPanel
|
||||
<h2 className={marketDataHeaderStyles}>{t('Risk parameters')}</h2>
|
||||
<RiskParametersInfoPanel
|
||||
market={marketData}
|
||||
parentMarket={parentMarketData}
|
||||
/>
|
||||
|
||||
-1
@@ -1 +0,0 @@
|
||||
export * from './proposal-referral-program-details';
|
||||
-161
@@ -1,161 +0,0 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import {
|
||||
formatMinimumRunningNotionalTakerVolume,
|
||||
formatReferralDiscountFactor,
|
||||
formatReferralRewardFactor,
|
||||
formatMinimumStakedTokens,
|
||||
formatReferralRewardMultiplier,
|
||||
ProposalReferralProgramDetails,
|
||||
} from './proposal-referral-program-details';
|
||||
import { generateProposal } from '../../test-helpers/generate-proposals';
|
||||
|
||||
jest.mock('../../../../contexts/app-state/app-state-context', () => ({
|
||||
useAppState: () => ({
|
||||
appState: {
|
||||
decimals: 2,
|
||||
},
|
||||
}),
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
jest.setSystemTime(0);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
describe('ProposalReferralProgramDetails helper functions', () => {
|
||||
it('should format minimum running notional taker volume correctly', () => {
|
||||
const input = '1000';
|
||||
const formatted = formatMinimumRunningNotionalTakerVolume(input);
|
||||
expect(formatted).toBe('1,000');
|
||||
});
|
||||
|
||||
it('should format referral discount factor correctly', () => {
|
||||
const input = '0.05';
|
||||
const formatted = formatReferralDiscountFactor(input);
|
||||
expect(formatted).toBe('5.00%');
|
||||
});
|
||||
|
||||
it('should format referral reward factor correctly', () => {
|
||||
const input = '0.1';
|
||||
const formatted = formatReferralRewardFactor(input);
|
||||
expect(formatted).toBe('10.00%');
|
||||
});
|
||||
|
||||
it('should format minimum staked tokens correctly', () => {
|
||||
const input = '15';
|
||||
const decimals = 18;
|
||||
const formatted = formatMinimumStakedTokens(input, decimals);
|
||||
expect(formatted).toBe('0.000000000000000015');
|
||||
});
|
||||
|
||||
it('should format referral reward multiplier correctly', () => {
|
||||
const input = '3';
|
||||
const formatted = formatReferralRewardMultiplier(input);
|
||||
expect(formatted).toBe('3x');
|
||||
});
|
||||
});
|
||||
|
||||
const mockReferralProposal = generateProposal({
|
||||
terms: {
|
||||
change: {
|
||||
__typename: 'UpdateReferralProgram',
|
||||
changes: {
|
||||
benefitTiers: [
|
||||
{
|
||||
minimumEpochs: 6,
|
||||
minimumRunningNotionalTakerVolume: '10000',
|
||||
referralDiscountFactor: '0.001',
|
||||
referralRewardFactor: '0.001',
|
||||
},
|
||||
{
|
||||
minimumEpochs: 24,
|
||||
minimumRunningNotionalTakerVolume: '500000',
|
||||
referralDiscountFactor: '0.005',
|
||||
referralRewardFactor: '0.005',
|
||||
},
|
||||
{
|
||||
minimumEpochs: 48,
|
||||
minimumRunningNotionalTakerVolume: '1000000',
|
||||
referralDiscountFactor: '0.01',
|
||||
referralRewardFactor: '0.01',
|
||||
},
|
||||
],
|
||||
endOfProgramTimestamp: '2026-10-03T10:34:34Z',
|
||||
windowLength: 3,
|
||||
stakingTiers: [
|
||||
{
|
||||
minimumStakedTokens: '1',
|
||||
referralRewardMultiplier: '1',
|
||||
},
|
||||
{
|
||||
minimumStakedTokens: '2',
|
||||
referralRewardMultiplier: '2',
|
||||
},
|
||||
{
|
||||
minimumStakedTokens: '5',
|
||||
referralRewardMultiplier: '3',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
describe('<ProposalReferralProgramDetails />', () => {
|
||||
it('should not render if proposal is null', () => {
|
||||
render(<ProposalReferralProgramDetails proposal={null} />);
|
||||
expect(
|
||||
screen.queryByTestId('proposal-referral-program-details')
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it('should not render if __typename is not UpdateReferralProgram', () => {
|
||||
const updateMarketProposal = generateProposal({
|
||||
terms: {
|
||||
change: {
|
||||
__typename: 'UpdateMarket',
|
||||
},
|
||||
},
|
||||
});
|
||||
render(<ProposalReferralProgramDetails proposal={updateMarketProposal} />);
|
||||
expect(
|
||||
screen.queryByTestId('proposal-referral-program-details')
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it('should not render if there are no relevant fields', () => {
|
||||
const incompleteProposal = generateProposal({
|
||||
terms: {
|
||||
change: {
|
||||
__typename: 'UpdateReferralProgram',
|
||||
changes: {},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
render(<ProposalReferralProgramDetails proposal={incompleteProposal} />);
|
||||
expect(
|
||||
screen.queryByTestId('proposal-referral-program-details')
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it('should render relevant fields if present', () => {
|
||||
render(<ProposalReferralProgramDetails proposal={mockReferralProposal} />);
|
||||
expect(
|
||||
screen.getByTestId('proposal-referral-program-window-length')
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByTestId('proposal-referral-program-end-of-program-timestamp')
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByTestId('proposal-referral-program-benefit-tiers')
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByTestId('proposal-referral-program-benefit-tiers')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
-233
@@ -1,233 +0,0 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
|
||||
import {
|
||||
KeyValueTable,
|
||||
KeyValueTableRow,
|
||||
RoundedWrapper,
|
||||
Tooltip,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { formatNumber } from '../../../../lib/format-number';
|
||||
import {
|
||||
formatDateWithLocalTimezone,
|
||||
formatNumberPercentage,
|
||||
toBigNum,
|
||||
} from '@vegaprotocol/utils';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { useAppState } from '../../../../contexts/app-state/app-state-context';
|
||||
|
||||
interface ProposalReferralProgramDetailsProps {
|
||||
proposal: ProposalQuery['proposal'];
|
||||
}
|
||||
|
||||
export const formatEndOfProgramTimestamp = (value: string) => {
|
||||
return formatDateWithLocalTimezone(new Date(value));
|
||||
};
|
||||
|
||||
export const formatMinimumRunningNotionalTakerVolume = (value: string) => {
|
||||
return formatNumber(toBigNum(value, 0), 0);
|
||||
};
|
||||
|
||||
export const formatReferralDiscountFactor = (value: string) => {
|
||||
return formatNumberPercentage(new BigNumber(value).times(100));
|
||||
};
|
||||
|
||||
export const formatReferralRewardFactor = (value: string) => {
|
||||
return formatNumberPercentage(new BigNumber(value).times(100));
|
||||
};
|
||||
|
||||
export const formatMinimumStakedTokens = (value: string, decimals: number) => {
|
||||
return formatNumber(toBigNum(value, decimals));
|
||||
};
|
||||
|
||||
export const formatReferralRewardMultiplier = (value: string) => {
|
||||
return `${value}x`;
|
||||
};
|
||||
|
||||
export const ProposalReferralProgramDetails = ({
|
||||
proposal,
|
||||
}: ProposalReferralProgramDetailsProps) => {
|
||||
const {
|
||||
appState: { decimals },
|
||||
} = useAppState();
|
||||
const { t } = useTranslation();
|
||||
if (proposal?.terms?.change?.__typename !== 'UpdateReferralProgram') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const benefitTiers = proposal?.terms?.change?.changes?.benefitTiers;
|
||||
const stakingTiers = proposal?.terms?.change?.changes?.stakingTiers;
|
||||
const windowLength = proposal?.terms?.change?.changes?.windowLength;
|
||||
const endOfProgramTimestamp =
|
||||
proposal?.terms?.change?.changes?.endOfProgramTimestamp;
|
||||
|
||||
if (
|
||||
!benefitTiers &&
|
||||
!stakingTiers &&
|
||||
!windowLength &&
|
||||
!endOfProgramTimestamp
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div data-testid="proposal-referral-program-details">
|
||||
<RoundedWrapper paddingBottom={true}>
|
||||
{windowLength && (
|
||||
<div data-testid="proposal-referral-program-window-length">
|
||||
<KeyValueTable>
|
||||
<KeyValueTableRow>
|
||||
<Tooltip description={t('WindowLengthDescription')}>
|
||||
<span>{t('WindowLength')}</span>
|
||||
</Tooltip>
|
||||
{windowLength}
|
||||
</KeyValueTableRow>
|
||||
</KeyValueTable>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{endOfProgramTimestamp && (
|
||||
<div
|
||||
className="mb-6"
|
||||
data-testid="proposal-referral-program-end-of-program-timestamp"
|
||||
>
|
||||
<KeyValueTable>
|
||||
<KeyValueTableRow>
|
||||
<Tooltip description={t('EndOfProgramTimestampDescription')}>
|
||||
<span>{t('EndOfProgramTimestamp')}</span>
|
||||
</Tooltip>
|
||||
{formatEndOfProgramTimestamp(endOfProgramTimestamp)}
|
||||
</KeyValueTableRow>
|
||||
</KeyValueTable>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{benefitTiers && (
|
||||
<div
|
||||
className="mb-6"
|
||||
data-testid="proposal-referral-program-benefit-tiers"
|
||||
>
|
||||
<h3 className="mb-3 uppercase font-semibold text-lg">
|
||||
{t('BenefitTiers')}
|
||||
</h3>
|
||||
<KeyValueTable>
|
||||
{benefitTiers
|
||||
.sort((a, b) => a.minimumEpochs - b.minimumEpochs)
|
||||
.map((benefitTier, index) => (
|
||||
<div className="mb-4" key={index}>
|
||||
<h4 className="font-semibold uppercase">
|
||||
Tier {index + 1}
|
||||
</h4>
|
||||
{benefitTier.minimumEpochs && (
|
||||
<KeyValueTableRow>
|
||||
<Tooltip
|
||||
description={t('BenefitTierMinimumEpochsDescription')}
|
||||
>
|
||||
<span>{t('BenefitTierMinimumEpochs')}</span>
|
||||
</Tooltip>
|
||||
{benefitTier.minimumEpochs}
|
||||
</KeyValueTableRow>
|
||||
)}
|
||||
{benefitTier.minimumRunningNotionalTakerVolume && (
|
||||
<KeyValueTableRow>
|
||||
<Tooltip
|
||||
description={t(
|
||||
'BenefitTierMinimumRunningNotionalTakerVolumeDescription'
|
||||
)}
|
||||
>
|
||||
<span>
|
||||
{t('BenefitTierMinimumRunningNotionalTakerVolume')}
|
||||
</span>
|
||||
</Tooltip>
|
||||
{formatMinimumRunningNotionalTakerVolume(
|
||||
benefitTier.minimumRunningNotionalTakerVolume
|
||||
)}
|
||||
</KeyValueTableRow>
|
||||
)}
|
||||
{benefitTier.referralDiscountFactor && (
|
||||
<KeyValueTableRow>
|
||||
<Tooltip
|
||||
description={t(
|
||||
'BenefitTierReferralDiscountFactorDescription'
|
||||
)}
|
||||
>
|
||||
<span>{t('BenefitTierReferralDiscountFactor')}</span>
|
||||
</Tooltip>
|
||||
{formatReferralDiscountFactor(
|
||||
benefitTier.referralDiscountFactor
|
||||
)}
|
||||
</KeyValueTableRow>
|
||||
)}
|
||||
{benefitTier.referralRewardFactor && (
|
||||
<KeyValueTableRow>
|
||||
<Tooltip
|
||||
description={t(
|
||||
'BenefitTierReferralRewardFactorDescription'
|
||||
)}
|
||||
>
|
||||
<span>{t('BenefitTierReferralRewardFactor')}</span>
|
||||
</Tooltip>
|
||||
{formatReferralRewardFactor(
|
||||
benefitTier.referralRewardFactor
|
||||
)}
|
||||
</KeyValueTableRow>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</KeyValueTable>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{stakingTiers && (
|
||||
<div data-testid="proposal-referral-program-staking-tiers">
|
||||
<h3 className="mb-3 uppercase font-semibold text-lg">
|
||||
{t('StakingTiers')}
|
||||
</h3>
|
||||
<KeyValueTable>
|
||||
{stakingTiers
|
||||
.sort(
|
||||
(a, b) =>
|
||||
Number(a.minimumStakedTokens) -
|
||||
Number(b.minimumStakedTokens)
|
||||
)
|
||||
.map((stakingTier, index) => (
|
||||
<div className="mb-4" key={index}>
|
||||
{stakingTier.referralRewardMultiplier && (
|
||||
<KeyValueTableRow>
|
||||
<Tooltip
|
||||
description={t(
|
||||
'StakingTierReferralRewardMultiplierDescription'
|
||||
)}
|
||||
>
|
||||
<span>
|
||||
{t('StakingTierReferralRewardMultiplier')}
|
||||
</span>
|
||||
</Tooltip>
|
||||
{formatReferralRewardMultiplier(
|
||||
stakingTier.referralRewardMultiplier
|
||||
)}
|
||||
</KeyValueTableRow>
|
||||
)}
|
||||
{stakingTier.minimumStakedTokens && (
|
||||
<KeyValueTableRow>
|
||||
<Tooltip
|
||||
description={t(
|
||||
'StakingTierMinimumStakedTokensFactorDescription'
|
||||
)}
|
||||
>
|
||||
<span>{t('StakingTierMinimumStakedTokens')}</span>
|
||||
</Tooltip>
|
||||
{formatMinimumStakedTokens(
|
||||
stakingTier.minimumStakedTokens,
|
||||
decimals
|
||||
)}
|
||||
</KeyValueTableRow>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</KeyValueTable>
|
||||
</div>
|
||||
)}
|
||||
</RoundedWrapper>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,2 +0,0 @@
|
||||
export * from './proposal-transfer-details';
|
||||
export * from './proposal-cancel-transfer-details';
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
|
||||
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
|
||||
import { useCancelTransferProposalDetails } from '@vegaprotocol/proposals';
|
||||
import {
|
||||
KeyValueTable,
|
||||
KeyValueTableRow,
|
||||
RoundedWrapper,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { SubHeading } from '../../../../components/heading';
|
||||
|
||||
export const ProposalCancelTransferDetails = ({
|
||||
proposal,
|
||||
}: {
|
||||
proposal: ProposalFieldsFragment | ProposalQuery['proposal'];
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const details = useCancelTransferProposalDetails(proposal?.id);
|
||||
|
||||
if (!details) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<SubHeading title={t('proposalCancelTransferDetails')} />
|
||||
<RoundedWrapper paddingBottom={true}>
|
||||
<KeyValueTable data-testid="proposal-cancel-transfer-details-table">
|
||||
<KeyValueTableRow noBorder={true}>
|
||||
{t('transferId')}
|
||||
{details.transferId}
|
||||
</KeyValueTableRow>
|
||||
</KeyValueTable>
|
||||
</RoundedWrapper>
|
||||
</>
|
||||
);
|
||||
};
|
||||
-145
@@ -1,145 +0,0 @@
|
||||
import { useState } from 'react';
|
||||
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
|
||||
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
|
||||
import { CollapsibleToggle } from '../../../../components/collapsible-toggle';
|
||||
import { SubHeading } from '../../../../components/heading';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
KeyValueTable,
|
||||
KeyValueTableRow,
|
||||
RoundedWrapper,
|
||||
Tooltip,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { useNewTransferProposalDetails } from '@vegaprotocol/proposals';
|
||||
import {
|
||||
AccountTypeMapping,
|
||||
DescriptionGovernanceTransferTypeMapping,
|
||||
GovernanceTransferKindMapping,
|
||||
GovernanceTransferTypeMapping,
|
||||
} from '@vegaprotocol/types';
|
||||
import {
|
||||
addDecimalsFormatNumberQuantum,
|
||||
formatDateWithLocalTimezone,
|
||||
} from '@vegaprotocol/utils';
|
||||
|
||||
export const ProposalTransferDetails = ({
|
||||
proposal,
|
||||
}: {
|
||||
proposal: ProposalFieldsFragment | ProposalQuery['proposal'];
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const [show, setShow] = useState(false);
|
||||
|
||||
const details = useNewTransferProposalDetails(proposal?.id);
|
||||
if (!details) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<CollapsibleToggle
|
||||
toggleState={show}
|
||||
setToggleState={setShow}
|
||||
dataTestId="proposal-transfer-details"
|
||||
>
|
||||
<SubHeading title={t('proposalTransferDetails')} />
|
||||
</CollapsibleToggle>
|
||||
{show && (
|
||||
<RoundedWrapper paddingBottom={true}>
|
||||
<KeyValueTable data-testid="proposal-transfer-details-table">
|
||||
{/* The source account */}
|
||||
<KeyValueTableRow>
|
||||
{t('Source')}
|
||||
{details.source}
|
||||
</KeyValueTableRow>
|
||||
|
||||
{/* The type of source account */}
|
||||
<KeyValueTableRow>
|
||||
{t('Source Type')}
|
||||
{AccountTypeMapping[details.sourceType]}
|
||||
</KeyValueTableRow>
|
||||
|
||||
{/* The destination account */}
|
||||
<KeyValueTableRow>
|
||||
{t('Destination')}
|
||||
{details.destination}
|
||||
</KeyValueTableRow>
|
||||
|
||||
{/* The type of destination account */}
|
||||
<KeyValueTableRow>
|
||||
{t('Destination Type')}
|
||||
{AccountTypeMapping[details.destinationType]}
|
||||
</KeyValueTableRow>
|
||||
|
||||
{/* The asset to transfer */}
|
||||
<KeyValueTableRow>
|
||||
{t('Asset')}
|
||||
{details.asset.symbol}
|
||||
</KeyValueTableRow>
|
||||
|
||||
{/*The fraction of the balance to be transfer */}
|
||||
<KeyValueTableRow>
|
||||
{t('Fraction Of Balance')}
|
||||
{`${Number(details.fraction_of_balance) * 100}%`}
|
||||
</KeyValueTableRow>
|
||||
|
||||
{/* The maximum amount to be transferred */}
|
||||
<KeyValueTableRow>
|
||||
{t('Amount')}
|
||||
{addDecimalsFormatNumberQuantum(
|
||||
details.amount,
|
||||
details.asset.decimals,
|
||||
details.asset.quantum
|
||||
)}
|
||||
</KeyValueTableRow>
|
||||
|
||||
{/* The type of the governance transfer */}
|
||||
<KeyValueTableRow>
|
||||
{t('Transfer Type')}
|
||||
<Tooltip
|
||||
description={
|
||||
DescriptionGovernanceTransferTypeMapping[details.transferType]
|
||||
}
|
||||
>
|
||||
<span>
|
||||
{GovernanceTransferTypeMapping[details.transferType]}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</KeyValueTableRow>
|
||||
|
||||
{/* The type of governance transfer being made, i.e. a one-off or recurring trans */}
|
||||
<KeyValueTableRow>
|
||||
{t('Kind')}
|
||||
{GovernanceTransferKindMapping[details.kind.__typename]}
|
||||
</KeyValueTableRow>
|
||||
|
||||
{details.kind.__typename === 'OneOffGovernanceTransfer' &&
|
||||
details.kind.deliverOn && (
|
||||
<KeyValueTableRow noBorder={true}>
|
||||
{t('Deliver On')}
|
||||
{formatDateWithLocalTimezone(
|
||||
new Date(details.kind.deliverOn)
|
||||
)}
|
||||
</KeyValueTableRow>
|
||||
)}
|
||||
|
||||
{details.kind.__typename === 'RecurringGovernanceTransfer' && (
|
||||
<>
|
||||
<KeyValueTableRow noBorder={!details.kind.endEpoch}>
|
||||
{t('Start On')}
|
||||
<span>{details.kind.startEpoch}</span>
|
||||
</KeyValueTableRow>
|
||||
{details.kind.endEpoch && (
|
||||
<KeyValueTableRow noBorder={true}>
|
||||
{t('End on')}
|
||||
{details.kind.endEpoch}
|
||||
</KeyValueTableRow>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</KeyValueTable>
|
||||
</RoundedWrapper>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
-1
@@ -1 +0,0 @@
|
||||
export * from './proposal-volume-discount-program-details';
|
||||
-114
@@ -1,114 +0,0 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { ProposalVolumeDiscountProgramDetails } from './proposal-volume-discount-program-details';
|
||||
import { generateProposal } from '../../test-helpers/generate-proposals';
|
||||
|
||||
jest.mock('../../../../contexts/app-state/app-state-context', () => ({
|
||||
useAppState: () => ({
|
||||
appState: {
|
||||
decimals: 2,
|
||||
},
|
||||
}),
|
||||
}));
|
||||
|
||||
const mockReferralProposal = generateProposal({
|
||||
terms: {
|
||||
change: {
|
||||
__typename: 'UpdateVolumeDiscountProgram',
|
||||
benefitTiers: [
|
||||
{
|
||||
minimumRunningNotionalTakerVolume: '10000',
|
||||
volumeDiscountFactor: '0.05',
|
||||
},
|
||||
{
|
||||
minimumRunningNotionalTakerVolume: '50000',
|
||||
volumeDiscountFactor: '0.1',
|
||||
},
|
||||
{
|
||||
minimumRunningNotionalTakerVolume: '100000',
|
||||
volumeDiscountFactor: '0.15',
|
||||
},
|
||||
{
|
||||
minimumRunningNotionalTakerVolume: '250000',
|
||||
volumeDiscountFactor: '0.2',
|
||||
},
|
||||
{
|
||||
minimumRunningNotionalTakerVolume: '500000',
|
||||
volumeDiscountFactor: '0.25',
|
||||
},
|
||||
{
|
||||
minimumRunningNotionalTakerVolume: '1000000',
|
||||
volumeDiscountFactor: '0.3',
|
||||
},
|
||||
{
|
||||
minimumRunningNotionalTakerVolume: '1500000',
|
||||
volumeDiscountFactor: '0.35',
|
||||
},
|
||||
{
|
||||
minimumRunningNotionalTakerVolume: '2000000',
|
||||
volumeDiscountFactor: '0.4',
|
||||
},
|
||||
],
|
||||
endOfProgramTimestamp: '1970-01-01T00:00:01.791568493Z',
|
||||
windowLength: 7,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
describe('ProposalVolumeDiscountProgramDetails', () => {
|
||||
it('should not render if proposal is null', () => {
|
||||
render(<ProposalVolumeDiscountProgramDetails proposal={null} />);
|
||||
expect(
|
||||
screen.queryByTestId('proposal-volume-discount-program-details')
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it('should not render if __typename is not UpdateVolumeDiscountProgram', () => {
|
||||
const updateMarketProposal = generateProposal({
|
||||
terms: {
|
||||
change: {
|
||||
__typename: 'UpdateMarket',
|
||||
},
|
||||
},
|
||||
});
|
||||
render(
|
||||
<ProposalVolumeDiscountProgramDetails proposal={updateMarketProposal} />
|
||||
);
|
||||
expect(
|
||||
screen.queryByTestId('proposal-volume-discount-program-details')
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it('should not render if there are no relevant fields', () => {
|
||||
const incompleteProposal = generateProposal({
|
||||
terms: {
|
||||
change: {
|
||||
__typename: 'UpdateVolumeDiscountProgram',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
render(
|
||||
<ProposalVolumeDiscountProgramDetails proposal={incompleteProposal} />
|
||||
);
|
||||
expect(
|
||||
screen.queryByTestId('proposal-volume-discount-program-details')
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it('should render relevant fields if present', () => {
|
||||
render(
|
||||
<ProposalVolumeDiscountProgramDetails proposal={mockReferralProposal} />
|
||||
);
|
||||
expect(
|
||||
screen.getByTestId('proposal-volume-discount-program-window-length')
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByTestId(
|
||||
'proposal-volume-discount-program-end-of-program-timestamp'
|
||||
)
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByTestId('proposal-volume-discount-program-benefit-tiers')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
-130
@@ -1,130 +0,0 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
|
||||
import {
|
||||
KeyValueTable,
|
||||
KeyValueTableRow,
|
||||
RoundedWrapper,
|
||||
Tooltip,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import {
|
||||
formatEndOfProgramTimestamp,
|
||||
formatMinimumRunningNotionalTakerVolume,
|
||||
} from '../proposal-referral-program-details';
|
||||
import { formatNumberPercentage } from '@vegaprotocol/utils';
|
||||
import BigNumber from 'bignumber.js';
|
||||
|
||||
interface ProposalReferralProgramDetailsProps {
|
||||
proposal: ProposalQuery['proposal'];
|
||||
}
|
||||
|
||||
export const formatVolumeDiscountFactor = (value: string) => {
|
||||
return formatNumberPercentage(new BigNumber(value).times(100));
|
||||
};
|
||||
|
||||
export const ProposalVolumeDiscountProgramDetails = ({
|
||||
proposal,
|
||||
}: ProposalReferralProgramDetailsProps) => {
|
||||
const { t } = useTranslation();
|
||||
if (proposal?.terms?.change?.__typename !== 'UpdateVolumeDiscountProgram') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const benefitTiers = proposal?.terms?.change?.benefitTiers;
|
||||
const windowLength = proposal?.terms?.change?.windowLength;
|
||||
const endOfProgramTimestamp = proposal?.terms?.change?.endOfProgramTimestamp;
|
||||
|
||||
if (!benefitTiers && !windowLength && !endOfProgramTimestamp) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div data-testid="proposal-volume-discount-program-details">
|
||||
<RoundedWrapper paddingBottom={true}>
|
||||
{windowLength && (
|
||||
<div data-testid="proposal-volume-discount-program-window-length">
|
||||
<KeyValueTable>
|
||||
<KeyValueTableRow>
|
||||
<Tooltip description={t('WindowLengthDescription')}>
|
||||
<span>{t('WindowLength')}</span>
|
||||
</Tooltip>
|
||||
{windowLength}
|
||||
</KeyValueTableRow>
|
||||
</KeyValueTable>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{endOfProgramTimestamp && (
|
||||
<div
|
||||
className="mb-6"
|
||||
data-testid="proposal-volume-discount-program-end-of-program-timestamp"
|
||||
>
|
||||
<KeyValueTable>
|
||||
<KeyValueTableRow>
|
||||
<Tooltip description={t('EndOfProgramTimestampDescription')}>
|
||||
<span>{t('EndOfProgramTimestamp')}</span>
|
||||
</Tooltip>
|
||||
{formatEndOfProgramTimestamp(endOfProgramTimestamp)}
|
||||
</KeyValueTableRow>
|
||||
</KeyValueTable>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{benefitTiers && (
|
||||
<div
|
||||
className="mb-6"
|
||||
data-testid="proposal-volume-discount-program-benefit-tiers"
|
||||
>
|
||||
<h3 className="mb-3 uppercase font-semibold text-lg">
|
||||
{t('BenefitTiers')}
|
||||
</h3>
|
||||
<KeyValueTable>
|
||||
{benefitTiers
|
||||
.sort(
|
||||
(a, b) =>
|
||||
Number(a.minimumRunningNotionalTakerVolume) -
|
||||
Number(b.minimumRunningNotionalTakerVolume)
|
||||
)
|
||||
.map((benefitTier, index) => (
|
||||
<div className="mb-4" key={index}>
|
||||
<h4 className="font-semibold uppercase">
|
||||
Tier {index + 1}
|
||||
</h4>
|
||||
{benefitTier.minimumRunningNotionalTakerVolume && (
|
||||
<KeyValueTableRow>
|
||||
<Tooltip
|
||||
description={t(
|
||||
'BenefitTierMinimumRunningNotionalTakerVolumeDescription'
|
||||
)}
|
||||
>
|
||||
<span>
|
||||
{t('BenefitTierMinimumRunningNotionalTakerVolume')}
|
||||
</span>
|
||||
</Tooltip>
|
||||
{formatMinimumRunningNotionalTakerVolume(
|
||||
benefitTier.minimumRunningNotionalTakerVolume
|
||||
)}
|
||||
</KeyValueTableRow>
|
||||
)}
|
||||
{benefitTier.volumeDiscountFactor && (
|
||||
<KeyValueTableRow>
|
||||
<Tooltip
|
||||
description={t(
|
||||
'BenefitTierVolumeDiscountFactorDescription'
|
||||
)}
|
||||
>
|
||||
<span>{t('BenefitTierVolumeDiscountFactor')}</span>
|
||||
</Tooltip>
|
||||
{formatVolumeDiscountFactor(
|
||||
benefitTier.volumeDiscountFactor
|
||||
)}
|
||||
</KeyValueTableRow>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</KeyValueTable>
|
||||
</div>
|
||||
)}
|
||||
</RoundedWrapper>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -6,8 +6,6 @@ import { ProposalDescription } from '../proposal-description';
|
||||
import { ProposalChangeTable } from '../proposal-change-table';
|
||||
import { ProposalJson } from '../proposal-json';
|
||||
import { ProposalAssetDetails } from '../proposal-asset-details';
|
||||
import { ProposalReferralProgramDetails } from '../proposal-referral-program-details';
|
||||
import { ProposalVolumeDiscountProgramDetails } from '../proposal-volume-discount-program-details';
|
||||
import { UserVote } from '../vote-details';
|
||||
import { ListAsset } from '../list-asset';
|
||||
import Routes from '../../../routes';
|
||||
@@ -22,11 +20,6 @@ import { ProposalUpdateMarketState } from '../proposal-update-market-state';
|
||||
import type { NetworkParamsResult } from '@vegaprotocol/network-parameters';
|
||||
import { useVoteSubmit } from '@vegaprotocol/proposals';
|
||||
import { useUserVote } from '../vote-details/use-user-vote';
|
||||
import {
|
||||
ProposalCancelTransferDetails,
|
||||
ProposalTransferDetails,
|
||||
} from '../proposal-transfer';
|
||||
import { FLAGS } from '@vegaprotocol/environment';
|
||||
|
||||
export interface ProposalProps {
|
||||
proposal: ProposalQuery['proposal'];
|
||||
@@ -106,46 +99,9 @@ export const Proposal = ({
|
||||
minVoterBalance =
|
||||
networkParams.governance_proposal_freeform_minVoterBalance;
|
||||
break;
|
||||
case 'NewTransfer':
|
||||
// TODO: check minVoterBalance for 'NewTransfer'
|
||||
minVoterBalance =
|
||||
networkParams.governance_proposal_freeform_minVoterBalance;
|
||||
break;
|
||||
case 'CancelTransfer':
|
||||
// TODO: check minVoterBalance for 'CancelTransfer'
|
||||
minVoterBalance =
|
||||
networkParams.governance_proposal_freeform_minVoterBalance;
|
||||
break;
|
||||
case 'UpdateReferralProgram':
|
||||
minVoterBalance =
|
||||
networkParams.governance_proposal_referralProgram_minVoterBalance;
|
||||
break;
|
||||
case 'UpdateVolumeDiscountProgram':
|
||||
minVoterBalance =
|
||||
networkParams.governance_proposal_VolumeDiscountProgram_minVoterBalance;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Show governance transfer details only if the GOVERNANCE_TRANSFERS flag is on.
|
||||
const governanceTransferDetails = FLAGS.GOVERNANCE_TRANSFERS && (
|
||||
<>
|
||||
{proposal.terms.change.__typename === 'NewTransfer' && (
|
||||
/** Governance New Transfer Details */
|
||||
<div className="mb-4">
|
||||
<ProposalTransferDetails proposal={proposal} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{proposal.terms.change.__typename === 'CancelTransfer' && (
|
||||
/** Governance Cancel Transfer Details */
|
||||
<div className="mb-4">
|
||||
<ProposalCancelTransferDetails proposal={proposal} />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<section data-testid="proposal">
|
||||
<div className="flex items-center gap-1 mb-6">
|
||||
@@ -231,20 +187,6 @@ export const Proposal = ({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{proposal.terms.change.__typename === 'UpdateReferralProgram' && (
|
||||
<div className="mb-4">
|
||||
<ProposalReferralProgramDetails proposal={proposal} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{proposal.terms.change.__typename === 'UpdateVolumeDiscountProgram' && (
|
||||
<div className="mb-4">
|
||||
<ProposalVolumeDiscountProgramDetails proposal={proposal} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{governanceTransferDetails}
|
||||
|
||||
<div className="mb-10">
|
||||
<RoundedWrapper paddingBottom={true}>
|
||||
<UserVote
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ import {
|
||||
getProposalDialogTitle,
|
||||
} from '@vegaprotocol/proposals';
|
||||
import type { ProposalEventFieldsFragment } from '@vegaprotocol/proposals';
|
||||
import type { DialogProps } from '@vegaprotocol/proposals';
|
||||
import type { DialogProps } from '@vegaprotocol/wallet';
|
||||
|
||||
interface ProposalFormTransactionDialogProps {
|
||||
finalizedProposal: ProposalEventFieldsFragment | null;
|
||||
|
||||
@@ -6,7 +6,7 @@ import { ConnectToVega } from '../../../../components/connect-to-vega';
|
||||
import { VoteButtonsContainer } from './vote-buttons';
|
||||
import { SubHeading } from '../../../../components/heading';
|
||||
import type { VoteValue } from '@vegaprotocol/types';
|
||||
import type { DialogProps, VegaTxState } from '@vegaprotocol/proposals';
|
||||
import type { DialogProps, VegaTxState } from '@vegaprotocol/wallet';
|
||||
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
|
||||
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
|
||||
import type { VoteState } from './use-user-vote';
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { VoteTransactionDialog } from './vote-transaction-dialog';
|
||||
import { VoteState } from './use-user-vote';
|
||||
import { VegaTxStatus } from '@vegaprotocol/proposals';
|
||||
import { VegaTxStatus } from '@vegaprotocol/wallet';
|
||||
|
||||
describe('VoteTransactionDialog', () => {
|
||||
const mockTransactionDialog = jest.fn(({ title, content }) => (
|
||||
|
||||
@@ -17,7 +17,7 @@ import { VoteState } from './use-user-vote';
|
||||
import { ProposalMinRequirements, ProposalUserAction } from '../shared';
|
||||
import { VoteTransactionDialog } from './vote-transaction-dialog';
|
||||
import { useVoteButtonsQuery } from './__generated__/Stake';
|
||||
import type { DialogProps, VegaTxState } from '@vegaprotocol/proposals';
|
||||
import type { DialogProps, VegaTxState } from '@vegaprotocol/wallet';
|
||||
|
||||
interface VoteButtonsContainerProps {
|
||||
voteState: VoteState | null;
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { VoteState } from './use-user-vote';
|
||||
import type { DialogProps, VegaTxState } from '@vegaprotocol/proposals';
|
||||
import type { DialogProps, VegaTxState } from '@vegaprotocol/wallet';
|
||||
|
||||
interface VoteTransactionDialogProps {
|
||||
voteState: VoteState;
|
||||
|
||||
@@ -19,8 +19,6 @@ export const useProposalNetworkParams = ({
|
||||
NetworkParams.governance_proposal_market_requiredMajority,
|
||||
NetworkParams.governance_proposal_market_requiredParticipation,
|
||||
NetworkParams.governance_proposal_updateAsset_requiredMajority,
|
||||
NetworkParams.governance_proposal_referralProgram_requiredMajority,
|
||||
NetworkParams.governance_proposal_referralProgram_requiredParticipation,
|
||||
NetworkParams.governance_proposal_updateAsset_requiredParticipation,
|
||||
NetworkParams.governance_proposal_asset_requiredMajority,
|
||||
NetworkParams.governance_proposal_asset_requiredParticipation,
|
||||
@@ -28,8 +26,6 @@ export const useProposalNetworkParams = ({
|
||||
NetworkParams.governance_proposal_updateNetParam_requiredParticipation,
|
||||
NetworkParams.governance_proposal_freeform_requiredMajority,
|
||||
NetworkParams.governance_proposal_freeform_requiredParticipation,
|
||||
NetworkParams.governance_proposal_VolumeDiscountProgram_requiredMajority,
|
||||
NetworkParams.governance_proposal_VolumeDiscountProgram_requiredParticipation,
|
||||
]);
|
||||
|
||||
const fallback = {
|
||||
@@ -95,22 +91,6 @@ export const useProposalNetworkParams = ({
|
||||
params.governance_proposal_freeform_requiredParticipation
|
||||
),
|
||||
};
|
||||
case 'UpdateReferralProgram':
|
||||
return {
|
||||
requiredMajority:
|
||||
params.governance_proposal_referralProgram_requiredMajority,
|
||||
requiredParticipation: new BigNumber(
|
||||
params.governance_proposal_referralProgram_requiredParticipation
|
||||
),
|
||||
};
|
||||
case 'UpdateVolumeDiscountProgram':
|
||||
return {
|
||||
requiredMajority:
|
||||
params.governance_proposal_VolumeDiscountProgram_requiredMajority,
|
||||
requiredParticipation: new BigNumber(
|
||||
params.governance_proposal_VolumeDiscountProgram_requiredParticipation
|
||||
),
|
||||
};
|
||||
default:
|
||||
return fallback;
|
||||
}
|
||||
|
||||
@@ -43,50 +43,10 @@ fragment UpdateMarketState on Proposal {
|
||||
}
|
||||
}
|
||||
|
||||
fragment UpdateReferralProgram on Proposal {
|
||||
terms {
|
||||
change {
|
||||
... on UpdateReferralProgram {
|
||||
changes {
|
||||
benefitTiers {
|
||||
minimumEpochs
|
||||
minimumRunningNotionalTakerVolume
|
||||
referralDiscountFactor
|
||||
referralRewardFactor
|
||||
}
|
||||
endOfProgramTimestamp
|
||||
windowLength
|
||||
stakingTiers {
|
||||
minimumStakedTokens
|
||||
referralRewardMultiplier
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fragment UpdateVolumeDiscountProgram on Proposal {
|
||||
terms {
|
||||
change {
|
||||
... on UpdateVolumeDiscountProgram {
|
||||
benefitTiers {
|
||||
minimumRunningNotionalTakerVolume
|
||||
volumeDiscountFactor
|
||||
}
|
||||
endOfProgramTimestamp
|
||||
windowLength
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query Proposal(
|
||||
$proposalId: ID!
|
||||
$includeNewMarketProductField: Boolean!
|
||||
$includeUpdateMarketState: Boolean!
|
||||
$includeUpdateReferralProgram: Boolean!
|
||||
$includeUpdateVolumeDiscountProgram: Boolean!
|
||||
) {
|
||||
proposal(id: $proposalId) {
|
||||
id
|
||||
@@ -104,9 +64,6 @@ query Proposal(
|
||||
errorDetails
|
||||
...NewMarketProductField @include(if: $includeNewMarketProductField)
|
||||
...UpdateMarketState @include(if: $includeUpdateMarketState)
|
||||
...UpdateReferralProgram @include(if: $includeUpdateReferralProgram)
|
||||
...UpdateVolumeDiscountProgram
|
||||
@include(if: $includeUpdateVolumeDiscountProgram)
|
||||
terms {
|
||||
closingDatetime
|
||||
enactmentDatetime
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -36,8 +36,6 @@ export const ProposalContainer = () => {
|
||||
NetworkParams.governance_proposal_updateAsset_minVoterBalance,
|
||||
NetworkParams.governance_proposal_updateNetParam_minVoterBalance,
|
||||
NetworkParams.governance_proposal_freeform_minVoterBalance,
|
||||
NetworkParams.governance_proposal_referralProgram_minVoterBalance,
|
||||
NetworkParams.governance_proposal_VolumeDiscountProgram_minVoterBalance,
|
||||
NetworkParams.spam_protection_voting_min_tokens,
|
||||
NetworkParams.governance_proposal_market_requiredMajority,
|
||||
NetworkParams.governance_proposal_updateMarket_requiredMajority,
|
||||
@@ -46,8 +44,6 @@ export const ProposalContainer = () => {
|
||||
NetworkParams.governance_proposal_updateAsset_requiredMajority,
|
||||
NetworkParams.governance_proposal_updateNetParam_requiredMajority,
|
||||
NetworkParams.governance_proposal_freeform_requiredMajority,
|
||||
NetworkParams.governance_proposal_referralProgram_requiredMajority,
|
||||
NetworkParams.governance_proposal_VolumeDiscountProgram_requiredMajority,
|
||||
]);
|
||||
|
||||
const {
|
||||
@@ -61,8 +57,6 @@ export const ProposalContainer = () => {
|
||||
proposalId: params.proposalId || '',
|
||||
includeNewMarketProductField: !!FLAGS.PRODUCT_PERPETUALS,
|
||||
includeUpdateMarketState: !!FLAGS.UPDATE_MARKET_STATE,
|
||||
includeUpdateReferralProgram: !!FLAGS.REFERRALS,
|
||||
includeUpdateVolumeDiscountProgram: !!FLAGS.VOLUME_DISCOUNTS,
|
||||
},
|
||||
skip: !params.proposalId,
|
||||
});
|
||||
|
||||
@@ -43,44 +43,6 @@ fragment UpdateMarketStates on Proposal {
|
||||
}
|
||||
}
|
||||
|
||||
fragment UpdateReferralPrograms on Proposal {
|
||||
terms {
|
||||
change {
|
||||
... on UpdateReferralProgram {
|
||||
changes {
|
||||
benefitTiers {
|
||||
minimumEpochs
|
||||
minimumRunningNotionalTakerVolume
|
||||
referralDiscountFactor
|
||||
referralRewardFactor
|
||||
}
|
||||
endOfProgramTimestamp
|
||||
windowLength
|
||||
stakingTiers {
|
||||
minimumStakedTokens
|
||||
referralRewardMultiplier
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fragment UpdateVolumeDiscountPrograms on Proposal {
|
||||
terms {
|
||||
change {
|
||||
... on UpdateVolumeDiscountProgram {
|
||||
benefitTiers {
|
||||
minimumRunningNotionalTakerVolume
|
||||
volumeDiscountFactor
|
||||
}
|
||||
endOfProgramTimestamp
|
||||
windowLength
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fragment ProposalFields on Proposal {
|
||||
id
|
||||
rationale {
|
||||
@@ -165,8 +127,6 @@ fragment ProposalFields on Proposal {
|
||||
query Proposals(
|
||||
$includeNewMarketProductFields: Boolean!
|
||||
$includeUpdateMarketStates: Boolean!
|
||||
$includeUpdateReferralPrograms: Boolean!
|
||||
$includeUpdateVolumeDiscountPrograms: Boolean!
|
||||
) {
|
||||
proposalsConnection {
|
||||
edges {
|
||||
@@ -174,9 +134,6 @@ query Proposals(
|
||||
...ProposalFields
|
||||
...NewMarketProductFields @include(if: $includeNewMarketProductFields)
|
||||
...UpdateMarketStates @include(if: $includeUpdateMarketStates)
|
||||
...UpdateReferralPrograms @include(if: $includeUpdateReferralPrograms)
|
||||
...UpdateVolumeDiscountPrograms
|
||||
@include(if: $includeUpdateVolumeDiscountPrograms)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-55
@@ -7,21 +7,15 @@ export type NewMarketProductFieldsFragment = { __typename?: 'Proposal', terms: {
|
||||
|
||||
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 UpdateReferralProgramsFragment = { __typename?: 'Proposal', terms: { __typename?: 'ProposalTerms', change: { __typename?: 'CancelTransfer' } | { __typename?: 'NewAsset' } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket' } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset' } | { __typename?: 'UpdateMarket' } | { __typename?: 'UpdateMarketState' } | { __typename?: 'UpdateNetworkParameter' } | { __typename?: 'UpdateReferralProgram', changes: { __typename?: 'ReferralProgram', endOfProgramTimestamp: string, windowLength: number, benefitTiers: Array<{ __typename?: 'BenefitTier', minimumEpochs: number, minimumRunningNotionalTakerVolume: string, referralDiscountFactor: string, referralRewardFactor: string }>, stakingTiers: Array<{ __typename?: 'StakingTier', minimumStakedTokens: string, referralRewardMultiplier: string }> } } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram' } } };
|
||||
|
||||
export type UpdateVolumeDiscountProgramsFragment = { __typename?: 'Proposal', terms: { __typename?: 'ProposalTerms', change: { __typename?: 'CancelTransfer' } | { __typename?: 'NewAsset' } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket' } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset' } | { __typename?: 'UpdateMarket' } | { __typename?: 'UpdateMarketState' } | { __typename?: 'UpdateNetworkParameter' } | { __typename?: 'UpdateReferralProgram' } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram', endOfProgramTimestamp: any, windowLength: number, benefitTiers: Array<{ __typename?: 'VolumeBenefitTier', minimumRunningNotionalTakerVolume: string, volumeDiscountFactor: string }> } } };
|
||||
|
||||
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'];
|
||||
includeUpdateReferralPrograms: Types.Scalars['Boolean'];
|
||||
includeUpdateVolumeDiscountPrograms: 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, 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', changes: { __typename?: 'ReferralProgram', endOfProgramTimestamp: string, windowLength: number, benefitTiers: Array<{ __typename?: 'BenefitTier', minimumEpochs: number, minimumRunningNotionalTakerVolume: string, referralDiscountFactor: string, referralRewardFactor: string }>, stakingTiers: Array<{ __typename?: 'StakingTier', minimumStakedTokens: string, referralRewardMultiplier: string }> } } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram', endOfProgramTimestamp: any, windowLength: number, benefitTiers: Array<{ __typename?: 'VolumeBenefitTier', minimumRunningNotionalTakerVolume: string, volumeDiscountFactor: 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 {
|
||||
@@ -70,46 +64,6 @@ export const UpdateMarketStatesFragmentDoc = gql`
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const UpdateReferralProgramsFragmentDoc = gql`
|
||||
fragment UpdateReferralPrograms on Proposal {
|
||||
terms {
|
||||
change {
|
||||
... on UpdateReferralProgram {
|
||||
changes {
|
||||
benefitTiers {
|
||||
minimumEpochs
|
||||
minimumRunningNotionalTakerVolume
|
||||
referralDiscountFactor
|
||||
referralRewardFactor
|
||||
}
|
||||
endOfProgramTimestamp
|
||||
windowLength
|
||||
stakingTiers {
|
||||
minimumStakedTokens
|
||||
referralRewardMultiplier
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const UpdateVolumeDiscountProgramsFragmentDoc = gql`
|
||||
fragment UpdateVolumeDiscountPrograms on Proposal {
|
||||
terms {
|
||||
change {
|
||||
... on UpdateVolumeDiscountProgram {
|
||||
benefitTiers {
|
||||
minimumRunningNotionalTakerVolume
|
||||
volumeDiscountFactor
|
||||
}
|
||||
endOfProgramTimestamp
|
||||
windowLength
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const ProposalFieldsFragmentDoc = gql`
|
||||
fragment ProposalFields on Proposal {
|
||||
id
|
||||
@@ -193,24 +147,20 @@ export const ProposalFieldsFragmentDoc = gql`
|
||||
}
|
||||
`;
|
||||
export const ProposalsDocument = gql`
|
||||
query Proposals($includeNewMarketProductFields: Boolean!, $includeUpdateMarketStates: Boolean!, $includeUpdateReferralPrograms: Boolean!, $includeUpdateVolumeDiscountPrograms: Boolean!) {
|
||||
query Proposals($includeNewMarketProductFields: Boolean!, $includeUpdateMarketStates: Boolean!) {
|
||||
proposalsConnection {
|
||||
edges {
|
||||
node {
|
||||
...ProposalFields
|
||||
...NewMarketProductFields @include(if: $includeNewMarketProductFields)
|
||||
...UpdateMarketStates @include(if: $includeUpdateMarketStates)
|
||||
...UpdateReferralPrograms @include(if: $includeUpdateReferralPrograms)
|
||||
...UpdateVolumeDiscountPrograms @include(if: $includeUpdateVolumeDiscountPrograms)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
${ProposalFieldsFragmentDoc}
|
||||
${NewMarketProductFieldsFragmentDoc}
|
||||
${UpdateMarketStatesFragmentDoc}
|
||||
${UpdateReferralProgramsFragmentDoc}
|
||||
${UpdateVolumeDiscountProgramsFragmentDoc}`;
|
||||
${UpdateMarketStatesFragmentDoc}`;
|
||||
|
||||
/**
|
||||
* __useProposalsQuery__
|
||||
@@ -226,8 +176,6 @@ ${UpdateVolumeDiscountProgramsFragmentDoc}`;
|
||||
* variables: {
|
||||
* includeNewMarketProductFields: // value for 'includeNewMarketProductFields'
|
||||
* includeUpdateMarketStates: // value for 'includeUpdateMarketStates'
|
||||
* includeUpdateReferralPrograms: // value for 'includeUpdateReferralPrograms'
|
||||
* includeUpdateVolumeDiscountPrograms: // value for 'includeUpdateVolumeDiscountPrograms'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
|
||||
@@ -49,8 +49,6 @@ export const ProposalsContainer = () => {
|
||||
variables: {
|
||||
includeNewMarketProductFields: !!FLAGS.PRODUCT_PERPETUALS,
|
||||
includeUpdateMarketStates: !!FLAGS.UPDATE_MARKET_STATE,
|
||||
includeUpdateReferralPrograms: !!FLAGS.REFERRALS,
|
||||
includeUpdateVolumeDiscountPrograms: !!FLAGS.VOLUME_DISCOUNTS,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -41,8 +41,6 @@ export const RejectedProposalsContainer = () => {
|
||||
variables: {
|
||||
includeNewMarketProductFields: !!FLAGS.PRODUCT_PERPETUALS,
|
||||
includeUpdateMarketStates: !!FLAGS.UPDATE_MARKET_STATE,
|
||||
includeUpdateReferralPrograms: !!FLAGS.REFERRALS,
|
||||
includeUpdateVolumeDiscountPrograms: !!FLAGS.VOLUME_DISCOUNTS,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
.pre-loader {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.pre-loader .loader-item {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: #000;
|
||||
}
|
||||
.pre-loader .pre-loader-center {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.pre-loader .pre-loader-wrapper {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(0) {
|
||||
animation-delay: 0ms;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.pre-loader .loader-item:first-child {
|
||||
animation-delay: -0.1s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(2) {
|
||||
animation-delay: 0.3s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(3) {
|
||||
animation-delay: -0.45s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(4) {
|
||||
animation-delay: 1s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(5) {
|
||||
animation-delay: -0.75s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(6) {
|
||||
animation-delay: 0.9s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(7) {
|
||||
animation-delay: -1.4s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(8) {
|
||||
animation-delay: 1.6s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(9) {
|
||||
animation-delay: -0.45s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(10) {
|
||||
animation-delay: 1.5s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(11) {
|
||||
animation-delay: -2.75s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(12) {
|
||||
animation-delay: 1.2s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(13) {
|
||||
animation-delay: -1.95s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(14) {
|
||||
animation-delay: 2.8s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(15) {
|
||||
animation-delay: -0.75s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(16) {
|
||||
animation-delay: 4s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(17) {
|
||||
animation-delay: -0.85s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(18) {
|
||||
animation-delay: 1.8s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(19) {
|
||||
animation-delay: -1.9s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(20) {
|
||||
animation-delay: 5s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(21) {
|
||||
animation-delay: -5.25s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(22) {
|
||||
animation-delay: 4.4s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(23) {
|
||||
animation-delay: -5.75s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(24) {
|
||||
animation-delay: 4.8s;
|
||||
animation-direction: reverse;
|
||||
}
|
||||
.pre-loader .loader-item:nth-child(25) {
|
||||
animation-delay: -5s;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
.pre-loader .loader-item {
|
||||
animation: flickering 0.4s linear infinite alternate;
|
||||
}
|
||||
@keyframes flickering {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
25% {
|
||||
opacity: 1;
|
||||
}
|
||||
26% {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
html.dark .pre-loader .loader-item {
|
||||
background: #fff;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
.pre-loader {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.loader-item {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
background: black;
|
||||
}
|
||||
.pre-loader-center {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.pre-loader-wrapper {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
@for $i from 0 through 25 {
|
||||
.loader-item:nth-child(#{$i}) {
|
||||
@if $i % 2 == 0 {
|
||||
animation-delay: #{$i * 50 * random(5)}ms;
|
||||
animation-direction: reverse;
|
||||
} @else {
|
||||
animation-delay: #{$i * -50 * random(5)}ms;
|
||||
animation-direction: alternate;
|
||||
}
|
||||
}
|
||||
}
|
||||
.loader-item {
|
||||
animation: flickering 0.4s linear alternate infinite;
|
||||
}
|
||||
@keyframes flickering {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
25% {
|
||||
opacity: 1;
|
||||
}
|
||||
26% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
html.dark {
|
||||
.pre-loader {
|
||||
.loader-item {
|
||||
background: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,7 +61,7 @@ describe('home', { tags: '@regression' }, () => {
|
||||
// 0006-NETW-020
|
||||
cy.getByTestId(nodeHealthTrigger).click();
|
||||
cy.getByTestId('connect').should('be.disabled');
|
||||
cy.getByTestId('node-url-custom').click({ force: true });
|
||||
cy.getByTestId('node-url-custom').click();
|
||||
cy.getByTestId('connect').should('be.disabled');
|
||||
cy.get("input[placeholder='https://']")
|
||||
.focus()
|
||||
|
||||
@@ -58,7 +58,7 @@ describe('Market trading page', () => {
|
||||
// 6002-MDET-003
|
||||
cy.getByTestId(marketSummaryBlock).within(() => {
|
||||
cy.getByTestId(marketPrice).within(() => {
|
||||
cy.getByTestId(itemHeader).should('have.text', 'Mark Price');
|
||||
cy.getByTestId(itemHeader).should('have.text', 'Price');
|
||||
cy.getByTestId(itemValue).should('not.be.empty');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { MarketState } from '@vegaprotocol/types';
|
||||
|
||||
const oracleBannerDialogTrigger = 'oracle-banner-dialog-trigger';
|
||||
const oracleBannerStatus = 'oracle-banner-status';
|
||||
const oracleFullProfile = 'oracle-full-profile';
|
||||
|
||||
describe('oracle information', { tags: '@smoke' }, () => {
|
||||
before(() => {
|
||||
cy.setOnBoardingViewed();
|
||||
cy.mockTradingPage(
|
||||
MarketState.STATE_ACTIVE,
|
||||
undefined,
|
||||
undefined,
|
||||
'COMPROMISED'
|
||||
);
|
||||
cy.mockSubscription();
|
||||
cy.visit('/#/markets/market-0');
|
||||
cy.wait('@Markets');
|
||||
});
|
||||
|
||||
it('show oracle banner', () => {
|
||||
cy.getByTestId(oracleBannerStatus).should('contain.text', 'COMPROMISED');
|
||||
cy.getByTestId(oracleBannerDialogTrigger)
|
||||
.should('contain.text', 'Show more')
|
||||
.click();
|
||||
cy.getByTestId(oracleFullProfile).should('exist');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,179 @@
|
||||
import { checkSorting } from '@vegaprotocol/cypress';
|
||||
|
||||
const dialogClose = 'dialog-close';
|
||||
|
||||
describe('accounts', { tags: '@smoke' }, () => {
|
||||
beforeEach(() => {
|
||||
cy.mockTradingPage();
|
||||
cy.mockWeb3Provider();
|
||||
cy.mockSubscription();
|
||||
cy.setVegaWallet();
|
||||
cy.visit('/#/markets/market-0');
|
||||
});
|
||||
|
||||
it('renders accounts', () => {
|
||||
// 7001-COLL-001
|
||||
// 7001-COLL-002
|
||||
// 7001-COLL-003
|
||||
// 7001-COLL-004
|
||||
// 7001-COLL-005
|
||||
// 7001-COLL-006
|
||||
// 7001-COLL-007
|
||||
// 1003-TRAN-001
|
||||
// 7001-COLL-012
|
||||
|
||||
const tradingAccountRowId = '[row-id="t-0"]';
|
||||
cy.getByTestId('Collateral').click();
|
||||
|
||||
cy.getByTestId('tab-accounts').should('be.visible');
|
||||
|
||||
cy.getByTestId('tab-accounts')
|
||||
.get(tradingAccountRowId)
|
||||
.find('[col-id="asset.symbol"]')
|
||||
.should('have.text', 'AST0');
|
||||
|
||||
cy.getByTestId('tab-accounts')
|
||||
.get(tradingAccountRowId)
|
||||
.find('[col-id="used"]')
|
||||
.should('have.text', '1.01' + '1.00%');
|
||||
|
||||
cy.getByTestId('tab-accounts')
|
||||
.get(tradingAccountRowId)
|
||||
.find('[col-id="available"]')
|
||||
.should('have.text', '100.00');
|
||||
|
||||
cy.getByTestId('tab-accounts')
|
||||
.get(tradingAccountRowId)
|
||||
.find('[col-id="total"]')
|
||||
.should('have.text', '101.01');
|
||||
|
||||
cy.getByTestId('tab-accounts')
|
||||
.get(tradingAccountRowId)
|
||||
.find('[col-id="accounts-actions"]')
|
||||
.should('have.text', '');
|
||||
|
||||
cy.getByTestId('tab-accounts')
|
||||
.get('[col-id="accounts-actions"]')
|
||||
.find('[data-testid="dropdown-menu"]')
|
||||
.eq(1)
|
||||
.click();
|
||||
cy.getByTestId('deposit').should('be.visible');
|
||||
cy.getByTestId('withdraw').should('be.visible');
|
||||
cy.getByTestId('transfer').should('be.visible');
|
||||
cy.getByTestId('breakdown').should('be.visible');
|
||||
cy.getByTestId('Collateral').click({ force: true });
|
||||
});
|
||||
|
||||
it('should open usage breakdown dialog when clicked on used', () => {
|
||||
// 7001-COLL-009
|
||||
cy.get('[col-id="used"]').contains('1.01').click();
|
||||
const headers = ['Market', 'Account type', 'Balance', 'Margin health'];
|
||||
cy.getByTestId('usage-breakdown').within(($headers) => {
|
||||
cy.wrap($headers)
|
||||
.get('.ag-header-cell-text')
|
||||
.each(($header, i) => {
|
||||
cy.wrap($header).should('have.text', headers[i]);
|
||||
});
|
||||
});
|
||||
cy.getByTestId(dialogClose).click();
|
||||
});
|
||||
|
||||
describe('sorting by ag-grid columns should work well', () => {
|
||||
before(() => {
|
||||
const dialogs = Cypress.$('[data-testid="dialog-close"]:visible');
|
||||
if (dialogs.length > 0) {
|
||||
dialogs.each((btn) => {
|
||||
cy.wrap(btn).click();
|
||||
});
|
||||
}
|
||||
cy.contains('Loading...').should('not.exist');
|
||||
});
|
||||
// 7001-COLL-010
|
||||
it('sorting by asset', () => {
|
||||
cy.getByTestId('Collateral').click();
|
||||
const marketsSortedDefault = ['tBTC', 'tEURO', 'tDAI', 'tBTC'];
|
||||
const marketsSortedAsc = ['tBTC', 'tBTC', 'tDAI', 'tEURO'];
|
||||
const marketsSortedDesc = Array.from(marketsSortedAsc).reverse();
|
||||
checkSorting(
|
||||
'asset.symbol',
|
||||
marketsSortedDefault,
|
||||
marketsSortedAsc,
|
||||
marketsSortedDesc
|
||||
);
|
||||
});
|
||||
|
||||
it('sorting by total', () => {
|
||||
cy.getByTestId('Collateral').click();
|
||||
const marketsSortedDefault = [
|
||||
'1,000.00002',
|
||||
'1,000.01',
|
||||
'1,000.00',
|
||||
'1,000.00001',
|
||||
];
|
||||
const marketsSortedAsc = [
|
||||
'1,000.00',
|
||||
'1,000.00001',
|
||||
'1,000.00002',
|
||||
'1,000.01',
|
||||
];
|
||||
const marketsSortedDesc = Array.from(marketsSortedAsc).reverse();
|
||||
|
||||
checkSorting(
|
||||
'total',
|
||||
marketsSortedDefault,
|
||||
marketsSortedAsc,
|
||||
marketsSortedDesc
|
||||
);
|
||||
});
|
||||
|
||||
it('sorting by used', () => {
|
||||
cy.getByTestId('Collateral').click();
|
||||
// concat actual value with percentage value
|
||||
// as cypress will pick up the entire cell contes
|
||||
// textContent
|
||||
const marketsSortedDefault = [
|
||||
'0.00' + '0.00%',
|
||||
'0.01' + '0.00%',
|
||||
'0.00' + '0.00%',
|
||||
'0.00' + '0.00%',
|
||||
];
|
||||
const marketsSortedAsc = [
|
||||
'0.00' + '0.00%',
|
||||
'0.00' + '0.00%',
|
||||
'0.00' + '0.00%',
|
||||
'0.01' + '0.00%',
|
||||
];
|
||||
const marketsSortedDesc = Array.from(marketsSortedAsc).reverse();
|
||||
checkSorting(
|
||||
'used',
|
||||
marketsSortedDefault,
|
||||
marketsSortedAsc,
|
||||
marketsSortedDesc
|
||||
);
|
||||
});
|
||||
|
||||
it('sorting by available', () => {
|
||||
cy.getByTestId('Collateral').click();
|
||||
const marketsSortedDefault = [
|
||||
'1,000.00002',
|
||||
'1,000.00',
|
||||
'1,000.00',
|
||||
'1,000.00001',
|
||||
];
|
||||
const marketsSortedAsc = [
|
||||
'1,000.00',
|
||||
'1,000.00',
|
||||
'1,000.00001',
|
||||
'1,000.00002',
|
||||
];
|
||||
const marketsSortedDesc = Array.from(marketsSortedAsc).reverse();
|
||||
|
||||
checkSorting(
|
||||
'available',
|
||||
marketsSortedDefault,
|
||||
marketsSortedAsc,
|
||||
marketsSortedDesc
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
+83
-2
@@ -1,11 +1,92 @@
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import { aliasGQLQuery } from '@vegaprotocol/cypress';
|
||||
import {
|
||||
accountsQuery,
|
||||
amendGeneralAccountBalance,
|
||||
amendMarginAccountBalance,
|
||||
} from '@vegaprotocol/mock';
|
||||
import type { OrderSubmission } from '@vegaprotocol/wallet';
|
||||
import { createOrder } from '../support/create-order';
|
||||
|
||||
describe(
|
||||
'vega wallet - prompt',
|
||||
describe.skip(
|
||||
'account validation',
|
||||
{ tags: '@regression', testIsolation: true },
|
||||
() => {
|
||||
describe.skip('zero balance error', () => {
|
||||
beforeEach(() => {
|
||||
cy.setVegaWallet();
|
||||
cy.mockTradingPage();
|
||||
let accounts = accountsQuery();
|
||||
accounts = amendMarginAccountBalance(accounts, 'market-0', '1000');
|
||||
accounts = amendGeneralAccountBalance(accounts, 'market-0', '0');
|
||||
cy.mockGQL((req) => {
|
||||
aliasGQLQuery(req, 'Accounts', accounts);
|
||||
});
|
||||
cy.mockSubscription();
|
||||
cy.visit('/#/markets/market-0');
|
||||
cy.wait('@Markets');
|
||||
});
|
||||
|
||||
it('should show an error if your balance is zero', () => {
|
||||
const accounts = accountsQuery();
|
||||
amendMarginAccountBalance(accounts, 'market-0', '0');
|
||||
cy.mockGQL((req) => {
|
||||
aliasGQLQuery(req, 'Accounts', accounts);
|
||||
});
|
||||
// 7002-SORD-060
|
||||
cy.getByTestId('place-order').should('be.enabled');
|
||||
// 7002-SORD-003
|
||||
cy.getByTestId('deal-ticket-error-message-zero-balance').should(
|
||||
'have.text',
|
||||
'You need ' +
|
||||
'tDAI' +
|
||||
' in your wallet to trade in this market. See all your collateral.Make a deposit'
|
||||
);
|
||||
cy.getByTestId('deal-ticket-deposit-dialog-button').should('exist');
|
||||
});
|
||||
});
|
||||
|
||||
describe('not enough balance warning', () => {
|
||||
beforeEach(() => {
|
||||
cy.setVegaWallet();
|
||||
cy.mockTradingPage();
|
||||
let accounts = accountsQuery();
|
||||
accounts = amendMarginAccountBalance(accounts, 'market-0', '1000');
|
||||
accounts = amendGeneralAccountBalance(accounts, 'market-0', '1');
|
||||
cy.mockGQL((req) => {
|
||||
aliasGQLQuery(req, 'Accounts', accounts);
|
||||
});
|
||||
cy.mockSubscription();
|
||||
cy.visit('/#/markets/market-0');
|
||||
cy.wait('@Markets');
|
||||
|
||||
cy.get('[data-testid="deal-ticket-form"]').then(($form) => {
|
||||
if (!$form.length) {
|
||||
cy.getByTestId('Order').click();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should display info and button for deposit', () => {
|
||||
// 7002-SORD-003
|
||||
|
||||
// warning should show immediately
|
||||
cy.getByTestId('deal-ticket-warning-margin').should(
|
||||
'contain.text',
|
||||
'You may not have enough margin available to open this position'
|
||||
);
|
||||
cy.getByTestId('deal-ticket-warning-margin').should(
|
||||
'contain.text',
|
||||
'You may not have enough margin available to open this position. 5.00 tDAI is currently required. You have only 0.01001 tDAI available.'
|
||||
);
|
||||
cy.getByTestId('deal-ticket-deposit-dialog-button').click();
|
||||
cy.getByTestId('sidebar-content')
|
||||
.find('h2')
|
||||
.eq(0)
|
||||
.should('have.text', 'Deposit');
|
||||
});
|
||||
});
|
||||
|
||||
describe('must submit order', { tags: '@smoke' }, () => {
|
||||
// 7002-SORD-039
|
||||
beforeEach(() => {
|
||||
@@ -0,0 +1,186 @@
|
||||
import {
|
||||
TIFlist,
|
||||
orderTIFDropDown,
|
||||
toggleLimit,
|
||||
toggleMarket,
|
||||
} from '../support/deal-ticket';
|
||||
|
||||
const tooltipContent = 'tooltip-content';
|
||||
const reduceOnly = 'reduce-only';
|
||||
const postOnly = 'post-only';
|
||||
|
||||
describe('time in force validation', { tags: '@smoke' }, () => {
|
||||
before(() => {
|
||||
cy.setVegaWallet();
|
||||
cy.mockTradingPage();
|
||||
cy.mockSubscription();
|
||||
cy.clearAllLocalStorage();
|
||||
cy.setOnBoardingViewed();
|
||||
cy.visit('/#/markets/market-0');
|
||||
cy.wait('@Markets');
|
||||
});
|
||||
|
||||
it('must have market order set up to IOC by default', function () {
|
||||
// 7002-SORD-030
|
||||
cy.getByTestId(toggleMarket).click();
|
||||
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
|
||||
'have.text',
|
||||
TIFlist.filter((item) => item.code === 'IOC')[0].text
|
||||
);
|
||||
});
|
||||
|
||||
it('must have time in force set to GTC for limit order', function () {
|
||||
// 7002-SORD-031
|
||||
cy.getByTestId(toggleLimit).click();
|
||||
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
|
||||
'have.text',
|
||||
TIFlist.filter((item) => item.code === 'GTC')[0].text
|
||||
);
|
||||
});
|
||||
|
||||
it('selections should be remembered', () => {
|
||||
cy.getByTestId(orderTIFDropDown).select('TIME_IN_FORCE_GTT');
|
||||
cy.getByTestId(toggleMarket).click();
|
||||
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
|
||||
'have.text',
|
||||
TIFlist.filter((item) => item.code === 'IOC')[0].text
|
||||
);
|
||||
cy.getByTestId(orderTIFDropDown).select('TIME_IN_FORCE_FOK');
|
||||
cy.getByTestId(toggleLimit).click();
|
||||
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
|
||||
'have.text',
|
||||
TIFlist.filter((item) => item.code === 'GTT')[0].text
|
||||
);
|
||||
cy.getByTestId(toggleMarket).click();
|
||||
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
|
||||
'have.text',
|
||||
TIFlist.filter((item) => item.code === 'FOK')[0].text
|
||||
);
|
||||
});
|
||||
|
||||
describe('limit order', () => {
|
||||
before(() => {
|
||||
cy.getByTestId(toggleLimit).click();
|
||||
});
|
||||
const validTIF = TIFlist;
|
||||
validTIF.forEach((tif) => {
|
||||
// 7002-SORD-023
|
||||
// 7002-SORD-024
|
||||
// 7002-SORD-025
|
||||
// 7002-SORD-026
|
||||
// 7002-SORD-027
|
||||
// 7002-SORD-028
|
||||
|
||||
it(`must be able to select ${tif.code}`, function () {
|
||||
cy.getByTestId(orderTIFDropDown).select(tif.value);
|
||||
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
|
||||
'have.text',
|
||||
tif.text
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('market order', () => {
|
||||
before(() => {
|
||||
cy.getByTestId(toggleMarket).click();
|
||||
});
|
||||
|
||||
const validTIF = TIFlist.filter((tif) => ['FOK', 'IOC'].includes(tif.code));
|
||||
const invalidTIF = TIFlist.filter(
|
||||
(tif) => !['FOK', 'IOC'].includes(tif.code)
|
||||
);
|
||||
|
||||
validTIF.forEach((tif) => {
|
||||
// 7002-SORD-025
|
||||
// 7002-SORD-026
|
||||
|
||||
it(`must be able to select ${tif.code}`, function () {
|
||||
cy.getByTestId(orderTIFDropDown).select(tif.value);
|
||||
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
|
||||
'have.text',
|
||||
tif.text
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
invalidTIF.forEach((tif) => {
|
||||
// 7002-SORD-023
|
||||
// 7002-SORD-024
|
||||
// 7002-SORD-027
|
||||
// 7002-SORD-028
|
||||
it(`must not be able to select ${tif.code}`, function () {
|
||||
cy.getByTestId(orderTIFDropDown).should('not.contain', tif.text);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('post and reduce - market order', () => {
|
||||
before(() => {
|
||||
cy.getByTestId(toggleMarket).click();
|
||||
});
|
||||
|
||||
const validTIF = TIFlist.filter((tif) => ['FOK', 'IOC'].includes(tif.code));
|
||||
|
||||
validTIF.forEach((tif) => {
|
||||
// 7002-SORD-025
|
||||
// 7002-SORD-026
|
||||
|
||||
it(`post and reduce order market for ${tif.code}`, function () {
|
||||
// 7003-SORD-054
|
||||
// 7003-SORD-055
|
||||
// 7003-SORD-056
|
||||
// 7003-SORD-057
|
||||
|
||||
cy.getByTestId(orderTIFDropDown).select(tif.value);
|
||||
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
|
||||
'have.text',
|
||||
tif.text
|
||||
);
|
||||
cy.getByTestId(postOnly).should('be.disabled');
|
||||
cy.getByTestId(reduceOnly).should('be.enabled');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('post and reduce - limit order', () => {
|
||||
before(() => {
|
||||
cy.getByTestId(toggleLimit).click();
|
||||
});
|
||||
|
||||
const validTIFLimit = TIFlist.filter((tif) =>
|
||||
['GFA', 'GFN', 'GTC', 'GTT'].includes(tif.code)
|
||||
);
|
||||
|
||||
validTIFLimit.forEach((tif) => {
|
||||
it(`post and reduce order for limit ${tif.code}`, function () {
|
||||
// 7003-SORD-054
|
||||
// 7003-SORD-055
|
||||
// 7003-SORD-056
|
||||
// 7003-SORD-057
|
||||
cy.getByTestId(orderTIFDropDown).select(tif.value);
|
||||
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
|
||||
'have.text',
|
||||
tif.text
|
||||
);
|
||||
cy.getByTestId(postOnly).should('be.enabled');
|
||||
cy.getByTestId(reduceOnly).should('be.disabled');
|
||||
});
|
||||
});
|
||||
it(`can see explanation of what post only and reduce only is/does`, function () {
|
||||
// 7003-SORD-058
|
||||
cy.get('[for="post-only"]').should('have.text', 'Post only').realHover();
|
||||
cy.getByTestId(tooltipContent).should(
|
||||
'contain.text',
|
||||
`"Post only" will ensure the order is not filled immediately but is placed on the order book as a passive order. When the order is processed it is either stopped (if it would not be filled immediately), or placed in the order book as a passive order until the price taker matches with it.`
|
||||
);
|
||||
cy.get('[for="reduce-only"]')
|
||||
.should('have.text', 'Reduce only')
|
||||
.realHover();
|
||||
cy.getByTestId(tooltipContent).should(
|
||||
'contain.text',
|
||||
`"Reduce only" can be used only with non-persistent orders, such as "Fill or Kill" or "Immediate or Cancel".`
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
import { aliasGQLQuery } from '@vegaprotocol/cypress';
|
||||
import { partyAssetsQuery } from '@vegaprotocol/mock';
|
||||
|
||||
describe('Portfolio page', { tags: '@smoke' }, () => {
|
||||
beforeEach(() => {
|
||||
cy.mockGQL((req) => {
|
||||
aliasGQLQuery(req, 'PartyAssets', partyAssetsQuery());
|
||||
});
|
||||
cy.mockTradingPage();
|
||||
cy.mockSubscription();
|
||||
cy.setVegaWallet();
|
||||
});
|
||||
describe('Ledger entries', () => {
|
||||
it('Download form should be properly rendered', () => {
|
||||
// 7007-LEEN-001
|
||||
cy.visit('/#/portfolio');
|
||||
cy.getByTestId('"Ledger entries"').click();
|
||||
cy.getByTestId('tab-ledger-entries').within(($headers) => {
|
||||
cy.wrap($headers)
|
||||
.getByTestId('ledger-download-button')
|
||||
.should('be.visible');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,94 @@
|
||||
const colHeader = '.ag-header-cell-text';
|
||||
const colIdPrice = '[col-id=price]';
|
||||
const colIdSize = '[col-id=size]';
|
||||
const colIdCreatedAt = '[col-id=createdAt]';
|
||||
const tradesTab = 'Trades';
|
||||
const tradesTable = 'tab-trades';
|
||||
|
||||
describe('trades', { tags: '@smoke' }, () => {
|
||||
before(() => {
|
||||
cy.mockTradingPage();
|
||||
cy.mockSubscription();
|
||||
cy.setOnBoardingViewed();
|
||||
cy.intercept('POST', '/graphql', (req) => {
|
||||
if (req.body.operationName === 'Trades') {
|
||||
req.alias = '@Trades';
|
||||
}
|
||||
});
|
||||
cy.visit('/#/markets/market-0');
|
||||
cy.getByTestId(tradesTab).click();
|
||||
cy.wait('@Trades');
|
||||
});
|
||||
|
||||
it('show trades', () => {
|
||||
// 6005-THIS-001
|
||||
// 6005-THIS-002
|
||||
cy.getByTestId(tradesTab).should('be.visible');
|
||||
cy.getByTestId(tradesTable).should('be.visible');
|
||||
cy.getByTestId(tradesTable).should('not.be.empty');
|
||||
});
|
||||
|
||||
it('show trades prices', () => {
|
||||
// 6005-THIS-003
|
||||
cy.getByTestId(tradesTable)
|
||||
.get(`${colIdPrice} ${colHeader}`)
|
||||
.first()
|
||||
.should('have.text', 'Price');
|
||||
cy.getByTestId(tradesTable)
|
||||
.get(colIdPrice)
|
||||
.each(($tradePrice) => {
|
||||
cy.wrap($tradePrice).invoke('text').should('not.be.empty');
|
||||
});
|
||||
});
|
||||
|
||||
it('show trades sizes', () => {
|
||||
// 6005-THIS-004
|
||||
cy.getByTestId(tradesTable)
|
||||
.get(`${colIdSize} ${colHeader}`)
|
||||
.first()
|
||||
.should('have.text', 'Size');
|
||||
cy.getByTestId(tradesTable)
|
||||
.get(colIdSize)
|
||||
.each(($tradeSize) => {
|
||||
cy.wrap($tradeSize).invoke('text').should('not.be.empty');
|
||||
});
|
||||
});
|
||||
|
||||
it('show trades date and time', () => {
|
||||
// 6005-THIS-005
|
||||
cy.getByTestId(tradesTable) // order table shares identical col id
|
||||
.find(`${colIdCreatedAt} ${colHeader}`)
|
||||
.should('have.text', 'Created at');
|
||||
const dateTimeRegex = /(\d{1,2}):(\d{1,2}):(\d{1,2})/gm;
|
||||
cy.getByTestId(tradesTable)
|
||||
.get(`.ag-center-cols-container ${colIdCreatedAt}`)
|
||||
.each(($tradeDateTime) => {
|
||||
cy.wrap($tradeDateTime).invoke('text').should('match', dateTimeRegex);
|
||||
});
|
||||
});
|
||||
|
||||
it('trades are sorted descending by datetime', () => {
|
||||
// 6005-THIS-006
|
||||
const dateTimes: Date[] = [];
|
||||
cy.getByTestId(tradesTable)
|
||||
.find(colIdCreatedAt)
|
||||
.each(($tradeDateTime, index) => {
|
||||
if (index != 0) {
|
||||
//ignore header
|
||||
dateTimes.push(new Date($tradeDateTime.text()));
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
expect(dateTimes).to.deep.equal(
|
||||
dateTimes.sort((a, b) => b.getTime() - a.getTime())
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('copy price to deal ticket form', () => {
|
||||
// 6005-THIS-007
|
||||
cy.getByTestId('order-type-Limit').click();
|
||||
cy.get(colIdPrice).last().should('be.visible').click();
|
||||
cy.getByTestId('order-price').should('have.value', '171.16898');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,91 @@
|
||||
import { selectAsset } from '../support/helpers';
|
||||
|
||||
const amountField = 'input[name="amount"]';
|
||||
const amountShortName = 'input[name="amount"] + div + span.text-xs';
|
||||
const assetSelection = 'select-asset';
|
||||
const assetBalance = 'asset-balance';
|
||||
const assetOption = 'rich-select-option';
|
||||
const openTransferButton = 'open-transfer';
|
||||
const submitTransferBtn = '[type="submit"]';
|
||||
const toAddressField = '[name="toAddress"]';
|
||||
const transferForm = 'transfer-form';
|
||||
const ASSET_SEPOLIA_TBTC = 2;
|
||||
const collateralTab = 'Collateral';
|
||||
const toastCloseBtn = 'toast-close';
|
||||
const toastContent = 'toast-content';
|
||||
|
||||
describe('withdraw actions', { tags: '@smoke', testIsolation: true }, () => {
|
||||
beforeEach(() => {
|
||||
cy.mockWeb3Provider();
|
||||
cy.mockTradingPage();
|
||||
cy.mockSubscription();
|
||||
cy.setVegaWallet();
|
||||
|
||||
cy.visit('/#/portfolio');
|
||||
cy.getByTestId(collateralTab).click();
|
||||
cy.getByTestId(openTransferButton).click();
|
||||
|
||||
cy.wait('@Accounts');
|
||||
cy.wait('@Assets');
|
||||
cy.mockVegaWalletTransaction();
|
||||
});
|
||||
|
||||
it('key to key transfers by select key', () => {
|
||||
// 1003-TRAN-001
|
||||
// 1003-TRAN-006
|
||||
// 1003-TRAN-007
|
||||
// 1003-TRAN-008
|
||||
// 1003-TRAN-009
|
||||
// 1003-TRAN-010
|
||||
// 1003-TRAN-023
|
||||
cy.getByTestId(transferForm).should('be.visible');
|
||||
cy.getByTestId(transferForm).find(toAddressField).select(1);
|
||||
|
||||
cy.getByTestId(assetSelection).click();
|
||||
cy.getByTestId(assetOption);
|
||||
cy.getByTestId(assetBalance).should('not.be.empty');
|
||||
cy.getByTestId(assetOption).should('have.length.gt', 4);
|
||||
|
||||
let optionText: string;
|
||||
cy.getByTestId(assetOption)
|
||||
.eq(2)
|
||||
.invoke('text')
|
||||
.then((text: string) => {
|
||||
optionText = text;
|
||||
cy.getByTestId(assetOption).eq(2).click();
|
||||
cy.getByTestId(assetSelection).should('have.text', optionText);
|
||||
});
|
||||
|
||||
cy.getByTestId(transferForm)
|
||||
.find(amountField)
|
||||
.type('1', { delay: 100, force: true });
|
||||
|
||||
cy.getByTestId(transferForm).find(amountShortName).should('not.be.empty');
|
||||
|
||||
cy.getByTestId(transferForm).find(submitTransferBtn).click();
|
||||
cy.getByTestId(toastContent).should(
|
||||
'contain.text',
|
||||
'Awaiting confirmation'
|
||||
);
|
||||
cy.getByTestId(toastCloseBtn).click();
|
||||
});
|
||||
|
||||
it('key to key transfers by enter manual key', () => {
|
||||
//1003-TRAN-005
|
||||
cy.getByTestId(transferForm).should('be.visible');
|
||||
cy.contains('Enter manually').click();
|
||||
cy.getByTestId(transferForm)
|
||||
.find(toAddressField)
|
||||
.type('7f9cf07d3a9905b1a61a1069f7a758855da428bc0f4a97de87f48644bfc25535');
|
||||
selectAsset(ASSET_SEPOLIA_TBTC);
|
||||
cy.getByTestId(transferForm)
|
||||
.find(amountField)
|
||||
.type('1', { delay: 100, force: true });
|
||||
cy.getByTestId(transferForm).find(submitTransferBtn).click();
|
||||
cy.getByTestId(toastContent).should(
|
||||
'contain.text',
|
||||
'Awaiting confirmation'
|
||||
);
|
||||
cy.getByTestId(toastCloseBtn).click();
|
||||
});
|
||||
});
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
assetQuery,
|
||||
assetsQuery,
|
||||
candlesQuery,
|
||||
chainIdQuery,
|
||||
chartQuery,
|
||||
depositsQuery,
|
||||
estimateFeesQuery,
|
||||
@@ -24,6 +25,7 @@ import {
|
||||
estimatePositionQuery,
|
||||
positionsQuery,
|
||||
proposalListQuery,
|
||||
statisticsQuery,
|
||||
tradesQuery,
|
||||
withdrawalsQuery,
|
||||
protocolUpgradeProposalsQuery,
|
||||
@@ -89,6 +91,8 @@ const mockTradingPage = (
|
||||
tradingMode?: Schema.MarketTradingMode,
|
||||
trigger?: Schema.AuctionTrigger
|
||||
) => {
|
||||
aliasGQLQuery(req, 'ChainId', chainIdQuery());
|
||||
aliasGQLQuery(req, 'NodeCheck', statisticsQuery());
|
||||
aliasGQLQuery(req, 'NodeGuard', nodeGuardQuery());
|
||||
aliasGQLQuery(
|
||||
req,
|
||||
@@ -214,7 +218,6 @@ export const addMockTradingPage = () => {
|
||||
trigger,
|
||||
oracleStatus
|
||||
) => {
|
||||
cy.mockChainId();
|
||||
cy.mockGQL((req) => {
|
||||
mockTradingPage(req, state, tradingMode, trigger);
|
||||
});
|
||||
|
||||
@@ -16,7 +16,6 @@ NX_VEGA_CONSOLE_URL=https://console.vega.xyz
|
||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-mainnet/codfcglpplgmmlokgilfkpcjnmkbfiel
|
||||
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_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
|
||||
@@ -16,7 +16,7 @@ NX_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports
|
||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||
|
||||
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
|
||||
@@ -17,7 +17,6 @@ NX_VEGA_CONSOLE_URL=https://console.fairground.wtf
|
||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
import MarketPage from '../market';
|
||||
|
||||
export const ClosedMarketPage = () => {
|
||||
return <MarketPage closed />;
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
export { ClosedMarketPage as default } from './closed-market';
|
||||
@@ -1,10 +1,9 @@
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||
import { DocsLinks, useEnvironment } from '@vegaprotocol/environment';
|
||||
import { ButtonLink, ExternalLink, Link } from '@vegaprotocol/ui-toolkit';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { ButtonLink, Link } from '@vegaprotocol/ui-toolkit';
|
||||
import { MarketProposalNotification } from '@vegaprotocol/proposals';
|
||||
import type { Market } from '@vegaprotocol/markets';
|
||||
import {
|
||||
addDecimalsFormatNumber,
|
||||
fromNanoSeconds,
|
||||
getExpiryDate,
|
||||
getMarketExpiryDate,
|
||||
@@ -15,12 +14,9 @@ import {
|
||||
Last24hVolume,
|
||||
getAsset,
|
||||
getDataSourceSpecForSettlementSchedule,
|
||||
isMarketInAuction,
|
||||
marketInfoProvider,
|
||||
useFundingPeriodsQuery,
|
||||
useFundingRate,
|
||||
useMarketTradingMode,
|
||||
useExternalTwap,
|
||||
} from '@vegaprotocol/markets';
|
||||
import { MarketState as State } from '@vegaprotocol/types';
|
||||
import { HeaderStat } from '../../components/header';
|
||||
@@ -30,7 +26,6 @@ import { MarketState } from '../../components/market-state';
|
||||
import { MarketLiquiditySupplied } from '../../components/liquidity-supplied';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||
import { PriceCell } from '@vegaprotocol/datagrid';
|
||||
|
||||
interface MarketHeaderStatsProps {
|
||||
market: Market;
|
||||
@@ -43,8 +38,34 @@ export const MarketHeaderStats = ({ market }: MarketHeaderStatsProps) => {
|
||||
const asset = getAsset(market);
|
||||
|
||||
return (
|
||||
<div className="flex gap-8">
|
||||
<HeaderStat heading={t('Mark Price')} testId="market-price">
|
||||
<>
|
||||
{market.tradableInstrument.instrument.product.__typename === 'Future' && (
|
||||
<HeaderStat
|
||||
heading={t('Expiry')}
|
||||
description={
|
||||
<ExpiryTooltipContent
|
||||
market={market}
|
||||
explorerUrl={VEGA_EXPLORER_URL}
|
||||
/>
|
||||
}
|
||||
testId="market-expiry"
|
||||
>
|
||||
<ExpiryLabel market={market} />
|
||||
</HeaderStat>
|
||||
)}
|
||||
{market.tradableInstrument.instrument.product.__typename ===
|
||||
'Perpetual' && (
|
||||
<HeaderStat
|
||||
heading={`${t('Funding')} / ${t('Countdown')}`}
|
||||
testId="market-funding"
|
||||
>
|
||||
<div className="flex justify-between gap-2">
|
||||
<FundingRate marketId={market.id} />
|
||||
<FundingCountdown marketId={market.id} />
|
||||
</div>
|
||||
</HeaderStat>
|
||||
)}
|
||||
<HeaderStat heading={t('Price')} testId="market-price">
|
||||
<MarketMarkPrice
|
||||
marketId={market.id}
|
||||
decimalPlaces={market.decimalPlaces}
|
||||
@@ -87,64 +108,8 @@ export const MarketHeaderStats = ({ market }: MarketHeaderStatsProps) => {
|
||||
marketId={market.id}
|
||||
assetDecimals={asset?.decimals || 0}
|
||||
/>
|
||||
{market.tradableInstrument.instrument.product.__typename === 'Future' && (
|
||||
<HeaderStat
|
||||
heading={t('Expiry')}
|
||||
description={
|
||||
<ExpiryTooltipContent
|
||||
market={market}
|
||||
explorerUrl={VEGA_EXPLORER_URL}
|
||||
/>
|
||||
}
|
||||
testId="market-expiry"
|
||||
>
|
||||
<ExpiryLabel market={market} />
|
||||
</HeaderStat>
|
||||
)}
|
||||
{market.tradableInstrument.instrument.product.__typename ===
|
||||
'Perpetual' && (
|
||||
<HeaderStat
|
||||
heading={`${t('Funding Rate')} / ${t('Countdown')}`}
|
||||
testId="market-funding"
|
||||
>
|
||||
<div className="flex justify-between gap-2">
|
||||
<FundingRate marketId={market.id} />
|
||||
<FundingCountdown marketId={market.id} />
|
||||
</div>
|
||||
</HeaderStat>
|
||||
)}
|
||||
{market.tradableInstrument.instrument.product.__typename ===
|
||||
'Perpetual' && (
|
||||
<HeaderStat
|
||||
heading={`${t('Index Price')}`}
|
||||
description={
|
||||
<div className="p1">
|
||||
{t(
|
||||
'The external time weighted average price (TWAP) received from the data source defined in the data sourcing specification.'
|
||||
)}
|
||||
{DocsLinks && (
|
||||
<ExternalLink
|
||||
href={DocsLinks.ETH_DATA_SOURCES}
|
||||
className="mt-2"
|
||||
>
|
||||
{t('Find out more')}
|
||||
</ExternalLink>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
testId="index-price"
|
||||
>
|
||||
<IndexPrice
|
||||
marketId={market.id}
|
||||
decimalPlaces={
|
||||
market.tradableInstrument.instrument.product.settlementAsset
|
||||
.decimals
|
||||
}
|
||||
/>
|
||||
</HeaderStat>
|
||||
)}
|
||||
<MarketProposalNotification marketId={market.id} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -161,24 +126,6 @@ export const FundingRate = ({ marketId }: { marketId: string }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export const IndexPrice = ({
|
||||
marketId,
|
||||
decimalPlaces,
|
||||
}: {
|
||||
marketId: string;
|
||||
decimalPlaces?: number;
|
||||
}) => {
|
||||
const { data: externalTwap } = useExternalTwap(marketId);
|
||||
return externalTwap && decimalPlaces ? (
|
||||
<PriceCell
|
||||
value={Number(externalTwap)}
|
||||
valueFormatted={addDecimalsFormatNumber(externalTwap, decimalPlaces)}
|
||||
/>
|
||||
) : (
|
||||
'-'
|
||||
);
|
||||
};
|
||||
|
||||
const useNow = () => {
|
||||
const [now, setNow] = useState(Date.now());
|
||||
useEffect(() => {
|
||||
@@ -189,11 +136,9 @@ const useNow = () => {
|
||||
};
|
||||
|
||||
const useEvery = (marketId: string) => {
|
||||
const { data: marketTradingMode } = useMarketTradingMode(marketId);
|
||||
const { data: marketInfo } = useDataProvider({
|
||||
dataProvider: marketInfoProvider,
|
||||
variables: { marketId },
|
||||
skip: !marketTradingMode || isMarketInAuction(marketTradingMode),
|
||||
});
|
||||
let every: number | undefined = undefined;
|
||||
const sourceType =
|
||||
|
||||
@@ -3,16 +3,15 @@ import { addDecimalsFormatNumber, titlefy } from '@vegaprotocol/utils';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { useScreenDimensions } from '@vegaprotocol/react-helpers';
|
||||
import { useThrottledDataProvider } from '@vegaprotocol/data-provider';
|
||||
import { ExternalLink, Loader, Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { AsyncRenderer, ExternalLink, Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { getAsset, marketDataProvider, useMarket } from '@vegaprotocol/markets';
|
||||
import { useGlobalStore, usePageTitleStore } from '../../stores';
|
||||
import { TradeGrid } from './trade-grid';
|
||||
import { TradePanels } from './trade-panels';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { Links, Routes } from '../../lib/links';
|
||||
import { Links } from '../../lib/links';
|
||||
import { ViewType, useSidebar } from '../../components/sidebar';
|
||||
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
|
||||
import { MarketState } from '@vegaprotocol/types';
|
||||
|
||||
const calculatePrice = (markPrice?: string, decimalPlaces?: number) => {
|
||||
return markPrice && decimalPlaces
|
||||
@@ -57,7 +56,7 @@ const TitleUpdater = ({
|
||||
return null;
|
||||
};
|
||||
|
||||
export const MarketPage = ({ closed }: { closed?: boolean }) => {
|
||||
export const MarketPage = () => {
|
||||
const { marketId } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const currentRouteId = useGetCurrentRouteId();
|
||||
@@ -68,36 +67,19 @@ export const MarketPage = ({ closed }: { closed?: boolean }) => {
|
||||
const update = useGlobalStore((store) => store.update);
|
||||
const lastMarketId = useGlobalStore((store) => store.marketId);
|
||||
|
||||
const { data, loading } = useMarket(marketId);
|
||||
const { data, error, loading } = useMarket(marketId);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
data?.state &&
|
||||
[
|
||||
MarketState.STATE_SETTLED,
|
||||
MarketState.STATE_TRADING_TERMINATED,
|
||||
].includes(data.state) &&
|
||||
currentRouteId !== Routes.CLOSED_MARKETS &&
|
||||
marketId
|
||||
) {
|
||||
navigate(Links.CLOSED_MARKETS(marketId));
|
||||
}
|
||||
}, [data?.state, currentRouteId, navigate, marketId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (data?.id && data.id !== lastMarketId && !closed) {
|
||||
if (data?.id && data.id !== lastMarketId) {
|
||||
update({ marketId: data.id });
|
||||
}
|
||||
}, [update, lastMarketId, data?.id, closed]);
|
||||
}, [update, lastMarketId, data?.id]);
|
||||
|
||||
useEffect(() => {
|
||||
if (largeScreen && view === undefined) {
|
||||
setViews(
|
||||
{ type: closed ? ViewType.Info : ViewType.Order },
|
||||
currentRouteId
|
||||
);
|
||||
setViews({ type: ViewType.Order }, currentRouteId);
|
||||
}
|
||||
}, [setViews, view, currentRouteId, largeScreen, closed]);
|
||||
}, [setViews, view, currentRouteId, largeScreen]);
|
||||
|
||||
const pinnedAsset = data && getAsset(data);
|
||||
|
||||
@@ -110,15 +92,7 @@ export const MarketPage = ({ closed }: { closed?: boolean }) => {
|
||||
}
|
||||
}, [largeScreen, data, pinnedAsset]);
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<Splash>
|
||||
<Loader />
|
||||
</Splash>
|
||||
);
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
if (!data && marketId) {
|
||||
return (
|
||||
<Splash>
|
||||
<span className="flex flex-col items-center gap-2">
|
||||
@@ -128,7 +102,7 @@ export const MarketPage = ({ closed }: { closed?: boolean }) => {
|
||||
<p className="justify-center text-sm">
|
||||
{t(`Please choose another market from the`)}{' '}
|
||||
<ExternalLink onClick={() => navigate(Links.MARKETS())}>
|
||||
{t('market list')}
|
||||
market list
|
||||
</ExternalLink>
|
||||
</p>
|
||||
</span>
|
||||
@@ -137,13 +111,18 @@ export const MarketPage = ({ closed }: { closed?: boolean }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<AsyncRenderer
|
||||
loading={loading}
|
||||
error={error}
|
||||
data={data || undefined}
|
||||
noDataCondition={(data) => false}
|
||||
>
|
||||
<TitleUpdater
|
||||
marketId={data?.id}
|
||||
marketName={data?.tradableInstrument.instrument.name}
|
||||
decimalPlaces={data?.decimalPlaces}
|
||||
/>
|
||||
{tradeView}
|
||||
</>
|
||||
</AsyncRenderer>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -18,7 +18,6 @@ import { TradingViews } from './trade-views';
|
||||
import {
|
||||
MarketSuccessorBanner,
|
||||
MarketSuccessorProposalBanner,
|
||||
MarketTerminationBanner,
|
||||
} from '../../components/market-banner';
|
||||
import { FLAGS } from '@vegaprotocol/environment';
|
||||
|
||||
@@ -137,10 +136,7 @@ const MainGrid = memo(
|
||||
</Tab>
|
||||
) : null}
|
||||
<Tab id="fills" name={t('Fills')}>
|
||||
<TradingViews.fills.component />
|
||||
</Tab>
|
||||
<Tab id="funding-payments" name={t('Funding payments')}>
|
||||
<TradingViews.fundingPayments.component />
|
||||
<TradingViews.fills.component marketId={marketId} />
|
||||
</Tab>
|
||||
<Tab
|
||||
id="accounts"
|
||||
@@ -173,7 +169,6 @@ export const TradeGrid = ({ market, pinnedAsset }: TradeGridProps) => {
|
||||
<MarketSuccessorProposalBanner marketId={market?.id} />
|
||||
</>
|
||||
)}
|
||||
<MarketTerminationBanner market={market} />
|
||||
<OracleBanner marketId={market?.id || ''} />
|
||||
</div>
|
||||
<div className="min-h-0 p-0.5">
|
||||
|
||||
@@ -11,7 +11,6 @@ import classNames from 'classnames';
|
||||
import {
|
||||
MarketSuccessorBanner,
|
||||
MarketSuccessorProposalBanner,
|
||||
MarketTerminationBanner,
|
||||
} from '../../components/market-banner';
|
||||
import { FLAGS } from '@vegaprotocol/environment';
|
||||
|
||||
@@ -60,7 +59,6 @@ export const TradePanels = ({ market, pinnedAsset }: TradePanelsProps) => {
|
||||
<MarketSuccessorProposalBanner marketId={market?.id} />
|
||||
</>
|
||||
)}
|
||||
<MarketTerminationBanner market={market} />
|
||||
<OracleBanner marketId={market?.id || ''} />
|
||||
</div>
|
||||
<div>{renderMenu()}</div>
|
||||
|
||||
@@ -14,7 +14,6 @@ import { PositionsContainer } from '../../components/positions-container';
|
||||
import { AccountsContainer } from '../../components/accounts-container';
|
||||
import { LiquidityContainer } from '../../components/liquidity-container';
|
||||
import { FundingContainer } from '../../components/funding-container';
|
||||
import { FundingPaymentsContainer } from '../../components/funding-payments-container';
|
||||
import type { OrderContainerProps } from '../../components/orders-container';
|
||||
import { OrdersContainer } from '../../components/orders-container';
|
||||
import { StopOrdersContainer } from '../../components/stop-orders-container';
|
||||
@@ -56,10 +55,6 @@ export const TradingViews = {
|
||||
label: 'Funding',
|
||||
component: requiresMarket(FundingContainer),
|
||||
},
|
||||
fundingPayments: {
|
||||
label: 'Funding Payments',
|
||||
component: FundingPaymentsContainer,
|
||||
},
|
||||
orderbook: {
|
||||
label: 'Orderbook',
|
||||
component: requiresMarket(OrderbookContainer),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { act, render, screen, waitFor, within } from '@testing-library/react';
|
||||
import { act, render, screen, within } from '@testing-library/react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { Closed } from './closed';
|
||||
import { MarketStateMapping, PropertyKeyType } from '@vegaprotocol/types';
|
||||
@@ -300,11 +300,9 @@ describe('Closed', () => {
|
||||
].includes(m.node.state);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
// check rows length is correct
|
||||
const rows = container.getAllByRole('row');
|
||||
expect(rows).toHaveLength(expectedRows.length);
|
||||
});
|
||||
// check rows length is correct
|
||||
const rows = container.getAllByRole('row');
|
||||
expect(rows).toHaveLength(expectedRows.length);
|
||||
|
||||
// check that only included ids are shown
|
||||
const cells = screen
|
||||
|
||||
@@ -22,8 +22,6 @@ import { SettlementPriceCell } from './settlement-price-cell';
|
||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||
import { MarketCodeCell } from './market-code-cell';
|
||||
import { MarketActionsDropdown } from './market-table-actions';
|
||||
import type { CellClickedEvent } from 'ag-grid-community';
|
||||
import { useClosedMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
|
||||
|
||||
type SettlementAsset = Pick<
|
||||
Asset,
|
||||
@@ -127,7 +125,6 @@ const ClosedMarketsDataGrid = ({
|
||||
rowData: Row[];
|
||||
error: Error | undefined;
|
||||
}) => {
|
||||
const handleOnSelect = useClosedMarketClickHandler();
|
||||
const openAssetDialog = useAssetDetailsDialogStore((store) => store.open);
|
||||
|
||||
const colDefs = useMemo(() => {
|
||||
@@ -284,27 +281,6 @@ const ClosedMarketsDataGrid = ({
|
||||
overlayNoRowsTemplate={error ? error.message : t('No markets')}
|
||||
components={components}
|
||||
rowHeight={45}
|
||||
onCellClicked={({ data, column, event }: CellClickedEvent<Row>) => {
|
||||
if (!data) return;
|
||||
|
||||
// prevent navigating to the market page if any of the below cells are clicked
|
||||
// event.preventDefault or event.stopPropagation dont seem to apply for aggird
|
||||
const colId = column.getColId();
|
||||
|
||||
if (
|
||||
[
|
||||
'settlementDate',
|
||||
'settlementDataOracleId',
|
||||
'settlementAsset',
|
||||
'market-actions',
|
||||
].includes(colId)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// @ts-ignore metaKey exists
|
||||
handleOnSelect(data.id, event ? event.metaKey : false);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -9,9 +9,7 @@ import { usePageTitleStore } from '../../stores';
|
||||
import { AccountsContainer } from '../../components/accounts-container';
|
||||
import { DepositsContainer } from '../../components/deposits-container';
|
||||
import { FillsContainer } from '../../components/fills-container';
|
||||
import { FundingPaymentsContainer } from '../../components/funding-payments-container';
|
||||
import { PositionsContainer } from '../../components/positions-container';
|
||||
import { PositionsMenu } from '../../components/positions-menu';
|
||||
import { WithdrawalsContainer } from '../../components/withdrawals-container';
|
||||
import { OrdersContainer } from '../../components/orders-container';
|
||||
import { LedgerContainer } from '../../components/ledger-container';
|
||||
@@ -70,11 +68,7 @@ export const Portfolio = () => {
|
||||
<Tab id="account-history" name={t('Account history')}>
|
||||
<AccountHistoryContainer />
|
||||
</Tab>
|
||||
<Tab
|
||||
id="positions"
|
||||
name={t('Positions')}
|
||||
menu={<PositionsMenu />}
|
||||
>
|
||||
<Tab id="positions" name={t('Positions')}>
|
||||
<PositionsContainer allKeys />
|
||||
</Tab>
|
||||
<Tab id="orders" name={t('Orders')}>
|
||||
@@ -83,9 +77,6 @@ export const Portfolio = () => {
|
||||
<Tab id="fills" name={t('Fills')}>
|
||||
<FillsContainer />
|
||||
</Tab>
|
||||
<Tab id="funding-payments" name={t('Funding payments')}>
|
||||
<FundingPaymentsContainer />
|
||||
</Tab>
|
||||
<Tab id="ledger-entries" name={t('Ledger entries')}>
|
||||
<LedgerContainer />
|
||||
</Tab>
|
||||
|
||||
@@ -10,10 +10,12 @@ import classNames from 'classnames';
|
||||
import { Navigate, useSearchParams } from 'react-router-dom';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { Button } from './buttons';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import {
|
||||
useTransactionEventSubscription,
|
||||
useVegaWallet,
|
||||
} from '@vegaprotocol/wallet';
|
||||
import { useReferral } from './hooks/use-referral';
|
||||
import { Routes } from '../../lib/links';
|
||||
import { useTransactionEventSubscription } from '@vegaprotocol/web3';
|
||||
|
||||
export const ApplyCodeForm = () => {
|
||||
const [status, setStatus] = useState<
|
||||
|
||||
+8
-4
@@ -1,7 +1,6 @@
|
||||
import type { InMemoryCacheConfig } from '@apollo/client';
|
||||
import {
|
||||
AppFailure,
|
||||
AppLoader,
|
||||
DocsLinks,
|
||||
NetworkLoader,
|
||||
NodeGuard,
|
||||
@@ -10,10 +9,15 @@ import {
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { MaintenancePage } from '@vegaprotocol/ui-toolkit';
|
||||
import { VegaWalletProvider } from '@vegaprotocol/wallet';
|
||||
import dynamic from 'next/dynamic';
|
||||
import type { ReactNode } from 'react';
|
||||
import { Web3Provider } from './web3-provider';
|
||||
|
||||
export const Bootstrapper = ({ children }: { children: ReactNode }) => {
|
||||
export const DynamicLoader = dynamic(() => import('../preloader/preloader'), {
|
||||
loading: () => <>Loading...</>,
|
||||
});
|
||||
|
||||
export const AppLoader = ({ children }: { children: ReactNode }) => {
|
||||
const {
|
||||
error,
|
||||
VEGA_URL,
|
||||
@@ -43,13 +47,13 @@ export const Bootstrapper = ({ children }: { children: ReactNode }) => {
|
||||
return (
|
||||
<NetworkLoader
|
||||
cache={cacheConfig}
|
||||
skeleton={<AppLoader />}
|
||||
skeleton={<DynamicLoader />}
|
||||
failure={
|
||||
<AppFailure title={t('Could not initialize app')} error={error} />
|
||||
}
|
||||
>
|
||||
<NodeGuard
|
||||
skeleton={<AppLoader />}
|
||||
skeleton={<DynamicLoader />}
|
||||
failure={<AppFailure title={t(`Node: ${VEGA_URL} is unsuitable`)} />}
|
||||
>
|
||||
<Web3Provider>
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
export * from './bootstrapper';
|
||||
export * from './app-loader';
|
||||
export * from './web3-provider';
|
||||
@@ -9,7 +9,7 @@ import type { DataGridSlice } from '../../stores/datagrid-store-slice';
|
||||
import { createDataGridSlice } from '../../stores/datagrid-store-slice';
|
||||
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
|
||||
|
||||
export const FillsContainer = () => {
|
||||
export const FillsContainer = ({ marketId }: { marketId?: string }) => {
|
||||
const onMarketClick = useMarketClickHandler(true);
|
||||
const { pubKey } = useVegaWallet();
|
||||
|
||||
@@ -31,6 +31,7 @@ export const FillsContainer = () => {
|
||||
return (
|
||||
<FillsManager
|
||||
partyId={pubKey}
|
||||
marketId={marketId}
|
||||
onMarketClick={onMarketClick}
|
||||
gridProps={gridStoreCallbacks}
|
||||
/>
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { FundingPaymentsManager } from '@vegaprotocol/funding-payments';
|
||||
import { create } from 'zustand';
|
||||
import { persist } from 'zustand/middleware';
|
||||
import { useDataGridEvents } from '@vegaprotocol/datagrid';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import type { DataGridSlice } from '../../stores/datagrid-store-slice';
|
||||
import { createDataGridSlice } from '../../stores/datagrid-store-slice';
|
||||
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
|
||||
|
||||
export const FundingPaymentsContainer = () => {
|
||||
const onMarketClick = useMarketClickHandler(true);
|
||||
const { pubKey } = useVegaWallet();
|
||||
|
||||
const gridStore = useFundingPaymentsStore((store) => store.gridStore);
|
||||
const updateGridStore = useFundingPaymentsStore(
|
||||
(store) => store.updateGridStore
|
||||
);
|
||||
|
||||
const gridStoreCallbacks = useDataGridEvents(gridStore, (colState) => {
|
||||
updateGridStore(colState);
|
||||
});
|
||||
|
||||
if (!pubKey) {
|
||||
return (
|
||||
<Splash>
|
||||
<p>{t('Please connect Vega wallet')}</p>
|
||||
</Splash>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<FundingPaymentsManager
|
||||
partyId={pubKey}
|
||||
onMarketClick={onMarketClick}
|
||||
gridProps={gridStoreCallbacks}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const useFundingPaymentsStore = create<DataGridSlice>()(
|
||||
persist(createDataGridSlice, {
|
||||
name: 'vega_funding_payments_store',
|
||||
})
|
||||
);
|
||||
@@ -1 +0,0 @@
|
||||
export * from './funding-payments-container';
|
||||
@@ -23,10 +23,6 @@ export const LayoutWithSidebar = () => {
|
||||
<div className="col-span-full">
|
||||
<Routes>
|
||||
<Route path="markets/:marketId" element={<MarketHeader />} />
|
||||
<Route
|
||||
path="markets/all/closed/:marketId"
|
||||
element={<MarketHeader />}
|
||||
/>
|
||||
<Route path="liquidity/:marketId" element={<LiquidityHeader />} />
|
||||
</Routes>
|
||||
</div>
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
export * from './market-successor-banner';
|
||||
export * from './market-successor-proposal-banner';
|
||||
export * from './market-termination-banner';
|
||||
|
||||
@@ -3,17 +3,12 @@ import type { SingleExecutionResult } from '@apollo/client';
|
||||
import type { MockedResponse } from '@apollo/react-testing';
|
||||
import { MockedProvider } from '@apollo/react-testing';
|
||||
import { MarketSuccessorProposalBanner } from './market-successor-proposal-banner';
|
||||
import type { MarketViewProposalsQuery } from '@vegaprotocol/proposals';
|
||||
import { MarketViewProposalsDocument } from '@vegaprotocol/proposals';
|
||||
import * as Types from '@vegaprotocol/types';
|
||||
import type { SuccessorProposalsListQuery } from '@vegaprotocol/proposals';
|
||||
import { SuccessorProposalsListDocument } from '@vegaprotocol/proposals';
|
||||
|
||||
const marketProposalMock: MockedResponse<MarketViewProposalsQuery> = {
|
||||
const marketProposalMock: MockedResponse<SuccessorProposalsListQuery> = {
|
||||
request: {
|
||||
query: MarketViewProposalsDocument,
|
||||
variables: {
|
||||
inState: Types.ProposalState.STATE_OPEN,
|
||||
proposalType: Types.ProposalType.TYPE_NEW_MARKET,
|
||||
},
|
||||
query: SuccessorProposalsListDocument,
|
||||
},
|
||||
result: {
|
||||
data: {
|
||||
@@ -23,11 +18,8 @@ const marketProposalMock: MockedResponse<MarketViewProposalsQuery> = {
|
||||
node: {
|
||||
__typename: 'Proposal',
|
||||
id: 'proposal-1',
|
||||
state: Types.ProposalState.STATE_OPEN,
|
||||
terms: {
|
||||
__typename: 'ProposalTerms',
|
||||
closingDatetime: '2023-09-27',
|
||||
enactmentDatetime: '2023-09-28',
|
||||
change: {
|
||||
__typename: 'NewMarket',
|
||||
instrument: {
|
||||
@@ -74,13 +66,12 @@ describe('MarketSuccessorProposalBanner', () => {
|
||||
proposalsConnection: {
|
||||
edges: [
|
||||
...((
|
||||
marketProposalMock?.result as SingleExecutionResult<MarketViewProposalsQuery>
|
||||
marketProposalMock?.result as SingleExecutionResult<SuccessorProposalsListQuery>
|
||||
)?.data?.proposalsConnection?.edges ?? []),
|
||||
{
|
||||
node: {
|
||||
__typename: 'Proposal',
|
||||
id: 'proposal-2',
|
||||
state: Types.ProposalState.STATE_OPEN,
|
||||
terms: {
|
||||
__typename: 'ProposalTerms',
|
||||
change: {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { Fragment, useState } from 'react';
|
||||
import type { NewMarketSuccessorFieldsFragment } from '@vegaprotocol/proposals';
|
||||
import { useMarketViewProposals } from '@vegaprotocol/proposals';
|
||||
import type {
|
||||
SuccessorProposalListFieldsFragment,
|
||||
NewMarketSuccessorFieldsFragment,
|
||||
} from '@vegaprotocol/proposals';
|
||||
import { useSuccessorProposalsListQuery } from '@vegaprotocol/proposals';
|
||||
import {
|
||||
ExternalLink,
|
||||
Intent,
|
||||
@@ -8,33 +11,23 @@ import {
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { DApp, TOKEN_PROPOSAL, useLinks } from '@vegaprotocol/environment';
|
||||
import * as Types from '@vegaprotocol/types';
|
||||
|
||||
export const MarketSuccessorProposalBanner = ({
|
||||
marketId,
|
||||
}: {
|
||||
marketId?: string;
|
||||
}) => {
|
||||
const proposals = useMarketViewProposals({
|
||||
const { data: proposals } = useSuccessorProposalsListQuery({
|
||||
skip: !marketId,
|
||||
inState: Types.ProposalState.STATE_OPEN,
|
||||
proposalType: Types.ProposalType.TYPE_NEW_MARKET,
|
||||
typename: 'NewMarket',
|
||||
});
|
||||
|
||||
const successors =
|
||||
proposals?.filter((item) => {
|
||||
if (item.terms.change.__typename === 'NewMarket') {
|
||||
const newMarket = item.terms.change;
|
||||
if (
|
||||
newMarket.successorConfiguration?.parentMarketId === marketId &&
|
||||
item.state === Types.ProposalState.STATE_OPEN
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}) ?? [];
|
||||
proposals?.proposalsConnection?.edges
|
||||
?.map((item) => item?.node as SuccessorProposalListFieldsFragment)
|
||||
.filter(
|
||||
(item: SuccessorProposalListFieldsFragment) =>
|
||||
(item.terms?.change as NewMarketSuccessorFieldsFragment)
|
||||
?.successorConfiguration?.parentMarketId === marketId
|
||||
) ?? [];
|
||||
const [visible, setVisible] = useState(true);
|
||||
const tokenLink = useLinks(DApp.Governance);
|
||||
if (visible && successors.length) {
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
import { render, screen, waitFor } from '@testing-library/react';
|
||||
import * as Types from '@vegaprotocol/types';
|
||||
import type { MockedResponse } from '@apollo/client/testing';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import type { MarketViewProposalsQuery } from '@vegaprotocol/proposals';
|
||||
import { MarketViewProposalsDocument } from '@vegaprotocol/proposals';
|
||||
import type { Market } from '@vegaprotocol/markets';
|
||||
import { MarketTerminationBanner } from './market-termination-banner';
|
||||
|
||||
const marketMock = {
|
||||
id: 'market-1',
|
||||
decimalPlaces: 3,
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
quoteName: 'tDAI',
|
||||
},
|
||||
},
|
||||
},
|
||||
} as Market;
|
||||
|
||||
const proposalMock: MockedResponse<MarketViewProposalsQuery> = {
|
||||
request: {
|
||||
query: MarketViewProposalsDocument,
|
||||
variables: { inState: Types.ProposalState.STATE_PASSED },
|
||||
},
|
||||
result: {
|
||||
data: {
|
||||
proposalsConnection: {
|
||||
edges: [
|
||||
{
|
||||
node: {
|
||||
id: 'first-id',
|
||||
state: Types.ProposalState.STATE_PASSED,
|
||||
terms: {
|
||||
closingDatetime: '2023-09-27T11:48:18Z',
|
||||
enactmentDatetime: '2023-09-30T11:48:18',
|
||||
change: {
|
||||
__typename: 'UpdateMarketState',
|
||||
updateType:
|
||||
Types.MarketUpdateType.MARKET_STATE_UPDATE_TYPE_TERMINATE,
|
||||
price: '',
|
||||
market: {
|
||||
id: 'market-1',
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
name: 'Market one name',
|
||||
code: 'Market one',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
node: {
|
||||
id: 'second-id',
|
||||
state: Types.ProposalState.STATE_PASSED,
|
||||
terms: {
|
||||
closingDatetime: '2023-09-27T11:48:18Z',
|
||||
enactmentDatetime: '2023-10-01T11:48:18',
|
||||
change: {
|
||||
__typename: 'UpdateMarketState',
|
||||
updateType:
|
||||
Types.MarketUpdateType.MARKET_STATE_UPDATE_TYPE_TERMINATE,
|
||||
price: '',
|
||||
market: {
|
||||
id: 'market-2',
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
name: 'Market two name',
|
||||
code: 'Market two',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const mocks: MockedResponse[] = [proposalMock];
|
||||
|
||||
describe('MarketTerminationBanner', () => {
|
||||
beforeAll(() => {
|
||||
jest.useFakeTimers().setSystemTime(new Date('2023-09-28T10:10:10.000Z'));
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it('should be properly rendered', async () => {
|
||||
const { container } = render(
|
||||
<MockedProvider mocks={mocks}>
|
||||
<MarketTerminationBanner market={marketMock} />
|
||||
</MockedProvider>
|
||||
);
|
||||
await waitFor(() => {
|
||||
expect(container).not.toBeEmptyDOMElement();
|
||||
});
|
||||
expect(
|
||||
screen.getByTestId('termination-warning-banner-market-1')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -1,81 +0,0 @@
|
||||
import { useState } from 'react';
|
||||
import { format, formatDuration, intervalToDuration } from 'date-fns';
|
||||
import { Intent, NotificationBanner } from '@vegaprotocol/ui-toolkit';
|
||||
import { useMarketViewProposals } from '@vegaprotocol/proposals';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import * as Types from '@vegaprotocol/types';
|
||||
import type { Market } from '@vegaprotocol/markets';
|
||||
import { getQuoteName } from '@vegaprotocol/markets';
|
||||
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
|
||||
|
||||
export const MarketTerminationBanner = ({
|
||||
market,
|
||||
}: {
|
||||
market: Market | null;
|
||||
}) => {
|
||||
const [visible, setVisible] = useState(true);
|
||||
const skip = !market || !visible;
|
||||
const proposalsData = useMarketViewProposals({
|
||||
skip,
|
||||
inState: Types.ProposalState.STATE_PASSED,
|
||||
typename: 'UpdateMarketState',
|
||||
});
|
||||
|
||||
if (!market) return null;
|
||||
const marketFound = (proposalsData || []).find(
|
||||
(item) =>
|
||||
item.terms.change.__typename === 'UpdateMarketState' &&
|
||||
item.terms.change.market.id === market.id &&
|
||||
item.terms.change.updateType ===
|
||||
Types.MarketUpdateType.MARKET_STATE_UPDATE_TYPE_TERMINATE &&
|
||||
item.state === Types.ProposalState.STATE_PASSED // subscription doesn't have state parameter
|
||||
);
|
||||
|
||||
const enactmentDatetime = new Date(marketFound?.terms.enactmentDatetime);
|
||||
const name =
|
||||
marketFound?.terms.change.__typename === 'UpdateMarketState'
|
||||
? marketFound.terms.change.market.tradableInstrument.instrument.code
|
||||
: '';
|
||||
|
||||
if (name && enactmentDatetime.getTime() > Date.now()) {
|
||||
const dayMonthDate = format(enactmentDatetime, 'dd MMMM');
|
||||
const duration = intervalToDuration({
|
||||
start: new Date(),
|
||||
end: enactmentDatetime,
|
||||
});
|
||||
const formattedDuration = formatDuration(duration, {
|
||||
format: ['days', 'hours'],
|
||||
});
|
||||
const price =
|
||||
marketFound?.terms.change.__typename === 'UpdateMarketState'
|
||||
? marketFound.terms.change.price
|
||||
: '';
|
||||
const assetSymbol = getQuoteName(market);
|
||||
return (
|
||||
<NotificationBanner
|
||||
intent={Intent.Warning}
|
||||
onClose={() => {
|
||||
setVisible(false);
|
||||
}}
|
||||
data-testid={`termination-warning-banner-${market.id}`}
|
||||
>
|
||||
<div className="uppercase mb-1">
|
||||
{t('Trading on Market %s will stop on %s', [name, dayMonthDate])}
|
||||
</div>
|
||||
<div>
|
||||
{t(
|
||||
'You will no longer be able to hold a position on this market when it closes in %s.',
|
||||
[formattedDuration]
|
||||
)}{' '}
|
||||
{price &&
|
||||
assetSymbol &&
|
||||
t('The final price will be %s %s.', [
|
||||
addDecimalsFormatNumber(price, market.decimalPlaces),
|
||||
assetSymbol,
|
||||
])}
|
||||
</div>
|
||||
</NotificationBanner>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user