diff --git a/apps/trading-e2e/src/integration/trading-positions.cy.ts b/apps/trading-e2e/src/integration/trading-positions.cy.ts index 0db3dc86c..b81e89086 100644 --- a/apps/trading-e2e/src/integration/trading-positions.cy.ts +++ b/apps/trading-e2e/src/integration/trading-positions.cy.ts @@ -42,22 +42,20 @@ describe('positions', { tags: '@smoke' }, () => { cy.wrap($prices).invoke('text').should('not.be.empty'); }); - cy.get('[col-id="liquidationPrice"]') - .should('contain.text', '85,093.38') // entry price - .should('contain.text', '0.00'); // liquidation price + cy.get('[col-id="liquidationPrice"]').should('contain.text', '0'); // liquidation price cy.get('[col-id="currentLeverage"]').should('contain.text', '0.8'); cy.get('[col-id="marginAccountBalance"]') // margin allocated - .should('contain.text', '1,000.00000'); + .should('contain.text', '1,000'); cy.get('[col-id="unrealisedPNL"]').each(($unrealisedPnl) => { cy.wrap($unrealisedPnl).invoke('text').should('not.be.empty'); }); cy.get('[col-id="notional"]').should('contain.text', '276,761.40348'); // Total tDAI position - 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="realisedPNL"]').should('contain.text', '0.001'); // Total Realised PNL + cy.get('[col-id="unrealisedPNL"]').should('contain.text', '8.95'); // Total Unrealised PNL }); cy.getByTestId('close-position').should('be.visible').and('have.length', 3); diff --git a/libs/positions/src/lib/positions-manager.tsx b/libs/positions/src/lib/positions-manager.tsx index 7b1925e07..f149eaa3b 100644 --- a/libs/positions/src/lib/positions-manager.tsx +++ b/libs/positions/src/lib/positions-manager.tsx @@ -1,11 +1,6 @@ import { useRef } from 'react'; import { AsyncRenderer, Icon, Intent } from '@vegaprotocol/ui-toolkit'; -import { - useClosePosition, - usePositionsData, - PositionsTable, - getSummaryRowData, -} from '../'; +import { useClosePosition, usePositionsData, PositionsTable } from '../'; import type { AgGridReact } from 'ag-grid-react'; import { Requested } from './close-position-dialog/requested'; import { Complete } from './close-position-dialog/complete'; @@ -34,7 +29,6 @@ export const PositionsManager = ({ partyId }: PositionsManagerProps) => { submit(position)} /> diff --git a/libs/positions/src/lib/positions-table.spec.tsx b/libs/positions/src/lib/positions-table.spec.tsx index 7880d2f5b..87861735b 100644 --- a/libs/positions/src/lib/positions-table.spec.tsx +++ b/libs/positions/src/lib/positions-table.spec.tsx @@ -92,7 +92,7 @@ it('add color and sign to amount, displays positive notional value', async () => expect(cells[2].classList.contains('text-vega-green-dark')).toBeTruthy(); expect(cells[2].classList.contains('text-vega-red-dark')).toBeFalsy(); expect(cells[2].textContent).toEqual('+100'); - expect(cells[1].textContent).toEqual('123.00'); + expect(cells[1].textContent).toEqual('1,230'); await act(async () => { result.rerender( @@ -102,7 +102,7 @@ it('add color and sign to amount, displays positive notional value', async () => expect(cells[2].classList.contains('text-vega-green-dark')).toBeFalsy(); expect(cells[2].classList.contains('text-vega-red-dark')).toBeTruthy(); expect(cells[2].textContent?.startsWith('-100')).toBeTruthy(); - expect(cells[1].textContent).toEqual('123.00'); + expect(cells[1].textContent).toEqual('1,230'); }); it('displays mark price', async () => { @@ -139,23 +139,13 @@ it("displays properly entry, liquidation price and liquidation bar and it's inte }); let cells = screen.getAllByRole('gridcell'); const entryPrice = cells[5].firstElementChild?.firstElementChild?.textContent; - const liquidationPrice = - cells[6].firstElementChild?.lastElementChild?.textContent; - const progressBarTrack = cells[6].lastElementChild; - let progressBar = progressBarTrack?.firstElementChild as HTMLElement; - const progressBarWidth = progressBar?.style?.width; expect(entryPrice).toEqual('13.3'); - expect(liquidationPrice).toEqual('8.3'); - expect(progressBar.classList.contains('bg-warning')).toEqual(false); - expect(progressBarWidth).toEqual('20%'); await act(async () => { result.rerender( ); }); cells = screen.getAllByRole('gridcell'); - progressBar = cells[6].lastElementChild?.firstElementChild as HTMLElement; - expect(progressBar?.classList.contains('bg-warning')).toEqual(true); }); it('displays leverage', async () => { @@ -172,7 +162,7 @@ it('displays allocated margin', async () => { }); const cells = screen.getAllByRole('gridcell'); const cell = cells[8]; - expect(cell.textContent).toEqual('123,456.00'); + expect(cell.textContent).toEqual('123,456'); }); it('displays realised and unrealised PNL', async () => { diff --git a/libs/positions/src/lib/positions-table.tsx b/libs/positions/src/lib/positions-table.tsx index f1b27f6c2..bda7600d7 100644 --- a/libs/positions/src/lib/positions-table.tsx +++ b/libs/positions/src/lib/positions-table.tsx @@ -1,20 +1,16 @@ import classNames from 'classnames'; import { forwardRef } from 'react'; import type { CSSProperties } from 'react'; +import type { CellRendererSelectorResult } from 'ag-grid-community'; import type { - ICellRendererParams, - CellRendererSelectorResult, -} from 'ag-grid-community'; -import type { - ValueProps as PriceCellProps, VegaValueFormatterParams, VegaValueGetterParams, TypedDataAgGrid, } from '@vegaprotocol/ui-toolkit'; -import { EmptyCell, ProgressBarCell } from '@vegaprotocol/ui-toolkit'; +import { ProgressBarCell } from '@vegaprotocol/ui-toolkit'; import { PriceFlashCell, - addDecimalsFormatNumber, + addDecimalsNormalizeNumber, volumePrefix, t, toBigNum, @@ -29,7 +25,7 @@ import { AgGridColumn } from 'ag-grid-react'; import type { AgGridReact } from 'ag-grid-react'; import type { Position } from './positions-data-providers'; import { Schema } from '@vegaprotocol/types'; -import { Intent, Button, TooltipCellComponent } from '@vegaprotocol/ui-toolkit'; +import { Button, TooltipCellComponent } from '@vegaprotocol/ui-toolkit'; import { getRowId } from './use-positions-data'; interface Props extends TypedDataAgGrid { @@ -72,11 +68,11 @@ export const AmountCell = ({ valueFormatted }: AmountCellProps) => { className={classNames('text-right', signedNumberCssClass(openVolume))} > {volumePrefix( - addDecimalsFormatNumber(openVolume, positionDecimalPlaces) + addDecimalsNormalizeNumber(openVolume, positionDecimalPlaces) )}
- {addDecimalsFormatNumber(notional, marketDecimalPlaces)} + {addDecimalsNormalizeNumber(notional, marketDecimalPlaces)}
) : null; @@ -102,27 +98,6 @@ const ButtonCell = ({ ); }; -const progressBarValueFormatter = ({ - data, - node, -}: VegaValueFormatterParams): - | PriceCellProps['valueFormatted'] - | undefined => { - if (!data || node?.rowPinned) { - return undefined; - } - const min = BigInt(data.averageEntryPrice); - const max = BigInt(data.liquidationPrice); - const mid = BigInt(data.markPrice); - const range = max - min; - return { - low: addDecimalsFormatNumber(min.toString(), data.marketDecimalPlaces), - high: addDecimalsFormatNumber(max.toString(), data.marketDecimalPlaces), - value: range ? Number(((mid - min) * BigInt(100)) / range) : 0, - intent: data.lowMarginLevel ? Intent.Warning : undefined, - }; -}; - export const PositionsTable = forwardRef( ({ onClose, ...props }, ref) => { return ( @@ -173,14 +148,17 @@ export const PositionsTable = forwardRef( }: VegaValueGetterParams) => { return data?.notional === undefined ? undefined - : toBigNum(data?.notional, data.decimals).toNumber(); + : toBigNum(data?.notional, data.marketDecimalPlaces).toNumber(); }} valueFormatter={({ data, }: VegaValueFormatterParams) => { return !data ? undefined - : addDecimalsFormatNumber(data.notional, data.decimals); + : addDecimalsNormalizeNumber( + data.notional, + data.marketDecimalPlaces + ); }} /> ( return data?.openVolume === undefined ? undefined : volumePrefix( - addDecimalsFormatNumber( + addDecimalsNormalizeNumber( data.openVolume, data.positionDecimalPlaces ) @@ -216,11 +194,9 @@ export const PositionsTable = forwardRef( headerName={t('Mark price')} field="markPrice" type="rightAligned" - cellRendererSelector={( - params: ICellRendererParams - ): CellRendererSelectorResult => { + cellRendererSelector={(): CellRendererSelectorResult => { return { - component: params.node.rowPinned ? EmptyCell : PriceFlashCell, + component: PriceFlashCell, }; }} filter="agNumberColumnFilter" @@ -237,7 +213,7 @@ export const PositionsTable = forwardRef( data, node, }: VegaValueFormatterParams) => { - if (!data || node?.rowPinned) { + if (!data) { return undefined; } if ( @@ -246,7 +222,7 @@ export const PositionsTable = forwardRef( ) { return '-'; } - return addDecimalsFormatNumber( + return addDecimalsNormalizeNumber( data.markPrice, data.marketDecimalPlaces ); @@ -257,11 +233,9 @@ export const PositionsTable = forwardRef( headerName={t('Entry price')} field="averageEntryPrice" type="rightAligned" - cellRendererSelector={( - params: ICellRendererParams - ): CellRendererSelectorResult => { + cellRendererSelector={(): CellRendererSelectorResult => { return { - component: params.node.rowPinned ? EmptyCell : PriceFlashCell, + component: PriceFlashCell, }; }} filter="agNumberColumnFilter" @@ -281,10 +255,10 @@ export const PositionsTable = forwardRef( }: VegaValueFormatterParams): | string | undefined => { - if (!data || node?.rowPinned) { + if (!data) { return undefined; } - return addDecimalsFormatNumber( + return addDecimalsNormalizeNumber( data.averageEntryPrice, data.marketDecimalPlaces ); @@ -293,40 +267,45 @@ export const PositionsTable = forwardRef( { + return { + component: PriceFlashCell, + }; + }} filter="agNumberColumnFilter" valueGetter={({ data, }: VegaValueGetterParams) => { - return !data + return data?.liquidationPrice === undefined || !data ? undefined : toBigNum( - data?.liquidationPrice, + data.liquidationPrice, data.marketDecimalPlaces ).toNumber(); }} - cellRendererSelector={( - params: ICellRendererParams - ): CellRendererSelectorResult => { - return { - component: params.node.rowPinned ? EmptyCell : ProgressBarCell, - }; + valueFormatter={({ + data, + }: VegaValueFormatterParams): + | string + | undefined => { + if (!data) { + return undefined; + } + return addDecimalsNormalizeNumber( + data.liquidationPrice, + data.marketDecimalPlaces + ); }} - valueFormatter={progressBarValueFormatter} /> { + cellRendererSelector={(): CellRendererSelectorResult => { return { - component: params.node.rowPinned ? EmptyCell : PriceFlashCell, + component: PriceFlashCell, }; }} valueFormatter={({ @@ -340,11 +319,9 @@ export const PositionsTable = forwardRef( field="marginAccountBalance" type="rightAligned" filter="agNumberColumnFilter" - cellRendererSelector={( - params: ICellRendererParams - ): CellRendererSelectorResult => { + cellRendererSelector={(): CellRendererSelectorResult => { return { - component: params.node.rowPinned ? EmptyCell : PriceFlashCell, + component: PriceFlashCell, }; }} valueGetter={({ @@ -360,10 +337,10 @@ export const PositionsTable = forwardRef( }: VegaValueFormatterParams): | string | undefined => { - if (!data || node?.rowPinned) { + if (!data) { return undefined; } - return addDecimalsFormatNumber( + return addDecimalsNormalizeNumber( data.marginAccountBalance, data.decimals ); @@ -387,7 +364,7 @@ export const PositionsTable = forwardRef( }: VegaValueFormatterParams) => { return !data ? undefined - : addDecimalsFormatNumber(data.realisedPNL, data.decimals); + : addDecimalsNormalizeNumber(data.realisedPNL, data.decimals); }} cellRenderer="PriceFlashCell" headerTooltip={t( @@ -412,7 +389,7 @@ export const PositionsTable = forwardRef( }: VegaValueFormatterParams) => !data ? undefined - : addDecimalsFormatNumber(data.unrealisedPNL, data.decimals) + : addDecimalsNormalizeNumber(data.unrealisedPNL, data.decimals) } cellRenderer="PriceFlashCell" headerTooltip={t( @@ -435,11 +412,9 @@ export const PositionsTable = forwardRef( /> {onClose ? ( { + cellRendererSelector={(): CellRendererSelectorResult => { return { - component: params.node.rowPinned ? EmptyCell : ButtonCell, + component: ButtonCell, }; }} cellRendererParams={{ onClick: onClose }} diff --git a/libs/positions/src/lib/use-positions-data.tsx b/libs/positions/src/lib/use-positions-data.tsx index b3c41cf82..42872e92d 100644 --- a/libs/positions/src/lib/use-positions-data.tsx +++ b/libs/positions/src/lib/use-positions-data.tsx @@ -1,41 +1,13 @@ import { useCallback, useMemo, useRef } from 'react'; import type { RefObject } from 'react'; -import { BigNumber } from 'bignumber.js'; import type { AgGridReact } from 'ag-grid-react'; import type { Position } from './positions-data-providers'; import { positionsMetricsProvider } from './positions-data-providers'; import type { PositionsMetricsProviderVariables } from './positions-data-providers'; -import { t, toBigNum, useDataProvider } from '@vegaprotocol/react-helpers'; +import { useDataProvider } from '@vegaprotocol/react-helpers'; export const getRowId = ({ data }: { data: Position }) => data.marketId; -export const getSummaryRowData = (positions: Position[]) => { - const summaryRow = { - notional: new BigNumber(0), - realisedPNL: BigInt(0), - unrealisedPNL: BigInt(0), - }; - positions.forEach((position) => { - summaryRow.notional = summaryRow.notional.plus( - toBigNum(position.notional, position.marketDecimalPlaces) - ); - summaryRow.realisedPNL += BigInt(position.realisedPNL); - summaryRow.unrealisedPNL += BigInt(position.unrealisedPNL); - }); - const decimals = positions[0]?.decimals || 0; - return { - marketName: t('Total'), - // we are using asset decimals instead of market decimals because each market can have different decimals - notional: summaryRow.notional - .multipliedBy(10 ** decimals) - .toFixed() - .toString(), - realisedPNL: summaryRow.realisedPNL.toString(), - unrealisedPNL: summaryRow.unrealisedPNL.toString(), - decimals, - }; -}; - export const usePositionsData = ( partyId: string, gridRef: RefObject @@ -76,18 +48,6 @@ export const usePositionsData = ( add, addIndex: 0, }); - const summaryRowNode = gridRef.current.api.getPinnedBottomRow(0); - if (summaryRowNode && dataRef.current) { - summaryRowNode.data = getSummaryRowData(dataRef.current); - gridRef.current.api.refreshCells({ - force: true, - rowNodes: [summaryRowNode], - }); - } else { - gridRef.current.api.setPinnedBottomRowData( - dataRef.current ? [getSummaryRowData(dataRef.current)] : [] - ); - } } return true; }, diff --git a/libs/ui-toolkit/src/components/progress-bar/grid-progress-bar.tsx b/libs/ui-toolkit/src/components/progress-bar/grid-progress-bar.tsx index a487550cc..70b4f66a8 100644 --- a/libs/ui-toolkit/src/components/progress-bar/grid-progress-bar.tsx +++ b/libs/ui-toolkit/src/components/progress-bar/grid-progress-bar.tsx @@ -36,6 +36,6 @@ export const progressBarCellRendererSelector = ( params: ICellRendererParams ): CellRendererSelectorResult => { return { - component: params.node.rowPinned ? EmptyCell : ProgressBarCell, + component: ProgressBarCell, }; };