feat: add tooltips to headers on the LP dashboard and add some new data points (#2064)

* feat: add tooltips to headers on the details view

* feat: add header tooltips to liqudity dashboard markets page

* feat: add fee level and target stake to market summary list

These two data points are already in our health bar, but we want to call
them out more visibly so you don't have to hover to see them.

* feat: add % Target stake column to market list page

Adds a column which calculates what percentage of the target stake is
currently being supplied. We _trim_ this number to the whole percentage
value, so some precision may be lost, which we can add later if we want.

* chore: remove the estimated return/APY column while we dont use it

We can revert this commit later if we want it to return.

* feat: wrap the status pill with a tooltip

Uses the ui-toolkit tooltip to wrap the status pill, providing a bit
more information for what the statuses mean.

* chore: wrap getTooltipDescription in t() translate fn
This commit is contained in:
Ciaran McGhie 2022-11-22 15:50:49 +00:00 committed by GitHub
parent 9aa672968f
commit ce62342d9a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 139 additions and 20 deletions

View File

@ -8,8 +8,17 @@ import type {
} from 'ag-grid-community';
import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-alpine.css';
import { t, addDecimalsFormatNumber } from '@vegaprotocol/react-helpers';
import { Icon, AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import {
t,
addDecimalsFormatNumber,
formatNumberPercentage,
toBigNum,
} from '@vegaprotocol/react-helpers';
import {
Icon,
AsyncRenderer,
TooltipCellComponent,
} from '@vegaprotocol/ui-toolkit';
import type { Market } from '@vegaprotocol/liquidity';
import {
useMarketsLiquidity,
@ -50,9 +59,11 @@ export const MarketList = () => {
sortable: true,
unSortIcon: true,
cellClass: ['flex', 'flex-col', 'justify-center'],
tooltipComponent: TooltipCellComponent,
}}
getRowId={getRowId}
isRowClickable
tooltipShowDelay={500}
>
<AgGridColumn
headerName={t('Market (futures)')}
@ -78,6 +89,7 @@ export const MarketList = () => {
}}
minWidth={100}
flex="1"
headerTooltip={t('The market name and settlement asset')}
/>
<AgGridColumn
@ -90,10 +102,11 @@ export const MarketList = () => {
.decimals
)} (${displayChange(data.volumeChange)})`
}
headerTooltip={t('The trade volume over the last 24h')}
/>
<AgGridColumn
headerName={t('Committed bond/stake')}
headerName={t('Committed bond')}
field="liquidityCommitted"
valueFormatter={({ value, data }: ValueFormatterParams) =>
formatWithAsset(
@ -101,6 +114,47 @@ export const MarketList = () => {
data.tradableInstrument.instrument.product.settlementAsset
)
}
headerTooltip={t(
'The amount of funds allocated to provide liquidity'
)}
/>
<AgGridColumn
headerName={t('Target stake')}
field="target"
valueFormatter={({ value, data }: ValueFormatterParams) =>
formatWithAsset(
value,
data.tradableInstrument.instrument.product.settlementAsset
)
}
headerTooltip={t(
'The ideal committed liquidity to operate the market. If total commitment currently below this level then LPs can set the fee level with new commitment.'
)}
/>
<AgGridColumn
headerName={t('% Target stake met')}
valueFormatter={({ data }: ValueFormatterParams) => {
const roundedPercentage =
parseInt(
(data.liquidityCommitted / parseFloat(data.target)).toFixed(0)
) * 100;
const display = Number.isNaN(roundedPercentage)
? 'N/A'
: formatNumberPercentage(toBigNum(roundedPercentage, 2));
return display;
}}
headerTooltip={t('% Target stake met')}
/>
<AgGridColumn
headerName={t('Fee levels')}
field="fees"
valueFormatter={({ value, data }: ValueFormatterParams) =>
`${value.factors.liquidityFee}%`
}
headerTooltip={t('Fee level for this market')}
/>
<AgGridColumn
@ -117,6 +171,9 @@ export const MarketList = () => {
<Status trigger={data.data?.trigger} tradingMode={value} />
);
}}
headerTooltip={t(
'The current market status - those below the target stake mark are most in need of liquidity'
)}
/>
<AgGridColumn
@ -154,7 +211,6 @@ export const MarketList = () => {
sortable={false}
cellStyle={{ overflow: 'unset' }}
/>
<AgGridColumn headerName={t('Est. return / APY')} field="apy" />
</Grid>
<HealthDialog

View File

@ -11,6 +11,7 @@ import type {
import { formatWithAsset } from '@vegaprotocol/liquidity';
import { Grid } from '../../grid';
import { TooltipCellComponent } from '@vegaprotocol/ui-toolkit';
const formatToHours = ({ value }: { value?: string | null }) => {
if (!value) {
@ -39,11 +40,14 @@ export const LPProvidersGrid = ({
return (
<Grid
rowData={liquidityProviders}
tooltipShowDelay={500}
defaultColDef={{
resizable: true,
sortable: true,
unSortIcon: true,
cellClass: ['flex', 'flex-col', 'justify-center'],
tooltipComponent: TooltipCellComponent,
minWidth: 100,
}}
getRowId={getRowId}
rowHeight={92}
@ -53,11 +57,13 @@ export const LPProvidersGrid = ({
field="party.id"
flex="1"
minWidth={100}
headerTooltip={t('Liquidity providers')}
/>
<AgGridColumn
headerName={t('Time in market')}
headerName={t('Duration')}
valueFormatter={formatToHours}
field="createdAt"
headerTooltip={t('Time in market')}
/>
<AgGridColumn
headerName={t('Equity-like share')}
@ -67,23 +73,50 @@ export const LPProvidersGrid = ({
? `${parseFloat(parseFloat(value).toFixed(2)) * 100}%`
: '';
}}
headerTooltip={t(
'The share of the markets liquidity held - the earlier you commit liquidity the greater % fees you earn'
)}
minWidth={140}
/>
<AgGridColumn
headerName={t('committed bond/stake')}
headerName={t('committed bond')}
field="commitmentAmount"
valueFormatter={({ value }: { value?: string | null }) =>
value ? formatWithAsset(value, settlementAsset) : '0'
}
headerTooltip={t('The amount of funds allocated to provide liquidity')}
minWidth={140}
/>
<AgGridColumn
headerName={t('Margin Req.')}
field="margin"
headerTooltip={t(
'Margin required for arising positions based on liquidity commitment'
)}
/>
<AgGridColumn
headerName={t('24h Fees')}
field="fees"
headerTooltip={t(
'Total fees earned by the liquidity provider in the last 24 hours'
)}
/>
<AgGridColumn headerName={t('Margin Req.')} field="margin" />
<AgGridColumn headerName={t('24h Fees')} field="fees" />
<AgGridColumn
headerName={t('Fee level')}
valueFormatter={({ value }: { value?: string | null }) => `${value}%`}
field="fee"
headerTooltip={t(
"The market's liquidity fee, or the percentage of a trade's value which is collected from the price taker for every trade"
)}
/>
<AgGridColumn headerName={t('APY')} field="apy" />
<AgGridColumn
headerName={t('APY')}
field="apy"
headerTooltip={t(
'An annualised estimate based on the total liquidity provision fees and maker fees collected by liquidity providers, the maximum margin needed and maximum commitment (bond) over the course of 7 epochs'
)}
/>
</Grid>
);
};

View File

@ -1,4 +1,4 @@
import { Lozenge } from '@vegaprotocol/ui-toolkit';
import { Lozenge, Tooltip } from '@vegaprotocol/ui-toolkit';
import classNames from 'classnames';
import {
@ -6,6 +6,7 @@ import {
AuctionTriggerMapping,
Schema,
} from '@vegaprotocol/types';
import { t } from '@vegaprotocol/react-helpers';
import { Indicator } from '../indicator';
@ -33,17 +34,46 @@ export const Status = ({
return MarketTradingModeMapping[tradingMode];
};
const status = getStatus();
const tooltipDescription = t(getTooltipDescription(status));
return (
<div
className={classNames('inline-flex whitespace-normal', {
'text-base': size === 'large',
'text-sm': size === 'small',
})}
>
<Lozenge className="border border-greys-light-300 bg-greys-light-100 flex items-center">
<Indicator status={tradingMode} />
{getStatus()}
</Lozenge>
<div>
<Tooltip description={tooltipDescription}>
<div
className={classNames('inline-flex whitespace-normal', {
'text-base': size === 'large',
'text-sm': size === 'small',
})}
>
<Lozenge className="border border-greys-light-300 bg-greys-light-100 flex items-center">
<Indicator status={tradingMode} />
{status}
</Lozenge>
</div>
</Tooltip>
</div>
);
};
const getTooltipDescription = (status: string) => {
let tooltipDescription = '';
switch (status) {
case MarketTradingModeMapping.TRADING_MODE_CONTINUOUS:
tooltipDescription =
'This is the standard trading mode where trades are executed whenever orders are received';
break;
case `${MarketTradingModeMapping.TRADING_MODE_MONITORING_AUCTION} - ${AuctionTriggerMapping.AUCTION_TRIGGER_LIQUIDITY}`:
tooltipDescription =
'This market is in auction until it reaches sufficient liquidity';
break;
case MarketTradingModeMapping.TRADING_MODE_OPENING_AUCTION:
tooltipDescription =
'This is a new market in an opening auction to determine a fair mid-price before starting continuous trading.';
break;
default:
break;
}
return tooltipDescription;
};