Skip to content

Commit

Permalink
Merge pull request #773 from oasisprotocol/lw/format-intl
Browse files Browse the repository at this point in the history
Precisely format large numbers using Intl through i18n
  • Loading branch information
lukaw3d authored Aug 8, 2023
2 parents 85e1730 + c2a618b commit 9eda808
Show file tree
Hide file tree
Showing 15 changed files with 283 additions and 18 deletions.
1 change: 1 addition & 0 deletions .changelog/773.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Precisely format large numbers using Intl through i18n
39 changes: 39 additions & 0 deletions .github/workflows/ci-playwright.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# NOTE: This name appears in GitHub's Checks API and in workflow's status badge.
name: ci-playwright

# Trigger the workflow when:
on:
# A push occurs to one of the matched branches.
push:
branches: [master]
# Or when a pull request event occurs for a pull request against one of the
# matched branches.
pull_request:
branches: [master]

jobs:
playwright:
# NOTE: This name appears in GitHub's Checks API.
name: playwright
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up Node.js 20
uses: actions/setup-node@v3
with:
node-version: '20.x'
cache: yarn
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Run dev server
run: yarn start &
- name: Install playwright
run: yarn install --frozen-lockfile
working-directory: playwright
- name: Install playwright dependencies
run: yarn playwright install --with-deps
working-directory: playwright
- name: Run playwright tests
run: yarn test
working-directory: playwright
4 changes: 4 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ const config = {
transformIgnorePatterns: [
'/node_modules/(?!(cborg)/)',
],
testPathIgnorePatterns: [
'/node_modules/',
'/playwright/'
],
}

module.exports = config
8 changes: 8 additions & 0 deletions playwright/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"scripts": {
"test": "playwright test --browser all"
},
"devDependencies": {
"@playwright/test": "^1.36.2"
}
}
80 changes: 80 additions & 0 deletions playwright/tests/getPreciseNumberFormat.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { Page, expect, test } from '@playwright/test'
import { RuntimeAccount } from '../../src/oasis-nexus/api'

async function setup(page: Page, balance: string, decimals: number) {
await page.route(
'https://api.coingecko.com/api/v3/simple/price?ids=oasis-network&vs_currencies=usd',
route => {
// Don't respond
},
)
await page.route('**/v1/', route => {
// Don't respond
})
await page.route('**/v1/sapphire/status', route => {
// Don't respond
})

await page.route('**/v1/sapphire/accounts/oasis1qq2v39p9fqk997vk6742axrzqyu9v2ncyuqt8uek', route => {
route.fulfill({
body: JSON.stringify({
address: 'oasis1qq2v39p9fqk997vk6742axrzqyu9v2ncyuqt8uek',
address_preimage: {
address_data: 'AAAAAAAAAAAAAAAAAAAAAAAAAAA=',
context: 'oasis-runtime-sdk/address: secp256k1eth',
context_version: 0,
},
balances: [],
evm_balances: [
{
balance: balance,
token_decimals: decimals,
token_contract_addr: 'oasis1qzpyvqpw4e55wj4wjasp70w30x3kxsp4evy5dtf8',
token_contract_addr_eth: '0x6b59C68405B0216C2C8ba1EC1f8DCcBd47892c58',
token_name: 'TokenForTests',
token_symbol: 'USDT',
token_type: 'ERC20',
},
],
stats: {
num_txns: 0,
total_received: '0',
total_sent: '0',
},
} satisfies Partial<RuntimeAccount>),
})
})

await page.goto(
'http://localhost:1234/mainnet/sapphire/address/0x0000000000000000000000000000000000000000/tokens/erc-20#tokens',
)
}

test.describe('getPreciseNumberFormat', () => {
test('small number should be precise and formatted', async ({ page }) => {
await setup(page, '111222333444555', 9)
// Expect precisely formatted small number even when browser doesn't support precise formatting for large numbers
await expect(page.getByText('111,222.333444555', { exact: true })).toBeVisible()
})

test('large number should be precise and formatted or fallback to precise unformatted number in browsers without support', async ({
page,
}) => {
await setup(page, '111222333444555666777888999111222333444555666', 18)
await expect(
page
.getByText('111,222,333,444,555,666,777,888,999.111222333444555666', { exact: true })
// Expect precise fallback when browser doesn't support precise formatting
.or(page.getByText('111222333444555666777888999.111222333444555666', { exact: true })),
).toBeVisible()
})

test('exceeding maximumFractionDigits:20 should fallback to precise unformatted number', async ({
page,
}) => {
await setup(page, '111222333444555666777888999111222333444555666', 36)
await expect(
page.getByText('111222333.444555666777888999111222333444555666', { exact: true }),
).toBeVisible()
})
})
28 changes: 28 additions & 0 deletions playwright/yarn.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


"@playwright/test@^1.36.2":
version "1.36.2"
resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.36.2.tgz#9edd68a02b0929c5d78d9479a654ceb981dfb592"
integrity sha512-2rVZeyPRjxfPH6J0oGJqE8YxiM1IBRyM8hyrXYK7eSiAqmbNhxwcLa7dZ7fy9Kj26V7FYia5fh9XJRq4Dqme+g==
dependencies:
"@types/node" "*"
playwright-core "1.36.2"
optionalDependencies:
fsevents "2.3.2"

"@types/node@*":
version "20.4.5"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.4.5.tgz#9dc0a5cb1ccce4f7a731660935ab70b9c00a5d69"
integrity sha512-rt40Nk13II9JwQBdeYqmbn2Q6IVTA5uPhvSO+JVqdXw/6/4glI6oR9ezty/A9Hg5u7JH4OmYmuQ+XvjKm0Datg==

[email protected]:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==

[email protected]:
version "1.36.2"
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.36.2.tgz#32382f2d96764c24c65a86ea336cf79721c2e50e"
integrity sha512-sQYZt31dwkqxOrP7xy2ggDfEzUxM1lodjhsQ3NMMv5uGTRDsLxU0e4xf4wwMkF2gplIxf17QMBCodSFgm6bFVQ==
15 changes: 12 additions & 3 deletions src/app/components/Account/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { ContractCreatorInfo } from './ContractCreatorInfo'
import { ContractVerificationIcon } from '../ContractVerificationIcon'
import { TokenLink } from '../Tokens/TokenLink'
import BigNumber from 'bignumber.js'
import { getPreciseNumberFormat } from '../../../locales/getPreciseNumberFormat'

export const StyledAvatarContainer = styled('dt')(({ theme }) => ({
'&&': {
Expand Down Expand Up @@ -141,7 +142,7 @@ export const Account: FC<AccountProps> = ({ account, token, isLoading, tokenPric
<dd>
{balance === undefined
? t('common.missing')
: t('common.valueInToken', { value: balance, ticker: nativeTickerName })}
: t('common.valueInToken', { ...getPreciseNumberFormat(balance), ticker: nativeTickerName })}
</dd>

<dt>{t('common.tokens')}</dt>
Expand Down Expand Up @@ -181,11 +182,19 @@ export const Account: FC<AccountProps> = ({ account, token, isLoading, tokenPric

<dt>{t('account.totalReceived')}</dt>
<dd>
{t('common.valueInToken', { value: account.stats.total_received, ticker: nativeTickerName })}
{t('common.valueInToken', {
...getPreciseNumberFormat(account.stats.total_received),
ticker: nativeTickerName,
})}
</dd>

<dt>{t('account.totalSent')}</dt>
<dd>{t('common.valueInToken', { value: account.stats.total_sent, ticker: nativeTickerName })}</dd>
<dd>
{t('common.valueInToken', {
...getPreciseNumberFormat(account.stats.total_sent),
ticker: nativeTickerName,
})}
</dd>
</StyledDescriptionList>
)}
</>
Expand Down
17 changes: 12 additions & 5 deletions src/app/components/RoundedBalance/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { getNameForTicker } from '../../../types/ticker'
import { SearchScope } from '../../../types/searchScope'
import { TokenLink } from '../Tokens/TokenLink'
import { PlaceholderLabel } from '../../utils/PlaceholderLabel'
import { getPreciseNumberFormat } from '../../../locales/getPreciseNumberFormat'

type RoundedBalanceProps = {
ticker?: string
Expand Down Expand Up @@ -50,13 +51,13 @@ export const RoundedBalance: FC<RoundedBalanceProps> = ({
<Tooltip
arrow
placement="top"
title={t('common.valueInToken', { value: number.toFormat(), ticker: tickerName })}
title={t('common.valueInToken', { ...getPreciseNumberFormat(value), ticker: tickerName })}
enterDelay={tooltipDelay}
enterNextDelay={tooltipDelay}
>
<span>
{t('common.valuePair', {
value: number.toFixed(),
value: value,
formatParams: {
value: {
notation: 'compact',
Expand All @@ -75,7 +76,7 @@ export const RoundedBalance: FC<RoundedBalanceProps> = ({
<Trans
t={t}
i18nKey="common.valueInTokenWithLink"
values={{ value: number.toFormat() }}
values={{ ...getPreciseNumberFormat(value) }}
components={{ TickerLink: tickerLink }}
/>
)
Expand All @@ -88,7 +89,7 @@ export const RoundedBalance: FC<RoundedBalanceProps> = ({
<Tooltip
arrow
placement="top"
title={t('common.valueInToken', { value: number.toFormat(), ticker: tickerName })}
title={t('common.valueInToken', { ...getPreciseNumberFormat(value), ticker: tickerName })}
enterDelay={tooltipDelay}
enterNextDelay={tooltipDelay}
>
Expand All @@ -97,7 +98,13 @@ export const RoundedBalance: FC<RoundedBalanceProps> = ({
t={t}
i18nKey={almostZero ? 'common.lessThanAmount' : 'common.roundedValueInToken'}
values={{
value: truncatedNumber.toFormat(numberOfDecimals),
value: truncatedNumber.toFixed(numberOfDecimals),
formatParams: {
value: {
minimumFractionDigits: numberOfDecimals,
maximumFractionDigits: numberOfDecimals,
} satisfies Intl.NumberFormatOptions,
},
}}
shouldUnescape={true}
components={{ TickerLink: tickerLink }}
Expand Down
5 changes: 3 additions & 2 deletions src/app/components/Transactions/LogEvent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { WithdrawIcon } from './../CustomIcons/Withdraw'
import { COLORS } from '../../../styles/theme/colors'
import StreamIcon from '@mui/icons-material/Stream'
import LocalFireDepartmentIcon from '@mui/icons-material/LocalFireDepartment'
import { getPreciseNumberFormat } from '../../../locales/getPreciseNumberFormat'

export const EventTypeIcon: FC<{
eventType: RuntimeEventType
Expand Down Expand Up @@ -220,7 +221,7 @@ const LogEvent: FC<{
<dt>{t('transactionEvent.fields.amount')}</dt>
<dd>
{t('common.valueInToken', {
value: event.body.amount.Amount,
...getPreciseNumberFormat(event.body.amount.Amount),
ticker: event.body.amount.Denomination,
})}
</dd>
Expand Down Expand Up @@ -257,7 +258,7 @@ const LogEvent: FC<{
<dt>{t('transactionEvent.fields.amount')}</dt>
<dd>
{t('common.valueInToken', {
value: event.body.amount.Amount,
...getPreciseNumberFormat(event.body.amount.Amount),
ticker: event.body.amount.Denomination,
})}
</dd>
Expand Down
3 changes: 2 additions & 1 deletion src/app/pages/AccountDetailsPage/AccountTokensCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
import { SearchScope } from '../../../types/searchScope'
import Skeleton from '@mui/material/Skeleton'
import { AccountDetailsContext } from './index'
import { getPreciseNumberFormat } from '../../../locales/getPreciseNumberFormat'

type AccountTokensCardProps = AccountDetailsContext & {
type: EvmTokenType
Expand Down Expand Up @@ -98,7 +99,7 @@ export const AccountTokensCard: FC<AccountTokensCardProps> = ({ scope, address,
},
{
align: TableCellAlign.Right,
content: item.balance,
content: t('common.valueLong', getPreciseNumberFormat(item.balance)),
key: 'balance',
},
{
Expand Down
3 changes: 2 additions & 1 deletion src/app/pages/TokenDashboardPage/TokenDetailsCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { DelayedContractCreatorInfo } from '../../components/Account/ContractCre
import CardContent from '@mui/material/CardContent'
import { TokenTypeTag } from '../../components/Tokens/TokenList'
import { SearchScope } from '../../../types/searchScope'
import { getPreciseNumberFormat } from '../../../locales/getPreciseNumberFormat'

export const TokenDetailsCard: FC<{ scope: SearchScope; address: string }> = ({ scope, address }) => {
const { t } = useTranslation()
Expand Down Expand Up @@ -71,7 +72,7 @@ export const TokenDetailsCard: FC<{ scope: SearchScope; address: string }> = ({
<dd>
{balance === undefined
? t('common.missing')
: t('common.valueInToken', { value: balance, ticker: tickerName })}
: t('common.valueInToken', { ...getPreciseNumberFormat(balance), ticker: tickerName })}
</dd>
</StyledDescriptionList>
)}
Expand Down
14 changes: 12 additions & 2 deletions src/app/pages/TransactionDetailPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import Tooltip from '@mui/material/Tooltip'
import { TransactionEncrypted } from '../../components/TransactionEncryptionStatus'
import Typography from '@mui/material/Typography'
import { LongDataDisplay } from '../../components/LongDataDisplay'
import { getPreciseNumberFormat } from '../../../locales/getPreciseNumberFormat'

type TransactionSelectionResult = {
wantedTransaction?: RuntimeTransaction
Expand Down Expand Up @@ -298,7 +299,14 @@ export const TransactionDetailView: FC<{
)}

<dt>{t('common.value')}</dt>
<dd>{t('common.valueInToken', { value: transaction.amount, ticker: tickerName })}</dd>
<dd>
{transaction.amount != null
? t('common.valueInToken', {
...getPreciseNumberFormat(transaction.amount),
ticker: tickerName,
})
: t('common.missing')}
</dd>

{transaction.amount !== undefined &&
!!tokenPriceInfo &&
Expand All @@ -314,7 +322,9 @@ export const TransactionDetailView: FC<{
)}

<dt>{t('common.txnFee')}</dt>
<dd>{t('common.valueInToken', { value: transaction.fee, ticker: tickerName })}</dd>
<dd>
{t('common.valueInToken', { ...getPreciseNumberFormat(transaction.fee), ticker: tickerName })}
</dd>

<dt>{t('common.gasLimit')}</dt>
<dd>{transaction.gas_limit.toLocaleString()}</dd>
Expand Down
Loading

0 comments on commit 9eda808

Please sign in to comment.