// Send view: collect To, Amount, Token. Then go to confirmation. const { $, showFlash, formatAddressHtml } = require("./helpers"); const { state, currentAddress } = require("../../shared/state"); let ctx; const { getProvider } = require("../../shared/balances"); const { KNOWN_SYMBOLS } = require("../../shared/tokens"); function isSpoofedToken(t) { const upper = (t.symbol || "").toUpperCase(); if (!KNOWN_SYMBOLS.has(upper)) return false; const legit = KNOWN_SYMBOLS.get(upper); if (legit === null) return true; return t.address.toLowerCase() !== legit; } function renderSendTokenSelect(addr) { const sel = $("send-token"); sel.innerHTML = ''; const fraudSet = new Set( (state.fraudContracts || []).map((a) => a.toLowerCase()), ); for (const t of addr.tokenBalances || []) { if (isSpoofedToken(t)) continue; if (fraudSet.has(t.address.toLowerCase())) continue; if (state.hideLowHolderTokens && (t.holders || 0) < 1000) continue; const opt = document.createElement("option"); opt.value = t.address; opt.textContent = t.symbol; sel.appendChild(opt); } } function updateSendBalance() { const addr = currentAddress(); if (!addr) return; $("send-from").innerHTML = formatAddressHtml( addr.address, addr.ensName || null, null, ); const token = $("send-token").value; if (token === "ETH") { $("send-balance").textContent = "Current balance: " + (addr.balance || "0") + " ETH"; } else { const tb = (addr.tokenBalances || []).find( (t) => t.address.toLowerCase() === token.toLowerCase(), ); const symbol = tb ? tb.symbol : "?"; const bal = tb ? tb.balance || "0" : "0"; $("send-balance").textContent = "Current balance: " + bal + " " + symbol; } } function init(_ctx) { ctx = _ctx; $("send-token").addEventListener("change", updateSendBalance); $("btn-send-review").addEventListener("click", async () => { const to = $("send-to").value.trim(); const amount = $("send-amount").value.trim(); if (!to) { showFlash("Please enter a recipient address."); return; } if (!amount || isNaN(parseFloat(amount)) || parseFloat(amount) <= 0) { showFlash("Please enter a valid amount."); return; } // Resolve ENS if needed let resolvedTo = to; let ensName = null; if (to.includes(".") && !to.startsWith("0x")) { try { const provider = getProvider(state.rpcUrl); const resolved = await provider.resolveName(to); if (!resolved) { showFlash("Could not resolve " + to); return; } resolvedTo = resolved; ensName = to; } catch (e) { showFlash("Failed to resolve ENS name."); return; } } const token = $("send-token").value; const addr = currentAddress(); ctx.showConfirmTx({ from: addr.address, to: resolvedTo, ensName: ensName, amount: amount, token: token, balance: addr.balance, }); }); $("btn-send-back").addEventListener("click", () => { $("send-token").disabled = false; if (state.selectedToken) { ctx.showAddressToken(); } else { ctx.showAddressDetail(); } }); } module.exports = { init, updateSendBalance, renderSendTokenSelect };