Skip to content

Commit

Permalink
chore: Ensure localised currency display after merge
Browse files Browse the repository at this point in the history
After merging the main branch, updated the code to ensure localised currency is correctly displayed in both existing functionality and newly added features
  • Loading branch information
joeljkrb committed Feb 25, 2025
1 parent afb722e commit b975479
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 55 deletions.
64 changes: 64 additions & 0 deletions packages/app/src/library/FiatValue/LocalizedFiatValue.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright 2025 @polkadot-cloud/polkadot-staking-dashboard authors & contributors
// SPDX-License-Identifier: GPL-3.0-only

import type BigNumber from 'bignumber.js'
import { useTokenPrices } from 'contexts/TokenPrice'
import { formatFiatCurrency } from 'locales/src/util'

interface LocalizedFiatValueProps {
value?: number | BigNumber
tokenBalance?: number | BigNumber
showPlus?: boolean
wrapParentheses?: boolean
withApprox?: boolean
}

/**
* Component for displaying fiat values in the user's local currency.
* Can accept either a direct value or a token balance to be converted.
*/
export const LocalizedFiatValue = ({
value,
tokenBalance,
showPlus = false,
wrapParentheses = false,
withApprox = false,
}: LocalizedFiatValueProps) => {
const { price } = useTokenPrices()

const calculateValue = (): number => {
if (value !== undefined) {
return typeof value === 'number' ? value : value.toNumber()
}

// Calculate from token balance
if (tokenBalance !== undefined && price) {
const balance =
typeof tokenBalance === 'number'
? tokenBalance
: tokenBalance.toNumber()

return balance * price
}

return 0
}

const finalValue = calculateValue()

let formatted = formatFiatCurrency(finalValue)

if (showPlus && finalValue > 0) {
formatted = `+${formatted}`
}

if (withApprox) {
formatted = `≈ ${formatted}`
}

if (wrapParentheses) {
formatted = `(${formatted})`
}

return formatted
}
34 changes: 13 additions & 21 deletions packages/app/src/library/FiatValue/index.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,24 @@
// Copyright 2025 @polkadot-cloud/polkadot-staking-dashboard authors & contributors
// SPDX-License-Identifier: GPL-3.0-only

import BigNumber from 'bignumber.js'
import { useNetwork } from 'contexts/Network'
import type BigNumber from 'bignumber.js'
import { useTokenPrices } from 'contexts/TokenPrice'
import { formatFiatCurrency } from 'locales/src/util'

export const FiatValue = ({
tokenBalance,
currency,
}: {
tokenBalance: number
currency: string
}) => {
const { network } = useNetwork()
interface FiatValueProps {
tokenBalance: number | BigNumber
currency?: string
}

export const FiatValue = ({ tokenBalance }: FiatValueProps) => {
const { price } = useTokenPrices()

// Convert balance to fiat value
const freeFiat = new BigNumber(tokenBalance * price).decimalPlaces(2)

// Formatter for price feed
const formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency,
})
const balance =
typeof tokenBalance === 'number' ? tokenBalance : tokenBalance.toNumber()

if (network === 'westend') {
return null
}
const fiatValue = balance * price

return <>{formatter.format(freeFiat.toNumber())}</>
// Format using the user's preferred currency
return <>{formatFiatCurrency(fiatValue)}</>
}
35 changes: 23 additions & 12 deletions packages/app/src/pages/Overview/Payouts/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ import { useNetwork } from 'contexts/Network'
import { usePlugins } from 'contexts/Plugins'
import { useActivePool } from 'contexts/Pools/ActivePool'
import { useStaking } from 'contexts/Staking'
import { useTokenPrices } from 'contexts/TokenPrice'
import { useUi } from 'contexts/UI'
import { formatDistance, fromUnixTime, getUnixTime } from 'date-fns'
import { useSyncing } from 'hooks/useSyncing'
import { formatSize } from 'library/Graphs/Utils'
import { GraphWrapper } from 'library/Graphs/Wrapper'
import { StatusLabel } from 'library/StatusLabel'
import { DefaultLocale, locales } from 'locales'
import { formatFiatCurrency } from 'locales/src/util'
import type { RewardResult } from 'plugin-staking-api/types'
import { useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
Expand All @@ -37,6 +39,7 @@ export const Payouts = () => {
const { containerRefs } = useUi()
const { inPool } = useActivePool()
const { pluginEnabled } = usePlugins()
const { price: tokenPrice } = useTokenPrices()

const staking = !inSetup() || inPool
const notStaking = !syncing && !staking
Expand All @@ -63,28 +66,36 @@ export const Payouts = () => {
}
}

// Calculate the fiat value of the reward
const rewardAmount =
lastReward === undefined
? new BigNumber(0)
: planckToUnitBn(new BigNumber(lastReward?.reward || 0), units)

// Get formatted amount
const formattedAmount = minDecimalPlaces(rewardAmount.toFormat(), 2)

return (
<>
<CardHeader>
<h4>{t('recentPayouts')}</h4>
<h2>
<Token />
<Odometer
value={minDecimalPlaces(
lastReward === undefined
? '0'
: planckToUnitBn(
new BigNumber(lastReward?.reward || 0),
units
).toFormat(),
2
)}
/>
<Odometer value={formattedAmount} zeroDecimals={2} />
<CardLabel>
{lastReward === undefined ? (
''
) : (
<>&nbsp;{formatDistance(formatFrom, formatTo, formatOpts)}</>
<>
&nbsp;{formatDistance(formatFrom, formatTo, formatOpts)}
{rewardAmount.isGreaterThan(0) && tokenPrice > 0 && (
<span style={{ marginLeft: '0.5rem', opacity: 0.75 }}>
{formatFiatCurrency(
rewardAmount.multipliedBy(tokenPrice).toNumber()
)}
</span>
)}
</>
)}
</CardLabel>
</h2>
Expand Down
35 changes: 13 additions & 22 deletions packages/app/src/pages/Rewards/Overview/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { useTransferOptions } from 'contexts/TransferOptions'
import { useValidators } from 'contexts/Validators/ValidatorEntries'
import { useAverageRewardRate } from 'hooks/useAverageRewardRate'
import { CardWrapper } from 'library/Card/Wrappers'
import { FiatValue } from 'library/FiatValue'
import { formatFiatCurrency, getUserFiatCurrency } from 'locales/src/util'
import { AverageRewardRate } from 'pages/Overview/Stats/AveragelRewardRate'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
Expand Down Expand Up @@ -76,8 +76,11 @@ export const Overview = (props: PayoutHistoryProps) => {
? dailyRewardAfterCommission
: annualRewardBase / 365

const currency = 'USD'
const symbol = '$'
// Get the user's preferred currency
const userCurrency = getUserFiatCurrency() || 'USD'

// Format the currency with user's locale and currency preference
const formatLocalCurrency = (value: number) => formatFiatCurrency(value)

return (
<>
Expand All @@ -90,8 +93,8 @@ export const Overview = (props: PayoutHistoryProps) => {
key: 'RewardCalculator',
size: 'xs',
options: {
currency,
symbol,
currency: userCurrency,
symbol: '', // Symbol will be provided by formatFiatCurrency
},
})
}}
Expand Down Expand Up @@ -121,7 +124,7 @@ export const Overview = (props: PayoutHistoryProps) => {
zeroDecimals={2}
/>
<CardLabel>
<FiatValue tokenBalance={currentStake} currency={currency} />
{formatLocalCurrency(currentStake * tokenPrice)}
</CardLabel>
</h2>
</CardHeader>
Expand Down Expand Up @@ -157,7 +160,7 @@ export const Overview = (props: PayoutHistoryProps) => {
<Token />
{unit}
</h4>,
<h4>{currency}</h4>,
<h4>{userCurrency}</h4>,
]}
/>
</RewardGrid.Head>
Expand All @@ -179,11 +182,7 @@ export const Overview = (props: PayoutHistoryProps) => {
{dailyReward > 0 && tokenPrice > 0 && (
<FontAwesomeIcon icon={faCaretUp} />
)}
{symbol}
{(dailyReward * tokenPrice).toLocaleString('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
})}
{formatLocalCurrency(dailyReward * tokenPrice)}
</h3>
</RewardGrid.Cell>
</RewardGrid.Row>
Expand All @@ -204,11 +203,7 @@ export const Overview = (props: PayoutHistoryProps) => {
{monthlyReward > 0 && tokenPrice > 0 && (
<FontAwesomeIcon icon={faCaretUp} />
)}
{symbol}
{(monthlyReward * tokenPrice).toLocaleString('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
})}
{formatLocalCurrency(monthlyReward * tokenPrice)}
</h3>,
]}
/>
Expand All @@ -228,11 +223,7 @@ export const Overview = (props: PayoutHistoryProps) => {
{annualReward > 0 && tokenPrice > 0 && (
<FontAwesomeIcon icon={faCaretUp} />
)}
{symbol}
{(annualReward * tokenPrice).toLocaleString('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
})}
{formatLocalCurrency(annualReward * tokenPrice)}
</h3>,
]}
/>
Expand Down

0 comments on commit b975479

Please sign in to comment.