`;
html += `
${ago}${dirLabel}${err}
`;
- html += `
${addrStr}${amountStr}
`;
+ html += `
${dot}${addrStr}${amountStr}
`;
html += `
`;
i++;
}
@@ -126,10 +158,23 @@ function renderTransactions(txs) {
});
}
+function txDetailAddressHtml(address) {
+ const ensName = ensNameMap.get(address) || null;
+ const dot = addressDotHtml(address);
+ if (ensName) {
+ return (
+ dot +
+ escapeHtml(ensName) +
+ ``;
html += `
Address ${wi + 1}.${ai + 1}
`;
+ const dot = addressDotHtml(addr.address);
if (addr.ensName) {
- html += `
${addr.ensName}
`;
+ html += `
${dot}${addr.ensName}
`;
}
const addrUsd = formatUsd(getAddressValueUsd(addr));
html += `
`;
- html += `${addr.address}`;
+ html += `${addr.ensName ? "" : dot}${addr.address}`;
html += `${addrUsd}`;
html += `
`;
html += balanceLinesForAddress(addr);
diff --git a/src/shared/ens.js b/src/shared/ens.js
new file mode 100644
index 0000000..9b06aa6
--- /dev/null
+++ b/src/shared/ens.js
@@ -0,0 +1,57 @@
+// Cached ENS reverse resolution.
+// Resolves addresses to ENS names via ethers provider.lookupAddress(),
+// caching results in localStorage with a 12-hour TTL.
+
+const { getProvider } = require("./balances");
+const { log } = require("./log");
+
+const CACHE_TTL_MS = 43200000; // 12 hours
+const CACHE_PREFIX = "ens:";
+
+function getCached(address) {
+ const key = CACHE_PREFIX + address.toLowerCase();
+ try {
+ const raw = localStorage.getItem(key);
+ if (!raw) return undefined;
+ const entry = JSON.parse(raw);
+ if (Date.now() - entry.ts < CACHE_TTL_MS) {
+ return entry.name;
+ }
+ } catch {
+ // Corrupt cache entry — treat as miss.
+ }
+ return undefined;
+}
+
+function setCache(address, name) {
+ const key = CACHE_PREFIX + address.toLowerCase();
+ localStorage.setItem(key, JSON.stringify({ name, ts: Date.now() }));
+}
+
+async function resolveEnsName(address, rpcUrl) {
+ const cached = getCached(address);
+ if (cached !== undefined) return cached;
+
+ const provider = getProvider(rpcUrl);
+ try {
+ const name = (await provider.lookupAddress(address)) || null;
+ setCache(address, name);
+ return name;
+ } catch (e) {
+ log.errorf("ENS reverse lookup failed", address, e.message);
+ setCache(address, null);
+ return null;
+ }
+}
+
+async function resolveEnsNames(addresses, rpcUrl) {
+ const results = new Map();
+ await Promise.all(
+ addresses.map(async (addr) => {
+ results.set(addr, await resolveEnsName(addr, rpcUrl));
+ }),
+ );
+ return results;
+}
+
+module.exports = { resolveEnsName, resolveEnsNames };