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
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>
155 lines
4.7 KiB
JavaScript
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, '&')
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>')
|
|
.replace(/"/g, '"');
|
|
}
|
|
|
|
function escapeAttr(s) {
|
|
return escapeHtml(s).replace(/'/g, ''');
|
|
}
|
|
|
|
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);
|
|
})();
|