Compare commits
63
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
536c493a52 | ||
|
|
bd371ac6bb | ||
|
|
f9b154119d | ||
|
|
747d75c223 | ||
|
|
14928d318d | ||
|
|
a19ea1c939 | ||
|
|
c65c296db2 | ||
|
|
6c5cd85d96 | ||
|
|
da0c8d3720 | ||
|
|
8efadda98c | ||
|
|
0872a14f44 | ||
|
|
13817e4d57 | ||
|
|
9da704c117 | ||
|
|
d262650258 | ||
|
|
30da1663eb | ||
|
|
79cbe62774 | ||
|
|
df11401b69 | ||
|
|
2f0be0bf34 | ||
|
|
5b5802104e | ||
|
|
3a149ddfb2 | ||
|
|
0e519f4d0e | ||
|
|
ff2e2574f6 | ||
|
|
9b52cecf21 | ||
|
|
478cc9e753 | ||
|
|
18f1fbd56d | ||
|
|
ccb22f02c3 | ||
|
|
015d8f51c0 | ||
|
|
e2a72cb395 | ||
|
|
0669696b6f | ||
|
|
56c662e5ba | ||
|
|
7fe269fad6 | ||
|
|
b761023069 | ||
|
|
7453acd632 | ||
|
|
1f507facba | ||
|
|
9d6b34963a | ||
|
|
7ac3a68ac9 | ||
|
|
2640ccb20a | ||
|
|
77c0894501 | ||
|
|
60d7cf3029 | ||
|
|
2b8abde938 | ||
|
|
2005f19d50 | ||
|
|
d78de10855 | ||
|
|
bb402c02f6 | ||
|
|
8a9b1c7874 | ||
|
|
a7e8b0eb01 | ||
|
|
89b3c06107 | ||
|
|
cd5c73d3fd | ||
|
|
b3a5ab022d | ||
|
|
ba438549bc | ||
|
|
496d1f5c68 | ||
|
|
e914e7bb70 | ||
|
|
71a36c2382 | ||
|
|
1c6a307bcd | ||
|
|
ef4a740b91 | ||
|
|
a6303456c5 | ||
|
|
2d4be5fcb3 | ||
|
|
9cbd6baccd | ||
|
|
525773773a | ||
|
|
45d6f43e74 | ||
|
|
41760f2956 | ||
|
|
835f2b793f | ||
|
|
d50b988b4a | ||
|
|
a6aec899c8 |
@@ -10,7 +10,6 @@ on:
|
||||
- opened
|
||||
- ready_for_review
|
||||
- reopened
|
||||
- edited
|
||||
- synchronize
|
||||
jobs:
|
||||
node-modules:
|
||||
@@ -44,13 +43,6 @@ jobs:
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: yarn install --pure-lockfile
|
||||
|
||||
lint-pr-title:
|
||||
needs: node-modules
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
name: Verify PR title
|
||||
uses: ./.github/workflows/lint-pr.yml
|
||||
secrets: inherit
|
||||
|
||||
lint-format:
|
||||
timeout-minutes: 20
|
||||
needs: node-modules
|
||||
|
||||
@@ -9,23 +9,37 @@ on:
|
||||
github-sha:
|
||||
required: true
|
||||
type: string
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
console-test-branch:
|
||||
type: choice
|
||||
description: 'main: v0.72.14, develop: v0.73.0-preview7'
|
||||
options:
|
||||
- main
|
||||
- develop
|
||||
|
||||
jobs:
|
||||
run-tests:
|
||||
name: run-tests
|
||||
runs-on: console-test
|
||||
timeout-minutes: 40
|
||||
runs-on: 8-cores
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
#----------------------------------------------
|
||||
# check-out frontend-monorepo
|
||||
#----------------------------------------------
|
||||
- name: Checkout console test repo
|
||||
- name: Checkout frontend-monorepo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ inputs.github-sha }}
|
||||
ref: ${{ inputs.github-sha || github.sha }}
|
||||
#----------------------------------------------
|
||||
# cache node modules
|
||||
#----------------------------------------------
|
||||
- name: setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '16'
|
||||
cache: yarn
|
||||
|
||||
- name: Cache node modules
|
||||
id: cache
|
||||
uses: actions/cache@v3
|
||||
@@ -68,7 +82,18 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: vegaprotocol/console-test
|
||||
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: './console-test/.env.${{ inputs.console-test-branch }}'
|
||||
export-variables: true
|
||||
keys-case: upper
|
||||
log-variables: true
|
||||
|
||||
#----------------------------------------------
|
||||
# install dependencies
|
||||
#----------------------------------------------
|
||||
@@ -96,8 +121,7 @@ jobs:
|
||||
#----------------------------------------------
|
||||
- name: Install vega binaries
|
||||
working-directory: ./console-test
|
||||
if: steps.vega_binaries_cache.outputs.cache-hit != 'true'
|
||||
run: poetry run python -m vega_sim.tools.load_binaries --force --version $VEGA_VERSION
|
||||
run: poetry run python -m vega_sim.tools.load_binaries --force --version ${{ env.VEGA_VERSION }}
|
||||
#----------------------------------------------
|
||||
# install playwright
|
||||
#----------------------------------------------
|
||||
@@ -109,7 +133,7 @@ jobs:
|
||||
#----------------------------------------------
|
||||
- name: Run tests
|
||||
working-directory: ./console-test
|
||||
run: poetry run pytest -v -s --numprocesses 2 --dist loadfile --durations=20
|
||||
run: poetry run pytest -v -s --numprocesses 4 --dist loadfile --durations=15
|
||||
- name: Check files
|
||||
run: |
|
||||
ls -al .
|
||||
@@ -124,3 +148,13 @@ jobs:
|
||||
name: playwright-trace
|
||||
path: ./traces/
|
||||
retention-days: 15
|
||||
#----------------------------------------------
|
||||
# ----- upload logs -----
|
||||
#----------------------------------------------
|
||||
- name: Upload worker logs
|
||||
uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: worker-logs
|
||||
path: ./logs/
|
||||
retention-days: 15
|
||||
|
||||
@@ -13,13 +13,35 @@ on:
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
runner-choice:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
runner: ${{ steps.step.outputs.runner }}
|
||||
steps:
|
||||
- name: Check branch
|
||||
id: step
|
||||
run: |
|
||||
if [ ${{ github.base_ref }} == 'main' ]; then
|
||||
echo "runner=mainnet-compatible-runner" >> $GITHUB_OUTPUT
|
||||
elif [ ${{ github.base_ref }} == 'develop' ] && [ ${{ github.ref_name }} == 'main' ]; then
|
||||
echo "runner=mainnet-compatible-runner" >> $GITHUB_OUTPUT
|
||||
elif [ ${{ github.event_name }} == 'push' ] && [ ${{ contains(github.ref_name, 'release/mainnet') }} ]; then
|
||||
echo "runner=mainnet-compatible-runner" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "runner=self-hosted-runner" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Print runner
|
||||
run: echo ${{ steps.step.outputs.runner }}
|
||||
|
||||
e2e:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
project: ${{ fromJSON(inputs.projects) }}
|
||||
name: ${{ matrix.project }}
|
||||
runs-on: self-hosted-runner
|
||||
needs: runner-choice
|
||||
runs-on: ${{ needs.runner-choice.outputs.runner }}
|
||||
timeout-minutes: 120
|
||||
steps:
|
||||
# Checks if skip cache was requested
|
||||
|
||||
@@ -2,7 +2,12 @@
|
||||
name: Verify PR title
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
- reopened
|
||||
- synchronize
|
||||
|
||||
jobs:
|
||||
lint_pr:
|
||||
@@ -11,21 +16,16 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
|
||||
cache: yarn
|
||||
node-version: 16
|
||||
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: node_modules
|
||||
key: ${{ runner.os }}-cache-node-modules-${{ hashFiles('yarn.lock') }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
rm package.json
|
||||
npm install --no-save @commitlint/cli @commitlint/config-conventional @commitlint/config-nx-scopes nx
|
||||
|
||||
- name: Check PR title
|
||||
run: echo "${{ github.event.pull_request.title }}" | npx commitlint --config ./commitlint.config-ci.js
|
||||
|
||||
@@ -30,12 +30,18 @@ jobs:
|
||||
echo IS_IPFS_RELEASE=false >> $GITHUB_ENV
|
||||
echo IS_S3_RELEASE=false >> $GITHUB_ENV
|
||||
echo IS_DEV_IMAGE=false >> $GITHUB_ENV
|
||||
echo IS_MAIN_IMAGE=false >> $GITHUB_ENV
|
||||
|
||||
- name: Is dev image
|
||||
if: ${{ contains(github.ref, 'develop') && github.event_name == 'push' && matrix.app == 'trading' }}
|
||||
if: ${{ github.ref_name == 'develop' && github.event_name == 'push' && matrix.app == 'trading' }}
|
||||
run: |
|
||||
echo IS_DEV_IMAGE=true >> $GITHUB_ENV
|
||||
|
||||
- name: Is main image
|
||||
if: ${{ github.ref_name == 'main' && github.event_name == 'push' && matrix.app == 'trading' }}
|
||||
run: |
|
||||
echo IS_MAIN_IMAGE=true >> $GITHUB_ENV
|
||||
|
||||
- name: Is PR
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
run: |
|
||||
@@ -81,7 +87,7 @@ jobs:
|
||||
|
||||
- name: Log in to the Container registry (docker hub)
|
||||
uses: docker/login-action@v2
|
||||
if: ${{ env.IS_IPFS_RELEASE == 'true' || env.IS_DEV_IMAGE == 'true' }}
|
||||
if: ${{ env.IS_IPFS_RELEASE == 'true' || env.IS_DEV_IMAGE == 'true' || env.IS_MAIN_IMAGE == 'true' }}
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
@@ -179,7 +185,7 @@ jobs:
|
||||
uses: docker/build-push-action@v3
|
||||
continue-on-error: true
|
||||
id: dockerhub-push
|
||||
if: ${{ env.IS_IPFS_RELEASE == 'true' || env.IS_DEV_IMAGE == 'true' }}
|
||||
if: ${{ env.IS_IPFS_RELEASE == 'true' || env.IS_DEV_IMAGE == 'true' || env.IS_MAIN_IMAGE == 'true' }}
|
||||
with:
|
||||
context: .
|
||||
file: docker/node-outside-docker.Dockerfile
|
||||
@@ -189,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' || '' }}
|
||||
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
|
||||
@@ -216,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' || '' }}
|
||||
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
|
||||
|
||||
@@ -87,7 +87,6 @@ context('Market page', { tags: '@regression' }, function () {
|
||||
// Liquidity
|
||||
cy.validate_element_from_table('Target Stake', '0.00 fUSDC');
|
||||
cy.validate_element_from_table('Supplied Stake', '0.00 fUSDC');
|
||||
cy.validate_element_from_table('Market Value Proxy', '0.00 fUSDC');
|
||||
// Liquidity price range
|
||||
cy.validate_element_from_table(
|
||||
'Liquidity Price Range',
|
||||
@@ -95,7 +94,6 @@ context('Market page', { tags: '@regression' }, function () {
|
||||
);
|
||||
cy.validate_element_from_table('Lowest Price', '0.00 fUSDC');
|
||||
cy.validate_element_from_table('Highest Price', '0.00 fUSDC');
|
||||
|
||||
cy.getByTestId('oracle-spec-links')
|
||||
.should('have.attr', 'href')
|
||||
.and(
|
||||
@@ -144,11 +142,8 @@ context('Market page', { tags: '@regression' }, function () {
|
||||
.as('successorMarketId');
|
||||
cy.contains('Token test market').click();
|
||||
cy.getByTestId(marketHeaders).should('have.text', 'Token test market');
|
||||
cy.validate_proposal_change_type('Triggering Ratio', 'Added');
|
||||
cy.validate_element_from_table('Triggering Ratio', '0.7');
|
||||
cy.validate_proposal_change_type('Time Window', 'Added');
|
||||
cy.validate_element_from_table('Time Window', '3,600');
|
||||
cy.validate_proposal_change_type('Scaling Factor', 'Added');
|
||||
cy.validate_element_from_table('Scaling Factor', '10');
|
||||
|
||||
cy.getByTestId(successionLineItem)
|
||||
|
||||
@@ -129,6 +129,12 @@ function getSuccessorTxBody(parentMarketId) {
|
||||
parentMarketId: parentMarketId,
|
||||
insurancePoolFraction: '0.75',
|
||||
},
|
||||
liquiditySlaParameters: {
|
||||
priceRange: '0.95',
|
||||
commitmentMinTimeFraction: '0.5',
|
||||
performanceHysteresisEpochs: 2,
|
||||
slaCompetitionFactor: '0.75',
|
||||
},
|
||||
},
|
||||
},
|
||||
closingTimestamp,
|
||||
|
||||
@@ -4,7 +4,7 @@ import { AssetTypeMapping, AssetStatusMapping } from '@vegaprotocol/assets';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { AgGrid } from '@vegaprotocol/datagrid';
|
||||
import type { VegaICellRendererParams } from '@vegaprotocol/datagrid';
|
||||
import { useRef, useLayoutEffect } from 'react';
|
||||
import { BREAKPOINT_MD } from '../../config/breakpoints';
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import type { MarketInfoWithData } from '@vegaprotocol/markets';
|
||||
import {
|
||||
LiquidityPriceRangeInfoPanel,
|
||||
LiquiditySLAParametersInfoPanel,
|
||||
PriceMonitoringBoundsInfoPanel,
|
||||
SuccessionLineInfoPanel,
|
||||
getDataSourceSpecForSettlementData,
|
||||
@@ -94,6 +96,10 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
|
||||
)}
|
||||
<h2 className={headerClassName}>{t('Liquidity monitoring')}</h2>
|
||||
<LiquidityMonitoringParametersInfoPanel market={market} />
|
||||
<h2 className={headerClassName}>{t('Liquidity price range')}</h2>
|
||||
<LiquidityPriceRangeInfoPanel market={market} />
|
||||
<h2 className={headerClassName}>{t('Liquidity SLA protocol')}</h2>
|
||||
<LiquiditySLAParametersInfoPanel market={market} />
|
||||
<h2 className={headerClassName}>{t('Liquidity')}</h2>
|
||||
<LiquidityInfoPanel market={market} />
|
||||
{showTwoOracles ? (
|
||||
|
||||
@@ -4,7 +4,7 @@ import { t } from '@vegaprotocol/i18n';
|
||||
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import type { ColDef } from 'ag-grid-community';
|
||||
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { AgGrid } from '@vegaprotocol/datagrid';
|
||||
import type {
|
||||
VegaICellRendererParams,
|
||||
VegaValueGetterParams,
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { ProposalListFieldsFragment } from '@vegaprotocol/proposals';
|
||||
import { VoteProgress } from '@vegaprotocol/proposals';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { AgGrid } from '@vegaprotocol/datagrid';
|
||||
import type {
|
||||
VegaICellRendererParams,
|
||||
VegaValueFormatterParams,
|
||||
@@ -105,7 +105,7 @@ export const ProposalsTable = ({ data }: ProposalsTableProps) => {
|
||||
? new BigNumber(0)
|
||||
: yesTokens.multipliedBy(100).dividedBy(totalTokensVoted);
|
||||
return (
|
||||
<div className="uppercase flex h-full items-center justify-center pt-2">
|
||||
<div className="flex items-center justify-center h-full pt-2 uppercase">
|
||||
<VoteProgress
|
||||
threshold={requiredMajorityPercentage}
|
||||
progress={yesPercentage}
|
||||
|
||||
@@ -49,6 +49,37 @@ fragment ExplorerOracleDataSource on OracleSpec {
|
||||
}
|
||||
... on DataSourceDefinitionExternal {
|
||||
sourceType {
|
||||
... on EthCallSpec {
|
||||
abi
|
||||
args
|
||||
method
|
||||
requiredConfirmations
|
||||
address
|
||||
normalisers {
|
||||
name
|
||||
expression
|
||||
}
|
||||
trigger {
|
||||
trigger {
|
||||
... on EthTimeTrigger {
|
||||
initial
|
||||
every
|
||||
until
|
||||
}
|
||||
}
|
||||
}
|
||||
filters {
|
||||
key {
|
||||
name
|
||||
type
|
||||
numberDecimalPlaces
|
||||
}
|
||||
conditions {
|
||||
value
|
||||
operator
|
||||
}
|
||||
}
|
||||
}
|
||||
... on DataSourceSpecConfiguration {
|
||||
signers {
|
||||
signer {
|
||||
|
||||
+34
-3
@@ -5,19 +5,19 @@ import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type ExplorerOracleDataConnectionFragment = { __typename?: 'OracleSpec', dataConnection: { __typename?: 'OracleDataConnection', edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } };
|
||||
|
||||
export type ExplorerOracleDataSourceFragment = { __typename?: 'OracleSpec', dataSourceSpec: { __typename?: 'ExternalDataSourceSpec', spec: { __typename?: 'DataSourceSpec', id: string, createdAt: any, updatedAt?: any | null, status: Types.DataSourceSpecStatus, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } | { __typename?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger' } } } } }, dataConnection: { __typename?: 'OracleDataConnection', edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } };
|
||||
export type ExplorerOracleDataSourceFragment = { __typename?: 'OracleSpec', dataSourceSpec: { __typename?: 'ExternalDataSourceSpec', spec: { __typename?: 'DataSourceSpec', id: string, createdAt: any, updatedAt?: any | null, status: Types.DataSourceSpecStatus, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } | { __typename?: 'EthCallSpec', abi?: Array<string> | null, args?: Array<string> | null, method: string, requiredConfirmations: number, address: string, normalisers?: Array<{ __typename?: 'Normaliser', name: string, expression: string }> | null, trigger: { __typename?: 'EthCallTrigger', trigger: { __typename?: 'EthTimeTrigger', initial?: any | null, every?: number | null, until?: any | null } }, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger' } } } } }, dataConnection: { __typename?: 'OracleDataConnection', edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } };
|
||||
|
||||
export type ExplorerOracleSpecsQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type ExplorerOracleSpecsQuery = { __typename?: 'Query', oracleSpecsConnection?: { __typename?: 'OracleSpecsConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, edges?: Array<{ __typename?: 'OracleSpecEdge', node: { __typename?: 'OracleSpec', dataSourceSpec: { __typename?: 'ExternalDataSourceSpec', spec: { __typename?: 'DataSourceSpec', id: string, createdAt: any, updatedAt?: any | null, status: Types.DataSourceSpecStatus, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } | { __typename?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger' } } } } }, dataConnection: { __typename?: 'OracleDataConnection', edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } } } | null> | null } | null };
|
||||
export type ExplorerOracleSpecsQuery = { __typename?: 'Query', oracleSpecsConnection?: { __typename?: 'OracleSpecsConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, edges?: Array<{ __typename?: 'OracleSpecEdge', node: { __typename?: 'OracleSpec', dataSourceSpec: { __typename?: 'ExternalDataSourceSpec', spec: { __typename?: 'DataSourceSpec', id: string, createdAt: any, updatedAt?: any | null, status: Types.DataSourceSpecStatus, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } | { __typename?: 'EthCallSpec', abi?: Array<string> | null, args?: Array<string> | null, method: string, requiredConfirmations: number, address: string, normalisers?: Array<{ __typename?: 'Normaliser', name: string, expression: string }> | null, trigger: { __typename?: 'EthCallTrigger', trigger: { __typename?: 'EthTimeTrigger', initial?: any | null, every?: number | null, until?: any | null } }, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger' } } } } }, dataConnection: { __typename?: 'OracleDataConnection', edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } } } | null> | null } | null };
|
||||
|
||||
export type ExplorerOracleSpecByIdQueryVariables = Types.Exact<{
|
||||
id: Types.Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
export type ExplorerOracleSpecByIdQuery = { __typename?: 'Query', oracleSpec?: { __typename?: 'OracleSpec', dataSourceSpec: { __typename?: 'ExternalDataSourceSpec', spec: { __typename?: 'DataSourceSpec', id: string, createdAt: any, updatedAt?: any | null, status: Types.DataSourceSpecStatus, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } | { __typename?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger' } } } } }, dataConnection: { __typename?: 'OracleDataConnection', edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } } | null };
|
||||
export type ExplorerOracleSpecByIdQuery = { __typename?: 'Query', oracleSpec?: { __typename?: 'OracleSpec', dataSourceSpec: { __typename?: 'ExternalDataSourceSpec', spec: { __typename?: 'DataSourceSpec', id: string, createdAt: any, updatedAt?: any | null, status: Types.DataSourceSpecStatus, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } | { __typename?: 'EthCallSpec', abi?: Array<string> | null, args?: Array<string> | null, method: string, requiredConfirmations: number, address: string, normalisers?: Array<{ __typename?: 'Normaliser', name: string, expression: string }> | null, trigger: { __typename?: 'EthCallTrigger', trigger: { __typename?: 'EthTimeTrigger', initial?: any | null, every?: number | null, until?: any | null } }, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger' } } } } }, dataConnection: { __typename?: 'OracleDataConnection', edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } } | null };
|
||||
|
||||
export const ExplorerOracleDataConnectionFragmentDoc = gql`
|
||||
fragment ExplorerOracleDataConnection on OracleSpec {
|
||||
@@ -72,6 +72,37 @@ export const ExplorerOracleDataSourceFragmentDoc = gql`
|
||||
}
|
||||
... on DataSourceDefinitionExternal {
|
||||
sourceType {
|
||||
... on EthCallSpec {
|
||||
abi
|
||||
args
|
||||
method
|
||||
requiredConfirmations
|
||||
address
|
||||
normalisers {
|
||||
name
|
||||
expression
|
||||
}
|
||||
trigger {
|
||||
trigger {
|
||||
... on EthTimeTrigger {
|
||||
initial
|
||||
every
|
||||
until
|
||||
}
|
||||
}
|
||||
}
|
||||
filters {
|
||||
key {
|
||||
name
|
||||
type
|
||||
numberDecimalPlaces
|
||||
}
|
||||
conditions {
|
||||
value
|
||||
operator
|
||||
}
|
||||
}
|
||||
}
|
||||
... on DataSourceSpecConfiguration {
|
||||
signers {
|
||||
signer {
|
||||
|
||||
@@ -21,6 +21,8 @@ NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||
NX_VEGA_REST_URL=http://localhost:3008/api/v2/
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
NX_PRODUCT_PERPETUALS=true
|
||||
NX_UPDATE_MARKET_STATE=true
|
||||
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||
|
||||
@@ -4,3 +4,5 @@ NX_VEGA_URL=https://api.n04.d.vega.xyz/graphql
|
||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
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
|
||||
|
||||
@@ -4,3 +4,5 @@ NX_VEGA_URL=https://api.vega.community/graphql
|
||||
NX_ETHEREUM_PROVIDER_URL=https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
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
|
||||
|
||||
@@ -4,3 +4,5 @@ NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
|
||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
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
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"rationale": {
|
||||
"title": "Add USDT Coin (USDT)",
|
||||
"description": "Proposal to add USDT Coin (USDT) as an asset"
|
||||
},
|
||||
"terms": {
|
||||
"newAsset": {
|
||||
"changes": {
|
||||
"name": "USDT Coin",
|
||||
"symbol": "USDT",
|
||||
"decimals": "18",
|
||||
"quantum": "1",
|
||||
"erc20": {
|
||||
"contractAddress": "0xb404c51bbc10dcbe948077f18a4b8e553d160084"
|
||||
}
|
||||
}
|
||||
},
|
||||
"closingTimestamp": 1662374250,
|
||||
"enactmentTimestamp": 1662460650
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
{
|
||||
"rationale": {
|
||||
"description": "## Summary\n\nThis proposal requests to list BTC PERPS Incentive as a market with USD-P as a settlement asset on the Vega Network as discussed in: https://community.vega.xyz/.\n\n## Rationale\n\n- BTC is the largest Crypto asset with the highest volume and Marketcap.\n- Given the price, 1 decimal places will be used for price due to the number of valid digits in asset price. \n- Position decimal places will be set to 4 considering the value per contract\n- USDT is chosen as settlement asset due to its stability.",
|
||||
"title": "perpetual market proposal"
|
||||
},
|
||||
"terms": {
|
||||
"closingTimestamp": 0,
|
||||
"enactmentTimestamp": 0,
|
||||
"newMarket": {
|
||||
"changes": {
|
||||
"instrument": {
|
||||
"name": "Token test market",
|
||||
"code": "TEST.24h",
|
||||
"perpetual": {
|
||||
"clampLowerBound": "0",
|
||||
"clampUpperBound": "0",
|
||||
"interestRate": "0",
|
||||
"marginFundingFactor": "0.1",
|
||||
"settlementAsset": "73174a6fb1d5802ba0ac7bd7ab79e0a3a4837b262de0a4e80815a55442692bd0",
|
||||
"quoteName": "fBTC",
|
||||
"dataSourceSpecForSettlementData": {
|
||||
"external": {
|
||||
"ethOracle": {
|
||||
"address": "0x1b44F3514812d835EB1BDB0acB33d3fA3351Ee43",
|
||||
"abi": "[{\"inputs\":[],\"name\":\"latestAnswer\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]",
|
||||
"method": "latestAnswer",
|
||||
"normalisers": [
|
||||
{
|
||||
"name": "btc.price",
|
||||
"expression": "$[0]"
|
||||
}
|
||||
],
|
||||
"requiredConfirmations": 3,
|
||||
"trigger": {
|
||||
"timeTrigger": {
|
||||
"every": 30
|
||||
}
|
||||
},
|
||||
"filters": [
|
||||
{
|
||||
"key": {
|
||||
"name": "btc.price",
|
||||
"type": "TYPE_INTEGER",
|
||||
"numberDecimalPlaces": 8
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"operator": "OPERATOR_GREATER_THAN_OR_EQUAL",
|
||||
"value": "0"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"dataSourceSpecForSettlementSchedule": {
|
||||
"internal": {
|
||||
"timeTrigger": {
|
||||
"conditions": [
|
||||
{
|
||||
"operator": "OPERATOR_GREATER_THAN_OR_EQUAL",
|
||||
"value": "0"
|
||||
}
|
||||
],
|
||||
"triggers": [
|
||||
{
|
||||
"every": 1800
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"dataSourceSpecBinding": {
|
||||
"settlementDataProperty": "btc.price",
|
||||
"settlementScheduleProperty": "vegaprotocol.builtin.timetrigger"
|
||||
}
|
||||
}
|
||||
},
|
||||
"metadata": [
|
||||
"base:BTC",
|
||||
"quote:USD-P",
|
||||
"class:fx/crypto",
|
||||
"quarterly",
|
||||
"sector:defi",
|
||||
"enactment:2023-06-15T14:00:00Z",
|
||||
"settlement:2023-09-30T08:00:00Z"
|
||||
],
|
||||
"priceMonitoringParameters": {
|
||||
"triggers": [
|
||||
{
|
||||
"horizon": "3600",
|
||||
"probability": "0.9999",
|
||||
"auctionExtension": "120"
|
||||
},
|
||||
{
|
||||
"horizon": "14400",
|
||||
"probability": "0.9999",
|
||||
"auctionExtension": "180"
|
||||
},
|
||||
{
|
||||
"horizon": "43200",
|
||||
"probability": "0.9999",
|
||||
"auctionExtension": "300"
|
||||
}
|
||||
]
|
||||
},
|
||||
"liquidityMonitoringParameters": {
|
||||
"targetStakeParameters": {
|
||||
"timeWindow": "3600",
|
||||
"scalingFactor": 1
|
||||
},
|
||||
"triggeringRatio": "0.7",
|
||||
"auctionExtension": "1"
|
||||
},
|
||||
|
||||
"liquiditySlaParameters": {
|
||||
"priceRange": "0.05",
|
||||
"commitmentMinTimeFraction": "0.95",
|
||||
"performanceHysteresisEpochs": 1,
|
||||
"slaCompetitionFactor": "0.95"
|
||||
},
|
||||
|
||||
"logNormal": {
|
||||
"riskAversionParameter": 0.000001,
|
||||
"tau": 0.0001140771161,
|
||||
"params": {
|
||||
"sigma": 1.5
|
||||
}
|
||||
},
|
||||
"decimalPlaces": "1",
|
||||
"positionDecimalPlaces": "4",
|
||||
"linearSlippageFactor": "0.001",
|
||||
"quadraticSlippageFactor": "0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"rationale": {
|
||||
"title": "Market resume test",
|
||||
"description": "E2E test for market resume proposal"
|
||||
},
|
||||
"terms": {
|
||||
"updateMarketState": {
|
||||
"changes": {
|
||||
"marketId": "b33bb4157e12355db22e41f277ddd0c10104dec29a4d6960bbcb96d186c40cbd",
|
||||
"updateType": "MARKET_STATE_UPDATE_TYPE_RESUME"
|
||||
}
|
||||
},
|
||||
"closingTimestamp": 0,
|
||||
"enactmentTimestamp": 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"rationale": {
|
||||
"title": "Market suspended test",
|
||||
"description": "E2E test for market suspended proposal"
|
||||
},
|
||||
"terms": {
|
||||
"updateMarketState": {
|
||||
"changes": {
|
||||
"marketId": "",
|
||||
"updateType": "MARKET_STATE_UPDATE_TYPE_SUSPEND"
|
||||
}
|
||||
},
|
||||
"closingTimestamp": 0,
|
||||
"enactmentTimestamp": 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"rationale": {
|
||||
"title": "Market terminate test",
|
||||
"description": "E2E test for market terminate proposal"
|
||||
},
|
||||
"terms": {
|
||||
"updateMarketState": {
|
||||
"changes": {
|
||||
"marketId": "",
|
||||
"updateType": "MARKET_STATE_UPDATE_TYPE_TERMINATE",
|
||||
"price": "100"
|
||||
}
|
||||
},
|
||||
"closingTimestamp": 0,
|
||||
"enactmentTimestamp": 0
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
{
|
||||
"instrument": {
|
||||
"code": "Token.24h",
|
||||
"future": {
|
||||
"quoteName": "fBTC",
|
||||
"dataSourceSpecForSettlementData": {
|
||||
"external": {
|
||||
"oracle": {
|
||||
"signers": [
|
||||
{
|
||||
"pubKey": {
|
||||
"key": "70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680"
|
||||
}
|
||||
}
|
||||
],
|
||||
"filters": [
|
||||
{
|
||||
"key": {
|
||||
"name": "prices.BTC.value",
|
||||
"type": "TYPE_INTEGER"
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"operator": "OPERATOR_GREATER_THAN",
|
||||
"value": "0"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"dataSourceSpecForTradingTermination": {
|
||||
"external": {
|
||||
"oracle": {
|
||||
"signers": [
|
||||
{
|
||||
"pubKey": {
|
||||
"key": "70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680"
|
||||
}
|
||||
}
|
||||
],
|
||||
"filters": [
|
||||
{
|
||||
"key": {
|
||||
"name": "trading.terminated.ETH5",
|
||||
"type": "TYPE_BOOLEAN"
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"operator": "OPERATOR_GREATER_THAN_OR_EQUAL",
|
||||
"value": "1648684800000000000"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"dataSourceSpecBinding": {
|
||||
"settlementDataProperty": "prices.BTC.value",
|
||||
"tradingTerminationProperty": "trading.terminated.ETH5"
|
||||
}
|
||||
}
|
||||
},
|
||||
"metadata": ["sector:energy", "sector:food", "source:docs.vega.xyz"],
|
||||
"priceMonitoringParameters": {
|
||||
"triggers": [
|
||||
{
|
||||
"horizon": "43200",
|
||||
"probability": "0.9999999",
|
||||
"auctionExtension": "600"
|
||||
}
|
||||
]
|
||||
},
|
||||
"logNormal": {
|
||||
"tau": 0.0001140771161,
|
||||
"riskAversionParameter": 0.001,
|
||||
"params": {
|
||||
"mu": 0,
|
||||
"r": 0.016,
|
||||
"sigma": 0.3
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
createTenDigitUnixTimeStampForSpecifiedDays,
|
||||
generateFreeFormProposalTitle,
|
||||
getDateFormatForSpecifiedDays,
|
||||
getProposalDetailsValue,
|
||||
getProposalFromTitle,
|
||||
getProposalInformationFromTable,
|
||||
goToMakeNewProposal,
|
||||
@@ -50,6 +51,7 @@ const openProposals = 'open-proposals';
|
||||
const viewProposalButton = 'view-proposal-btn';
|
||||
const proposalTermsToggle = 'proposal-json-toggle';
|
||||
const marketDataToggle = 'proposal-market-data-toggle';
|
||||
const marketProposalType = 'proposal-type';
|
||||
|
||||
describe(
|
||||
'Governance flow for proposal details',
|
||||
@@ -58,6 +60,17 @@ describe(
|
||||
before('connect wallets and set approval limit', function () {
|
||||
cy.visit('/');
|
||||
ethereumWalletConnect();
|
||||
cy.createMarket();
|
||||
navigateTo(navigation.proposals);
|
||||
cy.getByTestId('closed-proposals').within(() => {
|
||||
cy.contains('Add Lorem Ipsum market')
|
||||
.parentsUntil(proposalListItem)
|
||||
.last()
|
||||
.within(() => {
|
||||
cy.getByTestId(viewProposalButton).click();
|
||||
});
|
||||
});
|
||||
getProposalInformationFromTable('ID').invoke('text').as('parentMarketId');
|
||||
});
|
||||
|
||||
beforeEach('visit proposals tab', function () {
|
||||
@@ -296,9 +309,6 @@ describe(
|
||||
});
|
||||
|
||||
it('Able to see successor market details with new and updated values', function () {
|
||||
cy.createMarket();
|
||||
cy.reload();
|
||||
waitForSpinner();
|
||||
cy.getByTestId('closed-proposals').within(() => {
|
||||
cy.contains('Add Lorem Ipsum market')
|
||||
.parentsUntil(proposalListItem)
|
||||
@@ -307,14 +317,9 @@ describe(
|
||||
cy.getByTestId(viewProposalButton).click();
|
||||
});
|
||||
});
|
||||
getProposalInformationFromTable('ID')
|
||||
.invoke('text')
|
||||
.as('parentMarketId')
|
||||
.then(() => {
|
||||
cy.VegaWalletSubmitProposal(
|
||||
createSuccessorMarketProposalTxBody(this.parentMarketId)
|
||||
);
|
||||
});
|
||||
cy.VegaWalletSubmitProposal(
|
||||
createSuccessorMarketProposalTxBody(this.parentMarketId)
|
||||
);
|
||||
navigateTo(navigation.proposals);
|
||||
cy.reload();
|
||||
getProposalFromTitle('Test successor market proposal details').within(
|
||||
@@ -372,19 +377,147 @@ describe(
|
||||
});
|
||||
|
||||
// 3003-PMAN-011
|
||||
cy.get('.underline').contains('Parent Market ID').realHover();
|
||||
cy.contains('Parent Market ID').realHover();
|
||||
cy.getByTestId('tooltip-content', { timeout: 8000 }).should(
|
||||
'contain.text',
|
||||
'The ID of the market this market succeeds.'
|
||||
);
|
||||
cy.get('.underline')
|
||||
.contains('Insurance Pool Fraction')
|
||||
.realMouseUp()
|
||||
.realHover();
|
||||
cy.contains('Insurance Pool Fraction').realMouseUp().realHover();
|
||||
cy.getByTestId('tooltip-content', { timeout: 8000 }).should(
|
||||
'contain.text',
|
||||
'The fraction of the insurance pool balance that is carried over from the parent market to the successor.'
|
||||
);
|
||||
});
|
||||
|
||||
it('Able to see perpetual market', function () {
|
||||
const proposalPath =
|
||||
'src/fixtures/proposals/new-market-perpetual-raw.json';
|
||||
const enactmentTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(3);
|
||||
const closingTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(2);
|
||||
submitUniqueRawProposal({
|
||||
proposalBody: proposalPath,
|
||||
enactmentTimestamp: enactmentTimestamp,
|
||||
closingTimestamp: closingTimestamp,
|
||||
});
|
||||
getProposalFromTitle('perpetual market proposal').within(() => {
|
||||
cy.getByTestId(marketProposalType).should(
|
||||
'have.text',
|
||||
'New market - perpetual'
|
||||
);
|
||||
cy.getByTestId(viewProposalButton).click();
|
||||
});
|
||||
cy.getByTestId(marketDataToggle).click();
|
||||
getProposalDetailsValue('Product Type').should(
|
||||
'contain.text',
|
||||
'Perpetual'
|
||||
);
|
||||
cy.getByTestId(marketProposalType).should(
|
||||
'have.text',
|
||||
'New market - perpetual'
|
||||
);
|
||||
// Liquidity SLA protocols
|
||||
getProposalDetailsValue('Performance Hysteresis Epochs').should(
|
||||
'contain.text',
|
||||
'1'
|
||||
);
|
||||
getProposalDetailsValue('SLA Competition Factor').should(
|
||||
'contain.text',
|
||||
'95.00%'
|
||||
);
|
||||
getProposalDetailsValue('Epoch Length').should('contain.text', '5s');
|
||||
getProposalDetailsValue('Non Performance Bond Penalty Max').should(
|
||||
'contain.text',
|
||||
'0.05'
|
||||
);
|
||||
getProposalDetailsValue('Stake To CCY Volume').should(
|
||||
'contain.text',
|
||||
'0.3'
|
||||
);
|
||||
getProposalDetailsValue(
|
||||
'Minimum Probability Of Trading LP Orders'
|
||||
).should('contain.text', '1e-8');
|
||||
});
|
||||
|
||||
it('Able to see suspended market proposal', function () {
|
||||
const proposalPath = 'src/fixtures/proposals/suspend-market-raw.json';
|
||||
const enactmentTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(3);
|
||||
const closingTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(2);
|
||||
submitUniqueRawProposal({
|
||||
proposalBody: proposalPath,
|
||||
updateMarketId: this.parentMarketId,
|
||||
enactmentTimestamp: enactmentTimestamp,
|
||||
closingTimestamp: closingTimestamp,
|
||||
});
|
||||
getProposalFromTitle('Market suspended test').within(() => {
|
||||
cy.getByTestId(marketProposalType).should(
|
||||
'have.text',
|
||||
'Suspend market'
|
||||
);
|
||||
cy.getByTestId(viewProposalButton).click();
|
||||
});
|
||||
cy.getByTestId(marketProposalType).should('have.text', 'Suspend market');
|
||||
cy.getByTestId(marketDataToggle).click();
|
||||
cy.getByTestId('proposal-update-market-state').within(() => {
|
||||
getProposalInformationFromTable('Market ID')
|
||||
.invoke('text')
|
||||
.and('eq', this.parentMarketId);
|
||||
});
|
||||
});
|
||||
|
||||
it('Able to see resume market proposal', function () {
|
||||
const proposalPath = 'src/fixtures/proposals/resume-market-raw.json';
|
||||
const enactmentTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(3);
|
||||
const closingTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(2);
|
||||
submitUniqueRawProposal({
|
||||
proposalBody: proposalPath,
|
||||
updateMarketId: this.parentMarketId,
|
||||
enactmentTimestamp: enactmentTimestamp,
|
||||
closingTimestamp: closingTimestamp,
|
||||
});
|
||||
getProposalFromTitle('Market resume test').within(() => {
|
||||
cy.getByTestId(marketProposalType).should('have.text', 'Resume market');
|
||||
cy.getByTestId(viewProposalButton).click();
|
||||
});
|
||||
cy.getByTestId(marketProposalType).should('have.text', 'Resume market');
|
||||
cy.getByTestId(marketDataToggle).click();
|
||||
cy.getByTestId('proposal-update-market-state').within(() => {
|
||||
getProposalInformationFromTable('Market ID')
|
||||
.invoke('text')
|
||||
.and('eq', this.parentMarketId);
|
||||
});
|
||||
});
|
||||
|
||||
it('Able to see terminate market proposal', function () {
|
||||
const proposalPath = 'src/fixtures/proposals/terminate-market-raw.json';
|
||||
const enactmentTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(3);
|
||||
const closingTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(2);
|
||||
submitUniqueRawProposal({
|
||||
proposalBody: proposalPath,
|
||||
updateMarketId: this.parentMarketId,
|
||||
enactmentTimestamp: enactmentTimestamp,
|
||||
closingTimestamp: closingTimestamp,
|
||||
});
|
||||
getProposalFromTitle('Market terminate test').within(() => {
|
||||
cy.getByTestId(marketProposalType).should(
|
||||
'have.text',
|
||||
'Terminate market'
|
||||
);
|
||||
cy.getByTestId(viewProposalButton).click();
|
||||
});
|
||||
cy.getByTestId(marketProposalType).should(
|
||||
'have.text',
|
||||
'Terminate market'
|
||||
);
|
||||
cy.getByTestId(marketDataToggle).click();
|
||||
cy.getByTestId('proposal-update-market-state').within(() => {
|
||||
getProposalInformationFromTable('Market ID')
|
||||
.invoke('text')
|
||||
.and('eq', this.parentMarketId);
|
||||
getProposalDetailsValue('Termination Price').should(
|
||||
'contain.text',
|
||||
'0.001 fUSDC'
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
@@ -65,7 +65,10 @@ context(
|
||||
cy.getByTestId(viewProposalButton).click();
|
||||
});
|
||||
});
|
||||
cy.getByTestId('proposal-type').should('have.text', 'New market');
|
||||
cy.getByTestId('proposal-type').should(
|
||||
'have.text',
|
||||
'New market - future'
|
||||
);
|
||||
cy.getByTestId(proposalStatus).should('have.text', 'Enacted');
|
||||
cy.getByTestId(votesTable).within(() => {
|
||||
cy.contains('Voting has ended.').should('be.visible');
|
||||
|
||||
@@ -89,11 +89,12 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
|
||||
|
||||
it('Newly created proposals list - shows title and portion of summary', function () {
|
||||
const proposalPath = 'src/fixtures/proposals/new-market-raw.json';
|
||||
const proposalTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(3);
|
||||
const enactmentTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(3);
|
||||
const closingTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(2);
|
||||
submitUniqueRawProposal({
|
||||
proposalBody: proposalPath,
|
||||
enactmentTimestamp: proposalTimestamp,
|
||||
closingTimestamp: proposalTimestamp,
|
||||
enactmentTimestamp: enactmentTimestamp,
|
||||
closingTimestamp: closingTimestamp,
|
||||
}); // 3001-VOTE-052
|
||||
// 3001-VOTE-008
|
||||
// 3001-VOTE-034
|
||||
|
||||
@@ -54,6 +54,7 @@ export function submitUniqueRawProposal(proposalFields: {
|
||||
proposalBody?: string;
|
||||
proposalTitle?: string;
|
||||
proposalDescription?: string;
|
||||
updateMarketId?: string;
|
||||
closingTimestamp?: number;
|
||||
enactmentTimestamp?: number;
|
||||
submit?: boolean;
|
||||
@@ -71,6 +72,10 @@ export function submitUniqueRawProposal(proposalFields: {
|
||||
if (proposalFields.proposalDescription) {
|
||||
rawProposal.rationale.description = proposalFields.proposalDescription;
|
||||
}
|
||||
if (proposalFields.updateMarketId) {
|
||||
rawProposal.terms.updateMarketState.changes.marketId =
|
||||
proposalFields.updateMarketId;
|
||||
}
|
||||
if (proposalFields.closingTimestamp) {
|
||||
rawProposal.terms.closingTimestamp = proposalFields.closingTimestamp;
|
||||
} else if (
|
||||
@@ -232,21 +237,25 @@ export function getDownloadedProposalJsonPath(proposalType: string) {
|
||||
return filepath;
|
||||
}
|
||||
|
||||
export function getProposalDetailsValue(RowName: string) {
|
||||
return cy
|
||||
.contains(RowName)
|
||||
.parentsUntil(proposalInformationTableRows)
|
||||
.parent()
|
||||
.first();
|
||||
}
|
||||
|
||||
export function validateProposalDetailsDiff(
|
||||
RowName: string,
|
||||
changeType: proposalChangeType,
|
||||
newValue: string,
|
||||
oldValue?: string
|
||||
) {
|
||||
cy.contains(RowName)
|
||||
.parentsUntil(proposalInformationTableRows)
|
||||
.parent()
|
||||
.first()
|
||||
.within(() => {
|
||||
cy.contains(changeType).should('be.visible');
|
||||
cy.contains(newValue).should('be.visible');
|
||||
if (oldValue) cy.contains(oldValue).should('have.class', 'line-through');
|
||||
});
|
||||
getProposalDetailsValue(RowName).within(() => {
|
||||
cy.contains(changeType).should('be.visible');
|
||||
cy.contains(newValue).should('be.visible');
|
||||
if (oldValue) cy.contains(oldValue).should('have.class', 'line-through');
|
||||
});
|
||||
}
|
||||
|
||||
function getFormattedTime() {
|
||||
|
||||
@@ -32,3 +32,5 @@ LC_ALL="en_US.UTF-8"
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
NX_METAMASK_SNAPS=true
|
||||
NX_PRODUCT_PERPETUALS=false
|
||||
NX_UPDATE_MARKET_STATE=false
|
||||
|
||||
@@ -33,3 +33,5 @@ CYPRESS_FAIRGROUND=false
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=false
|
||||
NX_METAMASK_SNAPS=false
|
||||
NX_PRODUCT_PERPETUALS=true
|
||||
NX_UPDATE_MARKET_STATE=true
|
||||
|
||||
@@ -25,3 +25,5 @@ NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/m
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
NX_METAMASK_SNAPS=true
|
||||
NX_PRODUCT_PERPETUALS=true
|
||||
NX_UPDATE_MARKET_STATE=true
|
||||
|
||||
@@ -24,3 +24,5 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=false
|
||||
NX_METAMASK_SNAPS=false
|
||||
NX_PRODUCT_PERPETUALS=false
|
||||
NX_UPDATE_MARKET_STATE=false
|
||||
|
||||
@@ -23,3 +23,5 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://be.mainnet-mirror.vega.rocks/websocket
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=false
|
||||
NX_METAMASK_SNAPS=false
|
||||
NX_PRODUCT_PERPETUALS=false
|
||||
NX_UPDATE_MARKET_STATE=false
|
||||
|
||||
@@ -20,3 +20,5 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
NX_METAMASK_SNAPS=true
|
||||
NX_PRODUCT_PERPETUALS=true
|
||||
NX_UPDATE_MARKET_STATE=true
|
||||
|
||||
@@ -25,3 +25,5 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://be.testnet.vega.xyz/websocket
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
NX_METAMASK_SNAPS=true
|
||||
NX_PRODUCT_PERPETUALS=true
|
||||
NX_UPDATE_MARKET_STATE=true
|
||||
|
||||
@@ -22,3 +22,5 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=false
|
||||
NX_METAMASK_SNAPS=false
|
||||
NX_PRODUCT_PERPETUALS=false
|
||||
NX_UPDATE_MARKET_STATE=false
|
||||
|
||||
@@ -308,7 +308,7 @@ const AppContainer = () => {
|
||||
<Router>
|
||||
<ScrollToTop />
|
||||
<AppStateProvider>
|
||||
<div className="min-h-full text-white">
|
||||
<div className="min-h-full text-white grid">
|
||||
<NodeGuard
|
||||
skeleton={<div>{t('Loading')}</div>}
|
||||
failure={
|
||||
|
||||
@@ -613,6 +613,9 @@
|
||||
"proposalDetails": "Proposal details",
|
||||
"marketSpecification": "Market specification",
|
||||
"viewMarketJson": "View market JSON",
|
||||
"marketId": "Market ID",
|
||||
"marketName": "Market name",
|
||||
"marketCode": "Market code",
|
||||
"proposalDescription": "Description",
|
||||
"currentlySetTo": "Currently expected to ",
|
||||
"currently": "currently",
|
||||
@@ -705,10 +708,17 @@
|
||||
"parameter": "parameter",
|
||||
"NewMarketProposal": "New market proposal",
|
||||
"UpdateMarketProposal": "Update market proposal",
|
||||
"UpdateMarketStateProposal": "Update market state proposal",
|
||||
"MarketChange": "Market change",
|
||||
"MarketStateChange": "Market state change",
|
||||
"MarketDetails": "Market details",
|
||||
"NewAssetProposal": "New asset proposal",
|
||||
"UpdateAssetProposal": "Update asset proposal",
|
||||
"NewFreeformProposal": "New freeform proposal",
|
||||
"NewRawProposal": "New proposal",
|
||||
"MARKET_STATE_UPDATE_TYPE_RESUME": "Resume market",
|
||||
"MARKET_STATE_UPDATE_TYPE_SUSPEND": "Suspend market",
|
||||
"MARKET_STATE_UPDATE_TYPE_TERMINATE": "Terminate market",
|
||||
"MinProposalRequirements": "You must have at least {{value}} VEGA associated to make a proposal",
|
||||
"MinProposalVoteRequirements": "You must have at least {{value}} VEGA associated to vote on this proposal",
|
||||
"totalSupply": "Total Supply",
|
||||
@@ -717,7 +727,11 @@
|
||||
"ProposalDocsPrefix": "For guidance on how to make proposals, see",
|
||||
"NetworkParameter": "Network parameter",
|
||||
"NewMarket": "New market",
|
||||
"NewMarketPerpetualProduct": "New market - perpetual",
|
||||
"NewMarketFutureProduct": "New market - future",
|
||||
"NewMarketSpotProduct": "New market - spot",
|
||||
"UpdateMarket": "Update market",
|
||||
"UpdateMarketState": "Update market state",
|
||||
"NewAsset": "New asset",
|
||||
"UpdateAsset": "Update asset",
|
||||
"AssetID": "Asset ID",
|
||||
|
||||
@@ -12,7 +12,7 @@ import { useRefreshAfterEpoch } from '../../hooks/use-refresh-after-epoch';
|
||||
import { ProposalsListItem } from '../proposals/components/proposals-list-item';
|
||||
import { ProtocolUpgradeProposalsListItem } from '../proposals/components/protocol-upgrade-proposals-list-item/protocol-upgrade-proposals-list-item';
|
||||
import Routes from '../routes';
|
||||
import { ExternalLinks } from '@vegaprotocol/environment';
|
||||
import { ExternalLinks, FLAGS } from '@vegaprotocol/environment';
|
||||
import { removePaginationWrapper } from '@vegaprotocol/utils';
|
||||
import { useNodesQuery } from '../staking/home/__generated__/Nodes';
|
||||
import { useProposalsQuery } from '../proposals/proposals/__generated__/Proposals';
|
||||
@@ -23,7 +23,6 @@ import {
|
||||
import { Heading, SubHeading } from '../../components/heading';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import type { RouteChildProps } from '..';
|
||||
import type { ProposalFieldsFragment } from '../proposals/proposals/__generated__/Proposals';
|
||||
import type { NodesFragmentFragment } from '../staking/home/__generated__/Nodes';
|
||||
import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals';
|
||||
import { useProtocolUpgradeProposalsQuery } from '@vegaprotocol/proposals';
|
||||
@@ -32,6 +31,7 @@ import {
|
||||
orderByUpgradeBlockHeight,
|
||||
} from '../proposals/components/proposals-list/proposals-list';
|
||||
import { BigNumber } from '../../lib/bignumber';
|
||||
import type { ProposalQuery } from '../proposals/proposal/__generated__/Proposal';
|
||||
|
||||
const nodesToShow = 6;
|
||||
|
||||
@@ -39,7 +39,7 @@ const HomeProposals = ({
|
||||
proposals,
|
||||
protocolUpgradeProposals,
|
||||
}: {
|
||||
proposals: ProposalFieldsFragment[];
|
||||
proposals: ProposalQuery['proposal'][];
|
||||
protocolUpgradeProposals: ProtocolUpgradeProposalFieldsFragment[];
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
@@ -60,9 +60,12 @@ const HomeProposals = ({
|
||||
<ProtocolUpgradeProposalsListItem key={index} proposal={proposal} />
|
||||
))}
|
||||
|
||||
{proposals.map((proposal) => (
|
||||
<ProposalsListItem key={proposal.id} proposal={proposal} />
|
||||
))}
|
||||
{proposals.map(
|
||||
(proposal) =>
|
||||
proposal?.id && (
|
||||
<ProposalsListItem key={proposal.id} proposal={proposal} />
|
||||
)
|
||||
)}
|
||||
</ul>
|
||||
|
||||
<div className="mt-6">
|
||||
@@ -182,6 +185,10 @@ const GovernanceHome = ({ name }: RouteChildProps) => {
|
||||
pollInterval: 5000,
|
||||
fetchPolicy: 'network-only',
|
||||
errorPolicy: 'ignore',
|
||||
variables: {
|
||||
includeNewMarketProductFields: !!FLAGS.PRODUCT_PERPETUALS,
|
||||
includeUpdateMarketStates: !!FLAGS.UPDATE_MARKET_STATE,
|
||||
},
|
||||
});
|
||||
|
||||
const {
|
||||
@@ -206,7 +213,9 @@ const GovernanceHome = ({ name }: RouteChildProps) => {
|
||||
const proposals = useMemo(
|
||||
() =>
|
||||
proposalsData
|
||||
? getNotRejectedProposals(proposalsData.proposalsConnection)
|
||||
? getNotRejectedProposals(
|
||||
removePaginationWrapper(proposalsData.proposalsConnection?.edges)
|
||||
)
|
||||
: [],
|
||||
[proposalsData]
|
||||
);
|
||||
|
||||
+25
-4
@@ -3,7 +3,6 @@ import { Lozenge, VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit';
|
||||
import { shorten } from '@vegaprotocol/utils';
|
||||
import { Heading, SubHeading } from '../../../../components/heading';
|
||||
import type { ReactNode } from 'react';
|
||||
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
|
||||
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
|
||||
import { truncateMiddle } from '../../../../lib/truncate-middle';
|
||||
import { CurrentProposalState } from '../current-proposal-state';
|
||||
@@ -20,7 +19,7 @@ export const ProposalHeader = ({
|
||||
isListItem = true,
|
||||
voteState,
|
||||
}: {
|
||||
proposal: ProposalFieldsFragment | ProposalQuery['proposal'];
|
||||
proposal: ProposalQuery['proposal'];
|
||||
isListItem?: boolean;
|
||||
voteState?: VoteState | null;
|
||||
}) => {
|
||||
@@ -37,7 +36,10 @@ export const ProposalHeader = ({
|
||||
|
||||
switch (change?.__typename) {
|
||||
case 'NewMarket': {
|
||||
proposalType = 'NewMarket';
|
||||
proposalType =
|
||||
FLAGS.PRODUCT_PERPETUALS && change?.instrument?.product?.__typename
|
||||
? `NewMarket${change?.instrument?.product?.__typename}`
|
||||
: 'NewMarket';
|
||||
fallbackTitle = t('NewMarketProposal');
|
||||
details = (
|
||||
<>
|
||||
@@ -61,12 +63,31 @@ export const ProposalHeader = ({
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'UpdateMarketState': {
|
||||
proposalType =
|
||||
FLAGS.UPDATE_MARKET_STATE && change?.updateType
|
||||
? t(change.updateType)
|
||||
: 'UpdateMarketState';
|
||||
fallbackTitle = t('UpdateMarketStateProposal');
|
||||
details = (
|
||||
<span>
|
||||
{FLAGS.UPDATE_MARKET_STATE &&
|
||||
change?.market?.id &&
|
||||
change.updateType ? (
|
||||
<>
|
||||
{t(change.updateType)}: {truncateMiddle(change.market.id)}
|
||||
</>
|
||||
) : null}
|
||||
</span>
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'UpdateMarket': {
|
||||
proposalType = 'UpdateMarket';
|
||||
fallbackTitle = t('UpdateMarketProposal');
|
||||
details = (
|
||||
<>
|
||||
<span>{t('Market change')}:</span>{' '}
|
||||
<span>{t('MarketChange')}:</span>{' '}
|
||||
<span>{truncateMiddle(change.marketId)}</span>
|
||||
</>
|
||||
);
|
||||
|
||||
+17
@@ -5,6 +5,8 @@ import {
|
||||
InstrumentInfoPanel,
|
||||
KeyDetailsInfoPanel,
|
||||
LiquidityMonitoringParametersInfoPanel,
|
||||
LiquidityPriceRangeInfoPanel,
|
||||
LiquiditySLAParametersInfoPanel,
|
||||
MetadataInfoPanel,
|
||||
OracleInfoPanel,
|
||||
PriceMonitoringBoundsInfoPanel,
|
||||
@@ -270,6 +272,21 @@ export const ProposalMarketData = ({
|
||||
market={marketData}
|
||||
parentMarket={parentMarketData}
|
||||
/>
|
||||
<h2 className={marketDataHeaderStyles}>
|
||||
{t('Liquidity price range')}
|
||||
</h2>
|
||||
<LiquidityPriceRangeInfoPanel
|
||||
market={marketData}
|
||||
parentMarket={parentMarketData}
|
||||
/>
|
||||
|
||||
<h2 className={marketDataHeaderStyles}>
|
||||
{t('Liquidity SLA protocol')}
|
||||
</h2>
|
||||
<LiquiditySLAParametersInfoPanel
|
||||
market={marketData}
|
||||
parentMarket={parentMarketData}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export * from './proposal-update-market-state';
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
import { fireEvent, render, screen } from '@testing-library/react';
|
||||
import { ProposalUpdateMarketState } from './proposal-update-market-state';
|
||||
import { generateProposal } from '../../test-helpers/generate-proposals';
|
||||
import { MarketUpdateType } from '@vegaprotocol/types';
|
||||
|
||||
describe('<ProposalUpdateMarketState />', () => {
|
||||
const suspendProposal = generateProposal({
|
||||
terms: {
|
||||
change: {
|
||||
__typename: 'UpdateMarketState',
|
||||
market: {
|
||||
id: '1',
|
||||
decimalPlaces: 0,
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
name: 'suspendProposal Name',
|
||||
code: 'suspendProposal Code',
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
quoteName: 'USD',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
updateType: MarketUpdateType.MARKET_STATE_UPDATE_TYPE_SUSPEND,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const resumeProposal = generateProposal({
|
||||
terms: {
|
||||
change: {
|
||||
__typename: 'UpdateMarketState',
|
||||
market: {
|
||||
id: '1',
|
||||
decimalPlaces: 0,
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
name: 'resumeProposal Name',
|
||||
code: 'resumeProposal Code',
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
quoteName: 'USD',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
updateType: MarketUpdateType.MARKET_STATE_UPDATE_TYPE_RESUME,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const terminateProposal = generateProposal({
|
||||
terms: {
|
||||
change: {
|
||||
__typename: 'UpdateMarketState',
|
||||
market: {
|
||||
id: '1',
|
||||
decimalPlaces: 0,
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
name: 'terminateProposal Name',
|
||||
code: 'terminateProposal Code',
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
quoteName: 'USD',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
updateType: MarketUpdateType.MARKET_STATE_UPDATE_TYPE_TERMINATE,
|
||||
price: '123',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
it('should render nothing if proposal is null', () => {
|
||||
render(<ProposalUpdateMarketState proposal={null} />);
|
||||
expect(screen.queryByTestId('proposal-update-market-state')).toBeNull();
|
||||
});
|
||||
|
||||
it('should toggle details when CollapsibleToggle is clicked', () => {
|
||||
render(<ProposalUpdateMarketState proposal={suspendProposal} />);
|
||||
|
||||
expect(
|
||||
screen.queryByTestId('proposal-update-market-state-table')
|
||||
).toBeNull();
|
||||
|
||||
fireEvent.click(screen.getByTestId('proposal-market-data-toggle'));
|
||||
|
||||
expect(
|
||||
screen.getByTestId('proposal-update-market-state-table')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display suspend market information when showDetails is true', () => {
|
||||
render(<ProposalUpdateMarketState proposal={suspendProposal} />);
|
||||
|
||||
fireEvent.click(screen.getByTestId('proposal-market-data-toggle'));
|
||||
|
||||
expect(screen.getByText('suspendProposal Name')).toBeInTheDocument();
|
||||
expect(screen.getByText('suspendProposal Code')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display resume market information when showDetails is true', () => {
|
||||
render(<ProposalUpdateMarketState proposal={resumeProposal} />);
|
||||
|
||||
fireEvent.click(screen.getByTestId('proposal-market-data-toggle'));
|
||||
|
||||
expect(screen.getByText('resumeProposal Name')).toBeInTheDocument();
|
||||
expect(screen.getByText('resumeProposal Code')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display terminate market information when showDetails is true', () => {
|
||||
render(<ProposalUpdateMarketState proposal={terminateProposal} />);
|
||||
|
||||
fireEvent.click(screen.getByTestId('proposal-market-data-toggle'));
|
||||
|
||||
expect(screen.getByText('terminateProposal Name')).toBeInTheDocument();
|
||||
expect(screen.getByText('terminateProposal Code')).toBeInTheDocument();
|
||||
expect(screen.getByText('123 USD')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
KeyValueTable,
|
||||
KeyValueTableRow,
|
||||
RoundedWrapper,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { Row } from '@vegaprotocol/markets';
|
||||
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
|
||||
import { useState } from 'react';
|
||||
import { CollapsibleToggle } from '../../../../components/collapsible-toggle';
|
||||
import { SubHeading } from '../../../../components/heading';
|
||||
|
||||
interface ProposalUpdateMarketStateProps {
|
||||
proposal: ProposalQuery['proposal'];
|
||||
}
|
||||
|
||||
export const ProposalUpdateMarketState = ({
|
||||
proposal,
|
||||
}: ProposalUpdateMarketStateProps) => {
|
||||
const { t } = useTranslation();
|
||||
const [showDetails, setShowDetails] = useState(false);
|
||||
let market;
|
||||
let isTerminate = false;
|
||||
|
||||
if (!proposal) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (proposal?.terms.change.__typename === 'UpdateMarketState') {
|
||||
market = proposal?.terms?.change?.market;
|
||||
isTerminate =
|
||||
proposal?.terms?.change?.updateType ===
|
||||
'MARKET_STATE_UPDATE_TYPE_TERMINATE';
|
||||
}
|
||||
|
||||
return (
|
||||
<section className="relative" data-testid="proposal-update-market-state">
|
||||
<CollapsibleToggle
|
||||
toggleState={showDetails}
|
||||
setToggleState={setShowDetails}
|
||||
dataTestId="proposal-market-data-toggle"
|
||||
>
|
||||
<SubHeading title={t('MarketDetails')} />
|
||||
</CollapsibleToggle>
|
||||
|
||||
{showDetails && (
|
||||
<RoundedWrapper paddingBottom={true} marginBottomLarge={true}>
|
||||
{proposal?.terms.change.__typename === 'UpdateMarketState' && (
|
||||
<KeyValueTable data-testid="proposal-update-market-state-table">
|
||||
<KeyValueTableRow>
|
||||
{t('marketId')}
|
||||
{market?.id}
|
||||
</KeyValueTableRow>
|
||||
<KeyValueTableRow>
|
||||
{t('marketName')}
|
||||
{market?.tradableInstrument?.instrument?.name}
|
||||
</KeyValueTableRow>
|
||||
<KeyValueTableRow noBorder={!isTerminate}>
|
||||
{t('marketCode')}
|
||||
{market?.tradableInstrument?.instrument?.code}
|
||||
</KeyValueTableRow>
|
||||
{isTerminate && (
|
||||
<Row
|
||||
field="termination-price"
|
||||
value={proposal?.terms?.change?.price}
|
||||
assetSymbol={
|
||||
market?.tradableInstrument?.instrument?.product
|
||||
?.__typename === 'Future' ||
|
||||
market?.tradableInstrument?.instrument?.product
|
||||
?.__typename === 'Perpetual'
|
||||
? market?.tradableInstrument?.instrument?.product
|
||||
?.quoteName
|
||||
: undefined
|
||||
}
|
||||
decimalPlaces={market?.decimalPlaces}
|
||||
/>
|
||||
)}
|
||||
</KeyValueTable>
|
||||
)}
|
||||
</RoundedWrapper>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
};
|
||||
@@ -10,21 +10,21 @@ import { UserVote } from '../vote-details';
|
||||
import { ListAsset } from '../list-asset';
|
||||
import Routes from '../../../routes';
|
||||
import { ProposalMarketData } from '../proposal-market-data';
|
||||
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
|
||||
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
|
||||
import type { MarketInfo } from '@vegaprotocol/markets';
|
||||
import type { AssetQuery } from '@vegaprotocol/assets';
|
||||
import { removePaginationWrapper } from '@vegaprotocol/utils';
|
||||
import { ProposalState } from '@vegaprotocol/types';
|
||||
import { ProposalMarketChanges } from '../proposal-market-changes';
|
||||
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';
|
||||
|
||||
export interface ProposalProps {
|
||||
proposal: ProposalFieldsFragment | ProposalQuery['proposal'];
|
||||
proposal: ProposalQuery['proposal'];
|
||||
networkParams: Partial<NetworkParamsResult>;
|
||||
newMarketData?: MarketInfo | null;
|
||||
marketData?: MarketInfo | null;
|
||||
parentMarketData?: MarketInfo | null;
|
||||
assetData?: AssetQuery | null;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
@@ -39,7 +39,7 @@ export const Proposal = ({
|
||||
proposal,
|
||||
networkParams,
|
||||
restData,
|
||||
newMarketData,
|
||||
marketData,
|
||||
parentMarketData,
|
||||
assetData,
|
||||
originalMarketProposalRestData,
|
||||
@@ -74,14 +74,15 @@ export const Proposal = ({
|
||||
|
||||
if (networkParams) {
|
||||
switch (proposal.terms.change.__typename) {
|
||||
case 'UpdateMarket':
|
||||
case 'UpdateMarketState':
|
||||
minVoterBalance =
|
||||
networkParams.governance_proposal_updateMarket_minVoterBalance;
|
||||
break;
|
||||
case 'NewMarket':
|
||||
minVoterBalance =
|
||||
networkParams.governance_proposal_market_minVoterBalance;
|
||||
break;
|
||||
case 'UpdateMarket':
|
||||
minVoterBalance =
|
||||
networkParams.governance_proposal_updateMarket_minVoterBalance;
|
||||
break;
|
||||
case 'NewAsset':
|
||||
minVoterBalance =
|
||||
networkParams.governance_proposal_asset_minVoterBalance;
|
||||
@@ -145,15 +146,21 @@ export const Proposal = ({
|
||||
<ProposalDescription description={proposal.rationale.description} />
|
||||
</div>
|
||||
|
||||
{newMarketData && (
|
||||
{marketData && (
|
||||
<div className="mb-4">
|
||||
<ProposalMarketData
|
||||
marketData={newMarketData}
|
||||
marketData={marketData}
|
||||
parentMarketData={parentMarketData ? parentMarketData : undefined}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{proposal.terms.change.__typename === 'UpdateMarketState' && (
|
||||
<div className="mb-4">
|
||||
<ProposalUpdateMarketState proposal={proposal} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{proposal.terms.change.__typename === 'UpdateMarket' && (
|
||||
<div className="mb-4">
|
||||
<ProposalMarketChanges
|
||||
|
||||
+1
-2
@@ -2,11 +2,10 @@ import { RoundedWrapper } from '@vegaprotocol/ui-toolkit';
|
||||
import { ProposalHeader } from '../proposal-detail-header/proposal-header';
|
||||
import { ProposalsListItemDetails } from './proposals-list-item-details';
|
||||
import { useUserVote } from '../vote-details/use-user-vote';
|
||||
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
|
||||
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
|
||||
|
||||
interface ProposalsListItemProps {
|
||||
proposal?: ProposalFieldsFragment | ProposalQuery['proposal'] | null;
|
||||
proposal?: ProposalQuery['proposal'] | null;
|
||||
}
|
||||
|
||||
export const ProposalsListItem = ({ proposal }: ProposalsListItemProps) => {
|
||||
|
||||
@@ -16,14 +16,14 @@ import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/propos
|
||||
import { ExternalLinks } from '@vegaprotocol/environment';
|
||||
|
||||
interface ProposalsListProps {
|
||||
proposals: Array<ProposalFieldsFragment | ProposalQuery['proposal']>;
|
||||
proposals: Array<ProposalQuery['proposal']>;
|
||||
protocolUpgradeProposals: ProtocolUpgradeProposalFieldsFragment[];
|
||||
lastBlockHeight?: string;
|
||||
}
|
||||
|
||||
interface SortedProposalsProps {
|
||||
open: Array<ProposalFieldsFragment | ProposalQuery['proposal']>;
|
||||
closed: Array<ProposalFieldsFragment | ProposalQuery['proposal']>;
|
||||
open: ProposalQuery['proposal'][];
|
||||
closed: ProposalQuery['proposal'][];
|
||||
}
|
||||
|
||||
interface SortedProtocolUpgradeProposalsProps {
|
||||
@@ -31,7 +31,7 @@ interface SortedProtocolUpgradeProposalsProps {
|
||||
closed: ProtocolUpgradeProposalFieldsFragment[];
|
||||
}
|
||||
|
||||
export const orderByDate = (arr: ProposalFieldsFragment[]) =>
|
||||
export const orderByDate = (arr: ProposalQuery['proposal'][]) =>
|
||||
orderBy(
|
||||
arr,
|
||||
[
|
||||
@@ -92,12 +92,12 @@ export const ProposalsList = ({
|
||||
return {
|
||||
open:
|
||||
initialSorting.open.length > 0
|
||||
? orderByDate(initialSorting.open as ProposalFieldsFragment[])
|
||||
? orderByDate(initialSorting.open as ProposalQuery['proposal'][])
|
||||
: [],
|
||||
closed:
|
||||
initialSorting.closed.length > 0
|
||||
? orderByDate(
|
||||
initialSorting.closed as ProposalFieldsFragment[]
|
||||
initialSorting.closed as ProposalQuery['proposal'][]
|
||||
).reverse()
|
||||
: [],
|
||||
};
|
||||
|
||||
+2
-5
@@ -3,20 +3,17 @@ import { useTranslation } from 'react-i18next';
|
||||
import { Heading } from '../../../../components/heading';
|
||||
import { ProposalsListItem } from '../proposals-list-item';
|
||||
import { ProposalsListFilter } from '../proposals-list-filter';
|
||||
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
|
||||
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
|
||||
|
||||
interface ProposalsListProps {
|
||||
proposals: Array<ProposalQuery['proposal'] | ProposalFieldsFragment>;
|
||||
proposals: ProposalQuery['proposal'][];
|
||||
}
|
||||
|
||||
export const RejectedProposalsList = ({ proposals }: ProposalsListProps) => {
|
||||
const { t } = useTranslation();
|
||||
const [filterString, setFilterString] = useState('');
|
||||
|
||||
const filterPredicate = (
|
||||
p: ProposalFieldsFragment | ProposalQuery['proposal']
|
||||
) =>
|
||||
const filterPredicate = (p: ProposalQuery['proposal']) =>
|
||||
p?.id?.includes(filterString) ||
|
||||
p?.party?.id?.toString().includes(filterString);
|
||||
|
||||
|
||||
@@ -28,17 +28,20 @@ export const useProposalNetworkParams = ({
|
||||
NetworkParams.governance_proposal_freeform_requiredParticipation,
|
||||
]);
|
||||
|
||||
const fallback = {
|
||||
requiredMajority: new BigNumber(1),
|
||||
requiredMajorityLP: new BigNumber(0),
|
||||
requiredParticipation: new BigNumber(1),
|
||||
requiredParticipationLP: new BigNumber(0),
|
||||
};
|
||||
|
||||
if (!params) {
|
||||
return {
|
||||
requiredMajority: new BigNumber(1),
|
||||
requiredMajorityLP: new BigNumber(0),
|
||||
requiredParticipation: new BigNumber(1),
|
||||
requiredParticipationLP: new BigNumber(0),
|
||||
};
|
||||
return fallback;
|
||||
}
|
||||
|
||||
switch (proposal?.terms.change.__typename) {
|
||||
case 'UpdateMarket':
|
||||
case 'UpdateMarketState':
|
||||
return {
|
||||
requiredMajority:
|
||||
params.governance_proposal_updateMarket_requiredMajority,
|
||||
@@ -89,6 +92,6 @@ export const useProposalNetworkParams = ({
|
||||
),
|
||||
};
|
||||
default:
|
||||
throw new Error('Unknown proposal type');
|
||||
return fallback;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,4 +1,53 @@
|
||||
query Proposal($proposalId: ID!) {
|
||||
fragment NewMarketProductField on Proposal {
|
||||
terms {
|
||||
change {
|
||||
... on NewMarket {
|
||||
instrument {
|
||||
product {
|
||||
__typename
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fragment UpdateMarketState on Proposal {
|
||||
terms {
|
||||
change {
|
||||
... on UpdateMarketState {
|
||||
updateType
|
||||
market {
|
||||
decimalPlaces
|
||||
id
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
product {
|
||||
__typename
|
||||
... on Future {
|
||||
quoteName
|
||||
}
|
||||
... on Perpetual {
|
||||
quoteName
|
||||
}
|
||||
}
|
||||
name
|
||||
code
|
||||
}
|
||||
}
|
||||
}
|
||||
updateType
|
||||
price
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query Proposal(
|
||||
$proposalId: ID!
|
||||
$includeNewMarketProductField: Boolean!
|
||||
$includeUpdateMarketState: Boolean!
|
||||
) {
|
||||
proposal(id: $proposalId) {
|
||||
id
|
||||
rationale {
|
||||
@@ -13,6 +62,8 @@ query Proposal($proposalId: ID!) {
|
||||
id
|
||||
}
|
||||
errorDetails
|
||||
...NewMarketProductField @include(if: $includeNewMarketProductField)
|
||||
...UpdateMarketState @include(if: $includeUpdateMarketState)
|
||||
terms {
|
||||
closingDatetime
|
||||
enactmentDatetime
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -53,7 +53,11 @@ export const ProposalContainer = () => {
|
||||
const { data, loading, error, refetch } = useProposalQuery({
|
||||
fetchPolicy: 'network-only',
|
||||
errorPolicy: 'ignore',
|
||||
variables: { proposalId: params.proposalId || '' },
|
||||
variables: {
|
||||
proposalId: params.proposalId || '',
|
||||
includeNewMarketProductField: !!FLAGS.PRODUCT_PERPETUALS,
|
||||
includeUpdateMarketState: !!FLAGS.UPDATE_MARKET_STATE,
|
||||
},
|
||||
skip: !params.proposalId,
|
||||
});
|
||||
|
||||
@@ -91,9 +95,9 @@ export const ProposalContainer = () => {
|
||||
);
|
||||
|
||||
const {
|
||||
data: newMarketData,
|
||||
loading: newMarketLoading,
|
||||
error: newMarketError,
|
||||
data: marketData,
|
||||
loading: marketLoading,
|
||||
error: marketError,
|
||||
} = useDataProvider({
|
||||
dataProvider: marketInfoProvider,
|
||||
skipUpdates: true,
|
||||
@@ -109,9 +113,9 @@ export const ProposalContainer = () => {
|
||||
error: parentMarketIdError,
|
||||
} = useParentMarketIdQuery({
|
||||
variables: {
|
||||
marketId: newMarketData?.id || '',
|
||||
marketId: marketData?.id || '',
|
||||
},
|
||||
skip: !FLAGS.SUCCESSOR_MARKETS || !isSuccessor || !newMarketData?.id,
|
||||
skip: !FLAGS.SUCCESSOR_MARKETS || !isSuccessor || !marketData?.id,
|
||||
});
|
||||
|
||||
const {
|
||||
@@ -191,7 +195,7 @@ export const ProposalContainer = () => {
|
||||
<AsyncRenderer
|
||||
loading={
|
||||
loading ||
|
||||
newMarketLoading ||
|
||||
marketLoading ||
|
||||
assetLoading ||
|
||||
networkParamsLoading ||
|
||||
parentMarketIdLoading ||
|
||||
@@ -206,7 +210,7 @@ export const ProposalContainer = () => {
|
||||
}
|
||||
error={
|
||||
error ||
|
||||
newMarketError ||
|
||||
marketError ||
|
||||
assetError ||
|
||||
networkParamsError ||
|
||||
parentMarketIdError ||
|
||||
@@ -218,7 +222,7 @@ export const ProposalContainer = () => {
|
||||
data={{
|
||||
...data,
|
||||
...networkParams,
|
||||
...(newMarketData ? { newMarketData } : {}),
|
||||
...(marketData ? { newMarketData: marketData } : {}),
|
||||
...(parentMarketData ? { parentMarketData } : {}),
|
||||
...(assetData ? { assetData } : {}),
|
||||
...(restData ? { restData } : {}),
|
||||
@@ -235,7 +239,7 @@ export const ProposalContainer = () => {
|
||||
proposal={data.proposal}
|
||||
networkParams={networkParams}
|
||||
restData={restData}
|
||||
newMarketData={newMarketData}
|
||||
marketData={marketData}
|
||||
parentMarketData={parentMarketData}
|
||||
assetData={assetData}
|
||||
originalMarketProposalRestData={originalMarketProposalRestData}
|
||||
|
||||
@@ -1,3 +1,48 @@
|
||||
fragment NewMarketProductFields on Proposal {
|
||||
terms {
|
||||
change {
|
||||
... on NewMarket {
|
||||
instrument {
|
||||
product {
|
||||
__typename
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fragment UpdateMarketStates on Proposal {
|
||||
terms {
|
||||
change {
|
||||
... on UpdateMarketState {
|
||||
updateType
|
||||
market {
|
||||
decimalPlaces
|
||||
id
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
product {
|
||||
__typename
|
||||
... on Future {
|
||||
quoteName
|
||||
}
|
||||
... on Perpetual {
|
||||
quoteName
|
||||
}
|
||||
}
|
||||
name
|
||||
code
|
||||
}
|
||||
}
|
||||
}
|
||||
updateType
|
||||
price
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fragment ProposalFields on Proposal {
|
||||
id
|
||||
rationale {
|
||||
@@ -79,11 +124,16 @@ fragment ProposalFields on Proposal {
|
||||
}
|
||||
}
|
||||
|
||||
query Proposals {
|
||||
query Proposals(
|
||||
$includeNewMarketProductFields: Boolean!
|
||||
$includeUpdateMarketStates: Boolean!
|
||||
) {
|
||||
proposalsConnection {
|
||||
edges {
|
||||
node {
|
||||
...ProposalFields
|
||||
...NewMarketProductFields @include(if: $includeNewMarketProductFields)
|
||||
...UpdateMarketStates @include(if: $includeUpdateMarketStates)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+65
-5
@@ -3,13 +3,67 @@ import * as Types from '@vegaprotocol/types';
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type NewMarketProductFieldsFragment = { __typename?: 'Proposal', terms: { __typename?: 'ProposalTerms', change: { __typename?: 'CancelTransfer' } | { __typename?: 'NewAsset' } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', product?: { __typename: 'FutureProduct' } | { __typename: 'PerpetualProduct' } | { __typename: 'SpotProduct' } | null } } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset' } | { __typename?: 'UpdateMarket' } | { __typename?: 'UpdateMarketState' } | { __typename?: 'UpdateNetworkParameter' } | { __typename?: 'UpdateReferralProgram' } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram' } } };
|
||||
|
||||
export type UpdateMarketStatesFragment = { __typename?: 'Proposal', terms: { __typename?: 'ProposalTerms', change: { __typename?: 'CancelTransfer' } | { __typename?: 'NewAsset' } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket' } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset' } | { __typename?: 'UpdateMarket' } | { __typename?: 'UpdateMarketState', updateType: Types.MarketUpdateType, price?: string | null, market: { __typename?: 'Market', decimalPlaces: number, id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, code: string, product: { __typename: 'Future', quoteName: string } | { __typename: 'Perpetual', quoteName: string } | { __typename: 'Spot' } } } } } | { __typename?: 'UpdateNetworkParameter' } | { __typename?: 'UpdateReferralProgram' } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram' } } };
|
||||
|
||||
export type ProposalFieldsFragment = { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: any, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string }, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: any, enactmentDatetime?: any | null, change: { __typename?: 'CancelTransfer' } | { __typename: 'NewAsset', name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string, withdrawThreshold: string, lifetimeLimit: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null } } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset', quantum: string, assetId: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateMarketState' } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } | { __typename?: 'UpdateReferralProgram' } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram' } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string } } };
|
||||
|
||||
export type ProposalsQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
export type ProposalsQueryVariables = Types.Exact<{
|
||||
includeNewMarketProductFields: Types.Scalars['Boolean'];
|
||||
includeUpdateMarketStates: Types.Scalars['Boolean'];
|
||||
}>;
|
||||
|
||||
|
||||
export type ProposalsQuery = { __typename?: 'Query', proposalsConnection?: { __typename?: 'ProposalsConnection', edges?: Array<{ __typename?: 'ProposalEdge', node: { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: any, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string }, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: any, enactmentDatetime?: any | null, change: { __typename?: 'CancelTransfer' } | { __typename: 'NewAsset', name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string, withdrawThreshold: string, lifetimeLimit: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null } } | { __typename?: '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 } } } } | null> | null } | null };
|
||||
export type ProposalsQuery = { __typename?: 'Query', proposalsConnection?: { __typename?: 'ProposalsConnection', edges?: Array<{ __typename?: 'ProposalEdge', node: { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: any, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string }, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: any, enactmentDatetime?: any | null, change: { __typename?: 'CancelTransfer' } | { __typename: 'NewAsset', name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string, withdrawThreshold: string, lifetimeLimit: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null, product?: { __typename: 'FutureProduct' } | { __typename: 'PerpetualProduct' } | { __typename: 'SpotProduct' } | null } } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset', quantum: string, assetId: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateMarketState', updateType: Types.MarketUpdateType, price?: string | null, market: { __typename?: 'Market', decimalPlaces: number, id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, code: string, product: { __typename: 'Future', quoteName: string } | { __typename: 'Perpetual', quoteName: string } | { __typename: 'Spot' } } } } } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } | { __typename?: 'UpdateReferralProgram' } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram' } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string } } } } | null> | null } | null };
|
||||
|
||||
export const NewMarketProductFieldsFragmentDoc = gql`
|
||||
fragment NewMarketProductFields on Proposal {
|
||||
terms {
|
||||
change {
|
||||
... on NewMarket {
|
||||
instrument {
|
||||
product {
|
||||
__typename
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const UpdateMarketStatesFragmentDoc = gql`
|
||||
fragment UpdateMarketStates on Proposal {
|
||||
terms {
|
||||
change {
|
||||
... on UpdateMarketState {
|
||||
updateType
|
||||
market {
|
||||
decimalPlaces
|
||||
id
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
product {
|
||||
__typename
|
||||
... on Future {
|
||||
quoteName
|
||||
}
|
||||
... on Perpetual {
|
||||
quoteName
|
||||
}
|
||||
}
|
||||
name
|
||||
code
|
||||
}
|
||||
}
|
||||
}
|
||||
updateType
|
||||
price
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const ProposalFieldsFragmentDoc = gql`
|
||||
fragment ProposalFields on Proposal {
|
||||
id
|
||||
@@ -93,16 +147,20 @@ export const ProposalFieldsFragmentDoc = gql`
|
||||
}
|
||||
`;
|
||||
export const ProposalsDocument = gql`
|
||||
query Proposals {
|
||||
query Proposals($includeNewMarketProductFields: Boolean!, $includeUpdateMarketStates: Boolean!) {
|
||||
proposalsConnection {
|
||||
edges {
|
||||
node {
|
||||
...ProposalFields
|
||||
...NewMarketProductFields @include(if: $includeNewMarketProductFields)
|
||||
...UpdateMarketStates @include(if: $includeUpdateMarketStates)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
${ProposalFieldsFragmentDoc}`;
|
||||
${ProposalFieldsFragmentDoc}
|
||||
${NewMarketProductFieldsFragmentDoc}
|
||||
${UpdateMarketStatesFragmentDoc}`;
|
||||
|
||||
/**
|
||||
* __useProposalsQuery__
|
||||
@@ -116,10 +174,12 @@ export const ProposalsDocument = gql`
|
||||
* @example
|
||||
* const { data, loading, error } = useProposalsQuery({
|
||||
* variables: {
|
||||
* includeNewMarketProductFields: // value for 'includeNewMarketProductFields'
|
||||
* includeUpdateMarketStates: // value for 'includeUpdateMarketStates'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useProposalsQuery(baseOptions?: Apollo.QueryHookOptions<ProposalsQuery, ProposalsQueryVariables>) {
|
||||
export function useProposalsQuery(baseOptions: Apollo.QueryHookOptions<ProposalsQuery, ProposalsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<ProposalsQuery, ProposalsQueryVariables>(ProposalsDocument, options);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useTranslation } from 'react-i18next';
|
||||
import { SplashLoader } from '../../../components/splash-loader';
|
||||
import { ProposalsList } from '../components/proposals-list';
|
||||
import { useProposalsQuery } from './__generated__/Proposals';
|
||||
import { getNodes } from '@vegaprotocol/utils';
|
||||
import { getNodes, removePaginationWrapper } from '@vegaprotocol/utils';
|
||||
import {
|
||||
ProposalState,
|
||||
ProtocolUpgradeProposalStatus,
|
||||
@@ -15,14 +15,13 @@ import type { NodeConnection, NodeEdge } from '@vegaprotocol/utils';
|
||||
import type { ProposalFieldsFragment } from './__generated__/Proposals';
|
||||
import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals';
|
||||
import { useProtocolUpgradeProposalsQuery } from '@vegaprotocol/proposals';
|
||||
import { FLAGS } from '@vegaprotocol/environment';
|
||||
|
||||
export function getNotRejectedProposals<T extends ProposalFieldsFragment>(
|
||||
data?: NodeConnection<NodeEdge<T>> | null
|
||||
): T[] {
|
||||
export function getNotRejectedProposals(data?: ProposalFieldsFragment[]) {
|
||||
return flow([
|
||||
(data) =>
|
||||
getNodes<ProposalFieldsFragment>(data, (p) =>
|
||||
p ? p.state !== ProposalState.STATE_REJECTED : false
|
||||
data.filter(
|
||||
(p: ProposalFieldsFragment) => p?.state !== ProposalState.STATE_REJECTED
|
||||
),
|
||||
])(data);
|
||||
}
|
||||
@@ -47,6 +46,10 @@ export const ProposalsContainer = () => {
|
||||
pollInterval: 5000,
|
||||
fetchPolicy: 'network-only',
|
||||
errorPolicy: 'ignore',
|
||||
variables: {
|
||||
includeNewMarketProductFields: !!FLAGS.PRODUCT_PERPETUALS,
|
||||
includeUpdateMarketStates: !!FLAGS.UPDATE_MARKET_STATE,
|
||||
},
|
||||
});
|
||||
|
||||
const {
|
||||
@@ -60,7 +63,10 @@ export const ProposalsContainer = () => {
|
||||
});
|
||||
|
||||
const proposals = useMemo(
|
||||
() => getNotRejectedProposals(data?.proposalsConnection),
|
||||
() =>
|
||||
getNotRejectedProposals(
|
||||
removePaginationWrapper(data?.proposalsConnection?.edges)
|
||||
),
|
||||
[data]
|
||||
);
|
||||
|
||||
|
||||
@@ -6,11 +6,11 @@ import { SplashLoader } from '../../../components/splash-loader';
|
||||
import { RejectedProposalsList } from '../components/proposals-list';
|
||||
import type { ProposalFieldsFragment } from '../proposals/__generated__/Proposals';
|
||||
import { useProposalsQuery } from '../proposals/__generated__/Proposals';
|
||||
import type { NodeConnection, NodeEdge } from '@vegaprotocol/utils';
|
||||
import { getNodes } from '@vegaprotocol/utils';
|
||||
import { removePaginationWrapper } from '@vegaprotocol/utils';
|
||||
import flow from 'lodash/flow';
|
||||
import orderBy from 'lodash/orderBy';
|
||||
import { ProposalState } from '@vegaprotocol/types';
|
||||
import { FLAGS } from '@vegaprotocol/environment';
|
||||
|
||||
const orderByDate = (arr: ProposalFieldsFragment[]) =>
|
||||
orderBy(
|
||||
@@ -22,13 +22,11 @@ const orderByDate = (arr: ProposalFieldsFragment[]) =>
|
||||
['desc', 'desc']
|
||||
);
|
||||
|
||||
export function getRejectedProposals<T extends ProposalFieldsFragment>(
|
||||
data?: NodeConnection<NodeEdge<ProposalFieldsFragment>> | null
|
||||
): T[] {
|
||||
export function getRejectedProposals(data?: ProposalFieldsFragment[] | null) {
|
||||
return flow([
|
||||
(data) =>
|
||||
getNodes<ProposalFieldsFragment>(data, (p) =>
|
||||
p ? p?.state === ProposalState.STATE_REJECTED : false
|
||||
data.filter(
|
||||
(p: ProposalFieldsFragment) => p?.state === ProposalState.STATE_REJECTED
|
||||
),
|
||||
orderByDate,
|
||||
])(data);
|
||||
@@ -36,11 +34,21 @@ export function getRejectedProposals<T extends ProposalFieldsFragment>(
|
||||
|
||||
export const RejectedProposalsContainer = () => {
|
||||
const { t } = useTranslation();
|
||||
const { data, loading, error } = useProposalsQuery();
|
||||
const { data, loading, error } = useProposalsQuery({
|
||||
pollInterval: 5000,
|
||||
fetchPolicy: 'network-only',
|
||||
errorPolicy: 'ignore',
|
||||
variables: {
|
||||
includeNewMarketProductFields: !!FLAGS.PRODUCT_PERPETUALS,
|
||||
includeUpdateMarketStates: !!FLAGS.UPDATE_MARKET_STATE,
|
||||
},
|
||||
});
|
||||
|
||||
const proposals = useMemo(
|
||||
() =>
|
||||
getRejectedProposals<ProposalFieldsFragment>(data?.proposalsConnection),
|
||||
getRejectedProposals(
|
||||
removePaginationWrapper(data?.proposalsConnection?.edges)
|
||||
),
|
||||
[data]
|
||||
);
|
||||
|
||||
|
||||
+10
-4
@@ -1,4 +1,4 @@
|
||||
import { useMemo, useEffect, useState, useCallback } from 'react';
|
||||
import { useMemo, useEffect, useState, useCallback, useRef } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { AsyncRenderer, Pagination } from '@vegaprotocol/ui-toolkit';
|
||||
import { removePaginationWrapper } from '@vegaprotocol/utils';
|
||||
@@ -86,12 +86,18 @@ export const EpochIndividualRewards = ({
|
||||
[epochId, page, refetch, delegationsPagination, pubKey]
|
||||
);
|
||||
|
||||
const prevEpochIdRef = useRef<number | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
// when the epoch changes, we want to refetch the data to update the current page
|
||||
if (data) {
|
||||
if (prevEpochIdRef.current === null) {
|
||||
prevEpochIdRef.current = epochId;
|
||||
} else if (epochId !== prevEpochIdRef.current) {
|
||||
// When the epoch changes, we want to refetch the data to update the current page
|
||||
refetchData();
|
||||
}
|
||||
}, [epochId, data, refetchData]);
|
||||
|
||||
prevEpochIdRef.current = epochId;
|
||||
}, [epochId, refetchData]);
|
||||
|
||||
return (
|
||||
<AsyncRenderer
|
||||
|
||||
+5
-5
@@ -3,7 +3,7 @@ import { forwardRef, useMemo, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Button, Icon } from '@vegaprotocol/ui-toolkit';
|
||||
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { useAppState } from '../../../../contexts/app-state/app-state-context';
|
||||
import { BigNumber } from '../../../../lib/bignumber';
|
||||
import {
|
||||
@@ -85,17 +85,17 @@ const TopThirdCellRenderer = (
|
||||
}}
|
||||
className="grid grid-cols-[60px_1fr] w-full h-full py-4 px-0 text-sm text-white text-center overflow-scroll"
|
||||
>
|
||||
<div className="text-xs text-left px-3">
|
||||
<div className="px-3 text-xs text-left">
|
||||
{params?.data?.rankingDisplay}
|
||||
</div>
|
||||
<div className="whitespace-normal px-3">
|
||||
<div className="px-3 whitespace-normal">
|
||||
<div className="mb-4">
|
||||
<Button
|
||||
data-testid="show-all-validators"
|
||||
rightIcon={
|
||||
<Icon
|
||||
name="arrow-right"
|
||||
className="fill-current mr-2 align-text-top"
|
||||
className="mr-2 align-text-top fill-current"
|
||||
/>
|
||||
}
|
||||
className="inline-flex items-center"
|
||||
@@ -103,7 +103,7 @@ const TopThirdCellRenderer = (
|
||||
{t('Reveal top validators')}
|
||||
</Button>
|
||||
</div>
|
||||
<p className="font-semibold text-white mb-0">
|
||||
<p className="mb-0 font-semibold text-white">
|
||||
{t(
|
||||
'Validators with too great a stake share will have the staking rewards for their delegators penalised.'
|
||||
)}
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import { forwardRef, useMemo, useRef } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { useAppState } from '../../../../contexts/app-state/app-state-context';
|
||||
import { BigNumber } from '../../../../lib/bignumber';
|
||||
import {
|
||||
|
||||
@@ -64,48 +64,6 @@ describe('accounts', { tags: '@smoke' }, () => {
|
||||
cy.getByTestId('Collateral').click({ force: true });
|
||||
});
|
||||
|
||||
it('should open asset details dialog when clicked on symbol', () => {
|
||||
// 7001-COLL-008
|
||||
// 6501-ASSE-001
|
||||
// 6501-ASSE-002
|
||||
// 6501-ASSE-003
|
||||
// 6501-ASSE-004
|
||||
// 6501-ASSE-005
|
||||
// 6501-ASSE-006
|
||||
// 6501-ASSE-007
|
||||
// 6501-ASSE-008
|
||||
// 6501-ASSE-009
|
||||
// 6501-ASSE-010
|
||||
// 6501-ASSE-011
|
||||
// 6501-ASSE-012
|
||||
// 6501-ASSE-013
|
||||
const titles = [
|
||||
'ID',
|
||||
'Type',
|
||||
'Name',
|
||||
'Symbol',
|
||||
'Decimals',
|
||||
'Quantum',
|
||||
'Status',
|
||||
'Contract address',
|
||||
'Withdrawal threshold',
|
||||
'Lifetime limit',
|
||||
'Infrastructure fee account balance',
|
||||
'Global reward pool account balance',
|
||||
'Maker paid fees account balance',
|
||||
'Maker received fees account balance',
|
||||
'Liquidity provision fee reward account balance',
|
||||
'Market proposer reward account balance',
|
||||
];
|
||||
cy.get('[col-id="asset.symbol"]').contains('tEURO').click();
|
||||
cy.get('[data-testid$="_label"]').should('have.length', 16);
|
||||
cy.get('[data-testid$="_label"]').each((element, index) => {
|
||||
cy.wrap(element).should('have.text', titles[index]);
|
||||
});
|
||||
cy.getByTestId(dialogClose).click();
|
||||
cy.getByTestId(dialogClose).should('not.exist');
|
||||
});
|
||||
|
||||
it('should open usage breakdown dialog when clicked on used', () => {
|
||||
// 7001-COLL-009
|
||||
cy.get('[col-id="used"]').contains('1.01').click();
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import { mockConnectWallet } from '@vegaprotocol/cypress';
|
||||
import {
|
||||
orderPriceField,
|
||||
placeOrderBtn,
|
||||
toggleLimit,
|
||||
toggleLong,
|
||||
toggleMarket,
|
||||
toggleShort,
|
||||
} from '../support/deal-ticket';
|
||||
|
||||
describe('deal ticket basics', { tags: '@smoke' }, () => {
|
||||
before(() => {
|
||||
cy.mockTradingPage();
|
||||
cy.mockSubscription();
|
||||
cy.clearAllLocalStorage();
|
||||
cy.setOnBoardingViewed();
|
||||
cy.visit('/#/markets/market-0');
|
||||
cy.wait('@Markets');
|
||||
});
|
||||
|
||||
it('must show place order button and connect wallet if wallet is not connected', () => {
|
||||
// 0003-WTXN-001
|
||||
cy.getByTestId('connect-vega-wallet'); // Not connected
|
||||
cy.getByTestId(placeOrderBtn).should('exist');
|
||||
cy.getByTestId('order-connect-wallet').should('exist');
|
||||
});
|
||||
|
||||
it('must be able to select order direction - long/short', function () {
|
||||
// 7002-SORD-004
|
||||
cy.getByTestId(toggleShort).click().next('input').should('be.checked');
|
||||
cy.getByTestId(toggleLong).click().next('input').should('be.checked');
|
||||
});
|
||||
|
||||
it('must be able to select order type - limit/market', function () {
|
||||
// 7002-SORD-005
|
||||
// 7002-SORD-006
|
||||
// 7002-SORD-007
|
||||
cy.getByTestId(toggleLimit).click().next('input').should('be.checked');
|
||||
cy.getByTestId(toggleMarket).click().next('input').should('be.checked');
|
||||
});
|
||||
|
||||
it('order connect vega wallet button should connect', () => {
|
||||
mockConnectWallet();
|
||||
cy.getByTestId(toggleLimit).click();
|
||||
cy.getByTestId(orderPriceField).clear().type('101');
|
||||
cy.getByTestId('order-connect-wallet').click();
|
||||
cy.getByTestId('dialog-content').should('be.visible');
|
||||
cy.getByTestId('connectors-list')
|
||||
.find('[data-testid="connector-jsonRpc"]')
|
||||
.click();
|
||||
cy.wait('@walletReq');
|
||||
cy.getByTestId(placeOrderBtn).should('be.visible');
|
||||
cy.getByTestId(toggleLimit).next('input').should('be.checked');
|
||||
cy.getByTestId(orderPriceField).should('have.value', '101');
|
||||
});
|
||||
|
||||
it('sidebar should be open after reload', () => {
|
||||
cy.mockTradingPage();
|
||||
cy.getByTestId('deal-ticket-form').should('be.visible');
|
||||
cy.getByTestId('Order').click();
|
||||
cy.getByTestId('deal-ticket-form').should('not.exist');
|
||||
cy.reload();
|
||||
cy.getByTestId('deal-ticket-form').should('be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
describe(
|
||||
'market states not accepting orders',
|
||||
{ tags: '@smoke', testIsolation: true },
|
||||
function () {
|
||||
//7002-SORD-062
|
||||
//7002-SORD-063
|
||||
//7002-SORD-066
|
||||
|
||||
const states = [
|
||||
Schema.MarketState.STATE_REJECTED,
|
||||
Schema.MarketState.STATE_CANCELLED,
|
||||
Schema.MarketState.STATE_CLOSED,
|
||||
Schema.MarketState.STATE_SETTLED,
|
||||
Schema.MarketState.STATE_TRADING_TERMINATED,
|
||||
];
|
||||
|
||||
states.forEach((marketState) => {
|
||||
describe(marketState, function () {
|
||||
beforeEach(function () {
|
||||
cy.mockTradingPage(marketState);
|
||||
cy.mockSubscription();
|
||||
cy.setVegaWallet();
|
||||
cy.visit('/#/markets/market-0');
|
||||
});
|
||||
it('must display that market is not accepting orders', function () {
|
||||
cy.getByTestId('deal-ticket-error-message-summary').should(
|
||||
'have.text',
|
||||
`This market is ${marketState
|
||||
.split('_')
|
||||
.pop()
|
||||
?.toLowerCase()} and not accepting orders`
|
||||
);
|
||||
// 7002-SORD-060
|
||||
cy.getByTestId('place-order').should('be.enabled');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -1,134 +0,0 @@
|
||||
import {
|
||||
orderPriceField,
|
||||
orderSizeField,
|
||||
orderTIFDropDown,
|
||||
placeOrderBtn,
|
||||
toggleLimit,
|
||||
toggleMarket,
|
||||
} from '../support/deal-ticket';
|
||||
|
||||
describe('deal ticker order validation', { tags: '@smoke' }, () => {
|
||||
before(() => {
|
||||
cy.setVegaWallet();
|
||||
cy.mockTradingPage();
|
||||
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();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.mockTradingPage();
|
||||
cy.getByTestId('deal-ticket-fee-margin-required').click();
|
||||
});
|
||||
|
||||
describe('limit order', () => {
|
||||
before(() => {
|
||||
cy.getByTestId(toggleLimit).click();
|
||||
});
|
||||
|
||||
it('must see the price unit', function () {
|
||||
// 7002-SORD-018
|
||||
cy.getByTestId(orderPriceField).next().should('have.text', 'DAI');
|
||||
});
|
||||
|
||||
it('must see warning when placing an order with expiry date in past', () => {
|
||||
const expiresAt = new Date(Date.now() - 24 * 60 * 60 * 1000);
|
||||
const expiresAtInputValue = expiresAt.toISOString().substring(0, 16);
|
||||
cy.getByTestId(toggleLimit).click();
|
||||
cy.getByTestId(orderPriceField).clear().type('0.1');
|
||||
cy.getByTestId(orderSizeField).clear().type('1');
|
||||
cy.getByTestId(orderTIFDropDown).select('TIME_IN_FORCE_GTT');
|
||||
|
||||
cy.log('choosing yesterday');
|
||||
cy.getByTestId('date-picker-field').type(expiresAtInputValue);
|
||||
|
||||
cy.getByTestId(placeOrderBtn).click();
|
||||
|
||||
cy.getByTestId('deal-ticket-error-message-expiry').should(
|
||||
'have.text',
|
||||
'The expiry date that you have entered appears to be in the past'
|
||||
);
|
||||
});
|
||||
|
||||
it('must see warning if price has too many digits after decimal place', function () {
|
||||
// 7002-SORD-059
|
||||
cy.getByTestId(toggleLimit).click();
|
||||
cy.getByTestId(orderTIFDropDown).select('TIME_IN_FORCE_GTC');
|
||||
cy.getByTestId(orderSizeField).clear().type('1');
|
||||
cy.getByTestId(orderPriceField).clear().type('1.123456');
|
||||
cy.getByTestId(placeOrderBtn).click();
|
||||
cy.getByTestId('deal-ticket-error-message-price').should(
|
||||
'have.text',
|
||||
'Price accepts up to 5 decimal places'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('market order', () => {
|
||||
before(() => {
|
||||
cy.getByTestId(toggleMarket).click();
|
||||
cy.getByTestId(placeOrderBtn).click();
|
||||
});
|
||||
|
||||
it('must not see the price unit', function () {
|
||||
// 7002-SORD-019
|
||||
cy.getByTestId(orderPriceField).should('not.exist');
|
||||
});
|
||||
|
||||
it('must warn if order size input has too many digits after the decimal place', function () {
|
||||
// 7002-SORD-016
|
||||
cy.getByTestId(orderSizeField).clear().type('1.234');
|
||||
// 7002-SORD-060
|
||||
cy.getByTestId(placeOrderBtn).should('be.enabled');
|
||||
cy.getByTestId('deal-ticket-error-message-size').should(
|
||||
'have.text',
|
||||
'Size must be whole numbers for this market'
|
||||
);
|
||||
});
|
||||
|
||||
it('must warn if order size is set to 0', function () {
|
||||
cy.getByTestId(orderSizeField).clear().type('0');
|
||||
cy.getByTestId(placeOrderBtn).should('be.enabled');
|
||||
cy.getByTestId('deal-ticket-error-message-size').should(
|
||||
'have.text',
|
||||
'Size cannot be lower than 1'
|
||||
);
|
||||
});
|
||||
|
||||
it('must have total margin available', () => {
|
||||
// 7001-COLL-011
|
||||
cy.getByTestId('deal-ticket-fee-total-margin-available').within(() => {
|
||||
cy.get('[data-state="closed"]').should(
|
||||
'have.text',
|
||||
'Total margin available100.01 tDAI'
|
||||
);
|
||||
});
|
||||
cy.getByTestId('deal-ticket-fee-margin-required').click();
|
||||
});
|
||||
|
||||
it('must have current margin allocation', () => {
|
||||
cy.getByTestId('deal-ticket-fee-current-margin-allocation').within(() => {
|
||||
cy.get('[data-state="closed"]:first').should(
|
||||
'have.text',
|
||||
'Current margin allocation'
|
||||
);
|
||||
});
|
||||
cy.getByTestId('deal-ticket-fee-margin-required').click();
|
||||
});
|
||||
|
||||
it('should open usage breakdown dialog when clicked on current margin allocation', () => {
|
||||
cy.getByTestId('deal-ticket-fee-current-margin-allocation').within(() => {
|
||||
cy.get('button').click();
|
||||
});
|
||||
cy.getByTestId('usage-breakdown').should('exist');
|
||||
cy.getByTestId('dialog-close').click();
|
||||
cy.getByTestId('deal-ticket-fee-margin-required').click();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
testOrderAmendment,
|
||||
} from '../support/order-validation';
|
||||
|
||||
const orderSymbol = 'market.tradableInstrument.instrument.code';
|
||||
const orderSymbol = 'instrument-code';
|
||||
const orderSize = 'size';
|
||||
const orderType = 'type';
|
||||
const orderStatus = 'status';
|
||||
@@ -229,10 +229,7 @@ describe('subscribe orders', { tags: '@smoke' }, () => {
|
||||
status: Schema.OrderStatus.STATUS_FILLED,
|
||||
});
|
||||
cy.getByTestId(`order-status-${orderId}`).should('have.text', 'Filled');
|
||||
cy.get('[col-id="market.tradableInstrument.instrument.code"]').contains(
|
||||
'[title="Future"]',
|
||||
'Futr'
|
||||
);
|
||||
cy.get(`[col-id="${orderSymbol}"]`).contains('[title="Future"]', 'Futr');
|
||||
});
|
||||
|
||||
it('must see a rejected order', () => {
|
||||
|
||||
@@ -15,6 +15,7 @@ NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/annou
|
||||
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
|
||||
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import MarketPage from '../market';
|
||||
|
||||
export const ClosedMarketPage = () => {
|
||||
return <MarketPage closed />;
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export { ClosedMarketPage as default } from './closed-market';
|
||||
@@ -9,9 +9,10 @@ import { useGlobalStore, usePageTitleStore } from '../../stores';
|
||||
import { TradeGrid } from './trade-grid';
|
||||
import { TradePanels } from './trade-panels';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { Links } from '../../lib/links';
|
||||
import { Links, Routes } 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
|
||||
@@ -56,7 +57,7 @@ const TitleUpdater = ({
|
||||
return null;
|
||||
};
|
||||
|
||||
export const MarketPage = () => {
|
||||
export const MarketPage = ({ closed }: { closed?: boolean }) => {
|
||||
const { marketId } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const currentRouteId = useGetCurrentRouteId();
|
||||
@@ -70,16 +71,33 @@ export const MarketPage = () => {
|
||||
const { data, error, loading } = useMarket(marketId);
|
||||
|
||||
useEffect(() => {
|
||||
if (data?.id && data.id !== lastMarketId) {
|
||||
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) {
|
||||
update({ marketId: data.id });
|
||||
}
|
||||
}, [update, lastMarketId, data?.id]);
|
||||
}, [update, lastMarketId, data?.id, closed]);
|
||||
|
||||
useEffect(() => {
|
||||
if (largeScreen && view === undefined) {
|
||||
setViews({ type: ViewType.Order }, currentRouteId);
|
||||
setViews(
|
||||
{ type: closed ? ViewType.Info : ViewType.Order },
|
||||
currentRouteId
|
||||
);
|
||||
}
|
||||
}, [setViews, view, currentRouteId, largeScreen]);
|
||||
}, [setViews, view, currentRouteId, largeScreen, closed]);
|
||||
|
||||
const pinnedAsset = data && getAsset(data);
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import type {
|
||||
VegaICellRendererParams,
|
||||
VegaValueFormatterParams,
|
||||
} from '@vegaprotocol/datagrid';
|
||||
import { AgGridLazy as AgGrid, COL_DEFS } from '@vegaprotocol/datagrid';
|
||||
import { AgGrid, COL_DEFS } from '@vegaprotocol/datagrid';
|
||||
import { useMemo } from 'react';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import type { Asset } from '@vegaprotocol/types';
|
||||
@@ -22,6 +22,8 @@ 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,
|
||||
@@ -125,6 +127,7 @@ const ClosedMarketsDataGrid = ({
|
||||
rowData: Row[];
|
||||
error: Error | undefined;
|
||||
}) => {
|
||||
const handleOnSelect = useClosedMarketClickHandler();
|
||||
const openAssetDialog = useAssetDetailsDialogStore((store) => store.open);
|
||||
|
||||
const colDefs = useMemo(() => {
|
||||
@@ -281,6 +284,27 @@ 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);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { TypedDataAgGrid } from '@vegaprotocol/datagrid';
|
||||
import { AgGridLazy as AgGrid, PriceFlashCell } from '@vegaprotocol/datagrid';
|
||||
import { AgGrid, PriceFlashCell } from '@vegaprotocol/datagrid';
|
||||
import type { MarketMaybeWithData } from '@vegaprotocol/markets';
|
||||
import { useColumnDefs } from './use-column-defs';
|
||||
|
||||
@@ -8,6 +8,7 @@ export const getRowId = ({ data }: { data: { id: string } }) => data.id;
|
||||
const defaultColDef = {
|
||||
sortable: true,
|
||||
filter: true,
|
||||
resizable: true,
|
||||
filterParams: { buttons: ['reset'] },
|
||||
};
|
||||
|
||||
|
||||
@@ -7,13 +7,21 @@ import {
|
||||
import type { FieldValues } from 'react-hook-form';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import classNames from 'classnames';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { useEffect, useState } from 'react';
|
||||
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';
|
||||
|
||||
export const ApplyCodeForm = () => {
|
||||
const [finalized, setFinalized] = useState<boolean>(false);
|
||||
const [status, setStatus] = useState<
|
||||
'requested' | 'failed' | 'successful' | null
|
||||
>(null);
|
||||
const txHash = useRef<string | null>(null);
|
||||
const { isReadOnly, pubKey, sendTx } = useVegaWallet();
|
||||
const {
|
||||
register,
|
||||
@@ -24,6 +32,9 @@ export const ApplyCodeForm = () => {
|
||||
} = useForm();
|
||||
const [params] = useSearchParams();
|
||||
|
||||
const { data: referee } = useReferral(pubKey, 'referee');
|
||||
const { data: referrer } = useReferral(pubKey, 'referrer');
|
||||
|
||||
useEffect(() => {
|
||||
const code = params.get('code');
|
||||
if (code) setValue('code', code);
|
||||
@@ -34,23 +45,67 @@ export const ApplyCodeForm = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
setStatus('requested');
|
||||
|
||||
sendTx(pubKey, {
|
||||
applyReferralCode: {
|
||||
id: code as string,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
setFinalized(true);
|
||||
if (!res) {
|
||||
setError('code', {
|
||||
type: 'required',
|
||||
message: 'The transaction could not be sent',
|
||||
});
|
||||
}
|
||||
if (res) {
|
||||
txHash.current = res.transactionHash.toLowerCase();
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
setError('code', {
|
||||
type: 'required',
|
||||
message: 'Your code has been rejected',
|
||||
});
|
||||
if (err.message.includes('user rejected')) {
|
||||
setStatus(null);
|
||||
} else {
|
||||
setError('code', {
|
||||
type: 'required',
|
||||
message: 'Your code has been rejected',
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if (finalized) {
|
||||
useTransactionEventSubscription({
|
||||
variables: { partyId: pubKey || '' },
|
||||
skip: !pubKey,
|
||||
fetchPolicy: 'no-cache',
|
||||
onData: ({ data: result }) =>
|
||||
result.data?.busEvents?.forEach((event) => {
|
||||
if (event.event.__typename === 'TransactionResult') {
|
||||
const hash = event.event.hash.toLowerCase();
|
||||
if (txHash.current && txHash.current === hash) {
|
||||
const err = event.event.error;
|
||||
const status = event.event.status;
|
||||
if (err) {
|
||||
setStatus(null);
|
||||
setError('code', {
|
||||
type: 'required',
|
||||
message: err,
|
||||
});
|
||||
}
|
||||
if (status && !err) {
|
||||
setStatus('successful');
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
});
|
||||
|
||||
if (referee || referrer) {
|
||||
return <Navigate to={Routes.REFERRALS} />;
|
||||
}
|
||||
|
||||
if (status === 'successful') {
|
||||
return (
|
||||
<div className="w-1/2 mx-auto">
|
||||
<h3 className="mb-5 text-xl text-center uppercase calt flex flex-row gap-2 justify-center items-center">
|
||||
@@ -63,6 +118,27 @@ export const ApplyCodeForm = () => {
|
||||
);
|
||||
}
|
||||
|
||||
const getButtonProps = () => {
|
||||
if (isReadOnly || !pubKey) {
|
||||
return {
|
||||
disabled: true,
|
||||
children: 'Apply',
|
||||
};
|
||||
}
|
||||
|
||||
if (status === 'requested') {
|
||||
return {
|
||||
disabled: true,
|
||||
children: 'Confirm in wallet...',
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
children: 'Apply',
|
||||
};
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-1/2 mx-auto">
|
||||
<h3 className="mb-5 text-xl text-center uppercase calt">
|
||||
@@ -86,13 +162,7 @@ export const ApplyCodeForm = () => {
|
||||
})}
|
||||
/>
|
||||
</label>
|
||||
<Button
|
||||
disabled={isReadOnly || !pubKey}
|
||||
className="w-full"
|
||||
type="submit"
|
||||
>
|
||||
Apply
|
||||
</Button>
|
||||
<Button className="w-full" type="submit" {...getButtonProps()} />
|
||||
</form>
|
||||
{errors.code && (
|
||||
<InputError>{errors.code.message?.toString()}</InputError>
|
||||
|
||||
@@ -38,18 +38,36 @@ export const RainbowButton = ({
|
||||
|
||||
const RAINBOW_TAB_STYLE = classNames(
|
||||
'inline-block',
|
||||
'bg-vega-clight-500 dark:bg-vega-cdark-500 hover:bg-vega-clight-400 dark:hover:bg-vega-cdark-400',
|
||||
'data-[state="active"]:text-white data-[state="active"]:bg-rainbow data-[state="active"]:hover:bg-none data-[state="active"]:hover:bg-vega-pink-500 dark:data-[state="active"]:hover:bg-vega-pink-500',
|
||||
'[&.active]:text-white [&.active]:bg-rainbow [&.active]:hover:bg-none [&.active]:hover:bg-vega-pink-500 dark:[&.active]:hover:bg-vega-pink-500',
|
||||
'bg-vega-clight-500 dark:bg-vega-cdark-500',
|
||||
'hover:bg-vega-clight-400 dark:hover:bg-vega-cdark-400',
|
||||
'data-[state="active"]:text-white data-[state="active"]:bg-rainbow',
|
||||
'data-[state="active"]:hover:bg-none data-[state="active"]:hover:bg-vega-pink-500 dark:data-[state="active"]:hover:bg-vega-pink-500',
|
||||
'[&.active]:text-white [&.active]:bg-rainbow',
|
||||
'[&.active]:hover:bg-none [&.active]:hover:bg-vega-pink-500 dark:[&.active]:hover:bg-vega-pink-500',
|
||||
'px-5 py-3',
|
||||
'first:rounded-tl-lg last:rounded-tr-lg'
|
||||
);
|
||||
|
||||
const DISABLED_RAINBOW_TAB_STYLE = classNames(
|
||||
'pointer-events-none',
|
||||
'text-vega-clight-100 dark:text-vega-cdark-100',
|
||||
'data-[state="active"]:text-white',
|
||||
'[&.active]:text-white'
|
||||
);
|
||||
|
||||
export const RainbowTabButton = forwardRef<
|
||||
HTMLButtonElement,
|
||||
ButtonHTMLAttributes<HTMLButtonElement>
|
||||
>(({ children, ...props }, ref) => (
|
||||
<button ref={ref} className={RAINBOW_TAB_STYLE} {...props}>
|
||||
{ disabled?: boolean } & ButtonHTMLAttributes<HTMLButtonElement>
|
||||
>(({ children, className, disabled = false, ...props }, ref) => (
|
||||
<button
|
||||
ref={ref}
|
||||
className={classNames(
|
||||
RAINBOW_TAB_STYLE,
|
||||
{ 'pointer-events-none': disabled },
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
));
|
||||
@@ -58,9 +76,19 @@ RainbowTabButton.displayName = 'RainbowTabButton';
|
||||
export const RainbowTabLink = ({
|
||||
to,
|
||||
children,
|
||||
className,
|
||||
disabled = false,
|
||||
...props
|
||||
}: ComponentProps<typeof NavLink>) => (
|
||||
<NavLink to={to} className={RAINBOW_TAB_STYLE} {...props}>
|
||||
}: { disabled?: boolean } & ComponentProps<typeof NavLink>) => (
|
||||
<NavLink
|
||||
to={to}
|
||||
className={classNames(
|
||||
RAINBOW_TAB_STYLE,
|
||||
disabled && DISABLED_RAINBOW_TAB_STYLE,
|
||||
typeof className === 'string' ? className : undefined
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</NavLink>
|
||||
);
|
||||
|
||||
@@ -9,8 +9,14 @@ import { TiersContainer } from './tiers';
|
||||
import { RainbowTabLink } from './buttons';
|
||||
import { Outlet } from 'react-router-dom';
|
||||
import { Routes } from '../../lib/links';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { useReferral } from './hooks/use-referral';
|
||||
|
||||
export const Referrals = () => {
|
||||
const { pubKey } = useVegaWallet();
|
||||
const { data: referee } = useReferral(pubKey, 'referee');
|
||||
const { data: referrer } = useReferral(pubKey, 'referrer');
|
||||
|
||||
return (
|
||||
<>
|
||||
<LandingBanner />
|
||||
@@ -19,7 +25,10 @@ export const Referrals = () => {
|
||||
<RainbowTabLink end to={Routes.REFERRALS}>
|
||||
Your referrals
|
||||
</RainbowTabLink>
|
||||
<RainbowTabLink to={Routes.REFERRALS_APPLY_CODE}>
|
||||
<RainbowTabLink
|
||||
disabled={Boolean(referee || referrer)}
|
||||
to={Routes.REFERRALS_APPLY_CODE}
|
||||
>
|
||||
Apply a code
|
||||
</RainbowTabLink>
|
||||
</div>
|
||||
|
||||
@@ -9,5 +9,11 @@ export const AnnouncementBanner = () => {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <Banner app="console" configUrl={ANNOUNCEMENTS_CONFIG_URL} />;
|
||||
return (
|
||||
<Banner
|
||||
app="console"
|
||||
configUrl={ANNOUNCEMENTS_CONFIG_URL}
|
||||
background="url('/banner-bg.jpg')"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -53,7 +53,7 @@ export const HeaderStat = ({
|
||||
<div data-testid="item-header" id={id}>
|
||||
{heading}
|
||||
</div>
|
||||
<Tooltip description={description}>
|
||||
<Tooltip description={description} underline>
|
||||
<div
|
||||
data-testid="item-value"
|
||||
aria-labelledby={id}
|
||||
|
||||
@@ -23,6 +23,10 @@ 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>
|
||||
|
||||
@@ -12,10 +12,6 @@ import {
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { ExternalLink, Indicator } from '@vegaprotocol/ui-toolkit';
|
||||
import { DocsLinks } from '@vegaprotocol/environment';
|
||||
import {
|
||||
NetworkParams,
|
||||
useNetworkParams,
|
||||
} from '@vegaprotocol/network-parameters';
|
||||
import { useCheckLiquidityStatus } from '@vegaprotocol/liquidity';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
@@ -31,12 +27,8 @@ export const LiquidityHeader = () => {
|
||||
const assetDecimalPlaces = asset?.decimals || 0;
|
||||
const symbol = asset?.symbol;
|
||||
|
||||
const { params } = useNetworkParams([
|
||||
NetworkParams.market_liquidity_stakeToCcyVolume,
|
||||
NetworkParams.market_liquidity_targetstake_triggering_ratio,
|
||||
]);
|
||||
const triggeringRatio =
|
||||
params.market_liquidity_targetstake_triggering_ratio || '1';
|
||||
market?.liquidityMonitoringParameters.triggeringRatio || '1';
|
||||
|
||||
const { percentage, status } = useCheckLiquidityStatus({
|
||||
suppliedStake: suppliedStake || 0,
|
||||
|
||||
@@ -61,7 +61,6 @@ describe('MarketSelectorItem', () => {
|
||||
indicativeVolume: '100',
|
||||
marketState: MarketState.STATE_ACTIVE,
|
||||
marketTradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
marketValueProxy: '100',
|
||||
markPrice: '50000',
|
||||
midPrice: '100',
|
||||
staticMidPrice: '100',
|
||||
|
||||
@@ -126,10 +126,12 @@ export const MarketSelector = ({
|
||||
onSelect={onSelect}
|
||||
noItems={
|
||||
filter.product === Product.Perpetual
|
||||
? t('Perpetual markets coming soon.')
|
||||
? t('No perpetual markets.')
|
||||
: filter.product === Product.Spot
|
||||
? t('Spot markets coming soon.')
|
||||
: t('No markets')
|
||||
: filter.product === Product.Future
|
||||
? t('No future markets.')
|
||||
: t('No markets.')
|
||||
}
|
||||
allProducts={allProducts}
|
||||
/>
|
||||
|
||||
@@ -7,6 +7,8 @@ import * as Schema from '@vegaprotocol/types';
|
||||
import { HeaderStat } from '../header';
|
||||
import { useCallback, useRef, useState } from 'react';
|
||||
import * as constants from '../constants';
|
||||
import { DocsLinks } from '@vegaprotocol/environment';
|
||||
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
export const MarketState = ({ market }: { market: Market | null }) => {
|
||||
const [marketState, setMarketState] = useState<Schema.MarketState | null>(
|
||||
@@ -90,5 +92,20 @@ const getMarketStateTooltip = (state: Schema.MarketState | null) => {
|
||||
);
|
||||
}
|
||||
|
||||
if (state === Schema.MarketState.STATE_SUSPENDED_VIA_GOVERNANCE) {
|
||||
return (
|
||||
<p>
|
||||
{t(
|
||||
`This market has been suspended via a governance vote and can be resumed or terminated by further votes.`
|
||||
)}
|
||||
{DocsLinks && (
|
||||
<ExternalLink href={DocsLinks.MARKET_LIFECYCLE} className="ml-1">
|
||||
{t('Find out more')}
|
||||
</ExternalLink>
|
||||
)}
|
||||
</p>
|
||||
);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
@@ -28,14 +28,20 @@ export interface OrderContainerProps {
|
||||
filter?: Filter;
|
||||
}
|
||||
|
||||
const AUTO_SIZE_COLUMNS = ['instrument-code'];
|
||||
|
||||
export const OrdersContainer = ({ filter }: OrderContainerProps) => {
|
||||
const { pubKey, isReadOnly } = useVegaWallet();
|
||||
const onMarketClick = useMarketClickHandler(true);
|
||||
const onOrderTypeClick = useMarketLiquidityClickHandler();
|
||||
const { gridState, updateGridState } = useOrderListGridState(filter);
|
||||
const gridStoreCallbacks = useDataGridEvents(gridState, (newState) => {
|
||||
updateGridState(filter, newState);
|
||||
});
|
||||
const gridStoreCallbacks = useDataGridEvents(
|
||||
gridState,
|
||||
(newState) => {
|
||||
updateGridState(filter, newState);
|
||||
},
|
||||
AUTO_SIZE_COLUMNS
|
||||
);
|
||||
|
||||
if (!pubKey) {
|
||||
return <Splash>{t('Please connect Vega wallet')}</Splash>;
|
||||
|
||||
@@ -10,6 +10,8 @@ import { create } from 'zustand';
|
||||
import { persist } from 'zustand/middleware';
|
||||
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
|
||||
|
||||
const AUTO_SIZE_COLUMNS = ['marketCode'];
|
||||
|
||||
export const PositionsContainer = ({ allKeys }: { allKeys?: boolean }) => {
|
||||
const onMarketClick = useMarketClickHandler(true);
|
||||
const { pubKey, pubKeys, isReadOnly } = useVegaWallet();
|
||||
@@ -17,7 +19,11 @@ export const PositionsContainer = ({ allKeys }: { allKeys?: boolean }) => {
|
||||
const showClosed = usePositionsStore((store) => store.showClosedMarkets);
|
||||
const gridStore = usePositionsStore((store) => store.gridStore);
|
||||
const updateGridStore = usePositionsStore((store) => store.updateGridStore);
|
||||
const gridStoreCallbacks = useDataGridEvents(gridStore, updateGridStore);
|
||||
const gridStoreCallbacks = useDataGridEvents(
|
||||
gridStore,
|
||||
updateGridStore,
|
||||
AUTO_SIZE_COLUMNS
|
||||
);
|
||||
|
||||
if (!pubKey) {
|
||||
return (
|
||||
|
||||
@@ -55,7 +55,6 @@ const MarketSidebarButtons = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<SidebarDivider />
|
||||
<SidebarButton
|
||||
view={ViewType.Order}
|
||||
icon={VegaIconNames.TICKET}
|
||||
@@ -72,6 +71,33 @@ const MarketSidebarButtons = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const AssetSidebarButtons = () => {
|
||||
const currentRouteId = useGetCurrentRouteId();
|
||||
|
||||
return (
|
||||
<>
|
||||
<SidebarButton
|
||||
view={ViewType.Deposit}
|
||||
icon={VegaIconNames.DEPOSIT}
|
||||
tooltip={t('Deposit')}
|
||||
routeId={currentRouteId}
|
||||
/>
|
||||
<SidebarButton
|
||||
view={ViewType.Withdraw}
|
||||
icon={VegaIconNames.WITHDRAW}
|
||||
tooltip={t('Withdraw')}
|
||||
routeId={currentRouteId}
|
||||
/>
|
||||
<SidebarButton
|
||||
view={ViewType.Transfer}
|
||||
icon={VegaIconNames.TRANSFER}
|
||||
tooltip={t('Transfer')}
|
||||
routeId={currentRouteId}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const Sidebar = () => {
|
||||
const currentRouteId = useGetCurrentRouteId();
|
||||
const navClasses = 'flex lg:flex-col items-center gap-2 lg:gap-4 p-1';
|
||||
@@ -80,41 +106,49 @@ export const Sidebar = () => {
|
||||
return (
|
||||
<div className="flex h-full p-1 lg:flex-col gap-2" data-testid="sidebar">
|
||||
<nav className={navClasses}>
|
||||
{/* sidebar options that always show */}
|
||||
<SidebarButton
|
||||
view={ViewType.Deposit}
|
||||
icon={VegaIconNames.DEPOSIT}
|
||||
tooltip={t('Deposit')}
|
||||
routeId={currentRouteId}
|
||||
/>
|
||||
<SidebarButton
|
||||
view={ViewType.Withdraw}
|
||||
icon={VegaIconNames.WITHDRAW}
|
||||
tooltip={t('Withdraw')}
|
||||
routeId={currentRouteId}
|
||||
/>
|
||||
<SidebarButton
|
||||
view={ViewType.Transfer}
|
||||
icon={VegaIconNames.TRANSFER}
|
||||
tooltip={t('Transfer')}
|
||||
routeId={currentRouteId}
|
||||
/>
|
||||
{/* buttons for specific routes */}
|
||||
<Routes>
|
||||
<Route path="markets/all" element={<AssetSidebarButtons />} />
|
||||
<Route path="portfolio">
|
||||
<Route
|
||||
// Show deposit/withdraw/transfer sidebar options only on portflio dashboard (index)
|
||||
index={true}
|
||||
element={<AssetSidebarButtons />}
|
||||
/>
|
||||
</Route>
|
||||
<Route
|
||||
path="markets/all"
|
||||
// render nothing for markets/all, otherwise markets/:marketId will match with markets/all
|
||||
element={null}
|
||||
path="markets/:marketId"
|
||||
element={
|
||||
<>
|
||||
<AssetSidebarButtons />
|
||||
<SidebarDivider />
|
||||
<MarketSidebarButtons />
|
||||
</>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
// render nothing for portfolio
|
||||
path="portfolio"
|
||||
element={null}
|
||||
/>
|
||||
<Route path="markets/:marketId" element={<MarketSidebarButtons />} />
|
||||
<Route
|
||||
path="liquidity/:marketId"
|
||||
element={<MarketSidebarButtons />}
|
||||
element={
|
||||
<>
|
||||
<AssetSidebarButtons />
|
||||
<SidebarDivider />
|
||||
<MarketSidebarButtons />
|
||||
</>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="markets/all/closed/:marketId"
|
||||
element={
|
||||
<>
|
||||
<AssetSidebarButtons />
|
||||
<SidebarDivider />
|
||||
<SidebarButton
|
||||
view={ViewType.Info}
|
||||
icon={VegaIconNames.BREAKDOWN}
|
||||
tooltip={t('Market specification')}
|
||||
routeId={currentRouteId}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</Routes>
|
||||
</nav>
|
||||
|
||||
@@ -20,3 +20,16 @@ export const useMarketLiquidityClickHandler = () => {
|
||||
window.open(`/#/liquidity/${selectedId}`, metaKey ? '_blank' : '_self');
|
||||
}, []);
|
||||
};
|
||||
|
||||
export const useClosedMarketClickHandler = (replace = false) => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (selectedId: string, metaKey?: boolean) => {
|
||||
const link = Links.CLOSED_MARKETS(selectedId);
|
||||
if (metaKey) {
|
||||
window.open(`/#${link}`, '_blank');
|
||||
} else {
|
||||
navigate(link, { replace });
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ import trimEnd from 'lodash/trimEnd';
|
||||
export const Routes = {
|
||||
HOME: '/',
|
||||
MARKETS: '/markets/all',
|
||||
CLOSED_MARKETS: '/markets/all/closed/:marketId',
|
||||
MARKET: '/markets/:marketId',
|
||||
LIQUIDITY: '/liquidity/:marketId',
|
||||
PORTFOLIO: '/portfolio',
|
||||
@@ -28,6 +29,8 @@ export const Links: ConsoleLinks = {
|
||||
MARKET: (marketId: string) =>
|
||||
trimEnd(Routes.MARKET.replace(':marketId', marketId)),
|
||||
MARKETS: () => Routes.MARKETS,
|
||||
CLOSED_MARKETS: (marketId: string) =>
|
||||
trimEnd(Routes.CLOSED_MARKETS.replace(':marketId', marketId)),
|
||||
PORTFOLIO: () => Routes.PORTFOLIO,
|
||||
LIQUIDITY: (marketId: string) =>
|
||||
trimEnd(Routes.LIQUIDITY.replace(':marketId', marketId)),
|
||||
|
||||
@@ -5,6 +5,7 @@ const MARKET_TEMPLATE = [
|
||||
MarketState.STATE_ACTIVE,
|
||||
MarketState.STATE_SUSPENDED,
|
||||
MarketState.STATE_PENDING,
|
||||
MarketState.STATE_SUSPENDED_VIA_GOVERNANCE,
|
||||
];
|
||||
|
||||
export const isMarketActive = (state: MarketState) => {
|
||||
|
||||
@@ -4,33 +4,24 @@ export default function Document() {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
{/*
|
||||
{/*
|
||||
meta tags
|
||||
- next advised against using _document for this, so they exist in our
|
||||
- next advised against using _document for this, so they exist in our
|
||||
- single page index.page.tsx
|
||||
*/}
|
||||
|
||||
{/* icons */}
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/x-icon"
|
||||
href="https://static.vega.xyz/favicon.ico"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
content="https://static.vega.xyz/favicon.ico"
|
||||
/>
|
||||
|
||||
{/* fonts */}
|
||||
{/* preload fonts */}
|
||||
<link
|
||||
rel="preload"
|
||||
href="https://static.vega.xyz/AlphaLyrae-Medium.woff2"
|
||||
href="/AlphaLyrae-Medium.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
/>
|
||||
|
||||
{/* styles */}
|
||||
<link rel="stylesheet" href="https://static.vega.xyz/fonts.css" />
|
||||
{/* icons */}
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||
<link rel="apple-touch-icon" content="/favicon.ico" />
|
||||
|
||||
{/* eslint-disable-next-line @next/next/no-css-tags */}
|
||||
<link rel="stylesheet" href="/preloader.css" media="all" />
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import { FLAGS } from '@vegaprotocol/environment';
|
||||
// These must remain dynamically imported as pennant cannot be compiled by nextjs due to ESM
|
||||
// Using dynamic imports is a workaround for this until pennant is published as ESM
|
||||
const MarketPage = lazy(() => import('../client-pages/market'));
|
||||
const ClosedMarketPage = lazy(() => import('../client-pages/closed-market'));
|
||||
const Portfolio = lazy(() => import('../client-pages/portfolio'));
|
||||
|
||||
const NotFound = () => (
|
||||
@@ -101,6 +102,11 @@ export const routerConfig: RouteObject[] = compact([
|
||||
element: <MarketPage />,
|
||||
id: Routes.MARKET,
|
||||
},
|
||||
{
|
||||
path: 'all/closed/:marketId',
|
||||
element: <ClosedMarketPage />,
|
||||
id: Routes.CLOSED_MARKETS,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -19,17 +19,11 @@ export default function Index() {
|
||||
<meta name="og:url" content="https://console.vega.xyz/" />
|
||||
<meta name="og:title" content="Vega Protocol - Console" />
|
||||
<meta name="og:site_name" content="Vega Protocol - Console" />
|
||||
<meta name="og:image" content="https://static.vega.xyz/favicon.ico" />
|
||||
<meta
|
||||
name="twitter:card"
|
||||
content="https://static.vega.xyz/favicon.ico"
|
||||
/>
|
||||
<meta name="og:image" content="./favicon.ico" />
|
||||
<meta name="twitter:card" content="./favicon.ico" />
|
||||
<meta name="twitter:title" content="Vega Protocol - Console" />
|
||||
<meta name="twitter:description" content="Vega Protocol - Console" />
|
||||
<meta
|
||||
name="twitter:image"
|
||||
content="https://static.vega.xyz/favicon.ico"
|
||||
/>
|
||||
<meta name="twitter:image" content="./favicon.ico" />
|
||||
<meta name="twitter:image:alt" content="VEGA logo" />
|
||||
<meta name="twitter:site" content="@vegaprotocol" />
|
||||
</Head>
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
@import 'ag-grid-community/styles/ag-grid.css';
|
||||
@import 'ag-grid-community/styles/ag-theme-balham.css';
|
||||
|
||||
/** Load AlphaLyrae font */
|
||||
@font-face {
|
||||
font-family: AlphaLyrae;
|
||||
src: url('/AlphaLyrae-Medium.woff2') format('woff2'),
|
||||
url('/AlphaLyrae-Medium.woff') format('woff');
|
||||
}
|
||||
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
@@ -103,8 +110,8 @@ html [data-theme='light'] {
|
||||
--pennant-color-depth-sell-fill: theme(colors.market.red.DEFAULT);
|
||||
--pennant-color-depth-sell-stroke: theme(colors.market.red.650);
|
||||
|
||||
--pennant-color-volume-buy: theme(colors.market.green.300);
|
||||
--pennant-color-volume-sell: theme(colors.market.red.300);
|
||||
--pennant-color-volume-buy: theme(colors.market.green.DEFAULT);
|
||||
--pennant-color-volume-sell: theme(colors.market.red.DEFAULT);
|
||||
}
|
||||
|
||||
html [data-theme='dark'] {
|
||||
@@ -125,7 +132,7 @@ html [data-theme='dark'] {
|
||||
--pennant-color-depth-sell-stroke: theme(colors.market.red.DEFAULT);
|
||||
|
||||
--pennant-color-volume-buy: theme(colors.market.green.600);
|
||||
--pennant-color-volume-sell: theme(colors.market.red.650);
|
||||
--pennant-color-volume-sell: theme(colors.market.red.DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 101 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 7.2 KiB |
@@ -1,14 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
entrypoint="${1:-nginx}"
|
||||
|
||||
if [[ "$entrypoint" = "nginx" ]]; then
|
||||
nginx -g 'daemon off;'
|
||||
elif [[ "$entrypoint" = "ipfs" ]]; then
|
||||
ipfs config profile apply server
|
||||
ipfs config --json Addresses.Gateway '"/ip4/127.0.0.1/tcp/80"'
|
||||
ipfs daemon
|
||||
elif [[ "-c" ]]; then
|
||||
shift
|
||||
/bin/sh -c "$@"
|
||||
fi
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
VegaIconNames,
|
||||
TooltipCellComponent,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { AgGrid } from '@vegaprotocol/datagrid';
|
||||
import type {
|
||||
IGetRowsParams,
|
||||
IRowNode,
|
||||
|
||||
@@ -13,7 +13,7 @@ import type {
|
||||
VegaICellRendererParams,
|
||||
} from '@vegaprotocol/datagrid';
|
||||
import { ProgressBarCell } from '@vegaprotocol/datagrid';
|
||||
import { AgGridLazy as AgGrid, PriceCell } from '@vegaprotocol/datagrid';
|
||||
import { AgGrid, PriceCell } from '@vegaprotocol/datagrid';
|
||||
import type { ColDef } from 'ag-grid-community';
|
||||
import { accountValuesComparator } from './accounts-table';
|
||||
import { MarginHealthChart } from './margin-health-chart';
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
export type AnnouncementBannerProps = {
|
||||
app: AppNameType;
|
||||
configUrl: string;
|
||||
background?: string;
|
||||
};
|
||||
|
||||
// run only if below the allowed maximum delay ~24.8 days (https://developer.mozilla.org/en-US/docs/Web/API/setTimeout#maximum_delay_value)
|
||||
@@ -36,6 +37,7 @@ const doesEndInTheFuture = (now: Date, data: Announcement) => {
|
||||
export const AnnouncementBanner = ({
|
||||
app,
|
||||
configUrl,
|
||||
background,
|
||||
}: AnnouncementBannerProps) => {
|
||||
const [isVisible, setVisible] = useState(false);
|
||||
const { data, reload } = useAnnouncement(app, configUrl);
|
||||
@@ -79,10 +81,10 @@ export const AnnouncementBanner = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<Banner className="relative px-10">
|
||||
<Banner className="relative px-10" background={background}>
|
||||
<div
|
||||
data-testid="app-announcement"
|
||||
className="relative font-alpha flex gap-2 justify-center text-center text-lg text-white"
|
||||
className="relative flex justify-center text-lg text-center text-white font-alpha gap-2"
|
||||
>
|
||||
<span>{data.text}</span>{' '}
|
||||
{data.urlText && data.url && (
|
||||
@@ -90,7 +92,7 @@ export const AnnouncementBanner = ({
|
||||
)}
|
||||
</div>
|
||||
<button
|
||||
className="absolute right-0 top-0 p-4 w-10 h-full flex items-center justify-center text-white"
|
||||
className="absolute top-0 right-0 flex items-center justify-center w-10 h-full p-4 text-white"
|
||||
data-testid="app-announcement-close"
|
||||
onClick={() => {
|
||||
setVisible(false);
|
||||
|
||||
@@ -62,6 +62,20 @@ const WrappedAssetDetailsDialog = ({ assetId }: { assetId: string }) => (
|
||||
);
|
||||
|
||||
describe('AssetDetailsDialog', () => {
|
||||
// 7001-COLL-008
|
||||
// 6501-ASSE-001
|
||||
// 6501-ASSE-002
|
||||
// 6501-ASSE-003
|
||||
// 6501-ASSE-004
|
||||
// 6501-ASSE-005
|
||||
// 6501-ASSE-006
|
||||
// 6501-ASSE-007
|
||||
// 6501-ASSE-008
|
||||
// 6501-ASSE-009
|
||||
// 6501-ASSE-010
|
||||
// 6501-ASSE-011
|
||||
// 6501-ASSE-012
|
||||
// 6501-ASSE-013
|
||||
it('should show no data message given unknown asset symbol', async () => {
|
||||
render(<WrappedAssetDetailsDialog assetId={'UNKNOWN_FOR_SURE'} />);
|
||||
expect((await screen.findByTestId('splash')).textContent).toContain(
|
||||
|
||||
@@ -13,7 +13,7 @@ import { createLog } from './logging';
|
||||
import { getMarkets } from './get-markets';
|
||||
import { createWalletClient } from './wallet-client';
|
||||
import { createEthereumWallet } from './ethereum-wallet';
|
||||
import { ASSET_ID_FOR_MARKET } from './contants';
|
||||
import { ASSET_ID_FOR_MARKET } from './constants';
|
||||
|
||||
const log = createLog('create-market');
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { createLog } from './logging';
|
||||
import type { ProposalSubmissionBody } from '@vegaprotocol/wallet';
|
||||
import { getProposal } from './get-proposal';
|
||||
import { sendVegaTx } from './wallet-client';
|
||||
import { ASSET_ID_FOR_MARKET, ASSET_SYMBOL } from './contants';
|
||||
import { ASSET_ID_FOR_MARKET, ASSET_SYMBOL } from './constants';
|
||||
|
||||
const log = createLog('propose-market');
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export * from './lib/ag-grid/ag-grid-lazy';
|
||||
export * from './lib/ag-grid/ag-grid';
|
||||
|
||||
export * from './lib/column-definitions';
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user