Compare commits

...

2 Commits

Author SHA1 Message Date
user
8c805537c0 fix: use null instead of 0 for testnet token USD fallback
All checks were successful
check / check (push) Successful in 12s
When price is null (testnet), the fallback value 0 caused formatUsd()
to display "$0.00" instead of hiding the USD value. Using null makes
formatUsd() return an empty string, so the UI correctly shows no USD
on the token detail view.
2026-03-01 11:18:04 -08:00
user
57de01b546 fix: suppress USD display on testnet networks
All checks were successful
check / check (push) Successful in 13s
When connected to a testnet (e.g. Sepolia), stale mainnet prices from
the in-memory cache caused USD values to display even though
refreshPrices() correctly skipped fetching. Three fixes applied:

- refreshPrices() now clears the price cache when on a testnet instead
  of silently returning, removing any stale mainnet prices
- getPrice(), getAddressValueUsd(), getWalletValueUsd(), and
  getTotalValueUsd() all return null when the current network is a
  testnet, as defense-in-depth
- The settings network switcher immediately clears prices when
  switching to a testnet, so the UI updates without waiting for the
  next refresh cycle

closes #139
2026-03-01 11:14:39 -08:00
3 changed files with 25 additions and 3 deletions

View File

@@ -161,7 +161,7 @@ function show() {
`<a href="${addrLink}" target="_blank" rel="noopener" class="inline-flex items-center">${EXT_ICON}</a>`; `<a href="${addrLink}" target="_blank" rel="noopener" class="inline-flex items-center">${EXT_ICON}</a>`;
// USD total for this token only // USD total for this token only
const usdVal = price ? amount * price : 0; const usdVal = price ? amount * price : null;
const usdStr = formatUsd(usdVal); const usdStr = formatUsd(usdVal);
$("address-token-usd-total").innerHTML = usdStr || "&nbsp;"; $("address-token-usd-total").innerHTML = usdStr || "&nbsp;";

View File

@@ -2,6 +2,7 @@ const { $, showView, showFlash, escapeHtml } = require("./helpers");
const { applyTheme } = require("../theme"); const { applyTheme } = require("../theme");
const { state, saveState, currentNetwork } = require("../../shared/state"); const { state, saveState, currentNetwork } = require("../../shared/state");
const { NETWORKS, SUPPORTED_CHAIN_IDS } = require("../../shared/networks"); const { NETWORKS, SUPPORTED_CHAIN_IDS } = require("../../shared/networks");
const { clearPrices } = require("../../shared/prices");
const { log, debugFetch } = require("../../shared/log"); const { log, debugFetch } = require("../../shared/log");
const deleteWallet = require("./deleteWallet"); const deleteWallet = require("./deleteWallet");
@@ -227,6 +228,7 @@ function init(ctx) {
state.blockscoutUrl = net.defaultBlockscoutUrl; state.blockscoutUrl = net.defaultBlockscoutUrl;
$("settings-rpc").value = state.rpcUrl; $("settings-rpc").value = state.rpcUrl;
$("settings-blockscout").value = state.blockscoutUrl; $("settings-blockscout").value = state.blockscoutUrl;
if (net.isTestnet) clearPrices();
await saveState(); await saveState();
showFlash("Switched to " + net.name + "."); showFlash("Switched to " + net.name + ".");
}); });

View File

@@ -8,9 +8,13 @@ const prices = {};
let lastFetchedAt = 0; let lastFetchedAt = 0;
async function refreshPrices() { async function refreshPrices() {
// Testnet tokens have no real market value — skip price fetching. // Testnet tokens have no real market value — skip price fetching
// and clear any stale mainnet prices so the UI shows no USD values.
const { currentNetwork } = require("./state"); const { currentNetwork } = require("./state");
if (currentNetwork().isTestnet) return; if (currentNetwork().isTestnet) {
clearPrices();
return;
}
const now = Date.now(); const now = Date.now();
if (now - lastFetchedAt < PRICE_CACHE_TTL) return; if (now - lastFetchedAt < PRICE_CACHE_TTL) return;
try { try {
@@ -22,7 +26,16 @@ async function refreshPrices() {
} }
} }
function clearPrices() {
for (const key of Object.keys(prices)) {
delete prices[key];
}
lastFetchedAt = 0;
}
function getPrice(symbol) { function getPrice(symbol) {
const { currentNetwork } = require("./state");
if (currentNetwork().isTestnet) return null;
return prices[symbol] || null; return prices[symbol] || null;
} }
@@ -40,6 +53,8 @@ function formatUsd(amount) {
} }
function getAddressValueUsd(addr) { function getAddressValueUsd(addr) {
const { currentNetwork } = require("./state");
if (currentNetwork().isTestnet) return null;
if (!prices.ETH) return null; if (!prices.ETH) return null;
let total = 0; let total = 0;
const ethBal = parseFloat(addr.balance || "0"); const ethBal = parseFloat(addr.balance || "0");
@@ -54,6 +69,8 @@ function getAddressValueUsd(addr) {
} }
function getWalletValueUsd(wallet) { function getWalletValueUsd(wallet) {
const { currentNetwork } = require("./state");
if (currentNetwork().isTestnet) return null;
if (!prices.ETH) return null; if (!prices.ETH) return null;
let total = 0; let total = 0;
for (const addr of wallet.addresses) { for (const addr of wallet.addresses) {
@@ -63,6 +80,8 @@ function getWalletValueUsd(wallet) {
} }
function getTotalValueUsd(wallets) { function getTotalValueUsd(wallets) {
const { currentNetwork } = require("./state");
if (currentNetwork().isTestnet) return null;
if (!prices.ETH) return null; if (!prices.ETH) return null;
let total = 0; let total = 0;
for (const wallet of wallets) { for (const wallet of wallets) {
@@ -74,6 +93,7 @@ function getTotalValueUsd(wallets) {
module.exports = { module.exports = {
prices, prices,
refreshPrices, refreshPrices,
clearPrices,
getPrice, getPrice,
formatUsd, formatUsd,
getAddressValueUsd, getAddressValueUsd,