fix: the balance lists and Home cut amounts to four decimals (closes #757)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run

The balance lists and Home's ETH line rounded with toFixed(4), so 0.99996
ETH read 1.0000 there and 0.9999 on Send. They now cut the stored decimal
string with truncateAmount(), as the history rows do. balanceLine() takes
the stored balance string instead of a parsed number, and escapes the
quantity cell. The screens that state what is authorized keep the floor
of truncateAmountNeverZero().

Model: opus-5-5
This commit is contained in:
sneak committed 2026-11-10 21:54:45 +00:00
1 parent 6d158bf1b1
commit fb7c75101f
12 files changed
+146 -54

No files matched your search

+6 -5
View File
@@ -159,10 +159,10 @@ function renderBalance() {
const addr =
state.wallets[state.selectedWallet].addresses[state.selectedAddress];
const tokenId = state.selectedToken;
let amount, price;
let balance, price;
if (tokenId === "ETH") {
// null when no refresh has read the balance.
amount = unknownableAmount(addr.balance);
balance = addr.balance;
price = getPrice("ETH");
} else {
const id = tokenId.toLowerCase();
@@ -175,12 +175,13 @@ function renderBalance() {
// null when the scale is unknown, or when no refresh has read the
// token's balance: no quantity to show, and none to price.
// balanceLine() states that rather than printing 0.0000.
if (tb) amount = unknownableAmount(tb.balance);
else amount = tracked && tracked.balanceNotFetched ? null : 0;
if (tb) balance = tb.balance;
else balance = tracked && tracked.balanceNotFetched ? null : "0";
price = getPrice(tokenId);
}
// USD total for this token only
const amount = unknownableAmount(balance);
const usdVal = price && amount !== null ? amount * price : null;
const usdStr = formatUsd(usdVal);
$("address-token-usd-total").innerHTML = escapeHtml(usdStr) || " ";
@@ -188,7 +189,7 @@ function renderBalance() {
// Single token balance line (no tokenId — not clickable here)
$("address-token-balance").innerHTML = balanceLine(
currentSymbol,
amount,
balance,
price,
);
}
+2 -2
View File
@@ -79,8 +79,8 @@ function recoveryPathText(wallet) {
// "Holds" means ETH or any ERC-20 the wallet knows about — an address with no
// ETH and a five-figure stablecoin position must not get the blank line on
// the one screen whose job is to warn. The sentence names no figure of its
// own: the rendered lines round to four decimals, so a sentence built from a
// rounded number would report "0.0000 ETH" for an address holding real money.
// own: the rendered lines cut to four decimals, so a sentence built from their
// figure would report "0.0000 ETH" for an address holding real money.
// The lines below it carry the amounts, in the same format as Home and
// AddressDetail, followed by the USD total when there is one to give — no
// total line at all on testnet, before the first price fetch or while no
+14 -11
View File
@@ -18,6 +18,7 @@
const { formatEther } = require("ethers");
const makeBlockie = require("ethereum-blockies-base64");
const {
truncateAmount,
truncateAmountNeverZero,
isBelowOneMillionth,
} = require("../../shared/amountDisplay");
@@ -373,13 +374,15 @@ function formatFee(wei, symbol, chainId) {
// the row that issue #307 was reported against: every screen that lists a
// holding renders through here.
//
// `amount` is null for a holding whose scale nothing knows
// `balance` is the stored balance, a decimal string. It is null for a holding
// whose scale nothing knows
// (https://git.eeqj.de/sneak/AutistMask/issues/349), and for a balance no
// refresh has read. There is no quantity to print for it and no fiat value to
// derive from one, and printing 0.0000 for a real holding is the failure this
// whole rule exists to prevent, so the row says so instead.
function balanceLine(symbol, amount, price, tokenId) {
const qty = amount === null ? "quantity unknown" : amount.toFixed(4);
function balanceLine(symbol, balance, price, tokenId) {
const amount = unknownableAmount(balance);
const qty = amount === null ? "quantity unknown" : truncateAmount(balance);
const usd =
price && amount !== null
? escapeHtml(formatUsd(amount * price)) || " "
@@ -394,7 +397,7 @@ function balanceLine(symbol, amount, price, tokenId) {
`<div class="flex text-xs${clickClass}"${tokenAttr}>` +
`<span class="flex justify-between w-[42ch] max-w-full">` +
`<span>${escapeHtml(displaySymbol(symbol))}</span>` +
`<span>${qty}</span>` +
`<span>${escapeHtml(qty)}</span>` +
`</span>` +
`<span class="text-right text-muted flex-1">${usd}</span>` +
`</div>`
@@ -420,7 +423,7 @@ function markTrackedTokensNotFetched() {
function balanceLinesForAddress(addr, trackedTokens, showZero) {
let html = balanceLine(
nativeCurrency(),
unknownableAmount(addr.balance),
addr.balance,
getPrice("ETH"),
"ETH",
);
@@ -438,7 +441,7 @@ function balanceLinesForAddress(addr, trackedTokens, showZero) {
if (bal === 0 && !showZero) continue;
html += balanceLine(
t.symbol,
bal,
t.balance,
getPrice(t.address),
t.address.toLowerCase(),
);
@@ -456,7 +459,7 @@ function balanceLinesForAddress(addr, trackedTokens, showZero) {
}
html += balanceLine(
t.symbol,
t.balanceNotFetched ? null : 0,
t.balanceNotFetched ? null : "0",
getPrice(t.address),
t.address.toLowerCase(),
);
@@ -467,10 +470,10 @@ function balanceLinesForAddress(addr, trackedTokens, showZero) {
// Whether an address holds anything at all: ETH or any ERC-20 the wallet
// knows about, except a token holding below 0.000001, which the balance list
// under the remove-address warning leaves out too. Deliberately unrounded —
// the rendered lines round to four decimals, so a dust balance displays as
// 0.0000 while still being real money at a real address. Callers that warn
// about holdings must ask this, not the rendered figure.
// under the remove-address warning leaves out too. Deliberately exact — the
// rendered lines cut to four decimals, so a dust balance displays as 0.0000
// while still being real money at a real address. Callers that warn about
// holdings must ask this, not the rendered figure.
function addressHoldsFunds(addr) {
if (!addr) return false;
// A null or absent ETH balance reads as unknown, so the address may hold
+2 -1
View File
@@ -31,6 +31,7 @@ const {
resetSendValidation,
} = require("./send");
const { deriveAddressFromXpub } = require("../../shared/wallet");
const { truncateAmount } = require("../../shared/amountDisplay");
const { canRemoveAddress } = require("../../shared/walletDelete");
const {
walletDefect,
@@ -81,7 +82,7 @@ function renderTotalValue() {
if (ethBal === null) {
el.textContent = "unknown (" + nativeCurrency() + ")";
} else {
const ethStr = ethBal.toFixed(4) + " " + nativeCurrency();
const ethStr = truncateAmount(addr.balance) + " " + nativeCurrency();
const ethUsd = ethPrice
? " (" + formatUsd(ethBal * ethPrice) + ")"
: "";