Compare commits
5 Commits
develop
...
fix/trades
Author | SHA1 | Date | |
---|---|---|---|
|
ca3b2dfa4d | ||
|
7ac4fbaa67 | ||
|
87fbcb2994 | ||
|
7c632e8867 | ||
|
42c477763c |
@ -3,6 +3,7 @@ fragment TradeFields on Trade {
|
||||
price
|
||||
size
|
||||
createdAt
|
||||
aggressor
|
||||
market {
|
||||
id
|
||||
}
|
||||
@ -35,5 +36,6 @@ subscription TradesUpdate($marketId: ID!) {
|
||||
size
|
||||
createdAt
|
||||
marketId
|
||||
aggressor
|
||||
}
|
||||
}
|
||||
|
8
libs/trades/src/lib/__generated__/Trades.ts
generated
8
libs/trades/src/lib/__generated__/Trades.ts
generated
@ -3,7 +3,7 @@ import * as Types from '@vegaprotocol/types';
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type TradeFieldsFragment = { __typename?: 'Trade', id: string, price: string, size: string, createdAt: any, market: { __typename?: 'Market', id: string } };
|
||||
export type TradeFieldsFragment = { __typename?: 'Trade', id: string, price: string, size: string, createdAt: any, aggressor: Types.Side, market: { __typename?: 'Market', id: string } };
|
||||
|
||||
export type TradesQueryVariables = Types.Exact<{
|
||||
marketId: Types.Scalars['ID'];
|
||||
@ -11,14 +11,14 @@ export type TradesQueryVariables = Types.Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type TradesQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, tradesConnection?: { __typename?: 'TradeConnection', edges: Array<{ __typename?: 'TradeEdge', cursor: string, node: { __typename?: 'Trade', id: string, price: string, size: string, createdAt: any, market: { __typename?: 'Market', id: string } } }>, pageInfo: { __typename?: 'PageInfo', startCursor: string, endCursor: string, hasNextPage: boolean, hasPreviousPage: boolean } } | null } | null };
|
||||
export type TradesQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, tradesConnection?: { __typename?: 'TradeConnection', edges: Array<{ __typename?: 'TradeEdge', cursor: string, node: { __typename?: 'Trade', id: string, price: string, size: string, createdAt: any, aggressor: Types.Side, market: { __typename?: 'Market', id: string } } }>, pageInfo: { __typename?: 'PageInfo', startCursor: string, endCursor: string, hasNextPage: boolean, hasPreviousPage: boolean } } | null } | null };
|
||||
|
||||
export type TradesUpdateSubscriptionVariables = Types.Exact<{
|
||||
marketId: Types.Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
export type TradesUpdateSubscription = { __typename?: 'Subscription', trades?: Array<{ __typename?: 'TradeUpdate', id: string, price: string, size: string, createdAt: any, marketId: string }> | null };
|
||||
export type TradesUpdateSubscription = { __typename?: 'Subscription', trades?: Array<{ __typename?: 'TradeUpdate', id: string, price: string, size: string, createdAt: any, marketId: string, aggressor: Types.Side }> | null };
|
||||
|
||||
export const TradeFieldsFragmentDoc = gql`
|
||||
fragment TradeFields on Trade {
|
||||
@ -26,6 +26,7 @@ export const TradeFieldsFragmentDoc = gql`
|
||||
price
|
||||
size
|
||||
createdAt
|
||||
aggressor
|
||||
market {
|
||||
id
|
||||
}
|
||||
@ -89,6 +90,7 @@ export const TradesUpdateDocument = gql`
|
||||
size
|
||||
createdAt
|
||||
marketId
|
||||
aggressor
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
@ -1,13 +1,15 @@
|
||||
import { act, render, screen } from '@testing-library/react';
|
||||
import { getDateTimeFormat } from '@vegaprotocol/react-helpers';
|
||||
import { DOWN_CLASS, TradesTable, UP_CLASS } from './trades-table';
|
||||
import { SELL_CLASS, TradesTable, BUY_CLASS } from './trades-table';
|
||||
import type { Trade } from './trades-data-provider';
|
||||
import { Side } from '@vegaprotocol/types';
|
||||
|
||||
const trade: Trade = {
|
||||
__typename: 'Trade',
|
||||
id: 'trade-id',
|
||||
price: '111122200',
|
||||
size: '2000',
|
||||
aggressor: Side.SIDE_BUY,
|
||||
createdAt: new Date('2022-04-06T19:00:00').toISOString(),
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
@ -17,59 +19,58 @@ const trade: Trade = {
|
||||
} as Trade['market'],
|
||||
};
|
||||
|
||||
it('Correct columns are rendered', async () => {
|
||||
await act(async () => {
|
||||
render(<TradesTable rowData={[trade]} />);
|
||||
});
|
||||
const expectedHeaders = ['Price', 'Size', 'Created at'];
|
||||
const headers = screen.getAllByRole('columnheader');
|
||||
expect(headers).toHaveLength(expectedHeaders.length);
|
||||
expect(headers.map((h) => h.textContent?.trim())).toEqual(expectedHeaders);
|
||||
});
|
||||
|
||||
it('Number and data columns are formatted', async () => {
|
||||
await act(async () => {
|
||||
render(<TradesTable rowData={[trade]} />);
|
||||
describe('TradesTable', () => {
|
||||
it('should render correct columns', async () => {
|
||||
await act(async () => {
|
||||
render(<TradesTable rowData={[trade]} />);
|
||||
});
|
||||
const expectedHeaders = ['Price', 'Size', 'Created at'];
|
||||
const headers = screen.getAllByRole('columnheader');
|
||||
expect(headers).toHaveLength(expectedHeaders.length);
|
||||
expect(headers.map((h) => h.textContent?.trim())).toEqual(expectedHeaders);
|
||||
});
|
||||
|
||||
const cells = screen.getAllByRole('gridcell');
|
||||
const expectedValues = [
|
||||
'1,111,222.00',
|
||||
'20.00',
|
||||
getDateTimeFormat().format(new Date(trade.createdAt)),
|
||||
];
|
||||
cells.forEach((cell, i) => {
|
||||
expect(cell).toHaveTextContent(expectedValues[i]);
|
||||
it('should format number and data columns', async () => {
|
||||
await act(async () => {
|
||||
render(<TradesTable rowData={[trade]} />);
|
||||
});
|
||||
|
||||
const cells = screen.getAllByRole('gridcell');
|
||||
const expectedValues = [
|
||||
'1,111,222.00',
|
||||
'20.00',
|
||||
getDateTimeFormat().format(new Date(trade.createdAt)),
|
||||
];
|
||||
cells.forEach((cell, i) => {
|
||||
expect(cell).toHaveTextContent(expectedValues[i]);
|
||||
});
|
||||
});
|
||||
|
||||
it('should format price and size columns', async () => {
|
||||
const trade2 = {
|
||||
...trade,
|
||||
id: 'trade-id-2',
|
||||
price: (Number(trade.price) + 10).toString(),
|
||||
size: (Number(trade.size) - 10).toString(),
|
||||
};
|
||||
await act(async () => {
|
||||
render(<TradesTable rowData={[trade2, trade]} />);
|
||||
});
|
||||
|
||||
const cells = screen.getAllByRole('gridcell');
|
||||
|
||||
const priceCells = cells.filter(
|
||||
(cell) => cell.getAttribute('col-id') === 'price'
|
||||
);
|
||||
const sizeCells = cells.filter(
|
||||
(cell) => cell.getAttribute('col-id') === 'size'
|
||||
);
|
||||
|
||||
// For first trade price should have green class
|
||||
// row 1
|
||||
expect(priceCells[0]).toHaveClass(BUY_CLASS);
|
||||
expect(priceCells[1]).not.toHaveClass(SELL_CLASS);
|
||||
expect(sizeCells[1]).not.toHaveClass(SELL_CLASS);
|
||||
expect(sizeCells[1]).not.toHaveClass(BUY_CLASS);
|
||||
});
|
||||
});
|
||||
|
||||
it('Price and size columns are formatted', async () => {
|
||||
const trade2 = {
|
||||
...trade,
|
||||
id: 'trade-id-2',
|
||||
price: (Number(trade.price) + 10).toString(),
|
||||
size: (Number(trade.size) - 10).toString(),
|
||||
};
|
||||
await act(async () => {
|
||||
render(<TradesTable rowData={[trade2, trade]} />);
|
||||
});
|
||||
|
||||
const cells = screen.getAllByRole('gridcell');
|
||||
|
||||
const priceCells = cells.filter(
|
||||
(cell) => cell.getAttribute('col-id') === 'price'
|
||||
);
|
||||
const sizeCells = cells.filter(
|
||||
(cell) => cell.getAttribute('col-id') === 'size'
|
||||
);
|
||||
|
||||
// For first trade price should have green class and size should have red class
|
||||
// row 1
|
||||
expect(priceCells[0]).toHaveClass(UP_CLASS);
|
||||
expect(priceCells[1]).not.toHaveClass(DOWN_CLASS);
|
||||
expect(priceCells[1]).not.toHaveClass(UP_CLASS);
|
||||
|
||||
expect(sizeCells[0]).toHaveClass(DOWN_CLASS);
|
||||
expect(sizeCells[1]).not.toHaveClass(DOWN_CLASS);
|
||||
expect(sizeCells[1]).not.toHaveClass(UP_CLASS);
|
||||
});
|
||||
|
@ -13,31 +13,22 @@ import type { IDatasource, IGetRowsParams } from 'ag-grid-community';
|
||||
import type { CellClassParams, ValueFormatterParams } from 'ag-grid-community';
|
||||
import type { AgGridReactProps } from 'ag-grid-react';
|
||||
import type { Trade } from './trades-data-provider';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { Side } from '@vegaprotocol/types';
|
||||
|
||||
export const UP_CLASS = 'text-vega-green dark:text-vega-green';
|
||||
export const DOWN_CLASS = 'text-vega-pink dark:text-vega-pink';
|
||||
export const BUY_CLASS = 'text-vega-green dark:text-vega-green';
|
||||
export const SELL_CLASS = 'text-vega-pink dark:text-vega-pink';
|
||||
|
||||
const changeCellClass =
|
||||
(dataKey: string) =>
|
||||
({ api, value, node }: CellClassParams) => {
|
||||
const rowIndex = node?.rowIndex;
|
||||
let colorClass = '';
|
||||
const changeCellClass = ({ node }: CellClassParams) => {
|
||||
let colorClass = '';
|
||||
|
||||
if (typeof rowIndex === 'number') {
|
||||
const prevRowNode = api.getModel().getRow(rowIndex + 1);
|
||||
const prevValue = prevRowNode?.data && prevRowNode.data[dataKey];
|
||||
const valueNum = new BigNumber(value);
|
||||
if (node.data?.aggressor === Side.SIDE_BUY) {
|
||||
colorClass = BUY_CLASS;
|
||||
} else if (node.data?.aggressor === Side.SIDE_SELL) {
|
||||
colorClass = SELL_CLASS;
|
||||
}
|
||||
|
||||
if (valueNum.isGreaterThan(prevValue)) {
|
||||
colorClass = UP_CLASS;
|
||||
} else if (valueNum.isLessThan(prevValue)) {
|
||||
colorClass = DOWN_CLASS;
|
||||
}
|
||||
}
|
||||
|
||||
return ['font-mono text-right', colorClass].join(' ');
|
||||
};
|
||||
return ['font-mono text-right', colorClass].join(' ');
|
||||
};
|
||||
|
||||
export interface GetRowsParams extends Omit<IGetRowsParams, 'successCallback'> {
|
||||
successCallback(rowsThisBlock: (Trade | null)[], lastRow?: number): void;
|
||||
@ -77,7 +68,7 @@ export const TradesTable = forwardRef<AgGridReact, Props>((props, ref) => {
|
||||
field="price"
|
||||
type="rightAligned"
|
||||
width={130}
|
||||
cellClass={changeCellClass('price')}
|
||||
cellClass={changeCellClass}
|
||||
valueFormatter={({
|
||||
value,
|
||||
data,
|
||||
@ -127,7 +118,6 @@ export const TradesTable = forwardRef<AgGridReact, Props>((props, ref) => {
|
||||
}
|
||||
return addDecimal(value, data.market.positionDecimalPlaces);
|
||||
}}
|
||||
cellClass={changeCellClass('size')}
|
||||
/>
|
||||
<AgGridColumn
|
||||
headerName={t('Created at')}
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { Side } from '@vegaprotocol/types';
|
||||
import merge from 'lodash/merge';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
import type {
|
||||
@ -47,6 +48,7 @@ export const tradesUpdateSubscription = (
|
||||
size: '24',
|
||||
createdAt: '2022-04-06T16:19:42.692598951Z',
|
||||
marketId: 'market-0',
|
||||
aggressor: Side.SIDE_BUY,
|
||||
},
|
||||
],
|
||||
};
|
||||
@ -59,6 +61,7 @@ const trades: TradeFieldsFragment[] = [
|
||||
price: '17116898',
|
||||
size: '24',
|
||||
createdAt: '2022-04-06T16:19:42.692598951Z',
|
||||
aggressor: Side.SIDE_BUY,
|
||||
market: {
|
||||
id: 'market-0',
|
||||
__typename: 'Market',
|
||||
@ -70,6 +73,7 @@ const trades: TradeFieldsFragment[] = [
|
||||
price: '17209102',
|
||||
size: '7',
|
||||
createdAt: '2022-04-07T06:59:44.835686754Z',
|
||||
aggressor: Side.SIDE_SELL,
|
||||
market: {
|
||||
id: 'market-0',
|
||||
__typename: 'Market',
|
||||
@ -81,6 +85,7 @@ const trades: TradeFieldsFragment[] = [
|
||||
price: '17106734',
|
||||
size: '18',
|
||||
createdAt: '2022-04-07T17:56:47.997938583Z',
|
||||
aggressor: Side.SIDE_BUY,
|
||||
market: {
|
||||
id: 'market-0',
|
||||
__typename: 'Market',
|
||||
|
Loading…
Reference in New Issue
Block a user