import isEqual from 'lodash/isEqual'; 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 { GetRowsParams } from './positions-table'; import type { Position } from './positions-data-providers'; import { positionsMetricsDataProvider as dataProvider } from './positions-data-providers'; import filter from 'lodash/filter'; import { t, toBigNum, useDataProvider } from '@vegaprotocol/react-helpers'; const getSummaryRow = (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, assetSymbol?: string ) => { const variables = useMemo(() => ({ partyId }), [partyId]); const summaryRow = useRef>(); const dataRef = useRef(null); const update = useCallback( ({ data }: { data: Position[] | null }) => { dataRef.current = assetSymbol ? filter(data, { assetSymbol }) : data; gridRef.current?.api?.refreshInfiniteCache(); return true; }, [assetSymbol, gridRef] ); const { data, error, loading } = useDataProvider({ dataProvider, update, variables, }); if (!dataRef.current && data) { dataRef.current = assetSymbol ? filter(data, { assetSymbol }) : data; } const getRows = useCallback( async ({ successCallback, startRow, endRow }: GetRowsParams) => { const rowsThisBlock = dataRef.current ? dataRef.current.slice(startRow, endRow) : []; const lastRow = dataRef.current?.length ?? -1; successCallback(rowsThisBlock, lastRow); if (gridRef.current?.api) { const updatedSummaryRow = getSummaryRow(rowsThisBlock); if (!isEqual(updatedSummaryRow, summaryRow.current)) { summaryRow.current = updatedSummaryRow; gridRef.current.api.setPinnedBottomRowData([updatedSummaryRow]); } } }, [gridRef] ); return { data, error, loading, getRows, }; };