diff --git a/src/background/index.js b/src/background/index.js index 887f2a2..861bf5d 100644 --- a/src/background/index.js +++ b/src/background/index.js @@ -607,10 +607,13 @@ runtime.onMessage.addListener((msg, sender, sendResponse) => { const connected = signer.connect(provider); const tx = await connected.sendTransaction(approval.txParams); approval.resolve({ txHash: tx.hash }); + sendResponse({ txHash: tx.hash }); } catch (e) { + const errMsg = e.shortMessage || e.message; approval.resolve({ - error: { message: e.shortMessage || e.message }, + error: { message: errMsg }, }); + sendResponse({ error: errMsg }); } })(); return true; diff --git a/src/popup/index.js b/src/popup/index.js index df17fab..af43b14 100644 --- a/src/popup/index.js +++ b/src/popup/index.js @@ -169,8 +169,9 @@ async function init() { await saveState(); } - // Always init approval — it may run in its own popup window + // Always init approval and txStatus — they may run in the approval popup window approval.init(ctx); + txStatus.init(ctx); // Check for approval mode const params = new URLSearchParams(window.location.search); @@ -202,7 +203,6 @@ async function init() { addressToken.init(ctx); send.init(ctx); confirmTx.init(ctx); - txStatus.init(ctx); transactionDetail.init(ctx); receive.init(ctx); addToken.init(ctx); diff --git a/src/popup/views/approval.js b/src/popup/views/approval.js index 04f36f8..c9732f9 100644 --- a/src/popup/views/approval.js +++ b/src/popup/views/approval.js @@ -3,6 +3,7 @@ const { state, saveState } = require("../../shared/state"); const { formatEther, formatUnits, Interface } = require("ethers"); const { ERC20_ABI } = require("../../shared/constants"); const { TOKEN_BY_ADDRESS } = require("../../shared/tokenList"); +const txStatus = require("./txStatus"); const runtime = typeof browser !== "undefined" ? browser.runtime : chrome.runtime; @@ -117,9 +118,38 @@ function decodeCalldata(data, toAddress) { } function showTxApproval(details) { + const toAddr = details.txParams.to; + const token = toAddr ? TOKEN_BY_ADDRESS.get(toAddr.toLowerCase()) : null; + const ethValue = formatEther(details.txParams.value || "0"); + + // Build txInfo for status screens + pendingTxDetails = { + from: state.activeAddress, + to: toAddr || "", + amount: formatTxValue(ethValue), + token: "ETH", + tokenSymbol: token ? token.symbol : null, + }; + + // If this is an ERC-20 call, try to extract the real recipient and amount + const decoded = decodeCalldata(details.txParams.data, toAddr || ""); + if (decoded && decoded.details) { + for (const d of decoded.details) { + if (d.label === "Recipient" && d.address) { + pendingTxDetails.to = d.address; + } + if (d.label === "Amount") { + pendingTxDetails.amount = d.value; + } + } + if (token) { + pendingTxDetails.token = toAddr; + pendingTxDetails.tokenSymbol = token.symbol; + } + } + $("approve-tx-hostname").textContent = details.hostname; $("approve-tx-from").innerHTML = approvalAddressHtml(state.activeAddress); - const toAddr = details.txParams.to; // Show token symbol next to contract address if known const symbol = toAddr ? tokenLabel(toAddr) : null; @@ -141,8 +171,7 @@ function showTxApproval(details) { $("approve-tx-value").textContent = formatTxValue(formatEther(details.txParams.value || "0")) + " ETH"; - // Decode calldata - const decoded = decodeCalldata(details.txParams.data, toAddr || ""); + // Decode calldata (reuse decoded from above) const decodedEl = $("approve-tx-decoded"); if (decoded) { $("approve-tx-action").textContent = decoded.name; @@ -204,6 +233,7 @@ function show(id) { } let approvalId = null; +let pendingTxDetails = null; function init(ctx) { $("approve-remember").addEventListener("change", async () => { @@ -234,13 +264,33 @@ function init(ctx) { }); $("btn-approve-tx").addEventListener("click", () => { - runtime.sendMessage({ - type: "AUTISTMASK_TX_RESPONSE", - id: approvalId, - approved: true, - password: $("approve-tx-password").value, - }); - window.close(); + const password = $("approve-tx-password").value; + if (!password) { + $("approve-tx-error").textContent = "Please enter your password."; + $("approve-tx-error").classList.remove("hidden"); + return; + } + $("approve-tx-error").classList.add("hidden"); + $("btn-approve-tx").disabled = true; + $("btn-approve-tx").classList.add("text-muted"); + + runtime.sendMessage( + { + type: "AUTISTMASK_TX_RESPONSE", + id: approvalId, + approved: true, + password: password, + }, + (response) => { + if (response && response.txHash) { + txStatus.showWait(pendingTxDetails, response.txHash); + } else { + const msg = + (response && response.error) || "Transaction failed."; + txStatus.showError(pendingTxDetails, null, msg); + } + }, + ); }); $("btn-reject-tx").addEventListener("click", () => { diff --git a/src/popup/views/txStatus.js b/src/popup/views/txStatus.js index f94f245..a36fd31 100644 --- a/src/popup/views/txStatus.js +++ b/src/popup/views/txStatus.js @@ -161,7 +161,15 @@ function renderError() { showView("error-tx"); } +function isApprovalPopup() { + return new URLSearchParams(window.location.search).has("approval"); +} + function navigateBack() { + if (isApprovalPopup()) { + window.close(); + return; + } if (state.selectedToken) { ctx.showAddressToken(); } else {