chore: update fills tab - add tooltip with fees breakdown (#2606)
* chore: update fills tab - add tooltip with fees breakdown * chore: update fills tab - fix failing unit test * chore: update fills tab - add unit test * chore: update fills tab - adjust int test
This commit is contained in:
parent
6d3795f1f4
commit
2b28ff6c18
@ -66,7 +66,9 @@ describe('Portfolio page tabs', { tags: '@smoke' }, () => {
|
||||
|
||||
it('data should be properly rendered', () => {
|
||||
cy.get('.ag-center-cols-container .ag-row').should('have.length', 5);
|
||||
cy.contains('.ag-center-cols-container button', 'tEURO').click();
|
||||
cy.get('[role="gridcell"][col-id="account-asset"] button')
|
||||
.contains('tEURO')
|
||||
.click();
|
||||
cy.getByTestId('dialog-title').should(
|
||||
'have.text',
|
||||
'Asset details - tEURO'
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { act, render, screen, waitFor } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { getDateTimeFormat } from '@vegaprotocol/react-helpers';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
@ -57,8 +58,8 @@ describe('FillsTable', () => {
|
||||
const expectedHeaders = [
|
||||
'Market',
|
||||
'Size',
|
||||
'Value',
|
||||
'Filled value',
|
||||
'Price',
|
||||
'Notional',
|
||||
'Role',
|
||||
'Fee',
|
||||
'Date',
|
||||
@ -82,7 +83,7 @@ describe('FillsTable', () => {
|
||||
},
|
||||
});
|
||||
|
||||
render(<FillsTable partyId={partyId} rowData={[buyerFill]} />);
|
||||
render(<FillsTable partyId={partyId} rowData={[{ ...buyerFill }]} />);
|
||||
await waitForGridToBeInTheDOM();
|
||||
await waitForDataToHaveLoaded();
|
||||
|
||||
@ -179,4 +180,38 @@ describe('FillsTable', () => {
|
||||
.find((c) => c.getAttribute('col-id') === 'aggressor')
|
||||
).toHaveTextContent('Maker');
|
||||
});
|
||||
|
||||
it('should render tooltip over fees', async () => {
|
||||
const partyId = 'party-id';
|
||||
const takerFill = generateFill({
|
||||
seller: {
|
||||
id: partyId,
|
||||
},
|
||||
aggressor: Schema.Side.SIDE_SELL,
|
||||
});
|
||||
act(() => {
|
||||
render(<FillsTable partyId={partyId} rowData={[takerFill]} />);
|
||||
});
|
||||
await waitForGridToBeInTheDOM();
|
||||
await waitForDataToHaveLoaded();
|
||||
|
||||
const feeCell = screen
|
||||
.getAllByRole('gridcell')
|
||||
.find(
|
||||
(c) =>
|
||||
c.getAttribute('col-id') ===
|
||||
'market.tradableInstrument.instrument.product'
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(feeCell).toBeInTheDocument();
|
||||
});
|
||||
act(() => {
|
||||
userEvent.hover(feeCell as HTMLElement);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('fee-breakdown-tooltip')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,4 +1,9 @@
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import type {
|
||||
AgGridReact,
|
||||
AgGridReactProps,
|
||||
AgReactUiProps,
|
||||
} from 'ag-grid-react';
|
||||
import type { ITooltipParams } from 'ag-grid-community';
|
||||
import {
|
||||
addDecimal,
|
||||
addDecimalsFormatNumber,
|
||||
@ -15,7 +20,6 @@ import type { VegaValueFormatterParams } from '@vegaprotocol/ui-toolkit';
|
||||
import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
|
||||
import { forwardRef } from 'react';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import type { AgGridReactProps, AgReactUiProps } from 'ag-grid-react';
|
||||
import type { Trade } from './fills-data-provider';
|
||||
|
||||
export type Props = (AgGridReactProps | AgReactUiProps) & {
|
||||
@ -31,6 +35,8 @@ export const FillsTable = forwardRef<AgGridReact, Props>(
|
||||
defaultColDef={{ flex: 1, resizable: true }}
|
||||
style={{ width: '100%', height: '100%' }}
|
||||
getRowId={({ data }) => data?.id}
|
||||
tooltipShowDelay={0}
|
||||
tooltipHideDelay={2000}
|
||||
{...props}
|
||||
>
|
||||
<AgGridColumn
|
||||
@ -54,13 +60,13 @@ export const FillsTable = forwardRef<AgGridReact, Props>(
|
||||
valueFormatter={formatSize(partyId)}
|
||||
/>
|
||||
<AgGridColumn
|
||||
headerName={t('Value')}
|
||||
headerName={t('Price')}
|
||||
field="price"
|
||||
valueFormatter={formatPrice}
|
||||
type="rightAligned"
|
||||
/>
|
||||
<AgGridColumn
|
||||
headerName={t('Filled value')}
|
||||
headerName={t('Notional')}
|
||||
field="price"
|
||||
valueFormatter={formatTotal}
|
||||
type="rightAligned"
|
||||
@ -75,6 +81,9 @@ export const FillsTable = forwardRef<AgGridReact, Props>(
|
||||
field="market.tradableInstrument.instrument.product"
|
||||
valueFormatter={formatFee(partyId)}
|
||||
type="rightAligned"
|
||||
tooltipField="market.tradableInstrument.instrument.product"
|
||||
tooltipComponent={FeesBreakdownTooltip}
|
||||
tooltipComponentParams={{ partyId }}
|
||||
/>
|
||||
<AgGridColumn
|
||||
headerName={t('Date')}
|
||||
@ -148,16 +157,15 @@ const formatTotal = ({
|
||||
if (!data?.market || !isNumeric(value)) {
|
||||
return '-';
|
||||
}
|
||||
const asset =
|
||||
data?.market.tradableInstrument.instrument.product.settlementAsset.symbol;
|
||||
const { symbol: assetSymbol, decimals: assetDecimals } =
|
||||
data?.market.tradableInstrument.instrument.product.settlementAsset ?? {};
|
||||
const size = new BigNumber(
|
||||
addDecimal(data?.size, data?.market.positionDecimalPlaces)
|
||||
);
|
||||
const price = new BigNumber(addDecimal(value, data?.market.decimalPlaces));
|
||||
|
||||
const total = size.times(price).toString();
|
||||
const valueFormatted = formatNumber(total, data?.market.decimalPlaces);
|
||||
return `${valueFormatted} ${asset}`;
|
||||
const valueFormatted = formatNumber(total, assetDecimals);
|
||||
return `${valueFormatted} ${assetSymbol}`;
|
||||
};
|
||||
|
||||
const formatRole = (partyId: string) => {
|
||||
@ -210,3 +218,50 @@ const formatFee = (partyId: string) => {
|
||||
return `${totalFees} ${asset.symbol}`;
|
||||
};
|
||||
};
|
||||
|
||||
const FeesBreakdownTooltip = ({
|
||||
data,
|
||||
value,
|
||||
valueFormatted,
|
||||
partyId,
|
||||
}: ITooltipParams & { partyId?: string }) => {
|
||||
if (!value?.settlementAsset || !data) {
|
||||
return null;
|
||||
}
|
||||
const asset = value.settlementAsset;
|
||||
let feesObj;
|
||||
if (data?.buyer.id === partyId) {
|
||||
feesObj = data?.buyerFee;
|
||||
} else if (data?.seller.id === partyId) {
|
||||
feesObj = data?.sellerFee;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
data-testid="fee-breakdown-tooltip"
|
||||
className="max-w-sm border border-neutral-600 bg-neutral-100 dark:bg-neutral-800 px-4 py-2 z-20 rounded text-sm break-word text-black dark:text-white"
|
||||
>
|
||||
<dl className="grid grid-cols-2 gap-x-2">
|
||||
<dt>{t('Infrastructure fee')}</dt>
|
||||
<dd className="text-right">
|
||||
{addDecimalsFormatNumber(feesObj.infrastructureFee, asset.decimals)}{' '}
|
||||
{asset.symbol}
|
||||
</dd>
|
||||
<dt>{t('Liquidity fee')}</dt>
|
||||
<dd className="text-right">
|
||||
{addDecimalsFormatNumber(feesObj.liquidityFee, asset.decimals)}{' '}
|
||||
{asset.symbol}
|
||||
</dd>
|
||||
<dt>{t('Maker fee')}</dt>
|
||||
<dd className="text-right">
|
||||
{addDecimalsFormatNumber(feesObj.makerFee, asset.decimals)}{' '}
|
||||
{asset.symbol}
|
||||
</dd>
|
||||
<dt>{t('Total fees')}</dt>
|
||||
<dd className="text-right">{valueFormatted}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user