fix: unify address display with shared renderAddressHtml utility
All checks were successful
check / check (push) Successful in 26s

All address rendering now uses a single renderAddressHtml() function in
helpers.js that produces consistent output everywhere:
- Color dot (deterministic from address)
- Full address with dashed-underline click-to-copy affordance
- Etherscan external link icon

Refactored all callsites across 9 view files:
- approval.js: approvalAddressHtml now delegates to renderAddressHtml,
  added attachCopyHandlers for click-to-copy on approve-tx/sign/site views
- confirmTx.js: confirmAddressHtml uses renderAddressHtml, token contract
  address uses renderAddressHtml with attachCopyHandlers
- txStatus.js: toAddressHtml delegates to renderAddressHtml
- transactionDetail.js: txAddressHtml delegates to renderAddressHtml,
  decoded calldata addresses use renderAddressHtml
- home.js: active address display uses renderAddressHtml
- send.js: from-address display uses renderAddressHtml
- receive.js: address block uses formatAddressHtml (which delegates to
  renderAddressHtml), removed separate etherscan link element
- addressDetail.js: address line uses renderAddressHtml, export-privkey
  address uses renderAddressHtml
- addressToken.js: address line and contract info use renderAddressHtml

Also consolidated:
- EXT_ICON SVG constant moved to helpers.js (removed 6 duplicates)
- copyableHtml() moved to helpers.js (removed duplicate in transactionDetail)
- etherscanLinkHtml() moved to helpers.js (removed duplicates)
- attachCopyHandlers() moved to helpers.js (removed duplicate in txStatus)
- Removed unused local functions (etherscanTokenLink, etherscanAddressLink)
- Cleaned up unused imports across all files

closes #97
This commit is contained in:
user
2026-03-01 05:59:17 -08:00
parent a138a36710
commit 5395fc6ede
10 changed files with 179 additions and 395 deletions

View File

@@ -1,11 +1,12 @@
const {
$,
addressDotHtml,
addressTitle,
escapeHtml,
showView,
showError,
hideError,
renderAddressHtml,
attachCopyHandlers,
} = require("./helpers");
const { state, saveState, currentNetwork } = require("../../shared/state");
const { formatEther, formatUnits, Interface, toUtf8String } = require("ethers");
@@ -17,28 +18,11 @@ const uniswap = require("../../shared/uniswap");
const runtime =
typeof browser !== "undefined" ? browser.runtime : chrome.runtime;
const EXT_ICON =
`<span style="display:inline-block;width:10px;height:10px;margin-left:4px;vertical-align:middle">` +
`<svg viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="1.5">` +
`<path d="M4.5 1.5H2a.5.5 0 00-.5.5v8a.5.5 0 00.5.5h8a.5.5 0 00.5-.5V7.5"/>` +
`<path d="M7 1.5h3.5V5M7 5.5L10.5 1.5"/>` +
`</svg></span>`;
const erc20Iface = new Interface(ERC20_ABI);
function approvalAddressHtml(address) {
const dot = addressDotHtml(address);
const link = `${currentNetwork().explorerUrl}/address/${address}`;
const extLink = `<a href="${link}" target="_blank" rel="noopener" class="inline-flex items-center">${EXT_ICON}</a>`;
const title = addressTitle(address, state.wallets);
let html = "";
if (title) {
html += `<div class="flex items-center font-bold">${dot}${escapeHtml(title)}</div>`;
html += `<div class="break-all">${escapeHtml(address)}${extLink}</div>`;
} else {
html += `<div class="flex items-center">${dot}<span class="break-all">${escapeHtml(address)}</span>${extLink}</div>`;
}
return html;
return renderAddressHtml(address, { title });
}
function formatTxValue(val) {
@@ -53,10 +37,6 @@ function tokenLabel(address) {
return t ? t.symbol : null;
}
function etherscanTokenLink(address) {
return `${currentNetwork().explorerUrl}/token/${address}`;
}
// Try to decode calldata using known ABIs.
// Returns { name, description, details } or null.
function decodeCalldata(data, toAddress) {
@@ -235,10 +215,6 @@ function showTxApproval(details) {
toHtml += `<div class="font-bold mb-1">${escapeHtml(symbol)}</div>`;
}
toHtml += approvalAddressHtml(toAddr);
if (symbol) {
const link = etherscanTokenLink(toAddr);
toHtml = toHtml.replace("</div>", "") + ""; // approvalAddressHtml already has etherscan link
}
$("approve-tx-to").innerHTML = toHtml;
} else {
$("approve-tx-to").innerHTML = escapeHtml("(contract creation)");
@@ -266,12 +242,9 @@ function showTxApproval(details) {
detailsHtml += `<div class="text-muted">${escapeHtml(d.label)}</div>`;
if (d.address) {
if (d.isToken) {
const tLink = etherscanTokenLink(d.address);
detailsHtml += `<div class="font-bold">${escapeHtml(tokenLabel(d.address) || "Unknown token")}</div>`;
detailsHtml += approvalAddressHtml(d.address);
} else {
detailsHtml += approvalAddressHtml(d.address);
}
detailsHtml += approvalAddressHtml(d.address);
} else {
detailsHtml += `<div class="font-bold">${escapeHtml(d.value)}</div>`;
}
@@ -295,6 +268,7 @@ function showTxApproval(details) {
hideError("approve-tx-error");
showView("approve-tx");
attachCopyHandlers("view-approve-tx");
}
function decodeHexMessage(hex) {
@@ -392,6 +366,7 @@ function showSignApproval(details) {
$("btn-approve-sign").classList.remove("text-muted");
showView("approve-sign");
attachCopyHandlers("view-approve-sign");
}
function show(id) {
@@ -419,6 +394,7 @@ function show(id) {
$("approve-address").innerHTML = approvalAddressHtml(
state.activeAddress,
);
attachCopyHandlers("view-approve-site");
$("approve-remember").checked = state.rememberSiteChoice;
});
}