// Shared DOM helpers used by all views. const { DEBUG } = require("../../shared/constants"); const { formatUsd, getPrice, getAddressValueUsd, } = require("../../shared/prices"); const VIEWS = [ "welcome", "add-wallet", "import-key", "main", "address", "address-token", "send", "confirm-tx", "receive", "add-token", "settings", "transaction", "approve-site", "approve-tx", ]; function $(id) { return document.getElementById(id); } function showError(id, msg) { const el = $(id); el.textContent = msg; el.classList.remove("hidden"); } function hideError(id) { $(id).classList.add("hidden"); } function showView(name) { for (const v of VIEWS) { const el = document.getElementById(`view-${v}`); if (el) { el.classList.toggle("hidden", v !== name); } } clearFlash(); if (DEBUG) { const banner = document.getElementById("debug-banner"); if (banner) { banner.textContent = "DEBUG / INSECURE (" + name + ")"; } } } let flashTimer = null; function clearFlash() { if (flashTimer) { clearTimeout(flashTimer); flashTimer = null; } $("flash-msg").textContent = ""; } function showFlash(msg, duration = 2000) { clearFlash(); $("flash-msg").textContent = msg; flashTimer = setTimeout(() => { $("flash-msg").textContent = ""; flashTimer = null; }, duration); } function balanceLine(symbol, amount, price, tokenId) { const qty = amount.toFixed(4); const usd = price ? formatUsd(amount * price) : ""; const tokenAttr = tokenId ? ` data-token="${tokenId}"` : ""; const clickClass = tokenId ? " cursor-pointer hover:bg-hover balance-row" : ""; return ( `
` + `` + `${symbol}` + `${qty}` + `` + `${usd}` + `
` ); } function balanceLinesForAddress(addr, trackedTokens, showZero) { let html = balanceLine( "ETH", parseFloat(addr.balance || "0"), getPrice("ETH"), "ETH", ); const seen = new Set(); for (const t of addr.tokenBalances || []) { const bal = parseFloat(t.balance || "0"); if (bal === 0 && !showZero) continue; html += balanceLine( t.symbol, bal, getPrice(t.symbol), t.address.toLowerCase(), ); seen.add(t.address.toLowerCase()); } if (showZero && trackedTokens) { for (const t of trackedTokens) { if (seen.has(t.address.toLowerCase())) continue; html += balanceLine( t.symbol, 0, getPrice(t.symbol), t.address.toLowerCase(), ); } } return html; } function truncateMiddle(str, maxLen) { if (str.length <= maxLen) return str; if (maxLen < 5) return str.slice(0, maxLen); const half = Math.floor((maxLen - 1) / 2); return str.slice(0, half) + "\u2026" + str.slice(-(maxLen - 1 - half)); } // 16 colors evenly spaced around the hue wheel (22.5° apart), // all at HSL saturation 70%, lightness 50% for uniform vibrancy. const ADDRESS_COLORS = [ "#d92626", "#d96926", "#d9ac26", "#c2d926", "#80d926", "#3dd926", "#26d953", "#26d996", "#26d9d9", "#2696d9", "#2653d9", "#3d26d9", "#8026d9", "#c226d9", "#d926ac", "#d92669", ]; function addressColor(address) { const idx = parseInt(address.slice(2, 6), 16) % 16; return ADDRESS_COLORS[idx]; } function addressDotHtml(address) { const color = addressColor(address); return ``; } function escapeHtml(s) { const div = document.createElement("div"); div.textContent = s; return div.innerHTML; } // Look up an address across all wallets and return its title // (e.g. "Address 1.2") or null if it's not one of ours. function addressTitle(address, wallets) { const lower = address.toLowerCase(); for (let wi = 0; wi < wallets.length; wi++) { const addrs = wallets[wi].addresses; for (let ai = 0; ai < addrs.length; ai++) { if (addrs[ai].address.toLowerCase() === lower) { return wallets[wi].name + " \u2014 Address " + (ai + 1); } } } return null; } // Render an address with color dot, optional ENS name, optional title, // and optional truncation. Title and ENS are shown as bold labels above // the full address. function formatAddressHtml(address, ensName, maxLen, title) { const dot = addressDotHtml(address); const displayAddr = maxLen ? truncateMiddle(address, maxLen) : address; if (title || ensName) { let html = ""; if (title) { html += `
${dot}${escapeHtml(title)}
`; } if (ensName) { html += `
${title ? "" : dot}${escapeHtml(ensName)}
`; } html += `
${escapeHtml(displayAddr)}
`; return html; } return `
${dot}${escapeHtml(displayAddr)}
`; } module.exports = { $, showError, hideError, showView, showFlash, balanceLine, balanceLinesForAddress, addressColor, addressDotHtml, escapeHtml, addressTitle, formatAddressHtml, truncateMiddle, };