Files
smom-dbis-138/services/checkpoint-indexer/dist/txMainnetLinks.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

236 lines
9.5 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.linksFromBatchMeta = linksFromBatchMeta;
exports.resolveTxMainnetLinks = resolveTxMainnetLinks;
const ethers_1 = require("ethers");
const config_1 = require("./config");
const iso20022LogDecode_1 = require("./iso20022LogDecode");
const participantSurfaceLogDecode_1 = require("./participantSurfaceLogDecode");
const TRANSACTION_MIRRORED_TOPIC0 = '0xc25ce5062c7e42c68fa21fe088d21e609cc0c61b8bec3180681363bb5cf02a9e';
const PARTICIPANT_CREDITED_TOPIC0 = '0x853ebad0824f583553bcb4360a0df947d39654e86aba8d7c0625499cbf09f0d5';
const PARTICIPANT_DEBITED_TOPIC0 = '0xf122cad7c8ada37ddd6b6ddca0982b9f7be689cde15eedfd767cc207fa7dc2c8';
const CHECKPOINT_SUBMITTED_TOPIC0 = ethers_1.ethers.id('CheckpointSubmitted(uint64,uint256,bytes32,uint16,uint32,uint64,address,bytes32)');
const META_LAYER_MAP = [
{ key: 'hubTx', layer: 'checkpointHub', label: 'Checkpoint batch (hub)' },
{ key: 'mirrorTx', layer: 'transactionMirror', label: 'Transaction mirror' },
{ key: 'activityRegistryV1Tx', layer: 'activityRegistryV1', label: 'Activity registry V1' },
{ key: 'activityRegistryV2Tx', layer: 'activityRegistryV2', label: 'ISO-20022 PaymentAttested (V2)' },
{ key: 'participantSurfaceTx', layer: 'participantSurface', label: 'Participant surface' },
];
function linksFromBatchMeta(raw) {
const meta = raw?.mainnetAttestation;
if (!meta)
return [];
const links = [];
for (const row of META_LAYER_MAP) {
const hash = meta[row.key];
if (typeof hash === 'string' && /^0x[a-fA-F0-9]{64}$/.test(hash)) {
links.push({
layer: row.layer,
label: row.label,
mainnetTxHash: hash,
mainnetExplorerUrl: etherscanTx(hash),
});
}
}
if (Array.isArray(meta.participantTopLevelTxs)) {
for (const hash of meta.participantTopLevelTxs) {
if (!/^0x[a-fA-F0-9]{64}$/.test(hash))
continue;
links.push({
layer: 'participantWallet',
label: 'Participant wallet (0 ETH attestation tx)',
mainnetTxHash: hash,
mainnetExplorerUrl: etherscanTx(hash),
});
}
}
return links;
}
function etherscanTx(hash) {
return `https://etherscan.io/tx/${hash}`;
}
function logRows(logs) {
return logs.map((log) => ({
topics: log.topics,
transactionHash: log.transactionHash,
blockNumber: log.blockNumber.toString(),
logIndex: log.index.toString(),
data: log.data,
}));
}
function uniqLinks(links) {
const seen = new Set();
return links.filter((l) => {
const k = `${l.layer}:${l.mainnetTxHash}:${l.logIndex ?? ''}`;
if (seen.has(k))
return false;
seen.add(k);
return true;
});
}
const LOG_LOOKBACK_BLOCKS = parseInt(process.env.CHECKPOINT_MAINNET_LOGS_LOOKBACK || '120000', 10);
async function resolveFromBlock(provider, batchId) {
const head = await provider.getBlockNumber();
const fallback = Math.max(0, head - LOG_LOOKBACK_BLOCKS);
if (!batchId || batchId === '0' || !config_1.checkpointIndexerConfig.checkpointProxy)
return fallback;
try {
const batchTopic = ethers_1.ethers.zeroPadValue(ethers_1.ethers.toBeHex(BigInt(batchId)), 32);
const hubLogs = await provider.getLogs({
address: config_1.checkpointIndexerConfig.checkpointProxy,
fromBlock: fallback,
toBlock: 'latest',
topics: [CHECKPOINT_SUBMITTED_TOPIC0, batchTopic],
});
if (hubLogs.length) {
return Math.max(0, hubLogs[0].blockNumber - 10);
}
}
catch {
/* use fallback */
}
return fallback;
}
async function resolveTxMainnetLinks(provider, txHash, batchId) {
const links = [];
const want = txHash.toLowerCase();
const txTopic = ethers_1.ethers.zeroPadValue(txHash, 32);
const fromBlock = await resolveFromBlock(provider, batchId);
if (batchId && batchId !== '0' && config_1.checkpointIndexerConfig.checkpointProxy) {
try {
const batchTopic = ethers_1.ethers.zeroPadValue(ethers_1.ethers.toBeHex(BigInt(batchId)), 32);
const hubLogs = await provider.getLogs({
address: config_1.checkpointIndexerConfig.checkpointProxy,
fromBlock,
toBlock: 'latest',
topics: [CHECKPOINT_SUBMITTED_TOPIC0, batchTopic],
});
for (const log of hubLogs) {
links.push({
layer: 'checkpointHub',
label: `Checkpoint batch #${batchId}`,
mainnetTxHash: log.transactionHash,
mainnetExplorerUrl: etherscanTx(log.transactionHash),
contractAddress: config_1.checkpointIndexerConfig.checkpointProxy,
logIndex: log.index,
});
}
}
catch {
/* non-fatal — RPC may prune old logs */
}
}
try {
const mirrorLogs = await provider.getLogs({
address: config_1.checkpointIndexerConfig.legacyMirror,
fromBlock,
toBlock: 'latest',
topics: [TRANSACTION_MIRRORED_TOPIC0, txTopic],
});
for (const log of mirrorLogs) {
links.push({
layer: 'transactionMirror',
label: 'Transaction mirror',
mainnetTxHash: log.transactionHash,
mainnetExplorerUrl: etherscanTx(log.transactionHash),
contractAddress: config_1.checkpointIndexerConfig.legacyMirror,
logIndex: log.index,
});
}
}
catch {
/* non-fatal */
}
if (config_1.checkpointIndexerConfig.addressActivityRegistry) {
for (const [topic0, role] of [
[PARTICIPANT_CREDITED_TOPIC0, 'credited'],
[PARTICIPANT_DEBITED_TOPIC0, 'debited'],
]) {
try {
const regLogs = await provider.getLogs({
address: config_1.checkpointIndexerConfig.addressActivityRegistry,
fromBlock,
toBlock: 'latest',
topics: [topic0, txTopic],
});
for (const log of regLogs) {
links.push({
layer: 'activityRegistryV1',
label: `Activity registry V1 (${role})`,
mainnetTxHash: log.transactionHash,
mainnetExplorerUrl: etherscanTx(log.transactionHash),
contractAddress: config_1.checkpointIndexerConfig.addressActivityRegistry,
logIndex: log.index,
meta: { role },
});
}
}
catch {
/* non-fatal */
}
}
}
if (config_1.checkpointIndexerConfig.addressActivityRegistryV2) {
try {
const v2Logs = await provider.getLogs({
address: config_1.checkpointIndexerConfig.addressActivityRegistryV2,
fromBlock,
toBlock: 'latest',
topics: [iso20022LogDecode_1.PAYMENT_ATTESTED_TOPIC0, txTopic],
});
const decoded = (0, iso20022LogDecode_1.decodePaymentAttestedLogs)({ status: '1', result: logRows(v2Logs) });
for (const row of decoded) {
if (row.chain138TxHash.toLowerCase() !== want)
continue;
links.push({
layer: 'activityRegistryV2',
label: 'ISO-20022 PaymentAttested (V2)',
mainnetTxHash: row.mainnetTxHash,
mainnetExplorerUrl: row.mainnetExplorerUrl,
contractAddress: config_1.checkpointIndexerConfig.addressActivityRegistryV2,
logIndex: row.logIndex ? parseInt(row.logIndex, 10) : undefined,
meta: { instructionId: row.instructionId, uetr: row.uetr },
});
}
}
catch {
/* non-fatal */
}
}
if (config_1.checkpointIndexerConfig.participantSurface) {
try {
const surfaceLogs = await provider.getLogs({
address: config_1.checkpointIndexerConfig.participantSurface,
fromBlock,
toBlock: 'latest',
topics: [participantSurfaceLogDecode_1.CHAIN138_ACTIVITY_NOTIFIED_TOPIC0, null, txTopic],
});
const decoded = (0, participantSurfaceLogDecode_1.decodeChain138ActivityNotifiedLogs)({
status: '1',
result: logRows(surfaceLogs),
});
for (const row of decoded) {
if (row.chain138TxHash.toLowerCase() !== want)
continue;
links.push({
layer: 'participantSurface',
label: 'Participant surface notification',
mainnetTxHash: row.mainnetTxHash,
mainnetExplorerUrl: row.mainnetExplorerUrl,
contractAddress: config_1.checkpointIndexerConfig.participantSurface,
logIndex: row.logIndex ? parseInt(row.logIndex, 10) : undefined,
meta: {
participant: row.participant,
direction: String(row.direction),
},
});
}
}
catch {
/* non-fatal */
}
}
return uniqLinks(links);
}