vega-frontend-monorepo/libs/positions/src/lib/use-positions-data.tsx

87 lines
2.9 KiB
TypeScript

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<AgGridReact>,
assetSymbol?: string
) => {
const variables = useMemo(() => ({ partyId }), [partyId]);
const summaryRow = useRef<ReturnType<typeof getSummaryRow>>();
const dataRef = useRef<Position[] | null>(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<Position[], never>({
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,
};
};