Feat/815 auction conditions (#955)
* feat: add tooltip for market trading modes * fix: format * fix: remove log * fix: typo
This commit is contained in:
parent
2e644de413
commit
1c9cd3aa2a
1
apps/trading/components/trading-mode-tooltip/index.tsx
Normal file
1
apps/trading/components/trading-mode-tooltip/index.tsx
Normal file
@ -0,0 +1 @@
|
||||
export * from './trading-mode-tooltip';
|
@ -0,0 +1,201 @@
|
||||
import type { ReactNode } from 'react';
|
||||
import {
|
||||
t,
|
||||
getDateTimeFormat,
|
||||
addDecimalsFormatNumber,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import { Link } from '@vegaprotocol/ui-toolkit';
|
||||
import { MarketTradingMode, AuctionTrigger } from '@vegaprotocol/types';
|
||||
import type { Market_market } from '../../pages/markets/__generated__/Market';
|
||||
|
||||
type MarketDataGridProps = {
|
||||
grid: {
|
||||
label: string;
|
||||
value?: ReactNode;
|
||||
isEstimate?: boolean;
|
||||
}[];
|
||||
};
|
||||
|
||||
const MarketDataGrid = ({ grid }: MarketDataGridProps) => {
|
||||
return (
|
||||
<>
|
||||
{grid.map(
|
||||
({ label, value, isEstimate }, index) =>
|
||||
value && (
|
||||
<div key={index} className="grid grid-cols-2">
|
||||
<span>{label}</span>
|
||||
<span>
|
||||
{isEstimate && <span className="ml-[-0.625em]">{'~'}</span>}
|
||||
{value}
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const formatStake = (value: string, market: Market_market) => {
|
||||
const formattedValue = addDecimalsFormatNumber(
|
||||
value,
|
||||
market.positionDecimalPlaces
|
||||
);
|
||||
const asset =
|
||||
market.tradableInstrument.instrument.product.settlementAsset.symbol;
|
||||
return `${formattedValue} ${asset}`;
|
||||
};
|
||||
|
||||
const compileGridData = (market: Market_market) => {
|
||||
const grid: MarketDataGridProps['grid'] = [];
|
||||
const isLiquidityMonitoringAuction =
|
||||
market.tradingMode === MarketTradingMode.MonitoringAuction &&
|
||||
market.data?.trigger === AuctionTrigger.Liquidity;
|
||||
|
||||
if (!market.data) return grid;
|
||||
|
||||
if (market.data?.auctionStart) {
|
||||
grid.push({
|
||||
label: t('Auction start'),
|
||||
value: getDateTimeFormat().format(new Date(market.data.auctionStart)),
|
||||
});
|
||||
}
|
||||
|
||||
if (market.data?.auctionEnd) {
|
||||
grid.push({
|
||||
label: isLiquidityMonitoringAuction
|
||||
? t('Est auction end')
|
||||
: t('Auction end'),
|
||||
value: getDateTimeFormat().format(new Date(market.data.auctionEnd)),
|
||||
isEstimate: isLiquidityMonitoringAuction ? true : false,
|
||||
});
|
||||
}
|
||||
|
||||
if (isLiquidityMonitoringAuction && market.data?.targetStake) {
|
||||
grid.push({
|
||||
label: t('Target liquidity'),
|
||||
value: formatStake(market.data.targetStake, market),
|
||||
});
|
||||
}
|
||||
|
||||
if (isLiquidityMonitoringAuction && market.data?.suppliedStake) {
|
||||
grid.push({
|
||||
label: t('Current liquidity'),
|
||||
// @TODO: link this to liquidity view when https://github.com/vegaprotocol/frontend-monorepo/issues/491 is done
|
||||
value: formatStake(market.data.suppliedStake, market),
|
||||
});
|
||||
}
|
||||
|
||||
if (market.data?.indicativePrice) {
|
||||
grid.push({
|
||||
label: t('Est uncrossing price'),
|
||||
value: addDecimalsFormatNumber(
|
||||
market.data.indicativePrice,
|
||||
market.positionDecimalPlaces
|
||||
),
|
||||
isEstimate: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (market.data?.indicativeVolume) {
|
||||
grid.push({
|
||||
label: t('Est uncrossing vol'),
|
||||
value: addDecimalsFormatNumber(
|
||||
market.data.indicativeVolume,
|
||||
market.positionDecimalPlaces
|
||||
),
|
||||
isEstimate: true,
|
||||
});
|
||||
}
|
||||
|
||||
return grid;
|
||||
};
|
||||
|
||||
type TradingModeTooltipProps = {
|
||||
market: Market_market;
|
||||
};
|
||||
|
||||
export const TradingModeTooltip = ({ market }: TradingModeTooltipProps) => {
|
||||
switch (market.tradingMode) {
|
||||
case MarketTradingMode.Continuous: {
|
||||
return (
|
||||
<>
|
||||
{t(
|
||||
'This is the standard trading mode where trades are executed whenever orders are received.'
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
case MarketTradingMode.OpeningAuction: {
|
||||
return (
|
||||
<>
|
||||
<p className="mb-16">
|
||||
<span>
|
||||
{t(
|
||||
'This new market is in an opening auction to determine a fair mid-price before starting continuous trading.'
|
||||
)}
|
||||
</span>{' '}
|
||||
<Link
|
||||
href="https://docs.fairground.vega.xyz/docs/trading-questions/#auctions-what-happens-in-an-opening-auction"
|
||||
target="_blank"
|
||||
>
|
||||
{t('Find out more')}
|
||||
</Link>
|
||||
</p>
|
||||
<MarketDataGrid grid={compileGridData(market)} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
case MarketTradingMode.MonitoringAuction: {
|
||||
switch (market.data?.trigger) {
|
||||
case AuctionTrigger.Liquidity: {
|
||||
return (
|
||||
<>
|
||||
<p className="mb-16">
|
||||
<span>
|
||||
{t(
|
||||
'This market is in auction until it reaches sufficient liquidity.'
|
||||
)}
|
||||
</span>{' '}
|
||||
<Link
|
||||
href="https://docs.fairground.vega.xyz/docs/trading-questions/#auctions-what-is-a-liquidity-monitoring-auction"
|
||||
target="_blank"
|
||||
>
|
||||
{t('Find out more')}
|
||||
</Link>
|
||||
</p>
|
||||
<MarketDataGrid grid={compileGridData(market)} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
case AuctionTrigger.Price: {
|
||||
return (
|
||||
<>
|
||||
<p className="mb-16">
|
||||
<span>
|
||||
{t('This market is in auction due to high price volatility.')}
|
||||
</span>{' '}
|
||||
<Link
|
||||
href="https://docs.fairground.vega.xyz/docs/trading-questions/#auctions-what-is-a-price-monitoring-auction"
|
||||
target="_blank"
|
||||
>
|
||||
{t('Find out more')}
|
||||
</Link>
|
||||
</p>
|
||||
<MarketDataGrid grid={compileGridData(market)} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
default: {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
case MarketTradingMode.NoTrading: {
|
||||
return <>{t('No trading enabled for this market.')}</>;
|
||||
}
|
||||
case MarketTradingMode.BatchAuction:
|
||||
default: {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
@ -25,13 +25,17 @@ const MARKET_QUERY = gql`
|
||||
market {
|
||||
id
|
||||
}
|
||||
auctionStart
|
||||
auctionEnd
|
||||
markPrice
|
||||
indicativeVolume
|
||||
indicativePrice
|
||||
suppliedStake
|
||||
targetStake
|
||||
bestBidVolume
|
||||
bestOfferVolume
|
||||
bestStaticBidVolume
|
||||
bestStaticOfferVolume
|
||||
indicativeVolume
|
||||
trigger
|
||||
}
|
||||
tradableInstrument {
|
||||
|
20
apps/trading/pages/markets/__generated__/Market.ts
generated
20
apps/trading/pages/markets/__generated__/Market.ts
generated
@ -23,6 +23,14 @@ export interface Market_market_data {
|
||||
* market id of the associated mark price
|
||||
*/
|
||||
market: Market_market_data_market;
|
||||
/**
|
||||
* RFC3339Nano time at which the next auction will start (null if none is scheduled)
|
||||
*/
|
||||
auctionStart: string | null;
|
||||
/**
|
||||
* RFC3339Nano time at which the auction will stop (null if not in auction mode)
|
||||
*/
|
||||
auctionEnd: string | null;
|
||||
/**
|
||||
* the mark price (actually an unsigned int)
|
||||
*/
|
||||
@ -31,6 +39,18 @@ export interface Market_market_data {
|
||||
* indicative volume if the auction ended now, 0 if not in auction mode
|
||||
*/
|
||||
indicativeVolume: string;
|
||||
/**
|
||||
* indicative price if the auction ended now, 0 if not in auction mode
|
||||
*/
|
||||
indicativePrice: string;
|
||||
/**
|
||||
* the supplied stake for the market
|
||||
*/
|
||||
suppliedStake: string | null;
|
||||
/**
|
||||
* the amount of stake targeted for this market
|
||||
*/
|
||||
targetStake: string | null;
|
||||
/**
|
||||
* the aggregated volume being bid at the best bid price.
|
||||
*/
|
||||
|
@ -25,12 +25,14 @@ import {
|
||||
Tab,
|
||||
Tabs,
|
||||
PriceCellChange,
|
||||
Tooltip,
|
||||
ResizablePanel,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import type { CandleClose } from '@vegaprotocol/types';
|
||||
import { AuctionTrigger } from '@vegaprotocol/types';
|
||||
import { MarketTradingMode } from '@vegaprotocol/types';
|
||||
import { Allotment, LayoutPriority } from 'allotment';
|
||||
import { TradingModeTooltip } from '../../components/trading-mode-tooltip';
|
||||
|
||||
const TradingViews = {
|
||||
Candles: CandlesChartContainer,
|
||||
@ -102,18 +104,23 @@ export const TradeMarketHeader = ({
|
||||
: '-'}
|
||||
</span>
|
||||
</div>
|
||||
<div className={headerItemClassName}>
|
||||
<span className={itemClassName}>{t('Trading mode')}</span>
|
||||
<span data-testid="trading-mode" className={itemValueClassName}>
|
||||
{market.tradingMode === MarketTradingMode.MonitoringAuction &&
|
||||
market.data?.trigger &&
|
||||
market.data.trigger !== AuctionTrigger.Unspecified
|
||||
? `${formatLabel(
|
||||
market.tradingMode
|
||||
)} - ${market.data?.trigger.toLowerCase()}`
|
||||
: formatLabel(market.tradingMode)}
|
||||
</span>
|
||||
</div>
|
||||
<Tooltip
|
||||
align="start"
|
||||
description={<TradingModeTooltip market={market} />}
|
||||
>
|
||||
<div className={headerItemClassName}>
|
||||
<span className={itemClassName}>{t('Trading mode')}</span>
|
||||
<span data-testid="trading-mode" className={itemValueClassName}>
|
||||
{market.tradingMode === MarketTradingMode.MonitoringAuction &&
|
||||
market.data?.trigger &&
|
||||
market.data.trigger !== AuctionTrigger.Unspecified
|
||||
? `${formatLabel(
|
||||
market.tradingMode
|
||||
)} - ${market.data?.trigger.toLowerCase()}`
|
||||
: formatLabel(market.tradingMode)}
|
||||
</span>
|
||||
</div>
|
||||
</Tooltip>
|
||||
<div className={headerItemClassName}>
|
||||
<span className={itemClassName}>{t('Price')}</span>
|
||||
<span data-testid="mark-price" className={itemValueClassName}>
|
||||
|
@ -1,3 +1,4 @@
|
||||
import type { ReactNode } from 'react';
|
||||
import React from 'react';
|
||||
import {
|
||||
Provider,
|
||||
@ -9,7 +10,7 @@ import {
|
||||
|
||||
export interface TooltipProps {
|
||||
children: React.ReactElement;
|
||||
description?: string;
|
||||
description?: string | ReactNode;
|
||||
open?: boolean;
|
||||
align?: 'start' | 'center' | 'end';
|
||||
}
|
||||
@ -20,19 +21,19 @@ export const Tooltip = ({ children, description, open, align }: TooltipProps) =>
|
||||
<Provider delayDuration={200} skipDelayDuration={100}>
|
||||
<Root open={open}>
|
||||
<Trigger asChild>{children}</Trigger>
|
||||
<Content align={align} alignOffset={5}>
|
||||
<Content align={align} alignOffset={8}>
|
||||
<div className="relative z-0 p-8 bg-black-50 border border-black-60 text-white rounded-sm max-w-sm">
|
||||
{description}
|
||||
</div>
|
||||
<Arrow
|
||||
width={10}
|
||||
height={5}
|
||||
className="z-[1] fill-black-60 dark:fill-white-60 z-0 translate-x-[1px] translate-y-[-1px]"
|
||||
className="z-[1] mx-8 fill-black-60 dark:fill-white-60 z-0 translate-x-[1px] translate-y-[-1px]"
|
||||
/>
|
||||
<Arrow
|
||||
width={8}
|
||||
height={4}
|
||||
className="z-[1] translate-y-[-1px] fill-black-50"
|
||||
className="z-[1] mx-8 translate-y-[-1px] fill-black-50"
|
||||
/>
|
||||
</Content>
|
||||
</Root>
|
||||
|
Loading…
Reference in New Issue
Block a user