Amount
diff --git a/src/popup/views/addressToken.js b/src/popup/views/addressToken.js
index 21d9310..6f25fef 100644
--- a/src/popup/views/addressToken.js
+++ b/src/popup/views/addressToken.js
@@ -12,7 +12,7 @@ const {
balanceLine,
} = require("./helpers");
const { state, currentAddress, saveState } = require("../../shared/state");
-const { TOKEN_BY_ADDRESS } = require("../../shared/tokenList");
+const { TOKEN_BY_ADDRESS, resolveSymbol } = require("../../shared/tokenList");
const {
formatUsd,
getPrice,
@@ -96,14 +96,11 @@ function show() {
const tb = (addr.tokenBalances || []).find(
(t) => t.address.toLowerCase() === tokenId.toLowerCase(),
);
- const tracked = (state.trackedTokens || []).find(
- (t) => t.address.toLowerCase() === tokenId.toLowerCase(),
+ symbol = resolveSymbol(
+ tokenId,
+ addr.tokenBalances,
+ state.trackedTokens,
);
- symbol =
- (tb && tb.symbol) ||
- (tracked && tracked.symbol) ||
- (knownToken && knownToken.symbol) ||
- "?";
amount = tb ? parseFloat(tb.balance || "0") : 0;
price = getPrice(symbol);
}
diff --git a/src/popup/views/approval.js b/src/popup/views/approval.js
index 8641960..1b05110 100644
--- a/src/popup/views/approval.js
+++ b/src/popup/views/approval.js
@@ -184,6 +184,15 @@ function showTxApproval(details) {
}
}
+ // Carry decoded calldata info through to success/error views
+ if (decoded) {
+ pendingTxDetails.decoded = {
+ name: decoded.name,
+ description: decoded.description,
+ details: decoded.details,
+ };
+ }
+
$("approve-tx-hostname").textContent = details.hostname;
$("approve-tx-from").innerHTML = approvalAddressHtml(state.activeAddress);
diff --git a/src/popup/views/send.js b/src/popup/views/send.js
index 9272784..fda8a66 100644
--- a/src/popup/views/send.js
+++ b/src/popup/views/send.js
@@ -10,7 +10,7 @@ const {
const { state, currentAddress } = require("../../shared/state");
let ctx;
const { getProvider } = require("../../shared/balances");
-const { KNOWN_SYMBOLS, TOKEN_BY_ADDRESS } = require("../../shared/tokenList");
+const { KNOWN_SYMBOLS, resolveSymbol } = require("../../shared/tokenList");
const EXT_ICON =
`
` +
@@ -73,15 +73,11 @@ function updateSendBalance() {
const tb = (addr.tokenBalances || []).find(
(t) => t.address.toLowerCase() === token.toLowerCase(),
);
- const knownToken = TOKEN_BY_ADDRESS.get(token.toLowerCase());
- const tracked = (state.trackedTokens || []).find(
- (t) => t.address.toLowerCase() === token.toLowerCase(),
+ const symbol = resolveSymbol(
+ token,
+ addr.tokenBalances,
+ state.trackedTokens,
);
- const symbol =
- (tb && tb.symbol) ||
- (tracked && tracked.symbol) ||
- (knownToken && knownToken.symbol) ||
- "?";
const bal = tb ? tb.balance || "0" : "0";
$("send-balance").textContent =
"Current balance: " + bal + " " + symbol;
@@ -132,15 +128,11 @@ function init(_ctx) {
const tb = (addr.tokenBalances || []).find(
(t) => t.address.toLowerCase() === token.toLowerCase(),
);
- const knownTk = TOKEN_BY_ADDRESS.get(token.toLowerCase());
- const trackedTk = (state.trackedTokens || []).find(
- (t) => t.address.toLowerCase() === token.toLowerCase(),
+ tokenSymbol = resolveSymbol(
+ token,
+ addr.tokenBalances,
+ state.trackedTokens,
);
- tokenSymbol =
- (tb && tb.symbol) ||
- (trackedTk && trackedTk.symbol) ||
- (knownTk && knownTk.symbol) ||
- "?";
tokenBalance = tb ? tb.balance || "0" : "0";
}
diff --git a/src/popup/views/transactionDetail.js b/src/popup/views/transactionDetail.js
index cee3cb4..d24e040 100644
--- a/src/popup/views/transactionDetail.js
+++ b/src/popup/views/transactionDetail.js
@@ -143,11 +143,10 @@ function render() {
typeEl.textContent = tx.directionLabel;
typeSection.classList.remove("hidden");
}
- if (headingEl) headingEl.textContent = tx.directionLabel;
} else {
if (typeSection) typeSection.classList.add("hidden");
- if (headingEl) headingEl.textContent = "Transaction";
}
+ if (headingEl) headingEl.textContent = "Transaction";
// Hide calldata and raw data sections; re-fetch if this is a contract call
const calldataSection = $("tx-detail-calldata-section");
diff --git a/src/popup/views/txStatus.js b/src/popup/views/txStatus.js
index a755b84..b8e408a 100644
--- a/src/popup/views/txStatus.js
+++ b/src/popup/views/txStatus.js
@@ -8,6 +8,7 @@ const {
addressTitle,
escapeHtml,
} = require("./helpers");
+const { TOKEN_BY_ADDRESS } = require("../../shared/tokenList");
const { state, saveState } = require("../../shared/state");
const { getProvider } = require("../../shared/balances");
const { log } = require("../../shared/log");
@@ -121,11 +122,51 @@ function showSuccess(txInfo, txHash, blockNumber) {
to: txInfo.to,
hash: txHash,
blockNumber: blockNumber,
+ decoded: txInfo.decoded || null,
};
renderSuccess();
ctx.doRefreshAndRender();
}
+function tokenLabel(address) {
+ const t = TOKEN_BY_ADDRESS.get(address.toLowerCase());
+ return t ? t.symbol : null;
+}
+
+function etherscanTokenLink(address) {
+ return `https://etherscan.io/token/${address}`;
+}
+
+function decodedDetailsHtml(decoded) {
+ if (!decoded || !decoded.details) return "";
+ let html = "";
+ if (decoded.name) {
+ html += `Action
`;
+ html += `
${escapeHtml(decoded.name)}
`;
+ }
+ if (decoded.description) {
+ html += `Description
`;
+ html += `
${escapeHtml(decoded.description)}
`;
+ }
+ for (const d of decoded.details) {
+ html += ``;
+ html += `
${escapeHtml(d.label)}
`;
+ if (d.address) {
+ if (d.isToken) {
+ const sym = tokenLabel(d.address) || "Unknown token";
+ html += `
${escapeHtml(sym)}
`;
+ html += toAddressHtml(d.address);
+ } else {
+ html += toAddressHtml(d.address);
+ }
+ } else {
+ html += `
${escapeHtml(d.value)}
`;
+ }
+ html += `
`;
+ }
+ return html;
+}
+
function renderSuccess() {
const d = state.viewData;
if (!d || !d.hash) return;
@@ -133,6 +174,16 @@ function renderSuccess() {
$("success-tx-to").innerHTML = toAddressHtml(d.to);
$("success-tx-block").textContent = String(d.blockNumber);
$("success-tx-hash").innerHTML = txHashHtml(d.hash);
+
+ // Show decoded calldata details if present
+ const decodedEl = $("success-tx-decoded");
+ if (decodedEl && d.decoded) {
+ decodedEl.innerHTML = decodedDetailsHtml(d.decoded);
+ decodedEl.classList.remove("hidden");
+ } else if (decodedEl) {
+ decodedEl.classList.add("hidden");
+ }
+
attachCopyHandlers("view-success-tx");
showView("success-tx");
}
diff --git a/src/shared/tokenList.js b/src/shared/tokenList.js
index 45aa587..eff9dd6 100644
--- a/src/shared/tokenList.js
+++ b/src/shared/tokenList.js
@@ -3645,10 +3645,27 @@ async function getTopTokenPrices(n) {
return prices;
}
+// Resolve a token symbol from multiple sources, never returning "?".
+function resolveSymbol(tokenAddress, tokenBalances, trackedTokens) {
+ const lower = (tokenAddress || "").toLowerCase();
+ const tb = (tokenBalances || []).find(
+ (t) => t.address.toLowerCase() === lower,
+ );
+ if (tb && tb.symbol) return tb.symbol;
+ const known = TOKEN_BY_ADDRESS.get(lower);
+ if (known && known.symbol) return known.symbol;
+ const tracked = (trackedTokens || []).find(
+ (t) => t.address.toLowerCase() === lower,
+ );
+ if (tracked && tracked.symbol) return tracked.symbol;
+ return lower.slice(0, 10) + "\u2026";
+}
+
module.exports = {
TOKENS,
TOKEN_BY_ADDRESS,
KNOWN_SYMBOLS,
getTopTokens,
getTopTokenPrices,
+ resolveSymbol,
};