An amount below the 4-decimal display floor now extends to its first significant digit on the approval and confirmation screens, instead of stating a real transfer, allowance or swap Min. received as 0.0000. The rule had been implemented three times; all three now share src/shared/amountDisplay.js, which holds the plain truncation and the floored variant side by side. History and balance lists keep the unfloored rule, pinned by test.
47 lines
2.3 KiB
JavaScript
47 lines
2.3 KiB
JavaScript
// The 4-decimal amount rule from README.md's Display Consistency section, and
|
|
// the one exception to it, in one place. Three call sites had grown their own
|
|
// copy of the truncation — the history and balance lists
|
|
// (`src/shared/transactions.js`), the approval screen's ERC-20 amount line
|
|
// (`src/popup/views/approval.js`) and its Uniswap swap detail lines
|
|
// (`src/shared/uniswap.js`) — and a fix applied to one of them left the other
|
|
// two showing a different number for the same value.
|
|
//
|
|
// The two functions below are the two policies, not two implementations of
|
|
// one: summary lists truncate, and the screens that state what is being
|
|
// authorized truncate with a floor. Keeping them adjacent is the point, so a
|
|
// change to the rule cannot reach one screen and miss another.
|
|
|
|
// Truncate to exactly four decimal places. Truncation, never rounding: an
|
|
// amount must never be displayed as larger than it is, so 0.99999 stays
|
|
// 0.9999.
|
|
function truncateAmount(val) {
|
|
const parts = val.split(".");
|
|
if (parts.length === 1) return val + ".0000";
|
|
return parts[0] + "." + (parts[1] + "0000").slice(0, 4);
|
|
}
|
|
|
|
// The same rule, plus the invariant the approval and confirmation screens
|
|
// hold: a nonzero amount never renders as zero. Truncating to four decimals
|
|
// does exactly that to an amount below 0.0001 — one base unit of an 18-decimal
|
|
// token, 500 of an 8-decimal one — and a real transfer or allowance then reads
|
|
// as "nothing is being moved" on the screen whose whole job is to say what is
|
|
// being authorized.
|
|
//
|
|
// When the truncated string carries no significant digit and the value does,
|
|
// the amount is extended to its first significant digit instead. It stays in
|
|
// token units, the same unit as the symbol printed beside it. A genuine zero
|
|
// still renders 0.0000, and anything at or above the floor is untouched.
|
|
function truncateAmountNeverZero(val) {
|
|
const truncated = truncateAmount(val);
|
|
// Tests the whole truncated string, integer part included: 1.00005 has a
|
|
// significant digit already and stays 1.0000.
|
|
if (/[1-9]/.test(truncated)) return truncated;
|
|
const parts = val.split(".");
|
|
if (parts.length === 1) return truncated;
|
|
const sig = parts[1].search(/[1-9]/);
|
|
if (sig === -1) return truncated;
|
|
return parts[0] + "." + parts[1].slice(0, sig + 1);
|
|
}
|
|
|
|
module.exports = { truncateAmount, truncateAmountNeverZero };
|