vega-frontend-monorepo/libs/positions/src/lib/positions.tsx
Bartłomiej Głownia 6de90c6b1f
feat(#840): update positions tab (#1101)
* feat(#473): add positions metrics data provider

* feat(#473) add positions stats

* feat(#473) add positions stats

* feat(#473): add positions stats

* feat(#473): add positions stats

* feat(#473): position metrics, test and refactoring

* feat(#473): add unit tests to positions table

* feat(#473): fix spelling, order positions by updated at desc

* feat(#473): protect from division by 0

* feat(#473): fix trading positions e2e tests

* feat(#473): fix e2e data mocks

* feat(#473): post code review clean up

* feat(#993): dependencies handling in data provider

* feat(#993): fix e2e tests data mocks

* feat(#993): remove position metrics mocks, add market data market id

* feat(#993): add missing mocks, fix combine function

* feat(#993): set loading initially to true, add unit tests

* feat(#993): cleanup, add comments

* feat(#993): remove undefined from client type

* feat(#993): cosmetic changes

* feat(#840): update positions tab

* feat:(#993): pass informaton about update callback cause

* feat(#840): update positions tab

* feat(#840): update positions tab

* feat(#840): update positions tab

* chore: skip handles 5000 markets e2e test

* feat(#840): update positions tab

* feat(#840): rename assetDecimals to decimals

* feat(#840): close position

* feat(#993): notify about update

* feat(#840): add use close position hook

* feat(#840): do not show 0 volume positions, make liquidation price minimum 0

* feat(#840): post code review fixes and improvments

* feat: fix fill-table spec
2022-09-02 13:53:00 -07:00

109 lines
3.6 KiB
TypeScript

import { useRef, useCallback, useMemo, memo } from 'react';
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { BigNumber } from 'bignumber.js';
import { t, toBigNum, useDataProvider } from '@vegaprotocol/react-helpers';
import type { AgGridReact } from 'ag-grid-react';
import filter from 'lodash/filter';
import PositionsTable from './positions-table';
import type { GetRowsParams } from './positions-table';
import { positionsMetricsDataProvider as dataProvider } from './positions-data-providers';
import { AssetBalance } from '@vegaprotocol/accounts';
import type { Position } from './positions-data-providers';
interface PositionsProps {
partyId: string;
assetSymbol: string;
onClose: (position: Position) => void;
}
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 Positions = memo(
({ partyId, assetSymbol, onClose }: PositionsProps) => {
const gridRef = useRef<AgGridReact | null>(null);
const variables = useMemo(() => ({ partyId }), [partyId]);
const dataRef = useRef<Position[] | null>(null);
const update = useCallback(
({ data }: { data: Position[] | null }) => {
if (!gridRef.current?.api) {
return false;
}
dataRef.current = filter(data, { assetSymbol });
gridRef.current.api.refreshInfiniteCache();
return true;
},
[assetSymbol]
);
const { data, error, loading } = useDataProvider<Position[], never>({
dataProvider,
update,
variables,
});
dataRef.current = filter(data, { assetSymbol });
const getRows = 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) {
gridRef.current.api.setPinnedBottomRowData([
getSummaryRow(rowsThisBlock),
]);
}
};
return (
<AsyncRenderer loading={loading} error={error} data={data}>
<div className="p-2">
<h4 className="text-lg">
{assetSymbol} {t('markets')}
</h4>
<p>
{assetSymbol} {t('balance')}:
<span className="pl-1 font-mono">
<AssetBalance partyId={partyId} assetSymbol={assetSymbol} />
</span>
</p>
</div>
<PositionsTable
domLayout="autoHeight"
style={{ width: '100%' }}
ref={gridRef}
rowModelType={data?.length ? 'infinite' : 'clientSide'}
rowData={data?.length ? undefined : []}
datasource={{ getRows }}
onClose={onClose}
/>
</AsyncRenderer>
);
}
);