fix: 1875 & 1876 fix deal ticket fees display and remove insignificant trailing zeros (#1898)

This commit is contained in:
m.ray 2022-11-01 11:03:29 +00:00 committed by GitHub
parent 082683a541
commit 3e970f7023
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 116 additions and 48 deletions

View File

@ -7,7 +7,7 @@ import {
calcCandleVolume,
} from '@vegaprotocol/market-list';
import {
addDecimalsFormatNumber,
addDecimalsNormalizeNumber,
PriceCell,
signedNumberCssClass,
t,
@ -236,7 +236,7 @@ export const columns = (
value: market.data?.markPrice ? (
<PriceCell
value={Number(market.data?.markPrice)}
valueFormatted={addDecimalsFormatNumber(
valueFormatted={addDecimalsNormalizeNumber(
market.data?.markPrice.toString(),
market.decimalPlaces,
2
@ -300,7 +300,7 @@ export const columns = (
value: candleHigh ? (
<PriceCell
value={Number(candleHigh)}
valueFormatted={addDecimalsFormatNumber(
valueFormatted={addDecimalsNormalizeNumber(
candleHigh.toString(),
market.decimalPlaces,
2
@ -317,7 +317,7 @@ export const columns = (
value: candleLow ? (
<PriceCell
value={Number(candleLow)}
valueFormatted={addDecimalsFormatNumber(
valueFormatted={addDecimalsNormalizeNumber(
candleLow.toString(),
market.decimalPlaces,
2
@ -332,7 +332,7 @@ export const columns = (
{
kind: ColumnKind.Volume,
value: candleVolume
? addDecimalsFormatNumber(
? addDecimalsNormalizeNumber(
candleVolume.toString(),
market.positionDecimalPlaces,
2
@ -411,7 +411,7 @@ export const columnsPositionMarkets = (
value: market.data?.markPrice ? (
<PriceCell
value={Number(market.data.markPrice)}
valueFormatted={addDecimalsFormatNumber(
valueFormatted={addDecimalsNormalizeNumber(
market.data.markPrice.toString(),
market.decimalPlaces,
2
@ -475,7 +475,7 @@ export const columnsPositionMarkets = (
value: candleHigh ? (
<PriceCell
value={Number(candleHigh)}
valueFormatted={addDecimalsFormatNumber(
valueFormatted={addDecimalsNormalizeNumber(
candleHigh.toString(),
market.decimalPlaces,
2
@ -492,7 +492,7 @@ export const columnsPositionMarkets = (
value: candleLow ? (
<PriceCell
value={Number(candleLow)}
valueFormatted={addDecimalsFormatNumber(
valueFormatted={addDecimalsNormalizeNumber(
candleLow.toString(),
market.decimalPlaces,
2
@ -507,7 +507,7 @@ export const columnsPositionMarkets = (
{
kind: ColumnKind.Volume,
value: candleVolume
? addDecimalsFormatNumber(
? addDecimalsNormalizeNumber(
candleVolume.toString(),
market.positionDecimalPlaces,
2

View File

@ -1,8 +1,8 @@
import React from 'react';
import { formatNumber, t } from '@vegaprotocol/react-helpers';
import { Button, Dialog } from '@vegaprotocol/ui-toolkit';
import { useState } from 'react';
import { DepositContainer } from '@vegaprotocol/deposits';
import { normalizeFormatNumber, t } from '@vegaprotocol/react-helpers';
import { Button, Dialog } from '@vegaprotocol/ui-toolkit';
import React from 'react';
import { useState } from 'react';
interface Props {
margin: string;
@ -30,9 +30,11 @@ export const ValidateMargin = ({
{t("You don't have enough margin available to open this position.")}
</p>
<p>
{`${formatNumber(margin, decimals)} ${symbol} ${t(
{`${normalizeFormatNumber(margin, decimals)} ${symbol} ${t(
'currently required'
)}, ${formatNumber(balance, decimals)} ${symbol} ${t('available')}`}
)}, ${normalizeFormatNumber(balance, decimals)} ${symbol} ${t(
'available'
)}`}
</p>
<Button
className="center mt-2"

View File

@ -1,4 +1,5 @@
import { Tooltip } from '@vegaprotocol/ui-toolkit';
import type { ReactNode } from 'react';
interface DealTicketFeeDetailsProps {
@ -20,7 +21,7 @@ export const DealTicketFeeDetails = ({
{details.map(({ label, value, labelDescription, quoteName }) => (
<div
key={label}
className="text-sm mt-2 flex justify-between items-center gap-4 flex-wrap"
className="text-xs mt-2 flex justify-between items-center gap-4 flex-wrap"
>
<div>
<Tooltip description={labelDescription}>

View File

@ -1,27 +1,28 @@
import { useCallback, useEffect } from 'react';
import { useForm, Controller } from 'react-hook-form';
import { t, removeDecimal, addDecimal } from '@vegaprotocol/react-helpers';
import { Button, InputError } from '@vegaprotocol/ui-toolkit';
import { TypeSelector } from './type-selector';
import { SideSelector } from './side-selector';
import { DealTicketAmount } from './deal-ticket-amount';
import { TimeInForceSelector } from './time-in-force-selector';
import type { DealTicketMarketFragment } from './__generated___/DealTicket';
import { ExpirySelector } from './expiry-selector';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
import { addDecimal, removeDecimal, t } from '@vegaprotocol/react-helpers';
import { Schema } from '@vegaprotocol/types';
import { Button, InputError } from '@vegaprotocol/ui-toolkit';
import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
import { useCallback, useEffect } from 'react';
import { Controller, useForm } from 'react-hook-form';
import {
getFeeDetailsValues,
useFeeDealTicketDetails,
} from '../../hooks/use-fee-deal-ticket-details';
import { getDefaultOrder } from '../deal-ticket-validation';
import {
isMarketInAuction,
useOrderValidation,
} from '../deal-ticket-validation/use-order-validation';
import { DealTicketAmount } from './deal-ticket-amount';
import { DealTicketFeeDetails } from './deal-ticket-fee-details';
import {
useFeeDealTicketDetails,
getFeeDetailsValues,
} from '../../hooks/use-fee-deal-ticket-details';
import { ExpirySelector } from './expiry-selector';
import { SideSelector } from './side-selector';
import { TimeInForceSelector } from './time-in-force-selector';
import { TypeSelector } from './type-selector';
import type { DealTicketMarketFragment } from './__generated___/DealTicket';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
export type TransactionStatus = 'default' | 'pending';
export interface DealTicketProps {

View File

@ -1,22 +1,23 @@
import { FeesBreakdown } from '@vegaprotocol/market-info';
import { formatNumber, t } from '@vegaprotocol/react-helpers';
import { normalizeFormatNumber, t } from '@vegaprotocol/react-helpers';
import { Schema } from '@vegaprotocol/types';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import { useVegaWallet } from '@vegaprotocol/wallet';
import BigNumber from 'bignumber.js';
import { useMemo } from 'react';
import type { DealTicketMarketFragment } from '../components';
import {
NOTIONAL_SIZE_TOOLTIP_TEXT,
EST_MARGIN_TOOLTIP_TEXT,
EST_CLOSEOUT_TOOLTIP_TEXT,
EST_MARGIN_TOOLTIP_TEXT,
NOTIONAL_SIZE_TOOLTIP_TEXT,
} from '../components/constants';
import { usePartyBalanceQuery } from './__generated__/PartyBalance';
import { useCalculateSlippage } from './use-calculate-slippage';
import { useOrderCloseOut } from './use-order-closeout';
import type { OrderMargin } from './use-order-margin';
import { useOrderMargin } from './use-order-margin';
import { usePartyBalanceQuery } from './__generated__/PartyBalance';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import type { DealTicketMarketFragment } from '../components';
import type { OrderMargin } from './use-order-margin';
export const useFeeDealTicketDetails = (
order: OrderSubmissionBody['orderSubmission'],
market: DealTicketMarketFragment
@ -97,12 +98,12 @@ export const getFeeDetailsValues = ({
}: FeeDetails) => {
const formatValue = (value: string | number | null | undefined): string => {
return value && !isNaN(Number(value))
? formatNumber(value, market.decimalPlaces)
? normalizeFormatNumber(value, market.decimalPlaces)
: '-';
};
return [
{
label: t('Notional value'),
label: t('Notional'),
value: formatValue(notionalSize),
quoteName,
labelDescription: NOTIONAL_SIZE_TOOLTIP_TEXT,
@ -127,14 +128,14 @@ export const getFeeDetailsValues = ({
quoteName,
},
{
label: t('Margin required'),
label: t('Margin'),
value: estMargin?.margin && `~${formatValue(estMargin?.margin)}`,
quoteName,
labelDescription: EST_MARGIN_TOOLTIP_TEXT,
},
{
label: t('Liquidation price (variable)'),
value: formatValue(estCloseOut),
label: t('Liquidation'),
value: estCloseOut && `~${formatValue(estCloseOut)}`,
quoteName,
labelDescription: EST_CLOSEOUT_TOOLTIP_TEXT,
},

View File

@ -1,13 +1,45 @@
import BigNumber from 'bignumber.js';
import {
addDecimalsNormalizeNumber,
compactNumber,
formatNumber,
formatNumberPercentage,
toNumberParts,
isNumeric,
compactNumber,
normalizeFormatNumber,
toNumberParts,
} from './number';
describe('formatNumber and formatNumberPercentage', () => {
describe('number react-helpers', () => {
it.each([
{ v: new BigNumber(123000), d: 5, o: '1.23' },
{ v: new BigNumber(123000), d: 3, o: '123' },
{ v: new BigNumber(123000), d: 1, o: '12,300.0' },
{ v: new BigNumber(123001), d: 2, o: '1,230.01' },
{ v: new BigNumber(123001000), d: 2, o: '1,230,010.00' },
])(
'formats with addDecimalsNormalizeNumber given number correctly',
({ v, d, o }) => {
expect(addDecimalsNormalizeNumber(v.toString(), d)).toStrictEqual(o);
}
);
it.each([
{ v: new BigNumber(123.0), d: 3, o: '123' },
{ v: new BigNumber(123.123), d: 3, o: '123.123' },
{ v: new BigNumber(123.6666), d: 3, o: '123.667' },
{ v: new BigNumber(123.003), d: 6, o: '123.003' },
{ v: new BigNumber(123.003), d: 0, o: '123' },
{ v: new BigNumber(123), d: undefined, o: '123' },
{ v: new BigNumber(30000), d: undefined, o: '30,000' },
{ v: new BigNumber(3.000001), d: undefined, o: '3' },
])(
`formats with normalizeFormatNumber given number correctly`,
({ v, d, o }) => {
expect(normalizeFormatNumber(v, d)).toStrictEqual(o);
}
);
it.each([
{ v: new BigNumber(123), d: 3, o: '123.000' },
{ v: new BigNumber(123.123), d: 3, o: '123.123' },
@ -17,7 +49,7 @@ describe('formatNumber and formatNumberPercentage', () => {
{ v: new BigNumber(123), d: undefined, o: '123' },
{ v: new BigNumber(30000), d: undefined, o: '30,000' },
{ v: new BigNumber(3.000001), d: undefined, o: '3' },
])('formats given number correctly', ({ v, d, o }) => {
])('formats with formatNumber given number correctly', ({ v, d, o }) => {
expect(formatNumber(v, d)).toStrictEqual(o);
});

View File

@ -3,6 +3,7 @@ import { BigNumber as EthersBigNumber } from 'ethers';
import isNil from 'lodash/isNil';
import memoize from 'lodash/memoize';
import React from 'react';
import { getUserLocale } from './utils';
const MAX_FRACTION_DIGITS = 20;
@ -55,6 +56,10 @@ export const getDecimalSeparator = memoize(
.find((part) => part.type === 'decimal')?.value
);
/** formatNumber will format the number with fixed decimals
* @param rawValue - should be a number that is not outside the safe range fail as in https://mikemcl.github.io/bignumber.js/#toN
* @param formatDecimals - number of decimals to use
*/
export const formatNumber = (
rawValue: string | number | BigNumber,
formatDecimals = 0
@ -62,6 +67,23 @@ export const formatNumber = (
return getNumberFormat(formatDecimals).format(Number(rawValue));
};
/** normalizeFormatNumber will format the number with fixed decimals, but without insignificant trailing zeros
* @param rawValue - should be a number that is not outside the safe range fail as in https://mikemcl.github.io/bignumber.js/#toN
* @param formatDecimals - number of decimals to use
*/
export const normalizeFormatNumber = (
rawValue: string | number | BigNumber,
formatDecimals = 0
): string => {
const numberToFormat = getNumberFormat(formatDecimals).format(
Number(rawValue)
);
// Multiplying by 1 safely removes the insignificant trailing zeros from the formatted number
return !isNaN(Number(numberToFormat))
? (Number(numberToFormat) * 1).toString()
: numberToFormat;
};
export const addDecimalsFormatNumber = (
rawValue: string | number,
decimalPlaces: number,
@ -72,6 +94,15 @@ export const addDecimalsFormatNumber = (
return formatNumber(x, formatDecimals);
};
export const addDecimalsNormalizeNumber = (
rawValue: string | number,
decimalPlaces: number,
formatDecimals: number = decimalPlaces
) => {
const x = addDecimal(rawValue, decimalPlaces);
return normalizeFormatNumber(x, formatDecimals);
};
export const formatNumberPercentage = (value: BigNumber, decimals?: number) => {
const decimalPlaces =
typeof decimals === 'undefined' ? Math.max(value.dp() || 0, 2) : decimals;