Refactor popup into shared modules, wire up real ERC-20 tokens
All checks were successful
check / check (push) Successful in 13s
All checks were successful
check / check (push) Successful in 13s
Split popup/index.js (784 lines) into focused modules: - shared/state.js: state management, storage persistence - shared/wallet.js: mnemonic gen, HD derivation, signing - shared/prices.js: price cache (5min TTL), USD formatting, value aggregation (address → wallet → total) - shared/balances.js: ETH + ERC-20 balance cache (60s TTL), ENS lookup, token contract metadata lookup - shared/vault.js: unchanged (libsodium encryption) - shared/tokens.js: unchanged (token list + CoinDesk client) - popup/index.js: view switching and event wiring only Token tracking is now app-wide: trackedTokens stored in state, balances fetched for all tracked tokens across all addresses. Add Token now calls the real contract to read name/symbol/decimals. Total portfolio value shown in 2x type on Home screen.
This commit is contained in:
79
src/shared/prices.js
Normal file
79
src/shared/prices.js
Normal file
@@ -0,0 +1,79 @@
|
||||
// Price fetching with 5-minute cache, USD formatting, value aggregation.
|
||||
|
||||
const { getTopTokenPrices } = require("./tokens");
|
||||
|
||||
const PRICE_CACHE_TTL = 300000; // 5 minutes
|
||||
|
||||
const prices = {};
|
||||
let lastFetchedAt = 0;
|
||||
|
||||
async function refreshPrices() {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
function getPrice(symbol) {
|
||||
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) {
|
||||
let total = 0;
|
||||
const ethBal = parseFloat(addr.balance || "0");
|
||||
const ethPrice = prices.ETH;
|
||||
if (ethPrice) {
|
||||
total += ethBal * ethPrice;
|
||||
}
|
||||
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) {
|
||||
let total = 0;
|
||||
for (const addr of wallet.addresses) {
|
||||
total += getAddressValueUsd(addr);
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
function getTotalValueUsd(wallets) {
|
||||
let total = 0;
|
||||
for (const wallet of wallets) {
|
||||
total += getWalletValueUsd(wallet);
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
prices,
|
||||
refreshPrices,
|
||||
getPrice,
|
||||
formatUsd,
|
||||
getAddressValueUsd,
|
||||
getWalletValueUsd,
|
||||
getTotalValueUsd,
|
||||
};
|
||||
Reference in New Issue
Block a user