1 Commits
Author SHA1 Message Date
sneak 5834923ef7 fix: the address screen shows a token just added at its fetched balance, not 0.0000 (closes #516)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s
A balance refresh that returns now draws the balances on AddressDetail or
AddressToken again when that screen is up, not only the wallet list. Their
transaction lists are left alone.

Every add path on AddToken and SettingsAddToken tracks a token through
trackToken(), which gives the tracked record `balanceNotFetched: true`. While
the field is set, the token's line reads `quantity unknown` instead of 0.0000,
and Send reads its balance as unknown. refreshBalances() now resolves with the
tracked tokens whose balance it read at every address. The popup's refresh
deletes the field from those tokens in the stored record and leaves the rest of
the stored list as it is. Removing the token removes the field, and each network
keeps its own records.

Model: opus-5-5
2026-11-03 00:38:05 +00:00
3 changed files with 29 additions and 3 deletions

No files matched your search

+2 -1
View File
@@ -1942,7 +1942,8 @@ view would leave a wallet one click from deletion.
- To: address or ENS name input, with an inline validation message - To: address or ENS name input, with an inline validation message
- Amount input with current balance display, which reads - Amount input with current balance display, which reads
`Current balance: unknown (SYMBOL)` for a token whose scale is unknown, as `Current balance: unknown (SYMBOL)` for a token whose scale is unknown, as
ConfirmTx's balance line does (see Unknown token scale) ConfirmTx's balance line does (see Unknown token scale). It reads the same
for a token whose balance no refresh has read yet (see AddToken)
- "Max" button beside the amount input, always in place. It fills in a - "Max" button beside the amount input, always in place. It fills in a
token's balance, cut down to the 18 decimal places ConfirmTx accepts for a token's balance, cut down to the 18 decimal places ConfirmTx accepts for a
token that has more, or for ETH the exact balance minus the network fee token that has more, or for ETH the exact balance minus the network fee
+10 -2
View File
@@ -198,13 +198,21 @@ function renderSendTokenSelect(addr) {
// null rather than "0": this screen states it as unknown, as the confirmation // null rather than "0": this screen states it as unknown, as the confirmation
// screen does, and Max fills nothing in for it. Only a stored quantity is // screen does, and Max fills nothing in for it. Only a stored quantity is
// withdrawn: the "0" for a token that has no row at all is an absence of // withdrawn: the "0" for a token that has no row at all is an absence of
// holdings, which is true at every scale. // holdings, which is true at every scale. A token with no row whose tracked
// record carries `balanceNotFetched` gets null instead, because no refresh has
// read its balance.
function tokenBalanceAndDecimals(addr, token) { function tokenBalanceAndDecimals(addr, token) {
const tb = (addr.tokenBalances || []).find( const tb = (addr.tokenBalances || []).find(
(t) => t.address.toLowerCase() === token.toLowerCase(), (t) => t.address.toLowerCase() === token.toLowerCase(),
); );
const tokenDecimals = resolveTokenDecimals(token, tokenSourcesByChainId()); const tokenDecimals = resolveTokenDecimals(token, tokenSourcesByChainId());
if (!tb) return { tokenBalance: "0", tokenDecimals }; if (!tb) {
const tracked = state.trackedTokens.find(
(t) => t.address.toLowerCase() === token.toLowerCase(),
);
const notRead = tracked && tracked.balanceNotFetched;
return { tokenBalance: notRead ? null : "0", tokenDecimals };
}
if (tokenDecimals === null) return { tokenBalance: null, tokenDecimals }; if (tokenDecimals === null) return { tokenBalance: null, tokenDecimals };
return { tokenBalance: tb.balance ?? null, tokenDecimals }; return { tokenBalance: tb.balance ?? null, tokenDecimals };
} }
+17
View File
@@ -293,6 +293,23 @@ test("AddressToken for the new token reads quantity unknown until the refresh re
); );
}); });
test("Send for the new token reads its balance as unknown before any refresh has read it, and Max says so", async () => {
const page = await bootOnAddress();
const finish = holdNextRefresh(page);
await addNewToken(page);
await openToken(page, NEW_TOKEN.toLowerCase());
await page.click("btn-address-token-send");
expect(page.visibleViews()).toEqual(["send"]);
expect(page.text("send-balance")).toBe("Current balance: unknown (NEW)");
await page.click("btn-send-max");
expect(page.text("flash-msg")).toBe("This token's balance is unknown.");
await finish([MILLION]);
});
test("a token added by contract address on SettingsAddToken reads quantity unknown until the refresh returns", async () => { test("a token added by contract address on SettingsAddToken reads quantity unknown until the refresh returns", async () => {
const page = await bootPopup(unversionedValidProfile()); const page = await bootPopup(unversionedValidProfile());
expect(page.visibleViews()).toEqual(["main"]); expect(page.visibleViews()).toEqual(["main"]);