diff --git a/apps/trading/client-pages/market/market-header-stats.tsx b/apps/trading/client-pages/market/market-header-stats.tsx index c9ee0dee6..ffb327a16 100644 --- a/apps/trading/client-pages/market/market-header-stats.tsx +++ b/apps/trading/client-pages/market/market-header-stats.tsx @@ -56,7 +56,6 @@ export const MarketHeaderStats = ({ market }: MarketHeaderStatsProps) => { -} /> diff --git a/apps/trading/client-pages/market/trade-panels.tsx b/apps/trading/client-pages/market/trade-panels.tsx index 759a56364..bce9c210d 100644 --- a/apps/trading/client-pages/market/trade-panels.tsx +++ b/apps/trading/client-pages/market/trade-panels.tsx @@ -72,7 +72,14 @@ export const TradePanels = ({ market, pinnedAsset }: TradePanelsProps) => {
- {['chart', 'orderbook', 'trades', 'liquidity', 'fundingPayments'] + {[ + 'chart', + 'orderbook', + 'trades', + 'liquidity', + 'fundingPayments', + 'funding', + ] // filter to control available views for the current market // e.g. only perpetuals should get the funding views .filter((_key) => { @@ -163,9 +170,12 @@ const ViewButton = ({ onClick: () => void; }) => { const label = useViewLabel(view); - const className = classNames('py-2 px-4 min-w-[100px] capitalize text-sm', { - 'bg-vega-clight-500 dark:bg-vega-cdark-500': isActive, - }); + const className = classNames( + 'py-2 px-4 capitalize text-sm whitespace-nowrap', + { + 'bg-vega-clight-500 dark:bg-vega-cdark-500': isActive, + } + ); return ( } > { setOpenPrice(x); }} trigger={ - + } > {data && ( @@ -104,11 +117,11 @@ export const MobileMarketHeader = () => { ); }; -export interface PopoverProps extends PopoverPrimitive.PopoverProps { +interface PopoverProps extends PopoverPrimitive.PopoverProps { trigger: React.ReactNode | string; } -export const FullScreenPopover = ({ +const FullScreenPopover = ({ trigger, children, open, @@ -116,7 +129,7 @@ export const FullScreenPopover = ({ }: PopoverProps) => { return ( - + {trigger} diff --git a/apps/trading/e2e/tests/market_lifecycle/test_market_lifecycle.py b/apps/trading/e2e/tests/market_lifecycle/test_market_lifecycle.py index 7df845583..dc2532e0b 100644 --- a/apps/trading/e2e/tests/market_lifecycle/test_market_lifecycle.py +++ b/apps/trading/e2e/tests/market_lifecycle/test_market_lifecycle.py @@ -35,9 +35,9 @@ def test_market_lifecycle(proposed_market, vega: VegaServiceNull, page: Page): # 6002-MDET-003 expect(page.get_by_test_id("market-price")).to_have_text("Mark Price0.00") # 6002-MDET-004 - expect(page.get_by_test_id("market-change")).to_have_text("Change (24h)0.00%0.00") + expect(page.get_by_test_id("market-change")).to_have_text("Change (24h)-") # 6002-MDET-005 - expect(page.get_by_test_id("market-volume")).to_have_text("Volume (24h)- (- BTC)") + expect(page.get_by_test_id("market-volume")).to_have_text("Volume (24h)-") # 6002-MDET-008 expect(page.get_by_test_id("market-settlement-asset")).to_have_text( "Settlement assettDAI" diff --git a/libs/datagrid/src/lib/use-datagrid-events.ts b/libs/datagrid/src/lib/use-datagrid-events.ts index 842a4a137..b4ddbb5aa 100644 --- a/libs/datagrid/src/lib/use-datagrid-events.ts +++ b/libs/datagrid/src/lib/use-datagrid-events.ts @@ -7,7 +7,7 @@ import { type FirstDataRenderedEvent, type SortChangedEvent, type GridReadyEvent, - GridApi, + type GridApi, } from 'ag-grid-community'; import { useCallback, useEffect, useRef } from 'react'; diff --git a/libs/i18n/src/locales/en/markets.json b/libs/i18n/src/locales/en/markets.json index 0623dd78e..d8a161745 100644 --- a/libs/i18n/src/locales/en/markets.json +++ b/libs/i18n/src/locales/en/markets.json @@ -2,7 +2,7 @@ "{{liquidityPriceRange}} of mid price": "{{liquidityPriceRange}} of mid price", "{{probability}} probability price bounds": "{{probability}} probability price bounds", "24 hour change is unavailable at this time. The price change in the last 120 hours is:": "24 hour change is unavailable at this time. The price change in the last 120 hours is:", - "24 hour change is unavailable at this time. The volume change in the last 120 hours is {{candleVolumeValue}}": "24 hour change is unavailable at this time. The volume change in the last 120 hours is {{candleVolumeValue}}", + "24 hour change is unavailable at this time. The volume change in the last 120 hours is {{candleVolumeValue}} for a total of {{candleVolumePrice}} {{quoteUnit}}": "24 hour change is unavailable at this time. The volume change in the last 120 hours is {{candleVolumeValue}} for a total of {{candleVolumePrice}} {{quoteUnit}}", "A concept derived from traditional markets. It is a calculated value for the ‘current market price’ on a market.": "A concept derived from traditional markets. It is a calculated value for the ‘current market price’ on a market.", "A number that will be calculated by an appropriate stochastic risk model, dependent on the type of risk model used and its parameters.": "A number that will be calculated by an appropriate stochastic risk model, dependent on the type of risk model used and its parameters.", "A sliding penalty for how much an LP bond is slashed if an LP fails to reach the minimum SLA. This is a network parameter.": "A sliding penalty for how much an LP bond is slashed if an LP fails to reach the minimum SLA. This is a network parameter.", @@ -49,6 +49,9 @@ "Market": "Market", "Market data": "Market data", "Market governance": "Market governance", + "Market has not been active for 24 hours. The price change between {{start}} and {{end}} is:": "Market has not been active for 24 hours. The price change between {{start}} and {{end}} is:", + "Market has not been active for 24 hours. The volume traded between {{start}} and {{end}} is:": "Market has not been active for 24 hours. The volume traded between {{start}} and {{end}} is:", + "Market has not been active for 24 hours. The volume traded between {{start}} and {{end}} is {{candleVolumeValue}} for a total of {{candleVolumePrice}} {{quoteUnit}}": "Market has not been active for 24 hours. The volume traded between {{start}} and {{end}} is {{candleVolumeValue}} for a total of {{candleVolumePrice}} {{quoteUnit}}", "Market ID": "Market ID", "Market price": "Market price", "Market specification": "Market specification", diff --git a/libs/markets/src/lib/components/last-24h-price-change/last-24h-price-change.tsx b/libs/markets/src/lib/components/last-24h-price-change/last-24h-price-change.tsx index 828841bf4..4d1a9d4d7 100644 --- a/libs/markets/src/lib/components/last-24h-price-change/last-24h-price-change.tsx +++ b/libs/markets/src/lib/components/last-24h-price-change/last-24h-price-change.tsx @@ -1,7 +1,8 @@ +import { type ReactNode } from 'react'; import { addDecimalsFormatNumber, formatNumberPercentage, - isNumeric, + getDateTimeFormat, priceChange, priceChangePercentage, } from '@vegaprotocol/utils'; @@ -14,29 +15,57 @@ import { useT } from '../../use-t'; interface Props { marketId?: string; - decimalPlaces?: number; - initialValue?: string[]; - isHeader?: boolean; - noUpdate?: boolean; - // render prop for no price change - fallback?: React.ReactNode; + decimalPlaces: number; + fallback?: ReactNode; } export const Last24hPriceChange = ({ marketId, decimalPlaces, - initialValue, fallback, }: Props) => { const t = useT(); - const { oneDayCandles, error, fiveDaysCandles } = useCandles({ + const { oneDayCandles, fiveDaysCandles, error } = useCandles({ marketId, }); - if ( - fiveDaysCandles && - fiveDaysCandles.length > 0 && - (!oneDayCandles || oneDayCandles?.length === 0) - ) { + + const nonIdeal = fallback || {'-'}; + + if (error || !oneDayCandles || !fiveDaysCandles) { + return nonIdeal; + } + + if (fiveDaysCandles.length < 24) { + return ( + + {t( + 'Market has not been active for 24 hours. The price change between {{start}} and {{end}} is:', + { + start: getDateTimeFormat().format( + new Date(fiveDaysCandles[0].periodStart) + ), + end: getDateTimeFormat().format( + new Date( + fiveDaysCandles[fiveDaysCandles.length - 1].periodStart + ) + ), + } + )} + c.close) || []} + decimalPlaces={decimalPlaces} + /> + + } + > + {nonIdeal} + + ); + } + + if (oneDayCandles.length < 24) { return ( } > - {fallback} + {nonIdeal} ); } - if (error || !isNumeric(decimalPlaces)) { - return {fallback}; - } - - const candles = oneDayCandles?.map((c) => c.close) || initialValue || []; + const candles = oneDayCandles?.map((c) => c.close) || []; const change = priceChange(candles); const changePercentage = priceChangePercentage(candles); diff --git a/libs/markets/src/lib/components/last-24h-volume/last-24h-volume.tsx b/libs/markets/src/lib/components/last-24h-volume/last-24h-volume.tsx index 7cf631a6e..c8b1f24cd 100644 --- a/libs/markets/src/lib/components/last-24h-volume/last-24h-volume.tsx +++ b/libs/markets/src/lib/components/last-24h-volume/last-24h-volume.tsx @@ -2,6 +2,7 @@ import { calcCandleVolume, calcCandleVolumePrice } from '../../market-utils'; import { addDecimalsFormatNumber, formatNumber, + getDateTimeFormat, isNumeric, } from '@vegaprotocol/utils'; import { Tooltip } from '@vegaprotocol/ui-toolkit'; @@ -26,15 +27,17 @@ export const Last24hVolume = ({ quoteUnit, }: Props) => { const t = useT(); - const { oneDayCandles, fiveDaysCandles } = useCandles({ + const { oneDayCandles, fiveDaysCandles, error } = useCandles({ marketId, }); - if ( - fiveDaysCandles && - fiveDaysCandles.length > 0 && - (!oneDayCandles || oneDayCandles?.length === 0) - ) { + const nonIdeal = {'-'}; + + if (error || !oneDayCandles || !fiveDaysCandles) { + return nonIdeal; + } + + if (fiveDaysCandles.length < 24) { const candleVolume = calcCandleVolume(fiveDaysCandles); const candleVolumePrice = calcCandleVolumePrice( fiveDaysCandles, @@ -55,14 +58,59 @@ export const Last24hVolume = ({
{t( - '24 hour change is unavailable at this time. The volume change in the last 120 hours is {{candleVolumeValue}} ({{candleVolumePrice}} {{quoteUnit}})', + 'Market has not been active for 24 hours. The volume traded between {{start}} and {{end}} is {{candleVolumeValue}} for a total of {{candleVolumePrice}} {{quoteUnit}}', + { + start: getDateTimeFormat().format( + new Date(fiveDaysCandles[0].periodStart) + ), + end: getDateTimeFormat().format( + new Date( + fiveDaysCandles[fiveDaysCandles.length - 1].periodStart + ) + ), + candleVolumeValue, + candleVolumePrice, + quoteUnit, + } + )} + +
+ } + > + {nonIdeal} + + ); + } + + if (oneDayCandles.length < 24) { + const candleVolume = calcCandleVolume(fiveDaysCandles); + const candleVolumePrice = calcCandleVolumePrice( + fiveDaysCandles, + marketDecimals, + positionDecimalPlaces + ); + const candleVolumeValue = + candleVolume && isNumeric(positionDecimalPlaces) + ? addDecimalsFormatNumber( + candleVolume, + positionDecimalPlaces, + formatDecimals + ) + : '-'; + return ( + + + {t( + '24 hour change is unavailable at this time. The volume change in the last 120 hours is {{candleVolumeValue}} for a total of ({{candleVolumePrice}} {{quoteUnit}})', { candleVolumeValue, candleVolumePrice, quoteUnit } )}
} > - - + {nonIdeal} ); } diff --git a/libs/markets/src/lib/hooks/use-candles.spec.ts b/libs/markets/src/lib/hooks/use-candles.spec.ts index 2bbe50b80..0734c7db0 100644 --- a/libs/markets/src/lib/hooks/use-candles.spec.ts +++ b/libs/markets/src/lib/hooks/use-candles.spec.ts @@ -15,7 +15,6 @@ const mockData = [ periodStart: today.toISOString(), __typename: 'Candle', }, - null, { high: '6309988', low: '6296335', diff --git a/libs/markets/src/lib/hooks/use-candles.ts b/libs/markets/src/lib/hooks/use-candles.ts index 572036cfc..d22adc991 100644 --- a/libs/markets/src/lib/hooks/use-candles.ts +++ b/libs/markets/src/lib/hooks/use-candles.ts @@ -18,7 +18,12 @@ export const useCandles = ({ marketId }: { marketId?: string }) => { skip: !marketId, }); - const fiveDaysCandles = data?.filter(Boolean); + const fiveDaysCandles = data?.filter((c) => { + if (c.open === '' || c.close === '' || c.high === '' || c.close === '') { + return false; + } + return true; + }); const oneDayCandles = fiveDaysCandles?.filter((candle) => isCandleLessThan24hOld(candle, yesterday) diff --git a/libs/positions/src/lib/use-open-volume.ts b/libs/positions/src/lib/use-open-volume.ts index 9e83ab0bb..2d77fcd3e 100644 --- a/libs/positions/src/lib/use-open-volume.ts +++ b/libs/positions/src/lib/use-open-volume.ts @@ -1,7 +1,7 @@ import { useState, useCallback } from 'react'; import { - OpenVolumeData, openVolumeDataProvider, + type OpenVolumeData, } from './positions-data-providers'; import { useDataProvider } from '@vegaprotocol/data-provider';