Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee57d2f1c0 | ||
|
|
8b249e1917 | ||
|
|
abb771e2f9 | ||
|
|
acf1d50d0f | ||
|
|
30da1663eb | ||
|
|
79cbe62774 | ||
|
|
2f0be0bf34 | ||
|
|
5b5802104e | ||
|
|
ff2e2574f6 | ||
|
|
478cc9e753 | ||
|
|
e2a72cb395 | ||
|
|
7fe269fad6 | ||
|
|
b761023069 | ||
|
|
7ac3a68ac9 | ||
|
|
2640ccb20a | ||
|
|
d78de10855 | ||
|
|
bb402c02f6 | ||
|
|
8a9b1c7874 | ||
|
|
a7e8b0eb01 | ||
|
|
89b3c06107 | ||
|
|
cd5c73d3fd | ||
|
|
b3a5ab022d | ||
|
|
496d1f5c68 | ||
|
|
e914e7bb70 | ||
|
|
71a36c2382 | ||
|
|
1c6a307bcd | ||
|
|
ef4a740b91 | ||
|
|
2d4be5fcb3 | ||
|
|
835f2b793f | ||
|
|
d50b988b4a | ||
|
|
a6aec899c8 |
@@ -5,17 +5,15 @@ on:
|
||||
branches:
|
||||
- release/*
|
||||
- develop
|
||||
- main
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- ready_for_review
|
||||
- reopened
|
||||
- edited
|
||||
- synchronize
|
||||
jobs:
|
||||
node-modules:
|
||||
# All jobs depend on node_modules, so none should run if the PR is in draft
|
||||
if: github.event.pull_request.draft == false
|
||||
runs-on: ubuntu-22.04
|
||||
name: 'Cache yarn modules'
|
||||
steps:
|
||||
@@ -44,13 +42,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
|
||||
@@ -177,19 +168,42 @@ jobs:
|
||||
preview_explorer: ${{ env.PREVIEW_EXPLORER }}
|
||||
preview_tools: ${{ env.PREVIEW_TOOLS }}
|
||||
|
||||
console-e2e:
|
||||
# console-e2e:
|
||||
# needs: build-sources
|
||||
# name: '(CI) console python'
|
||||
# uses: ./.github/workflows/console-test-run.yml
|
||||
# secrets: inherit
|
||||
# if: ${{ contains(fromJSON(needs.build-sources.outputs.projects), 'trading') && github.event_name == 'pull_request' }}
|
||||
# with:
|
||||
# github-sha: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
check-e2e-needed:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-sources
|
||||
name: '(CI) console python'
|
||||
uses: ./.github/workflows/console-test-run.yml
|
||||
secrets: inherit
|
||||
if: ${{ contains(fromJSON(needs.build-sources.outputs.projects), 'trading') && github.event_name == 'pull_request' }}
|
||||
with:
|
||||
github-sha: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
name: '(CI) check if e2e needed'
|
||||
outputs:
|
||||
run-tests: ${{ steps.check-test.outputs.e2e-needed }}
|
||||
steps:
|
||||
- name: Check branch
|
||||
id: check-test
|
||||
run: |
|
||||
if [ ${{ github.base_ref }} == 'develop' ]; then
|
||||
echo "e2e-needed=true" >> $GITHUB_OUTPUT
|
||||
elif [ ${{ github.base_ref }} == 'main' ]; then
|
||||
echo "e2e-needed=true" >> $GITHUB_OUTPUT
|
||||
elif [[ ${{ github.event_name }} == 'push' && ${{ contains(github.ref_name, 'release/') }} ]]; then
|
||||
echo "e2e-needed=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "e2e-needed=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- name: Print result
|
||||
run: |
|
||||
echo "e2e-needed: ${{ steps.check-test.outputs.e2e-needed }}"
|
||||
|
||||
cypress:
|
||||
needs: build-sources
|
||||
needs: [build-sources, check-e2e-needed]
|
||||
name: '(CI) cypress'
|
||||
# if: ${{ needs.build-sources.outputs.projects-e2e != '[]' }}
|
||||
if: ${{ needs.check-e2e-needed.outputs.run-tests == 'true' }}
|
||||
uses: ./.github/workflows/cypress-run.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
|
||||
@@ -1,31 +1,42 @@
|
||||
name: (CI) Console tests
|
||||
|
||||
env:
|
||||
VEGA_VERSION: v0.72.14
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
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,36 +79,30 @@ 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
|
||||
# install dependencies if cache does not exist
|
||||
#----------------------------------------------
|
||||
- name: Install dependencies
|
||||
working-directory: ./console-test
|
||||
run: poetry install --no-interaction --no-root
|
||||
#----------------------------------------------
|
||||
# find vega binaries path
|
||||
#----------------------------------------------
|
||||
- name: Find vega binaries path
|
||||
id: vega_bin_path
|
||||
working-directory: ./console-test
|
||||
run: echo path=$(poetry run python -c "import vega_sim; print(vega_sim.vega_bin_path)") >> $GITHUB_OUTPUT
|
||||
#----------------------------------------------
|
||||
# vega binaries cache
|
||||
#----------------------------------------------
|
||||
- name: Vega binaries cache
|
||||
uses: actions/cache@v3
|
||||
id: vega_binaries_cache
|
||||
with:
|
||||
path: ${{ steps.vega_bin_path.outputs.path }}
|
||||
key: ${{ runner.os }}-vega-binaries-${{ env.VEGA_VERSION }}
|
||||
#----------------------------------------------
|
||||
# install vega binaries
|
||||
# install vega binaries
|
||||
#----------------------------------------------
|
||||
- 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 +114,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 +129,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
|
||||
@@ -63,6 +85,7 @@ jobs:
|
||||
- name: Run Vegacapsule network and Vega wallet
|
||||
id: setup-vega
|
||||
uses: ./frontend-monorepo/.github/actions/run-vegacapsule
|
||||
timeout-minutes: 10
|
||||
|
||||
######
|
||||
## Run some tests
|
||||
|
||||
@@ -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: |
|
||||
@@ -57,7 +63,7 @@ jobs:
|
||||
echo IS_IPFS_RELEASE=true >> $GITHUB_ENV
|
||||
|
||||
- name: Is S3 Release
|
||||
if: ${{ env.IS_IPFS_RELEASE == 'false' && github.event_name == 'push' }}
|
||||
if: ${{ env.IS_IPFS_RELEASE == 'false' && github.event_name == 'push' && github.ref_name != 'main'}}
|
||||
run: |
|
||||
echo IS_S3_RELEASE=true >> $GITHUB_ENV
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -26,6 +26,7 @@ function getSuccessorTxBody(parentMarketId) {
|
||||
positionDecimalPlaces: '5',
|
||||
linearSlippageFactor: '0.001',
|
||||
quadraticSlippageFactor: '0',
|
||||
lpPriceRange: '10',
|
||||
instrument: {
|
||||
name: 'Token test market',
|
||||
code: 'TEST.24h',
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -13,12 +13,6 @@ query ExplorerMarket($id: ID!) {
|
||||
decimals
|
||||
}
|
||||
}
|
||||
... on Perpetual {
|
||||
quoteName
|
||||
settlementAsset {
|
||||
decimals
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-7
@@ -8,7 +8,7 @@ export type ExplorerMarketQueryVariables = Types.Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type ExplorerMarketQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', decimals: number } } | { __typename?: 'Perpetual', quoteName: string, settlementAsset: { __typename?: 'Asset', decimals: number } } | { __typename?: 'Spot' } } } } | null };
|
||||
export type ExplorerMarketQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', decimals: number } } } } } | null };
|
||||
|
||||
|
||||
export const ExplorerMarketDocument = gql`
|
||||
@@ -27,12 +27,6 @@ export const ExplorerMarketDocument = gql`
|
||||
decimals
|
||||
}
|
||||
}
|
||||
... on Perpetual {
|
||||
quoteName
|
||||
settlementAsset {
|
||||
decimals
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,6 @@ describe('Market link component', () => {
|
||||
instrument: {
|
||||
name: 'test-label',
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
quoteName: 'dai',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -3,14 +3,13 @@ import type { MarketInfoWithData } from '@vegaprotocol/markets';
|
||||
import {
|
||||
PriceMonitoringBoundsInfoPanel,
|
||||
SuccessionLineInfoPanel,
|
||||
getDataSourceSpecForSettlementData,
|
||||
getDataSourceSpecForTradingTermination,
|
||||
} from '@vegaprotocol/markets';
|
||||
import {
|
||||
LiquidityInfoPanel,
|
||||
LiquidityMonitoringParametersInfoPanel,
|
||||
InstrumentInfoPanel,
|
||||
KeyDetailsInfoPanel,
|
||||
LiquidityPriceRangeInfoPanel,
|
||||
MetadataInfoPanel,
|
||||
OracleInfoPanel,
|
||||
RiskFactorsInfoPanel,
|
||||
@@ -19,21 +18,20 @@ import {
|
||||
SettlementAssetInfoPanel,
|
||||
} from '@vegaprotocol/markets';
|
||||
import { MarketInfoTable } from '@vegaprotocol/markets';
|
||||
import type { DataSourceFragment } from '@vegaprotocol/markets';
|
||||
import type { DataSourceDefinition } from '@vegaprotocol/types';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
|
||||
export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
|
||||
if (!market) return null;
|
||||
const { product } = market.tradableInstrument.instrument;
|
||||
const settlementDataSource = getDataSourceSpecForSettlementData(product);
|
||||
const terminationDataSource = getDataSourceSpecForTradingTermination(product);
|
||||
|
||||
const getSigners = ({ data }: DataSourceFragment) => {
|
||||
const settlementData = market.tradableInstrument.instrument.product
|
||||
.dataSourceSpecForSettlementData.data as DataSourceDefinition;
|
||||
const terminationData = market.tradableInstrument.instrument.product
|
||||
.dataSourceSpecForTradingTermination.data as DataSourceDefinition;
|
||||
|
||||
const getSigners = (data: DataSourceDefinition) => {
|
||||
if (data.sourceType.__typename === 'DataSourceDefinitionExternal') {
|
||||
const signers =
|
||||
('signers' in data.sourceType.sourceType &&
|
||||
data.sourceType.sourceType.signers) ||
|
||||
[];
|
||||
const signers = data.sourceType.sourceType.signers || [];
|
||||
|
||||
return signers.map(({ signer }, i) => {
|
||||
return (
|
||||
@@ -45,13 +43,10 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
|
||||
return [];
|
||||
};
|
||||
|
||||
const showTwoOracles =
|
||||
settlementDataSource &&
|
||||
terminationDataSource &&
|
||||
isEqual(
|
||||
getSigners(settlementDataSource),
|
||||
getSigners(terminationDataSource)
|
||||
);
|
||||
const showTwoOracles = isEqual(
|
||||
getSigners(settlementData),
|
||||
getSigners(terminationData)
|
||||
);
|
||||
|
||||
const headerClassName = 'font-alpha calt text-xl mt-4 border-b-2 pb-2';
|
||||
|
||||
@@ -96,6 +91,8 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
|
||||
<LiquidityMonitoringParametersInfoPanel market={market} />
|
||||
<h2 className={headerClassName}>{t('Liquidity')}</h2>
|
||||
<LiquidityInfoPanel market={market} />
|
||||
<h2 className={headerClassName}>{t('Liquidity price range')}</h2>
|
||||
<LiquidityPriceRangeInfoPanel market={market} />
|
||||
{showTwoOracles ? (
|
||||
<>
|
||||
<h2 className={headerClassName}>{t('Settlement oracle')}</h2>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { useMemo } from 'react';
|
||||
import { getAsset, type MarketFieldsFragment } from '@vegaprotocol/markets';
|
||||
import type { MarketFieldsFragment } from '@vegaprotocol/markets';
|
||||
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,
|
||||
@@ -73,7 +73,8 @@ export const MarketsTable = ({ data }: MarketsTableProps) => {
|
||||
MarketFieldsFragment,
|
||||
'tradableInstrument.instrument.product.settlementAsset.symbol'
|
||||
>) => {
|
||||
const value = data && getAsset(data);
|
||||
const value =
|
||||
data?.tradableInstrument.instrument.product.settlementAsset;
|
||||
return value ? (
|
||||
<ButtonLink
|
||||
onClick={(e) => {
|
||||
|
||||
@@ -31,9 +31,6 @@ fragment ExplorerDeterministicOrderFields on Order {
|
||||
... on Future {
|
||||
quoteName
|
||||
}
|
||||
... on Perpetual {
|
||||
quoteName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import * as Types from '@vegaprotocol/types';
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type ExplorerDeterministicOrderFieldsFragment = { __typename?: 'Order', id: string, type?: Types.OrderType | null, reference: string, status: Types.OrderStatus, version: string, createdAt: any, updatedAt?: any | null, expiresAt?: any | null, timeInForce: Types.OrderTimeInForce, price: string, side: Types.Side, remaining: string, size: string, rejectionReason?: Types.OrderRejectionReason | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null, party: { __typename?: 'Party', id: string }, market: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } | { __typename?: 'Perpetual', quoteName: string } | { __typename?: 'Spot' } } } } };
|
||||
export type ExplorerDeterministicOrderFieldsFragment = { __typename?: 'Order', id: string, type?: Types.OrderType | null, reference: string, status: Types.OrderStatus, version: string, createdAt: any, updatedAt?: any | null, expiresAt?: any | null, timeInForce: Types.OrderTimeInForce, price: string, side: Types.Side, remaining: string, size: string, rejectionReason?: Types.OrderRejectionReason | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null, party: { __typename?: 'Party', id: string }, market: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } } } } };
|
||||
|
||||
export type ExplorerDeterministicOrderQueryVariables = Types.Exact<{
|
||||
orderId: Types.Scalars['ID'];
|
||||
@@ -11,7 +11,7 @@ export type ExplorerDeterministicOrderQueryVariables = Types.Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type ExplorerDeterministicOrderQuery = { __typename?: 'Query', orderByID: { __typename?: 'Order', id: string, type?: Types.OrderType | null, reference: string, status: Types.OrderStatus, version: string, createdAt: any, updatedAt?: any | null, expiresAt?: any | null, timeInForce: Types.OrderTimeInForce, price: string, side: Types.Side, remaining: string, size: string, rejectionReason?: Types.OrderRejectionReason | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null, party: { __typename?: 'Party', id: string }, market: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } | { __typename?: 'Perpetual', quoteName: string } | { __typename?: 'Spot' } } } } } };
|
||||
export type ExplorerDeterministicOrderQuery = { __typename?: 'Query', orderByID: { __typename?: 'Order', id: string, type?: Types.OrderType | null, reference: string, status: Types.OrderStatus, version: string, createdAt: any, updatedAt?: any | null, expiresAt?: any | null, timeInForce: Types.OrderTimeInForce, price: string, side: Types.Side, remaining: string, size: string, rejectionReason?: Types.OrderRejectionReason | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null, party: { __typename?: 'Party', id: string }, market: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } } } } } };
|
||||
|
||||
export const ExplorerDeterministicOrderFieldsFragmentDoc = gql`
|
||||
fragment ExplorerDeterministicOrderFields on Order {
|
||||
@@ -47,9 +47,6 @@ export const ExplorerDeterministicOrderFieldsFragmentDoc = gql`
|
||||
... on Future {
|
||||
quoteName
|
||||
}
|
||||
... on Perpetual {
|
||||
quoteName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,7 +150,6 @@ function renderExistingAmend(
|
||||
instrument: {
|
||||
name: 'test-label',
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
quoteName: 'dai',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -33,8 +33,6 @@ const PriceInMarket = ({
|
||||
label = addDecimalsFormatNumber(price, data.market.decimalPlaces);
|
||||
} else if (
|
||||
decimalSource === 'SETTLEMENT_ASSET' &&
|
||||
data.market &&
|
||||
'settlementAsset' in data.market.tradableInstrument.instrument.product &&
|
||||
data.market?.tradableInstrument.instrument.product.settlementAsset
|
||||
) {
|
||||
label = addDecimalsFormatNumber(
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -11,14 +11,6 @@ fragment ExplorerOracleForMarketsMarket on Market {
|
||||
id
|
||||
}
|
||||
}
|
||||
... on Perpetual {
|
||||
dataSourceSpecForSettlementData {
|
||||
id
|
||||
}
|
||||
dataSourceSpecForSettlementSchedule {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } } } } }, dataConnection: { __typename?: 'OracleDataConnection', edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } };
|
||||
|
||||
export type 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?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } } } } }, dataConnection: { __typename?: 'OracleDataConnection', edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } } } | null> | null } | null };
|
||||
|
||||
export type 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?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } } } } }, dataConnection: { __typename?: 'OracleDataConnection', edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } } | null };
|
||||
|
||||
export const ExplorerOracleDataConnectionFragmentDoc = gql`
|
||||
fragment ExplorerOracleDataConnection on OracleSpec {
|
||||
|
||||
@@ -3,12 +3,12 @@ import * as Types from '@vegaprotocol/types';
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type ExplorerOracleForMarketsMarketFragment = { __typename?: 'Market', id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', product: { __typename?: 'Future', dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string } } | { __typename?: 'Perpetual', dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecForSettlementSchedule: { __typename?: 'DataSourceSpec', id: string } } | { __typename?: 'Spot' } } } };
|
||||
export type ExplorerOracleForMarketsMarketFragment = { __typename?: 'Market', id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', product: { __typename?: 'Future', dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string } } } } };
|
||||
|
||||
export type ExplorerOracleFormMarketsQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type ExplorerOracleFormMarketsQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', product: { __typename?: 'Future', dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string } } | { __typename?: 'Perpetual', dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecForSettlementSchedule: { __typename?: 'DataSourceSpec', id: string } } | { __typename?: 'Spot' } } } } }> } | null };
|
||||
export type ExplorerOracleFormMarketsQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', product: { __typename?: 'Future', dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string } } } } } }> } | null };
|
||||
|
||||
export const ExplorerOracleForMarketsMarketFragmentDoc = gql`
|
||||
fragment ExplorerOracleForMarketsMarket on Market {
|
||||
@@ -24,14 +24,6 @@ export const ExplorerOracleForMarketsMarketFragmentDoc = gql`
|
||||
id
|
||||
}
|
||||
}
|
||||
... on Perpetual {
|
||||
dataSourceSpecForSettlementData {
|
||||
id
|
||||
}
|
||||
dataSourceSpecForSettlementSchedule {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ interface OracleMarketsProps {
|
||||
}
|
||||
|
||||
/**
|
||||
* Slightly misleading names, OracleMarkets lists the market (almost always singular)
|
||||
* Slightly misleadlingly names, OracleMarkets lists the market (almost always singular)
|
||||
* to which an oracle is attached. It also checks what it triggers, by checking on the
|
||||
* market whether it is attached to the dataSourceSpecForSettlementData or ..TradingTermination
|
||||
*/
|
||||
@@ -27,10 +27,8 @@ export function OracleMarkets({ id }: OracleMarketsProps) {
|
||||
const m = markets.find((m) => {
|
||||
const p = m.tradableInstrument.instrument.product;
|
||||
if (
|
||||
((p.__typename === 'Future' || p.__typename === 'Perpetual') &&
|
||||
p.dataSourceSpecForSettlementData.id === id) ||
|
||||
('dataSourceSpecForTradingTermination' in p &&
|
||||
p.dataSourceSpecForTradingTermination.id === id)
|
||||
p?.dataSourceSpecForSettlementData?.id === id ||
|
||||
p?.dataSourceSpecForTradingTermination?.id === id
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
@@ -63,32 +61,8 @@ export function getLabel(
|
||||
m: ExplorerOracleForMarketsMarketFragment | null
|
||||
): string {
|
||||
const settlementId =
|
||||
((m?.tradableInstrument?.instrument?.product?.__typename === 'Future' ||
|
||||
m?.tradableInstrument?.instrument?.product?.__typename === 'Perpetual') &&
|
||||
m?.tradableInstrument?.instrument?.product
|
||||
?.dataSourceSpecForSettlementData?.id) ||
|
||||
null;
|
||||
m?.tradableInstrument?.instrument?.product?.dataSourceSpecForSettlementData
|
||||
?.id || null;
|
||||
|
||||
const terminationId =
|
||||
(m?.tradableInstrument?.instrument?.product?.__typename === 'Future' &&
|
||||
m?.tradableInstrument?.instrument?.product
|
||||
?.dataSourceSpecForTradingTermination?.id) ||
|
||||
null;
|
||||
|
||||
const settlementScheduleId =
|
||||
(m?.tradableInstrument?.instrument?.product?.__typename === 'Perpetual' &&
|
||||
m?.tradableInstrument?.instrument?.product
|
||||
?.dataSourceSpecForSettlementSchedule?.id) ||
|
||||
null;
|
||||
|
||||
switch (id) {
|
||||
case settlementId:
|
||||
return 'Settlement for';
|
||||
case terminationId:
|
||||
return 'Termination for';
|
||||
case settlementScheduleId:
|
||||
return 'Settlement schedule for';
|
||||
default:
|
||||
return 'Unknown';
|
||||
}
|
||||
return id === settlementId ? 'Settlement for' : 'Termination for';
|
||||
}
|
||||
|
||||
@@ -67,9 +67,6 @@ export function OracleSigners({ sourceType }: OracleDetailsSignersProps) {
|
||||
if (sourceType.__typename !== 'DataSourceDefinitionExternal') {
|
||||
return null;
|
||||
}
|
||||
if (!('signers' in sourceType.sourceType)) {
|
||||
return null;
|
||||
}
|
||||
const signers = sourceType.sourceType.signers;
|
||||
|
||||
if (!signers || signers.length === 0) {
|
||||
|
||||
@@ -8,7 +8,9 @@ import { useScrollToLocation } from '../../../hooks/scroll-to-location';
|
||||
import filter from 'recursive-key-filter';
|
||||
|
||||
const Oracles = () => {
|
||||
const { data, loading, error } = useExplorerOracleSpecsQuery();
|
||||
const { data, loading, error } = useExplorerOracleSpecsQuery({
|
||||
errorPolicy: 'ignore',
|
||||
});
|
||||
|
||||
useDocumentTitle(['Oracles']);
|
||||
useScrollToLocation();
|
||||
|
||||
@@ -23,9 +23,6 @@ fragment ExplorerPartyAssetsAccounts on AccountBalance {
|
||||
... on Future {
|
||||
quoteName
|
||||
}
|
||||
... on Perpetual {
|
||||
quoteName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,14 +3,14 @@ import * as Types from '@vegaprotocol/types';
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type ExplorerPartyAssetsAccountsFragment = { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', name: string, id: string, decimals: number, symbol: string, source: { __typename: 'BuiltinAsset' } | { __typename: 'ERC20', contractAddress: string } }, market?: { __typename?: 'Market', id: string, decimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } | { __typename?: 'Perpetual', quoteName: string } | { __typename?: 'Spot' } } } } | null };
|
||||
export type ExplorerPartyAssetsAccountsFragment = { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', name: string, id: string, decimals: number, symbol: string, source: { __typename: 'BuiltinAsset' } | { __typename: 'ERC20', contractAddress: string } }, market?: { __typename?: 'Market', id: string, decimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } } } } | null };
|
||||
|
||||
export type ExplorerPartyAssetsQueryVariables = Types.Exact<{
|
||||
partyId: Types.Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
export type ExplorerPartyAssetsQuery = { __typename?: 'Query', partiesConnection?: { __typename?: 'PartyConnection', edges: Array<{ __typename?: 'PartyEdge', node: { __typename?: 'Party', id: string, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string, name: string } } } | null> | null } | null, stakingSummary: { __typename?: 'StakingSummary', currentStakeAvailable: string, linkings: { __typename?: 'StakesConnection', edges?: Array<{ __typename?: 'StakeLinkingEdge', node: { __typename?: 'StakeLinking', type: Types.StakeLinkingType, status: Types.StakeLinkingStatus, amount: string } } | null> | null } }, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', name: string, id: string, decimals: number, symbol: string, source: { __typename: 'BuiltinAsset' } | { __typename: 'ERC20', contractAddress: string } }, market?: { __typename?: 'Market', id: string, decimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } | { __typename?: 'Perpetual', quoteName: string } | { __typename?: 'Spot' } } } } | null } } | null> | null } | null } }> } | null };
|
||||
export type ExplorerPartyAssetsQuery = { __typename?: 'Query', partiesConnection?: { __typename?: 'PartyConnection', edges: Array<{ __typename?: 'PartyEdge', node: { __typename?: 'Party', id: string, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string, name: string } } } | null> | null } | null, stakingSummary: { __typename?: 'StakingSummary', currentStakeAvailable: string, linkings: { __typename?: 'StakesConnection', edges?: Array<{ __typename?: 'StakeLinkingEdge', node: { __typename?: 'StakeLinking', type: Types.StakeLinkingType, status: Types.StakeLinkingStatus, amount: string } } | null> | null } }, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', name: string, id: string, decimals: number, symbol: string, source: { __typename: 'BuiltinAsset' } | { __typename: 'ERC20', contractAddress: string } }, market?: { __typename?: 'Market', id: string, decimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } } } } | null } } | null> | null } | null } }> } | null };
|
||||
|
||||
export const ExplorerPartyAssetsAccountsFragmentDoc = gql`
|
||||
fragment ExplorerPartyAssetsAccounts on AccountBalance {
|
||||
@@ -38,9 +38,6 @@ export const ExplorerPartyAssetsAccountsFragmentDoc = gql`
|
||||
... on Future {
|
||||
quoteName
|
||||
}
|
||||
... on Perpetual {
|
||||
quoteName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
@@ -1453,6 +1453,11 @@ export interface components {
|
||||
readonly liquidityMonitoringParameters?: components['schemas']['vegaLiquidityMonitoringParameters'];
|
||||
/** @description Log normal risk model parameters, valid only if MODEL_LOG_NORMAL is selected. */
|
||||
readonly logNormal?: components['schemas']['vegaLogNormalRiskModel'];
|
||||
/**
|
||||
* @description Percentage move up and down from the mid price which specifies the range of
|
||||
* price levels over which automated liquidity provision orders will be deployed.
|
||||
*/
|
||||
readonly lpPriceRange?: string;
|
||||
/** @description Optional new futures market metadata, tags. */
|
||||
readonly metadata?: readonly string[];
|
||||
/**
|
||||
@@ -1848,6 +1853,11 @@ export interface components {
|
||||
readonly liquidityMonitoringParameters?: components['schemas']['vegaLiquidityMonitoringParameters'];
|
||||
/** @description Log normal risk model parameters, valid only if MODEL_LOG_NORMAL is selected. */
|
||||
readonly logNormal?: components['schemas']['vegaLogNormalRiskModel'];
|
||||
/**
|
||||
* @description Percentage move up and down from the mid price which specifies the range of
|
||||
* price levels over which automated liquidity provision orders will be deployed.
|
||||
*/
|
||||
readonly lpPriceRange?: string;
|
||||
/** @description Optional futures market metadata, tags. */
|
||||
readonly metadata?: readonly string[];
|
||||
/** @description Price monitoring parameters. */
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"positionDecimalPlaces": "5",
|
||||
"linearSlippageFactor": "0.001",
|
||||
"quadraticSlippageFactor": "0",
|
||||
"lpPriceRange": "10",
|
||||
"instrument": {
|
||||
"name": "Token test market",
|
||||
"code": "TEST.24h",
|
||||
@@ -103,12 +104,6 @@
|
||||
"r": 0.016,
|
||||
"sigma": 0.5
|
||||
}
|
||||
},
|
||||
"liquiditySlaParameters": {
|
||||
"priceRange": "0.95",
|
||||
"commitmentMinTimeFraction": "0.5",
|
||||
"performanceHysteresisEpochs": 2,
|
||||
"slaCompetitionFactor": "0.75"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"positionDecimalPlaces": "5",
|
||||
"linearSlippageFactor": "0.001",
|
||||
"quadraticSlippageFactor": "0",
|
||||
"lpPriceRange": "10",
|
||||
"instrument": {
|
||||
"name": "Token test market",
|
||||
"code": "Token.24h",
|
||||
@@ -97,12 +98,6 @@
|
||||
"r": 0.016,
|
||||
"sigma": 0.8
|
||||
}
|
||||
},
|
||||
"liquiditySlaParameters": {
|
||||
"priceRange": "0.95",
|
||||
"commitmentMinTimeFraction": "0.5",
|
||||
"performanceHysteresisEpochs": 2,
|
||||
"slaCompetitionFactor": "0.75"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"positionDecimalPlaces": "5",
|
||||
"linearSlippageFactor": "0.001",
|
||||
"quadraticSlippageFactor": "0",
|
||||
"lpPriceRange": "10",
|
||||
"instrument": {
|
||||
"name": "Token test market",
|
||||
"code": "Token.24h",
|
||||
@@ -98,12 +99,6 @@
|
||||
"sigma": 0.8
|
||||
}
|
||||
},
|
||||
"liquiditySlaParameters": {
|
||||
"priceRange": "0.95",
|
||||
"commitmentMinTimeFraction": "0.5",
|
||||
"performanceHysteresisEpochs": 2,
|
||||
"slaCompetitionFactor": "0.75"
|
||||
},
|
||||
"successor": {
|
||||
"parentMarketId": "",
|
||||
"insurancePoolFraction": "0.75"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"lpPriceRange": "11",
|
||||
"instrument": {
|
||||
"code": "Token.24h",
|
||||
"future": {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"lpPriceRange": "10",
|
||||
"linearSlippageFactor": "0.001",
|
||||
"quadraticSlippageFactor": "0",
|
||||
"instrument": {
|
||||
@@ -97,11 +98,5 @@
|
||||
"r": 0.016,
|
||||
"sigma": 0.3
|
||||
}
|
||||
},
|
||||
"liquiditySlaParameters": {
|
||||
"priceRange": "0.95",
|
||||
"commitmentMinTimeFraction": "0.5",
|
||||
"performanceHysteresisEpochs": 2,
|
||||
"slaCompetitionFactor": "0.75"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ const proposalType = 'proposal-type';
|
||||
const proposalDetails = 'proposal-details';
|
||||
const newProposalSubmitButton = 'proposal-submit';
|
||||
const proposalVoteDeadline = 'proposal-vote-deadline';
|
||||
const proposalEnactmentDeadline = 'proposal-enactment-deadline';
|
||||
const proposalParameterSelect = 'proposal-parameter-select';
|
||||
const proposalMarketSelect = 'proposal-market-select';
|
||||
const newProposalTitle = 'proposal-title';
|
||||
@@ -228,8 +227,6 @@ context(
|
||||
parseSpecialCharSequences: false,
|
||||
delay: 2,
|
||||
});
|
||||
cy.getByTestId(proposalVoteDeadline).clear().type('2');
|
||||
cy.getByTestId(proposalEnactmentDeadline).clear().type('3');
|
||||
});
|
||||
cy.getByTestId(proposalDownloadBtn)
|
||||
.should('be.visible')
|
||||
@@ -637,8 +634,6 @@ context(
|
||||
parseSpecialCharSequences: false,
|
||||
delay: 2,
|
||||
});
|
||||
cy.getByTestId(proposalVoteDeadline).clear().type('2');
|
||||
cy.getByTestId(proposalEnactmentDeadline).clear().type('3');
|
||||
});
|
||||
cy.getByTestId(proposalDownloadBtn)
|
||||
.should('be.visible')
|
||||
|
||||
@@ -105,13 +105,8 @@ export function createNewMarketProposalTxBody(): ProposalSubmissionBody {
|
||||
decimalPlaces: '5',
|
||||
positionDecimalPlaces: '5',
|
||||
linearSlippageFactor: '0.001',
|
||||
liquiditySlaParameters: {
|
||||
priceRange: '0.5',
|
||||
commitmentMinTimeFraction: '0.1',
|
||||
performanceHysteresisEpochs: 0,
|
||||
slaCompetitionFactor: '0.1',
|
||||
},
|
||||
quadraticSlippageFactor: '0',
|
||||
lpPriceRange: '10',
|
||||
instrument: {
|
||||
name: 'Token test market',
|
||||
code: 'TEST.24h',
|
||||
@@ -240,12 +235,7 @@ export function createSuccessorMarketProposalTxBody(
|
||||
positionDecimalPlaces: '5',
|
||||
linearSlippageFactor: '0.001',
|
||||
quadraticSlippageFactor: '0',
|
||||
liquiditySlaParameters: {
|
||||
priceRange: '0.5',
|
||||
commitmentMinTimeFraction: '0.1',
|
||||
performanceHysteresisEpochs: 0,
|
||||
slaCompetitionFactor: '0.1',
|
||||
},
|
||||
lpPriceRange: '10',
|
||||
instrument: {
|
||||
name: 'Token test market',
|
||||
code: 'TEST.24h',
|
||||
|
||||
+48
-66
@@ -5,6 +5,7 @@ import {
|
||||
InstrumentInfoPanel,
|
||||
KeyDetailsInfoPanel,
|
||||
LiquidityMonitoringParametersInfoPanel,
|
||||
LiquidityPriceRangeInfoPanel,
|
||||
MetadataInfoPanel,
|
||||
OracleInfoPanel,
|
||||
PriceMonitoringBoundsInfoPanel,
|
||||
@@ -12,10 +13,6 @@ import {
|
||||
RiskModelInfoPanel,
|
||||
RiskParametersInfoPanel,
|
||||
SettlementAssetInfoPanel,
|
||||
getDataSourceSpecForSettlementSchedule,
|
||||
getDataSourceSpecForSettlementData,
|
||||
getDataSourceSpecForTradingTermination,
|
||||
getSigners,
|
||||
} from '@vegaprotocol/markets';
|
||||
import {
|
||||
Button,
|
||||
@@ -27,6 +24,7 @@ import {
|
||||
import { SubHeading } from '../../../../components/heading';
|
||||
import { CollapsibleToggle } from '../../../../components/collapsible-toggle';
|
||||
import type { MarketInfo } from '@vegaprotocol/markets';
|
||||
import type { DataSourceDefinition } from '@vegaprotocol/types';
|
||||
import { create } from 'zustand';
|
||||
|
||||
type MarketDataDialogState = {
|
||||
@@ -61,31 +59,20 @@ export const ProposalMarketData = ({
|
||||
return null;
|
||||
}
|
||||
|
||||
const { product } = marketData.tradableInstrument.instrument;
|
||||
|
||||
const settlementData = getDataSourceSpecForSettlementData(product);
|
||||
const settlementScheduleData =
|
||||
getDataSourceSpecForSettlementSchedule(product);
|
||||
const terminationData = getDataSourceSpecForTradingTermination(product);
|
||||
|
||||
const parentProduct = parentMarketData?.tradableInstrument.instrument.product;
|
||||
const settlementData = marketData.tradableInstrument.instrument.product
|
||||
.dataSourceSpecForSettlementData.data as DataSourceDefinition;
|
||||
const parentSettlementData =
|
||||
parentProduct && getDataSourceSpecForSettlementData(parentProduct);
|
||||
const parentSettlementScheduleData =
|
||||
parentProduct && getDataSourceSpecForSettlementSchedule(parentProduct);
|
||||
parentMarketData?.tradableInstrument.instrument?.product
|
||||
?.dataSourceSpecForSettlementData?.data;
|
||||
const terminationData = marketData.tradableInstrument.instrument.product
|
||||
.dataSourceSpecForTradingTermination.data as DataSourceDefinition;
|
||||
const parentTerminationData =
|
||||
parentProduct && getDataSourceSpecForTradingTermination(parentProduct);
|
||||
|
||||
// TODO add settlementScheduleData for Perp Proposal
|
||||
parentMarketData?.tradableInstrument.instrument?.product
|
||||
?.dataSourceSpecForTradingTermination?.data;
|
||||
|
||||
const isParentSettlementDataEqual =
|
||||
parentSettlementData !== undefined &&
|
||||
isEqual(settlementData, parentSettlementData);
|
||||
|
||||
const isParentSettlementScheduleDataEqual =
|
||||
parentSettlementData !== undefined &&
|
||||
isEqual(settlementScheduleData, parentSettlementScheduleData);
|
||||
|
||||
const isParentTerminationDataEqual =
|
||||
parentTerminationData !== undefined &&
|
||||
isEqual(terminationData, parentTerminationData);
|
||||
@@ -98,6 +85,20 @@ export const ProposalMarketData = ({
|
||||
parentMarketData?.priceMonitoringSettings?.parameters?.triggers
|
||||
);
|
||||
|
||||
const getSigners = (data: DataSourceDefinition) => {
|
||||
if (data.sourceType.__typename === 'DataSourceDefinitionExternal') {
|
||||
const signers = data.sourceType.sourceType.signers || [];
|
||||
|
||||
return signers.map(({ signer }) => {
|
||||
return (
|
||||
(signer.__typename === 'ETHAddress' && signer.address) ||
|
||||
(signer.__typename === 'PubKey' && signer.key)
|
||||
);
|
||||
});
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="relative" data-testid="proposal-market-data">
|
||||
<CollapsibleToggle
|
||||
@@ -128,9 +129,10 @@ export const ProposalMarketData = ({
|
||||
parentMarket={parentMarketData}
|
||||
/>
|
||||
|
||||
{settlementData &&
|
||||
terminationData &&
|
||||
isEqual(getSigners(settlementData), getSigners(terminationData)) ? (
|
||||
{isEqual(
|
||||
getSigners(settlementData),
|
||||
getSigners(terminationData)
|
||||
) ? (
|
||||
<>
|
||||
<h2 className={marketDataHeaderStyles}>{t('Oracle')}</h2>
|
||||
|
||||
@@ -138,17 +140,14 @@ export const ProposalMarketData = ({
|
||||
market={marketData}
|
||||
type="settlementData"
|
||||
parentMarket={
|
||||
isParentSettlementDataEqual ||
|
||||
isParentSettlementScheduleDataEqual
|
||||
? undefined
|
||||
: parentMarketData
|
||||
isParentSettlementDataEqual ? undefined : parentMarketData
|
||||
}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<h2 className={marketDataHeaderStyles}>
|
||||
{t('Settlement oracle')}
|
||||
{t('Settlement Oracle')}
|
||||
</h2>
|
||||
<OracleInfoPanel
|
||||
market={marketData}
|
||||
@@ -158,41 +157,16 @@ export const ProposalMarketData = ({
|
||||
}
|
||||
/>
|
||||
|
||||
{marketData.tradableInstrument.instrument.product.__typename ===
|
||||
'Future' && (
|
||||
<div>
|
||||
<h2 className={marketDataHeaderStyles}>
|
||||
{t('Termination oracle')}
|
||||
</h2>
|
||||
<OracleInfoPanel
|
||||
market={marketData}
|
||||
type="termination"
|
||||
parentMarket={
|
||||
isParentTerminationDataEqual
|
||||
? undefined
|
||||
: parentMarketData
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{marketData.tradableInstrument.instrument.product.__typename ===
|
||||
'Perpetual' && (
|
||||
<div>
|
||||
<h2 className={marketDataHeaderStyles}>
|
||||
{t('Settlement schedule oracle')}
|
||||
</h2>
|
||||
<OracleInfoPanel
|
||||
market={marketData}
|
||||
type="settlementSchedule"
|
||||
parentMarket={
|
||||
isParentSettlementScheduleDataEqual
|
||||
? undefined
|
||||
: parentMarketData
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<h2 className={marketDataHeaderStyles}>
|
||||
{t('Termination Oracle')}
|
||||
</h2>
|
||||
<OracleInfoPanel
|
||||
market={marketData}
|
||||
type="termination"
|
||||
parentMarket={
|
||||
isParentTerminationDataEqual ? undefined : parentMarketData
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -270,6 +244,14 @@ export const ProposalMarketData = ({
|
||||
market={marketData}
|
||||
parentMarket={parentMarketData}
|
||||
/>
|
||||
|
||||
<h2 className={marketDataHeaderStyles}>
|
||||
{t('Liquidity price range')}
|
||||
</h2>
|
||||
<LiquidityPriceRangeInfoPanel
|
||||
market={marketData}
|
||||
parentMarket={parentMarketData}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -20,6 +20,7 @@ query Proposal($proposalId: ID!) {
|
||||
... on NewMarket {
|
||||
decimalPlaces
|
||||
metadata
|
||||
lpPriceRange
|
||||
riskParameters {
|
||||
... on LogNormalRiskModel {
|
||||
riskAversionParameter
|
||||
@@ -151,6 +152,7 @@ query Proposal($proposalId: ID!) {
|
||||
}
|
||||
}
|
||||
positionDecimalPlaces
|
||||
lpPriceRange
|
||||
linearSlippageFactor
|
||||
quadraticSlippageFactor
|
||||
}
|
||||
@@ -160,13 +162,37 @@ query Proposal($proposalId: ID!) {
|
||||
instrument {
|
||||
code
|
||||
product {
|
||||
... on UpdateFutureProduct {
|
||||
quoteName
|
||||
dataSourceSpecForSettlementData {
|
||||
sourceType {
|
||||
... on DataSourceDefinitionInternal {
|
||||
sourceType {
|
||||
... on DataSourceSpecConfigurationTime {
|
||||
quoteName
|
||||
dataSourceSpecForSettlementData {
|
||||
sourceType {
|
||||
... on DataSourceDefinitionInternal {
|
||||
sourceType {
|
||||
... on DataSourceSpecConfigurationTime {
|
||||
conditions {
|
||||
operator
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
... on DataSourceDefinitionExternal {
|
||||
sourceType {
|
||||
... on DataSourceSpecConfiguration {
|
||||
signers {
|
||||
signer {
|
||||
... on PubKey {
|
||||
key
|
||||
}
|
||||
... on ETHAddress {
|
||||
address
|
||||
}
|
||||
}
|
||||
}
|
||||
filters {
|
||||
key {
|
||||
name
|
||||
type
|
||||
}
|
||||
conditions {
|
||||
operator
|
||||
value
|
||||
@@ -174,125 +200,52 @@ query Proposal($proposalId: ID!) {
|
||||
}
|
||||
}
|
||||
}
|
||||
... on DataSourceDefinitionExternal {
|
||||
sourceType {
|
||||
... on DataSourceSpecConfiguration {
|
||||
signers {
|
||||
signer {
|
||||
... on PubKey {
|
||||
key
|
||||
}
|
||||
... on ETHAddress {
|
||||
address
|
||||
}
|
||||
}
|
||||
}
|
||||
filters {
|
||||
key {
|
||||
name
|
||||
type
|
||||
}
|
||||
conditions {
|
||||
operator
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# dataSourceSpecForTradingTermination {
|
||||
# sourceType {
|
||||
# ... on DataSourceDefinitionInternal {
|
||||
# sourceType {
|
||||
# ... on DataSourceSpecConfigurationTime {
|
||||
# conditions {
|
||||
# operator
|
||||
# value
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# ... on DataSourceDefinitionExternal {
|
||||
# sourceType {
|
||||
# ... on DataSourceSpecConfiguration {
|
||||
# signers {
|
||||
# signer {
|
||||
# ... on PubKey {
|
||||
# key
|
||||
# }
|
||||
# ... on ETHAddress {
|
||||
# address
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# filters {
|
||||
# key {
|
||||
# name
|
||||
# type
|
||||
# }
|
||||
# conditions {
|
||||
# operator
|
||||
# value
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
dataSourceSpecBinding {
|
||||
settlementDataProperty
|
||||
tradingTerminationProperty
|
||||
}
|
||||
}
|
||||
... on UpdatePerpetualProduct {
|
||||
quoteName
|
||||
dataSourceSpecForSettlementData {
|
||||
sourceType {
|
||||
... on DataSourceDefinitionInternal {
|
||||
sourceType {
|
||||
... on DataSourceSpecConfigurationTime {
|
||||
conditions {
|
||||
operator
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
... on DataSourceDefinitionExternal {
|
||||
sourceType {
|
||||
... on DataSourceSpecConfiguration {
|
||||
signers {
|
||||
signer {
|
||||
... on PubKey {
|
||||
key
|
||||
}
|
||||
... on ETHAddress {
|
||||
address
|
||||
}
|
||||
}
|
||||
}
|
||||
filters {
|
||||
key {
|
||||
name
|
||||
type
|
||||
}
|
||||
conditions {
|
||||
operator
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dataSourceSpecBinding {
|
||||
settlementDataProperty
|
||||
settlementScheduleProperty
|
||||
}
|
||||
# dataSourceSpecForTradingTermination {
|
||||
# sourceType {
|
||||
# ... on DataSourceDefinitionInternal {
|
||||
# sourceType {
|
||||
# ... on DataSourceSpecConfigurationTime {
|
||||
# conditions {
|
||||
# operator
|
||||
# value
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# ... on DataSourceDefinitionExternal {
|
||||
# sourceType {
|
||||
# ... on DataSourceSpecConfiguration {
|
||||
# signers {
|
||||
# signer {
|
||||
# ... on PubKey {
|
||||
# key
|
||||
# }
|
||||
# ... on ETHAddress {
|
||||
# address
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# filters {
|
||||
# key {
|
||||
# name
|
||||
# type
|
||||
# }
|
||||
# conditions {
|
||||
# operator
|
||||
# value
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
dataSourceSpecBinding {
|
||||
settlementDataProperty
|
||||
tradingTerminationProperty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -6,6 +6,11 @@ import { MockedProvider } from '@apollo/client/testing';
|
||||
import { MemoryRouter, Route, Routes } from 'react-router-dom';
|
||||
import { ProposalDocument } from './__generated__/Proposal';
|
||||
|
||||
jest.mock('@vegaprotocol/data-provider', () => ({
|
||||
...jest.requireActual('@vegaprotocol/data-provider'),
|
||||
useDataProvider: jest.fn(() => ({ data: [], loading: false })),
|
||||
}));
|
||||
|
||||
jest.mock('../components/proposal', () => ({
|
||||
Proposal: () => <div data-testid="proposal" />,
|
||||
}));
|
||||
|
||||
@@ -3,12 +3,12 @@ import * as Types from '@vegaprotocol/types';
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type ProposalFieldsFragment = { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: any, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string }, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: any, enactmentDatetime?: any | null, change: { __typename?: 'CancelTransfer' } | { __typename: 'NewAsset', name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string, withdrawThreshold: string, lifetimeLimit: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null } } | { __typename?: '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 ProposalFieldsFragment = { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: any, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string }, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: any, enactmentDatetime?: any | null, change: { __typename?: 'CancelTransfer' } | { __typename: 'NewAsset', name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string, withdrawThreshold: string, lifetimeLimit: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null } } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset', quantum: string, assetId: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string } } };
|
||||
|
||||
export type ProposalsQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
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 } } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset', quantum: string, assetId: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string } } } } | null> | null } | null };
|
||||
|
||||
export const ProposalFieldsFragmentDoc = gql`
|
||||
fragment ProposalFields on Proposal {
|
||||
|
||||
+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 {
|
||||
|
||||
+28
-7
@@ -35,7 +35,6 @@ import { HealthDialog } from '../../health-dialog';
|
||||
import { Status } from '../../status';
|
||||
import { intentForStatus } from '../../../lib/utils';
|
||||
import { formatDistanceToNow } from 'date-fns';
|
||||
import { getAsset } from '@vegaprotocol/markets';
|
||||
|
||||
export const MarketList = () => {
|
||||
const { data, error, loading } = useMarketsLiquidity();
|
||||
@@ -52,7 +51,12 @@ export const MarketList = () => {
|
||||
return (
|
||||
<>
|
||||
<span className="leading-3">{value}</span>
|
||||
<span className="leading-3">{getAsset(data).symbol}</span>
|
||||
<span className="leading-3">
|
||||
{
|
||||
data?.tradableInstrument?.instrument?.product?.settlementAsset
|
||||
?.symbol
|
||||
}
|
||||
</span>
|
||||
</>
|
||||
);
|
||||
},
|
||||
@@ -83,7 +87,12 @@ export const MarketList = () => {
|
||||
value,
|
||||
data,
|
||||
}: VegaValueFormatterParams<Market, 'data.markPrice'>) =>
|
||||
value && data ? formatWithAsset(value, getAsset(data)) : '-',
|
||||
value && data
|
||||
? formatWithAsset(
|
||||
value,
|
||||
data.tradableInstrument.instrument.product.settlementAsset
|
||||
)
|
||||
: '-',
|
||||
},
|
||||
|
||||
{
|
||||
@@ -114,7 +123,8 @@ export const MarketList = () => {
|
||||
value && data
|
||||
? `${addDecimalsFormatNumber(
|
||||
value,
|
||||
getAsset(data).decimals || 0
|
||||
data.tradableInstrument.instrument.product.settlementAsset
|
||||
.decimals
|
||||
)} (${displayChange(data.volumeChange)})`
|
||||
: '-',
|
||||
headerTooltip: t('The trade volume over the last 24h'),
|
||||
@@ -128,7 +138,10 @@ export const MarketList = () => {
|
||||
data,
|
||||
}: VegaValueFormatterParams<Market, 'liquidityCommitted'>) =>
|
||||
data && value
|
||||
? formatWithAsset(value.toString(), getAsset(data))
|
||||
? formatWithAsset(
|
||||
value.toString(),
|
||||
data.tradableInstrument.instrument.product.settlementAsset
|
||||
)
|
||||
: '-',
|
||||
headerTooltip: t('The amount of funds allocated to provide liquidity'),
|
||||
},
|
||||
@@ -140,7 +153,12 @@ export const MarketList = () => {
|
||||
value,
|
||||
data,
|
||||
}: VegaValueFormatterParams<Market, 'target'>) =>
|
||||
data && value ? formatWithAsset(value, getAsset(data)) : '-',
|
||||
data && value
|
||||
? formatWithAsset(
|
||||
value,
|
||||
data.tradableInstrument.instrument.product.settlementAsset
|
||||
)
|
||||
: '-',
|
||||
headerTooltip: t(
|
||||
'The ideal committed liquidity to operate the market. If total commitment currently below this level then LPs can set the fee level with new commitment.'
|
||||
),
|
||||
@@ -212,7 +230,10 @@ export const MarketList = () => {
|
||||
}) => (
|
||||
<HealthBar
|
||||
target={data.target}
|
||||
decimals={getAsset(data).decimals || 0}
|
||||
decimals={
|
||||
data.tradableInstrument.instrument.product.settlementAsset
|
||||
.decimals
|
||||
}
|
||||
levels={data.feeLevels}
|
||||
intent={intentForStatus(value)}
|
||||
/>
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
sumLiquidityCommitted,
|
||||
lpAggregatedDataProvider,
|
||||
} from '@vegaprotocol/liquidity';
|
||||
import { getAsset, marketWithDataProvider } from '@vegaprotocol/markets';
|
||||
import { marketWithDataProvider } from '@vegaprotocol/markets';
|
||||
import type { MarketWithData } from '@vegaprotocol/markets';
|
||||
|
||||
import { Market } from './market';
|
||||
@@ -19,8 +19,10 @@ import { LPProvidersGrid } from './providers';
|
||||
const formatMarket = (market: MarketWithData) => {
|
||||
return {
|
||||
name: market?.tradableInstrument.instrument.name,
|
||||
symbol: getAsset(market).symbol,
|
||||
settlementAsset: getAsset(market),
|
||||
symbol:
|
||||
market?.tradableInstrument.instrument.product.settlementAsset.symbol,
|
||||
settlementAsset:
|
||||
market?.tradableInstrument.instrument.product.settlementAsset,
|
||||
targetStake: market?.data?.targetStake,
|
||||
tradingMode: market?.data?.marketTradingMode,
|
||||
trigger: market?.data?.trigger,
|
||||
|
||||
@@ -7,7 +7,6 @@ const marketTradingModeStyle = {
|
||||
[Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION]: '#0046CD',
|
||||
[Schema.MarketTradingMode.TRADING_MODE_BATCH_AUCTION]: '#CF0064',
|
||||
[Schema.MarketTradingMode.TRADING_MODE_NO_TRADING]: '#CF0064',
|
||||
[Schema.MarketTradingMode.TRADING_MODE_SUSPENDED_VIA_GOVERNANCE]: '#CF0064',
|
||||
};
|
||||
|
||||
export const getColorForStatus = (status: Schema.MarketTradingMode) =>
|
||||
@@ -19,8 +18,6 @@ const marketTradingModeIntent = {
|
||||
[Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION]: Intent.Primary,
|
||||
[Schema.MarketTradingMode.TRADING_MODE_BATCH_AUCTION]: Intent.Danger,
|
||||
[Schema.MarketTradingMode.TRADING_MODE_NO_TRADING]: Intent.Danger,
|
||||
[Schema.MarketTradingMode.TRADING_MODE_SUSPENDED_VIA_GOVERNANCE]:
|
||||
Intent.Danger,
|
||||
};
|
||||
|
||||
export const intentForStatus = (status: Schema.MarketTradingMode) => {
|
||||
|
||||
@@ -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', () => {
|
||||
|
||||
@@ -122,7 +122,6 @@ const mockTradingPage = (
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
dataSourceSpecForSettlementData: {
|
||||
data: {
|
||||
sourceType: {
|
||||
|
||||
+6
-5
@@ -3,21 +3,22 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
||||
NX_SENTRY_DSN=https://2ffce43721964aafa78277c50654ece4@o286262.ingest.sentry.io/6300613
|
||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
|
||||
NX_VEGA_ENV=STAGNET1
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.stagnet1.vega.rocks
|
||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/fairground/vegawallet-fairground.toml
|
||||
NX_VEGA_ENV=TESTNET
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
||||
NX_VEGA_NETWORKS={\"MAINNET\":\"https://console.vega.xyz\",\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://trading.stagnet1.vega.rocks\"}
|
||||
NX_VEGA_TOKEN_URL=https://governance.stagnet1.vega.rocks
|
||||
NX_VEGA_TOKEN_URL=https://governance.fairground.wtf
|
||||
NX_VEGA_WALLET_URL=http://localhost:1789
|
||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
|
||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||
NX_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports
|
||||
NX_VEGA_CONSOLE_URL=https://console.fairground.wtf
|
||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
|
||||
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
NX_STOP_ORDERS=true
|
||||
|
||||
@@ -17,10 +17,6 @@ NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-ma
|
||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-mainnet
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
|
||||
|
||||
# TAG name of the current app version - TODO: bump to the latest upon release
|
||||
NX_APP_VERSION=v0.21.2-core-0.72.14
|
||||
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
NX_STOP_ORDERS=true
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { Links } from '../../lib/links';
|
||||
import classNames from 'classnames';
|
||||
import { NavLink, Outlet } from 'react-router-dom';
|
||||
|
||||
export const Assets = () => {
|
||||
const linkClasses = ({ isActive }: { isActive: boolean }) => {
|
||||
return classNames('border-b-2 border-transparent', {
|
||||
'border-vega-yellow': isActive,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="max-w-[500px] px-4 mx-auto my-8">
|
||||
<nav className="flex mb-6 text-lg gap-4">
|
||||
<NavLink to={Links.DEPOSIT()} className={linkClasses}>
|
||||
{t('Deposit')}
|
||||
</NavLink>
|
||||
<NavLink to={Links.WITHDRAW()} className={linkClasses}>
|
||||
{t('Withdraw')}
|
||||
</NavLink>
|
||||
<NavLink to={Links.TRANSFER()} className={linkClasses}>
|
||||
{t('Transfer')}
|
||||
</NavLink>
|
||||
</nav>
|
||||
<div className="pt-4 border-t md:p-6 md:border md:rounded-xl border-default">
|
||||
<Outlet />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
export { Assets } from './assets';
|
||||
@@ -1,44 +0,0 @@
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { Intent, TradingAnchorButton } from '@vegaprotocol/ui-toolkit';
|
||||
import { GetStartedCheckList } from '../../components/welcome-dialog';
|
||||
import {
|
||||
useGetOnboardingStep,
|
||||
useOnboardingStore,
|
||||
OnboardingStep,
|
||||
} from '../../components/welcome-dialog/use-get-onboarding-step';
|
||||
import { Links } from '../../lib/links';
|
||||
import classNames from 'classnames';
|
||||
|
||||
export const DepositGetStarted = () => {
|
||||
const onboardingDismissed = useOnboardingStore((store) => store.dismissed);
|
||||
const dismiss = useOnboardingStore((store) => store.dismiss);
|
||||
const step = useGetOnboardingStep();
|
||||
const wrapperClasses = classNames(
|
||||
'flex flex-col py-4 px-6 gap-4 rounded',
|
||||
'bg-vega-blue-300 dark:bg-vega-blue-700',
|
||||
'border border-vega-blue-350 dark:border-vega-blue-650'
|
||||
);
|
||||
|
||||
// Dont show unless still onboarding
|
||||
if (onboardingDismissed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="pt-6 border-t border-default">
|
||||
<div className={wrapperClasses}>
|
||||
<h3 className="text-lg">{t('Get started')}</h3>
|
||||
<GetStartedCheckList />
|
||||
{step > OnboardingStep.ONBOARDING_DEPOSIT_STEP && (
|
||||
<TradingAnchorButton
|
||||
href={Links.HOME()}
|
||||
onClick={() => dismiss()}
|
||||
intent={Intent.Info}
|
||||
>
|
||||
{t('Start trading')}
|
||||
</TradingAnchorButton>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,30 +0,0 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { Deposit } from './deposit';
|
||||
|
||||
jest.mock('@vegaprotocol/deposits', () => ({
|
||||
DepositContainer: ({ assetId }: { assetId?: string }) => (
|
||||
<div data-testid="assetId">{assetId}</div>
|
||||
),
|
||||
}));
|
||||
|
||||
jest.mock('./deposit-get-started', () => ({
|
||||
DepositGetStarted: () => <div>DepositGetStarted</div>,
|
||||
}));
|
||||
|
||||
const renderJsx = (route = '/deposit') => {
|
||||
render(
|
||||
<MemoryRouter initialEntries={[route]}>
|
||||
<Deposit />
|
||||
</MemoryRouter>
|
||||
);
|
||||
};
|
||||
|
||||
describe('Deposit page', () => {
|
||||
it('assetId should be passed down', () => {
|
||||
const assetId = 'foo';
|
||||
const route = '/deposit?assetId=' + assetId;
|
||||
renderJsx(route);
|
||||
expect(screen.getByTestId('assetId')).toHaveTextContent(assetId);
|
||||
});
|
||||
});
|
||||
@@ -1,14 +1,59 @@
|
||||
import { DepositContainer } from '@vegaprotocol/deposits';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { DepositGetStarted } from './deposit-get-started';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { Intent, TradingAnchorButton } from '@vegaprotocol/ui-toolkit';
|
||||
import { GetStartedCheckList } from '../../components/welcome-dialog';
|
||||
import {
|
||||
useGetOnboardingStep,
|
||||
useOnboardingStore,
|
||||
OnboardingStep,
|
||||
} from '../../components/welcome-dialog/use-get-onboarding-step';
|
||||
import { Links, Routes } from '../../pages/client-router';
|
||||
import classNames from 'classnames';
|
||||
|
||||
export const Deposit = () => {
|
||||
const [searchParams] = useSearchParams();
|
||||
const assetId = searchParams.get('assetId') || undefined;
|
||||
return (
|
||||
<div className="flex flex-col gap-6">
|
||||
<DepositContainer assetId={assetId} />
|
||||
<DepositGetStarted />
|
||||
<div className="max-w-[600px] px-4 py-8 mx-auto lg:px-8">
|
||||
<h1 className="mb-6 text-4xl uppercase xl:text-5xl font-alpha calt">
|
||||
{t('Deposit')}
|
||||
</h1>
|
||||
<div className="flex flex-col gap-6">
|
||||
<DepositContainer />
|
||||
<DepositGetStarted />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const DepositGetStarted = () => {
|
||||
const onboardingDismissed = useOnboardingStore((store) => store.dismissed);
|
||||
const dismiss = useOnboardingStore((store) => store.dismiss);
|
||||
const step = useGetOnboardingStep();
|
||||
const wrapperClasses = classNames(
|
||||
'flex flex-col py-4 px-6 gap-4 rounded',
|
||||
'bg-vega-blue-300 dark:bg-vega-blue-700',
|
||||
'border border-vega-blue-350 dark:border-vega-blue-650'
|
||||
);
|
||||
|
||||
// Dont show unless still onboarding
|
||||
if (onboardingDismissed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="pt-6 border-t border-default">
|
||||
<div className={wrapperClasses}>
|
||||
<h3 className="text-lg">{t('Get started')}</h3>
|
||||
<GetStartedCheckList />
|
||||
{step > OnboardingStep.ONBOARDING_DEPOSIT_STEP && (
|
||||
<TradingAnchorButton
|
||||
href={Links[Routes.HOME]()}
|
||||
onClick={() => dismiss()}
|
||||
intent={Intent.Info}
|
||||
>
|
||||
{t('Start trading')}
|
||||
</TradingAnchorButton>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
export { Deposit } from './deposit';
|
||||
import { Deposit } from './deposit';
|
||||
|
||||
export default Deposit;
|
||||
|
||||
@@ -2,45 +2,47 @@ import { t } from '@vegaprotocol/i18n';
|
||||
|
||||
export const Disclaimer = () => {
|
||||
return (
|
||||
<>
|
||||
<h1 className="text-4xl uppercase xl:text-5xl font-alpha calt">
|
||||
{t('Disclaimer')}
|
||||
</h1>
|
||||
<p className="mt-10 mb-6">
|
||||
{t(
|
||||
'Vega is a decentralised peer-to-peer protocol that can be used to trade derivatives with cryptoassets. The Vega Protocol is an implementation layer (layer one) protocol made of free, public, open-source or source-available software. Use of the Vega Protocol involves various risks, including but not limited to, losses while digital assets are supplied to the Vega Protocol and losses due to the fluctuation of prices of assets.'
|
||||
)}
|
||||
</p>
|
||||
<p className="mb-6">
|
||||
{t(
|
||||
'Before using the Vega Protocol, review the relevant documentation at docs.vega.xyz to make sure that you understand how it works. Conduct your own due diligence and consult your financial advisor before making any investment decisions.'
|
||||
)}
|
||||
</p>
|
||||
<p className="mb-6">
|
||||
{t(
|
||||
'As described in the Vega Protocol core license, the Vega Protocol is provided “as is”, at your own risk, and without warranties of any kind. Although Gobalsky Labs Limited developed much of the initial code for the Vega Protocol, it does not provide or control the Vega Protocol, which is run by third parties deploying it on a bespoke blockchain. Upgrades and modifications to the Vega Protocol are managed in a community-driven way by holders of the VEGA governance token.'
|
||||
)}
|
||||
</p>
|
||||
<p className="mb-8">
|
||||
{t(
|
||||
'No developer or entity involved in creating the Vega Protocol will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the Vega Protocol, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or legal costs, or loss of profits, cryptoassets, tokens or anything else of value.'
|
||||
)}
|
||||
</p>
|
||||
<p className="mb-8">
|
||||
{t(
|
||||
'This website is hosted on a decentralised network, the Interplanetary File System (“IPFS”). The IPFS decentralised web is made up of all the computers (nodes) connected to it. Data is therefore stored on many different computers.'
|
||||
)}
|
||||
</p>
|
||||
<p className="mb-8">
|
||||
{t(
|
||||
"The information provided on this website does not constitute investment advice, financial advice, trading advice, or any other sort of advice and you should not treat any of the website's content as such. No party recommends that any cryptoasset should be bought, sold, or held by you via this website. No party ensures the accuracy of information listed on this website or holds any responsibility for any missing or wrong information. You understand that you are using any and all information available here at your own risk."
|
||||
)}
|
||||
</p>
|
||||
<p className="mb-8">
|
||||
{t(
|
||||
'Additionally, just as you can access email protocols such as SMTP through multiple email clients, you can potentially access the Vega Protocol through many web or mobile interfaces. You are responsible for doing your own diligence on those interfaces to understand the associated risks and any fees.'
|
||||
)}
|
||||
</p>
|
||||
</>
|
||||
<div className="py-16 px-8 flex w-full justify-center">
|
||||
<div className="lg:min-w-[700px] min-w-[300px] max-w-[700px]">
|
||||
<h1 className="text-4xl xl:text-5xl uppercase font-alpha calt">
|
||||
{t('Disclaimer')}
|
||||
</h1>
|
||||
<p className="mb-6 mt-10">
|
||||
{t(
|
||||
'Vega is a decentralised peer-to-peer protocol that can be used to trade derivatives with cryptoassets. The Vega Protocol is an implementation layer (layer one) protocol made of free, public, open-source or source-available software. Use of the Vega Protocol involves various risks, including but not limited to, losses while digital assets are supplied to the Vega Protocol and losses due to the fluctuation of prices of assets.'
|
||||
)}
|
||||
</p>
|
||||
<p className="mb-6">
|
||||
{t(
|
||||
'Before using the Vega Protocol, review the relevant documentation at docs.vega.xyz to make sure that you understand how it works. Conduct your own due diligence and consult your financial advisor before making any investment decisions.'
|
||||
)}
|
||||
</p>
|
||||
<p className="mb-6">
|
||||
{t(
|
||||
'As described in the Vega Protocol core license, the Vega Protocol is provided “as is”, at your own risk, and without warranties of any kind. Although Gobalsky Labs Limited developed much of the initial code for the Vega Protocol, it does not provide or control the Vega Protocol, which is run by third parties deploying it on a bespoke blockchain. Upgrades and modifications to the Vega Protocol are managed in a community-driven way by holders of the VEGA governance token.'
|
||||
)}
|
||||
</p>
|
||||
<p className="mb-8">
|
||||
{t(
|
||||
'No developer or entity involved in creating the Vega Protocol will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the Vega Protocol, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or legal costs, or loss of profits, cryptoassets, tokens or anything else of value.'
|
||||
)}
|
||||
</p>
|
||||
<p className="mb-8">
|
||||
{t(
|
||||
'This website is hosted on a decentralised network, the Interplanetary File System (“IPFS”). The IPFS decentralised web is made up of all the computers (nodes) connected to it. Data is therefore stored on many different computers.'
|
||||
)}
|
||||
</p>
|
||||
<p className="mb-8">
|
||||
{t(
|
||||
"The information provided on this website does not constitute investment advice, financial advice, trading advice, or any other sort of advice and you should not treat any of the website's content as such. No party recommends that any cryptoasset should be bought, sold, or held by you via this website. No party ensures the accuracy of information listed on this website or holds any responsibility for any missing or wrong information. You understand that you are using any and all information available here at your own risk."
|
||||
)}
|
||||
</p>
|
||||
<p className="mb-8">
|
||||
{t(
|
||||
'Additionally, just as you can access email protocols such as SMTP through multiple email clients, you can potentially access the Vega Protocol through many web or mobile interfaces. You are responsible for doing your own diligence on those interfaces to understand the associated risks and any fees.'
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
export { Disclaimer } from './disclaimer';
|
||||
import { Disclaimer } from './disclaimer';
|
||||
|
||||
export default Disclaimer;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Loader, Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { Links, Routes } from '../../pages/client-router';
|
||||
import { useGlobalStore } from '../../stores';
|
||||
import { useTopTradedMarkets } from '../../lib/hooks/use-top-traded-markets';
|
||||
import { Links } from '../../lib/links';
|
||||
|
||||
// The home pages only purpose is to redirect to the users last market,
|
||||
// the top traded if they are new, or fall back to the list of markets.
|
||||
@@ -15,17 +15,17 @@ export const Home = () => {
|
||||
|
||||
useEffect(() => {
|
||||
if (marketId) {
|
||||
navigate(Links.MARKET(marketId), {
|
||||
navigate(Links[Routes.MARKET](marketId), {
|
||||
replace: true,
|
||||
});
|
||||
} else if (data) {
|
||||
const marketDataId = data[0]?.id;
|
||||
if (marketDataId) {
|
||||
navigate(Links.MARKET(marketDataId), {
|
||||
navigate(Links[Routes.MARKET](marketDataId), {
|
||||
replace: true,
|
||||
});
|
||||
} else {
|
||||
navigate(Links.MARKETS());
|
||||
navigate(Links[Routes.MARKETS]());
|
||||
}
|
||||
}
|
||||
}, [marketId, data, navigate]);
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
export { Home } from './home';
|
||||
import { Home } from './home';
|
||||
|
||||
export default Home;
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
export { Liquidity } from './liquidity';
|
||||
import { Liquidity } from './liquidity';
|
||||
|
||||
export default Liquidity;
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
export { MarketPage as default } from './market';
|
||||
import { MarketPage } from './market';
|
||||
|
||||
export default MarketPage;
|
||||
|
||||
@@ -3,89 +3,63 @@ import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { ButtonLink, Link } from '@vegaprotocol/ui-toolkit';
|
||||
import { MarketProposalNotification } from '@vegaprotocol/proposals';
|
||||
import type { Market } from '@vegaprotocol/markets';
|
||||
import {
|
||||
fromNanoSeconds,
|
||||
getExpiryDate,
|
||||
getMarketExpiryDate,
|
||||
} from '@vegaprotocol/utils';
|
||||
import { getExpiryDate, getMarketExpiryDate } from '@vegaprotocol/utils';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import {
|
||||
Last24hPriceChange,
|
||||
Last24hVolume,
|
||||
getAsset,
|
||||
getDataSourceSpecForSettlementSchedule,
|
||||
marketInfoProvider,
|
||||
useFundingPeriodsQuery,
|
||||
useFundingRate,
|
||||
} from '@vegaprotocol/markets';
|
||||
import { Last24hPriceChange, Last24hVolume } from '@vegaprotocol/markets';
|
||||
import { MarketState as State } from '@vegaprotocol/types';
|
||||
import { HeaderStat } from '../../components/header';
|
||||
import { MarketMarkPrice } from '../../components/market-mark-price';
|
||||
import { HeaderStatMarketTradingMode } from '../../components/market-trading-mode';
|
||||
import { MarketState } from '../../components/market-state';
|
||||
import { MarketLiquiditySupplied } from '../../components/liquidity-supplied';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||
|
||||
interface MarketHeaderStatsProps {
|
||||
market: Market;
|
||||
market: Market | null;
|
||||
}
|
||||
|
||||
export const MarketHeaderStats = ({ market }: MarketHeaderStatsProps) => {
|
||||
const { VEGA_EXPLORER_URL } = useEnvironment();
|
||||
const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore();
|
||||
|
||||
const asset = getAsset(market);
|
||||
const asset = market?.tradableInstrument.instrument.product?.settlementAsset;
|
||||
|
||||
return (
|
||||
<>
|
||||
{market.tradableInstrument.instrument.product.__typename === 'Future' && (
|
||||
<HeaderStat
|
||||
heading={t('Expiry')}
|
||||
description={
|
||||
<HeaderStat
|
||||
heading={t('Expiry')}
|
||||
description={
|
||||
market && (
|
||||
<ExpiryTooltipContent
|
||||
market={market}
|
||||
explorerUrl={VEGA_EXPLORER_URL}
|
||||
/>
|
||||
}
|
||||
testId="market-expiry"
|
||||
>
|
||||
<ExpiryLabel market={market} />
|
||||
</HeaderStat>
|
||||
)}
|
||||
{market.tradableInstrument.instrument.product.__typename ===
|
||||
'Perpetual' && (
|
||||
<HeaderStat
|
||||
heading={`${t('Funding')} / ${t('Countdown')}`}
|
||||
testId="market-funding"
|
||||
>
|
||||
<div className="flex justify-between gap-2">
|
||||
<FundingRate marketId={market.id} />
|
||||
<FundingCountdown marketId={market.id} />
|
||||
</div>
|
||||
</HeaderStat>
|
||||
)}
|
||||
)
|
||||
}
|
||||
testId="market-expiry"
|
||||
>
|
||||
<ExpiryLabel market={market} />
|
||||
</HeaderStat>
|
||||
<HeaderStat heading={t('Price')} testId="market-price">
|
||||
<MarketMarkPrice
|
||||
marketId={market.id}
|
||||
decimalPlaces={market.decimalPlaces}
|
||||
marketId={market?.id}
|
||||
decimalPlaces={market?.decimalPlaces}
|
||||
/>
|
||||
</HeaderStat>
|
||||
<HeaderStat heading={t('Change (24h)')} testId="market-change">
|
||||
<Last24hPriceChange
|
||||
marketId={market.id}
|
||||
decimalPlaces={market.decimalPlaces}
|
||||
marketId={market?.id}
|
||||
decimalPlaces={market?.decimalPlaces}
|
||||
/>
|
||||
</HeaderStat>
|
||||
<HeaderStat heading={t('Volume (24h)')} testId="market-volume">
|
||||
<Last24hVolume
|
||||
marketId={market.id}
|
||||
positionDecimalPlaces={market.positionDecimalPlaces}
|
||||
marketId={market?.id}
|
||||
positionDecimalPlaces={market?.positionDecimalPlaces}
|
||||
/>
|
||||
</HeaderStat>
|
||||
<HeaderStatMarketTradingMode
|
||||
marketId={market.id}
|
||||
initialTradingMode={market.tradingMode}
|
||||
marketId={market?.id}
|
||||
initialTradingMode={market?.tradingMode}
|
||||
/>
|
||||
<MarketState market={market} />
|
||||
{asset ? (
|
||||
@@ -105,84 +79,27 @@ export const MarketHeaderStats = ({ market }: MarketHeaderStatsProps) => {
|
||||
</HeaderStat>
|
||||
) : null}
|
||||
<MarketLiquiditySupplied
|
||||
marketId={market.id}
|
||||
marketId={market?.id}
|
||||
assetDecimals={asset?.decimals || 0}
|
||||
/>
|
||||
<MarketProposalNotification marketId={market.id} />
|
||||
<MarketProposalNotification marketId={market?.id} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
type ExpiryLabelProps = {
|
||||
market: Market;
|
||||
};
|
||||
|
||||
export const FundingRate = ({ marketId }: { marketId: string }) => {
|
||||
const { data: fundingRate } = useFundingRate(marketId);
|
||||
return (
|
||||
<div data-testid="funding-rate">
|
||||
{fundingRate ? `${(Number(fundingRate) * 100).toFixed(4)}%` : '-'}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const padStart = (n: number) => n.toString().padStart(2, '0');
|
||||
|
||||
export const FundingCountdown = ({ marketId }: { marketId: string }) => {
|
||||
const { data: fundingPeriods } = useFundingPeriodsQuery({
|
||||
variables: {
|
||||
marketId: marketId,
|
||||
pagination: { first: 1 },
|
||||
},
|
||||
});
|
||||
const { data: marketInfo } = useDataProvider({
|
||||
dataProvider: marketInfoProvider,
|
||||
variables: { marketId },
|
||||
});
|
||||
|
||||
const [now, setNow] = useState(Date.now());
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => setNow(Date.now()), 1000);
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
const node = fundingPeriods?.fundingPeriods.edges?.[0]?.node;
|
||||
let startTime: number | undefined = undefined;
|
||||
if (node && node.startTime && !node.endTime) {
|
||||
startTime = fromNanoSeconds(node.startTime).getTime();
|
||||
}
|
||||
let diffFormatted = t('Unknown');
|
||||
let every: number | undefined = undefined;
|
||||
const sourceType =
|
||||
marketInfo &&
|
||||
getDataSourceSpecForSettlementSchedule(
|
||||
marketInfo.tradableInstrument.instrument.product
|
||||
)?.data.sourceType.sourceType;
|
||||
|
||||
if (sourceType?.__typename === 'DataSourceSpecConfigurationTimeTrigger') {
|
||||
every = sourceType.triggers?.[0]?.every ?? undefined;
|
||||
if (every) {
|
||||
every *= 1000;
|
||||
}
|
||||
}
|
||||
if (startTime && every) {
|
||||
const diff = every - ((now - startTime) % every);
|
||||
const hours = (diff / 3.6e6) | 0;
|
||||
const mins = ((diff % 3.6e6) / 6e4) | 0;
|
||||
const secs = Math.round((diff % 6e4) / 1e3);
|
||||
diffFormatted = `${padStart(hours)}:${padStart(mins)}:${padStart(secs)}`;
|
||||
}
|
||||
return <div data-testid="funding-countdown">{diffFormatted}</div>;
|
||||
market: Market | null;
|
||||
};
|
||||
|
||||
const ExpiryLabel = ({ market }: ExpiryLabelProps) => {
|
||||
const content = market.tradableInstrument.instrument.metadata.tags
|
||||
? getExpiryDate(
|
||||
market.tradableInstrument.instrument.metadata.tags,
|
||||
market.marketTimestamps.close,
|
||||
market.state
|
||||
)
|
||||
: '-';
|
||||
const content =
|
||||
market && market.tradableInstrument.instrument.metadata.tags
|
||||
? getExpiryDate(
|
||||
market.tradableInstrument.instrument.metadata.tags,
|
||||
market.marketTimestamps.close,
|
||||
market.state
|
||||
)
|
||||
: '-';
|
||||
return <div data-testid="trading-expiry">{content}</div>;
|
||||
};
|
||||
|
||||
@@ -195,12 +112,10 @@ const ExpiryTooltipContent = ({
|
||||
market,
|
||||
explorerUrl,
|
||||
}: ExpiryTooltipContentProps) => {
|
||||
if (market.marketTimestamps.close === null) {
|
||||
if (market?.marketTimestamps.close === null) {
|
||||
const oracleId =
|
||||
market.tradableInstrument.instrument.product.__typename === 'Future'
|
||||
? market.tradableInstrument.instrument.product
|
||||
.dataSourceSpecForTradingTermination?.id
|
||||
: undefined;
|
||||
market.tradableInstrument.instrument.product
|
||||
.dataSourceSpecForTradingTermination?.id;
|
||||
|
||||
const metadataExpiryDate = getMarketExpiryDate(
|
||||
market.tradableInstrument.instrument.metadata.tags
|
||||
|
||||
@@ -4,12 +4,12 @@ import { t } from '@vegaprotocol/i18n';
|
||||
import { useScreenDimensions } from '@vegaprotocol/react-helpers';
|
||||
import { useThrottledDataProvider } from '@vegaprotocol/data-provider';
|
||||
import { AsyncRenderer, ExternalLink, Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { getAsset, marketDataProvider, useMarket } from '@vegaprotocol/markets';
|
||||
import { marketDataProvider, useMarket } from '@vegaprotocol/markets';
|
||||
import { useGlobalStore, usePageTitleStore } from '../../stores';
|
||||
import { TradeGrid } from './trade-grid';
|
||||
import { TradePanels } from './trade-panels';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { Links } from '../../lib/links';
|
||||
import { Links, Routes } from '../../pages/client-router';
|
||||
import { ViewType, useSidebar } from '../../components/sidebar';
|
||||
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
|
||||
|
||||
@@ -81,27 +81,37 @@ export const MarketPage = () => {
|
||||
}
|
||||
}, [setViews, view, currentRouteId, largeScreen]);
|
||||
|
||||
const pinnedAsset = data && getAsset(data);
|
||||
|
||||
const tradeView = useMemo(() => {
|
||||
if (pinnedAsset) {
|
||||
if (largeScreen) {
|
||||
return <TradeGrid market={data} pinnedAsset={pinnedAsset} />;
|
||||
}
|
||||
return <TradePanels market={data} pinnedAsset={pinnedAsset} />;
|
||||
if (largeScreen) {
|
||||
return (
|
||||
<TradeGrid
|
||||
market={data}
|
||||
pinnedAsset={
|
||||
data?.tradableInstrument.instrument.product.settlementAsset
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}, [largeScreen, data, pinnedAsset]);
|
||||
return (
|
||||
<TradePanels
|
||||
market={data}
|
||||
pinnedAsset={
|
||||
data?.tradableInstrument.instrument.product.settlementAsset
|
||||
}
|
||||
/>
|
||||
);
|
||||
}, [largeScreen, data]);
|
||||
|
||||
if (!data && marketId) {
|
||||
return (
|
||||
<Splash>
|
||||
<span className="flex flex-col items-center gap-2">
|
||||
<p className="justify-center text-sm">
|
||||
<p className="text-sm justify-center">
|
||||
{t('This market URL is not available any more.')}
|
||||
</p>
|
||||
<p className="justify-center text-sm">
|
||||
<p className="text-sm justify-center">
|
||||
{t(`Please choose another market from the`)}{' '}
|
||||
<ExternalLink onClick={() => navigate(Links.MARKETS())}>
|
||||
<ExternalLink onClick={() => navigate(Links[Routes.MARKETS]())}>
|
||||
market list
|
||||
</ExternalLink>
|
||||
</p>
|
||||
|
||||
@@ -5,7 +5,7 @@ import classNames from 'classnames';
|
||||
import AutoSizer from 'react-virtualized-auto-sizer';
|
||||
import type { PinnedAsset } from '@vegaprotocol/accounts';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { OracleBanner, useMarket } from '@vegaprotocol/markets';
|
||||
import { OracleBanner } from '@vegaprotocol/markets';
|
||||
import type { Market } from '@vegaprotocol/markets';
|
||||
import { Filter } from '@vegaprotocol/orders';
|
||||
import { Tab, LocalStoragePersistTabs as Tabs } from '@vegaprotocol/ui-toolkit';
|
||||
@@ -34,7 +34,6 @@ const MainGrid = memo(
|
||||
marketId: string;
|
||||
pinnedAsset?: PinnedAsset;
|
||||
}) => {
|
||||
const { data: market } = useMarket(marketId);
|
||||
const [sizes, handleOnLayoutChange] = usePaneLayout({ id: 'top' });
|
||||
const [sizesMiddle, handleOnMiddleLayoutChange] = usePaneLayout({
|
||||
id: 'middle-1',
|
||||
@@ -69,13 +68,6 @@ const MainGrid = memo(
|
||||
<Tab id="liquidity" name={t('Liquidity')}>
|
||||
<TradingViews.liquidity.component marketId={marketId} />
|
||||
</Tab>
|
||||
{market &&
|
||||
market.tradableInstrument.instrument.product.__typename ===
|
||||
'Perpetual' ? (
|
||||
<Tab id="funding" name={t('Funding')}>
|
||||
<TradingViews.funding.component marketId={marketId} />
|
||||
</Tab>
|
||||
) : null}
|
||||
</Tabs>
|
||||
</TradeGridChild>
|
||||
</ResizableGridPanel>
|
||||
|
||||
@@ -13,7 +13,6 @@ import { FillsContainer } from '../../components/fills-container';
|
||||
import { PositionsContainer } from '../../components/positions-container';
|
||||
import { AccountsContainer } from '../../components/accounts-container';
|
||||
import { LiquidityContainer } from '../../components/liquidity-container';
|
||||
import { FundingContainer } from '../../components/funding-container';
|
||||
import type { OrderContainerProps } from '../../components/orders-container';
|
||||
import { OrdersContainer } from '../../components/orders-container';
|
||||
import { StopOrdersContainer } from '../../components/stop-orders-container';
|
||||
@@ -51,10 +50,6 @@ export const TradingViews = {
|
||||
label: 'Liquidity',
|
||||
component: requiresMarket(LiquidityContainer),
|
||||
},
|
||||
funding: {
|
||||
label: 'Funding',
|
||||
component: requiresMarket(FundingContainer),
|
||||
},
|
||||
orderbook: {
|
||||
label: 'Orderbook',
|
||||
component: requiresMarket(OrderbookContainer),
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
OracleSpecDataConnectionDocument,
|
||||
MarketsDataDocument,
|
||||
MarketsDocument,
|
||||
getAsset,
|
||||
} from '@vegaprotocol/markets';
|
||||
import type { VegaWalletContextShape } from '@vegaprotocol/wallet';
|
||||
import { VegaWalletContext } from '@vegaprotocol/wallet';
|
||||
@@ -49,13 +48,10 @@ describe('Closed', () => {
|
||||
tags: [settlementDateTag],
|
||||
},
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
dataSourceSpecForSettlementData: {
|
||||
__typename: 'DataSourceSpec',
|
||||
id: settlementDataId,
|
||||
data: {
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionExternal',
|
||||
sourceType: {
|
||||
filters: [
|
||||
{
|
||||
@@ -168,8 +164,7 @@ describe('Closed', () => {
|
||||
Date.now = originalNow;
|
||||
});
|
||||
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
it.skip('renders correctly formatted and filtered rows', async () => {
|
||||
it('renders correctly formatted and filtered rows', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
<MemoryRouter>
|
||||
@@ -201,8 +196,6 @@ describe('Closed', () => {
|
||||
expect(headers).toHaveLength(expectedHeaders.length);
|
||||
expect(headers.map((h) => h.textContent?.trim())).toEqual(expectedHeaders);
|
||||
|
||||
const assetSymbol = getAsset(market).symbol;
|
||||
|
||||
const cells = screen.getAllByRole('gridcell');
|
||||
const expectedValues = [
|
||||
market.tradableInstrument.instrument.code,
|
||||
@@ -217,7 +210,7 @@ describe('Closed', () => {
|
||||
addDecimalsFormatNumber(marketsData!.markPrice, market.decimalPlaces),
|
||||
/* eslint-enable @typescript-eslint/no-non-null-assertion */
|
||||
addDecimalsFormatNumber(property.value, market.decimalPlaces),
|
||||
assetSymbol,
|
||||
market.tradableInstrument.instrument.product.settlementAsset.symbol,
|
||||
'', // actions row
|
||||
];
|
||||
cells.forEach((cell, i) => {
|
||||
@@ -228,7 +221,7 @@ describe('Closed', () => {
|
||||
it('only renders settled and terminated markets', async () => {
|
||||
const mixedMarkets = [
|
||||
{
|
||||
// include as settled
|
||||
// inlclude as settled
|
||||
__typename: 'MarketEdge' as const,
|
||||
node: createMarketFragment({
|
||||
id: 'include-0',
|
||||
|
||||
@@ -4,29 +4,29 @@ 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';
|
||||
import type { ProductType } from '@vegaprotocol/types';
|
||||
import { MarketState, MarketStateMapping } from '@vegaprotocol/types';
|
||||
import {
|
||||
addDecimalsFormatNumber,
|
||||
getMarketExpiryDate,
|
||||
} from '@vegaprotocol/utils';
|
||||
import { closedMarketsWithDataProvider, getAsset } from '@vegaprotocol/markets';
|
||||
import type { DataSourceFilterFragment } from '@vegaprotocol/markets';
|
||||
import type {
|
||||
DataSourceFilterFragment,
|
||||
MarketMaybeWithData,
|
||||
} from '@vegaprotocol/markets';
|
||||
import { closedMarketsWithDataProvider } from '@vegaprotocol/markets';
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||
import { SettlementDateCell } from './settlement-date-cell';
|
||||
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 { MarketCodeCell } from './market-code-cell';
|
||||
|
||||
type SettlementAsset = Pick<
|
||||
Asset,
|
||||
'decimals' | 'name' | 'quantum' | 'id' | 'symbol'
|
||||
>;
|
||||
type SettlementAsset =
|
||||
MarketMaybeWithData['tradableInstrument']['instrument']['product']['settlementAsset'];
|
||||
|
||||
interface Row {
|
||||
id: string;
|
||||
@@ -41,7 +41,7 @@ interface Row {
|
||||
markPrice: string | undefined;
|
||||
settlementDataOracleId: string;
|
||||
settlementDataSpecBinding: string;
|
||||
settlementDataSourceFilter: DataSourceFilterFragment | undefined;
|
||||
setlementDataSourceFilter: DataSourceFilterFragment | undefined;
|
||||
tradingTerminationOracleId: string;
|
||||
settlementAsset: SettlementAsset;
|
||||
productType: ProductType | undefined;
|
||||
@@ -59,26 +59,18 @@ export const Closed = () => {
|
||||
const instrument = market.tradableInstrument.instrument;
|
||||
|
||||
const spec =
|
||||
(instrument.product.__typename === 'Future' ||
|
||||
instrument.product.__typename === 'Perpetual') &&
|
||||
instrument.product.dataSourceSpecForSettlementData.data.sourceType
|
||||
.__typename === 'DataSourceDefinitionExternal'
|
||||
? instrument.product.dataSourceSpecForSettlementData.data.sourceType
|
||||
.sourceType
|
||||
: undefined;
|
||||
const filters = (spec && 'filters' in spec && spec.filters) || [];
|
||||
const filters = spec?.filters || [];
|
||||
|
||||
const settlementDataSpecBinding =
|
||||
instrument.product.__typename === 'Future' ||
|
||||
instrument.product.__typename === 'Perpetual'
|
||||
? instrument.product.dataSourceSpecBinding.settlementDataProperty
|
||||
: '';
|
||||
const filter =
|
||||
filters && Array.isArray(filters)
|
||||
? filters?.find((filter) => {
|
||||
return filter.key.name === settlementDataSpecBinding;
|
||||
})
|
||||
: undefined;
|
||||
instrument.product.dataSourceSpecBinding.settlementDataProperty;
|
||||
const filter = filters?.find((filter) => {
|
||||
return filter.key.name === settlementDataSpecBinding;
|
||||
});
|
||||
|
||||
const row: Row = {
|
||||
id: market.id,
|
||||
@@ -92,17 +84,12 @@ export const Closed = () => {
|
||||
bestOfferPrice: market.data?.bestOfferPrice,
|
||||
markPrice: market.data?.markPrice,
|
||||
settlementDataOracleId:
|
||||
instrument.product.__typename === 'Future' ||
|
||||
instrument.product.__typename === 'Perpetual'
|
||||
? instrument.product.dataSourceSpecForSettlementData.id
|
||||
: '',
|
||||
instrument.product.dataSourceSpecForSettlementData.id,
|
||||
settlementDataSpecBinding,
|
||||
settlementDataSourceFilter: filter,
|
||||
setlementDataSourceFilter: filter,
|
||||
tradingTerminationOracleId:
|
||||
instrument.product.__typename === 'Future'
|
||||
? instrument.product.dataSourceSpecForTradingTermination.id
|
||||
: '',
|
||||
settlementAsset: getAsset({ tradableInstrument: { instrument } }),
|
||||
instrument.product.dataSourceSpecForTradingTermination.id,
|
||||
settlementAsset: instrument.product.settlementAsset,
|
||||
productType: instrument.product.__typename,
|
||||
successorMarketID: market.successorMarketID,
|
||||
parentMarketID: market.parentMarketID,
|
||||
@@ -234,7 +221,7 @@ const ClosedMarketsDataGrid = ({
|
||||
<SettlementPriceCell
|
||||
oracleSpecId={value}
|
||||
settlementDataSpecBinding={data?.settlementDataSpecBinding}
|
||||
filter={data?.settlementDataSourceFilter}
|
||||
filter={data?.setlementDataSourceFilter}
|
||||
/>
|
||||
),
|
||||
},
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
export { MarketsPage } from './markets-page';
|
||||
import { MarketsPage } from './markets-page';
|
||||
|
||||
export default MarketsPage;
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
import { DApp, EXPLORER_MARKET, useLinks } from '@vegaprotocol/environment';
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Links } from '../../lib/links';
|
||||
import { Links, Routes } from '../../pages/client-router';
|
||||
|
||||
export const MarketActionsDropdown = ({
|
||||
marketId,
|
||||
@@ -52,7 +52,7 @@ export const MarketActionsDropdown = ({
|
||||
{parentMarketID && (
|
||||
<TradingDropdownItem
|
||||
onClick={() => {
|
||||
navigate(Links.MARKET(parentMarketID));
|
||||
navigate(Links[Routes.MARKET](parentMarketID));
|
||||
}}
|
||||
>
|
||||
<VegaIcon name={VegaIconNames.EYE} size={16} />
|
||||
@@ -62,7 +62,7 @@ export const MarketActionsDropdown = ({
|
||||
{successorMarketID && (
|
||||
<TradingDropdownItem
|
||||
onClick={() => {
|
||||
navigate(Links.MARKET(successorMarketID));
|
||||
navigate(Links[Routes.MARKET](successorMarketID));
|
||||
}}
|
||||
>
|
||||
<VegaIcon name={VegaIconNames.EYE} size={16} />
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { Icon } from '@vegaprotocol/ui-toolkit';
|
||||
import type { IconName } from '@blueprintjs/icons';
|
||||
import type { Market } from '@vegaprotocol/markets';
|
||||
import {
|
||||
getMatchingOracleProvider,
|
||||
getVerifiedStatusIcon,
|
||||
useOracleProofs,
|
||||
} from '@vegaprotocol/markets';
|
||||
|
||||
export const OracleStatus = ({
|
||||
dataSourceSpecForSettlementData,
|
||||
dataSourceSpecForTradingTermination,
|
||||
}: Pick<
|
||||
Market['tradableInstrument']['instrument']['product'],
|
||||
'dataSourceSpecForSettlementData' | 'dataSourceSpecForTradingTermination'
|
||||
>) => {
|
||||
const { ORACLE_PROOFS_URL } = useEnvironment();
|
||||
const { data: providers } = useOracleProofs(ORACLE_PROOFS_URL);
|
||||
|
||||
if (providers) {
|
||||
const settlementDataProvider = getMatchingOracleProvider(
|
||||
dataSourceSpecForSettlementData.data,
|
||||
providers
|
||||
);
|
||||
const tradingTerminationDataProvider = getMatchingOracleProvider(
|
||||
dataSourceSpecForTradingTermination.data,
|
||||
providers
|
||||
);
|
||||
let maliciousOracleProvider = null;
|
||||
|
||||
if (settlementDataProvider?.oracle.status !== 'GOOD') {
|
||||
maliciousOracleProvider = settlementDataProvider;
|
||||
} else if (tradingTerminationDataProvider?.oracle.status !== 'GOOD') {
|
||||
maliciousOracleProvider = tradingTerminationDataProvider;
|
||||
}
|
||||
|
||||
if (!maliciousOracleProvider) return null;
|
||||
|
||||
const { icon } = getVerifiedStatusIcon(maliciousOracleProvider);
|
||||
|
||||
return <Icon size={3} name={icon as IconName} className="ml-1" />;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
@@ -16,7 +16,7 @@ import type {
|
||||
MarketMaybeWithDataAndCandles,
|
||||
} from '@vegaprotocol/markets';
|
||||
import { MarketActionsDropdown } from './market-table-actions';
|
||||
import { calcCandleVolume, getAsset } from '@vegaprotocol/markets';
|
||||
import { calcCandleVolume } from '@vegaprotocol/markets';
|
||||
import { MarketCodeCell } from './market-code-cell';
|
||||
|
||||
const { MarketTradingMode, AuctionTrigger } = Schema;
|
||||
@@ -151,7 +151,8 @@ export const useColumnDefs = () => {
|
||||
MarketMaybeWithData,
|
||||
'tradableInstrument.instrument.product.settlementAsset.symbol'
|
||||
>) => {
|
||||
const value = data && getAsset(data);
|
||||
const value =
|
||||
data?.tradableInstrument.instrument.product.settlementAsset;
|
||||
return value ? (
|
||||
<ButtonLink
|
||||
onClick={(e) => {
|
||||
@@ -210,7 +211,9 @@ export const useColumnDefs = () => {
|
||||
return (
|
||||
<MarketActionsDropdown
|
||||
marketId={data.id}
|
||||
assetId={getAsset(data).id}
|
||||
assetId={
|
||||
data.tradableInstrument.instrument.product.settlementAsset.id
|
||||
}
|
||||
successorMarketID={data.successorMarketID}
|
||||
parentMarketID={data.parentMarketID}
|
||||
/>
|
||||
|
||||
@@ -30,9 +30,9 @@ import {
|
||||
useThemeSwitcher,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||
import { getAsset, type Market } from '@vegaprotocol/markets';
|
||||
import type { Market } from '@vegaprotocol/markets';
|
||||
|
||||
export const DateRange = {
|
||||
const DateRange = {
|
||||
RANGE_1D: '1D',
|
||||
RANGE_7D: '7D',
|
||||
RANGE_1M: '1M',
|
||||
@@ -47,7 +47,7 @@ const dateRangeToggleItems = Object.entries(DateRange).map(([_, value]) => ({
|
||||
value: value,
|
||||
}));
|
||||
|
||||
export const calculateStartDate = (range: string): string | undefined => {
|
||||
const calculateStartDate = (range: string): string | undefined => {
|
||||
const now = new Date();
|
||||
switch (range) {
|
||||
case DateRange.RANGE_1D:
|
||||
@@ -131,12 +131,11 @@ const AccountHistoryManager = ({
|
||||
DateRange.RANGE_1M
|
||||
);
|
||||
const [market, setMarket] = useState<Market | null>(null);
|
||||
|
||||
const marketFilterCb = useCallback(
|
||||
(item: Market) => {
|
||||
const itemAsset = getAsset(item);
|
||||
return !asset?.id || itemAsset?.id === asset?.id;
|
||||
},
|
||||
(item: Market) =>
|
||||
!asset?.id ||
|
||||
item.tradableInstrument.instrument.product.settlementAsset.id ===
|
||||
asset?.id,
|
||||
[asset?.id]
|
||||
);
|
||||
const markets = useMemo<Market[] | null>(() => {
|
||||
@@ -156,8 +155,8 @@ const AccountHistoryManager = ({
|
||||
const resolveMarket = useCallback(
|
||||
(m: Market) => {
|
||||
setMarket(m);
|
||||
const itemAsset = getAsset(m);
|
||||
const newAssetId = itemAsset?.id;
|
||||
const newAssetId =
|
||||
m.tradableInstrument.instrument.product.settlementAsset.id;
|
||||
const newAsset = assets.find((item) => item.id === newAssetId);
|
||||
if ((!asset || (assets && newAssetId !== asset.id)) && newAsset) {
|
||||
setAssetId(newAsset.id);
|
||||
@@ -242,7 +241,11 @@ const AccountHistoryManager = ({
|
||||
setAssetId(a.id);
|
||||
|
||||
// if the selected asset is different to the selected market clear the market
|
||||
if (market && a.id !== getAsset(market).id) {
|
||||
if (
|
||||
a.id !==
|
||||
market?.tradableInstrument.instrument.product
|
||||
.settlementAsset.id
|
||||
) {
|
||||
setMarket(null);
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
export { Portfolio as default } from './portfolio';
|
||||
import { Portfolio } from './portfolio';
|
||||
|
||||
export default Portfolio;
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export { Transfer } from './transfer';
|
||||
@@ -1,30 +0,0 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { Transfer } from './transfer';
|
||||
|
||||
jest.mock('@vegaprotocol/accounts', () => ({
|
||||
TransferContainer: ({ assetId }: { assetId?: string }) => (
|
||||
<div data-testid="assetId">{assetId}</div>
|
||||
),
|
||||
}));
|
||||
|
||||
jest.mock('../../components/welcome-dialog/get-started.ts', () => ({
|
||||
GetStarted: () => <div>GetStarted</div>,
|
||||
}));
|
||||
|
||||
const renderJsx = (route = '/transfer') => {
|
||||
render(
|
||||
<MemoryRouter initialEntries={[route]}>
|
||||
<Transfer />
|
||||
</MemoryRouter>
|
||||
);
|
||||
};
|
||||
|
||||
describe('Transfer page', () => {
|
||||
it('assetId should be passed down', () => {
|
||||
const assetId = 'foo';
|
||||
const route = '/transfer?assetId=' + assetId;
|
||||
renderJsx(route);
|
||||
expect(screen.getByTestId('assetId')).toHaveTextContent(assetId);
|
||||
});
|
||||
});
|
||||
@@ -1,15 +0,0 @@
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { TransferContainer } from '@vegaprotocol/accounts';
|
||||
import { GetStarted } from '../../components/welcome-dialog';
|
||||
|
||||
export const Transfer = () => {
|
||||
const [searchParams] = useSearchParams();
|
||||
const assetId = searchParams.get('assetId') || undefined;
|
||||
|
||||
return (
|
||||
<>
|
||||
<TransferContainer assetId={assetId} />
|
||||
<GetStarted />
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
export { Withdraw } from './withdraw';
|
||||
@@ -1,30 +0,0 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { Withdraw } from './withdraw';
|
||||
|
||||
jest.mock('../../components/withdraw-container', () => ({
|
||||
WithdrawContainer: ({ assetId }: { assetId?: string }) => (
|
||||
<div data-testid="assetId">{assetId}</div>
|
||||
),
|
||||
}));
|
||||
|
||||
jest.mock('../../components/welcome-dialog/get-started.ts', () => ({
|
||||
GetStarted: () => <div>GetStarted</div>,
|
||||
}));
|
||||
|
||||
const renderJsx = (route = '/withdraw') => {
|
||||
render(
|
||||
<MemoryRouter initialEntries={[route]}>
|
||||
<Withdraw />
|
||||
</MemoryRouter>
|
||||
);
|
||||
};
|
||||
|
||||
describe('Withdraw page', () => {
|
||||
it('assetId should be passed down', () => {
|
||||
const assetId = 'foo';
|
||||
const route = '/withdraw?assetId=' + assetId;
|
||||
renderJsx(route);
|
||||
expect(screen.getByTestId('assetId')).toHaveTextContent(assetId);
|
||||
});
|
||||
});
|
||||
@@ -1,14 +0,0 @@
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { GetStarted } from '../../components/welcome-dialog';
|
||||
import { WithdrawContainer } from '../../components/withdraw-container';
|
||||
|
||||
export const Withdraw = () => {
|
||||
const [searchParams] = useSearchParams();
|
||||
const assetId = searchParams.get('assetId') || undefined;
|
||||
return (
|
||||
<>
|
||||
<WithdrawContainer assetId={assetId} />
|
||||
<GetStarted />
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -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')"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
export * from './announcement-banner';
|
||||
export * from './upgrade-banner';
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
import { gt, prerelease } from 'semver';
|
||||
import {
|
||||
ReleasesFeed,
|
||||
useEnvironment,
|
||||
useReleases,
|
||||
Networks,
|
||||
} from '@vegaprotocol/environment';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import {
|
||||
CopyWithTooltip,
|
||||
ExternalLink,
|
||||
Intent,
|
||||
NotificationBanner,
|
||||
VegaIcon,
|
||||
VegaIconNames,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
// v0.20.12-core-0.71.4 -> v0.20.12
|
||||
// we need to strip the "core" suffix in order to determine whether a release
|
||||
// is a pre-release (candidate); example: v.0.21.0-beta.1-core-0.71.4
|
||||
const parseTagName = (tagName: string) => tagName.replace(/-core-[\d.]+$/i, '');
|
||||
|
||||
type UpgradeBannerProps = {
|
||||
showVersionChange: boolean;
|
||||
};
|
||||
export const UpgradeBanner = ({ showVersionChange }: UpgradeBannerProps) => {
|
||||
const [visible, setVisible] = useState(true);
|
||||
const { data } = useReleases(ReleasesFeed.FrontEnd);
|
||||
const { APP_VERSION, VEGA_ENV, VEGA_NETWORKS } = useEnvironment();
|
||||
|
||||
const CANONICAL_URL = VEGA_NETWORKS[VEGA_ENV] || 'https://console.vega.xyz';
|
||||
|
||||
const newest = useMemo(() => {
|
||||
if (!APP_VERSION || !data) return undefined;
|
||||
const newer = data.filter((r) => gt(r.tagName, APP_VERSION));
|
||||
const valid =
|
||||
// filter pre-releases on mainnet
|
||||
VEGA_ENV === Networks.MAINNET
|
||||
? newer?.filter((r) => !prerelease(parseTagName(r.tagName)))
|
||||
: newer;
|
||||
return valid.sort((a, b) => (gt(a.tagName, b.tagName) ? -1 : 1))[0];
|
||||
}, [APP_VERSION, VEGA_ENV, data]);
|
||||
|
||||
if (!visible || !newest) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<NotificationBanner
|
||||
intent={Intent.Warning}
|
||||
onClose={() => {
|
||||
setVisible(false);
|
||||
}}
|
||||
>
|
||||
<div className="uppercase mb-1">
|
||||
<ExternalLink href={CANONICAL_URL}>
|
||||
{t('Upgrade to the latest version of Console')}
|
||||
</ExternalLink>
|
||||
</div>
|
||||
<div data-testid="bookmark-message">
|
||||
<a
|
||||
className="underline"
|
||||
href={newest.htmlUrl}
|
||||
rel="noreferrer nofollow noopener"
|
||||
target="_blank"
|
||||
>
|
||||
{t("View what's changed")}
|
||||
</a>{' '}
|
||||
{t(' or bookmark')}{' '}
|
||||
<a className="underline" href={CANONICAL_URL}>
|
||||
{t('console.vega.xyz')}
|
||||
</a>{' '}
|
||||
<CopyWithTooltip text={CANONICAL_URL}>
|
||||
<button title={t('Copy %s', CANONICAL_URL)}>
|
||||
<span className="sr-only">{t('Copy %s', CANONICAL_URL)}</span>
|
||||
<VegaIcon size={14} name={VegaIconNames.COPY} />
|
||||
</button>
|
||||
</CopyWithTooltip>{' '}
|
||||
{'to always see the latest version.'}
|
||||
</div>
|
||||
</NotificationBanner>
|
||||
);
|
||||
};
|
||||
@@ -1,55 +0,0 @@
|
||||
import { fromNanoSeconds } from '@vegaprotocol/utils';
|
||||
|
||||
import compact from 'lodash/compact';
|
||||
import sortBy from 'lodash/sortBy';
|
||||
import 'pennant/dist/style.css';
|
||||
import { useFundingPeriodsQuery } from '@vegaprotocol/markets';
|
||||
import { LineChart } from 'pennant';
|
||||
import { useMemo } from 'react';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { useThemeSwitcher } from '@vegaprotocol/react-helpers';
|
||||
import { Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import {
|
||||
DateRange,
|
||||
calculateStartDate,
|
||||
} from '../../client-pages/portfolio/account-history-container';
|
||||
|
||||
export const FundingContainer = ({ marketId }: { marketId: string }) => {
|
||||
const { theme } = useThemeSwitcher();
|
||||
const variables = useMemo(
|
||||
() => ({
|
||||
marketId: marketId || '',
|
||||
dateRange: { start: calculateStartDate(DateRange.RANGE_7D) },
|
||||
}),
|
||||
[marketId]
|
||||
);
|
||||
const { data } = useFundingPeriodsQuery({
|
||||
variables,
|
||||
skip: !marketId,
|
||||
});
|
||||
const values: { cols: [string, string]; rows: [Date, number][] } | null =
|
||||
useMemo(() => {
|
||||
if (!data?.fundingPeriods.edges.length) {
|
||||
return null;
|
||||
}
|
||||
const rows = compact(data?.fundingPeriods.edges)
|
||||
.filter((edge) => edge.node.endTime)
|
||||
.reduce((acc, edge) => {
|
||||
if (edge.node.endTime) {
|
||||
acc?.push({
|
||||
endTime: fromNanoSeconds(edge.node.endTime),
|
||||
fundingRate: Number(edge.node.fundingRate),
|
||||
});
|
||||
}
|
||||
return acc;
|
||||
}, [] as { endTime: Date; fundingRate: number }[]);
|
||||
return {
|
||||
cols: ['Date', t('Funding rate')],
|
||||
rows: sortBy(rows, 'endTime').map((d) => [d.endTime, d.fundingRate]),
|
||||
};
|
||||
}, [data?.fundingPeriods.edges]);
|
||||
if (!data || !values?.rows.length) {
|
||||
return <Splash> {t('No funding history data')}</Splash>;
|
||||
}
|
||||
return <LineChart data={values} theme={theme} />;
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
export * from './funding-container';
|
||||
@@ -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}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
import { Outlet } from 'react-router-dom';
|
||||
|
||||
export const LayoutCentered = () => {
|
||||
return (
|
||||
<div className="mx-auto lg:min-w-[700px] min-w-[300px] max-w-[700px] px-4 lg:px-8 py-8 lg:py-16">
|
||||
<Outlet />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Outlet, Routes, Route } from 'react-router-dom';
|
||||
import { Sidebar, SidebarContent, useSidebar } from '../sidebar';
|
||||
import classNames from 'classnames';
|
||||
import { Routes as AppRoutes } from '../../pages/client-router';
|
||||
import { MarketHeader } from '../market-header';
|
||||
import { LiquidityHeader } from '../liquidity-header';
|
||||
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
|
||||
@@ -22,8 +23,8 @@ export const LayoutWithSidebar = () => {
|
||||
<div className={gridClasses}>
|
||||
<div className="col-span-full">
|
||||
<Routes>
|
||||
<Route path="markets/:marketId" element={<MarketHeader />} />
|
||||
<Route path="liquidity/:marketId" element={<LiquidityHeader />} />
|
||||
<Route path={AppRoutes.MARKET} element={<MarketHeader />} />
|
||||
<Route path={AppRoutes.LIQUIDITY} element={<LiquidityHeader />} />
|
||||
</Routes>
|
||||
</div>
|
||||
<main
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
LiquidityTable,
|
||||
liquidityProvisionsDataProvider,
|
||||
} from '@vegaprotocol/liquidity';
|
||||
import { getAsset, useMarket } from '@vegaprotocol/markets';
|
||||
import { useMarket } from '@vegaprotocol/markets';
|
||||
import {
|
||||
NetworkParams,
|
||||
useNetworkParams,
|
||||
@@ -42,11 +42,12 @@ export const LiquidityContainer = ({
|
||||
skip: !marketId,
|
||||
});
|
||||
|
||||
const itemAsset = market && getAsset(market);
|
||||
|
||||
const assetDecimalPlaces = itemAsset?.decimals || 0;
|
||||
const quantum = itemAsset?.quantum || 0;
|
||||
const symbol = itemAsset?.symbol;
|
||||
const assetDecimalPlaces =
|
||||
market?.tradableInstrument.instrument.product.settlementAsset.decimals || 0;
|
||||
const quantum =
|
||||
market?.tradableInstrument.instrument.product.settlementAsset.quantum || 0;
|
||||
const symbol =
|
||||
market?.tradableInstrument.instrument.product.settlementAsset.symbol;
|
||||
|
||||
const { params } = useNetworkParams([
|
||||
NetworkParams.market_liquidity_stakeToCcyVolume,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {
|
||||
getAsset,
|
||||
tooltipMapping,
|
||||
useMarket,
|
||||
useStaticMarketData,
|
||||
@@ -25,11 +24,10 @@ export const LiquidityHeader = () => {
|
||||
const { data: marketData } = useStaticMarketData(marketId);
|
||||
const targetStake = marketData?.targetStake;
|
||||
const suppliedStake = marketData?.suppliedStake;
|
||||
|
||||
const asset = market && getAsset(market);
|
||||
|
||||
const assetDecimalPlaces = asset?.decimals || 0;
|
||||
const symbol = asset?.symbol;
|
||||
const assetDecimalPlaces =
|
||||
market?.tradableInstrument.instrument.product.settlementAsset.decimals || 0;
|
||||
const symbol =
|
||||
market?.tradableInstrument.instrument.product.settlementAsset.symbol;
|
||||
|
||||
const { params } = useNetworkParams([
|
||||
NetworkParams.market_liquidity_stakeToCcyVolume,
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
Indicator,
|
||||
KeyValueTable,
|
||||
KeyValueTableRow,
|
||||
Link as UILink,
|
||||
Link,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { useCheckLiquidityStatus } from '@vegaprotocol/liquidity';
|
||||
@@ -23,8 +23,6 @@ import {
|
||||
} from '@vegaprotocol/utils';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { DocsLinks } from '@vegaprotocol/environment';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Links } from '../../lib/links';
|
||||
|
||||
interface Props {
|
||||
marketId?: string;
|
||||
@@ -102,51 +100,51 @@ export const MarketLiquiditySupplied = ({
|
||||
|
||||
const description = marketId ? (
|
||||
<section data-testid="liquidity-supplied-tooltip">
|
||||
<div className="mb-2">
|
||||
<KeyValueTable>
|
||||
<KeyValueTableRow>
|
||||
<span>{t('Supplied stake')}</span>
|
||||
<span>
|
||||
{market?.suppliedStake
|
||||
? addDecimalsFormatNumber(
|
||||
new BigNumber(market?.suppliedStake).toString(),
|
||||
assetDecimals
|
||||
)
|
||||
: '-'}
|
||||
</span>
|
||||
</KeyValueTableRow>
|
||||
<KeyValueTableRow>
|
||||
<span>{t('Target stake')}</span>
|
||||
<span>
|
||||
{market?.targetStake
|
||||
? addDecimalsFormatNumber(
|
||||
new BigNumber(market?.targetStake).toString(),
|
||||
assetDecimals
|
||||
)
|
||||
: '-'}
|
||||
</span>
|
||||
</KeyValueTableRow>
|
||||
</KeyValueTable>
|
||||
<KeyValueTable>
|
||||
<KeyValueTableRow>
|
||||
<span>{t('Supplied stake')}</span>
|
||||
<span>
|
||||
{market?.suppliedStake
|
||||
? addDecimalsFormatNumber(
|
||||
new BigNumber(market?.suppliedStake).toString(),
|
||||
assetDecimals
|
||||
)
|
||||
: '-'}
|
||||
</span>
|
||||
</KeyValueTableRow>
|
||||
<KeyValueTableRow>
|
||||
<span>{t('Target stake')}</span>
|
||||
<span>
|
||||
{market?.targetStake
|
||||
? addDecimalsFormatNumber(
|
||||
new BigNumber(market?.targetStake).toString(),
|
||||
assetDecimals
|
||||
)
|
||||
: '-'}
|
||||
</span>
|
||||
</KeyValueTableRow>
|
||||
</KeyValueTable>
|
||||
<br />
|
||||
<div className="flex flex-col gap-2">
|
||||
<Link
|
||||
href={`/#/liquidity/${marketId}`}
|
||||
data-testid="view-liquidity-link"
|
||||
>
|
||||
{t('View liquidity provision table')}
|
||||
</Link>
|
||||
{DocsLinks && (
|
||||
<ExternalLink href={DocsLinks.LIQUIDITY} className="mt-2">
|
||||
{t('Learn about providing liquidity')}
|
||||
</ExternalLink>
|
||||
)}
|
||||
</div>
|
||||
{showMessage && (
|
||||
<p className="mb-2">
|
||||
<p className="mt-4">
|
||||
{t(
|
||||
'The market has sufficient liquidity but there are not enough priced limit orders in the order book, which are required to deploy liquidity commitment pegged orders.'
|
||||
)}
|
||||
</p>
|
||||
)}
|
||||
<div className="flex flex-col gap-2">
|
||||
<Link to={Links.LIQUIDITY(marketId)} data-testid="view-liquidity-link">
|
||||
<UILink>{t('View liquidity provision table')}</UILink>
|
||||
</Link>
|
||||
</div>
|
||||
{DocsLinks && (
|
||||
<div>
|
||||
<ExternalLink href={DocsLinks.LIQUIDITY} className="mt-2">
|
||||
{t('Learn about providing liquidity')}
|
||||
</ExternalLink>
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
) : (
|
||||
'-'
|
||||
|
||||
@@ -5,7 +5,6 @@ import { MarketSelector } from '../../components/market-selector/market-selector
|
||||
import { MarketHeaderStats } from '../../client-pages/market/market-header-stats';
|
||||
import { useMarket, useMarketList } from '@vegaprotocol/markets';
|
||||
import { useState } from 'react';
|
||||
import { MarketProductPill } from '@vegaprotocol/datagrid';
|
||||
|
||||
export const MarketHeader = () => {
|
||||
const { marketId } = useParams();
|
||||
@@ -26,14 +25,7 @@ export const MarketHeader = () => {
|
||||
onChange={setOpen}
|
||||
trigger={
|
||||
<HeaderTitle>
|
||||
<span>
|
||||
{data.tradableInstrument.instrument.code}
|
||||
<MarketProductPill
|
||||
productType={
|
||||
data.tradableInstrument.instrument.product.__typename
|
||||
}
|
||||
/>
|
||||
</span>
|
||||
{data.tradableInstrument.instrument.code}
|
||||
<VegaIcon name={VegaIconNames.CHEVRON_DOWN} size={14} />
|
||||
</HeaderTitle>
|
||||
}
|
||||
|
||||
@@ -24,37 +24,35 @@ export const AssetDropdown = ({
|
||||
}
|
||||
|
||||
return (
|
||||
assets && (
|
||||
<TradingDropdown
|
||||
trigger={
|
||||
<TradingDropdownTrigger data-testid="asset-trigger">
|
||||
<MarketSelectorButton>
|
||||
{triggerText({ assets, checkedAssets })}
|
||||
</MarketSelectorButton>
|
||||
</TradingDropdownTrigger>
|
||||
}
|
||||
>
|
||||
<TradingDropdownContent>
|
||||
{assets.filter(Boolean).map((a) => {
|
||||
return (
|
||||
<TradingDropdownCheckboxItem
|
||||
key={a.id}
|
||||
checked={checkedAssets.includes(a.id)}
|
||||
onCheckedChange={(checked) => {
|
||||
if (typeof checked === 'boolean') {
|
||||
onSelect(a.id, checked);
|
||||
}
|
||||
}}
|
||||
data-testid={`asset-id-${a.id}`}
|
||||
>
|
||||
{a.symbol}
|
||||
<TradingDropdownItemIndicator />
|
||||
</TradingDropdownCheckboxItem>
|
||||
);
|
||||
})}
|
||||
</TradingDropdownContent>
|
||||
</TradingDropdown>
|
||||
)
|
||||
<TradingDropdown
|
||||
trigger={
|
||||
<TradingDropdownTrigger data-testid="asset-trigger">
|
||||
<MarketSelectorButton>
|
||||
{triggerText({ assets, checkedAssets })}
|
||||
</MarketSelectorButton>
|
||||
</TradingDropdownTrigger>
|
||||
}
|
||||
>
|
||||
<TradingDropdownContent>
|
||||
{assets?.map((a) => {
|
||||
return (
|
||||
<TradingDropdownCheckboxItem
|
||||
key={a.id}
|
||||
checked={checkedAssets.includes(a.id)}
|
||||
onCheckedChange={(checked) => {
|
||||
if (typeof checked === 'boolean') {
|
||||
onSelect(a.id, checked);
|
||||
}
|
||||
}}
|
||||
data-testid={`asset-id-${a.id}`}
|
||||
>
|
||||
{a.symbol}
|
||||
<TradingDropdownItemIndicator />
|
||||
</TradingDropdownCheckboxItem>
|
||||
);
|
||||
})}
|
||||
</TradingDropdownContent>
|
||||
</TradingDropdown>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import type {
|
||||
MarketDataUpdateFieldsFragment,
|
||||
MarketDataUpdateSubscription,
|
||||
} from '@vegaprotocol/markets';
|
||||
import { MarketCandlesDocument, getAsset } from '@vegaprotocol/markets';
|
||||
import { MarketCandlesDocument } from '@vegaprotocol/markets';
|
||||
import { MarketDataUpdateDocument } from '@vegaprotocol/markets';
|
||||
import {
|
||||
AuctionTrigger,
|
||||
@@ -35,7 +35,6 @@ describe('MarketSelectorItem', () => {
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
settlementAsset: {
|
||||
symbol: 'SYM',
|
||||
},
|
||||
@@ -120,7 +119,8 @@ describe('MarketSelectorItem', () => {
|
||||
});
|
||||
|
||||
it('renders market information', async () => {
|
||||
const symbol = getAsset(market).symbol;
|
||||
const symbol =
|
||||
market.tradableInstrument.instrument.product.settlementAsset.symbol;
|
||||
|
||||
const mock: MockedResponse<MarketDataUpdateSubscription> = {
|
||||
request: {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Link } from 'react-router-dom';
|
||||
import classNames from 'classnames';
|
||||
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
|
||||
import type { MarketMaybeWithDataAndCandles } from '@vegaprotocol/markets';
|
||||
import { calcCandleVolume, getAsset } from '@vegaprotocol/markets';
|
||||
import { calcCandleVolume } from '@vegaprotocol/markets';
|
||||
import { useCandles } from '@vegaprotocol/markets';
|
||||
import { useMarketDataUpdateSubscription } from '@vegaprotocol/markets';
|
||||
import { Sparkline } from '@vegaprotocol/ui-toolkit';
|
||||
@@ -80,6 +80,7 @@ const MarketData = ({
|
||||
? MarketTradingModeMapping[marketTradingMode]
|
||||
: '';
|
||||
|
||||
const instrument = market.tradableInstrument.instrument;
|
||||
const { oneDayCandles } = useCandles({ marketId: market.id });
|
||||
|
||||
const vol = oneDayCandles ? calcCandleVolume(oneDayCandles) : '0';
|
||||
@@ -89,15 +90,12 @@ const MarketData = ({
|
||||
: '0.00';
|
||||
|
||||
const productType = market.tradableInstrument.instrument.product.__typename;
|
||||
const symbol = getAsset(market).symbol || '';
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="w-2/5" role="gridcell">
|
||||
<h3 className="flex items-baseline">
|
||||
<span className="text-sm lg:text-base text-ellipsis whitespace-nowrap overflow-hidden">
|
||||
{market.tradableInstrument.instrument.code}
|
||||
</span>
|
||||
<h3 className="overflow-hidden text-sm text-ellipsis lg:text-base whitespace-nowrap">
|
||||
{market.tradableInstrument.instrument.code}{' '}
|
||||
{allProducts && productType && (
|
||||
<MarketProductPill productType={productType} />
|
||||
)}
|
||||
@@ -110,11 +108,11 @@ const MarketData = ({
|
||||
</div>
|
||||
<div
|
||||
className="w-1/5 overflow-hidden text-xs lg:text-sm whitespace-nowrap text-ellipsis"
|
||||
title={symbol}
|
||||
title={instrument.product.settlementAsset.symbol}
|
||||
data-testid="market-selector-price"
|
||||
role="gridcell"
|
||||
>
|
||||
{price} {symbol}
|
||||
{price} {instrument.product.settlementAsset.symbol}
|
||||
</div>
|
||||
<div
|
||||
className="w-1/5 overflow-hidden text-xs text-right lg:text-sm whitespace-nowrap text-ellipsis"
|
||||
|
||||
@@ -22,7 +22,7 @@ jest.mock('./market-selector-item', () => ({
|
||||
),
|
||||
}));
|
||||
|
||||
// without a real DOM auto-size won't render with an actual height or width
|
||||
// without a real DOM autosize won't render with an actual height or width
|
||||
jest.mock('react-virtualized-auto-sizer', () => {
|
||||
// eslint-disable-next-line react/display-name
|
||||
return ({
|
||||
@@ -41,7 +41,6 @@ describe('MarketSelector', () => {
|
||||
code: 'a',
|
||||
name: 'a',
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
settlementAsset: {
|
||||
id: 'asset-0',
|
||||
},
|
||||
@@ -62,7 +61,6 @@ describe('MarketSelector', () => {
|
||||
code: 'b',
|
||||
name: 'b',
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
settlementAsset: {
|
||||
id: 'asset-0',
|
||||
},
|
||||
@@ -81,7 +79,6 @@ describe('MarketSelector', () => {
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
settlementAsset: {
|
||||
id: 'asset-1',
|
||||
},
|
||||
@@ -97,7 +94,6 @@ describe('MarketSelector', () => {
|
||||
code: 'c',
|
||||
name: 'c',
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
settlementAsset: {
|
||||
id: 'asset-1',
|
||||
},
|
||||
@@ -117,7 +113,6 @@ describe('MarketSelector', () => {
|
||||
code: 'cd',
|
||||
name: 'cd',
|
||||
product: {
|
||||
__typename: 'Perpetual',
|
||||
settlementAsset: {
|
||||
id: 'asset-2',
|
||||
},
|
||||
@@ -179,14 +174,21 @@ describe('MarketSelector', () => {
|
||||
);
|
||||
|
||||
await userEvent.click(screen.getByTestId('product-Perpetual'));
|
||||
expect(screen.queryAllByTestId(/market-\d/)).toHaveLength(1);
|
||||
expect(screen.queryAllByTestId(/market-\d/)).toHaveLength(0);
|
||||
expect(screen.getByTestId('no-items')).toHaveTextContent(
|
||||
'Perpetual markets coming soon.'
|
||||
);
|
||||
|
||||
await userEvent.click(screen.getByTestId('product-Future'));
|
||||
expect(screen.queryAllByTestId(/market-\d/)).toHaveLength(3);
|
||||
expect(screen.queryAllByTestId(/market-\d/)).toHaveLength(
|
||||
activeMarkets.length
|
||||
);
|
||||
expect(screen.queryByTestId('no-items')).not.toBeInTheDocument();
|
||||
|
||||
await userEvent.click(screen.getByTestId('product-All'));
|
||||
expect(screen.queryAllByTestId(/market-\d/)).toHaveLength(4);
|
||||
expect(screen.queryAllByTestId(/market-\d/)).toHaveLength(
|
||||
activeMarkets.length
|
||||
);
|
||||
expect(screen.queryByTestId('no-items')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
@@ -218,6 +220,38 @@ describe('MarketSelector', () => {
|
||||
expect(screen.getByTestId('market-4')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('filters by asset', async () => {
|
||||
render(
|
||||
<MemoryRouter>
|
||||
<MarketSelector currentMarketId="market-0" onSelect={jest.fn()} />
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
await userEvent.click(screen.getByTestId('asset-trigger'));
|
||||
expect(screen.getAllByTestId(/asset-id/)).toHaveLength(3);
|
||||
await userEvent.click(screen.getByTestId('asset-id-asset-0'));
|
||||
expect(screen.getAllByTestId(/market-\d/)).toHaveLength(2);
|
||||
expect(screen.getByTestId('market-0')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('market-1')).toBeInTheDocument();
|
||||
|
||||
// reopen asset dropdown and add asset-1
|
||||
await userEvent.click(screen.getByTestId('asset-trigger'));
|
||||
await userEvent.click(screen.getByTestId('asset-id-asset-1'));
|
||||
|
||||
// all markets with asset-0 or asset-1 shown (no market id as market is closed)
|
||||
expect(screen.getAllByTestId(/market-\d/)).toHaveLength(3);
|
||||
expect(screen.getByTestId('market-0')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('market-1')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('market-3')).toBeInTheDocument();
|
||||
|
||||
// reopen and uncheck asset-0
|
||||
await userEvent.click(screen.getByTestId('asset-trigger'));
|
||||
await userEvent.click(screen.getByTestId('asset-id-asset-0'));
|
||||
|
||||
expect(screen.getAllByTestId(/market-\d/)).toHaveLength(1);
|
||||
expect(screen.getByTestId('market-3')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('sorts by gained', async () => {
|
||||
render(
|
||||
<MemoryRouter>
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import uniqBy from 'lodash/uniqBy';
|
||||
import {
|
||||
getAsset,
|
||||
type MarketMaybeWithDataAndCandles,
|
||||
} from '@vegaprotocol/markets';
|
||||
import { type MarketMaybeWithDataAndCandles } from '@vegaprotocol/markets';
|
||||
import {
|
||||
TradingInput,
|
||||
TinyScroll,
|
||||
@@ -79,7 +76,9 @@ export const MarketSelector = ({
|
||||
</div>
|
||||
<AssetDropdown
|
||||
assets={uniqBy(
|
||||
data?.map((d) => getAsset(d)),
|
||||
data?.map(
|
||||
(d) => d.tradableInstrument.instrument.product.settlementAsset
|
||||
),
|
||||
'id'
|
||||
)}
|
||||
checkedAssets={filter.assets}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import classNames from 'classnames';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Routes } from '../../pages/client-router';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit';
|
||||
import { Links } from '../../lib/links';
|
||||
|
||||
// Make sure these match the available __typename properties on product
|
||||
export const Product = {
|
||||
@@ -55,7 +55,7 @@ export const ProductSelector = ({
|
||||
);
|
||||
})}
|
||||
<Link
|
||||
to={Links.MARKETS()}
|
||||
to={Routes.MARKETS}
|
||||
className="flex items-center ml-auto text-sm gap-2"
|
||||
title={t('See all markets')}
|
||||
>
|
||||
|
||||
@@ -78,22 +78,22 @@ describe('useMarketSelectorList', () => {
|
||||
},
|
||||
},
|
||||
}),
|
||||
// createMarketFragment({
|
||||
// id: 'market-1',
|
||||
// tradableInstrument: {
|
||||
// instrument: {
|
||||
// product: {
|
||||
// __typename: 'Spot',
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// }),
|
||||
createMarketFragment({
|
||||
id: 'market-1',
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
product: {
|
||||
__typename: 'Spot' as 'Future', // spot isn't in schema yet
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
createMarketFragment({
|
||||
id: 'market-2',
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
product: {
|
||||
__typename: 'Perpetual',
|
||||
__typename: 'Perpetual' as 'Future', // spot isn't in schema yet
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -107,20 +107,20 @@ describe('useMarketSelectorList', () => {
|
||||
});
|
||||
const { result, rerender } = setup();
|
||||
expect(result.current.markets).toEqual([markets[0]]);
|
||||
// rerender({
|
||||
// searchTerm: '',
|
||||
// product: Product.Spot as 'Future',
|
||||
// sort: Sort.TopTraded,
|
||||
// assets: [],
|
||||
// });
|
||||
// expect(result.current.markets).toEqual([markets[1]]);
|
||||
rerender({
|
||||
searchTerm: '',
|
||||
product: Product.Spot as 'Future',
|
||||
sort: Sort.TopTraded,
|
||||
assets: [],
|
||||
});
|
||||
expect(result.current.markets).toEqual([markets[1]]);
|
||||
rerender({
|
||||
searchTerm: '',
|
||||
product: Product.Perpetual as 'Future',
|
||||
sort: Sort.TopTraded,
|
||||
assets: [],
|
||||
});
|
||||
// expect(result.current.markets).toEqual([markets[2]]);
|
||||
expect(result.current.markets).toEqual([markets[2]]);
|
||||
rerender({
|
||||
searchTerm: '',
|
||||
product: Product.All,
|
||||
@@ -130,15 +130,13 @@ describe('useMarketSelectorList', () => {
|
||||
expect(result.current.markets).toEqual(markets);
|
||||
});
|
||||
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
it.skip('filters by asset', () => {
|
||||
it('filters by asset', () => {
|
||||
const markets = [
|
||||
createMarketFragment({
|
||||
id: 'market-0',
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
settlementAsset: {
|
||||
id: 'asset-0',
|
||||
},
|
||||
@@ -151,7 +149,6 @@ describe('useMarketSelectorList', () => {
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
settlementAsset: {
|
||||
id: 'asset-0',
|
||||
},
|
||||
@@ -164,7 +161,6 @@ describe('useMarketSelectorList', () => {
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
settlementAsset: {
|
||||
id: 'asset-1',
|
||||
},
|
||||
@@ -177,7 +173,6 @@ describe('useMarketSelectorList', () => {
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
settlementAsset: {
|
||||
id: 'asset-2',
|
||||
},
|
||||
@@ -198,7 +193,6 @@ describe('useMarketSelectorList', () => {
|
||||
sort: Sort.TopTraded,
|
||||
assets: ['asset-0'],
|
||||
});
|
||||
|
||||
expect(result.current.markets).toEqual([markets[0], markets[1]]);
|
||||
|
||||
rerender({
|
||||
@@ -414,7 +408,7 @@ describe('useMarketSelectorList', () => {
|
||||
const markets = [
|
||||
createMarketFragment({
|
||||
id: 'market-0',
|
||||
// @ts-ignore actual fragment doesn't contain candles and is joined later
|
||||
// @ts-ignore actual fragment doesnt contain candles and is joined later
|
||||
candles: [
|
||||
{
|
||||
close: '100',
|
||||
@@ -426,7 +420,7 @@ describe('useMarketSelectorList', () => {
|
||||
}),
|
||||
createMarketFragment({
|
||||
id: 'market-1',
|
||||
// @ts-ignore actual fragment doesn't contain candles and is joined later
|
||||
// @ts-ignore actual fragment doesnt contain candles and is joined later
|
||||
candles: [
|
||||
{
|
||||
close: '100',
|
||||
@@ -438,7 +432,7 @@ describe('useMarketSelectorList', () => {
|
||||
}),
|
||||
createMarketFragment({
|
||||
id: 'market-2',
|
||||
// @ts-ignore actual fragment doesn't contain candles and is joined later
|
||||
// @ts-ignore actual fragment doesnt contain candles and is joined later
|
||||
candles: [
|
||||
{
|
||||
close: '100',
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import { useMemo } from 'react';
|
||||
import orderBy from 'lodash/orderBy';
|
||||
import {
|
||||
calcTradedFactor,
|
||||
getAsset,
|
||||
useMarketList,
|
||||
} from '@vegaprotocol/markets';
|
||||
import { calcTradedFactor, useMarketList } from '@vegaprotocol/markets';
|
||||
import { priceChangePercentage } from '@vegaprotocol/utils';
|
||||
import type { Filter } from '../../components/market-selector/market-selector';
|
||||
import { Sort } from './sort-dropdown';
|
||||
@@ -36,8 +32,9 @@ export const useMarketSelectorList = ({
|
||||
})
|
||||
.filter((m) => {
|
||||
if (assets.length === 0) return true;
|
||||
const asset = getAsset(m);
|
||||
return assets.includes(asset.id);
|
||||
return assets.includes(
|
||||
m.tradableInstrument.instrument.product.settlementAsset.id
|
||||
);
|
||||
})
|
||||
// filter based on search term
|
||||
.filter((m) => {
|
||||
|
||||
@@ -15,7 +15,7 @@ import * as N from '@radix-ui/react-navigation-menu';
|
||||
import * as D from '@radix-ui/react-dialog';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
|
||||
import { Links } from '../../lib/links';
|
||||
import { Links, Routes } from '../../pages/client-router';
|
||||
import classNames from 'classnames';
|
||||
import { VegaWalletMenu } from '../vega-wallet';
|
||||
import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
|
||||
@@ -142,7 +142,9 @@ const NavbarMenu = ({ onClick }: { onClick: () => void }) => {
|
||||
|
||||
// If we have a stored marketId make Trade link go to that market
|
||||
// otherwise always go to /markets/all
|
||||
const tradingPath = marketId ? Links.MARKET(marketId) : Links.MARKETS();
|
||||
const tradingPath = marketId
|
||||
? Links[Routes.MARKET](marketId)
|
||||
: Links[Routes.MARKET]('');
|
||||
|
||||
return (
|
||||
<div className="lg:flex lg:h-full gap-3">
|
||||
@@ -169,7 +171,7 @@ const NavbarMenu = ({ onClick }: { onClick: () => void }) => {
|
||||
<NavbarListDivider />
|
||||
<NavbarList>
|
||||
<NavbarItem>
|
||||
<NavbarLink to={Links.MARKETS()} onClick={onClick}>
|
||||
<NavbarLink to={Links[Routes.MARKETS]()} onClick={onClick}>
|
||||
{t('Markets')}
|
||||
</NavbarLink>
|
||||
</NavbarItem>
|
||||
@@ -179,7 +181,7 @@ const NavbarMenu = ({ onClick }: { onClick: () => void }) => {
|
||||
</NavbarLink>
|
||||
</NavbarItem>
|
||||
<NavbarItem>
|
||||
<NavbarLink to={Links.PORTFOLIO()} onClick={onClick}>
|
||||
<NavbarLink to={Links[Routes.PORTFOLIO]()} onClick={onClick}>
|
||||
{t('Portfolio')}
|
||||
</NavbarLink>
|
||||
</NavbarItem>
|
||||
@@ -207,7 +209,7 @@ const NavbarMenu = ({ onClick }: { onClick: () => void }) => {
|
||||
</NavbarSubItem>
|
||||
)}
|
||||
<NavbarSubItem>
|
||||
<NavbarLink to={Links.DISCLAIMER()} onClick={onClick}>
|
||||
<NavbarLink to={Links[Routes.DISCLAIMER]()} onClick={onClick}>
|
||||
{t('Disclaimer')}
|
||||
</NavbarLink>
|
||||
</NavbarSubItem>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user