Files
smom-dbis-138/services/token-aggregation/public/chain138-attestation/overlay.js
defiQUG d54882cd0f
Some checks failed
CI/CD Pipeline / Solidity Contracts (push) Failing after 1m12s
CI/CD Pipeline / Security Scanning (push) Successful in 2m38s
CI/CD Pipeline / Lint and Format (push) Failing after 40s
CI/CD Pipeline / Terraform Validation (push) Failing after 21s
CI/CD Pipeline / Kubernetes Validation (push) Successful in 24s
HYBX OMNL TypeScript & anchor / token-aggregation build + reconcile artifact (push) Failing after 24s
Validation / validate-genesis (push) Successful in 26s
Validation / validate-terraform (push) Failing after 21s
Validation / validate-kubernetes (push) Failing after 9s
Validation / validate-smart-contracts (push) Failing after 9s
Validation / validate-security (push) Failing after 1m7s
Validation / validate-documentation (push) Failing after 15s
feat(checkpoint): expose mainnet Etherscan links on Chain 138 tx attestation.
Resolve etherscanLinks from batch metadata and optional mainnet log scans; serve a fast local-batch attestation path for the explorer CT.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-08 08:13:59 -07:00

155 lines
4.7 KiB
JavaScript

(function () {
'use strict';
window.__CHAIN138_ATTESTATION_OVERLAY__ = '1.0.0';
var API_BASE = '/api/v1/checkpoint/tx';
var PANEL_ID = 'chain138-mainnet-attestation-panel';
var lastHash = '';
function txHashFromPath() {
var m = window.location.pathname.match(/\/(?:transactions|tx)\/(0x[a-fA-F0-9]{64})\/?$/);
return m ? m[1] : null;
}
function shortHash(hash) {
return hash.slice(0, 10) + '…' + hash.slice(-8);
}
function ensurePanel() {
var existing = document.getElementById(PANEL_ID);
if (existing) return existing;
var panel = document.createElement('div');
panel.id = PANEL_ID;
panel.setAttribute('data-chain138-attestation', '1');
document.body.appendChild(panel);
return panel;
}
function watchPanel() {
if (window.__CHAIN138_ATTESTATION_WATCH__) return;
window.__CHAIN138_ATTESTATION_WATCH__ = 1;
var observer = new MutationObserver(function () {
if (!document.getElementById(PANEL_ID) && lastHash) {
loadAttestation(lastHash);
}
});
observer.observe(document.body, { childList: true, subtree: true });
}
function renderLoading(panel) {
panel.innerHTML =
'<div class="c138-card"><p class="c138-pending">Checking Ethereum mainnet attestation…</p></div>';
}
function renderNone(panel) {
panel.innerHTML = '';
}
function renderAttestation(panel, data) {
if (!data || !data.included) {
panel.innerHTML = '';
return;
}
var links = Array.isArray(data.etherscanLinks) ? data.etherscanLinks : [];
var batchId = data.batchId && data.batchId !== '0' ? data.batchId : null;
var usd = data.leaf && data.leaf.valueUsd ? data.leaf.valueUsd : data.batchTotalUsd;
var html = '<div class="c138-card">';
html += '<h2 class="c138-title">Ethereum mainnet attestation</h2>';
html +=
'<p class="c138-sub">This Chain 138 transaction is included in checkpoint batch' +
(batchId ? ' #' + batchId : '') +
(usd ? ' · USD ref ' + usd : '') +
'.</p>';
if (!links.length) {
html +=
'<p class="c138-pending">Attested on mainnet; Etherscan transaction links are indexing. Refresh in a minute or open the checkpoint contracts on Etherscan.</p>';
} else {
html += '<div class="c138-links">';
for (var i = 0; i < links.length; i++) {
var row = links[i];
html += '<div class="c138-link-row">';
html += '<span class="c138-layer">' + escapeHtml(row.label || row.layer || 'Mainnet') + '</span>';
html +=
'<a class="c138-etherscan" href="' +
escapeAttr(row.mainnetExplorerUrl) +
'" target="_blank" rel="noopener noreferrer">' +
escapeHtml(shortHash(row.mainnetTxHash)) +
' ↗</a>';
if (row.meta && row.meta.role) {
html += '<span class="c138-meta">role: ' + escapeHtml(row.meta.role) + '</span>';
}
if (row.meta && row.meta.uetr) {
html += '<span class="c138-meta">UETR: ' + escapeHtml(row.meta.uetr) + '</span>';
}
html += '</div>';
}
html += '</div>';
}
html += '</div>';
panel.innerHTML = html;
}
function escapeHtml(s) {
return String(s)
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;');
}
function escapeAttr(s) {
return escapeHtml(s).replace(/'/g, '&#39;');
}
function loadAttestation(txHash) {
if (!txHash) return;
var panel = ensurePanel();
var rendered = panel.getAttribute('data-tx-hash');
if (rendered === txHash && panel.querySelector('.c138-card')) return;
lastHash = txHash;
renderLoading(panel);
fetch(API_BASE + '/' + encodeURIComponent(txHash) + '/attestation', {
headers: { Accept: 'application/json' },
})
.then(function (r) {
return r.json();
})
.then(function (data) {
var active = document.getElementById(PANEL_ID) || ensurePanel();
renderAttestation(active, data);
if (data && data.included) active.setAttribute('data-tx-hash', txHash);
})
.catch(function () {
renderNone(panel);
lastHash = '';
});
}
function onRouteChange() {
var hash = txHashFromPath();
if (!hash) {
lastHash = '';
var panel = document.getElementById(PANEL_ID);
if (panel) panel.innerHTML = '';
return;
}
loadAttestation(hash);
}
function boot() {
watchPanel();
onRouteChange();
window.addEventListener('popstate', onRouteChange);
window.addEventListener('hashchange', onRouteChange);
setInterval(onRouteChange, 2000);
}
boot();
window.addEventListener('load', onRouteChange);
document.addEventListener('DOMContentLoaded', onRouteChange);
})();