Files
AutistMask/src/shared/prices.js
clawbot a138a36710
All checks were successful
check / check (push) Successful in 24s
fix: suppress USD display on testnet networks (#142)
## Summary

Fixes USD prices still showing on the main view when connected to a testnet (e.g. Sepolia). The root cause was stale mainnet prices lingering in the in-memory price cache after switching networks.

### Root Cause

PR #137 correctly made `refreshPrices()` skip fetching on testnets, but the cached prices from a prior mainnet session remained in the `prices` object. All display functions (`getPrice()`, `getAddressValueUsd()`, etc.) used whatever was cached without checking which network was active.

### Changes

- **`src/shared/prices.js`**
  - `refreshPrices()` now clears the price cache when on a testnet instead of silently returning
  - New `clearPrices()` function empties the cache and resets the fetch timestamp
  - `getPrice()` returns null on testnets (defense-in-depth)
  - `getAddressValueUsd()`, `getWalletValueUsd()`, `getTotalValueUsd()` return null on testnets

- **`src/popup/views/settings.js`**
  - Network switcher immediately clears prices when switching to a testnet, so the UI updates without waiting for the next refresh cycle

closes #139

Co-authored-by: clawbot <clawbot@noreply.git.eeqj.de>
Reviewed-on: #142
Co-authored-by: clawbot <clawbot@noreply.example.org>
Co-committed-by: clawbot <clawbot@noreply.example.org>
2026-03-01 20:31:45 +01:00

106 lines
2.9 KiB
JavaScript

// Price fetching with 5-minute cache, USD formatting, value aggregation.
const { getTopTokenPrices } = require("./tokenList");
const PRICE_CACHE_TTL = 300000; // 5 minutes
const prices = {};
let lastFetchedAt = 0;
async function refreshPrices() {
// 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");
if (currentNetwork().isTestnet) {
clearPrices();
return;
}
const now = Date.now();
if (now - lastFetchedAt < PRICE_CACHE_TTL) return;
try {
const fetched = await getTopTokenPrices(25);
Object.assign(prices, fetched);
lastFetchedAt = now;
} catch (e) {
// prices stay stale on error
}
}
// Clear all cached prices and reset the fetch timestamp so the
// next refreshPrices() call will fetch fresh data.
function clearPrices() {
for (const key of Object.keys(prices)) {
delete prices[key];
}
lastFetchedAt = 0;
}
// Return the USD price for a symbol, or null on testnet / unknown.
function getPrice(symbol) {
const { currentNetwork } = require("./state");
if (currentNetwork().isTestnet) return null;
return prices[symbol] || null;
}
function formatUsd(amount) {
if (amount === null || amount === undefined || isNaN(amount)) return "";
if (amount === 0) return "$0.00";
if (amount < 0.01) return "< $0.01";
return (
"$" +
amount.toLocaleString("en-US", {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
})
);
}
function getAddressValueUsd(addr) {
const { currentNetwork } = require("./state");
if (currentNetwork().isTestnet) return null;
if (!prices.ETH) return null;
let total = 0;
const ethBal = parseFloat(addr.balance || "0");
total += ethBal * prices.ETH;
for (const token of addr.tokenBalances || []) {
const tokenBal = parseFloat(token.balance || "0");
if (tokenBal > 0 && prices[token.symbol]) {
total += tokenBal * prices[token.symbol];
}
}
return total;
}
function getWalletValueUsd(wallet) {
const { currentNetwork } = require("./state");
if (currentNetwork().isTestnet) return null;
if (!prices.ETH) return null;
let total = 0;
for (const addr of wallet.addresses) {
total += getAddressValueUsd(addr);
}
return total;
}
function getTotalValueUsd(wallets) {
const { currentNetwork } = require("./state");
if (currentNetwork().isTestnet) return null;
if (!prices.ETH) return null;
let total = 0;
for (const wallet of wallets) {
total += getWalletValueUsd(wallet);
}
return total;
}
module.exports = {
prices,
refreshPrices,
clearPrices,
getPrice,
formatUsd,
getAddressValueUsd,
getWalletValueUsd,
getTotalValueUsd,
};