Skip to content

feat: add unified formatting standard#604

Open
ECWireless wants to merge 2 commits intomainfrom
feat/add-unified-formatting-standard
Open

feat: add unified formatting standard#604
ECWireless wants to merge 2 commits intomainfrom
feat/add-unified-formatting-standard

Conversation

@ECWireless
Copy link
Collaborator

See #545 for all details. Original PR created by @Roaring30s .

Roaring30s and others added 2 commits March 26, 2026 18:54
* feat: add numberFormatter and web3 utils

* feat: add formatting

* fix: fix bug

* fix: remove extra formatPercent

* fix: fix UI bugs

* fix: add abbreviation

* fix: remove linting errors

* fix: remove conflict

* fix: add linter checks

---------

Co-authored-by: ECWireless <40322776+ECWireless@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 27, 2026 01:06
@vercel
Copy link
Contributor

vercel bot commented Mar 27, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
explorer-arbitrum-one Ready Ready Preview, Comment Mar 27, 2026 1:06am

Request Review

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces centralized number/address formatting utilities and migrates many Explorer UI surfaces (voting, treasury, orchestrators, transactions, charts, and account views) away from ad-hoc formatting/divisors to shared formatters and constants.

Changes:

  • Added utils/numberFormatters.ts (LPT/ETH/USD/percent/round/number) with accompanying tests.
  • Added utils/web3.ts (address helpers, wei conversions, percent precision constants) and migrated call sites from @lib/utils.
  • Replaced scattered manual formatting across multiple pages/components (percent divisors, LPT/ETH display, address/hash shortening).

Reviewed changes

Copilot reviewed 50 out of 51 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
utils/web3.ts New web3/address + wei conversion helpers and percent precision constants
utils/web3.test.ts Unit tests for new utils/web3 helpers
utils/voting.ts Removes local formatPercent; switches fromWei import to @utils/web3
utils/numberFormatters.ts New centralized formatting utilities for LPT/ETH/USD/percent/etc.
utils/numberFormatters.test.ts Unit tests for new number formatting utilities
tsconfig.json Adds @utils/* path alias
pages/voting/create-poll.tsx Switches fromWei import to @utils/web3
pages/voting/[poll].tsx Uses shared formatters/constants instead of local/manual formatting
pages/treasury/create-proposal.tsx Uses formatLPT + fromWei/toWei from @utils/web3
pages/treasury/[proposal].tsx Uses shared formatters/constants; moves web3 helpers to @utils/web3
pages/migrate/orchestrator.tsx Switches address/hash formatting to @utils/web3
pages/migrate/delegator/index.tsx Switches address/hash formatting to @utils/web3
pages/migrate/broadcaster.tsx Switches address/hash formatting to @utils/web3
pages/index.tsx Replaces hardcoded inflation divisor with PERCENTAGE_PRECISION_BILLION
pages/api/score/[address].tsx Moves checkAddressEquality to @utils/web3
pages/api/l1-delegator/[address].tsx Moves EMPTY_ADDRESS to @utils/web3
pages/_app.tsx Removes global numbro.setDefaults initialization
lib/utils.tsx Removes web3/formatting helpers now housed in @utils/web3
lib/utils.test.ts Removes tests for moved helpers; imports EMPTY_ADDRESS from @utils/web3
lib/api/treasury.ts Switches fromWei import to @utils/web3
lib/api/ens.ts Switches formatAddress import to @utils/web3
layouts/main.tsx Switches EMPTY_ADDRESS/formatAddress imports to @utils/web3
layouts/account.tsx Switches checkAddressEquality import to @utils/web3
hooks/useSwr.tsx Switches formatAddress import to @utils/web3
components/TxStartedDialog/index.tsx Switches formatAddress/fromWei imports to @utils/web3
components/TxConfirmedDialog/index.tsx Switches formatAddress/fromWei imports to @utils/web3
components/Treasury/TreasuryVotingWidget/index.tsx Replaces various percent/LPT formatting with shared formatters
components/Treasury/TreasuryVoteTable/index.tsx Standardizes weight formatting with shared formatters
components/Treasury/TreasuryVoteTable/Views/VoteItem.tsx Switches formatTransactionHash import to @utils/web3
components/Treasury/TreasuryVoteTable/TreasuryVotePopover.tsx Uses formatNumber for vote counts
components/TransactionsList/index.tsx Replaces numbro/manual formatting with shared formatters/constants
components/TransactionBadge/index.tsx Switches formatTransactionHash import to @utils/web3
components/StakeTransactions/index.tsx Uses formatLPT and formatAddress from new utils
components/Search/index.tsx Switches formatAddress import to @utils/web3
components/RoundStatus/index.tsx Replaces numbro formatting with shared formatters
components/Profile/index.tsx Switches formatAddress import to @utils/web3
components/PollVotingWidget/index.tsx Uses shared percent + voting power formatting
components/PerformanceList/index.tsx Replaces numbro formatting with formatNumber/formatPercent + web3 address formatting
components/OrchestratorList/index.tsx Replaces numbro/manual percent formatting and divisors with shared formatters/constants
components/OrchestratingView/index.tsx Replaces numbro/manual formatting with shared formatters/constants
components/HistoryView/index.tsx Replaces numbro/manual formatting with shared formatters/constants
components/ExplorerChart/index.tsx Moves most subtitle/axis formatting to shared formatters
components/DelegatingWidget/index.tsx Uses formatLPT and fromWei from new utils
components/DelegatingWidget/ProjectionBox.tsx Uses shared formatters for ROI, principle, fees/rewards
components/DelegatingWidget/InputBox.tsx Switches fromWei import to @utils/web3
components/DelegatingWidget/Input.tsx Replaces hardcoded divisors with percent precision constants
components/DelegatingWidget/Header.tsx Switches formatAddress import to @utils/web3
components/DelegatingView/index.tsx Replaces numbro/manual formatting with shared formatters
components/Claim/index.tsx Switches formatAddress import to @utils/web3
components/AccountCell/index.tsx Switches formatAddress import to @utils/web3
components/Account/index.tsx Switches formatAddress import to @utils/web3

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

totalWeight > 0 ? ((parseFloat(w) / totalWeight) * 100).toFixed(2) : "0"
}%)`,
`${formatLPT(parseFloat(w), { abbreviate: false })} (${
totalWeight > 0 ? formatPercent(parseFloat(w) / totalWeight) : "0"
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When totalWeight is 0, formatWeight returns "0" (no percent sign) for the percentage portion, while the non-zero path returns values like "12.34%". Return "0%" (or use formatPercent(0)) for consistency.

Suggested change
totalWeight > 0 ? formatPercent(parseFloat(w) / totalWeight) : "0"
totalWeight > 0
? formatPercent(parseFloat(w) / totalWeight)
: formatPercent(0)

Copilot uses AI. Check for mistakes.
Comment on lines +229 to +233
<Box>
Total Support (
{+pollData.quota / PERCENTAGE_PRECISION_TEN_THOUSAND}%
needed)
</Box>
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The quota/quorum labels are still manually computing a percent (quota / PERCENTAGE_PRECISION_TEN_THOUSAND) and then appending %. Given poll quota/quorum are treated as 1e6-scaled fractions elsewhere (e.g. lib/api/polls.ts uses / 1_000_000), this would be clearer/less error-prone as formatPercent(+pollData.quota / PERCENTAGE_PRECISION_MILLION) (same for quorum) without manual % concatenation.

Copilot uses AI. Check for mistakes.
);

const formattedPrinciple = formatLPT(Number(principle) || 150, {
precision: 0,
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

formattedPrinciple is now built via formatLPT(...), which includes the LPT symbol by default. Elsewhere in this file the tooltip text still appends LPT after {formattedPrinciple}, which will result in duplicated units (e.g. 150 LPT LPT). Consider setting showSymbol: false here (or removing the extra LPT in the tooltip).

Suggested change
precision: 0,
precision: 0,
showSymbol: false,

Copilot uses AI. Check for mistakes.
Comment on lines +92 to +107
// Derive protocol inflation data
const inflationRate =
Number(protocolData?.inflation || 0) / PERCENTAGE_PRECISION_BILLION;
const inflationChangeAmount =
Number(protocolData?.inflationChange || 0) / PERCENTAGE_PRECISION_BILLION;
const inflationChangeSign =
Number(protocolData?.inflationChange || 0) > 0 ? "+" : "";

const formatPercentChange = useCallback(
(change: ROIInflationChange) =>
change === "none"
? `Fixed at ${numbro(
Number(protocolData?.inflation) / 1000000000
).format({
mantissa: 3,
output: "percent",
})}`
: `${numbro(
(change === "negative" ? -1 : 1) *
(Number(protocolData?.inflationChange) / 1000000000)
).format({
mantissa: 5,
output: "percent",
forceSign: true,
? `Fixed at ${formatPercent(inflationRate, { precision: 3 })}`
: `${inflationChangeSign}${formatPercent(inflationChangeAmount, {
precision: 5,
})} per round`,

[protocolData?.inflation, protocolData?.inflationChange]
[inflationRate, inflationChangeAmount, inflationChangeSign]
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

formatPercentChange ignores its change argument for the sign of the inflation change. Since protocolData.inflationChange comes from a uint256 (always positive magnitude), selecting the "negative" option will still display a positive change (e.g. +0.00010% per round). The sign should be derived from change (and/or forceSign), not from the raw protocol value.

Copilot uses AI. Check for mistakes.
Comment on lines 121 to 125
const transcodingInfo = outputTrans
? `${numbro(maxScore.transcoding?.score).divide(100).format({
output: "percent",
mantissa: 1,
})} - ${maxScore.transcoding.region}`
? `${formatPercent(maxScore.transcoding?.score)} - ${
maxScore.transcoding.region
}`
: "";
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maxScore.transcoding.score is produced by the /api/score endpoint as a 0–100 value (see pages/api/score/[address].tsx multiplying by 100). formatPercent expects a 0–1 fraction, so this will display 100x too large (e.g. 95 -> 9500%). Convert the score to a fraction (divide by 100) before calling formatPercent (and keep the prior 1-decimal precision if desired).

Copilot uses AI. Check for mistakes.
output: "percent",
mantissa: 0,
})
? formatPercent(+(transcoder?.rewardCut || 0) / 1000000)
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file imports PERCENTAGE_PRECISION_MILLION and uses it for feeShare, but rewardCut still divides by the hardcoded 1000000. Use the shared constant here as well to keep percent-scaling consistent and avoid future drift.

Suggested change
? formatPercent(+(transcoder?.rewardCut || 0) / 1000000)
? formatPercent(
+(transcoder?.rewardCut || 0) / PERCENTAGE_PRECISION_MILLION
)

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Review

Development

Successfully merging this pull request may close these issues.

3 participants