Show tx status screens after dApp transaction approval
All checks were successful
check / check (push) Successful in 17s
All checks were successful
check / check (push) Successful in 17s
Previously the approval popup closed immediately after the user entered their password, giving zero feedback about whether the transaction was broadcast or confirmed. Now: 1. Background sends the broadcast result back to the popup via sendResponse callback (txHash or error) 2. Popup shows wait-tx screen on success (with polling timer) or error-tx screen on failure 3. Wait-tx polls for confirmation and transitions to success-tx 4. Done button closes the approval window txStatus.init() moved before the approval early-return so the wait/success/error views are wired up in the approval popup. Done buttons detect the approval context and call window.close() instead of navigating to address detail.
This commit is contained in:
@@ -607,10 +607,13 @@ runtime.onMessage.addListener((msg, sender, sendResponse) => {
|
|||||||
const connected = signer.connect(provider);
|
const connected = signer.connect(provider);
|
||||||
const tx = await connected.sendTransaction(approval.txParams);
|
const tx = await connected.sendTransaction(approval.txParams);
|
||||||
approval.resolve({ txHash: tx.hash });
|
approval.resolve({ txHash: tx.hash });
|
||||||
|
sendResponse({ txHash: tx.hash });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
const errMsg = e.shortMessage || e.message;
|
||||||
approval.resolve({
|
approval.resolve({
|
||||||
error: { message: e.shortMessage || e.message },
|
error: { message: errMsg },
|
||||||
});
|
});
|
||||||
|
sendResponse({ error: errMsg });
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -169,8 +169,9 @@ async function init() {
|
|||||||
await saveState();
|
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);
|
approval.init(ctx);
|
||||||
|
txStatus.init(ctx);
|
||||||
|
|
||||||
// Check for approval mode
|
// Check for approval mode
|
||||||
const params = new URLSearchParams(window.location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
@@ -202,7 +203,6 @@ async function init() {
|
|||||||
addressToken.init(ctx);
|
addressToken.init(ctx);
|
||||||
send.init(ctx);
|
send.init(ctx);
|
||||||
confirmTx.init(ctx);
|
confirmTx.init(ctx);
|
||||||
txStatus.init(ctx);
|
|
||||||
transactionDetail.init(ctx);
|
transactionDetail.init(ctx);
|
||||||
receive.init(ctx);
|
receive.init(ctx);
|
||||||
addToken.init(ctx);
|
addToken.init(ctx);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ const { state, saveState } = require("../../shared/state");
|
|||||||
const { formatEther, formatUnits, Interface } = require("ethers");
|
const { formatEther, formatUnits, Interface } = require("ethers");
|
||||||
const { ERC20_ABI } = require("../../shared/constants");
|
const { ERC20_ABI } = require("../../shared/constants");
|
||||||
const { TOKEN_BY_ADDRESS } = require("../../shared/tokenList");
|
const { TOKEN_BY_ADDRESS } = require("../../shared/tokenList");
|
||||||
|
const txStatus = require("./txStatus");
|
||||||
|
|
||||||
const runtime =
|
const runtime =
|
||||||
typeof browser !== "undefined" ? browser.runtime : chrome.runtime;
|
typeof browser !== "undefined" ? browser.runtime : chrome.runtime;
|
||||||
@@ -117,9 +118,38 @@ function decodeCalldata(data, toAddress) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function showTxApproval(details) {
|
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-hostname").textContent = details.hostname;
|
||||||
$("approve-tx-from").innerHTML = approvalAddressHtml(state.activeAddress);
|
$("approve-tx-from").innerHTML = approvalAddressHtml(state.activeAddress);
|
||||||
const toAddr = details.txParams.to;
|
|
||||||
|
|
||||||
// Show token symbol next to contract address if known
|
// Show token symbol next to contract address if known
|
||||||
const symbol = toAddr ? tokenLabel(toAddr) : null;
|
const symbol = toAddr ? tokenLabel(toAddr) : null;
|
||||||
@@ -141,8 +171,7 @@ function showTxApproval(details) {
|
|||||||
$("approve-tx-value").textContent =
|
$("approve-tx-value").textContent =
|
||||||
formatTxValue(formatEther(details.txParams.value || "0")) + " ETH";
|
formatTxValue(formatEther(details.txParams.value || "0")) + " ETH";
|
||||||
|
|
||||||
// Decode calldata
|
// Decode calldata (reuse decoded from above)
|
||||||
const decoded = decodeCalldata(details.txParams.data, toAddr || "");
|
|
||||||
const decodedEl = $("approve-tx-decoded");
|
const decodedEl = $("approve-tx-decoded");
|
||||||
if (decoded) {
|
if (decoded) {
|
||||||
$("approve-tx-action").textContent = decoded.name;
|
$("approve-tx-action").textContent = decoded.name;
|
||||||
@@ -204,6 +233,7 @@ function show(id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let approvalId = null;
|
let approvalId = null;
|
||||||
|
let pendingTxDetails = null;
|
||||||
|
|
||||||
function init(ctx) {
|
function init(ctx) {
|
||||||
$("approve-remember").addEventListener("change", async () => {
|
$("approve-remember").addEventListener("change", async () => {
|
||||||
@@ -234,13 +264,33 @@ function init(ctx) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
$("btn-approve-tx").addEventListener("click", () => {
|
$("btn-approve-tx").addEventListener("click", () => {
|
||||||
runtime.sendMessage({
|
const password = $("approve-tx-password").value;
|
||||||
type: "AUTISTMASK_TX_RESPONSE",
|
if (!password) {
|
||||||
id: approvalId,
|
$("approve-tx-error").textContent = "Please enter your password.";
|
||||||
approved: true,
|
$("approve-tx-error").classList.remove("hidden");
|
||||||
password: $("approve-tx-password").value,
|
return;
|
||||||
});
|
}
|
||||||
window.close();
|
$("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", () => {
|
$("btn-reject-tx").addEventListener("click", () => {
|
||||||
|
|||||||
@@ -161,7 +161,15 @@ function renderError() {
|
|||||||
showView("error-tx");
|
showView("error-tx");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isApprovalPopup() {
|
||||||
|
return new URLSearchParams(window.location.search).has("approval");
|
||||||
|
}
|
||||||
|
|
||||||
function navigateBack() {
|
function navigateBack() {
|
||||||
|
if (isApprovalPopup()) {
|
||||||
|
window.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (state.selectedToken) {
|
if (state.selectedToken) {
|
||||||
ctx.showAddressToken();
|
ctx.showAddressToken();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user