Show decoded calldata in transaction detail view
All checks were successful
check / check (push) Successful in 22s
All checks were successful
check / check (push) Successful in 22s
Add decoded transaction summary (matching the approval screen format) to the transaction detail view. For unknown contract calls, show 'Unknown Contract Call' label with full raw calldata hex (not truncated).
This commit is contained in:
@@ -943,6 +943,23 @@
|
|||||||
<div class="text-xs text-muted mb-1">Transaction hash</div>
|
<div class="text-xs text-muted mb-1">Transaction hash</div>
|
||||||
<div id="tx-detail-hash" class="text-xs break-all"></div>
|
<div id="tx-detail-hash" class="text-xs break-all"></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
id="tx-detail-decoded"
|
||||||
|
class="mb-3 border border-border border-dashed p-2 hidden"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
id="tx-detail-action"
|
||||||
|
class="font-bold mb-1 text-xs"
|
||||||
|
></div>
|
||||||
|
<div id="tx-detail-decoded-details" class="text-xs"></div>
|
||||||
|
</div>
|
||||||
|
<div id="tx-detail-rawdata-section" class="mb-4 hidden">
|
||||||
|
<div class="text-xs text-muted mb-1">Raw calldata</div>
|
||||||
|
<div
|
||||||
|
id="tx-detail-rawdata"
|
||||||
|
class="text-xs break-all font-mono"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ============ TRANSACTION APPROVAL ============ -->
|
<!-- ============ TRANSACTION APPROVAL ============ -->
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ const {
|
|||||||
timeAgo,
|
timeAgo,
|
||||||
} = require("./helpers");
|
} = require("./helpers");
|
||||||
const { state } = require("../../shared/state");
|
const { state } = require("../../shared/state");
|
||||||
|
const { TOKEN_BY_ADDRESS } = require("../../shared/tokenList");
|
||||||
|
const { decodeCalldata } = require("../../shared/decodeCalldata");
|
||||||
const makeBlockie = require("ethereum-blockies-base64");
|
const makeBlockie = require("ethereum-blockies-base64");
|
||||||
|
|
||||||
const EXT_ICON =
|
const EXT_ICON =
|
||||||
@@ -85,6 +87,8 @@ function show(tx) {
|
|||||||
fromEns: tx.fromEns || null,
|
fromEns: tx.fromEns || null,
|
||||||
toEns: tx.toEns || null,
|
toEns: tx.toEns || null,
|
||||||
directionLabel: tx.directionLabel || null,
|
directionLabel: tx.directionLabel || null,
|
||||||
|
rawInput: tx.rawInput || null,
|
||||||
|
decoded: tx.decoded || null,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
render();
|
render();
|
||||||
@@ -124,6 +128,58 @@ function render() {
|
|||||||
$("tx-detail-time").textContent =
|
$("tx-detail-time").textContent =
|
||||||
isoDate(tx.timestamp) + " (" + timeAgo(tx.timestamp) + ")";
|
isoDate(tx.timestamp) + " (" + timeAgo(tx.timestamp) + ")";
|
||||||
$("tx-detail-status").textContent = tx.isError ? "Failed" : "Success";
|
$("tx-detail-status").textContent = tx.isError ? "Failed" : "Success";
|
||||||
|
|
||||||
|
// Decoded calldata section — matches approval screen format
|
||||||
|
const decodedEl = $("tx-detail-decoded");
|
||||||
|
const rawDataEl = $("tx-detail-rawdata-section");
|
||||||
|
const decoded = tx.decoded;
|
||||||
|
|
||||||
|
if (decoded) {
|
||||||
|
$("tx-detail-action").textContent = decoded.name;
|
||||||
|
let detailsHtml = "";
|
||||||
|
if (decoded.description) {
|
||||||
|
detailsHtml += `<div class="mb-2">${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) {
|
||||||
|
const t = TOKEN_BY_ADDRESS.get(d.address.toLowerCase());
|
||||||
|
const label = t ? t.symbol : "Unknown token";
|
||||||
|
detailsHtml += `<div class="font-bold">${escapeHtml(label)}</div>`;
|
||||||
|
}
|
||||||
|
const dot = addressDotHtml(d.address);
|
||||||
|
const link = `https://etherscan.io/address/${d.address}`;
|
||||||
|
detailsHtml +=
|
||||||
|
`<div class="flex items-center">${dot}` +
|
||||||
|
`<span class="break-all underline decoration-dashed cursor-pointer" data-copy="${escapeHtml(d.address)}">${escapeHtml(d.address)}</span>` +
|
||||||
|
`<a href="${link}" target="_blank" rel="noopener" class="inline-flex items-center">${EXT_ICON}</a></div>`;
|
||||||
|
} else {
|
||||||
|
detailsHtml += `<div class="font-bold">${escapeHtml(d.value)}</div>`;
|
||||||
|
}
|
||||||
|
detailsHtml += `</div>`;
|
||||||
|
}
|
||||||
|
$("tx-detail-decoded-details").innerHTML = detailsHtml;
|
||||||
|
decodedEl.classList.remove("hidden");
|
||||||
|
} else {
|
||||||
|
decodedEl.classList.add("hidden");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Raw calldata section — shown for unknown contract calls (full, not truncated)
|
||||||
|
if (tx.rawInput && tx.rawInput !== "0x" && !decoded) {
|
||||||
|
$("tx-detail-rawdata").textContent = tx.rawInput;
|
||||||
|
rawDataEl.classList.remove("hidden");
|
||||||
|
// Label as unknown contract call
|
||||||
|
$("tx-detail-action").textContent = "Unknown Contract Call";
|
||||||
|
$("tx-detail-decoded-details").innerHTML = "";
|
||||||
|
decodedEl.classList.remove("hidden");
|
||||||
|
} else if (!decoded) {
|
||||||
|
rawDataEl.classList.add("hidden");
|
||||||
|
} else {
|
||||||
|
rawDataEl.classList.add("hidden");
|
||||||
|
}
|
||||||
|
|
||||||
showView("transaction");
|
showView("transaction");
|
||||||
|
|
||||||
document
|
document
|
||||||
|
|||||||
Reference in New Issue
Block a user