chore(trading): 4858 redesign market header (#4976)
This commit is contained in:
parent
3371e8e2cc
commit
39c53a7326
@ -58,7 +58,7 @@ describe('Market trading page', () => {
|
|||||||
// 6002-MDET-003
|
// 6002-MDET-003
|
||||||
cy.getByTestId(marketSummaryBlock).within(() => {
|
cy.getByTestId(marketSummaryBlock).within(() => {
|
||||||
cy.getByTestId(marketPrice).within(() => {
|
cy.getByTestId(marketPrice).within(() => {
|
||||||
cy.getByTestId(itemHeader).should('have.text', 'Price');
|
cy.getByTestId(itemHeader).should('have.text', 'Mark Price');
|
||||||
cy.getByTestId(itemValue).should('not.be.empty');
|
cy.getByTestId(itemValue).should('not.be.empty');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||||
import { useEnvironment } from '@vegaprotocol/environment';
|
import { DocsLinks, useEnvironment } from '@vegaprotocol/environment';
|
||||||
import { ButtonLink, Link } from '@vegaprotocol/ui-toolkit';
|
import { ButtonLink, ExternalLink, Link } from '@vegaprotocol/ui-toolkit';
|
||||||
import { MarketProposalNotification } from '@vegaprotocol/proposals';
|
import { MarketProposalNotification } from '@vegaprotocol/proposals';
|
||||||
import type { Market } from '@vegaprotocol/markets';
|
import type { Market } from '@vegaprotocol/markets';
|
||||||
import {
|
import {
|
||||||
|
addDecimalsFormatNumber,
|
||||||
fromNanoSeconds,
|
fromNanoSeconds,
|
||||||
getExpiryDate,
|
getExpiryDate,
|
||||||
getMarketExpiryDate,
|
getMarketExpiryDate,
|
||||||
@ -17,6 +18,7 @@ import {
|
|||||||
marketInfoProvider,
|
marketInfoProvider,
|
||||||
useFundingPeriodsQuery,
|
useFundingPeriodsQuery,
|
||||||
useFundingRate,
|
useFundingRate,
|
||||||
|
useExternalTwap,
|
||||||
} from '@vegaprotocol/markets';
|
} from '@vegaprotocol/markets';
|
||||||
import { MarketState as State } from '@vegaprotocol/types';
|
import { MarketState as State } from '@vegaprotocol/types';
|
||||||
import { HeaderStat } from '../../components/header';
|
import { HeaderStat } from '../../components/header';
|
||||||
@ -26,6 +28,7 @@ import { MarketState } from '../../components/market-state';
|
|||||||
import { MarketLiquiditySupplied } from '../../components/liquidity-supplied';
|
import { MarketLiquiditySupplied } from '../../components/liquidity-supplied';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||||
|
import { PriceCell } from '@vegaprotocol/datagrid';
|
||||||
|
|
||||||
interface MarketHeaderStatsProps {
|
interface MarketHeaderStatsProps {
|
||||||
market: Market;
|
market: Market;
|
||||||
@ -38,34 +41,8 @@ export const MarketHeaderStats = ({ market }: MarketHeaderStatsProps) => {
|
|||||||
const asset = getAsset(market);
|
const asset = getAsset(market);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="flex gap-8">
|
||||||
{market.tradableInstrument.instrument.product.__typename === 'Future' && (
|
<HeaderStat heading={t('Mark Price')} testId="market-price">
|
||||||
<HeaderStat
|
|
||||||
heading={t('Expiry')}
|
|
||||||
description={
|
|
||||||
<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>
|
|
||||||
)}
|
|
||||||
<HeaderStat heading={t('Price')} testId="market-price">
|
|
||||||
<MarketMarkPrice
|
<MarketMarkPrice
|
||||||
marketId={market.id}
|
marketId={market.id}
|
||||||
decimalPlaces={market.decimalPlaces}
|
decimalPlaces={market.decimalPlaces}
|
||||||
@ -108,8 +85,64 @@ export const MarketHeaderStats = ({ market }: MarketHeaderStatsProps) => {
|
|||||||
marketId={market.id}
|
marketId={market.id}
|
||||||
assetDecimals={asset?.decimals || 0}
|
assetDecimals={asset?.decimals || 0}
|
||||||
/>
|
/>
|
||||||
|
{market.tradableInstrument.instrument.product.__typename === 'Future' && (
|
||||||
|
<HeaderStat
|
||||||
|
heading={t('Expiry')}
|
||||||
|
description={
|
||||||
|
<ExpiryTooltipContent
|
||||||
|
market={market}
|
||||||
|
explorerUrl={VEGA_EXPLORER_URL}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
testId="market-expiry"
|
||||||
|
>
|
||||||
|
<ExpiryLabel market={market} />
|
||||||
|
</HeaderStat>
|
||||||
|
)}
|
||||||
|
{market.tradableInstrument.instrument.product.__typename ===
|
||||||
|
'Perpetual' && (
|
||||||
|
<HeaderStat
|
||||||
|
heading={`${t('Funding Rate')} / ${t('Countdown')}`}
|
||||||
|
testId="market-funding"
|
||||||
|
>
|
||||||
|
<div className="flex justify-between gap-2">
|
||||||
|
<FundingRate marketId={market.id} />
|
||||||
|
<FundingCountdown marketId={market.id} />
|
||||||
|
</div>
|
||||||
|
</HeaderStat>
|
||||||
|
)}
|
||||||
|
{market.tradableInstrument.instrument.product.__typename ===
|
||||||
|
'Perpetual' && (
|
||||||
|
<HeaderStat
|
||||||
|
heading={`${t('Index Price')}`}
|
||||||
|
description={
|
||||||
|
<div className="p1">
|
||||||
|
{t(
|
||||||
|
'The external time weighted average price (TWAP) received from the data source defined in the data sourcing specification.'
|
||||||
|
)}
|
||||||
|
{DocsLinks && (
|
||||||
|
<ExternalLink
|
||||||
|
href={DocsLinks.ETH_DATA_SOURCES}
|
||||||
|
className="mt-2"
|
||||||
|
>
|
||||||
|
{t('Find out more')}
|
||||||
|
</ExternalLink>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
testId="index-price"
|
||||||
|
>
|
||||||
|
<IndexPrice
|
||||||
|
marketId={market.id}
|
||||||
|
decimalPlaces={
|
||||||
|
market.tradableInstrument.instrument.product.settlementAsset
|
||||||
|
.decimals
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</HeaderStat>
|
||||||
|
)}
|
||||||
<MarketProposalNotification marketId={market.id} />
|
<MarketProposalNotification marketId={market.id} />
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -126,6 +159,24 @@ export const FundingRate = ({ marketId }: { marketId: string }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const IndexPrice = ({
|
||||||
|
marketId,
|
||||||
|
decimalPlaces,
|
||||||
|
}: {
|
||||||
|
marketId: string;
|
||||||
|
decimalPlaces?: number;
|
||||||
|
}) => {
|
||||||
|
const { data: externalTwap } = useExternalTwap(marketId);
|
||||||
|
return externalTwap && decimalPlaces ? (
|
||||||
|
<PriceCell
|
||||||
|
value={Number(externalTwap)}
|
||||||
|
valueFormatted={addDecimalsFormatNumber(externalTwap, decimalPlaces)}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
'-'
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const useNow = () => {
|
const useNow = () => {
|
||||||
const [now, setNow] = useState(Date.now());
|
const [now, setNow] = useState(Date.now());
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -81,6 +81,7 @@ export const DocsLinks = VEGA_DOCS_URL
|
|||||||
WITHDRAWAL_LIMITS: `${VEGA_DOCS_URL}/concepts/assets/deposits-withdrawals#withdrawal-limits`,
|
WITHDRAWAL_LIMITS: `${VEGA_DOCS_URL}/concepts/assets/deposits-withdrawals#withdrawal-limits`,
|
||||||
VALIDATOR_SCORES_REWARDS: `${VEGA_DOCS_URL}/concepts/vega-chain/validator-scores-and-rewards`,
|
VALIDATOR_SCORES_REWARDS: `${VEGA_DOCS_URL}/concepts/vega-chain/validator-scores-and-rewards`,
|
||||||
MARKET_LIFECYCLE: `${VEGA_DOCS_URL}/concepts/trading-on-vega/market-lifecycle`,
|
MARKET_LIFECYCLE: `${VEGA_DOCS_URL}/concepts/trading-on-vega/market-lifecycle`,
|
||||||
|
ETH_DATA_SOURCES: `${VEGA_DOCS_URL}/concepts/trading-on-vega/data-sources#ethereum-data-sources`,
|
||||||
}
|
}
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
|
@ -132,6 +132,23 @@ export const useFundingRate = (marketId?: string, skip?: boolean) =>
|
|||||||
skip: skip || !marketId,
|
skip: skip || !marketId,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const externalTwapProvider = makeDerivedDataProvider<
|
||||||
|
string,
|
||||||
|
never,
|
||||||
|
MarketDataQueryVariables
|
||||||
|
>([marketDataProvider], (parts) => {
|
||||||
|
return (
|
||||||
|
(parts[0] as ReturnType<typeof getData>)?.productData?.externalTwap || null
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
export const useExternalTwap = (marketId?: string, skip?: boolean) =>
|
||||||
|
useDataProvider({
|
||||||
|
dataProvider: externalTwapProvider,
|
||||||
|
variables: { marketId: marketId || '' },
|
||||||
|
skip: skip || !marketId,
|
||||||
|
});
|
||||||
|
|
||||||
export const useStaticMarketData = (marketId?: string, skip?: boolean) => {
|
export const useStaticMarketData = (marketId?: string, skip?: boolean) => {
|
||||||
return useDataProvider({
|
return useDataProvider({
|
||||||
dataProvider: staticMarketDataProvider,
|
dataProvider: staticMarketDataProvider,
|
||||||
|
Loading…
Reference in New Issue
Block a user