fix: long symbols wrap on TxApproval and TransactionDetail, and SuccessTx keeps its amount and recipient (closes #743)
check / check (push) Canceled after 0s
e2e / e2e-chrome (push) Canceled after 0s
e2e / e2e-firefox (push) Canceled after 0s

TxApproval and TransactionDetail cut off a long symbol, amount or description at
the edge of the screen. These lines now wrap.

SuccessTx hid its Amount and To lines whenever it had a decoded action, even one
that showed neither. Each line is now hidden only when a readable decoded line
shows the same thing. A swap with no Amount line now shows its amount on
SuccessTx, as WaitTx and ErrorTx do.

Model: opus-5-5
This commit was merged in pull request #744.
This commit is contained in:
2026-11-03 12:27:20 +01:00
parent 1d40e2d7d5
commit 64ec571a17
11 changed files with 269 additions and 55 deletions
+6 -3
View File
@@ -1646,7 +1646,7 @@
<div class="text-xs text-muted mb-1">Action</div>
<div
id="tx-detail-calldata-action"
class="text-xs font-bold mb-2"
class="text-xs font-bold mb-2 break-words"
></div>
<div
id="tx-detail-calldata-details"
@@ -1721,7 +1721,7 @@
<div class="text-xs text-muted mb-1">Action</div>
<div
id="approve-tx-action"
class="text-xs font-bold mb-2"
class="text-xs font-bold mb-2 break-words"
></div>
<div id="approve-tx-decoded-details" class="text-xs"></div>
</div>
@@ -1736,7 +1736,10 @@
</div>
<div class="mb-3">
<div class="text-xs text-muted mb-1">Value</div>
<div id="approve-tx-value" class="text-xs font-bold"></div>
<div
id="approve-tx-value"
class="text-xs font-bold break-words"
></div>
</div>
<div class="mb-3">
<div class="text-xs text-muted mb-1">Network fee (max)</div>
+4 -4
View File
@@ -361,7 +361,7 @@ function showTxApproval(details) {
if (toAddr) {
let toHtml = "";
if (symbol) {
toHtml += `<div class="font-bold mb-1">${escapeHtml(symbol)}</div>`;
toHtml += `<div class="font-bold mb-1 break-words">${escapeHtml(symbol)}</div>`;
}
toHtml += approvalAddressHtml(toAddr, approvedTx.chainId);
$("approve-tx-to").innerHTML = toHtml;
@@ -394,14 +394,14 @@ function showTxApproval(details) {
$("approve-tx-action").textContent = decoded.name;
let detailsHtml = "";
if (decoded.description) {
detailsHtml += `<div class="mb-2">${escapeHtml(decoded.description)}</div>`;
detailsHtml += `<div class="mb-2 break-words">${escapeHtml(decoded.description)}</div>`;
}
for (const d of decoded.details) {
detailsHtml += `<div class="mb-2">`;
detailsHtml += `<div class="text-muted">${escapeHtml(d.label)}</div>`;
if (d.address) {
if (d.isToken) {
detailsHtml += `<div class="font-bold">${escapeHtml(tokenLabel(d.address, approvedTx.chainId) || "Unknown token")}</div>`;
detailsHtml += `<div class="font-bold break-words">${escapeHtml(tokenLabel(d.address, approvedTx.chainId) || "Unknown token")}</div>`;
detailsHtml += blockscoutOffTokenNoteHtml(
d.address,
approvedTx.chainId,
@@ -412,7 +412,7 @@ function showTxApproval(details) {
approvedTx.chainId,
);
} else {
detailsHtml += `<div class="font-bold">${escapeHtml(d.value)}</div>`;
detailsHtml += `<div class="font-bold break-words">${escapeHtml(d.value)}</div>`;
}
detailsHtml += `</div>`;
}
+8 -5
View File
@@ -126,13 +126,16 @@ function render() {
const exactStr = tx.exactValue
? tx.exactValue + " " + detailSym
: tx.directionLabel + " " + detailSym;
$("tx-detail-value").innerHTML = copyableHtml(exactStr, "font-bold");
$("tx-detail-value").innerHTML = copyableHtml(
exactStr,
"font-bold break-words",
);
// Native quantity (raw integer, copyable)
const nativeEl = $("tx-detail-native");
if (tx.rawAmount && tx.rawUnit) {
const nativeStr = tx.rawAmount + " " + tx.rawUnit;
nativeEl.innerHTML = copyableHtml(nativeStr, "");
nativeEl.innerHTML = copyableHtml(nativeStr, "break-words");
nativeEl.parentElement.classList.remove("hidden");
} else {
nativeEl.innerHTML = "";
@@ -368,7 +371,7 @@ async function loadFullTxDetails(txHash, chainId) {
actionEl.textContent = decoded.name;
let detailsHtml = "";
if (decoded.description) {
detailsHtml += `<div class="mb-2">${escapeHtml(decoded.description)}</div>`;
detailsHtml += `<div class="mb-2 break-words">${escapeHtml(decoded.description)}</div>`;
}
for (const d of decoded.details || []) {
detailsHtml += `<div class="mb-2">`;
@@ -377,13 +380,13 @@ async function loadFullTxDetails(txHash, chainId) {
// Token entry: show symbol on its own line, then address via shared renderer
const tokenSymbol = d.value.match(/^(\S+)\s*\(/)?.[1];
if (tokenSymbol) {
detailsHtml += `<div class="font-bold">${escapeHtml(displaySymbol(tokenSymbol))}</div>`;
detailsHtml += `<div class="font-bold break-words">${escapeHtml(displaySymbol(tokenSymbol))}</div>`;
}
detailsHtml += renderAddressHtml(d.address, { chainId });
} else if (d.address) {
detailsHtml += renderAddressHtml(d.address, { chainId });
} else {
detailsHtml += `<div class="font-bold">${escapeHtml(d.value)}</div>`;
detailsHtml += `<div class="font-bold break-words">${escapeHtml(d.value)}</div>`;
}
detailsHtml += `</div>`;
}
+22 -16
View File
@@ -321,10 +321,14 @@ function showSuccess(txInfo, txHash, blockNumber) {
ctx.doRefreshAndRender();
}
function readableLines(decoded) {
if (!decoded || !Array.isArray(decoded.details)) return [];
return decoded.details.filter(isReadableLine);
}
// The decoded action, or "" when no line of it can be read.
function decodedDetailsHtml(decoded, chainId) {
if (!decoded || !Array.isArray(decoded.details)) return "";
const lines = decoded.details.filter(isReadableLine);
const lines = readableLines(decoded);
if (lines.length === 0) return "";
let html = `<div class="border border-border border-dashed p-2 mb-3">`;
if (decoded.name && typeof decoded.name === "string") {
@@ -355,20 +359,22 @@ function renderSuccess() {
const decodedHtml = decodedDetailsHtml(d.decoded, d.chainId);
// When decoded details are present, the Amount and To are already
// shown inside the decoded well — hide the top-level duplicates.
const summarySection = $("success-tx-summary").parentElement;
const toSection = $("success-tx-to").parentElement;
if (decodedHtml) {
summarySection.classList.add("hidden");
toSection.classList.add("hidden");
} else {
summarySection.classList.remove("hidden");
toSection.classList.remove("hidden");
$("success-tx-summary").textContent =
d.amount + (d.symbol ? " " + d.symbol : "");
$("success-tx-to").innerHTML = toAddressHtml(d.to, d.chainId);
}
// Amount and To are hidden only when a readable decoded line shows the same
// thing: an `Amount` line, or a line with the address in `to`. Some swaps
// have no `Amount` line, and a saved record can have unreadable lines. An
// empty `to` is a contract creation, which no decoded line shows.
const lines = readableLines(d.decoded);
$("success-tx-summary").parentElement.classList.toggle(
"hidden",
lines.some((line) => line.label === "Amount"),
);
$("success-tx-to").parentElement.classList.toggle(
"hidden",
lines.some((line) => line.address && line.address === d.to),
);
$("success-tx-summary").textContent =
d.amount + (d.symbol ? " " + d.symbol : "");
$("success-tx-to").innerHTML = toAddressHtml(d.to, d.chainId);
$("success-tx-block").innerHTML = blockNumberHtml(d.blockNumber, d.chainId);
$("success-tx-hash").innerHTML = txHashHtml(d.hash, d.chainId);