fix: the ETH line reads unknown at an address no refresh has read (closes #736)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run

An address's ETH balance is now null until a refresh has read it. That covers
a new address, a new wallet, addresses a wallet scan finds, and every address
after a network switch.

Its line reads `quantity unknown`, Home's balance `unknown (ETH)`, and Send
`Current balance: unknown (ETH)`. Max says the balance is unknown. Send is no
longer refused as zero. The address has no total, and DeleteAddress warns that
it may hold a balance.

A refresh also deletes `balanceNotFetched` only when it read every address in
the stored record.

Model: opus-5-5
This commit was merged in pull request #741.
This commit is contained in:
2026-11-03 11:24:18 +01:00
parent 448afdb5ce
commit 9c691dfa6b
21 changed files with 470 additions and 67 deletions
+2 -2
View File
@@ -49,7 +49,7 @@ function clearPopupCaches() {
// follow runs first, and this switch is made after it.
//
// The save writes only the fields that differ from what this page last saved.
// When this page last saved a balance of "0", clearing that balance is no
// When this page last saved a balance of null, clearing that balance is no
// change. So the switch also resets these fields in the stored record:
//
// - every address's balance and token balances;
@@ -100,7 +100,7 @@ async function onChainSwitch(newNetworkId) {
stored.fraudContracts = [];
for (const wallet of stored.wallets) {
for (const addr of wallet.addresses) {
addr.balance = "0";
addr.balance = null;
addr.tokenBalances = [];
}
}
+4 -3
View File
@@ -68,10 +68,11 @@ function applyChainSwitchFields(s, newNetworkId) {
// Clear per-address balances and token balances so stale data
// from the previous chain is never displayed while the first
// refresh on the new chain is in flight.
// refresh on the new chain is in flight. A balance of null is one no
// refresh has read: it reads as unknown until one has, not as 0.0000.
for (const wallet of s.wallets || []) {
for (const addr of wallet.addresses || []) {
addr.balance = "0";
addr.balance = null;
addr.tokenBalances = [];
}
}
@@ -108,7 +109,7 @@ function copyChainSwitchFields(s, switched) {
for (const wallet of s.wallets) {
for (const addr of wallet.addresses) {
const got = stored.get(addr.address);
addr.balance = got ? got.balance : "0";
addr.balance = got ? got.balance : null;
addr.tokenBalances = got ? got.tokenBalances : [];
}
}
+4 -2
View File
@@ -146,7 +146,8 @@ function formatUsd(amount) {
// way an absent holders_count is not a count of zero.
//
// usd: the value of the holdings a price is known for, or null when
// nothing is knowable at all — testnet, or before the first fetch.
// no total can be stated — testnet, before the first fetch, or an
// ETH balance no refresh has read.
// partial: the address also holds a token with no price, so usd is a floor
// and not the total.
//
@@ -155,7 +156,8 @@ function getAddressValue(addr) {
const { currentNetwork } = require("./state");
if (currentNetwork().isTestnet) return { usd: null, partial: false };
if (!prices.ETH) return { usd: null, partial: false };
let usd = parseFloat(addr.balance || "0") * prices.ETH;
if (addr.balance == null) return { usd: null, partial: false };
let usd = parseFloat(addr.balance) * prices.ETH;
let partial = false;
for (const token of addr.tokenBalances || []) {
// A holding below 0.000001 is left out, as the balance lists leave it