const { $, showView, showFlash, flashCopyFeedback, balanceLinesForAddress, isoDate, timeAgo, addressDotHtml, addressTitle, escapeHtml, truncateMiddle, renderAddressHtml, attachCopyHandlers, pushCurrentView, } = require("./helpers"); const { state, saveState, currentAddress } = require("../../shared/state"); const { updateSendBalance, renderSendTokenSelect, resetSendValidation, } = require("./send"); const { deriveAddressFromXpub } = require("../../shared/wallet"); const { canRemoveAddress } = require("../../shared/walletDelete"); const { walletDefect, walletDefectHtml, } = require("../../shared/walletDefects"); const { formatUsd, getPrice, getAddressValueUsd, } = require("../../shared/prices"); const { fetchRecentTransactions, filterTransactions, } = require("../../shared/transactions"); const { log } = require("../../shared/log"); function findActiveAddr() { for (const w of state.wallets) { for (const a of w.addresses) { if (a.address === state.activeAddress) return a; } } return null; } function renderTotalValue() { const el = $("total-value"); const subEl = $("total-value-sub"); const priceEl = $("eth-price-display"); if (!el) return; const ethPrice = getPrice("ETH"); if (priceEl) { priceEl.innerHTML = ethPrice ? formatUsd(ethPrice) + " USD/ETH" : " "; } const addr = findActiveAddr(); if (!addr) { el.innerHTML = " "; if (subEl) subEl.innerHTML = " "; return; } const ethBal = parseFloat(addr.balance || "0"); const ethStr = ethBal.toFixed(4) + " ETH"; const ethUsd = ethPrice ? " (" + formatUsd(ethBal * ethPrice) + ")" : ""; el.textContent = ethStr + ethUsd; if (subEl) { const totalUsd = getAddressValueUsd(addr); subEl.innerHTML = totalUsd !== null ? "Total: " + formatUsd(totalUsd) : " "; } } function renderActiveAddress() { const el = $("active-address-display"); if (!el) return; if (state.activeAddress) { el.innerHTML = renderAddressHtml(state.activeAddress); attachCopyHandlers(el); } else { el.textContent = ""; } } let homeTxs = []; function renderHomeTxList(ctx) { const list = $("home-tx-list"); if (!list) return; if (homeTxs.length === 0) { list.innerHTML = '
No wallets yet. Add one to get started.
'; renderTotalValue(); renderActiveAddress(); return; } container.innerHTML = walletListHtml(); container.querySelectorAll(".address-row").forEach((row) => { row.addEventListener("click", async () => { const wi = parseInt(row.dataset.wallet, 10); const ai = parseInt(row.dataset.address, 10); const addr = state.wallets[wi].addresses[ai].address; if (state.activeAddress !== addr) { state.activeAddress = addr; await saveState(); render(ctx); const runtime = typeof browser !== "undefined" ? browser.runtime : chrome.runtime; runtime.sendMessage({ type: "AUTISTMASK_ACTIVE_CHANGED" }); } }); }); container.querySelectorAll(".btn-addr-info").forEach((btn) => { btn.addEventListener("click", (e) => { e.stopPropagation(); state.selectedWallet = parseInt(btn.dataset.wallet, 10); state.selectedAddress = parseInt(btn.dataset.address, 10); ctx.showAddressDetail(); }); }); container.querySelectorAll(".btn-remove-address").forEach((btn) => { btn.addEventListener("click", (e) => { e.stopPropagation(); ctx.showDeleteAddress( parseInt(btn.dataset.wallet, 10), parseInt(btn.dataset.address, 10), ); }); }); container.querySelectorAll(".btn-add-address").forEach((btn) => { btn.addEventListener("click", async (e) => { e.stopPropagation(); const wi = parseInt(btn.dataset.wallet, 10); const wallet = state.wallets[wi]; const newAddr = deriveAddressFromXpub( wallet.xpub, wallet.nextIndex, ); wallet.addresses.push({ address: newAddr, balance: "0.0000", tokenBalances: [], }); wallet.nextIndex++; await saveState(); render(ctx); ctx.doRefreshAndRender(); }); }); container.querySelectorAll(".wallet-name").forEach((span) => { span.addEventListener("click", (e) => { e.stopPropagation(); const wi = parseInt(span.dataset.wallet, 10); const wallet = state.wallets[wi]; const input = document.createElement("input"); input.type = "text"; input.value = wallet.name; input.className = "font-bold border border-border p-0 bg-bg text-fg"; input.style.width = "100%"; const save = async () => { const val = input.value.trim(); if (val && val !== wallet.name) { wallet.name = val; await saveState(); } render(ctx); }; input.addEventListener("blur", save); input.addEventListener("keydown", (ev) => { if (ev.key === "Enter") input.blur(); if (ev.key === "Escape") { input.value = wallet.name; input.blur(); } }); span.replaceWith(input); input.focus(); input.select(); }); }); renderTotalValue(); renderActiveAddress(); loadHomeTxs(ctx); } // The defect of the wallet the selected address belongs to, or null. Call // after selectActiveAddress(). function selectedWalletDefect() { if (state.selectedWallet === null) return null; return walletDefect(state.wallets[state.selectedWallet]); } function selectActiveAddress() { for (let wi = 0; wi < state.wallets.length; wi++) { for (let ai = 0; ai < state.wallets[wi].addresses.length; ai++) { if ( state.wallets[wi].addresses[ai].address === state.activeAddress ) { state.selectedWallet = wi; state.selectedAddress = ai; return true; } } } return false; } function init(ctx) { $("btn-add-wallet-bottom").addEventListener("click", ctx.showAddWalletView); $("btn-main-send").addEventListener("click", () => { if (!selectActiveAddress()) { showFlash("No active address selected."); return; } // Before the balance check and before any password is asked for: this // wallet cannot sign at all, so the send screen is a dead end. const defect = selectedWalletDefect(); if (defect) { showFlash(defect.shortMessage); return; } const addr = currentAddress(); if (!addr.balance || parseFloat(addr.balance) === 0) { showFlash("Cannot send \u2014 zero balance."); return; } $("send-to").value = ""; $("send-amount").value = ""; $("send-token").classList.remove("hidden"); $("send-token-static").classList.add("hidden"); renderSendTokenSelect(addr); updateSendBalance(); resetSendValidation(); pushCurrentView(); showView("send"); }); $("btn-main-receive").addEventListener("click", () => { if (!selectActiveAddress()) { showFlash("No active address selected."); return; } ctx.showReceive(); }); } module.exports = { init, render, walletListHtml };