fix: the wait and error screens show a swap's Moved from the sender amounts (closes #722)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run

A swap's Amount figure can leave out what its Moved from the sender lines
take, so these screens could read as if less left the wallet than can have
left. Both now show each of those amounts under the figure, using the decoded
details they already receive. The error screen saves those details too, so a
reopened popup keeps the lines. A saved record in another shape shows only the
lines it can read.

Model: opus-5-5
This commit was merged in pull request #732.
This commit is contained in:
2026-11-03 08:12:41 +01:00
parent 21d5e42528
commit f79390cad5
4 changed files with 187 additions and 10 deletions
+31 -9
View File
@@ -73,6 +73,29 @@ function toAddressHtml(address, chainId) {
return renderAddressHtml(address, { title, chainId });
}
// The amount of each `Moved from the sender` line of a decoded swap, for the
// wait and error screens to show under the Amount figure. That figure can leave
// these amounts out, so alone it can read as less than can have left the
// wallet. `decoded` can come back from storage in any shape, so this shows only
// the lines whose value is text.
function movedFromSenderHtml(decoded) {
if (!decoded || !Array.isArray(decoded.details)) return "";
let html = "";
for (const d of decoded.details) {
if (
!d ||
d.label !== "Moved from the sender" ||
typeof d.value !== "string"
)
continue;
html += `<div class="mt-2">`;
html += `<div class="text-xs text-muted mb-1">${escapeHtml(d.label)}</div>`;
html += `<div class="font-bold">${escapeHtml(d.value)}</div>`;
html += `</div>`;
}
return html;
}
function txHashHtml(hash, chainId) {
const link = explorerUrl("tx", hash, chainId);
return copyableHtml(hash, "break-all") + etherscanLinkHtml(link);
@@ -109,10 +132,9 @@ function startWait(txInfo, txHash, broadcastTime, pollNow) {
}
$("wait-tx-summary").textContent =
txInfo.amount + (symbol ? " " + symbol : "");
$("wait-tx-token-note").innerHTML = blockscoutOffTokenNoteHtml(
txInfo.token,
txInfo.chainId,
);
$("wait-tx-token-note").innerHTML =
blockscoutOffTokenNoteHtml(txInfo.token, txInfo.chainId) +
movedFromSenderHtml(txInfo.decoded);
$("wait-tx-to").innerHTML = toAddressHtml(txInfo.to, txInfo.chainId);
$("wait-tx-hash").innerHTML = txHashHtml(txHash, txInfo.chainId);
attachCopyHandlers("view-wait-tx");
@@ -223,7 +245,7 @@ function showWait(txInfo, txHash) {
// to name a network. txInfo.token and txInfo.tokenSymbol are not checked here.
// blockscoutOffTokenNoteHtml() shows no line for a token that is not text.
// Everything else only compares and coalesces them, and tokenSymbol is null for
// ETH.
// ETH. txInfo.decoded is not checked either: see movedFromSenderHtml().
function restoreWait() {
const d = state.viewData;
if (!d || !d.pendingWait) return false;
@@ -356,6 +378,7 @@ function showError(txInfo, txHash, message) {
to: txInfo.to,
hash: txHash || null,
message: message,
decoded: txInfo.decoded || null,
chainId: txInfo.chainId,
};
renderError();
@@ -366,10 +389,9 @@ function renderError() {
if (!d || !d.message) return;
$("error-tx-summary").textContent =
d.amount + (d.symbol ? " " + d.symbol : "");
$("error-tx-token-note").innerHTML = blockscoutOffTokenNoteHtml(
d.token,
d.chainId,
);
$("error-tx-token-note").innerHTML =
blockscoutOffTokenNoteHtml(d.token, d.chainId) +
movedFromSenderHtml(d.decoded);
$("error-tx-to").innerHTML = toAddressHtml(d.to, d.chainId);
$("error-tx-message").textContent = d.message;