From 303e64743484f64dcc6e5646adacc52078d6c49f Mon Sep 17 00:00:00 2001 From: Kristof Csillag Date: Tue, 25 Apr 2023 20:02:05 +0200 Subject: [PATCH] Use BigNumber for number formatting --- src/app/components/Account/index.tsx | 3 +- src/app/components/Blocks/BlockLink.tsx | 3 +- src/app/components/Blocks/index.tsx | 18 ++++---- src/app/pages/BlockDetailPage/index.tsx | 16 +++---- .../pages/DashboardPage/ActiveAccounts.tsx | 9 ++-- src/app/pages/DashboardPage/Nodes.tsx | 3 +- .../pages/DashboardPage/TotalTransactions.tsx | 10 ++--- .../DashboardPage/TransactionsChartCard.tsx | 12 +++--- .../pages/DashboardPage/TransactionsStats.tsx | 3 +- src/app/pages/TransactionDetailPage/index.tsx | 3 +- src/app/utils/numberFormatter.ts | 42 +++++++++++++++++++ src/locales/en/translation.json | 13 +++--- 12 files changed, 86 insertions(+), 49 deletions(-) create mode 100644 src/app/utils/numberFormatter.ts diff --git a/src/app/components/Account/index.tsx b/src/app/components/Account/index.tsx index 8f5e685c3f..a36e255dff 100644 --- a/src/app/components/Account/index.tsx +++ b/src/app/components/Account/index.tsx @@ -17,6 +17,7 @@ import { AccountLink } from './AccountLink' import { RouteUtils } from '../../utils/route-utils' import { accountTransactionsContainerId } from '../../pages/AccountDetailsPage/TransactionsCard' import Link from '@mui/material/Link' +import { formatNumber } from '../../utils/numberFormatter' export const StyledAvatarContainer = styled('dt')(({ theme }) => ({ '&&': { @@ -108,7 +109,7 @@ export const Account: FC = ({ account, isLoading, roseFiatValue, s
{t('common.transactions')}
- {t('common.transactionsNumber', { count: account.stats.num_txns })} + { formatNumber(account.stats.num_txns) }
diff --git a/src/app/components/Blocks/BlockLink.tsx b/src/app/components/Blocks/BlockLink.tsx index f8be09e745..17334641ea 100644 --- a/src/app/components/Blocks/BlockLink.tsx +++ b/src/app/components/Blocks/BlockLink.tsx @@ -6,11 +6,12 @@ import Link from '@mui/material/Link' import { Layer } from '../../../oasis-indexer/api' import { RouteUtils } from '../../utils/route-utils' import { TrimLinkLabel } from '../TrimLinkLabel' +import { formatNumber } from '../../utils/numberFormatter' export const BlockLink: FC<{ layer: Layer; height: number }> = ({ layer, height }) => ( - {height.toLocaleString()} + {formatNumber(height)} ) diff --git a/src/app/components/Blocks/index.tsx b/src/app/components/Blocks/index.tsx index f33cf0b2ae..0e4ca9ccac 100644 --- a/src/app/components/Blocks/index.tsx +++ b/src/app/components/Blocks/index.tsx @@ -6,6 +6,7 @@ import { Table, TableCellAlign, TableColProps } from '../../components/Table' import { paraTimesConfig } from '../../../config' import { TablePaginationProps } from '../Table/TablePagination' import { BlockHashLink, BlockLink } from './BlockLink' +import { formatNumber } from '../../utils/numberFormatter' export type TableRuntimeBlock = RuntimeBlock & { markAsNew?: boolean @@ -66,7 +67,7 @@ export const Blocks = (props: BlocksProps) => { }, { align: TableCellAlign.Right, - content: block.num_transactions, + content: formatNumber(block.num_transactions), key: 'txs', }, ...(verbose @@ -80,14 +81,9 @@ export const Blocks = (props: BlocksProps) => { { align: TableCellAlign.Right, content: t('common.bytes', { - value: block.size, - formatParams: { - value: { - style: 'unit', - unit: 'byte', - unitDisplay: 'long', - } satisfies Intl.NumberFormatOptions, - }, + value: formatNumber(block.size, { + unit: 'byte', + }), }), key: 'size', }, @@ -95,7 +91,7 @@ export const Blocks = (props: BlocksProps) => { ? [ { align: TableCellAlign.Right, - content: block.gas_used.toLocaleString(), + content: formatNumber(block.gas_used), key: 'gasUsed', }, ] @@ -104,7 +100,7 @@ export const Blocks = (props: BlocksProps) => { ? [ { align: TableCellAlign.Right, - content: blockGasLimit.toLocaleString(), + content: formatNumber(blockGasLimit), key: 'gasLimit', }, ] diff --git a/src/app/pages/BlockDetailPage/index.tsx b/src/app/pages/BlockDetailPage/index.tsx index eaa1f495f8..721e571ec9 100644 --- a/src/app/pages/BlockDetailPage/index.tsx +++ b/src/app/pages/BlockDetailPage/index.tsx @@ -18,6 +18,7 @@ import { transactionsContainerId } from './TransactionsCard' import { useLayerParam } from '../../hooks/useLayerParam' import { BlockLink, BlockHashLink } from '../../components/Blocks/BlockLink' import { RouteUtils } from '../../utils/route-utils' +import { formatNumber } from '../../utils/numberFormatter' export const BlockDetailPage: FC = () => { const { t } = useTranslation() @@ -101,14 +102,9 @@ export const BlockDetailView: FC<{
{t('common.size')}
{t('common.bytes', { - value: block.size, - formatParams: { - value: { - style: 'unit', - unit: 'byte', - unitDisplay: 'long', - } satisfies Intl.NumberFormatOptions, - }, + value: formatNumber(block.size, { + unit: 'byte', + }), })}
@@ -122,7 +118,7 @@ export const BlockDetailView: FC<{
{t('common.gasUsed')}
{t('block.gasUsed', { - value: block.gas_used, + value: formatNumber(block.gas_used), percentage: block.gas_used / blockGasLimit, formatParams: { percentage: { @@ -134,7 +130,7 @@ export const BlockDetailView: FC<{
{t('common.gasLimit')}
-
{blockGasLimit.toLocaleString()}
+
{formatNumber(blockGasLimit)}
) } diff --git a/src/app/pages/DashboardPage/ActiveAccounts.tsx b/src/app/pages/DashboardPage/ActiveAccounts.tsx index f6258947b3..63f6643efe 100644 --- a/src/app/pages/DashboardPage/ActiveAccounts.tsx +++ b/src/app/pages/DashboardPage/ActiveAccounts.tsx @@ -16,6 +16,7 @@ import { sumBucketsByStartDuration, } from '../../utils/chart-utils' import { useLayerParam } from '../../hooks/useLayerParam' +import { formatNumber } from '../../utils/numberFormatter' export const getActiveAccountsWindows = (duration: ChartDuration, windows: Windows[]) => { switch (duration) { @@ -80,8 +81,10 @@ export const ActiveAccounts: FC = ({ chartDuration }) => { getActiveAccountsWindows(chartDuration, activeAccountsQuery.data?.data?.windows) const totalNumberLabel = dailyChart && windows?.length - ? windows[0].active_accounts.toLocaleString() - : windows?.reduce((acc, curr) => acc + curr.active_accounts, 0).toLocaleString() + ? formatNumber(windows[0].active_accounts) + : windows + ? formatNumber(windows.reduce((acc, curr) => acc + curr.active_accounts, 0)) + : undefined return ( @@ -93,7 +96,7 @@ export const ActiveAccounts: FC = ({ chartDuration }) => { formatters={{ data: (value: number) => t('activeAccounts.tooltip', { - value, + value: formatNumber(value), }), label: (value: string) => t('common.formattedDateTime', { diff --git a/src/app/pages/DashboardPage/Nodes.tsx b/src/app/pages/DashboardPage/Nodes.tsx index 0fd2da1a57..ea4587f515 100644 --- a/src/app/pages/DashboardPage/Nodes.tsx +++ b/src/app/pages/DashboardPage/Nodes.tsx @@ -8,6 +8,7 @@ import { COLORS } from '../../../styles/theme/colors' import { Layer, useGetRuntimeStatus } from '../../../oasis-indexer/api' import { useLayerParam } from '../../hooks/useLayerParam' import { AppErrors } from '../../../types/errors' +import { formatNumber } from '../../utils/numberFormatter' export const Nodes: FC = () => { const { t } = useTranslation() @@ -25,7 +26,7 @@ export const Nodes: FC = () => { <> - {t('nodes.value', { value: activeNodes })} + {formatNumber(activeNodes)} )} diff --git a/src/app/pages/DashboardPage/TotalTransactions.tsx b/src/app/pages/DashboardPage/TotalTransactions.tsx index 7f47cdab29..12145d7987 100644 --- a/src/app/pages/DashboardPage/TotalTransactions.tsx +++ b/src/app/pages/DashboardPage/TotalTransactions.tsx @@ -9,6 +9,7 @@ import { DurationPills } from './DurationPills' import { CardHeaderWithResponsiveActions } from './CardHeaderWithResponsiveActions' import { ChartDuration, cumulativeSum } from '../../utils/chart-utils' import { useLayerParam } from '../../hooks/useLayerParam' +import { formatNumber } from '../../utils/numberFormatter' export const TotalTransactions: FC = () => { const { t } = useTranslation() @@ -47,12 +48,9 @@ export const TotalTransactions: FC = () => { formatters={{ data: (value: number) => t('totalTransactions.tooltip', { - value, - formatParams: { - value: { - maximumFractionDigits: 2, - } satisfies Intl.NumberFormatOptions, - }, + value: formatNumber(value, { + maximumFractionDigits: 2, + })!, }), label: (value: string) => t('common.formattedDateTime', { diff --git a/src/app/pages/DashboardPage/TransactionsChartCard.tsx b/src/app/pages/DashboardPage/TransactionsChartCard.tsx index bbb60aa217..ca2fcf6e4d 100644 --- a/src/app/pages/DashboardPage/TransactionsChartCard.tsx +++ b/src/app/pages/DashboardPage/TransactionsChartCard.tsx @@ -14,6 +14,7 @@ import { SnapshotCard } from './SnapshotCard' import { PercentageGain } from '../../components/PercentageGain' import startOfHour from 'date-fns/startOfHour' import { useLayerParam } from '../../hooks/useLayerParam' +import { formatNumber } from '../../utils/numberFormatter' interface TransactionsChartCardProps { chartDuration: ChartDuration @@ -67,7 +68,7 @@ const TransactionsChartCardCmp: FC = ({ chartDuratio /> ) } - label={totalTransactions.toLocaleString()} + label={formatNumber(totalTransactions)} > {lineChartData && ( = ({ chartDuratio formatters={{ data: (value: number) => t('transactionsTpsChart.tooltip', { - value, - formatParams: { - value: { - maximumFractionDigits: 2, - } satisfies Intl.NumberFormatOptions, - }, + value: formatNumber(value, { + maximumFractionDigits: 2, + }), }), label: (value: string) => t('common.formattedDateTime', { diff --git a/src/app/pages/DashboardPage/TransactionsStats.tsx b/src/app/pages/DashboardPage/TransactionsStats.tsx index 34fb796f23..343a5a56d4 100644 --- a/src/app/pages/DashboardPage/TransactionsStats.tsx +++ b/src/app/pages/DashboardPage/TransactionsStats.tsx @@ -13,6 +13,7 @@ import { DurationPills } from './DurationPills' import { CardHeaderWithResponsiveActions } from './CardHeaderWithResponsiveActions' import { ChartDuration } from '../../utils/chart-utils' import { useLayerParam } from '../../hooks/useLayerParam' +import { formatNumber } from '../../utils/numberFormatter' export const TransactionsStats: FC = () => { const { t } = useTranslation() @@ -55,7 +56,7 @@ export const TransactionsStats: FC = () => { data={buckets.slice().reverse()} dataKey="tx_volume" formatters={{ - data: (value: number) => t('transactionStats.tooltip', { value: value.toLocaleString() }), + data: (value: number) => t('transactionStats.tooltip', { value: formatNumber(value) }), label: (value: string) => t('common.formattedDateTime', { timestamp: new Date(value), diff --git a/src/app/pages/TransactionDetailPage/index.tsx b/src/app/pages/TransactionDetailPage/index.tsx index 10691a8d37..307825bf88 100644 --- a/src/app/pages/TransactionDetailPage/index.tsx +++ b/src/app/pages/TransactionDetailPage/index.tsx @@ -27,6 +27,7 @@ import { useLayerParam } from '../../hooks/useLayerParam' import { BlockLink } from '../../components/Blocks/BlockLink' import { TransactionLink } from '../../components/Transactions/TransactionLink' import { TransactionLogs } from '../../components/Transactions/Logs' +import { formatNumber } from '../../utils/numberFormatter' type TransactionSelectionResult = { wantedTransaction?: RuntimeTransaction @@ -204,7 +205,7 @@ export const TransactionDetailView: FC<{
{t('common.valueInRose', { value: transaction.fee })}
{t('common.gasLimit')}
-
{transaction.gas_limit.toLocaleString()}
+
{formatNumber(transaction.gas_limit)}
)} diff --git a/src/app/utils/numberFormatter.ts b/src/app/utils/numberFormatter.ts new file mode 100644 index 0000000000..95a17110f3 --- /dev/null +++ b/src/app/utils/numberFormatter.ts @@ -0,0 +1,42 @@ +import { BigNumber } from 'bignumber.js' + +export type NumberFormattingParameters = Partial & { + // Additional features which are not natively supported by BigNumber + + decimalPlaces?: number + maximumFractionDigits?: number + roundingMode?: BigNumber.RoundingMode + unit?: string +} + +export const formatNumber = ( + inputNumber: number | string | BigNumber.Instance | undefined, + format: NumberFormattingParameters = {}, +): string | undefined => { + if (inputNumber === undefined) return + const { decimalPlaces, maximumFractionDigits, roundingMode, unit, ...formatting } = format + let number = + typeof inputNumber === 'number' + ? BigNumber(inputNumber.toString(2), 2) // This is required to keep all precision + : BigNumber(inputNumber) + if (maximumFractionDigits !== undefined) { + number = BigNumber(number.toFixed(maximumFractionDigits, roundingMode)) + } + const wantedFormat = { ...BigNumber.config().FORMAT, ...formatting } + const numberString = + decimalPlaces === undefined + ? number.toFormat(wantedFormat) + : roundingMode === undefined + ? number.toFormat(decimalPlaces, wantedFormat) + : number.toFormat(decimalPlaces, roundingMode, wantedFormat) + if (unit) { + const formattedUnit = number + .toNumber() + .toLocaleString(undefined, { style: 'unit', unit, unitDisplay: 'long' }) + .split(' ') + .at(-1) + return `${numberString} ${formattedUnit}` + } else { + return numberString + } +} diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index f7708ffc6f..a36dccad21 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -14,13 +14,13 @@ }, "activeAccounts": { "title": "Active Accounts", - "tooltip": "{{value, number}} accounts" + "tooltip": "{{value}} accounts" }, "blocks": { "latest": "Latest Blocks" }, "block": { - "gasUsed": "{{value, number}} | {{percentage, number}}" + "gasUsed": "{{value}} | {{percentage, number}}" }, "buildInternal": "Please note this is an internal launch meant to gather your feedback. Please share your feedback with screenshots through this from: ", "buildPreview": "Please note this is an experimental build of Oasis Explorer and that data that is shown might be incorrect.", @@ -34,7 +34,7 @@ "active": "Active", "balance": "Balance", "block": "Block", - "bytes": "{{value, number}}", + "bytes": "{{value}}", "change": "Change", "data": "Data", "emerald": "Emerald", @@ -79,8 +79,7 @@ "paraTimeOnline": "ParaTime Online" }, "nodes": { - "title": "Active nodes", - "value": "{{value, number}}" + "title": "Active nodes" }, "errors": { "code": "error code", @@ -152,7 +151,7 @@ }, "totalTransactions": { "header": "Total Transactions", - "tooltip": "{{value, number}} total transactions" + "tooltip": "{{value}} total transactions" }, "transactions": { "latest": "Latest Transactions", @@ -186,7 +185,7 @@ "tooltip": "{{value}} tx/day" }, "transactionsTpsChart": { - "tooltip": "{{value, number}} TPS" + "tooltip": "{{value}} TPS" }, "select": { "placeholder": "Select"