diff --git a/frontend/public/explorer-spa.js b/frontend/public/explorer-spa.js
index 8e85fa6..53bb6b7 100644
--- a/frontend/public/explorer-spa.js
+++ b/frontend/public/explorer-spa.js
@@ -366,7 +366,7 @@
if (list.length === 0) { container.innerHTML = filterBar + '
No addresses in watchlist. Open an address and click "Add to watchlist".
'; return; }
if (filtered.length === 0) { container.innerHTML = filterBar + 'No watchlist entries match the current filter.
'; return; }
var html = filterBar + '
CCIPWETH9Bridge
- ${WETH9_BRIDGE_138}
+ ${explorerAddressLink(WETH9_BRIDGE_138, escapeHtml(WETH9_BRIDGE_138), 'color: inherit; text-decoration: none; font-size: 0.9rem;')}
- Token: WETH9
+ Token: ${explorerAddressLink('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', 'WETH9', 'color: inherit; text-decoration: none;')}
CCIPWETH10Bridge
- ${WETH10_BRIDGE_138}
+ ${explorerAddressLink(WETH10_BRIDGE_138, escapeHtml(WETH10_BRIDGE_138), 'color: inherit; text-decoration: none; font-size: 0.9rem;')}
- Token: WETH10
+ Token: ${explorerAddressLink('0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f', 'WETH10', 'color: inherit; text-decoration: none;')}
@@ -4315,8 +4315,8 @@
Transaction Count
@@ -4501,7 +4519,7 @@
const revertReason = t.revert_reason || (rawTx && (rawTx.revert_reason || rawTx.error || rawTx.result));
const inputHex = (t.input && t.input !== '0x') ? t.input : null;
const decodedInput = t.decoded_input || (rawTx && rawTx.decoded_input);
- const toCellContent = t.to ? formatAddressWithLabel(t.to) + '
' : 'N/A';
+ const toCellContent = t.to ? explorerAddressLink(t.to, formatAddressWithLabel(t.to), 'color: inherit; text-decoration: none;') + '
' : 'N/A';
let mainHtml = `
@@ -4533,7 +4551,7 @@
Block Number
-
${escapeHtml(String(t.block_number || 'N/A'))}
+
${explorerBlockLink(String(t.block_number || ''), escapeHtml(String(t.block_number || 'N/A')), 'color: inherit; text-decoration: none;')}
Block Hash
@@ -4541,11 +4559,11 @@
From
-
${formatAddressWithLabel(t.from || '')}
+
${explorerAddressLink(t.from || '', formatAddressWithLabel(t.from || ''), 'color: inherit; text-decoration: none;')}
To
-
${toCellContent}
+
${toCellContent}
Value
@@ -4569,7 +4587,7 @@
${t.tx_burnt_fee && parseInt(t.tx_burnt_fee) > 0 ? `
Burnt Fee
${burntFeeEth} ETH
` : ''}
- ${t.contract_address ? `
Contract Address
${escapeHtml(t.contract_address)}
` : ''}
+ ${t.contract_address ? `
Contract Address
${explorerAddressLink(t.contract_address, escapeHtml(t.contract_address), 'color: inherit; text-decoration: none;')}
` : ''}
`;
if (revertReason && t.status !== 1) {
@@ -4650,7 +4668,7 @@
const to = it.to?.hash || it.to || 'N/A';
const val = it.value ? formatEther(it.value) : '0';
const type = it.type || it.call_type || 'call';
- tbl += '
' + escapeHtml(type) + ' ' + escapeHtml(shortenHash(from)) + ' ' + escapeHtml(shortenHash(to)) + ' ' + escapeHtml(val) + ' ETH ';
+ tbl += '
' + escapeHtml(type) + ' ' + explorerAddressLink(from, escapeHtml(shortenHash(from)), 'color: inherit; text-decoration: none;') + ' ' + explorerAddressLink(to, escapeHtml(shortenHash(to)), 'color: inherit; text-decoration: none;') + ' ' + escapeHtml(val) + ' ETH ';
});
if (filteredInternals.length === 0) {
tbl += '
No internal transactions match the current filter. ';
@@ -4682,7 +4700,7 @@
const topics = (log.topics && Array.isArray(log.topics)) ? log.topics : (log.topic0 ? [log.topic0] : []);
const topicsStr = topics.join(', ');
const data = log.data || log.raw_data || '0x';
- tbl += '
' + escapeHtml(shortenHash(addr)) + ' ' + escapeHtml(String(topicsStr).substring(0, 80)) + (String(topicsStr).length > 80 ? '...' : '') + ' ' + escapeHtml(String(data).substring(0, 66)) + (String(data).length > 66 ? '...' : '') + ' — ';
+ tbl += '
' + explorerAddressLink(addr, escapeHtml(shortenHash(addr)), 'color: inherit; text-decoration: none;') + ' ' + escapeHtml(String(topicsStr).substring(0, 80)) + (String(topicsStr).length > 80 ? '...' : '') + ' ' + escapeHtml(String(data).substring(0, 66)) + (String(data).length > 66 ? '...' : '') + ' — ';
});
if (filteredLogs.length === 0) {
tbl += '
No event logs match the current filter. ';
@@ -4912,7 +4930,7 @@
Type
${a.is_contract ? 'Contract ' + verifiedBadge + (contractLink ? ' ' + contractLink : '') : 'EOA '}
- ${a.creation_tx_hash ? `
Contract created in
${escapeHtml(shortenHash(a.creation_tx_hash))}
` : ''}
+ ${a.creation_tx_hash ? `
Contract created in
${explorerTransactionLink(a.creation_tx_hash, escapeHtml(shortenHash(a.creation_tx_hash)), 'color: inherit; text-decoration: none;')}
` : ''}
${a.first_seen_at ? `
First seen
${escapeHtml(typeof a.first_seen_at === 'string' ? a.first_seen_at : new Date(a.first_seen_at).toISOString())}
` : ''}
${a.last_seen_at ? `
Last seen
${escapeHtml(typeof a.last_seen_at === 'string' ? a.last_seen_at : new Date(a.last_seen_at).toISOString())}
` : ''}
@@ -5013,7 +5031,7 @@
const divisor = Math.pow(10, parseInt(decimals, 10));
const displayBalance = (Number(balance) / divisor).toLocaleString(undefined, { maximumFractionDigits: 6 });
const type = token.type || b.token_type || 'ERC-20';
- tbl += '
' + escapeHtml(symbol) + ' ' + escapeHtml(shortenHash(contract)) + ' ' + escapeHtml(displayBalance) + ' ' + escapeHtml(type) + ' ';
+ tbl += '
' + escapeHtml(symbol) + ' ' + explorerAddressLink(contract, escapeHtml(shortenHash(contract)), 'color: inherit; text-decoration: none;') + ' ' + escapeHtml(displayBalance) + ' ' + escapeHtml(type) + ' ';
});
if (filteredItems.length === 0) {
tbl += '
No token balances match the current filter. ';
@@ -5063,7 +5081,7 @@
var tokenId = b.token_id != null ? b.token_id : (b.tokenId != null ? b.tokenId : (b.id != null ? b.id : '-'));
var name = token.name || token.symbol || '-';
var balance = b.value != null ? b.value : (b.balance != null ? b.balance : '1');
- tbl += '
' + escapeHtml(shortenHash(contract)) + ' ';
+ tbl += '' + explorerAddressLink(contract, escapeHtml(shortenHash(contract)), 'color: inherit; text-decoration: none;') + ' ';
tbl += '' + (tokenId !== '-' ? '' + escapeHtml(String(tokenId)) + ' ' : '-') + ' ';
tbl += '' + escapeHtml(name) + ' ' + escapeHtml(String(balance)) + ' ';
});
@@ -5108,7 +5126,7 @@
const val = it.value ? formatEther(it.value) : '0';
const block = it.block_number || it.block || '-';
const txHash = it.transaction_hash || it.tx_hash || '-';
- tbl += '
' + escapeHtml(block) + ' ' + escapeHtml(shortenHash(from)) + ' ' + escapeHtml(shortenHash(to)) + ' ' + escapeHtml(val) + ' ETH ' + (txHash !== '-' ? escapeHtml(shortenHash(txHash)) : '-') + ' ';
+ tbl += '
' + explorerBlockLink(block, escapeHtml(block), 'color: inherit; text-decoration: none;') + ' ' + explorerAddressLink(from, escapeHtml(shortenHash(from)), 'color: inherit; text-decoration: none;') + ' ' + explorerAddressLink(to, escapeHtml(shortenHash(to)), 'color: inherit; text-decoration: none;') + ' ' + escapeHtml(val) + ' ETH ' + (txHash !== '-' ? explorerTransactionLink(txHash, escapeHtml(shortenHash(txHash)), 'color: inherit; text-decoration: none;') : '-') + ' ';
});
if (filteredItems.length === 0) {
tbl += '
No internal transactions match the current filter. ';
@@ -5312,7 +5330,7 @@
}) : txs.data;
let txHtml = filterBar + '
Hash Block From To Value ';
filteredTxs.forEach(function(tx) {
- txHtml += '' + escapeHtml(shortenHash(tx.hash)) + ' ' + escapeHtml(String(tx.block_number)) + ' ' + formatAddressWithLabel(tx.from) + ' ' + (tx.to ? formatAddressWithLabel(tx.to) : 'N/A') + ' ' + escapeHtml(formatEther(tx.value || '0')) + ' ETH ';
+ txHtml += '' + explorerTransactionLink(tx.hash, escapeHtml(shortenHash(tx.hash)), 'color: inherit; text-decoration: none;') + ' ' + explorerBlockLink(String(tx.block_number), escapeHtml(String(tx.block_number)), 'color: inherit; text-decoration: none;') + ' ' + explorerAddressLink(tx.from, formatAddressWithLabel(tx.from), 'color: inherit; text-decoration: none;') + ' ' + (tx.to ? explorerAddressLink(tx.to, formatAddressWithLabel(tx.to), 'color: inherit; text-decoration: none;') : 'N/A') + ' ' + escapeHtml(formatEther(tx.value || '0')) + ' ETH ';
});
if (filteredTxs.length === 0) {
txHtml += 'No transactions match the current filter. ';
@@ -5380,7 +5398,7 @@
var addrEsc = tokenAddress.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
var symbolEsc = String(symbol).replace(/\\/g, '\\\\').replace(/'/g, "\\'");
var html = ' Add to wallet (MetaMask)
';
- html += 'Contract
' + escapeHtml(tokenAddress) + '
';
+ html += 'Contract
' + explorerAddressLink(tokenAddress, escapeHtml(tokenAddress), 'color: inherit; text-decoration: none;') + '
';
html += 'Name
' + escapeHtml(name) + '
';
html += 'Symbol
' + escapeHtml(symbol) + '
';
html += '';
@@ -5409,7 +5427,7 @@
var dec = tr.token?.decimals != null ? tr.token.decimals : decimals;
var v = Number(val) / Math.pow(10, parseInt(dec, 10));
var txHash = tr.transaction_hash || tr.tx_hash || '';
- html += '' + escapeHtml(shortenHash(from)) + ' ' + escapeHtml(shortenHash(to)) + ' ' + escapeHtml(v.toLocaleString(undefined, { maximumFractionDigits: 6 })) + ' ' + (txHash ? escapeHtml(shortenHash(txHash)) : '-') + ' ';
+ html += '' + explorerAddressLink(from, escapeHtml(shortenHash(from)), 'color: inherit; text-decoration: none;') + ' ' + explorerAddressLink(to, escapeHtml(shortenHash(to)), 'color: inherit; text-decoration: none;') + ' ' + escapeHtml(v.toLocaleString(undefined, { maximumFractionDigits: 6 })) + ' ' + (txHash ? explorerTransactionLink(txHash, escapeHtml(shortenHash(txHash)), 'color: inherit; text-decoration: none;') : '-') + ' ';
});
if (filteredTransfers.length === 0) {
html += 'No transfers match the current filter. ';
@@ -5442,7 +5460,7 @@
if (r) { data = r; break; }
} catch (e) {}
}
- var html = 'Contract
' + escapeHtml(contractAddress) + '
';
+ var html = 'Contract
' + explorerAddressLink(contractAddress, escapeHtml(contractAddress), 'color: inherit; text-decoration: none;') + '
';
html += 'Token ID
' + escapeHtml(String(tokenId)) + '
';
if (data) {
if (data.metadata && data.metadata.image) {
@@ -5450,7 +5468,7 @@
}
if (data.name) html += 'Name
' + escapeHtml(data.name) + '
';
if (data.description) html += 'Description
' + escapeHtml(data.description) + '
';
- if (data.owner) { var ownerAddr = (data.owner.hash || data.owner); html += 'Owner
' + escapeHtml(ownerAddr) + '
'; }
+ if (data.owner) { var ownerAddr = (data.owner.hash || data.owner); html += 'Owner
' + explorerAddressLink(ownerAddr, escapeHtml(ownerAddr), 'color: inherit; text-decoration: none;') + '
'; }
if (data.metadata && data.metadata.attributes && Array.isArray(data.metadata.attributes)) {
html += 'Traits
';
data.metadata.attributes.forEach(function(attr) {
@@ -5488,20 +5506,20 @@
if (item.address_hash || item.hash) {
addr = item.address_hash || item.hash;
if (/^0x[a-f0-9]{40}$/i.test(addr)) {
- html += '
Address ' + escapeHtml(shortenHash(addr)) + ' ';
+ html += '
Address ' + explorerAddressLink(addr, escapeHtml(shortenHash(addr)), 'color: inherit; text-decoration: none;') + ' ';
return;
}
}
if (item.tx_hash || (item.hash && item.hash.length === 66)) {
txHash = item.tx_hash || item.hash;
if (/^0x[a-f0-9]{64}$/i.test(txHash)) {
- html += '
Transaction ' + escapeHtml(shortenHash(txHash)) + ' ';
+ html += '
Transaction ' + explorerTransactionLink(txHash, escapeHtml(shortenHash(txHash)), 'color: inherit; text-decoration: none;') + ' ';
return;
}
}
if (item.block_number != null) {
blockNum = String(item.block_number);
- html += '
Block #' + escapeHtml(blockNum) + ' ';
+ html += '
Block ' + explorerBlockLink(blockNum, '#' + escapeHtml(blockNum), 'color: inherit; text-decoration: none;') + ' ';
return;
}
html += '
' + escapeHtml(type || 'Unknown') + ' ' + escapeHtml(String(label).substring(0, 80)) + ' ';
diff --git a/frontend/public/index.html b/frontend/public/index.html
index aeee489..be3f053 100644
--- a/frontend/public/index.html
+++ b/frontend/public/index.html
@@ -1200,7 +1200,7 @@
WETH9 Token
@@ -1250,7 +1250,7 @@
WETH10 Token
@@ -1307,8 +1307,8 @@
Contract Addresses
How to Use