feat(trading): market list snags and disable column removal (#5324)
Co-authored-by: bwallacee <ben@vega.xyz>
This commit is contained in:
parent
1e9251c9c0
commit
a5f2533a66
@ -1,7 +1,14 @@
|
|||||||
import type { TypedDataAgGrid } from '@vegaprotocol/datagrid';
|
import type { TypedDataAgGrid } from '@vegaprotocol/datagrid';
|
||||||
import { AgGrid, PriceFlashCell } from '@vegaprotocol/datagrid';
|
import {
|
||||||
|
AgGrid,
|
||||||
|
PriceFlashCell,
|
||||||
|
useDataGridEvents,
|
||||||
|
} from '@vegaprotocol/datagrid';
|
||||||
import type { MarketMaybeWithData } from '@vegaprotocol/markets';
|
import type { MarketMaybeWithData } from '@vegaprotocol/markets';
|
||||||
import { useColumnDefs } from './use-column-defs';
|
import { useColumnDefs } from './use-column-defs';
|
||||||
|
import type { DataGridStore } from '../../stores/datagrid-store-slice';
|
||||||
|
import { type StateCreator, create } from 'zustand';
|
||||||
|
import { persist } from 'zustand/middleware';
|
||||||
|
|
||||||
export const getRowId = ({ data }: { data: { id: string } }) => data.id;
|
export const getRowId = ({ data }: { data: { id: string } }) => data.id;
|
||||||
|
|
||||||
@ -18,8 +25,37 @@ const components = {
|
|||||||
|
|
||||||
type Props = TypedDataAgGrid<MarketMaybeWithData>;
|
type Props = TypedDataAgGrid<MarketMaybeWithData>;
|
||||||
|
|
||||||
|
export type DataGridSlice = {
|
||||||
|
gridStore: DataGridStore;
|
||||||
|
updateGridStore: (gridStore: DataGridStore) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createDataGridSlice: StateCreator<DataGridSlice> = (set) => ({
|
||||||
|
gridStore: {},
|
||||||
|
updateGridStore: (newStore) => {
|
||||||
|
set((curr) => ({
|
||||||
|
gridStore: {
|
||||||
|
...curr.gridStore,
|
||||||
|
...newStore,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const useMarketsStore = create<DataGridSlice>()(
|
||||||
|
persist(createDataGridSlice, {
|
||||||
|
name: 'vega_market_list_store',
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
export const MarketListTable = (props: Props) => {
|
export const MarketListTable = (props: Props) => {
|
||||||
const columnDefs = useColumnDefs();
|
const columnDefs = useColumnDefs();
|
||||||
|
const gridStore = useMarketsStore((store) => store.gridStore);
|
||||||
|
const updateGridStore = useMarketsStore((store) => store.updateGridStore);
|
||||||
|
|
||||||
|
const gridStoreCallbacks = useDataGridEvents(gridStore, (colState) => {
|
||||||
|
updateGridStore(colState);
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AgGrid
|
<AgGrid
|
||||||
@ -28,6 +64,7 @@ export const MarketListTable = (props: Props) => {
|
|||||||
columnDefs={columnDefs}
|
columnDefs={columnDefs}
|
||||||
components={components}
|
components={components}
|
||||||
rowHeight={45}
|
rowHeight={45}
|
||||||
|
{...gridStoreCallbacks}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -51,6 +51,29 @@ export const useColumnDefs = () => {
|
|||||||
headerName: t('Description'),
|
headerName: t('Description'),
|
||||||
field: 'tradableInstrument.instrument.name',
|
field: 'tradableInstrument.instrument.name',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
headerName: t('Settlement asset'),
|
||||||
|
field: 'tradableInstrument.instrument.product.settlementAsset.symbol',
|
||||||
|
cellRenderer: ({
|
||||||
|
data,
|
||||||
|
}: VegaICellRendererParams<
|
||||||
|
MarketMaybeWithData,
|
||||||
|
'tradableInstrument.instrument.product.settlementAsset.symbol'
|
||||||
|
>) => {
|
||||||
|
const value = data && getAsset(data);
|
||||||
|
return value ? (
|
||||||
|
<ButtonLink
|
||||||
|
onClick={(e) => {
|
||||||
|
openAssetDetailsDialog(value.id, e.target as HTMLElement);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{value.symbol}
|
||||||
|
</ButtonLink>
|
||||||
|
) : (
|
||||||
|
''
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
headerName: t('Trading mode'),
|
headerName: t('Trading mode'),
|
||||||
field: 'tradingMode',
|
field: 'tradingMode',
|
||||||
@ -142,27 +165,21 @@ export const useColumnDefs = () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
headerName: t('Settlement asset'),
|
headerName: t('Open Interest'),
|
||||||
field: 'tradableInstrument.instrument.product.settlementAsset.symbol',
|
field: 'data.openInterest',
|
||||||
cellRenderer: ({
|
type: 'rightAligned',
|
||||||
|
valueFormatter: ({
|
||||||
data,
|
data,
|
||||||
}: VegaICellRendererParams<
|
}: VegaValueFormatterParams<
|
||||||
MarketMaybeWithData,
|
MarketMaybeWithData,
|
||||||
'tradableInstrument.instrument.product.settlementAsset.symbol'
|
'data.openInterest'
|
||||||
>) => {
|
>) =>
|
||||||
const value = data && getAsset(data);
|
data?.data?.openInterest === undefined
|
||||||
return value ? (
|
? '-'
|
||||||
<ButtonLink
|
: addDecimalsFormatNumber(
|
||||||
onClick={(e) => {
|
data?.data?.openInterest,
|
||||||
openAssetDetailsDialog(value.id, e.target as HTMLElement);
|
data?.positionDecimalPlaces
|
||||||
}}
|
),
|
||||||
>
|
|
||||||
{value.symbol}
|
|
||||||
</ButtonLink>
|
|
||||||
) : (
|
|
||||||
''
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
headerName: t('Spread'),
|
headerName: t('Spread'),
|
||||||
|
@ -25,15 +25,15 @@ def test_table_headers(page: Page, create_markets):
|
|||||||
headers = [
|
headers = [
|
||||||
"Market",
|
"Market",
|
||||||
"Description",
|
"Description",
|
||||||
|
"Settlement asset",
|
||||||
"Trading mode",
|
"Trading mode",
|
||||||
"Status",
|
"Status",
|
||||||
"Mark price",
|
"Mark price",
|
||||||
"24h volume",
|
"24h volume",
|
||||||
"Settlement asset",
|
"Open Interest",
|
||||||
"Spread",
|
"Spread",
|
||||||
"",
|
"",
|
||||||
]
|
]
|
||||||
|
|
||||||
page.wait_for_selector('[data-testid="tab-open-markets"]', state="visible")
|
page.wait_for_selector('[data-testid="tab-open-markets"]', state="visible")
|
||||||
page_headers = (
|
page_headers = (
|
||||||
page.get_by_test_id("tab-open-markets").locator(".ag-header-cell-text").all()
|
page.get_by_test_id("tab-open-markets").locator(".ag-header-cell-text").all()
|
||||||
@ -157,4 +157,4 @@ def test_drag_and_drop_column(page: Page, create_markets):
|
|||||||
page.locator(col_instrument_code).drag_to(
|
page.locator(col_instrument_code).drag_to(
|
||||||
page.locator('.ag-header-row [col-id="data.bestBidPrice"]')
|
page.locator('.ag-header-row [col-id="data.bestBidPrice"]')
|
||||||
)
|
)
|
||||||
expect(page.locator(col_instrument_code)).to_have_attribute("aria-colindex", "8")
|
expect(page.locator(col_instrument_code)).to_have_attribute("aria-colindex", "9")
|
||||||
|
@ -39,6 +39,7 @@ export const AgGridThemed = ({
|
|||||||
ref={gridRef}
|
ref={gridRef}
|
||||||
overlayLoadingTemplate={t('Loading...')}
|
overlayLoadingTemplate={t('Loading...')}
|
||||||
overlayNoRowsTemplate={t('No data')}
|
overlayNoRowsTemplate={t('No data')}
|
||||||
|
suppressDragLeaveHidesColumns
|
||||||
{...defaultProps}
|
{...defaultProps}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
|
@ -3,12 +3,12 @@ import * as Types from '@vegaprotocol/types';
|
|||||||
import { gql } from '@apollo/client';
|
import { gql } from '@apollo/client';
|
||||||
import * as Apollo from '@apollo/client';
|
import * as Apollo from '@apollo/client';
|
||||||
const defaultOptions = {} as const;
|
const defaultOptions = {} as const;
|
||||||
export type MarketsDataFieldsFragment = { __typename?: 'MarketData', bestBidPrice: string, bestOfferPrice: string, markPrice: string, trigger: Types.AuctionTrigger, staticMidPrice: string, marketState: Types.MarketState, marketTradingMode: Types.MarketTradingMode, indicativeVolume: string, indicativePrice: string, bestStaticBidPrice: string, bestStaticOfferPrice: string, targetStake?: string | null, suppliedStake?: string | null, auctionStart?: string | null, auctionEnd?: string | null, market: { __typename?: 'Market', id: string } };
|
export type MarketsDataFieldsFragment = { __typename?: 'MarketData', bestBidPrice: string, bestOfferPrice: string, markPrice: string, trigger: Types.AuctionTrigger, staticMidPrice: string, marketState: Types.MarketState, marketTradingMode: Types.MarketTradingMode, indicativeVolume: string, indicativePrice: string, bestStaticBidPrice: string, bestStaticOfferPrice: string, targetStake?: string | null, suppliedStake?: string | null, auctionStart?: string | null, auctionEnd?: string | null, openInterest: string, market: { __typename?: 'Market', id: string } };
|
||||||
|
|
||||||
export type MarketsDataQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
export type MarketsDataQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||||
|
|
||||||
|
|
||||||
export type MarketsDataQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', data?: { __typename?: 'MarketData', bestBidPrice: string, bestOfferPrice: string, markPrice: string, trigger: Types.AuctionTrigger, staticMidPrice: string, marketState: Types.MarketState, marketTradingMode: Types.MarketTradingMode, indicativeVolume: string, indicativePrice: string, bestStaticBidPrice: string, bestStaticOfferPrice: string, targetStake?: string | null, suppliedStake?: string | null, auctionStart?: string | null, auctionEnd?: string | null, market: { __typename?: 'Market', id: string } } | null } }> } | null };
|
export type MarketsDataQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', data?: { __typename?: 'MarketData', bestBidPrice: string, bestOfferPrice: string, markPrice: string, trigger: Types.AuctionTrigger, staticMidPrice: string, marketState: Types.MarketState, marketTradingMode: Types.MarketTradingMode, indicativeVolume: string, indicativePrice: string, bestStaticBidPrice: string, bestStaticOfferPrice: string, targetStake?: string | null, suppliedStake?: string | null, auctionStart?: string | null, auctionEnd?: string | null, openInterest: string, market: { __typename?: 'Market', id: string } } | null } }> } | null };
|
||||||
|
|
||||||
export const MarketsDataFieldsFragmentDoc = gql`
|
export const MarketsDataFieldsFragmentDoc = gql`
|
||||||
fragment MarketsDataFields on MarketData {
|
fragment MarketsDataFields on MarketData {
|
||||||
@ -30,6 +30,7 @@ export const MarketsDataFieldsFragmentDoc = gql`
|
|||||||
suppliedStake
|
suppliedStake
|
||||||
auctionStart
|
auctionStart
|
||||||
auctionEnd
|
auctionEnd
|
||||||
|
openInterest
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
export const MarketsDataDocument = gql`
|
export const MarketsDataDocument = gql`
|
||||||
|
@ -17,6 +17,7 @@ fragment MarketsDataFields on MarketData {
|
|||||||
suppliedStake
|
suppliedStake
|
||||||
auctionStart
|
auctionStart
|
||||||
auctionEnd
|
auctionEnd
|
||||||
|
openInterest
|
||||||
}
|
}
|
||||||
|
|
||||||
query MarketsData {
|
query MarketsData {
|
||||||
|
@ -40,6 +40,7 @@ export const createMarketsDataFragment = (
|
|||||||
bestStaticBidPrice: '0',
|
bestStaticBidPrice: '0',
|
||||||
bestStaticOfferPrice: '0',
|
bestStaticOfferPrice: '0',
|
||||||
indicativeVolume: '0',
|
indicativeVolume: '0',
|
||||||
|
openInterest: '0',
|
||||||
bestBidPrice: '0',
|
bestBidPrice: '0',
|
||||||
bestOfferPrice: '0',
|
bestOfferPrice: '0',
|
||||||
markPrice: '4612690058',
|
markPrice: '4612690058',
|
||||||
|
@ -267,6 +267,7 @@ export const preparePositions = (metrics: Position[], showClosed: boolean) => {
|
|||||||
MarketState.STATE_ACTIVE,
|
MarketState.STATE_ACTIVE,
|
||||||
MarketState.STATE_PENDING,
|
MarketState.STATE_PENDING,
|
||||||
MarketState.STATE_SUSPENDED,
|
MarketState.STATE_SUSPENDED,
|
||||||
|
MarketState.STATE_SUSPENDED_VIA_GOVERNANCE,
|
||||||
].includes(p.marketState)
|
].includes(p.marketState)
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
|
14
libs/types/src/__generated__/types.ts
generated
14
libs/types/src/__generated__/types.ts
generated
@ -4376,7 +4376,19 @@ export type Query = {
|
|||||||
/** The last block process by the blockchain */
|
/** The last block process by the blockchain */
|
||||||
lastBlockHeight: Scalars['String'];
|
lastBlockHeight: Scalars['String'];
|
||||||
/**
|
/**
|
||||||
* Get ledger entries by asset, market, party, account type, transfer type within the given date range.
|
* Get a list of ledger entries within the given date range. The date range is restricted to a maximum of 5 days.
|
||||||
|
* This query requests and sums the number of ledger entries from a given subset of accounts, specified via the 'filter' argument.
|
||||||
|
* It returns a time series - implemented as a list of AggregateLedgerEntry structs - with a row for every time
|
||||||
|
* the summed ledger entries of the set of specified accounts changes.
|
||||||
|
* Each account filter must contain no more than one party ID.
|
||||||
|
* At least one party ID must be specified in the from or to account filter.
|
||||||
|
*
|
||||||
|
* Entries can be filtered by:
|
||||||
|
* - the sending account (market ID, asset ID, account type)
|
||||||
|
* - receiving account (market ID, asset ID, account type)
|
||||||
|
* - sending AND receiving account
|
||||||
|
* - transfer type either in addition to the above filters or as a standalone option
|
||||||
|
*
|
||||||
* Note: The date range is restricted to any 5 days.
|
* Note: The date range is restricted to any 5 days.
|
||||||
* If no start or end date is provided, only ledger entries from the last 5 days will be returned.
|
* If no start or end date is provided, only ledger entries from the last 5 days will be returned.
|
||||||
* If a start and end date are provided, but the end date is more than 5 days after the start date, only data up to 5 days after the start date will be returned.
|
* If a start and end date are provided, but the end date is more than 5 days after the start date, only data up to 5 days after the start date will be returned.
|
||||||
|
Loading…
Reference in New Issue
Block a user