chore: single position table (1645) (#1749)

* chore: single position table (1645)

chore: single position table (1645)

* chore: tests fixed

* chore: remove unused withSummaryRow arg

* chore: use ag grid value formatter type helper

* chore: update console-lite to use value formatter params helper

* chore: fix e2e test by ignoring pinned row

Co-authored-by: Rado <szpiechrados@gmail.com>
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
This commit is contained in:
Art 2022-10-20 01:59:36 +02:00 committed by GitHub
parent ce283aeee7
commit 8d2fe118ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 144 additions and 161 deletions

View File

@ -7,10 +7,7 @@ import {
signedNumberCssClassRules, signedNumberCssClassRules,
t, t,
} from '@vegaprotocol/react-helpers'; } from '@vegaprotocol/react-helpers';
import type { import type { Position } from '@vegaprotocol/positions';
PositionsTableValueFormatterParams,
Position,
} from '@vegaprotocol/positions';
import { AmountCell } from '@vegaprotocol/positions'; import { AmountCell } from '@vegaprotocol/positions';
import type { import type {
CellRendererSelectorResult, CellRendererSelectorResult,
@ -20,6 +17,7 @@ import type {
ColDef, ColDef,
} from 'ag-grid-community'; } from 'ag-grid-community';
import { MarketTradingMode } from '@vegaprotocol/types'; import { MarketTradingMode } from '@vegaprotocol/types';
import type { VegaValueFormatterParams } from '@vegaprotocol/ui-toolkit';
import { Intent, ProgressBarCell } from '@vegaprotocol/ui-toolkit'; import { Intent, ProgressBarCell } from '@vegaprotocol/ui-toolkit';
const EmptyCell = () => ''; const EmptyCell = () => '';
@ -77,9 +75,7 @@ const useColumnDefinitions = () => {
value, value,
data, data,
node, node,
}: PositionsTableValueFormatterParams & { }: VegaValueFormatterParams<Position, 'openVolume'>) => {
value: Position['openVolume'];
}) => {
let ret; let ret;
if (value && data) { if (value && data) {
ret = node?.rowPinned ret = node?.rowPinned
@ -107,9 +103,7 @@ const useColumnDefinitions = () => {
value, value,
data, data,
node, node,
}: PositionsTableValueFormatterParams & { }: VegaValueFormatterParams<Position, 'markPrice'>) => {
value: Position['markPrice'];
}) => {
if ( if (
data && data &&
value && value &&
@ -186,9 +180,8 @@ const useColumnDefinitions = () => {
valueFormatter: ({ valueFormatter: ({
value, value,
node, node,
}: PositionsTableValueFormatterParams & { }: VegaValueFormatterParams<Position, 'currentLeverage'>) =>
value: Position['currentLeverage']; value === undefined ? '' : formatNumber(value.toString(), 1),
}) => (value === undefined ? '' : formatNumber(value.toString(), 1)),
}, },
{ {
colId: 'marginallocated', colId: 'marginallocated',
@ -229,10 +222,8 @@ const useColumnDefinitions = () => {
valueFormatter: ({ valueFormatter: ({
value, value,
data, data,
}: PositionsTableValueFormatterParams & { }: VegaValueFormatterParams<Position, 'realisedPNL'>) =>
value: Position['realisedPNL']; value === undefined || data === undefined
}) =>
value === undefined
? '' ? ''
: addDecimalsFormatNumber(value.toString(), data.decimals), : addDecimalsFormatNumber(value.toString(), data.decimals),
cellRenderer: 'PriceFlashCell', cellRenderer: 'PriceFlashCell',
@ -249,10 +240,8 @@ const useColumnDefinitions = () => {
valueFormatter: ({ valueFormatter: ({
value, value,
data, data,
}: PositionsTableValueFormatterParams & { }: VegaValueFormatterParams<Position, 'unrealisedPNL'>) =>
value: Position['unrealisedPNL']; value === undefined || data === undefined
}) =>
value === undefined
? '' ? ''
: addDecimalsFormatNumber(value.toString(), data.decimals), : addDecimalsFormatNumber(value.toString(), data.decimals),
cellRenderer: 'PriceFlashCell', cellRenderer: 'PriceFlashCell',
@ -266,9 +255,7 @@ const useColumnDefinitions = () => {
type: 'rightAligned', type: 'rightAligned',
valueFormatter: ({ valueFormatter: ({
value, value,
}: PositionsTableValueFormatterParams & { }: VegaValueFormatterParams<Position, 'updatedAt'>) => {
value: Position['updatedAt'];
}) => {
if (!value) { if (!value) {
return ''; return '';
} }

View File

@ -31,36 +31,35 @@ describe('positions', { tags: '@smoke' }, () => {
cy.wrap($marketSymbol).invoke('text').should('not.be.empty'); cy.wrap($marketSymbol).invoke('text').should('not.be.empty');
}); });
cy.get('[col-id="openVolume"]').each(($openVolume) => { cy.get('.ag-center-cols-container [col-id="openVolume"]').each(
cy.wrap($openVolume).invoke('text').should('not.be.empty'); ($openVolume) => {
}); cy.wrap($openVolume).invoke('text').should('not.be.empty');
}
);
// includes average entry price, mark price, realised PNL & leverage // includes average entry price, mark price, realised PNL & leverage
cy.getByTestId('flash-cell').each(($prices) => { cy.getByTestId('flash-cell').each(($prices) => {
cy.wrap($prices).invoke('text').should('not.be.empty'); cy.wrap($prices).invoke('text').should('not.be.empty');
}); });
cy.get('[col-id="averageEntryPrice"]') cy.get('[col-id="liquidationPrice"]')
.should('contain.text', '85,093.38') // entry price .should('contain.text', '85,093.38') // entry price
.should('contain.text', '0.00'); // liquidation price .should('contain.text', '0.00'); // liquidation price
cy.get('[col-id="currentLeverage"]').should('contain.text', '0.8'); cy.get('[col-id="currentLeverage"]').should('contain.text', '0.8');
cy.get('[col-id="capitalUtilisation"]') // margin allocated cy.get('[col-id="marginAccountBalance"]') // margin allocated
.should('contain.text', '0.00%') .should('contain.text', '1,000.00000');
.should('contain.text', '1,000.01000');
cy.get('[col-id="unrealisedPNL"]').each(($unrealisedPnl) => { cy.get('[col-id="unrealisedPNL"]').each(($unrealisedPnl) => {
cy.wrap($unrealisedPnl).invoke('text').should('not.be.empty'); cy.wrap($unrealisedPnl).invoke('text').should('not.be.empty');
}); });
cy.getByTestId('flash-cell').should('contain.text', '276,761.40348'); // Total tDAI position cy.get('[col-id="notional"]').should('contain.text', '276,761.40348'); // Total tDAI position
cy.getByTestId('flash-cell').should('contain.text', '0.00000'); // Total Realised PNL cy.get('[col-id="realisedPNL"]').should('contain.text', '0.00100'); // Total Realised PNL
cy.get('[col-id="unrealisedPNL"]').should('contain.text', '8.95000'); // Total Unrealised PNL cy.get('[col-id="unrealisedPNL"]').should('contain.text', '8.95000'); // Total Unrealised PNL
}); });
cy.getByTestId('balance').eq(1).should('have.text', '1,000.01000'); // Asset balance
cy.getByTestId('close-position').should('be.visible').and('have.length', 3); cy.getByTestId('close-position').should('be.visible').and('have.length', 3);
} }
}); });

View File

@ -42,6 +42,7 @@ interface PositionRejoined {
export interface Position { export interface Position {
marketName: string; marketName: string;
averageEntryPrice: string; averageEntryPrice: string;
marginAccountBalance: BigNumber;
capitalUtilisation: number; capitalUtilisation: number;
currentLeverage: number; currentLeverage: number;
decimals: number; decimals: number;
@ -151,6 +152,7 @@ export const getMetrics = (
metrics.push({ metrics.push({
marketName: market.tradableInstrument.instrument.name, marketName: market.tradableInstrument.instrument.name,
averageEntryPrice: position.averageEntryPrice, averageEntryPrice: position.averageEntryPrice,
marginAccountBalance,
capitalUtilisation: Math.round(capitalUtilisation.toNumber()), capitalUtilisation: Math.round(capitalUtilisation.toNumber()),
currentLeverage: currentLeverage.toNumber(), currentLeverage: currentLeverage.toNumber(),
marketDecimalPlaces, marketDecimalPlaces,

View File

@ -1,8 +1,8 @@
import { useCallback } from 'react'; import { useCallback, useRef } from 'react';
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit'; import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import type { Position } from './positions-data-providers'; import type { Position } from './positions-data-providers';
import { Positions } from './positions'; import { PositionsTable, useClosePosition, usePositionsData } from '../';
import { useClosePosition, usePositionsAssets } from '../'; import type { AgGridReact } from 'ag-grid-react';
interface PositionsManagerProps { interface PositionsManagerProps {
partyId: string; partyId: string;
@ -17,18 +17,20 @@ export const PositionsManager = ({ partyId }: PositionsManagerProps) => {
[submit] [submit]
); );
const { data, error, loading, assetSymbols } = usePositionsAssets(partyId); const gridRef = useRef<AgGridReact | null>(null);
const { data, error, loading, getRows } = usePositionsData(partyId, gridRef);
return ( return (
<> <>
<AsyncRenderer loading={loading} error={error} data={data}> <AsyncRenderer loading={loading} error={error} data={data}>
{assetSymbols?.map((assetSymbol) => ( <PositionsTable
<Positions domLayout="autoHeight"
partyId={partyId} style={{ width: '100%' }}
assetSymbol={assetSymbol} ref={gridRef}
key={assetSymbol} rowModelType={data?.length ? 'infinite' : 'clientSide'}
onClose={onClose} rowData={data?.length ? undefined : []}
/> datasource={{ getRows }}
))} onClose={onClose}
/>
</AsyncRenderer> </AsyncRenderer>
<Dialog> <Dialog>

View File

@ -3,28 +3,31 @@ import { act, render, screen } from '@testing-library/react';
import PositionsTable from './positions-table'; import PositionsTable from './positions-table';
import type { Position } from './positions-data-providers'; import type { Position } from './positions-data-providers';
import { MarketTradingMode } from '@vegaprotocol/types'; import { MarketTradingMode } from '@vegaprotocol/types';
import BigNumber from 'bignumber.js';
import React from 'react';
const singleRow: Position = { const singleRow: Position = {
marketName: 'ETH/BTC (31 july 2022)', marketName: 'ETH/BTC (31 july 2022)',
averageEntryPrice: '133', // 13.3 averageEntryPrice: '133',
capitalUtilisation: 11, // 11.00% capitalUtilisation: 11,
currentLeverage: 1.1, currentLeverage: 1.1,
marketDecimalPlaces: 1, marketDecimalPlaces: 1,
positionDecimalPlaces: 0, positionDecimalPlaces: 0,
decimals: 2, decimals: 2,
totalBalance: '123456', totalBalance: '123456',
assetSymbol: 'BTC', assetSymbol: 'BTC',
liquidationPrice: '83', // 8.3 liquidationPrice: '83',
lowMarginLevel: false, lowMarginLevel: false,
marketId: 'string', marketId: 'string',
marketTradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS, marketTradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
markPrice: '123', // 12.3 markPrice: '123',
notional: '12300', // 1230.0 notional: '12300',
openVolume: '100', // 100 openVolume: '100',
realisedPNL: '123', // 1.23 realisedPNL: '123',
unrealisedPNL: '456', // 4.56 unrealisedPNL: '456',
searchPrice: '0', searchPrice: '0',
updatedAt: '2022-07-27T15:02:58.400Z', updatedAt: '2022-07-27T15:02:58.400Z',
marginAccountBalance: new BigNumber(123456),
}; };
const singleRowData = [singleRow]; const singleRowData = [singleRow];
@ -42,14 +45,17 @@ it('Render correct columns', async () => {
}); });
const headers = screen.getAllByRole('columnheader'); const headers = screen.getAllByRole('columnheader');
expect(headers).toHaveLength(9); expect(headers).toHaveLength(12);
expect( expect(
headers.map((h) => h.querySelector('[ref="eText"]')?.textContent?.trim()) headers.map((h) => h.querySelector('[ref="eText"]')?.textContent?.trim())
).toEqual([ ).toEqual([
'Market', 'Market',
'Size', 'Notional size',
'Open volume',
'Mark price', 'Mark price',
'Settlement asset',
'Entry price', 'Entry price',
'Liquidation price (est)',
'Leverage', 'Leverage',
'Margin allocated', 'Margin allocated',
'Realised PNL', 'Realised PNL',
@ -84,22 +90,21 @@ it('add color and sign to amount, displays positive notional value', async () =>
result = render(<PositionsTable rowData={singleRowData} />); result = render(<PositionsTable rowData={singleRowData} />);
}); });
let cells = screen.getAllByRole('gridcell'); let cells = screen.getAllByRole('gridcell');
let values = cells[1].querySelectorAll('.text-right');
expect(values[0].classList.contains('text-vega-green-dark')).toBeTruthy(); expect(cells[2].classList.contains('text-vega-green-dark')).toBeTruthy();
expect(values[0].classList.contains('text-vega-red-dark')).toBeFalsy(); expect(cells[2].classList.contains('text-vega-red-dark')).toBeFalsy();
expect(values[0].textContent).toEqual('+100'); expect(cells[2].textContent).toEqual('+100');
expect(values[1].textContent).toEqual('1,230.0'); expect(cells[1].textContent).toEqual('123.00');
await act(async () => { await act(async () => {
result.rerender( result.rerender(
<PositionsTable rowData={[{ ...singleRow, openVolume: '-100' }]} /> <PositionsTable rowData={[{ ...singleRow, openVolume: '-100' }]} />
); );
}); });
cells = screen.getAllByRole('gridcell'); cells = screen.getAllByRole('gridcell');
values = cells[1].querySelectorAll('.text-right'); expect(cells[2].classList.contains('text-vega-green-dark')).toBeFalsy();
expect(values[0].classList.contains('text-vega-green-dark')).toBeFalsy(); expect(cells[2].classList.contains('text-vega-red-dark')).toBeTruthy();
expect(values[0].classList.contains('text-vega-red-dark')).toBeTruthy(); expect(cells[2].textContent?.startsWith('-100')).toBeTruthy();
expect(values[0].textContent?.startsWith('-100')).toBeTruthy(); expect(cells[1].textContent).toEqual('123.00');
expect(values[1].textContent).toEqual('1,230.0');
}); });
it('displays mark price', async () => { it('displays mark price', async () => {
@ -109,7 +114,7 @@ it('displays mark price', async () => {
}); });
let cells = screen.getAllByRole('gridcell'); let cells = screen.getAllByRole('gridcell');
expect(cells[2].textContent).toEqual('12.3'); expect(cells[3].textContent).toEqual('12.3');
await act(async () => { await act(async () => {
result.rerender( result.rerender(
@ -125,7 +130,7 @@ it('displays mark price', async () => {
}); });
cells = screen.getAllByRole('gridcell'); cells = screen.getAllByRole('gridcell');
expect(cells[2].textContent).toEqual('-'); expect(cells[3].textContent).toEqual('-');
}); });
it("displays properly entry, liquidation price and liquidation bar and it's intent", async () => { it("displays properly entry, liquidation price and liquidation bar and it's intent", async () => {
@ -134,11 +139,10 @@ it("displays properly entry, liquidation price and liquidation bar and it's inte
result = render(<PositionsTable rowData={singleRowData} />); result = render(<PositionsTable rowData={singleRowData} />);
}); });
let cells = screen.getAllByRole('gridcell'); let cells = screen.getAllByRole('gridcell');
let cell = cells[3]; const entryPrice = cells[5].firstElementChild?.firstElementChild?.textContent;
const entryPrice = cell.firstElementChild?.firstElementChild?.textContent;
const liquidationPrice = const liquidationPrice =
cell.firstElementChild?.lastElementChild?.textContent; cells[6].firstElementChild?.lastElementChild?.textContent;
const progressBarTrack = cell.lastElementChild; const progressBarTrack = cells[6].lastElementChild;
let progressBar = progressBarTrack?.firstElementChild as HTMLElement; let progressBar = progressBarTrack?.firstElementChild as HTMLElement;
const progressBarWidth = progressBar?.style?.width; const progressBarWidth = progressBar?.style?.width;
expect(entryPrice).toEqual('13.3'); expect(entryPrice).toEqual('13.3');
@ -151,8 +155,7 @@ it("displays properly entry, liquidation price and liquidation bar and it's inte
); );
}); });
cells = screen.getAllByRole('gridcell'); cells = screen.getAllByRole('gridcell');
cell = cells[3]; progressBar = cells[6].lastElementChild?.firstElementChild as HTMLElement;
progressBar = cell.lastElementChild?.firstElementChild as HTMLElement;
expect(progressBar?.classList.contains('bg-warning')).toEqual(true); expect(progressBar?.classList.contains('bg-warning')).toEqual(true);
}); });
@ -161,24 +164,16 @@ it('displays leverage', async () => {
render(<PositionsTable rowData={singleRowData} />); render(<PositionsTable rowData={singleRowData} />);
}); });
const cells = screen.getAllByRole('gridcell'); const cells = screen.getAllByRole('gridcell');
expect(cells[4].textContent).toEqual('1.1'); expect(cells[7].textContent).toEqual('1.1');
}); });
it('displays allocated margin and margin bar', async () => { it('displays allocated margin', async () => {
await act(async () => { await act(async () => {
render(<PositionsTable rowData={singleRowData} />); render(<PositionsTable rowData={singleRowData} />);
}); });
const cells = screen.getAllByRole('gridcell'); const cells = screen.getAllByRole('gridcell');
const cell = cells[5]; const cell = cells[8];
const capitalUtilisation = expect(cell.textContent).toEqual('123,456.00');
cell.firstElementChild?.firstElementChild?.textContent;
const totalBalance = cell.firstElementChild?.lastElementChild?.textContent;
const progressBarTrack = cell.lastElementChild;
const progressBar = progressBarTrack?.firstElementChild as HTMLElement;
const progressBarWidth = progressBar?.style?.width;
expect(capitalUtilisation).toEqual('11.00%');
expect(totalBalance).toEqual('1,234.56');
expect(progressBarWidth).toEqual('11%');
}); });
it('displays realised and unrealised PNL', async () => { it('displays realised and unrealised PNL', async () => {
@ -186,6 +181,6 @@ it('displays realised and unrealised PNL', async () => {
render(<PositionsTable rowData={singleRowData} />); render(<PositionsTable rowData={singleRowData} />);
}); });
const cells = screen.getAllByRole('gridcell'); const cells = screen.getAllByRole('gridcell');
expect(cells[6].textContent).toEqual('1.23'); expect(cells[9].textContent).toEqual('1.23');
expect(cells[7].textContent).toEqual('4.56'); expect(cells[10].textContent).toEqual('4.56');
}); });

View File

@ -2,12 +2,13 @@ import classNames from 'classnames';
import { forwardRef } from 'react'; import { forwardRef } from 'react';
import type { CSSProperties } from 'react'; import type { CSSProperties } from 'react';
import type { import type {
ValueFormatterParams,
ValueGetterParams,
ICellRendererParams, ICellRendererParams,
CellRendererSelectorResult, CellRendererSelectorResult,
} from 'ag-grid-community'; } from 'ag-grid-community';
import type { ValueProps as PriceCellProps } from '@vegaprotocol/ui-toolkit'; import type {
ValueProps as PriceCellProps,
VegaValueFormatterParams,
} from '@vegaprotocol/ui-toolkit';
import { EmptyCell, ProgressBarCell } from '@vegaprotocol/ui-toolkit'; import { EmptyCell, ProgressBarCell } from '@vegaprotocol/ui-toolkit';
import { import {
PriceFlashCell, PriceFlashCell,
@ -43,13 +44,6 @@ interface Props extends AgGridReactProps {
style?: CSSProperties; style?: CSSProperties;
} }
export type PositionsTableValueFormatterParams = Omit<
ValueFormatterParams,
'data' | 'value'
> & {
data: Position;
};
export interface MarketNameCellProps { export interface MarketNameCellProps {
valueFormatted?: [string, string]; valueFormatted?: [string, string];
} }
@ -118,7 +112,7 @@ const ButtonCell = ({
const progressBarValueFormatter = ({ const progressBarValueFormatter = ({
data, data,
node, node,
}: PositionsTableValueFormatterParams): }: VegaValueFormatterParams<Position, 'liquidationPrice'>):
| PriceCellProps['valueFormatted'] | PriceCellProps['valueFormatted']
| undefined => { | undefined => {
if (!data || node?.rowPinned) { if (!data || node?.rowPinned) {
@ -151,7 +145,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
resizable: true, resizable: true,
tooltipComponent: TooltipCellComponent, tooltipComponent: TooltipCellComponent,
}} }}
components={{ PriceFlashCell, ProgressBarCell }} components={{ AmountCell, PriceFlashCell, ProgressBarCell }}
{...props} {...props}
> >
<AgGridColumn <AgGridColumn
@ -160,9 +154,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
cellRenderer={MarketNameCell} cellRenderer={MarketNameCell}
valueFormatter={({ valueFormatter={({
value, value,
}: PositionsTableValueFormatterParams & { }: VegaValueFormatterParams<Position, 'marketName'>) => {
value: Position['marketName'];
}) => {
if (!value) { if (!value) {
return undefined; return undefined;
} }
@ -175,33 +167,38 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
}} }}
/> />
<AgGridColumn <AgGridColumn
headerName={t('Size')} headerName={t('Notional size')}
field="openVolume" field="notional"
valueGetter={({ node, data }: ValueGetterParams) => {
return node?.rowPinned ? data?.notional : data?.openVolume;
}}
type="rightAligned" type="rightAligned"
cellRendererSelector={( cellClass="font-mono text-right"
params: ICellRendererParams
): CellRendererSelectorResult => {
return {
component: params.node.rowPinned ? PriceFlashCell : AmountCell,
};
}}
valueFormatter={({ valueFormatter={({
value, value,
data, data,
node, }: VegaValueFormatterParams<Position, 'notional'>): string => {
}: PositionsTableValueFormatterParams & { if (!value || !data) {
value: Position['openVolume']; return '';
}): AmountCellProps['valueFormatted'] | string => { }
return addDecimalsFormatNumber(value, data.decimals);
}}
/>
<AgGridColumn
headerName={t('Open volume')}
field="openVolume"
type="rightAligned"
cellClass="font-mono text-right"
cellClassRules={signedNumberCssClassRules}
valueFormatter={({
value,
data,
}: VegaValueFormatterParams<Position, 'openVolume'>):
| string
| undefined => {
if (!value || !data) { if (!value || !data) {
return undefined; return undefined;
} }
if (node?.rowPinned) { return volumePrefix(
return addDecimalsFormatNumber(value, data.decimals); addDecimalsFormatNumber(value, data.positionDecimalPlaces)
} );
return data;
}} }}
/> />
<AgGridColumn <AgGridColumn
@ -219,9 +216,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
value, value,
data, data,
node, node,
}: PositionsTableValueFormatterParams & { }: VegaValueFormatterParams<Position, 'markPrice'>) => {
value: Position['markPrice'];
}) => {
if (!data || !value || node?.rowPinned) { if (!data || !value || node?.rowPinned) {
return undefined; return undefined;
} }
@ -237,16 +232,34 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
); );
}} }}
/> />
<AgGridColumn headerName={t('Settlement asset')} field="assetSymbol" />
<AgGridColumn <AgGridColumn
headerName={t('Entry price')} headerName={t('Entry price')}
field="averageEntryPrice" field="averageEntryPrice"
headerComponentParams={{ type="rightAligned"
template: cellRendererSelector={(
'<div class="ag-cell-label-container" role="presentation">' + params: ICellRendererParams
` <span>${t('Liquidation price (est)')}</span>` + ): CellRendererSelectorResult => {
' <span ref="eText" class="ag-header-cell-text"></span>' + return {
'</div>', component: params.node.rowPinned ? EmptyCell : PriceFlashCell,
};
}} }}
valueFormatter={({
data,
value,
node,
}: VegaValueFormatterParams<Position, 'averageEntryPrice'>):
| string
| undefined => {
if (!data || node?.rowPinned || !value) {
return undefined;
}
return addDecimalsFormatNumber(value, data.marketDecimalPlaces);
}}
/>
<AgGridColumn
headerName={t('Liquidation price (est)')}
field="liquidationPrice"
flex={2} flex={2}
headerTooltip={t( headerTooltip={t(
'Liquidation prices are based on the amount of collateral you have available, the risk of your position and the liquidity on the order book. They can change rapidly based on the profit and loss of your positions and any changes to collateral from opening/closing other positions and making deposits/withdrawals.' 'Liquidation prices are based on the amount of collateral you have available, the risk of your position and the liquidity on the order book. They can change rapidly based on the profit and loss of your positions and any changes to collateral from opening/closing other positions and making deposits/withdrawals.'
@ -273,41 +286,32 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
}} }}
valueFormatter={({ valueFormatter={({
value, value,
node, }: VegaValueFormatterParams<Position, 'currentLeverage'>) =>
}: PositionsTableValueFormatterParams & {
value: Position['currentLeverage'];
}) =>
value === undefined ? undefined : formatNumber(value.toString(), 1) value === undefined ? undefined : formatNumber(value.toString(), 1)
} }
/> />
<AgGridColumn <AgGridColumn
headerName={t('Margin allocated')} headerName={t('Margin allocated')}
field="capitalUtilisation" field="marginAccountBalance"
type="rightAligned" type="rightAligned"
flex={2}
cellRenderer="ProgressBarCell"
cellRendererSelector={( cellRendererSelector={(
params: ICellRendererParams params: ICellRendererParams
): CellRendererSelectorResult => { ): CellRendererSelectorResult => {
return { return {
component: params.node.rowPinned ? EmptyCell : ProgressBarCell, component: params.node.rowPinned ? EmptyCell : PriceFlashCell,
}; };
}} }}
valueFormatter={({ valueFormatter={({
data, data,
value, value,
node, node,
}: PositionsTableValueFormatterParams & { }: VegaValueFormatterParams<Position, 'marginAccountBalance'>):
value: Position['capitalUtilisation']; | string
}): PriceCellProps['valueFormatted'] | undefined => { | undefined => {
if (!data || node?.rowPinned) { if (!data || node?.rowPinned || !value) {
return undefined; return undefined;
} }
return { return formatNumber(value, data.decimals);
low: `${formatNumber(value, 2)}%`,
high: addDecimalsFormatNumber(data.totalBalance, data.decimals),
value: Number(value),
};
}} }}
/> />
<AgGridColumn <AgGridColumn
@ -318,10 +322,8 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
valueFormatter={({ valueFormatter={({
value, value,
data, data,
}: PositionsTableValueFormatterParams & { }: VegaValueFormatterParams<Position, 'realisedPNL'>) =>
value: Position['realisedPNL']; value === undefined || data === undefined
}) =>
value === undefined
? undefined ? undefined
: addDecimalsFormatNumber(value.toString(), data.decimals) : addDecimalsFormatNumber(value.toString(), data.decimals)
} }
@ -338,10 +340,8 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
valueFormatter={({ valueFormatter={({
value, value,
data, data,
}: PositionsTableValueFormatterParams & { }: VegaValueFormatterParams<Position, 'unrealisedPNL'>) =>
value: Position['unrealisedPNL']; value === undefined || data === undefined
}) =>
value === undefined
? undefined ? undefined
: addDecimalsFormatNumber(value.toString(), data.decimals) : addDecimalsFormatNumber(value.toString(), data.decimals)
} }
@ -356,9 +356,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
type="rightAligned" type="rightAligned"
valueFormatter={({ valueFormatter={({
value, value,
}: PositionsTableValueFormatterParams & { }: VegaValueFormatterParams<Position, 'updatedAt'>) => {
value: Position['updatedAt'];
}) => {
if (!value) { if (!value) {
return value; return value;
} }