chore(trading): add quantum formatting to deal ticket (#4030)

This commit is contained in:
m.ray 2023-06-07 13:49:50 +03:00 committed by GitHub
parent 43d3754c64
commit 2ba0e9a1b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 206 additions and 33 deletions

View File

@ -100,9 +100,8 @@ describe('deal ticker order validation', { tags: '@smoke' }, () => {
.within(() => { .within(() => {
cy.get('[data-state="closed"]').should( cy.get('[data-state="closed"]').should(
'have.text', 'have.text',
'Total margin available' 'Total margin available100,000.01 tDAI'
); );
cy.get('.text-neutral-500').should('have.text', '100,000.01 tDAI');
}); });
}); });
}); });

View File

@ -33,24 +33,35 @@ export const DealTicketFeeDetails = (props: FeeDetails) => {
const details = getFeeDetailsValues(props); const details = getFeeDetailsValues(props);
return ( return (
<div> <div>
{details.map(({ label, value, labelDescription, symbol, indent }) => ( {details.map(
<div ({
key={typeof label === 'string' ? label : 'value-dropdown'} label,
className={classnames( value,
'text-xs mt-2 flex justify-between items-center gap-4 flex-wrap', labelDescription,
{ 'ml-2': indent } symbol,
)} indent,
> formattedValue,
<div> }) => (
<Tooltip description={labelDescription}> <div
<div>{label}</div> key={typeof label === 'string' ? label : 'value-dropdown'}
className={classnames(
'text-xs mt-2 flex justify-between items-center gap-4 flex-wrap',
{ 'ml-2': indent }
)}
>
<div>
<Tooltip description={labelDescription}>
<div>{label}</div>
</Tooltip>
</div>
<Tooltip description={`${value ?? '-'} ${symbol || ''}`}>
<div className="text-neutral-500 dark:text-neutral-300">{`${
formattedValue ?? '-'
} ${symbol || ''}`}</div>
</Tooltip> </Tooltip>
</div> </div>
<div className="text-neutral-500 dark:text-neutral-300">{`${ )
value ?? '-' )}
} ${symbol || ''}`}</div>
</div>
))}
</div> </div>
); );
}; };

View File

@ -0,0 +1,68 @@
import { formatRange, formatValue } from './use-fee-deal-ticket-details';
describe('useFeeDealTicketDetails', () => {
it.each([
{ v: 123000, d: 5, o: '1.23' },
{ v: 123000, d: 3, o: '123.00' },
{ v: 123000, d: 1, o: '12,300.0' },
{ v: 123001000, d: 2, o: '1,230,010.00' },
{ v: 123001, d: 2, o: '1,230.01' },
{
v: '123456789123456789',
d: 10,
o: '12,345,678.91234568',
},
])('formats values correctly', ({ v, d, o }) => {
expect(formatValue(v, d)).toStrictEqual(o);
});
it.each([
{ v: 123000, d: 5, o: '1.23', q: '0.1' },
{ v: 123000, d: 3, o: '123.00', q: '0.1' },
{ v: 123000, d: 1, o: '12,300.00', q: '0.1' },
{ v: 123001000, d: 2, o: '1,230,010.00', q: '0.1' },
{ v: 123001, d: 2, o: '1,230', q: '100' },
{ v: 123001, d: 2, o: '1,230.01', q: '0.1' },
{
v: '123456789123456789',
d: 10,
o: '12,345,678.9123457',
q: '0.00003846',
},
])(
'formats with formatValue with quantum given number correctly',
({ v, d, o, q }) => {
expect(formatValue(v.toString(), d, q)).toStrictEqual(o);
}
);
it.each([
{ min: 123000, max: 12300011111, d: 5, o: '1.23 - 123,000.111', q: '0.1' },
{
min: 123000,
max: 12300011111,
d: 3,
o: '123.00 - 12,300,011.111',
q: '0.1',
},
{
min: 123000,
max: 12300011111,
d: 1,
o: '12,300.00 - 1,230,001,111.10',
q: '0.1',
},
{
min: 123001000,
max: 12300011111,
d: 2,
o: '1,230,010 - 123,000,111',
q: '100',
},
])(
'formats with formatValue with quantum given number correctly',
({ min, max, d, o, q }) => {
expect(formatRange(min, max, d, q)).toStrictEqual(o);
}
);
});

View File

@ -1,5 +1,9 @@
import { FeesBreakdown } from '@vegaprotocol/markets'; import { FeesBreakdown } from '@vegaprotocol/markets';
import { addDecimalsFormatNumber, isNumeric } from '@vegaprotocol/utils'; import {
addDecimalsFormatNumber,
addDecimalsFormatNumberQuantum,
isNumeric,
} from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/i18n';
import { useVegaWallet } from '@vegaprotocol/wallet'; import { useVegaWallet } from '@vegaprotocol/wallet';
import type { Market } from '@vegaprotocol/markets'; import type { Market } from '@vegaprotocol/markets';
@ -52,21 +56,25 @@ export interface FeeDetails {
} }
const emptyValue = '-'; const emptyValue = '-';
const formatValue = (
export const formatValue = (
value: string | number | null | undefined, value: string | number | null | undefined,
formatDecimals: number formatDecimals: number,
quantum?: string
): string => { ): string => {
return isNumeric(value) if (!isNumeric(value)) return emptyValue;
? addDecimalsFormatNumber(value, formatDecimals) if (!quantum) return addDecimalsFormatNumber(value, formatDecimals);
: emptyValue; return addDecimalsFormatNumberQuantum(value, formatDecimals, quantum);
}; };
const formatRange = (
export const formatRange = (
min: string | number | null | undefined, min: string | number | null | undefined,
max: string | number | null | undefined, max: string | number | null | undefined,
formatDecimals: number formatDecimals: number,
quantum?: string
) => { ) => {
const minFormatted = formatValue(min, formatDecimals); const minFormatted = formatValue(min, formatDecimals, quantum);
const maxFormatted = formatValue(max, formatDecimals); const maxFormatted = formatValue(max, formatDecimals, quantum);
if (minFormatted !== maxFormatted) { if (minFormatted !== maxFormatted) {
return `${minFormatted} - ${maxFormatted}`; return `${minFormatted} - ${maxFormatted}`;
} }
@ -93,9 +101,12 @@ export const getFeeDetailsValues = ({
BigInt(generalAccountBalance || '0') + BigInt(marginAccountBalance || '0'); BigInt(generalAccountBalance || '0') + BigInt(marginAccountBalance || '0');
const assetDecimals = const assetDecimals =
market.tradableInstrument.instrument.product.settlementAsset.decimals; market.tradableInstrument.instrument.product.settlementAsset.decimals;
const quantum =
market.tradableInstrument.instrument.product.settlementAsset.quantum;
const details: { const details: {
label: string; label: string;
value?: string | null; value?: string | null;
formattedValue?: string | null;
symbol: string; symbol: string;
indent?: boolean; indent?: boolean;
labelDescription?: React.ReactNode; labelDescription?: React.ReactNode;
@ -103,6 +114,7 @@ export const getFeeDetailsValues = ({
{ {
label: t('Notional'), label: t('Notional'),
value: formatValue(notionalSize, assetDecimals), value: formatValue(notionalSize, assetDecimals),
formattedValue: formatValue(notionalSize, assetDecimals, quantum),
symbol: assetSymbol, symbol: assetSymbol,
labelDescription: NOTIONAL_SIZE_TOOLTIP_TEXT(assetSymbol), labelDescription: NOTIONAL_SIZE_TOOLTIP_TEXT(assetSymbol),
}, },
@ -111,6 +123,9 @@ export const getFeeDetailsValues = ({
value: value:
feeEstimate?.totalFeeAmount && feeEstimate?.totalFeeAmount &&
`~${formatValue(feeEstimate?.totalFeeAmount, assetDecimals)}`, `~${formatValue(feeEstimate?.totalFeeAmount, assetDecimals)}`,
formattedValue:
feeEstimate?.totalFeeAmount &&
`~${formatValue(feeEstimate?.totalFeeAmount, assetDecimals, quantum)}`,
labelDescription: ( labelDescription: (
<> <>
<span> <span>
@ -154,6 +169,12 @@ export const getFeeDetailsValues = ({
} }
details.push({ details.push({
label: t('Margin required'), label: t('Margin required'),
formattedValue: formatRange(
marginRequiredBestCase,
marginRequiredWorstCase,
assetDecimals,
quantum
),
value: formatRange( value: formatRange(
marginRequiredBestCase, marginRequiredBestCase,
marginRequiredWorstCase, marginRequiredWorstCase,
@ -172,12 +193,13 @@ export const getFeeDetailsValues = ({
details.push({ details.push({
indent: true, indent: true,
label: t('Total margin available'), label: t('Total margin available'),
formattedValue: formatValue(totalMarginAvailable, assetDecimals, quantum),
value: formatValue(totalMarginAvailable, assetDecimals), value: formatValue(totalMarginAvailable, assetDecimals),
symbol: assetSymbol, symbol: assetSymbol,
labelDescription: TOTAL_MARGIN_AVAILABLE( labelDescription: TOTAL_MARGIN_AVAILABLE(
formatValue(generalAccountBalance, assetDecimals), formatValue(generalAccountBalance, assetDecimals, quantum),
formatValue(marginAccountBalance, assetDecimals), formatValue(marginAccountBalance, assetDecimals, quantum),
formatValue(currentMaintenanceMargin, assetDecimals), formatValue(currentMaintenanceMargin, assetDecimals, quantum),
assetSymbol assetSymbol
), ),
}); });
@ -203,6 +225,16 @@ export const getFeeDetailsValues = ({
: '0', : '0',
assetDecimals assetDecimals
), ),
formattedValue: formatRange(
deductionFromCollateralBestCase > 0
? deductionFromCollateralBestCase.toString()
: '0',
deductionFromCollateralWorstCase > 0
? deductionFromCollateralWorstCase.toString()
: '0',
assetDecimals,
quantum
),
symbol: assetSymbol, symbol: assetSymbol,
labelDescription: DEDUCTION_FROM_COLLATERAL_TOOLTIP_TEXT(assetSymbol), labelDescription: DEDUCTION_FROM_COLLATERAL_TOOLTIP_TEXT(assetSymbol),
}); });
@ -214,6 +246,12 @@ export const getFeeDetailsValues = ({
marginEstimate?.worstCase.initialLevel, marginEstimate?.worstCase.initialLevel,
assetDecimals assetDecimals
), ),
formattedValue: formatRange(
marginEstimate?.bestCase.initialLevel,
marginEstimate?.worstCase.initialLevel,
assetDecimals,
quantum
),
symbol: assetSymbol, symbol: assetSymbol,
labelDescription: EST_TOTAL_MARGIN_TOOLTIP_TEXT, labelDescription: EST_TOTAL_MARGIN_TOOLTIP_TEXT,
}); });
@ -223,9 +261,11 @@ export const getFeeDetailsValues = ({
value: formatValue(marginAccountBalance, assetDecimals), value: formatValue(marginAccountBalance, assetDecimals),
symbol: assetSymbol, symbol: assetSymbol,
labelDescription: MARGIN_ACCOUNT_TOOLTIP_TEXT, labelDescription: MARGIN_ACCOUNT_TOOLTIP_TEXT,
formattedValue: formatValue(marginAccountBalance, assetDecimals, quantum),
}); });
let liquidationPriceEstimate = emptyValue; let liquidationPriceEstimate = emptyValue;
let liquidationPriceEstimateFormatted;
if (liquidationEstimate) { if (liquidationEstimate) {
const liquidationEstimateBestCaseIncludingBuyOrders = BigInt( const liquidationEstimateBestCaseIncludingBuyOrders = BigInt(
@ -262,11 +302,24 @@ export const getFeeDetailsValues = ({
).toString(), ).toString(),
assetDecimals assetDecimals
); );
liquidationPriceEstimateFormatted = formatRange(
(liquidationEstimateBestCase < liquidationEstimateWorstCase
? liquidationEstimateBestCase
: liquidationEstimateWorstCase
).toString(),
(liquidationEstimateBestCase > liquidationEstimateWorstCase
? liquidationEstimateBestCase
: liquidationEstimateWorstCase
).toString(),
assetDecimals,
quantum
);
} }
details.push({ details.push({
label: t('Liquidation price estimate'), label: t('Liquidation price estimate'),
value: liquidationPriceEstimate, value: liquidationPriceEstimate,
formattedValue: liquidationPriceEstimateFormatted,
symbol: assetSymbol, symbol: assetSymbol,
labelDescription: LIQUIDATION_PRICE_ESTIMATE_TOOLTIP_TEXT, labelDescription: LIQUIDATION_PRICE_ESTIMATE_TOOLTIP_TEXT,
}); });

View File

@ -32,6 +32,7 @@ export function generateMarket(override?: PartialDeep<Market>): Market {
symbol: 'tDAI', symbol: 'tDAI',
name: 'tDAI', name: 'tDAI',
decimals: 5, decimals: 5,
quantum: '1',
__typename: 'Asset', __typename: 'Asset',
}, },
dataSourceSpecForTradingTermination: { dataSourceSpecForTradingTermination: {

View File

@ -75,6 +75,7 @@ export const generateFill = (override?: PartialDeep<Trade>) => {
name: 'assset-id', name: 'assset-id',
symbol: 'SYM', symbol: 'SYM',
decimals: 18, decimals: 18,
quantum: '1',
}, },
quoteName: '', quoteName: '',
dataSourceSpecForTradingTermination: { dataSourceSpecForTradingTermination: {

View File

@ -7,12 +7,12 @@ export type DataSourceFilterFragment = { __typename?: 'Filter', key: { __typenam
export type DataSourceSpecFragment = { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } }; export type DataSourceSpecFragment = { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } };
export type MarketFieldsFragment = { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array<string> | null }, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } } }, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any } }; export type MarketFieldsFragment = { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array<string> | null }, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number, quantum: string }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } } }, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any } };
export type MarketsQueryVariables = Types.Exact<{ [key: string]: never; }>; export type MarketsQueryVariables = Types.Exact<{ [key: string]: never; }>;
export type MarketsQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array<string> | null }, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } } }, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any } } }> } | null }; export type MarketsQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array<string> | null }, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number, quantum: string }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } } }, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any } } }> } | null };
export const DataSourceFilterFragmentDoc = gql` export const DataSourceFilterFragmentDoc = gql`
fragment DataSourceFilter on Filter { fragment DataSourceFilter on Filter {
@ -77,6 +77,7 @@ export const MarketFieldsFragmentDoc = gql`
symbol symbol
name name
decimals decimals
quantum
} }
quoteName quoteName
dataSourceSpecForTradingTermination { dataSourceSpecForTradingTermination {

View File

@ -58,6 +58,7 @@ fragment MarketFields on Market {
symbol symbol
name name
decimals decimals
quantum
} }
quoteName quoteName
dataSourceSpecForTradingTermination { dataSourceSpecForTradingTermination {

View File

@ -60,6 +60,7 @@ export const createMarketFragment = (
symbol: 'tDAI', symbol: 'tDAI',
name: 'tDAI', name: 'tDAI',
decimals: 5, decimals: 5,
quantum: '1',
__typename: 'Asset', __typename: 'Asset',
}, },
dataSourceSpecForTradingTermination: { dataSourceSpecForTradingTermination: {

View File

@ -47,6 +47,7 @@ export const generateOrder = (partialOrder?: PartialDeep<Order>) => {
decimals: 1, decimals: 1,
symbol: 'XYZ', symbol: 'XYZ',
name: 'XYZ', name: 'XYZ',
quantum: '1',
}, },
dataSourceSpecForTradingTermination: { dataSourceSpecForTradingTermination: {
__typename: 'DataSourceSpec', __typename: 'DataSourceSpec',

View File

@ -2,6 +2,7 @@ import BigNumber from 'bignumber.js';
import { import {
addDecimalsFormatNumber, addDecimalsFormatNumber,
addDecimalsFormatNumberQuantum,
formatNumber, formatNumber,
formatNumberPercentage, formatNumberPercentage,
isNumeric, isNumeric,
@ -23,6 +24,28 @@ describe('number utils', () => {
} }
); );
it.each([
{ v: new BigNumber(123000), d: 5, o: '1.23', q: 0.1 },
{ v: new BigNumber(123000), d: 3, o: '123.00', q: 0.1 },
{ v: new BigNumber(123000), d: 1, o: '12,300.00', q: 0.1 },
{ v: new BigNumber(123001000), d: 2, o: '1,230,010.00', q: 0.1 },
{ v: new BigNumber(123001), d: 2, o: '1,230', q: 100 },
{ v: new BigNumber(123001), d: 2, o: '1,230.01', q: 0.1 },
{
v: BigNumber('123456789123456789'),
d: 10,
o: '12,345,678.9123457',
q: '0.00003846',
},
])(
'formats with addDecimalsFormatNumberQuantum given number correctly',
({ v, d, o, q }) => {
expect(addDecimalsFormatNumberQuantum(v.toString(), d, q)).toStrictEqual(
o
);
}
);
it.each([ it.each([
{ v: new BigNumber(123), d: 3, o: '123.00' }, { v: new BigNumber(123), d: 3, o: '123.00' },
{ v: new BigNumber(123.123), d: 3, o: '123.123' }, { v: new BigNumber(123.123), d: 3, o: '123.123' },

View File

@ -90,6 +90,18 @@ export const formatNumberFixed = (
return getFixedNumberFormat(formatDecimals).format(Number(rawValue)); return getFixedNumberFormat(formatDecimals).format(Number(rawValue));
}; };
export const addDecimalsFormatNumberQuantum = (
rawValue: string | number,
decimalPlaces: number,
quantum: number | string
) => {
if (isNaN(Number(quantum))) {
return addDecimalsFormatNumber(rawValue, decimalPlaces);
}
const numberDP = Math.max(0, Math.log10(100 / Number(quantum)));
return addDecimalsFormatNumber(rawValue, decimalPlaces, Math.ceil(numberDP));
};
export const addDecimalsFormatNumber = ( export const addDecimalsFormatNumber = (
rawValue: string | number, rawValue: string | number,
decimalPlaces: number, decimalPlaces: number,

View File

@ -165,6 +165,7 @@ describe('WithdrawFormContainer', () => {
name: 'asset-id', name: 'asset-id',
symbol: 'tUSDC', symbol: 'tUSDC',
decimals: 5, decimals: 5,
quantum: '1',
}, },
dataSourceSpecForTradingTermination: { dataSourceSpecForTradingTermination: {
__typename: 'DataSourceSpec', __typename: 'DataSourceSpec',