chore(explorer): market info shared panels (#3192)
This commit is contained in:
parent
93f8450ecb
commit
66a85cce2a
@ -1,143 +1,52 @@
|
|||||||
import {
|
|
||||||
addDecimalsFormatNumber,
|
|
||||||
formatNumberPercentage,
|
|
||||||
getMarketExpiryDateFormatted,
|
|
||||||
} from '@vegaprotocol/utils';
|
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import type { MarketInfoWithData } from '@vegaprotocol/market-info';
|
import type { MarketInfoWithData } from '@vegaprotocol/market-info';
|
||||||
import { MarketInfoTable } from '@vegaprotocol/market-info';
|
import { LiquidityInfoPanel } from '@vegaprotocol/market-info';
|
||||||
|
import { LiquidityMonitoringParametersInfoPanel } from '@vegaprotocol/market-info';
|
||||||
import {
|
import {
|
||||||
MarketStateMapping,
|
InstrumentInfoPanel,
|
||||||
MarketTradingModeMapping,
|
KeyDetailsInfoPanel,
|
||||||
} from '@vegaprotocol/types';
|
LiquidityPriceRangeInfoPanel,
|
||||||
import { AssetDetailsTable, useAssetDataProvider } from '@vegaprotocol/assets';
|
MetadataInfoPanel,
|
||||||
import { Splash } from '@vegaprotocol/ui-toolkit';
|
OracleInfoPanel,
|
||||||
import BigNumber from 'bignumber.js';
|
RiskFactorsInfoPanel,
|
||||||
import { useMemo } from 'react';
|
RiskModelInfoPanel,
|
||||||
|
RiskParametersInfoPanel,
|
||||||
|
SettlementAssetInfoPanel,
|
||||||
|
} from '@vegaprotocol/market-info';
|
||||||
|
import { MarketInfoTable } from '@vegaprotocol/market-info';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
|
export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
|
||||||
const quoteUnit = market?.tradableInstrument.instrument.product.quoteName;
|
|
||||||
const assetId = useMemo(
|
|
||||||
() => market?.tradableInstrument.instrument.product?.settlementAsset.id,
|
|
||||||
[market]
|
|
||||||
);
|
|
||||||
const { data: asset } = useAssetDataProvider(assetId ?? '');
|
|
||||||
|
|
||||||
if (!market) return null;
|
if (!market) return null;
|
||||||
|
|
||||||
const keyDetails = {
|
|
||||||
decimalPlaces: market.decimalPlaces,
|
|
||||||
positionDecimalPlaces: market.positionDecimalPlaces,
|
|
||||||
tradingMode: market.tradingMode,
|
|
||||||
state: MarketStateMapping[market.state],
|
|
||||||
};
|
|
||||||
const assetDecimals =
|
|
||||||
market.tradableInstrument.instrument.product.settlementAsset.decimals;
|
|
||||||
|
|
||||||
const liquidityPriceRange = formatNumberPercentage(
|
|
||||||
new BigNumber(market.lpPriceRange).times(100)
|
|
||||||
);
|
|
||||||
|
|
||||||
const panels = [
|
const panels = [
|
||||||
{
|
{
|
||||||
title: t('Key details'),
|
title: t('Key details'),
|
||||||
content: (
|
content: <KeyDetailsInfoPanel noBorder={false} market={market} />,
|
||||||
<MarketInfoTable
|
|
||||||
noBorder={false}
|
|
||||||
data={{
|
|
||||||
name: market.tradableInstrument.instrument.name,
|
|
||||||
marketID: market.id,
|
|
||||||
tradingMode:
|
|
||||||
keyDetails.tradingMode &&
|
|
||||||
MarketTradingModeMapping[keyDetails.tradingMode],
|
|
||||||
marketDecimalPlaces: market.decimalPlaces,
|
|
||||||
positionDecimalPlaces: market.positionDecimalPlaces,
|
|
||||||
settlementAssetDecimalPlaces: assetDecimals,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('Instrument'),
|
title: t('Instrument'),
|
||||||
content: (
|
content: <InstrumentInfoPanel noBorder={false} market={market} />,
|
||||||
<MarketInfoTable
|
|
||||||
noBorder={false}
|
|
||||||
data={{
|
|
||||||
marketName: market.tradableInstrument.instrument.name,
|
|
||||||
code: market.tradableInstrument.instrument.code,
|
|
||||||
productType:
|
|
||||||
market.tradableInstrument.instrument.product.__typename,
|
|
||||||
...market.tradableInstrument.instrument.product,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('Settlement asset'),
|
title: t('Settlement asset'),
|
||||||
content: asset ? (
|
content: <SettlementAssetInfoPanel market={market} noBorder={false} />,
|
||||||
<AssetDetailsTable
|
|
||||||
asset={asset}
|
|
||||||
inline={true}
|
|
||||||
noBorder={false}
|
|
||||||
dtClassName="text-black dark:text-white text-ui !px-0 !font-normal"
|
|
||||||
ddClassName="text-black dark:text-white text-ui !px-0 !font-normal max-w-full"
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<Splash>{t('No data')}</Splash>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('Metadata'),
|
title: t('Metadata'),
|
||||||
content: (
|
content: <MetadataInfoPanel noBorder={false} market={market} />,
|
||||||
<MarketInfoTable
|
|
||||||
noBorder={false}
|
|
||||||
data={{
|
|
||||||
expiryDate: getMarketExpiryDateFormatted(
|
|
||||||
market.tradableInstrument.instrument.metadata.tags
|
|
||||||
),
|
|
||||||
...market.tradableInstrument.instrument.metadata.tags
|
|
||||||
?.map((tag) => {
|
|
||||||
const [key, value] = tag.split(':');
|
|
||||||
return { [key]: value };
|
|
||||||
})
|
|
||||||
.reduce((acc, curr) => ({ ...acc, ...curr }), {}),
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('Risk model'),
|
title: t('Risk model'),
|
||||||
content: (
|
content: <RiskModelInfoPanel noBorder={false} market={market} />,
|
||||||
<MarketInfoTable
|
|
||||||
noBorder={false}
|
|
||||||
data={market.tradableInstrument.riskModel}
|
|
||||||
unformatted={true}
|
|
||||||
omits={[]}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('Risk parameters'),
|
title: t('Risk parameters'),
|
||||||
content: (
|
content: <RiskParametersInfoPanel noBorder={false} market={market} />,
|
||||||
<MarketInfoTable
|
|
||||||
noBorder={false}
|
|
||||||
data={market.tradableInstrument.riskModel.params}
|
|
||||||
unformatted={true}
|
|
||||||
omits={[]}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('Risk factors'),
|
title: t('Risk factors'),
|
||||||
content: (
|
content: <RiskFactorsInfoPanel noBorder={false} market={market} />,
|
||||||
<MarketInfoTable
|
|
||||||
noBorder={false}
|
|
||||||
data={market.riskFactors}
|
|
||||||
unformatted={true}
|
|
||||||
omits={['market', '__typename']}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
...(market.priceMonitoringSettings?.parameters?.triggers || []).map(
|
...(market.priceMonitoringSettings?.parameters?.triggers || []).map(
|
||||||
(trigger, i) => ({
|
(trigger, i) => ({
|
||||||
@ -158,7 +67,10 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
|
|||||||
<MarketInfoTable
|
<MarketInfoTable
|
||||||
noBorder={false}
|
noBorder={false}
|
||||||
data={{ referencePrice: trigger.referencePrice }}
|
data={{ referencePrice: trigger.referencePrice }}
|
||||||
decimalPlaces={assetDecimals}
|
decimalPlaces={
|
||||||
|
market.tradableInstrument.instrument.product.settlementAsset
|
||||||
|
.decimals
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
@ -166,64 +78,26 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
|
|||||||
{
|
{
|
||||||
title: t('Liquidity monitoring parameters'),
|
title: t('Liquidity monitoring parameters'),
|
||||||
content: (
|
content: (
|
||||||
<MarketInfoTable
|
<LiquidityMonitoringParametersInfoPanel
|
||||||
noBorder={false}
|
noBorder={false}
|
||||||
data={{
|
market={market}
|
||||||
triggeringRatio:
|
|
||||||
market.liquidityMonitoringParameters.triggeringRatio,
|
|
||||||
...market.liquidityMonitoringParameters.targetStakeParameters,
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: t('Liquidity'),
|
||||||
|
content: <LiquidityInfoPanel market={market} noBorder={false} />,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: t('Liquidity price range'),
|
title: t('Liquidity price range'),
|
||||||
content: (
|
content: (
|
||||||
<>
|
<LiquidityPriceRangeInfoPanel market={market} noBorder={false} />
|
||||||
<p className="text-xs mb-4">
|
|
||||||
{`For liquidity orders to count towards a commitment, they must be
|
|
||||||
within the liquidity monitoring bounds.`}
|
|
||||||
</p>
|
|
||||||
<p className="text-xs mb-4">
|
|
||||||
{`The liquidity price range is a ${liquidityPriceRange} difference from the mid
|
|
||||||
price.`}
|
|
||||||
</p>
|
|
||||||
<MarketInfoTable
|
|
||||||
noBorder={false}
|
|
||||||
data={{
|
|
||||||
liquidityPriceRange: `${liquidityPriceRange} of mid price`,
|
|
||||||
lowestPrice:
|
|
||||||
market.data?.midPrice &&
|
|
||||||
`${addDecimalsFormatNumber(
|
|
||||||
new BigNumber(1)
|
|
||||||
.minus(market.lpPriceRange)
|
|
||||||
.times(market.data.midPrice)
|
|
||||||
.toString(),
|
|
||||||
market.decimalPlaces
|
|
||||||
)} ${quoteUnit}`,
|
|
||||||
highestPrice:
|
|
||||||
market.data?.midPrice &&
|
|
||||||
`${addDecimalsFormatNumber(
|
|
||||||
new BigNumber(1)
|
|
||||||
.plus(market.lpPriceRange)
|
|
||||||
.times(market.data.midPrice)
|
|
||||||
.toString(),
|
|
||||||
market.decimalPlaces
|
|
||||||
)} ${quoteUnit}`,
|
|
||||||
}}
|
|
||||||
></MarketInfoTable>
|
|
||||||
</>
|
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('Oracle'),
|
title: t('Oracle'),
|
||||||
content: (
|
content: (
|
||||||
<MarketInfoTable
|
<OracleInfoPanel noBorder={false} market={market}>
|
||||||
noBorder={false}
|
|
||||||
data={
|
|
||||||
market.tradableInstrument.instrument.product.dataSourceSpecBinding
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Link
|
<Link
|
||||||
className="text-xs hover:underline"
|
className="text-xs hover:underline"
|
||||||
to={`/oracles#${market.tradableInstrument.instrument.product.dataSourceSpecForSettlementData.id}`}
|
to={`/oracles#${market.tradableInstrument.instrument.product.dataSourceSpecForSettlementData.id}`}
|
||||||
@ -236,7 +110,7 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
|
|||||||
>
|
>
|
||||||
{t('View termination oracle specification')}
|
{t('View termination oracle specification')}
|
||||||
</Link>
|
</Link>
|
||||||
</MarketInfoTable>
|
</OracleInfoPanel>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@ -244,7 +118,7 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{panels.map((p) => (
|
{panels.map((p) => (
|
||||||
<div className="mb-3">
|
<div key={p.title} className="mb-3">
|
||||||
<h2 className="font-alpha calt text-xl">{p.title}</h2>
|
<h2 className="font-alpha calt text-xl">{p.title}</h2>
|
||||||
{p.content}
|
{p.content}
|
||||||
</div>
|
</div>
|
||||||
|
@ -8,7 +8,7 @@ import { useScrollToLocation } from '../../hooks/scroll-to-location';
|
|||||||
import { useDocumentTitle } from '../../hooks/use-document-title';
|
import { useDocumentTitle } from '../../hooks/use-document-title';
|
||||||
import compact from 'lodash/compact';
|
import compact from 'lodash/compact';
|
||||||
import { JsonViewerDialog } from '../../components/dialogs/json-viewer-dialog';
|
import { JsonViewerDialog } from '../../components/dialogs/json-viewer-dialog';
|
||||||
import { marketInfoProvider } from '@vegaprotocol/market-info';
|
import { marketInfoWithDataProvider } from '@vegaprotocol/market-info';
|
||||||
import { PageTitle } from '../../components/page-helpers/page-title';
|
import { PageTitle } from '../../components/page-helpers/page-title';
|
||||||
|
|
||||||
export const MarketPage = () => {
|
export const MarketPage = () => {
|
||||||
@ -17,7 +17,7 @@ export const MarketPage = () => {
|
|||||||
const { marketId } = useParams<{ marketId: string }>();
|
const { marketId } = useParams<{ marketId: string }>();
|
||||||
|
|
||||||
const { data, loading, error } = useDataProvider({
|
const { data, loading, error } = useDataProvider({
|
||||||
dataProvider: marketInfoProvider,
|
dataProvider: marketInfoWithDataProvider,
|
||||||
skipUpdates: true,
|
skipUpdates: true,
|
||||||
variables: {
|
variables: {
|
||||||
marketId: marketId || '',
|
marketId: marketId || '',
|
||||||
|
@ -3,3 +3,4 @@ export * from './info-market';
|
|||||||
export * from './tooltip-mapping';
|
export * from './tooltip-mapping';
|
||||||
export * from './__generated__/MarketInfo';
|
export * from './__generated__/MarketInfo';
|
||||||
export * from './market-info-data-provider';
|
export * from './market-info-data-provider';
|
||||||
|
export * from './market-info-panels';
|
||||||
|
@ -1,17 +1,5 @@
|
|||||||
import { AssetDetailsTable, useAssetDataProvider } from '@vegaprotocol/assets';
|
|
||||||
import { useEnvironment } from '@vegaprotocol/environment';
|
import { useEnvironment } from '@vegaprotocol/environment';
|
||||||
import {
|
import { removePaginationWrapper, TokenLinks } from '@vegaprotocol/utils';
|
||||||
totalFeesPercentage,
|
|
||||||
calcCandleVolume,
|
|
||||||
} from '@vegaprotocol/market-list';
|
|
||||||
import {
|
|
||||||
addDecimalsFormatNumber,
|
|
||||||
formatNumber,
|
|
||||||
formatNumberPercentage,
|
|
||||||
removePaginationWrapper,
|
|
||||||
TokenLinks,
|
|
||||||
getMarketExpiryDateFormatted,
|
|
||||||
} from '@vegaprotocol/utils';
|
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import { useDataProvider, useYesterday } from '@vegaprotocol/react-helpers';
|
import { useDataProvider, useYesterday } from '@vegaprotocol/react-helpers';
|
||||||
import * as Schema from '@vegaprotocol/types';
|
import * as Schema from '@vegaprotocol/types';
|
||||||
@ -22,15 +10,31 @@ import {
|
|||||||
Link as UILink,
|
Link as UILink,
|
||||||
Splash,
|
Splash,
|
||||||
} from '@vegaprotocol/ui-toolkit';
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
import BigNumber from 'bignumber.js';
|
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { generatePath, Link } from 'react-router-dom';
|
import { generatePath, Link } from 'react-router-dom';
|
||||||
|
|
||||||
import { MarketInfoTable } from './info-key-value-table';
|
|
||||||
import { marketInfoWithDataAndCandlesProvider } from './market-info-data-provider';
|
import { marketInfoWithDataAndCandlesProvider } from './market-info-data-provider';
|
||||||
|
|
||||||
import type { MarketInfoWithDataAndCandles } from './market-info-data-provider';
|
import type { MarketInfoWithDataAndCandles } from './market-info-data-provider';
|
||||||
import { MarketProposalNotification } from '@vegaprotocol/proposals';
|
import { MarketProposalNotification } from '@vegaprotocol/proposals';
|
||||||
|
import {
|
||||||
|
CurrentFeesInfoPanel,
|
||||||
|
InstrumentInfoPanel,
|
||||||
|
InsurancePoolInfoPanel,
|
||||||
|
KeyDetailsInfoPanel,
|
||||||
|
LiquidityInfoPanel,
|
||||||
|
LiquidityMonitoringParametersInfoPanel,
|
||||||
|
LiquidityPriceRangeInfoPanel,
|
||||||
|
MarketPriceInfoPanel,
|
||||||
|
MarketVolumeInfoPanel,
|
||||||
|
MetadataInfoPanel,
|
||||||
|
OracleInfoPanel,
|
||||||
|
PriceMonitoringBoundsInfoPanel,
|
||||||
|
RiskFactorsInfoPanel,
|
||||||
|
RiskModelInfoPanel,
|
||||||
|
RiskParametersInfoPanel,
|
||||||
|
SettlementAssetInfoPanel,
|
||||||
|
} from './market-info-panels';
|
||||||
|
|
||||||
export interface InfoProps {
|
export interface InfoProps {
|
||||||
market: MarketInfoWithDataAndCandles;
|
market: MarketInfoWithDataAndCandles;
|
||||||
@ -80,15 +84,6 @@ export const MarketInfoContainer = ({
|
|||||||
export const Info = ({ market, onSelect }: InfoProps) => {
|
export const Info = ({ market, onSelect }: InfoProps) => {
|
||||||
const { VEGA_TOKEN_URL, VEGA_EXPLORER_URL } = useEnvironment();
|
const { VEGA_TOKEN_URL, VEGA_EXPLORER_URL } = useEnvironment();
|
||||||
const headerClassName = 'uppercase text-lg';
|
const headerClassName = 'uppercase text-lg';
|
||||||
const assetSymbol =
|
|
||||||
market?.tradableInstrument.instrument.product?.settlementAsset.symbol || '';
|
|
||||||
const quoteUnit =
|
|
||||||
market?.tradableInstrument.instrument.product?.quoteName || '';
|
|
||||||
const assetId = useMemo(
|
|
||||||
() => market?.tradableInstrument.instrument.product?.settlementAsset.id,
|
|
||||||
[market]
|
|
||||||
);
|
|
||||||
const { data: asset } = useAssetDataProvider(assetId ?? '');
|
|
||||||
|
|
||||||
if (!market) return null;
|
if (!market) return null;
|
||||||
|
|
||||||
@ -96,272 +91,75 @@ export const Info = ({ market, onSelect }: InfoProps) => {
|
|||||||
market.accountsConnection?.edges
|
market.accountsConnection?.edges
|
||||||
);
|
);
|
||||||
|
|
||||||
const last24hourVolume = market.candles && calcCandleVolume(market.candles);
|
|
||||||
|
|
||||||
const marketDataPanels = [
|
const marketDataPanels = [
|
||||||
{
|
{
|
||||||
title: t('Current fees'),
|
title: t('Current fees'),
|
||||||
content: (
|
content: <CurrentFeesInfoPanel market={market} />,
|
||||||
<>
|
|
||||||
<MarketInfoTable
|
|
||||||
data={{
|
|
||||||
...market.fees.factors,
|
|
||||||
totalFees: totalFeesPercentage(market.fees.factors),
|
|
||||||
}}
|
|
||||||
asPercentage={true}
|
|
||||||
/>
|
|
||||||
<p className="text-xs">
|
|
||||||
{t(
|
|
||||||
'All fees are paid by price takers and are a % of the trade notional value. Fees are not paid during auction uncrossing.'
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('Market price'),
|
title: t('Market price'),
|
||||||
content: (
|
content: <MarketPriceInfoPanel market={market} />,
|
||||||
<>
|
|
||||||
<MarketInfoTable
|
|
||||||
data={{
|
|
||||||
markPrice: market.data?.markPrice,
|
|
||||||
bestBidPrice: market.data?.bestBidPrice,
|
|
||||||
bestOfferPrice: market.data?.bestOfferPrice,
|
|
||||||
quoteUnit: market.tradableInstrument.instrument.product.quoteName,
|
|
||||||
}}
|
|
||||||
decimalPlaces={market.decimalPlaces}
|
|
||||||
/>
|
|
||||||
<p className="text-xs mt-4">
|
|
||||||
{t(
|
|
||||||
'There is 1 unit of the settlement asset (%s) to every 1 quote unit (%s).',
|
|
||||||
[assetSymbol, quoteUnit]
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('Market volume'),
|
title: t('Market volume'),
|
||||||
content: (
|
content: <MarketVolumeInfoPanel market={market} />,
|
||||||
<MarketInfoTable
|
|
||||||
data={{
|
|
||||||
'24hourVolume':
|
|
||||||
last24hourVolume && last24hourVolume !== '0'
|
|
||||||
? addDecimalsFormatNumber(
|
|
||||||
last24hourVolume,
|
|
||||||
market.positionDecimalPlaces
|
|
||||||
)
|
|
||||||
: '-',
|
|
||||||
openInterest: market.data?.openInterest,
|
|
||||||
bestBidVolume: market.data?.bestBidVolume,
|
|
||||||
bestOfferVolume: market.data?.bestOfferVolume,
|
|
||||||
bestStaticBidVolume: market.data?.bestStaticBidVolume,
|
|
||||||
bestStaticOfferVolume: market.data?.bestStaticOfferVolume,
|
|
||||||
}}
|
|
||||||
decimalPlaces={market.positionDecimalPlaces}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
...marketAccounts
|
...marketAccounts
|
||||||
.filter((a) => a.type === Schema.AccountType.ACCOUNT_TYPE_INSURANCE)
|
.filter((a) => a.type === Schema.AccountType.ACCOUNT_TYPE_INSURANCE)
|
||||||
.map((a) => ({
|
.map((a) => ({
|
||||||
title: t(`Insurance pool`),
|
title: t(`Insurance pool`),
|
||||||
content: (
|
content: <InsurancePoolInfoPanel market={market} account={a} />,
|
||||||
<MarketInfoTable
|
|
||||||
data={{
|
|
||||||
balance: a.balance,
|
|
||||||
}}
|
|
||||||
assetSymbol={assetSymbol}
|
|
||||||
decimalPlaces={
|
|
||||||
market.tradableInstrument.instrument.product.settlementAsset
|
|
||||||
.decimals
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
})),
|
})),
|
||||||
];
|
];
|
||||||
|
|
||||||
const keyDetails = {
|
|
||||||
decimalPlaces: market.decimalPlaces,
|
|
||||||
positionDecimalPlaces: market.positionDecimalPlaces,
|
|
||||||
tradingMode: market.tradingMode,
|
|
||||||
state: Schema.MarketStateMapping[market.state],
|
|
||||||
};
|
|
||||||
|
|
||||||
const assetDecimals =
|
|
||||||
market.tradableInstrument.instrument.product.settlementAsset.decimals;
|
|
||||||
|
|
||||||
const liquidityPriceRange = formatNumberPercentage(
|
|
||||||
new BigNumber(market.lpPriceRange).times(100)
|
|
||||||
);
|
|
||||||
|
|
||||||
const marketSpecPanels = [
|
const marketSpecPanels = [
|
||||||
{
|
{
|
||||||
title: t('Key details'),
|
title: t('Key details'),
|
||||||
content: (
|
content: <KeyDetailsInfoPanel market={market} />,
|
||||||
<MarketInfoTable
|
|
||||||
data={{
|
|
||||||
name: market.tradableInstrument.instrument.name,
|
|
||||||
marketID: market.id,
|
|
||||||
tradingMode:
|
|
||||||
keyDetails.tradingMode &&
|
|
||||||
Schema.MarketTradingModeMapping[keyDetails.tradingMode],
|
|
||||||
marketDecimalPlaces: market.decimalPlaces,
|
|
||||||
positionDecimalPlaces: market.positionDecimalPlaces,
|
|
||||||
settlementAssetDecimalPlaces: assetDecimals,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('Instrument'),
|
title: t('Instrument'),
|
||||||
content: (
|
content: <InstrumentInfoPanel market={market} />,
|
||||||
<MarketInfoTable
|
|
||||||
data={{
|
|
||||||
marketName: market.tradableInstrument.instrument.name,
|
|
||||||
code: market.tradableInstrument.instrument.code,
|
|
||||||
productType:
|
|
||||||
market.tradableInstrument.instrument.product.__typename,
|
|
||||||
...market.tradableInstrument.instrument.product,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('Settlement asset'),
|
title: t('Settlement asset'),
|
||||||
content: asset ? (
|
content: <SettlementAssetInfoPanel market={market} />,
|
||||||
<>
|
|
||||||
<AssetDetailsTable
|
|
||||||
asset={asset}
|
|
||||||
inline={true}
|
|
||||||
noBorder={true}
|
|
||||||
dtClassName="text-black dark:text-white text-ui !px-0 !font-normal"
|
|
||||||
ddClassName="text-black dark:text-white text-ui !px-0 !font-normal max-w-full"
|
|
||||||
/>
|
|
||||||
<p className="text-xs mt-4">
|
|
||||||
{t(
|
|
||||||
'There is 1 unit of the settlement asset (%s) to every 1 quote unit (%s).',
|
|
||||||
[assetSymbol, quoteUnit]
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<Splash>{t('No data')}</Splash>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('Metadata'),
|
title: t('Metadata'),
|
||||||
content: (
|
content: <MetadataInfoPanel market={market} />,
|
||||||
<MarketInfoTable
|
|
||||||
data={{
|
|
||||||
expiryDate: getMarketExpiryDateFormatted(
|
|
||||||
market.tradableInstrument.instrument.metadata.tags
|
|
||||||
),
|
|
||||||
...market.tradableInstrument.instrument.metadata.tags
|
|
||||||
?.map((tag) => {
|
|
||||||
const [key, value] = tag.split(':');
|
|
||||||
return { [key]: value };
|
|
||||||
})
|
|
||||||
.reduce((acc, curr) => ({ ...acc, ...curr }), {}),
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('Risk model'),
|
title: t('Risk model'),
|
||||||
content: (
|
content: <RiskModelInfoPanel market={market} />,
|
||||||
<MarketInfoTable
|
|
||||||
data={market.tradableInstrument.riskModel}
|
|
||||||
unformatted={true}
|
|
||||||
omits={[]}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('Risk parameters'),
|
title: t('Risk parameters'),
|
||||||
content: (
|
content: <RiskParametersInfoPanel market={market} />,
|
||||||
<MarketInfoTable
|
|
||||||
data={market.tradableInstrument.riskModel.params}
|
|
||||||
unformatted={true}
|
|
||||||
omits={[]}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('Risk factors'),
|
title: t('Risk factors'),
|
||||||
content: (
|
content: <RiskFactorsInfoPanel market={market} />,
|
||||||
<MarketInfoTable
|
|
||||||
data={market.riskFactors}
|
|
||||||
unformatted={true}
|
|
||||||
omits={['market', '__typename']}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
...(market.priceMonitoringSettings?.parameters?.triggers || []).map(
|
...(market.priceMonitoringSettings?.parameters?.triggers || []).map(
|
||||||
(trigger, i) => {
|
(_, triggerIndex) => ({
|
||||||
const bounds = market.data?.priceMonitoringBounds?.[i];
|
title: t(`Price monitoring bounds ${triggerIndex + 1}`),
|
||||||
return {
|
|
||||||
title: t(`Price monitoring bounds ${i + 1}`),
|
|
||||||
content: (
|
content: (
|
||||||
<div className="text-xs">
|
<PriceMonitoringBoundsInfoPanel
|
||||||
<div className="grid grid-cols-2 text-xs mb-4">
|
market={market}
|
||||||
<p className="col-span-1">
|
triggerIndex={triggerIndex}
|
||||||
{t('%s probability price bounds', [
|
|
||||||
formatNumberPercentage(
|
|
||||||
new BigNumber(trigger.probability).times(100)
|
|
||||||
),
|
|
||||||
])}
|
|
||||||
</p>
|
|
||||||
<p className="col-span-1 text-right">
|
|
||||||
{t('Within %s seconds', [formatNumber(trigger.horizonSecs)])}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="pl-2 pb-0 text-xs border-l-2">
|
|
||||||
{bounds && (
|
|
||||||
<MarketInfoTable
|
|
||||||
data={{
|
|
||||||
highestPrice: bounds.maxValidPrice,
|
|
||||||
lowestPrice: bounds.minValidPrice,
|
|
||||||
}}
|
|
||||||
decimalPlaces={market.decimalPlaces}
|
|
||||||
assetSymbol={quoteUnit}
|
|
||||||
/>
|
/>
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<p className="mt-4">
|
|
||||||
{t('Results in %s seconds auction if breached', [
|
|
||||||
trigger.auctionExtensionSecs.toString(),
|
|
||||||
])}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
),
|
),
|
||||||
};
|
})
|
||||||
}
|
|
||||||
),
|
),
|
||||||
{
|
{
|
||||||
title: t('Liquidity monitoring parameters'),
|
title: t('Liquidity monitoring parameters'),
|
||||||
content: (
|
content: <LiquidityMonitoringParametersInfoPanel market={market} />,
|
||||||
<MarketInfoTable
|
|
||||||
data={{
|
|
||||||
triggeringRatio:
|
|
||||||
market.liquidityMonitoringParameters.triggeringRatio,
|
|
||||||
...market.liquidityMonitoringParameters.targetStakeParameters,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('Liquidity'),
|
title: t('Liquidity'),
|
||||||
content: (
|
content: (
|
||||||
<MarketInfoTable
|
<LiquidityInfoPanel market={market}>
|
||||||
data={{
|
|
||||||
targetStake: market.data && market.data.targetStake,
|
|
||||||
suppliedStake: market.data && market.data?.suppliedStake,
|
|
||||||
marketValueProxy: market.data && market.data.marketValueProxy,
|
|
||||||
}}
|
|
||||||
decimalPlaces={assetDecimals}
|
|
||||||
assetSymbol={assetSymbol}
|
|
||||||
>
|
|
||||||
<Link
|
<Link
|
||||||
to={`/liquidity/${market.id}`}
|
to={`/liquidity/${market.id}`}
|
||||||
onClick={() => onSelect(market.id)}
|
onClick={() => onSelect(market.id)}
|
||||||
@ -369,57 +167,17 @@ export const Info = ({ market, onSelect }: InfoProps) => {
|
|||||||
>
|
>
|
||||||
<UILink>{t('View liquidity provision table')}</UILink>
|
<UILink>{t('View liquidity provision table')}</UILink>
|
||||||
</Link>
|
</Link>
|
||||||
</MarketInfoTable>
|
</LiquidityInfoPanel>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('Liquidity price range'),
|
title: t('Liquidity price range'),
|
||||||
content: (
|
content: <LiquidityPriceRangeInfoPanel market={market} />,
|
||||||
<>
|
|
||||||
<p className="text-xs mb-4">
|
|
||||||
{`For liquidity orders to count towards a commitment, they must be
|
|
||||||
within the liquidity monitoring bounds.`}
|
|
||||||
</p>
|
|
||||||
<p className="text-xs mb-4">
|
|
||||||
{`The liquidity price range is a ${liquidityPriceRange} difference from the mid
|
|
||||||
price.`}
|
|
||||||
</p>
|
|
||||||
<div className="pl-2 pb-0 text-xs border-l-2">
|
|
||||||
<MarketInfoTable
|
|
||||||
data={{
|
|
||||||
liquidityPriceRange: `${liquidityPriceRange} of mid price`,
|
|
||||||
lowestPrice:
|
|
||||||
market.data?.midPrice &&
|
|
||||||
`${addDecimalsFormatNumber(
|
|
||||||
new BigNumber(1)
|
|
||||||
.minus(market.lpPriceRange)
|
|
||||||
.times(market.data.midPrice)
|
|
||||||
.toString(),
|
|
||||||
market.decimalPlaces
|
|
||||||
)} ${quoteUnit}`,
|
|
||||||
highestPrice:
|
|
||||||
market.data?.midPrice &&
|
|
||||||
`${addDecimalsFormatNumber(
|
|
||||||
new BigNumber(1)
|
|
||||||
.plus(market.lpPriceRange)
|
|
||||||
.times(market.data.midPrice)
|
|
||||||
.toString(),
|
|
||||||
market.decimalPlaces
|
|
||||||
)} ${quoteUnit}`,
|
|
||||||
}}
|
|
||||||
></MarketInfoTable>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('Oracle'),
|
title: t('Oracle'),
|
||||||
content: (
|
content: (
|
||||||
<MarketInfoTable
|
<OracleInfoPanel market={market}>
|
||||||
data={
|
|
||||||
market.tradableInstrument.instrument.product.dataSourceSpecBinding
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<ExternalLink
|
<ExternalLink
|
||||||
href={`${VEGA_EXPLORER_URL}/oracles#${market.tradableInstrument.instrument.product.dataSourceSpecForSettlementData.id}`}
|
href={`${VEGA_EXPLORER_URL}/oracles#${market.tradableInstrument.instrument.product.dataSourceSpecForSettlementData.id}`}
|
||||||
>
|
>
|
||||||
@ -430,7 +188,7 @@ export const Info = ({ market, onSelect }: InfoProps) => {
|
|||||||
>
|
>
|
||||||
{t('View termination oracle specification')}
|
{t('View termination oracle specification')}
|
||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
</MarketInfoTable>
|
</OracleInfoPanel>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -0,0 +1,418 @@
|
|||||||
|
import type { ComponentProps } from 'react';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { AssetDetailsTable, useAssetDataProvider } from '@vegaprotocol/assets';
|
||||||
|
import { t } from '@vegaprotocol/i18n';
|
||||||
|
import {
|
||||||
|
calcCandleVolume,
|
||||||
|
totalFeesPercentage,
|
||||||
|
} from '@vegaprotocol/market-list';
|
||||||
|
import { Splash } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import {
|
||||||
|
addDecimalsFormatNumber,
|
||||||
|
formatNumber,
|
||||||
|
formatNumberPercentage,
|
||||||
|
getMarketExpiryDateFormatted,
|
||||||
|
} from '@vegaprotocol/utils';
|
||||||
|
import type { Get } from 'type-fest';
|
||||||
|
import { MarketInfoTable } from './info-key-value-table';
|
||||||
|
import type {
|
||||||
|
MarketInfo,
|
||||||
|
MarketInfoWithData,
|
||||||
|
MarketInfoWithDataAndCandles,
|
||||||
|
} from './market-info-data-provider';
|
||||||
|
import BigNumber from 'bignumber.js';
|
||||||
|
import { MarketTradingModeMapping } from '@vegaprotocol/types';
|
||||||
|
|
||||||
|
type PanelProps = Pick<
|
||||||
|
ComponentProps<typeof MarketInfoTable>,
|
||||||
|
'children' | 'noBorder'
|
||||||
|
>;
|
||||||
|
|
||||||
|
type MarketInfoProps = {
|
||||||
|
market: MarketInfo;
|
||||||
|
};
|
||||||
|
|
||||||
|
type MarketInfoWithDataProps = {
|
||||||
|
market: MarketInfoWithData;
|
||||||
|
};
|
||||||
|
|
||||||
|
type MarketInfoWithDataAndCandlesProps = {
|
||||||
|
market: MarketInfoWithDataAndCandles;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CurrentFeesInfoPanel = ({
|
||||||
|
market,
|
||||||
|
...props
|
||||||
|
}: MarketInfoProps & PanelProps) => (
|
||||||
|
<>
|
||||||
|
<MarketInfoTable
|
||||||
|
data={{
|
||||||
|
...market.fees.factors,
|
||||||
|
totalFees: totalFeesPercentage(market.fees.factors),
|
||||||
|
}}
|
||||||
|
asPercentage={true}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
<p className="text-xs">
|
||||||
|
{t(
|
||||||
|
'All fees are paid by price takers and are a % of the trade notional value. Fees are not paid during auction uncrossing.'
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const MarketPriceInfoPanel = ({
|
||||||
|
market,
|
||||||
|
...props
|
||||||
|
}: MarketInfoWithDataProps & PanelProps) => {
|
||||||
|
const assetSymbol =
|
||||||
|
market?.tradableInstrument.instrument.product?.settlementAsset.symbol || '';
|
||||||
|
const quoteUnit =
|
||||||
|
market?.tradableInstrument.instrument.product?.quoteName || '';
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<MarketInfoTable
|
||||||
|
data={{
|
||||||
|
markPrice: market.data?.markPrice,
|
||||||
|
bestBidPrice: market.data?.bestBidPrice,
|
||||||
|
bestOfferPrice: market.data?.bestOfferPrice,
|
||||||
|
quoteUnit: market.tradableInstrument.instrument.product.quoteName,
|
||||||
|
}}
|
||||||
|
decimalPlaces={market.decimalPlaces}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
<p className="text-xs mt-4">
|
||||||
|
{t(
|
||||||
|
'There is 1 unit of the settlement asset (%s) to every 1 quote unit (%s).',
|
||||||
|
[assetSymbol, quoteUnit]
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const MarketVolumeInfoPanel = ({
|
||||||
|
market,
|
||||||
|
...props
|
||||||
|
}: MarketInfoWithDataAndCandlesProps & PanelProps) => {
|
||||||
|
const last24hourVolume = market.candles && calcCandleVolume(market.candles);
|
||||||
|
return (
|
||||||
|
<MarketInfoTable
|
||||||
|
data={{
|
||||||
|
'24hourVolume':
|
||||||
|
last24hourVolume && last24hourVolume !== '0'
|
||||||
|
? addDecimalsFormatNumber(
|
||||||
|
last24hourVolume,
|
||||||
|
market.positionDecimalPlaces
|
||||||
|
)
|
||||||
|
: '-',
|
||||||
|
openInterest: market.data?.openInterest,
|
||||||
|
bestBidVolume: market.data?.bestBidVolume,
|
||||||
|
bestOfferVolume: market.data?.bestOfferVolume,
|
||||||
|
bestStaticBidVolume: market.data?.bestStaticBidVolume,
|
||||||
|
bestStaticOfferVolume: market.data?.bestStaticOfferVolume,
|
||||||
|
}}
|
||||||
|
decimalPlaces={market.positionDecimalPlaces}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const InsurancePoolInfoPanel = ({
|
||||||
|
market,
|
||||||
|
account,
|
||||||
|
...props
|
||||||
|
}: {
|
||||||
|
account: NonNullable<
|
||||||
|
Get<MarketInfoWithData, 'accountsConnection.edges[0].node'>
|
||||||
|
>;
|
||||||
|
} & MarketInfoProps &
|
||||||
|
PanelProps) => {
|
||||||
|
const assetSymbol =
|
||||||
|
market?.tradableInstrument.instrument.product?.settlementAsset.symbol || '';
|
||||||
|
return (
|
||||||
|
<MarketInfoTable
|
||||||
|
data={{
|
||||||
|
balance: account.balance,
|
||||||
|
}}
|
||||||
|
assetSymbol={assetSymbol}
|
||||||
|
decimalPlaces={
|
||||||
|
market.tradableInstrument.instrument.product.settlementAsset.decimals
|
||||||
|
}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const KeyDetailsInfoPanel = ({
|
||||||
|
market,
|
||||||
|
}: MarketInfoProps & PanelProps) => {
|
||||||
|
const assetDecimals =
|
||||||
|
market.tradableInstrument.instrument.product.settlementAsset.decimals;
|
||||||
|
return (
|
||||||
|
<MarketInfoTable
|
||||||
|
data={{
|
||||||
|
name: market.tradableInstrument.instrument.name,
|
||||||
|
marketID: market.id,
|
||||||
|
tradingMode:
|
||||||
|
market.tradingMode && MarketTradingModeMapping[market.tradingMode],
|
||||||
|
marketDecimalPlaces: market.decimalPlaces,
|
||||||
|
positionDecimalPlaces: market.positionDecimalPlaces,
|
||||||
|
settlementAssetDecimalPlaces: assetDecimals,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const InstrumentInfoPanel = ({
|
||||||
|
market,
|
||||||
|
...props
|
||||||
|
}: MarketInfoProps & PanelProps) => (
|
||||||
|
<MarketInfoTable
|
||||||
|
data={{
|
||||||
|
marketName: market.tradableInstrument.instrument.name,
|
||||||
|
code: market.tradableInstrument.instrument.code,
|
||||||
|
productType: market.tradableInstrument.instrument.product.__typename,
|
||||||
|
...market.tradableInstrument.instrument.product,
|
||||||
|
}}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const SettlementAssetInfoPanel = ({
|
||||||
|
market,
|
||||||
|
noBorder = true,
|
||||||
|
}: MarketInfoProps & PanelProps) => {
|
||||||
|
const assetSymbol =
|
||||||
|
market?.tradableInstrument.instrument.product?.settlementAsset.symbol || '';
|
||||||
|
const quoteUnit =
|
||||||
|
market?.tradableInstrument.instrument.product?.quoteName || '';
|
||||||
|
const assetId = useMemo(
|
||||||
|
() => market?.tradableInstrument.instrument.product?.settlementAsset.id,
|
||||||
|
[market]
|
||||||
|
);
|
||||||
|
const { data: asset } = useAssetDataProvider(assetId ?? '');
|
||||||
|
return asset ? (
|
||||||
|
<>
|
||||||
|
<AssetDetailsTable
|
||||||
|
asset={asset}
|
||||||
|
inline={true}
|
||||||
|
noBorder={noBorder}
|
||||||
|
dtClassName="text-black dark:text-white text-ui !px-0 !font-normal"
|
||||||
|
ddClassName="text-black dark:text-white text-ui !px-0 !font-normal max-w-full"
|
||||||
|
/>
|
||||||
|
<p className="text-xs mt-4">
|
||||||
|
{t(
|
||||||
|
'There is 1 unit of the settlement asset (%s) to every 1 quote unit (%s).',
|
||||||
|
[assetSymbol, quoteUnit]
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<Splash>{t('No data')}</Splash>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const MetadataInfoPanel = ({
|
||||||
|
market,
|
||||||
|
...props
|
||||||
|
}: MarketInfoProps & PanelProps) => (
|
||||||
|
<MarketInfoTable
|
||||||
|
data={{
|
||||||
|
expiryDate: getMarketExpiryDateFormatted(
|
||||||
|
market.tradableInstrument.instrument.metadata.tags
|
||||||
|
),
|
||||||
|
...market.tradableInstrument.instrument.metadata.tags
|
||||||
|
?.map((tag) => {
|
||||||
|
const [key, value] = tag.split(':');
|
||||||
|
return { [key]: value };
|
||||||
|
})
|
||||||
|
.reduce((acc, curr) => ({ ...acc, ...curr }), {}),
|
||||||
|
}}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const RiskModelInfoPanel = ({
|
||||||
|
market,
|
||||||
|
...props
|
||||||
|
}: MarketInfoProps & PanelProps) => (
|
||||||
|
<MarketInfoTable
|
||||||
|
data={market.tradableInstrument.riskModel}
|
||||||
|
unformatted={true}
|
||||||
|
omits={[]}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const RiskParametersInfoPanel = ({
|
||||||
|
market,
|
||||||
|
...props
|
||||||
|
}: MarketInfoProps & PanelProps) => (
|
||||||
|
<MarketInfoTable
|
||||||
|
data={market.tradableInstrument.riskModel.params}
|
||||||
|
unformatted={true}
|
||||||
|
omits={[]}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const RiskFactorsInfoPanel = ({
|
||||||
|
market,
|
||||||
|
...props
|
||||||
|
}: MarketInfoProps & PanelProps) => (
|
||||||
|
<MarketInfoTable
|
||||||
|
data={market.riskFactors}
|
||||||
|
unformatted={true}
|
||||||
|
omits={['market', '__typename']}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const PriceMonitoringBoundsInfoPanel = ({
|
||||||
|
market,
|
||||||
|
triggerIndex,
|
||||||
|
...props
|
||||||
|
}: {
|
||||||
|
triggerIndex: number;
|
||||||
|
} & MarketInfoWithDataProps &
|
||||||
|
PanelProps) => {
|
||||||
|
const quoteUnit =
|
||||||
|
market?.tradableInstrument.instrument.product?.quoteName || '';
|
||||||
|
const trigger =
|
||||||
|
market.priceMonitoringSettings?.parameters?.triggers?.[triggerIndex];
|
||||||
|
const bounds = market.data?.priceMonitoringBounds?.[triggerIndex];
|
||||||
|
if (!trigger) {
|
||||||
|
console.error(
|
||||||
|
`Could not find data for trigger ${triggerIndex} (market id: ${market.id})`
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className="text-xs">
|
||||||
|
<div className="grid grid-cols-2 text-xs mb-4">
|
||||||
|
<p className="col-span-1">
|
||||||
|
{t('%s probability price bounds', [
|
||||||
|
formatNumberPercentage(
|
||||||
|
new BigNumber(trigger.probability).times(100)
|
||||||
|
),
|
||||||
|
])}
|
||||||
|
</p>
|
||||||
|
<p className="col-span-1 text-right">
|
||||||
|
{t('Within %s seconds', [formatNumber(trigger.horizonSecs)])}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="pl-2 pb-0 text-xs border-l-2">
|
||||||
|
{bounds && (
|
||||||
|
<MarketInfoTable
|
||||||
|
data={{
|
||||||
|
highestPrice: bounds.maxValidPrice,
|
||||||
|
lowestPrice: bounds.minValidPrice,
|
||||||
|
}}
|
||||||
|
decimalPlaces={market.decimalPlaces}
|
||||||
|
assetSymbol={quoteUnit}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<p className="mt-4">
|
||||||
|
{t('Results in %s seconds auction if breached', [
|
||||||
|
trigger.auctionExtensionSecs.toString(),
|
||||||
|
])}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const LiquidityMonitoringParametersInfoPanel = ({
|
||||||
|
market,
|
||||||
|
...props
|
||||||
|
}: MarketInfoProps & PanelProps) => (
|
||||||
|
<MarketInfoTable
|
||||||
|
data={{
|
||||||
|
triggeringRatio: market.liquidityMonitoringParameters.triggeringRatio,
|
||||||
|
...market.liquidityMonitoringParameters.targetStakeParameters,
|
||||||
|
}}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const LiquidityInfoPanel = ({
|
||||||
|
market,
|
||||||
|
...props
|
||||||
|
}: MarketInfoWithDataProps & PanelProps) => {
|
||||||
|
const assetDecimals =
|
||||||
|
market.tradableInstrument.instrument.product.settlementAsset.decimals;
|
||||||
|
const assetSymbol =
|
||||||
|
market?.tradableInstrument.instrument.product?.settlementAsset.symbol || '';
|
||||||
|
return (
|
||||||
|
<MarketInfoTable
|
||||||
|
data={{
|
||||||
|
targetStake: market.data && market.data.targetStake,
|
||||||
|
suppliedStake: market.data && market.data?.suppliedStake,
|
||||||
|
marketValueProxy: market.data && market.data.marketValueProxy,
|
||||||
|
}}
|
||||||
|
decimalPlaces={assetDecimals}
|
||||||
|
assetSymbol={assetSymbol}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const LiquidityPriceRangeInfoPanel = ({
|
||||||
|
market,
|
||||||
|
...props
|
||||||
|
}: MarketInfoWithDataProps & PanelProps) => {
|
||||||
|
const quoteUnit =
|
||||||
|
market?.tradableInstrument.instrument.product?.quoteName || '';
|
||||||
|
const liquidityPriceRange = formatNumberPercentage(
|
||||||
|
new BigNumber(market.lpPriceRange).times(100)
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p className="text-xs mb-4">
|
||||||
|
{`For liquidity orders to count towards a commitment, they must be
|
||||||
|
within the liquidity monitoring bounds.`}
|
||||||
|
</p>
|
||||||
|
<p className="text-xs mb-4">
|
||||||
|
{`The liquidity price range is a ${liquidityPriceRange} difference from the mid
|
||||||
|
price.`}
|
||||||
|
</p>
|
||||||
|
<div className="pl-2 pb-0 text-xs border-l-2">
|
||||||
|
<MarketInfoTable
|
||||||
|
data={{
|
||||||
|
liquidityPriceRange: `${liquidityPriceRange} of mid price`,
|
||||||
|
lowestPrice:
|
||||||
|
market.data?.midPrice &&
|
||||||
|
`${addDecimalsFormatNumber(
|
||||||
|
new BigNumber(1)
|
||||||
|
.minus(market.lpPriceRange)
|
||||||
|
.times(market.data.midPrice)
|
||||||
|
.toString(),
|
||||||
|
market.decimalPlaces
|
||||||
|
)} ${quoteUnit}`,
|
||||||
|
highestPrice:
|
||||||
|
market.data?.midPrice &&
|
||||||
|
`${addDecimalsFormatNumber(
|
||||||
|
new BigNumber(1)
|
||||||
|
.plus(market.lpPriceRange)
|
||||||
|
.times(market.data.midPrice)
|
||||||
|
.toString(),
|
||||||
|
market.decimalPlaces
|
||||||
|
)} ${quoteUnit}`,
|
||||||
|
}}
|
||||||
|
></MarketInfoTable>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const OracleInfoPanel = ({
|
||||||
|
market,
|
||||||
|
...props
|
||||||
|
}: MarketInfoProps & PanelProps) => (
|
||||||
|
<MarketInfoTable
|
||||||
|
data={market.tradableInstrument.instrument.product.dataSourceSpecBinding}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
Loading…
Reference in New Issue
Block a user