Compare commits

..
Author SHA1 Message Date
asiaznik ee57d2f1c0 fix(trading): missing wallet connect button 2023-10-03 10:49:43 +02:00
Radosław Szpiech 8b249e1917 chore(ci): fix some minor issues in workflows (#4953) 2023-10-02 16:12:24 +02:00
Radosław Szpiech abb771e2f9 chore(ci): add conditions to run e2e tests (#4946) 2023-10-02 14:29:59 +02:00
Edd acf1d50d0f chore(explorer): ignore errors on oracle page (#4944) 2023-09-29 17:29:16 +01:00
Radosław Szpiech 30da1663eb chore(ci): add main develop merge condition to runner (#4941) 2023-09-29 17:36:18 +02:00
Radosław Szpiech 79cbe62774 chore(ci): add mainnet compatible runner to release mainnet branch push actions (#4939) 2023-09-29 11:00:20 -04:00
Maciek 2f0be0bf34 chore(trading): 4774 put connect dialog inside onboarding dialog - main branch (#4920) 2023-09-29 15:07:18 +02:00
Radosław Szpiech 5b5802104e chore(ci): trigger lint-pr on repoened and sync (#4937) 2023-09-29 15:03:58 +02:00
Maciek ff2e2574f6 chore(trading): add handle of autosizing selected columns - main branch (#4888) 2023-09-28 15:14:32 -04:00
Radosław Szpiech 478cc9e753 chore(ci): publish main image in dockerhub (#4930) 2023-09-28 17:38:00 +02:00
Radosław Szpiech e2a72cb395 chore(ci): separate lint pr (main) (#4917) 2023-09-28 14:01:36 +02:00
Radosław Szpiech 7fe269fad6 chore(ci): fix node version (main) (#4911) 2023-09-28 11:26:15 +02:00
Radosław Szpiech b761023069 chore(ci): add logic for choosing correct runner for cypress tests depending on base branch (#4918) 2023-09-28 11:25:44 +02:00
Radosław Szpiech 7ac3a68ac9 chore(trading): add possibility to manualy trigger console-test (#4899) 2023-09-27 15:18:32 +02:00
Radosław Szpiech 2640ccb20a chore(trading): change runner for mainnet compatible vega version (#4907) 2023-09-27 14:42:12 +02:00
Maciek d78de10855 chore(trading): remove underlines on tooltips (#4884) 2023-09-26 13:45:33 -04:00
Matthew Russell bb402c02f6 chore(trading): make volume bars color match candle color (#4881) 2023-09-26 12:08:12 -04:00
Bartłomiej Głownia 8a9b1c7874 feat(deal-ticket): amend fee estimates for postOnly orders and when market is in auction (#4843) 2023-09-26 11:57:47 -04:00
Matthew Russell a7e8b0eb01 fix(market-depth): ensure scroll bar doesn't show on orderbook (#4882) 2023-09-26 11:54:42 -04:00
Bartłomiej Głownia 89b3c06107 feat(deal-ticket): show worst case instead of ranges in estimated values (#4870) 2023-09-26 11:53:45 -04:00
Radosław Szpiech cd5c73d3fd chore(trading): temporary disable console-test to unblock CI queue (#4885) 2023-09-26 10:45:27 +01:00
Joe Tsang b3a5ab022d chore(ci): update genesis file (#4887) 2023-09-26 10:44:55 +01:00
Mikołaj Młodzikowski 496d1f5c68 feat(ci): parse if there are any changes 2023-09-25 18:10:01 -04:00
Mikołaj Młodzikowski e914e7bb70 fix(ci): provide proper ipfs process 2023-09-25 18:09:31 -04:00
Matthew Russell 71a36c2382 fix(trading): remove upgrade banner [main] (#4877) 2023-09-25 17:27:01 -04:00
Matthew Russell 1c6a307bcd fix(wallet): reduce time to check for wallet running [main] (#4876) 2023-09-25 17:26:40 -04:00
Matthew Russell ef4a740b91 fix(trading): allotment breaking [main] (#4875) 2023-09-25 17:26:06 -04:00
Sam Keen 2d4be5fcb3 fix(governance): mainnet rewards query looping (#4865) 2023-09-25 09:59:38 +00:00
m.rayandMatthew Russell 835f2b793f chore(trading): remove static assets console coming from vega.xyz (#4825)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-09-19 23:54:07 -07:00
Matthew Russell d50b988b4a Merge branch 'release/mainnet-trading' of github.com:vegaprotocol/frontend-monorepo into release/mainnet-trading 2023-09-18 09:03:44 -07:00
Madalina Raicu a6aec899c8 chore: update tag metamask snaps to true 2023-09-18 15:08:46 +01:00
217 changed files with 2261 additions and 4256 deletions
+33 -19
View File
@@ -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:
+43 -28
View File
@@ -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
+24 -1
View File
@@ -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
+11 -11
View File
@@ -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
+12 -6
View File
@@ -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
}
}
}
}
}
@@ -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
View File
@@ -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',
@@ -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 {
@@ -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
@@ -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,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 {
@@ -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', () => {
-1
View File
@@ -122,7 +122,6 @@ const mockTradingPage = (
tradableInstrument: {
instrument: {
product: {
__typename: 'Future',
dataSourceSpecForSettlementData: {
data: {
sourceType: {
+6 -5
View File
@@ -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
-4
View File
@@ -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);
});
});
+52 -7
View File
@@ -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>
);
};
+3 -1
View File
@@ -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;
+4 -4
View File
@@ -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]);
+3 -1
View File
@@ -1 +1,3 @@
export { Home } from './home';
import { Home } from './home';
export default Home;
+3 -1
View File
@@ -1 +1,3 @@
export { Liquidity } from './liquidity';
import { Liquidity } from './liquidity';
export default Liquidity;
+3 -1
View File
@@ -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
+23 -13
View File
@@ -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',
+20 -33
View File
@@ -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}
/>
),
},
+3 -1
View File
@@ -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);
}
}}
+3 -1
View File
@@ -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
View File
@@ -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';
+1 -1
View File
@@ -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) => {
+7 -5
View File
@@ -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