diff --git a/src/popup/index.html b/src/popup/index.html
index 7361124..15bc326 100644
--- a/src/popup/index.html
+++ b/src/popup/index.html
@@ -173,6 +173,9 @@
+
+
+
diff --git a/src/popup/index.js b/src/popup/index.js
index 5ee60c7..5458ae2 100644
--- a/src/popup/index.js
+++ b/src/popup/index.js
@@ -129,16 +129,27 @@ function addressFromPrivateKey(key) {
return w.address;
}
-// -- price fetching --
+// -- caching layer --
+const PRICE_CACHE_TTL = 300000; // 5 minutes
+const BALANCE_CACHE_TTL = 60000; // 60 seconds
+
+const cache = {
+ prices: { data: {}, fetchedAt: 0 },
+ balances: { fetchedAt: 0 },
+};
+
// { "ETH": 1234.56, "LINK": 8.60, ... }
const prices = {};
async function refreshPrices() {
+ const now = Date.now();
+ if (now - cache.prices.fetchedAt < PRICE_CACHE_TTL) return;
try {
const fetched = await getTopTokenPrices(25);
Object.assign(prices, fetched);
+ cache.prices.fetchedAt = now;
} catch (e) {
- // prices stay empty on error
+ // prices stay stale on error
}
}
@@ -187,11 +198,12 @@ function formatBalance(wei) {
}
async function refreshBalances() {
+ const now = Date.now();
+ if (now - cache.balances.fetchedAt < BALANCE_CACHE_TTL) return;
const provider = getProvider();
const updates = [];
for (const wallet of state.wallets) {
for (const addr of wallet.addresses) {
- // Fetch ETH balance
updates.push(
provider
.getBalance(addr.address)
@@ -200,7 +212,6 @@ async function refreshBalances() {
})
.catch(() => {}),
);
- // Reverse ENS lookup
updates.push(
provider
.lookupAddress(addr.address)
@@ -214,15 +225,54 @@ async function refreshBalances() {
}
}
await Promise.all(updates);
+ cache.balances.fetchedAt = now;
await saveState();
}
+function getAddressValueUsd(addr) {
+ let total = 0;
+ const ethBal = parseFloat(addr.balance || "0");
+ if (prices.ETH) {
+ total += ethBal * prices.ETH;
+ }
+ for (const token of addr.tokens || []) {
+ const tokenBal = parseFloat(token.balance || "0");
+ if (tokenBal > 0 && prices[token.symbol]) {
+ total += tokenBal * prices[token.symbol];
+ }
+ }
+ return total;
+}
+
+function getWalletValueUsd(wallet) {
+ let total = 0;
+ for (const addr of wallet.addresses) {
+ total += getAddressValueUsd(addr);
+ }
+ return total;
+}
+
+function getTotalValueUsd() {
+ let total = 0;
+ for (const wallet of state.wallets) {
+ total += getWalletValueUsd(wallet);
+ }
+ return total;
+}
+
+function renderTotalValue() {
+ const el = $("total-value");
+ if (!el) return;
+ el.textContent = formatUsd(getTotalValueUsd());
+}
+
// -- render wallet list on main view --
function renderWalletList() {
const container = $("wallet-list");
if (state.wallets.length === 0) {
container.innerHTML =
'
No wallets yet. Add one to get started.
';
+ renderTotalValue();
return;
}
@@ -244,12 +294,8 @@ function renderWalletList() {
html += `
${addr.address}
`;
html += `
`;
html += `${addr.balance} ETH`;
- const ethUsd = prices.ETH
- ? parseFloat(addr.balance) * prices.ETH
- : null;
- if (ethUsd !== null) {
- html += `${formatUsd(ethUsd)}`;
- }
+ const addrUsd = getAddressValueUsd(addr);
+ html += `${formatUsd(addrUsd)}`;
html += `
`;
html += `
`;
});
@@ -285,6 +331,8 @@ function renderWalletList() {
renderWalletList();
});
});
+
+ renderTotalValue();
}
function showAddressDetail() {
@@ -294,9 +342,7 @@ function showAddressDetail() {
$("address-full").textContent = addr.address;
$("address-copied-msg").textContent = "";
$("address-eth-balance").textContent = addr.balance;
- const ethUsd = prices.ETH ? parseFloat(addr.balance) * prices.ETH : null;
- $("address-usd-value").textContent =
- ethUsd !== null ? formatUsd(ethUsd) : "";
+ $("address-usd-value").textContent = formatUsd(getAddressValueUsd(addr));
const ensEl = $("address-ens");
if (addr.ensName) {
ensEl.textContent = addr.ensName;