Feat/625 market info more details - open interest, liquidity info, market and instrument ids, price and settlement asset in the header - Part 1 (#823)

* fix: #625 update the info market query with new fields

* fix: #625 generate code for info market query and fix pagination being removed from globalTypes

* fix:  add id and filter no trading auctions

* fix: add id and format labels

* fix: add name and code to instrument

* fix: add name and code to instrument

* fix: format check

* feat: add settlement asset and mark price

* feat: add liquidity parameters

* fix: remove settings.json

* fix: price instead of mark price label

* fix: add instrument metadata

* fix: remove unused set lodash

* fix: move Liquidity monitoring parameters after price monitoring

* fix: rename instrument metadata to metadata

* fix: settlement asset could be undefined

* Merge branch 'master' of github.com:vegaprotocol/frontend-monorepo into feat/625-market-info-more-details-open-interest-liquidity-ids-risk

* fix: format market id and trading mode label in key details

* fix: display settlement asset if defined

* fix: format trade-grid.tsx
This commit is contained in:
m.ray 2022-07-21 11:57:30 +02:00 committed by GitHub
parent f7c869674a
commit 8ce51dddbc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 317 additions and 33 deletions

View File

@ -41,6 +41,16 @@ const MARKET_QUERY = gql`
metadata {
tags
}
product {
... on Future {
quoteName
settlementAsset {
id
symbol
name
}
}
}
}
}
marketTimestamps {

View File

@ -61,6 +61,34 @@ export interface Market_market_tradableInstrument_instrument_metadata {
tags: string[] | null;
}
export interface Market_market_tradableInstrument_instrument_product_settlementAsset {
__typename: "Asset";
/**
* The id of the asset
*/
id: string;
/**
* The symbol of the asset (e.g: GBP)
*/
symbol: string;
/**
* The full name of the asset (e.g: Great British Pound)
*/
name: string;
}
export interface Market_market_tradableInstrument_instrument_product {
__typename: "Future";
/**
* String representing the quote (e.g. BTCUSD -> USD is quote)
*/
quoteName: string;
/**
* The name of the asset (string)
*/
settlementAsset: Market_market_tradableInstrument_instrument_product_settlementAsset;
}
export interface Market_market_tradableInstrument_instrument {
__typename: "Instrument";
/**
@ -75,6 +103,10 @@ export interface Market_market_tradableInstrument_instrument {
* Metadata for this instrument
*/
metadata: Market_market_tradableInstrument_instrument_metadata;
/**
* A reference to or instance of a fully specified product, including all required product parameters for that product (Product union)
*/
product: Market_market_tradableInstrument_instrument_product;
}
export interface Market_market_tradableInstrument {

View File

@ -85,14 +85,14 @@ export const TradeMarketHeader = ({
className="flex flex-auto items-start gap-64 overflow-x-auto whitespace-nowrap"
>
<div className={headerItemClassName}>
<span className={itemClassName}>Change (24h)</span>
<span className={itemClassName}>{t('Change (24h)')}</span>
<PriceCellChange
candles={candlesClose}
decimalPlaces={market.decimalPlaces}
/>
</div>
<div className={headerItemClassName}>
<span className={itemClassName}>Volume</span>
<span className={itemClassName}>{t('Volume')}</span>
<span data-testid="trading-volume" className={itemValueClassName}>
{market.data && market.data.indicativeVolume !== '0'
? addDecimalsFormatNumber(
@ -103,7 +103,7 @@ export const TradeMarketHeader = ({
</span>
</div>
<div className={headerItemClassName}>
<span className={itemClassName}>Trading mode</span>
<span className={itemClassName}>{t('Trading mode')}</span>
<span data-testid="trading-mode" className={itemValueClassName}>
{market.tradingMode === MarketTradingMode.MonitoringAuction &&
market.data?.trigger &&
@ -114,6 +114,29 @@ export const TradeMarketHeader = ({
: formatLabel(market.tradingMode)}
</span>
</div>
<div className={headerItemClassName}>
<span className={itemClassName}>{t('Price')}</span>
<span data-testid="mark-price" className={itemValueClassName}>
{market.data && market.data.markPrice !== '0'
? addDecimalsFormatNumber(
market.data.markPrice,
market.decimalPlaces
)
: '-'}
</span>
</div>
{market.tradableInstrument.instrument.product?.settlementAsset
?.symbol && (
<div className={headerItemClassName}>
<span className={itemClassName}>{t('Settlement asset')}</span>
<span data-testid="trading-mode" className={itemValueClassName}>
{
market.tradableInstrument.instrument.product?.settlementAsset
?.symbol
}
</span>
</div>
)}
</div>
</div>
</header>
@ -159,7 +182,7 @@ export const TradeGrid = ({ market }: TradeGridProps) => {
<TradeGridChild className="h-full px-4 bg-black-10 dark:bg-black-70">
<Tabs>
<Tab id="ticket" name={t('Ticket')}>
<TradingViews.Ticket marketId={market.id}/>
<TradingViews.Ticket marketId={market.id} />
</Tab>
<Tab id="info" name={t('Info')}>
<TradingViews.Info marketId={market.id} />

View File

@ -3,12 +3,36 @@
// @generated
// This file was automatically generated and should not be edited.
import { MarketState, MarketTradingMode } from "@vegaprotocol/types";
import { MarketState, MarketTradingMode, AccountType } from "@vegaprotocol/types";
// ====================================================
// GraphQL query operation: MarketInfoQuery
// ====================================================
export interface MarketInfoQuery_market_accounts_asset {
__typename: "Asset";
/**
* The id of the asset
*/
id: string;
}
export interface MarketInfoQuery_market_accounts {
__typename: "Account";
/**
* Account type (General, Margin, etc)
*/
type: AccountType;
/**
* Asset, the 'currency'
*/
asset: MarketInfoQuery_market_accounts_asset;
/**
* Balance as string - current account balance (approx. as balances can be updated several times per second)
*/
balance: string;
}
export interface MarketInfoQuery_market_fees_factors {
__typename: "FeeFactors";
/**
@ -125,6 +149,42 @@ export interface MarketInfoQuery_market_data {
* the aggregated volume being offered at the best static offer price, excluding pegged orders.
*/
bestStaticOfferVolume: string;
/**
* the sum of the size of all positions greater than 0.
*/
openInterest: string;
}
export interface MarketInfoQuery_market_liquidityMonitoringParameters_targetStakeParameters {
__typename: "TargetStakeParameters";
/**
* Specifies length of time window expressed in seconds for target stake calculation
*/
timeWindow: number;
/**
* Specifies scaling factors used in target stake calculation
*/
scalingFactor: number;
}
export interface MarketInfoQuery_market_liquidityMonitoringParameters {
__typename: "LiquidityMonitoringParameters";
/**
* Specifies the triggering ratio for entering liquidity auction
*/
triggeringRatio: number;
/**
* Specifies parameters related to target stake calculation
*/
targetStakeParameters: MarketInfoQuery_market_liquidityMonitoringParameters_targetStakeParameters;
}
export interface MarketInfoQuery_market_tradableInstrument_instrument_metadata {
__typename: "InstrumentMetadata";
/**
* An arbitrary list of tags to associated to associate to the Instrument (string list)
*/
tags: string[] | null;
}
export interface MarketInfoQuery_market_tradableInstrument_instrument_product_settlementAsset {
@ -143,6 +203,28 @@ export interface MarketInfoQuery_market_tradableInstrument_instrument_product_se
name: string;
}
export interface MarketInfoQuery_market_tradableInstrument_instrument_product_oracleSpecForSettlementPrice {
__typename: "OracleSpec";
/**
* id is a hash generated from the OracleSpec data.
*/
id: string;
}
export interface MarketInfoQuery_market_tradableInstrument_instrument_product_oracleSpecForTradingTermination {
__typename: "OracleSpec";
/**
* id is a hash generated from the OracleSpec data.
*/
id: string;
}
export interface MarketInfoQuery_market_tradableInstrument_instrument_product_oracleSpecBinding {
__typename: "OracleSpecToFutureBinding";
settlementPriceProperty: string;
tradingTerminationProperty: string;
}
export interface MarketInfoQuery_market_tradableInstrument_instrument_product {
__typename: "Future";
/**
@ -153,10 +235,38 @@ export interface MarketInfoQuery_market_tradableInstrument_instrument_product {
* The name of the asset (string)
*/
settlementAsset: MarketInfoQuery_market_tradableInstrument_instrument_product_settlementAsset;
/**
* The oracle spec describing the oracle data of interest for settlement price.
*/
oracleSpecForSettlementPrice: MarketInfoQuery_market_tradableInstrument_instrument_product_oracleSpecForSettlementPrice;
/**
* The oracle spec describing the oracle data of interest for trading termination.
*/
oracleSpecForTradingTermination: MarketInfoQuery_market_tradableInstrument_instrument_product_oracleSpecForTradingTermination;
/**
* The binding between the oracle spec and the settlement price
*/
oracleSpecBinding: MarketInfoQuery_market_tradableInstrument_instrument_product_oracleSpecBinding;
}
export interface MarketInfoQuery_market_tradableInstrument_instrument {
__typename: "Instrument";
/**
* Uniquely identify an instrument across all instruments available on Vega (string)
*/
id: string;
/**
* Full and fairly descriptive name for the instrument
*/
name: string;
/**
* A short non necessarily unique code used to easily describe the instrument (e.g: FX:BTCUSD/DEC18) (string)
*/
code: string;
/**
* Metadata for this instrument
*/
metadata: MarketInfoQuery_market_tradableInstrument_instrument_metadata;
/**
* A reference to or instance of a fully specified product, including all required product parameters for that product (Product union)
*/
@ -286,6 +396,10 @@ export interface MarketInfoQuery_market {
* Current mode of execution of the market
*/
tradingMode: MarketTradingMode;
/**
* Get account for a party or market
*/
accounts: MarketInfoQuery_market_accounts[] | null;
/**
* Fees related data
*/
@ -302,6 +416,10 @@ export interface MarketInfoQuery_market {
* marketData for the given market
*/
data: MarketInfoQuery_market_data | null;
/**
* Liquidity monitoring parameters for the market
*/
liquidityMonitoringParameters: MarketInfoQuery_market_liquidityMonitoringParameters;
/**
* An instance of or reference to a tradable instrument.
*/

View File

@ -1,6 +1,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import {
addDecimalsFormatNumber,
formatLabel,
formatNumber,
formatNumberPercentage,
t,
@ -15,10 +16,7 @@ import {
import startCase from 'lodash/startCase';
import pick from 'lodash/pick';
import omit from 'lodash/omit';
import type {
MarketInfoQuery,
MarketInfoQuery_market,
} from './__generated__/MarketInfoQuery';
import type { MarketInfoQuery, MarketInfoQuery_market } from './__generated__';
import BigNumber from 'bignumber.js';
import { gql, useQuery } from '@apollo/client';
@ -31,6 +29,13 @@ const MARKET_INFO_QUERY = gql`
positionDecimalPlaces
state
tradingMode
accounts {
type
asset {
id
}
balance
}
fees {
factors {
makerFee
@ -53,6 +58,13 @@ const MARKET_INFO_QUERY = gql`
short
long
}
accounts {
type
asset {
id
}
balance
}
data {
market {
id
@ -64,9 +76,23 @@ const MARKET_INFO_QUERY = gql`
bestStaticBidVolume
bestStaticOfferVolume
indicativeVolume
openInterest
}
liquidityMonitoringParameters {
triggeringRatio
targetStakeParameters {
timeWindow
scalingFactor
}
}
tradableInstrument {
instrument {
id
name
code
metadata {
tags
}
product {
... on Future {
quoteName
@ -75,6 +101,16 @@ const MARKET_INFO_QUERY = gql`
symbol
name
}
oracleSpecForSettlementPrice {
id
}
oracleSpecForTradingTermination {
id
}
oracleSpecBinding {
settlementPriceProperty
tradingTerminationProperty
}
}
}
}
@ -159,19 +195,28 @@ export const Info = ({ market }: InfoProps) => {
),
},
];
const keyDetails = pick(
market,
'name',
'decimalPlaces',
'positionDecimalPlaces',
'tradingMode',
'state',
'id' as 'marketId'
);
const marketSpecPanels = [
{
title: t('Key details'),
content: (
<MarketInfoTable
data={pick(
market,
'name',
'decimalPlaces',
'positionDecimalPlaces',
'tradingMode',
'state'
)}
data={{
...keyDetails,
marketId: keyDetails.id,
id: undefined,
tradingMode:
keyDetails.tradingMode && formatLabel(keyDetails.tradingMode),
}}
/>
),
},
@ -180,8 +225,28 @@ export const Info = ({ market }: InfoProps) => {
content: (
<MarketInfoTable
data={{
product: market.tradableInstrument.instrument.product,
...market.tradableInstrument.instrument.product.settlementAsset,
marketName: market.tradableInstrument.instrument.name,
code: market.tradableInstrument.instrument.code,
productType:
market.tradableInstrument.instrument.product.__typename,
...market.tradableInstrument.instrument.product,
...(market.tradableInstrument.instrument.product?.settlementAsset ??
{}),
}}
/>
),
},
{
title: t('Metadata'),
content: (
<MarketInfoTable
data={{
...market.tradableInstrument.instrument.metadata.tags
?.map((tag) => {
const [key, value] = tag.split(':');
return { [key]: value };
})
.reduce((acc, curr) => ({ ...acc, ...curr }), {}),
}}
/>
),
@ -212,6 +277,18 @@ export const Info = ({ market }: InfoProps) => {
content: <MarketInfoTable data={trigger} />,
})
),
{
title: t('Liquidity monitoring parameters'),
content: (
<MarketInfoTable
data={{
triggeringRatio:
market.liquidityMonitoringParameters.triggeringRatio,
...market.liquidityMonitoringParameters.targetStakeParameters,
}}
/>
),
},
];
return (
@ -261,7 +338,7 @@ const Row = ({
? decimalPlaces
? addDecimalsFormatNumber(value, decimalPlaces)
: asPercentage
? formatNumberPercentage(new BigNumber(value))
? formatNumberPercentage(new BigNumber(value * 100))
: formatNumber(Number(value))
: value}
</KeyValueTableRow>
@ -283,7 +360,7 @@ export const MarketInfoTable = ({
decimalPlaces,
asPercentage,
unformatted,
omits = ['id', '__typename'],
omits = ['__typename'],
}: MarketInfoTableProps) => {
return (
<KeyValueTable muted={true}>

View File

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { Interval, MarketState } from "@vegaprotocol/types";
import { Interval, MarketState, MarketTradingMode } from "@vegaprotocol/types";
// ====================================================
// GraphQL query operation: MarketList
@ -112,6 +112,10 @@ export interface MarketList_markets {
* Current state of the market
*/
state: MarketState;
/**
* Current mode of execution of the market
*/
tradingMode: MarketTradingMode;
/**
* marketData for the given market
*/

View File

@ -54,6 +54,7 @@ export const MARKET_LIST_QUERY = gql`
id
decimalPlaces
state
tradingMode
data {
market {
id

View File

@ -1,4 +1,4 @@
import { MarketState } from '@vegaprotocol/types';
import { MarketState, MarketTradingMode } from '@vegaprotocol/types';
import orderBy from 'lodash/orderBy';
import type {
MarketList,
@ -13,7 +13,11 @@ export const lastPrice = ({ candles }: MarketList_markets) =>
export const mapDataToMarketList = ({ markets }: MarketList) =>
orderBy(
markets
?.filter((m) => m.state !== MarketState.Rejected)
?.filter(
(m) =>
m.state !== MarketState.Rejected &&
m.tradingMode !== MarketTradingMode.NoTrading
)
.map((m) => {
return {
id: m.id,

View File

@ -1,5 +1,9 @@
import { act, render, screen } from '@testing-library/react';
import { addDecimal, getDateTimeFormat } from '@vegaprotocol/react-helpers';
import {
addDecimal,
formatLabel,
getDateTimeFormat,
} from '@vegaprotocol/react-helpers';
import type { Orders_party_orders } from '../__generated__/Orders';
import { OrderStatus, OrderRejectionReason } from '@vegaprotocol/types';
import { OrderListTable } from './order-list';
@ -118,7 +122,7 @@ describe('OrderListTable', () => {
});
const cells = screen.getAllByRole('gridcell');
expect(cells[3]).toHaveTextContent(
`${rejectedOrder.status}: ${rejectedOrder.rejectionReason}`
`${rejectedOrder.status}: ${formatLabel(rejectedOrder.rejectionReason)}`
);
});
});

View File

@ -1,6 +1,11 @@
import { OrderTimeInForce, OrderStatus, Side } from '@vegaprotocol/types';
import type { Orders_party_orders } from '../__generated__/Orders';
import { addDecimal, getDateTimeFormat, t } from '@vegaprotocol/react-helpers';
import {
addDecimal,
formatLabel,
getDateTimeFormat,
t,
} from '@vegaprotocol/react-helpers';
import { AgGridDynamic as AgGrid, Button } from '@vegaprotocol/ui-toolkit';
import type {
ICellRendererParams,
@ -139,7 +144,7 @@ export const OrderListTable = forwardRef<AgGridReact, OrderListTableProps>(
field="status"
valueFormatter={({ value, data }: ValueFormatterParams) => {
if (value === OrderStatus.Rejected) {
return `${value}: ${data.rejectionReason}`;
return `${value}: ${formatLabel(data.rejectionReason)}`;
}
return value;

1
libs/types/src/__generated__/index.ts generated Normal file
View File

@ -0,0 +1 @@
export * from './globalTypes';

View File

@ -1,3 +1,3 @@
export * from './__generated__/globalTypes';
export * from './__generated__';
export * from './candle';
export * from './pagination';

View File

@ -4,7 +4,11 @@ import type { VegaTxState } from '../use-vega-transaction';
import { VegaTxStatus } from '../use-vega-transaction';
import { Icon, Loader } from '@vegaprotocol/ui-toolkit';
import type { ReactNode } from 'react';
import { addDecimalsFormatNumber, t } from '@vegaprotocol/react-helpers';
import {
addDecimalsFormatNumber,
formatLabel,
t,
} from '@vegaprotocol/react-helpers';
import { useEnvironment } from '@vegaprotocol/environment';
import { OrderType } from '@vegaprotocol/types';
import type { Order } from '../wallet-types';
@ -169,7 +173,8 @@ export const VegaDialog = ({
icon={<Icon name="warning-sign" size={20} />}
>
<p data-testid="error-reason">
{t(`Reason: ${finalizedOrder.rejectionReason}`)}
{finalizedOrder.rejectionReason &&
t(`Reason: ${formatLabel(finalizedOrder.rejectionReason)}`)}
</p>
</OrderDialogWrapper>
);