// Post-broadcast transaction status views: wait, success, error. const { $, showView, addressTitle, escapeHtml, renderAddressHtml, attachCopyHandlers, copyableHtml, etherscanLinkHtml, } = require("./helpers"); const { TOKEN_BY_ADDRESS } = require("../../shared/tokenList"); const { state, saveState, currentNetwork } = require("../../shared/state"); const { getProvider } = require("../../shared/balances"); const { log } = require("../../shared/log"); let ctx; let elapsedTimer = null; let pollTimer = null; function clearTimers() { if (elapsedTimer) { clearInterval(elapsedTimer); elapsedTimer = null; } if (pollTimer) { clearInterval(pollTimer); pollTimer = null; } } function toAddressHtml(address) { const title = addressTitle(address, state.wallets); return renderAddressHtml(address, { title }); } function txHashHtml(hash) { const link = `${currentNetwork().explorerUrl}/tx/${hash}`; return copyableHtml(hash, "break-all") + etherscanLinkHtml(link); } function blockNumberHtml(blockNumber) { const num = String(blockNumber); const link = `${currentNetwork().explorerUrl}/block/${num}`; return copyableHtml(num) + etherscanLinkHtml(link); } function showWait(txInfo, txHash) { clearTimers(); const symbol = txInfo.token === "ETH" ? "ETH" : txInfo.tokenSymbol || "?"; $("wait-tx-summary").textContent = txInfo.amount + " " + symbol; $("wait-tx-to").innerHTML = toAddressHtml(txInfo.to); $("wait-tx-hash").innerHTML = txHashHtml(txHash); attachCopyHandlers("view-wait-tx"); const broadcastTime = Date.now(); $("wait-tx-status").textContent = "Waiting for confirmation... 0s"; elapsedTimer = setInterval(() => { const elapsed = Math.floor((Date.now() - broadcastTime) / 1000); $("wait-tx-status").textContent = "Waiting for confirmation... " + elapsed + "s"; }, 1000); const provider = getProvider(state.rpcUrl); pollTimer = setInterval(async () => { try { const receipt = await provider.getTransactionReceipt(txHash); if (receipt) { showSuccess(txInfo, txHash, receipt.blockNumber); } } catch (e) { log.errorf("poll receipt failed:", e.message); } const elapsed = Math.floor((Date.now() - broadcastTime) / 1000); if (elapsed >= 60) { showError( txInfo, txHash, "Transaction was not confirmed within 60 seconds. It may still confirm later \u2014 check Etherscan.", ); } }, 10000); showView("wait-tx"); } function showSuccess(txInfo, txHash, blockNumber) { clearTimers(); const symbol = txInfo.token === "ETH" ? "ETH" : txInfo.tokenSymbol || "?"; state.viewData = { amount: txInfo.amount, symbol: symbol, to: txInfo.to, hash: txHash, blockNumber: blockNumber, decoded: txInfo.decoded || null, }; renderSuccess(); ctx.doRefreshAndRender(); } function tokenLabel(address) { const t = TOKEN_BY_ADDRESS.get(address.toLowerCase()); return t ? t.symbol : null; } function etherscanTokenLink(address) { return `${currentNetwork().explorerUrl}/token/${address}`; } function decodedDetailsHtml(decoded) { if (!decoded || !decoded.details) return ""; let html = `