chore(2220): partial live update of market dropdown (#2263)
* chore: partial live update of market dropdown * chore: partial live update of market dropdown * chore: partial live update of market dropdown - some refactor * chore: partial live update of market dropdown - some refactor * chore: partial live update of market dropdown - fix lint error * chore: partial live update of market dropdown - fix failing tests * chore: partial live update of market dropdown - fix failing tests
This commit is contained in:
parent
03f659ebb3
commit
b67bc33c49
@ -159,10 +159,26 @@ export const TradeMarketHeader = ({
|
||||
>
|
||||
<ExpiryLabel market={market} />
|
||||
</HeaderStat>
|
||||
<MarketMarkPrice marketId={market?.id} />
|
||||
<Last24hPriceChange marketId={market?.id} />
|
||||
<Last24hVolume marketId={market?.id} />
|
||||
<MarketTradingModeComponent marketId={market?.id} onSelect={onSelect} />
|
||||
<MarketMarkPrice
|
||||
marketId={market?.id}
|
||||
decimalPlaces={market?.decimalPlaces}
|
||||
isHeader
|
||||
/>
|
||||
<Last24hPriceChange
|
||||
marketId={market?.id}
|
||||
decimalPlaces={market?.decimalPlaces}
|
||||
isHeader
|
||||
/>
|
||||
<Last24hVolume
|
||||
marketId={market?.id}
|
||||
positionDecimalPlaces={market?.positionDecimalPlaces}
|
||||
isHeader
|
||||
/>
|
||||
<MarketTradingModeComponent
|
||||
marketId={market?.id}
|
||||
onSelect={onSelect}
|
||||
isHeader
|
||||
/>
|
||||
{asset ? (
|
||||
<HeaderStat
|
||||
heading={t('Settlement asset')}
|
||||
|
@ -1,22 +1,37 @@
|
||||
import { useCallback, useMemo, useRef, useState } from 'react';
|
||||
import throttle from 'lodash/throttle';
|
||||
import { t, useDataProvider, useYesterday } from '@vegaprotocol/react-helpers';
|
||||
import {
|
||||
isNumeric,
|
||||
t,
|
||||
useDataProvider,
|
||||
useYesterday,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import { PriceCellChange } from '@vegaprotocol/ui-toolkit';
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
import type { CandleClose } from '@vegaprotocol/types';
|
||||
import type {
|
||||
SingleMarketFieldsFragment,
|
||||
Candle,
|
||||
} from '@vegaprotocol/market-list';
|
||||
import {
|
||||
marketCandlesProvider,
|
||||
marketProvider,
|
||||
} from '@vegaprotocol/market-list';
|
||||
import type { Candle } from '@vegaprotocol/market-list';
|
||||
import { marketCandlesProvider } from '@vegaprotocol/market-list';
|
||||
import { HeaderStat } from '../header';
|
||||
import * as constants from '../constants';
|
||||
|
||||
export const Last24hPriceChange = ({ marketId }: { marketId?: string }) => {
|
||||
const [candlesClose, setCandlesClose] = useState<string[]>([]);
|
||||
interface Props {
|
||||
marketId?: string;
|
||||
decimalPlaces?: number;
|
||||
initialValue?: string[];
|
||||
isHeader?: boolean;
|
||||
noUpdate?: boolean;
|
||||
}
|
||||
|
||||
export const Last24hPriceChange = ({
|
||||
marketId,
|
||||
decimalPlaces,
|
||||
initialValue,
|
||||
isHeader = false,
|
||||
noUpdate = false,
|
||||
}: Props) => {
|
||||
const [candlesClose, setCandlesClose] = useState<string[]>(
|
||||
initialValue || []
|
||||
);
|
||||
const yesterday = useYesterday();
|
||||
// Cache timestamp for yesterday to prevent full unmount of market page when
|
||||
// a rerender occurs
|
||||
@ -24,13 +39,6 @@ export const Last24hPriceChange = ({ marketId }: { marketId?: string }) => {
|
||||
return new Date(yesterday).toISOString();
|
||||
}, [yesterday]);
|
||||
|
||||
const marketVariables = useMemo(
|
||||
() => ({
|
||||
marketId: marketId,
|
||||
}),
|
||||
[marketId]
|
||||
);
|
||||
|
||||
const variables = useMemo(
|
||||
() => ({
|
||||
marketId: marketId,
|
||||
@ -40,18 +48,14 @@ export const Last24hPriceChange = ({ marketId }: { marketId?: string }) => {
|
||||
[marketId, yTimestamp]
|
||||
);
|
||||
|
||||
const { data, error } = useDataProvider<SingleMarketFieldsFragment, never>({
|
||||
dataProvider: marketProvider,
|
||||
variables: marketVariables,
|
||||
skip: !marketId,
|
||||
});
|
||||
|
||||
const throttledSetCandles = useRef(
|
||||
throttle((data: Candle[]) => {
|
||||
const candlesClose: string[] = data
|
||||
.map((candle) => candle?.close)
|
||||
.filter((c): c is CandleClose => c !== null);
|
||||
setCandlesClose(candlesClose);
|
||||
if (!noUpdate) {
|
||||
const candlesClose: string[] = data
|
||||
.map((candle) => candle?.close)
|
||||
.filter((c): c is CandleClose => c !== null);
|
||||
setCandlesClose(candlesClose);
|
||||
}
|
||||
}, constants.DEBOUNCE_UPDATE_TIME)
|
||||
).current;
|
||||
const update = useCallback(
|
||||
@ -64,23 +68,27 @@ export const Last24hPriceChange = ({ marketId }: { marketId?: string }) => {
|
||||
[throttledSetCandles]
|
||||
);
|
||||
|
||||
useDataProvider<Candle[], Candle>({
|
||||
const { error } = useDataProvider<Candle[], Candle>({
|
||||
dataProvider: marketCandlesProvider,
|
||||
update,
|
||||
variables,
|
||||
skip: !marketId || !data,
|
||||
skip: noUpdate || !marketId,
|
||||
});
|
||||
|
||||
return (
|
||||
const content = useMemo(() => {
|
||||
if (error || !isNumeric(decimalPlaces)) {
|
||||
return <>-</>;
|
||||
}
|
||||
return (
|
||||
<PriceCellChange candles={candlesClose} decimalPlaces={decimalPlaces} />
|
||||
);
|
||||
}, [candlesClose, decimalPlaces, error]);
|
||||
|
||||
return isHeader ? (
|
||||
<HeaderStat heading={t('Change (24h)')} testId="market-change">
|
||||
{!error && data?.decimalPlaces ? (
|
||||
<PriceCellChange
|
||||
candles={candlesClose}
|
||||
decimalPlaces={data.decimalPlaces}
|
||||
/>
|
||||
) : (
|
||||
'-'
|
||||
)}
|
||||
{content}
|
||||
</HeaderStat>
|
||||
) : (
|
||||
content
|
||||
);
|
||||
};
|
||||
|
@ -1,27 +1,37 @@
|
||||
import {
|
||||
calcCandleVolume,
|
||||
marketCandlesProvider,
|
||||
marketProvider,
|
||||
} from '@vegaprotocol/market-list';
|
||||
import {
|
||||
addDecimalsFormatNumber,
|
||||
t,
|
||||
useDataProvider,
|
||||
useYesterday,
|
||||
isNumeric,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
import throttle from 'lodash/throttle';
|
||||
import { useCallback, useMemo, useRef, useState } from 'react';
|
||||
|
||||
import * as constants from '../constants';
|
||||
import { HeaderStat } from '../header';
|
||||
import type { Candle } from '@vegaprotocol/market-list';
|
||||
|
||||
import type {
|
||||
SingleMarketFieldsFragment,
|
||||
Candle,
|
||||
} from '@vegaprotocol/market-list';
|
||||
export const Last24hVolume = ({ marketId }: { marketId?: string }) => {
|
||||
const [candleVolume, setCandleVolume] = useState<string>();
|
||||
interface Props {
|
||||
marketId?: string;
|
||||
positionDecimalPlaces?: number;
|
||||
noUpdate?: boolean;
|
||||
isHeader?: boolean;
|
||||
initialValue?: string;
|
||||
}
|
||||
|
||||
export const Last24hVolume = ({
|
||||
marketId,
|
||||
positionDecimalPlaces,
|
||||
noUpdate = false,
|
||||
isHeader = false,
|
||||
initialValue,
|
||||
}: Props) => {
|
||||
const [candleVolume, setCandleVolume] = useState<string>(initialValue || '');
|
||||
const yesterday = useYesterday();
|
||||
// Cache timestamp for yesterday to prevent full unmount of market page when
|
||||
// a rerender occurs
|
||||
@ -29,13 +39,6 @@ export const Last24hVolume = ({ marketId }: { marketId?: string }) => {
|
||||
return new Date(yesterday).toISOString();
|
||||
}, [yesterday]);
|
||||
|
||||
const marketVariables = useMemo(
|
||||
() => ({
|
||||
marketId: marketId,
|
||||
}),
|
||||
[marketId]
|
||||
);
|
||||
|
||||
const variables = useMemo(
|
||||
() => ({
|
||||
marketId: marketId,
|
||||
@ -45,15 +48,9 @@ export const Last24hVolume = ({ marketId }: { marketId?: string }) => {
|
||||
[marketId, yTimestamp]
|
||||
);
|
||||
|
||||
const { data, error } = useDataProvider<SingleMarketFieldsFragment, never>({
|
||||
dataProvider: marketProvider,
|
||||
variables: marketVariables,
|
||||
skip: !marketId,
|
||||
});
|
||||
|
||||
const throttledSetCandles = useRef(
|
||||
throttle((data: Candle[]) => {
|
||||
setCandleVolume(calcCandleVolume(data));
|
||||
noUpdate || setCandleVolume(calcCandleVolume(data) || '');
|
||||
}, constants.DEBOUNCE_UPDATE_TIME)
|
||||
).current;
|
||||
const update = useCallback(
|
||||
@ -66,26 +63,40 @@ export const Last24hVolume = ({ marketId }: { marketId?: string }) => {
|
||||
[throttledSetCandles]
|
||||
);
|
||||
|
||||
useDataProvider<Candle[], Candle>({
|
||||
const { error } = useDataProvider<Candle[], Candle>({
|
||||
dataProvider: marketCandlesProvider,
|
||||
update,
|
||||
variables,
|
||||
skip: !marketId || !data,
|
||||
skip: noUpdate || !marketId,
|
||||
});
|
||||
|
||||
return (
|
||||
const formatDecimals = isHeader ? positionDecimalPlaces || 0 : 2;
|
||||
const content = useMemo(() => {
|
||||
return (
|
||||
<>
|
||||
{!error && candleVolume && isNumeric(positionDecimalPlaces)
|
||||
? addDecimalsFormatNumber(
|
||||
candleVolume,
|
||||
positionDecimalPlaces,
|
||||
formatDecimals
|
||||
)
|
||||
: '-'}
|
||||
</>
|
||||
);
|
||||
}, [error, candleVolume, positionDecimalPlaces, formatDecimals]);
|
||||
return isHeader ? (
|
||||
<HeaderStat
|
||||
heading={t('Volume (24h)')}
|
||||
testId="market-volume"
|
||||
description={
|
||||
error && candleVolume && data?.positionDecimalPlaces
|
||||
error && candleVolume && positionDecimalPlaces
|
||||
? t('The total amount of assets traded in the last 24 hours.')
|
||||
: null
|
||||
}
|
||||
>
|
||||
{!error && candleVolume && data?.positionDecimalPlaces
|
||||
? addDecimalsFormatNumber(candleVolume, data.positionDecimalPlaces)
|
||||
: '-'}
|
||||
{content}
|
||||
</HeaderStat>
|
||||
) : (
|
||||
content
|
||||
);
|
||||
};
|
||||
|
@ -3,57 +3,82 @@ import throttle from 'lodash/throttle';
|
||||
import {
|
||||
addDecimalsFormatNumber,
|
||||
t,
|
||||
PriceCell,
|
||||
useDataProvider,
|
||||
isNumeric,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import type {
|
||||
MarketData,
|
||||
MarketDataUpdateFieldsFragment,
|
||||
SingleMarketFieldsFragment,
|
||||
} from '@vegaprotocol/market-list';
|
||||
import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list';
|
||||
import { marketDataProvider } from '@vegaprotocol/market-list';
|
||||
import { HeaderStat } from '../header';
|
||||
import * as constants from '../constants';
|
||||
|
||||
export const MarketMarkPrice = ({ marketId }: { marketId?: string }) => {
|
||||
const [marketPrice, setMarketPrice] = useState<string | null>(null);
|
||||
interface Props {
|
||||
marketId?: string;
|
||||
decimalPlaces?: number;
|
||||
isHeader?: boolean;
|
||||
noUpdate?: boolean;
|
||||
initialValue?: string;
|
||||
}
|
||||
|
||||
export const MarketMarkPrice = ({
|
||||
marketId,
|
||||
decimalPlaces,
|
||||
initialValue,
|
||||
isHeader = false,
|
||||
noUpdate = false,
|
||||
}: Props) => {
|
||||
const [marketPrice, setMarketPrice] = useState<string | null>(
|
||||
initialValue || null
|
||||
);
|
||||
const variables = useMemo(
|
||||
() => ({
|
||||
marketId: marketId,
|
||||
}),
|
||||
[marketId]
|
||||
);
|
||||
const { data } = useDataProvider<SingleMarketFieldsFragment, never>({
|
||||
dataProvider: marketProvider,
|
||||
variables,
|
||||
skip: !marketId,
|
||||
});
|
||||
|
||||
const throttledSetMarketPrice = useRef(
|
||||
throttle((price: string) => {
|
||||
setMarketPrice(price);
|
||||
noUpdate || setMarketPrice(price);
|
||||
}, constants.DEBOUNCE_UPDATE_TIME)
|
||||
).current;
|
||||
const update = useCallback(
|
||||
({ data: marketData }: { data: MarketData | null }) => {
|
||||
throttledSetMarketPrice(
|
||||
marketData?.markPrice && data?.decimalPlaces
|
||||
? addDecimalsFormatNumber(marketData.markPrice, data.decimalPlaces)
|
||||
: '-'
|
||||
);
|
||||
throttledSetMarketPrice(marketData?.markPrice || '');
|
||||
return true;
|
||||
},
|
||||
[data?.decimalPlaces, throttledSetMarketPrice]
|
||||
[throttledSetMarketPrice]
|
||||
);
|
||||
|
||||
useDataProvider<MarketData, MarketDataUpdateFieldsFragment>({
|
||||
dataProvider: marketDataProvider,
|
||||
update,
|
||||
variables,
|
||||
skip: !marketId || !data,
|
||||
skip: noUpdate || !marketId,
|
||||
});
|
||||
|
||||
return (
|
||||
const content = useMemo(() => {
|
||||
if (!marketPrice || !isNumeric(decimalPlaces)) {
|
||||
return <>-</>;
|
||||
}
|
||||
return isHeader ? (
|
||||
<div>{addDecimalsFormatNumber(marketPrice, decimalPlaces)}</div>
|
||||
) : (
|
||||
<PriceCell
|
||||
value={Number(marketPrice)}
|
||||
valueFormatted={addDecimalsFormatNumber(marketPrice, decimalPlaces, 2)}
|
||||
/>
|
||||
);
|
||||
}, [marketPrice, decimalPlaces, isHeader]);
|
||||
|
||||
return isHeader ? (
|
||||
<HeaderStat heading={t('Price')} testId="market-price">
|
||||
<div>{marketPrice}</div>
|
||||
{content}
|
||||
</HeaderStat>
|
||||
) : (
|
||||
content
|
||||
);
|
||||
};
|
||||
|
@ -15,16 +15,30 @@ import type {
|
||||
} from '@vegaprotocol/market-list';
|
||||
import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list';
|
||||
import { HeaderStat } from '../header';
|
||||
import { Tooltip } from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
interface Props {
|
||||
marketId?: string;
|
||||
onSelect?: (marketId: string) => void;
|
||||
isHeader?: boolean;
|
||||
noUpdate?: boolean;
|
||||
initialMode?: Types.MarketTradingMode;
|
||||
initialTrigger?: Types.AuctionTrigger;
|
||||
}
|
||||
|
||||
export const MarketTradingModeComponent = ({ marketId, onSelect }: Props) => {
|
||||
export const MarketTradingModeComponent = ({
|
||||
marketId,
|
||||
onSelect,
|
||||
isHeader = false,
|
||||
noUpdate = false,
|
||||
initialMode,
|
||||
initialTrigger,
|
||||
}: Props) => {
|
||||
const [tradingMode, setTradingMode] =
|
||||
useState<Types.MarketTradingMode | null>(null);
|
||||
const [trigger, setTrigger] = useState<Types.AuctionTrigger | null>(null);
|
||||
useState<Types.MarketTradingMode | null>(initialMode || null);
|
||||
const [trigger, setTrigger] = useState<Types.AuctionTrigger | null>(
|
||||
initialTrigger || null
|
||||
);
|
||||
const [market, setMarket] = useState<MarketDealTicket | null>(null);
|
||||
const variables = useMemo(
|
||||
() => ({
|
||||
@ -41,7 +55,7 @@ export const MarketTradingModeComponent = ({ marketId, onSelect }: Props) => {
|
||||
|
||||
const update = useCallback(
|
||||
({ data: marketData }: { data: MarketData | null }) => {
|
||||
if (marketData) {
|
||||
if (!noUpdate && marketData) {
|
||||
setTradingMode(marketData.marketTradingMode);
|
||||
setTrigger(marketData.trigger);
|
||||
setMarket({
|
||||
@ -51,24 +65,25 @@ export const MarketTradingModeComponent = ({ marketId, onSelect }: Props) => {
|
||||
}
|
||||
return true;
|
||||
},
|
||||
[data]
|
||||
[noUpdate, data]
|
||||
);
|
||||
|
||||
useDataProvider<MarketData, MarketDataUpdateFieldsFragment>({
|
||||
dataProvider: marketDataProvider,
|
||||
update,
|
||||
variables,
|
||||
skip: !marketId || !data,
|
||||
skip: noUpdate || !marketId || !data,
|
||||
});
|
||||
|
||||
const content =
|
||||
tradingMode === Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION &&
|
||||
(tradingMode === Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION &&
|
||||
trigger &&
|
||||
trigger !== Schema.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED
|
||||
? `${MarketTradingModeMapping[tradingMode]} - ${AuctionTriggerMapping[trigger]}`
|
||||
: MarketTradingModeMapping[tradingMode as Types.MarketTradingMode];
|
||||
: MarketTradingModeMapping[tradingMode as Types.MarketTradingMode]) ||
|
||||
'-';
|
||||
|
||||
return (
|
||||
return isHeader ? (
|
||||
<HeaderStat
|
||||
heading={t('Trading mode')}
|
||||
description={
|
||||
@ -82,7 +97,18 @@ export const MarketTradingModeComponent = ({ marketId, onSelect }: Props) => {
|
||||
}
|
||||
testId="market-trading-mode"
|
||||
>
|
||||
<div>{content || '-'}</div>
|
||||
<div>{content}</div>
|
||||
</HeaderStat>
|
||||
) : (
|
||||
<Tooltip
|
||||
description={
|
||||
tradingMode &&
|
||||
trigger && (
|
||||
<TradingModeTooltip tradingMode={tradingMode} trigger={trigger} />
|
||||
)
|
||||
}
|
||||
>
|
||||
<span>{content}</span>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
@ -1,5 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { TradingModeTooltip } from '@vegaprotocol/deal-ticket';
|
||||
import { FeesCell } from '@vegaprotocol/market-info';
|
||||
import {
|
||||
calcCandleHigh,
|
||||
@ -12,56 +10,23 @@ import {
|
||||
signedNumberCssClass,
|
||||
t,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import {
|
||||
AuctionTriggerMapping,
|
||||
MarketTradingModeMapping,
|
||||
Schema,
|
||||
} from '@vegaprotocol/types';
|
||||
import {
|
||||
Link as UILink,
|
||||
PriceCellChange,
|
||||
Sparkline,
|
||||
Tooltip,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { Link as UILink, Sparkline, Tooltip } from '@vegaprotocol/ui-toolkit';
|
||||
import isNil from 'lodash/isNil';
|
||||
|
||||
import type { CandleClose } from '@vegaprotocol/types';
|
||||
import type {
|
||||
MarketWithData,
|
||||
MarketWithCandles,
|
||||
} from '@vegaprotocol/market-list';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { MarketMarkPrice } from '../market-mark-price';
|
||||
import { Last24hPriceChange } from '../last-24h-price-change';
|
||||
import { MarketTradingModeComponent } from '../market-trading-mode';
|
||||
import { Last24hVolume } from '../last-24h-volume';
|
||||
|
||||
type Market = MarketWithData & MarketWithCandles;
|
||||
|
||||
export const cellClassNames = 'py-1 first:text-left text-right';
|
||||
|
||||
const TradingMode = ({ market }: { market: Market }) => {
|
||||
return (
|
||||
<Tooltip
|
||||
description={
|
||||
market && (
|
||||
<TradingModeTooltip
|
||||
tradingMode={market.tradingMode}
|
||||
trigger={market.data?.trigger || null}
|
||||
/>
|
||||
)
|
||||
}
|
||||
>
|
||||
<span>
|
||||
{market.tradingMode ===
|
||||
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION &&
|
||||
market.data?.trigger &&
|
||||
market.data.trigger !==
|
||||
Schema.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED
|
||||
? `${MarketTradingModeMapping[market.tradingMode]}
|
||||
- ${AuctionTriggerMapping[market.data.trigger]}`
|
||||
: MarketTradingModeMapping[market.tradingMode]}
|
||||
</span>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
const FeesInfo = () => {
|
||||
return (
|
||||
<Tooltip
|
||||
@ -205,7 +170,8 @@ export type OnCellClickHandler = (
|
||||
export const columns = (
|
||||
market: Market,
|
||||
onSelect: (id: string) => void,
|
||||
onCellClick: OnCellClickHandler
|
||||
onCellClick: OnCellClickHandler,
|
||||
activeMarketId?: string | null
|
||||
) => {
|
||||
const candlesClose = market.candles
|
||||
?.map((candle) => candle?.close)
|
||||
@ -221,6 +187,7 @@ export const columns = (
|
||||
return onSelect(id);
|
||||
}
|
||||
};
|
||||
const noUpdate = !activeMarketId || market.id !== activeMarketId;
|
||||
const selectMarketColumns: Column[] = [
|
||||
{
|
||||
kind: ColumnKind.Market,
|
||||
@ -248,27 +215,25 @@ export const columns = (
|
||||
},
|
||||
{
|
||||
kind: ColumnKind.LastPrice,
|
||||
value: market.data?.markPrice ? (
|
||||
<PriceCell
|
||||
value={Number(market.data?.markPrice)}
|
||||
valueFormatted={addDecimalsFormatNumber(
|
||||
market.data?.markPrice.toString(),
|
||||
market.decimalPlaces,
|
||||
2
|
||||
)}
|
||||
value: (
|
||||
<MarketMarkPrice
|
||||
marketId={market.id}
|
||||
decimalPlaces={market?.decimalPlaces}
|
||||
initialValue={market.data?.markPrice.toString()}
|
||||
noUpdate={noUpdate}
|
||||
/>
|
||||
) : (
|
||||
'-'
|
||||
),
|
||||
className: cellClassNames,
|
||||
onlyOnDetailed: false,
|
||||
},
|
||||
{
|
||||
kind: ColumnKind.Change24,
|
||||
value: candlesClose && (
|
||||
<PriceCellChange
|
||||
candles={candlesClose}
|
||||
decimalPlaces={market.decimalPlaces}
|
||||
value: (
|
||||
<Last24hPriceChange
|
||||
marketId={market.id}
|
||||
decimalPlaces={market?.decimalPlaces}
|
||||
noUpdate={noUpdate}
|
||||
initialValue={candlesClose}
|
||||
/>
|
||||
),
|
||||
className: cellClassNames,
|
||||
@ -345,20 +310,28 @@ export const columns = (
|
||||
},
|
||||
{
|
||||
kind: ColumnKind.Volume,
|
||||
value: candleVolume
|
||||
? addDecimalsFormatNumber(
|
||||
candleVolume.toString(),
|
||||
market.positionDecimalPlaces,
|
||||
2
|
||||
)
|
||||
: '-',
|
||||
value: (
|
||||
<Last24hVolume
|
||||
marketId={market.id}
|
||||
positionDecimalPlaces={market.positionDecimalPlaces}
|
||||
initialValue={candleVolume}
|
||||
noUpdate={noUpdate}
|
||||
/>
|
||||
),
|
||||
className: `${cellClassNames} hidden lg:table-cell font-mono`,
|
||||
onlyOnDetailed: true,
|
||||
dataTestId: 'market-volume',
|
||||
},
|
||||
{
|
||||
kind: ColumnKind.TradingMode,
|
||||
value: <TradingMode market={market} />,
|
||||
value: (
|
||||
<MarketTradingModeComponent
|
||||
marketId={market?.id}
|
||||
noUpdate={noUpdate}
|
||||
initialMode={market.tradingMode}
|
||||
initialTrigger={market.data?.trigger}
|
||||
/>
|
||||
),
|
||||
className: `${cellClassNames} hidden lg:table-cell`,
|
||||
onlyOnDetailed: true,
|
||||
dataTestId: 'trading-mode-col',
|
||||
@ -385,7 +358,8 @@ export const columnsPositionMarkets = (
|
||||
market: Market,
|
||||
onSelect: (id: string) => void,
|
||||
openVolume?: string,
|
||||
onCellClick?: OnCellClickHandler
|
||||
onCellClick?: OnCellClickHandler,
|
||||
activeMarketId?: string | null
|
||||
) => {
|
||||
const candlesClose = market.candles
|
||||
?.map((candle) => candle?.close)
|
||||
@ -401,6 +375,7 @@ export const columnsPositionMarkets = (
|
||||
}
|
||||
};
|
||||
const candleVolume = market.candles && calcCandleVolume(market.candles);
|
||||
const noUpdate = !activeMarketId || market.id !== activeMarketId;
|
||||
const selectMarketColumns: Column[] = [
|
||||
{
|
||||
kind: ColumnKind.Market,
|
||||
@ -428,27 +403,25 @@ export const columnsPositionMarkets = (
|
||||
},
|
||||
{
|
||||
kind: ColumnKind.LastPrice,
|
||||
value: market.data?.markPrice ? (
|
||||
<PriceCell
|
||||
value={Number(market.data.markPrice)}
|
||||
valueFormatted={addDecimalsFormatNumber(
|
||||
market.data.markPrice.toString(),
|
||||
market.decimalPlaces,
|
||||
2
|
||||
)}
|
||||
value: (
|
||||
<MarketMarkPrice
|
||||
marketId={market.id}
|
||||
decimalPlaces={market?.decimalPlaces}
|
||||
initialValue={market.data?.markPrice.toString()}
|
||||
noUpdate={noUpdate}
|
||||
/>
|
||||
) : (
|
||||
'-'
|
||||
),
|
||||
className: cellClassNames,
|
||||
onlyOnDetailed: false,
|
||||
},
|
||||
{
|
||||
kind: ColumnKind.Change24,
|
||||
value: candlesClose && (
|
||||
<PriceCellChange
|
||||
candles={candlesClose}
|
||||
decimalPlaces={market.decimalPlaces}
|
||||
value: (
|
||||
<Last24hPriceChange
|
||||
marketId={market.id}
|
||||
decimalPlaces={market?.decimalPlaces}
|
||||
noUpdate={noUpdate}
|
||||
initialValue={candlesClose}
|
||||
/>
|
||||
),
|
||||
className: cellClassNames,
|
||||
@ -525,20 +498,28 @@ export const columnsPositionMarkets = (
|
||||
},
|
||||
{
|
||||
kind: ColumnKind.Volume,
|
||||
value: candleVolume
|
||||
? addDecimalsFormatNumber(
|
||||
candleVolume.toString(),
|
||||
market.positionDecimalPlaces,
|
||||
2
|
||||
)
|
||||
: '-',
|
||||
value: (
|
||||
<Last24hVolume
|
||||
marketId={market.id}
|
||||
positionDecimalPlaces={market.positionDecimalPlaces}
|
||||
initialValue={candleVolume}
|
||||
noUpdate={noUpdate}
|
||||
/>
|
||||
),
|
||||
className: `${cellClassNames} hidden lg:table-cell font-mono`,
|
||||
onlyOnDetailed: true,
|
||||
dataTestId: 'market-volume',
|
||||
},
|
||||
{
|
||||
kind: ColumnKind.TradingMode,
|
||||
value: <TradingMode market={market} />,
|
||||
value: (
|
||||
<MarketTradingModeComponent
|
||||
marketId={market?.id}
|
||||
noUpdate={noUpdate}
|
||||
initialMode={market.tradingMode}
|
||||
initialTrigger={market.data?.trigger}
|
||||
/>
|
||||
),
|
||||
className: `${cellClassNames} hidden lg:table-cell`,
|
||||
onlyOnDetailed: true,
|
||||
dataTestId: 'trading-mode-col',
|
||||
|
@ -12,6 +12,7 @@ import type {
|
||||
MarketData,
|
||||
} from '@vegaprotocol/market-list';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
type Market = MarketWithCandles & MarketWithData;
|
||||
|
||||
type PartialMarket = Partial<
|
||||
@ -91,6 +92,7 @@ const MARKET_B: PartialMarket = {
|
||||
__typename: 'Market',
|
||||
id: '2',
|
||||
decimalPlaces: 2,
|
||||
positionDecimalPlaces: 0,
|
||||
tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
tradableInstrument: {
|
||||
__typename: 'TradableInstrument',
|
||||
@ -158,7 +160,8 @@ describe('SelectMarket', () => {
|
||||
onCellClick={onCellClick}
|
||||
onSelect={onSelect}
|
||||
/>
|
||||
</MemoryRouter>
|
||||
</MemoryRouter>,
|
||||
{ wrapper: MockedProvider }
|
||||
);
|
||||
expect(screen.getByText('ABCDEF')).toBeTruthy(); // name
|
||||
expect(screen.getByText('25.00%')).toBeTruthy(); // price change
|
||||
@ -178,7 +181,8 @@ describe('SelectMarket', () => {
|
||||
onCellClick={onCellClick}
|
||||
onSelect={onSelect}
|
||||
/>
|
||||
</MemoryRouter>
|
||||
</MemoryRouter>,
|
||||
{ wrapper: MockedProvider }
|
||||
);
|
||||
fireEvent.click(screen.getAllByTestId(`market-link-1`)[0]);
|
||||
expect(onSelect).toHaveBeenCalledWith('1');
|
||||
|
@ -11,7 +11,7 @@ import {
|
||||
Popover,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import {
|
||||
columnHeaders,
|
||||
@ -38,6 +38,7 @@ import {
|
||||
TOKEN_NEW_MARKET_PROPOSAL,
|
||||
useLinks,
|
||||
} from '@vegaprotocol/environment';
|
||||
import { useGlobalStore } from '../../stores';
|
||||
|
||||
type Market = MarketWithCandles & MarketWithData;
|
||||
|
||||
@ -87,14 +88,17 @@ export const SelectAllMarketsTableBody = ({
|
||||
positions,
|
||||
onSelect,
|
||||
onCellClick,
|
||||
activeMarketId,
|
||||
headers = columnHeaders,
|
||||
tableColumns = (market) => columns(market, onSelect, onCellClick),
|
||||
tableColumns = (market) =>
|
||||
columns(market, onSelect, onCellClick, activeMarketId),
|
||||
}: {
|
||||
markets?: Market[] | null;
|
||||
positions?: PositionFieldsFragment[];
|
||||
title?: string;
|
||||
onSelect: (id: string) => void;
|
||||
onCellClick: OnCellClickHandler;
|
||||
activeMarketId?: string | null;
|
||||
headers?: Column[];
|
||||
tableColumns?: (market: Market, openVolume?: string) => Column[];
|
||||
}) => {
|
||||
@ -112,7 +116,7 @@ export const SelectAllMarketsTableBody = ({
|
||||
<SelectMarketTableRow
|
||||
marketId={market.id}
|
||||
key={i}
|
||||
detailed={true}
|
||||
detailed
|
||||
onSelect={onSelect}
|
||||
columns={tableColumns(
|
||||
market,
|
||||
@ -143,23 +147,35 @@ export const SelectMarketPopover = ({
|
||||
onSelect: (id: string) => void;
|
||||
onCellClick: OnCellClickHandler;
|
||||
}) => {
|
||||
const { activeMarketId } = useGlobalStore((store) => ({
|
||||
activeMarketId: store.marketId,
|
||||
}));
|
||||
const triggerClasses =
|
||||
'sm:text-lg md:text-xl lg:text-2xl flex items-center gap-2 whitespace-nowrap hover:text-neutral-500 dark:hover:text-neutral-300 mt-1';
|
||||
const { pubKey } = useVegaWallet();
|
||||
const [open, setOpen] = useState(false);
|
||||
const { data, loading: marketsLoading } = useMarketList();
|
||||
const {
|
||||
data,
|
||||
loading: marketsLoading,
|
||||
reload: marketListReload,
|
||||
} = useMarketList();
|
||||
const variables = useMemo(() => ({ partyId: pubKey }), [pubKey]);
|
||||
const { data: party, loading: positionsLoading } = useDataProvider({
|
||||
const {
|
||||
data: party,
|
||||
loading: positionsLoading,
|
||||
reload,
|
||||
} = useDataProvider({
|
||||
dataProvider: positionsDataProvider,
|
||||
skipUpdates: true,
|
||||
variables,
|
||||
skip: !pubKey,
|
||||
});
|
||||
|
||||
const onSelectMarket = (marketId: string) => {
|
||||
onSelect(marketId);
|
||||
setOpen(false);
|
||||
};
|
||||
const onSelectMarket = useCallback(
|
||||
(marketId: string) => {
|
||||
onSelect(marketId);
|
||||
setOpen(false);
|
||||
},
|
||||
[onSelect]
|
||||
);
|
||||
|
||||
const iconClass = open ? 'rotate-180' : '';
|
||||
const markets = useMemo(
|
||||
@ -172,6 +188,13 @@ export const SelectMarketPopover = ({
|
||||
[data, party]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
reload();
|
||||
marketListReload();
|
||||
}
|
||||
}, [open, marketListReload, reload]);
|
||||
|
||||
return (
|
||||
<Popover
|
||||
open={open}
|
||||
@ -210,7 +233,8 @@ export const SelectMarketPopover = ({
|
||||
market,
|
||||
onSelectMarket,
|
||||
openVolume,
|
||||
onCellClick
|
||||
onCellClick,
|
||||
activeMarketId
|
||||
)
|
||||
}
|
||||
/>
|
||||
@ -221,6 +245,7 @@ export const SelectMarketPopover = ({
|
||||
markets={data}
|
||||
onSelect={onSelectMarket}
|
||||
onCellClick={onCellClick}
|
||||
activeMarketId={activeMarketId}
|
||||
/>
|
||||
</table>
|
||||
)}
|
||||
|
@ -5,7 +5,6 @@ import { LedgerTable } from './ledger-table';
|
||||
// '3ac37999796c2be3546e0c1d87daa8ec7e99d8c423969be44c2f63256c415004'
|
||||
type LedgerManagerProps = { partyId: string };
|
||||
export const LedgerManager = ({ partyId }: LedgerManagerProps) => {
|
||||
console.log('partyId', partyId);
|
||||
const { data, error, loading } = useLedgerEntriesDataProvider(partyId);
|
||||
|
||||
return (
|
||||
|
@ -98,15 +98,15 @@ export const useMarketList = () => {
|
||||
interval: Schema.Interval.INTERVAL_I1H,
|
||||
};
|
||||
}, [yesterday]);
|
||||
const { data, loading, error } = useDataProvider({
|
||||
const { data, loading, error, reload } = useDataProvider({
|
||||
dataProvider: marketListProvider,
|
||||
variables,
|
||||
skipUpdates: true,
|
||||
});
|
||||
|
||||
return {
|
||||
data,
|
||||
loading,
|
||||
error,
|
||||
reload,
|
||||
};
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user