Compare commits

..

1 Commits

Author SHA1 Message Date
user
9f85758ef6 persist confirm-tx view across popup close/reopen (closes #77)
All checks were successful
check / check (push) Successful in 21s
Add confirm-tx to RESTORABLE_VIEWS and save pendingTx in
state.viewData so the confirmation screen survives the popup
lifecycle. On restore, re-render the full confirmation view
including gas estimate.
2026-02-28 12:19:39 -08:00
3 changed files with 21 additions and 24 deletions

View File

@@ -74,8 +74,8 @@ const RESTORABLE_VIEWS = new Set([
"receive",
"settings",
"settings-addtoken",
"transaction",
"confirm-tx",
"transaction",
"success-tx",
"error-tx",
]);
@@ -128,16 +128,16 @@ function restoreView() {
case "settings-addtoken":
settingsAddToken.show();
break;
case "transaction":
if (state.viewData && state.viewData.tx) {
transactionDetail.render();
case "confirm-tx":
if (state.viewData && state.viewData.pendingTx) {
confirmTx.restore();
} else {
fallbackView();
}
break;
case "confirm-tx":
if (state.viewData && state.viewData.pendingTx) {
confirmTx.show(state.viewData.pendingTx);
case "transaction":
if (state.viewData && state.viewData.tx) {
transactionDetail.render();
} else {
fallbackView();
}

View File

@@ -18,7 +18,7 @@ const {
addressDotHtml,
escapeHtml,
} = require("./helpers");
const { state, saveState } = require("../../shared/state");
const { state } = require("../../shared/state");
const { getSignerForAddress } = require("../../shared/wallet");
const { decryptWithPassword } = require("../../shared/vault");
const { formatUsd, getPrice } = require("../../shared/prices");
@@ -38,6 +38,13 @@ const EXT_ICON =
let pendingTx = null;
function restore() {
const d = state.viewData;
if (d && d.pendingTx) {
show(d.pendingTx);
}
}
function etherscanTokenLink(address) {
return `https://etherscan.io/token/${address}`;
}
@@ -217,11 +224,8 @@ function show(txInfo) {
// Gas estimate — show placeholder then fetch async
$("confirm-fee").classList.remove("hidden");
$("confirm-fee-amount").textContent = "Estimating...";
showView("confirm-tx");
// Persist txInfo so the view survives popup close/reopen
state.viewData = { pendingTx: txInfo };
saveState();
showView("confirm-tx");
estimateGas(txInfo);
}
@@ -351,4 +355,4 @@ function init(ctx) {
});
}
module.exports = { init, show };
module.exports = { init, show, restore };

View File

@@ -153,11 +153,9 @@ async function fetchRecentTransactions(address, blockscoutUrl, count = 25) {
// When a token transfer shares a hash with a normal tx, the normal tx
// is the contract call (0 ETH) and the token transfer has the real
// amount and symbol. A single transaction (e.g. a swap) can produce
// multiple token transfers (one per token involved), so we key token
// transfers by hash + contract address to keep all of them. We also
// preserve contract-call metadata (direction, label, method) from the
// matching normal tx so swaps display correctly.
// amount and symbol. Replace the normal tx with the token transfer,
// but preserve contract call metadata (direction, label, method) so
// swaps and other contract interactions display correctly.
for (const tt of ttJson.items || []) {
const parsed = parseTokenTransfer(tt, addrLower);
const existing = txsByHash.get(parsed.hash);
@@ -166,13 +164,8 @@ async function fetchRecentTransactions(address, blockscoutUrl, count = 25) {
parsed.directionLabel = existing.directionLabel;
parsed.isContractCall = true;
parsed.method = existing.method;
// Remove the bare-hash normal tx so it doesn't appear as a
// duplicate with empty value; token transfers replace it.
txsByHash.delete(parsed.hash);
}
// Use composite key so multiple token transfers per tx are kept.
const ttKey = parsed.hash + ":" + (parsed.contractAddress || "");
txsByHash.set(ttKey, parsed);
txsByHash.set(parsed.hash, parsed);
}
const txs = [...txsByHash.values()];