Files
smom-dbis-138/services/checkpoint-indexer/dist/server.js
defiQUG c336809676
Some checks failed
CI/CD Pipeline / Solidity Contracts (push) Failing after 1m3s
CI/CD Pipeline / Security Scanning (push) Successful in 2m18s
CI/CD Pipeline / Lint and Format (push) Failing after 34s
CI/CD Pipeline / Terraform Validation (push) Failing after 20s
CI/CD Pipeline / Kubernetes Validation (push) Successful in 22s
Deploy ChainID 138 / Deploy ChainID 138 (push) Failing after 40s
HYBX OMNL TypeScript & anchor / token-aggregation build + reconcile artifact (push) Failing after 49s
OMNL reconcile anchor / Run omnl:reconcile and upload artifacts (push) Failing after 21s
Validation / validate-genesis (push) Successful in 25s
Validation / validate-terraform (push) Failing after 21s
Validation / validate-kubernetes (push) Failing after 8s
Validation / validate-smart-contracts (push) Failing after 8s
Validation / validate-security (push) Failing after 1m11s
Validation / validate-documentation (push) Failing after 14s
Verify Deployment / Verify Deployment (push) Failing after 45s
Add mainnet checkpoint stack: ISO attestation, participant Etherscan surface, and services.
Ship AddressActivityRegistry V1/V2, ISO20022IntakeGateway, Chain138ParticipantSurface,
checkpoint hub contracts, checkpoint-core package, aggregator/indexer/sdk services,
relay profile guards, M00 diamond bridge facet, and OMNL compliance contracts.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-25 00:30:45 -07:00

343 lines
15 KiB
JavaScript

"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const express_1 = __importDefault(require("express"));
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const ethers_1 = require("ethers");
const config_1 = require("./config");
const tokenEnrich_1 = require("./tokenEnrich");
const checkpoint_core_1 = require("@dbis/checkpoint-core");
const merkle_1 = require("./merkle");
const serialize_1 = require("./serialize");
const addressIndex_1 = require("./addressIndex");
const etherscanV2Shim_1 = require("./etherscanV2Shim");
const chain138Explorer_1 = require("./chain138Explorer");
const CHECKPOINT_ABI = [
'function getLatestBatchId() view returns (uint64)',
'function latestCheckpointBlock() view returns (uint256)',
'function getLatestCheckpoint() view returns (tuple(uint64,uint64,uint64,uint256,uint256,uint256,bytes32,bytes32,bytes32,bytes32,uint16,uint32,uint64,address,bytes32))',
'function getCheckpoint(uint64) view returns (tuple(uint64,uint64,uint64,uint256,uint256,uint256,bytes32,bytes32,bytes32,bytes32,uint16,uint32,uint64,address,bytes32))',
'function isTxIncluded(bytes32) view returns (bool,uint64)',
];
const MIRROR_ABI = ['function getMirroredTransactionCount() view returns (uint256)'];
const app = (0, express_1.default)();
const mainnet = new ethers_1.ethers.JsonRpcProvider(config_1.checkpointIndexerConfig.mainnetRpc);
const chain138 = new ethers_1.ethers.JsonRpcProvider(config_1.checkpointIndexerConfig.chain138Rpc);
const hub = config_1.checkpointIndexerConfig.checkpointProxy ? new ethers_1.ethers.Contract(config_1.checkpointIndexerConfig.checkpointProxy, CHECKPOINT_ABI, mainnet) : null;
const mirror = new ethers_1.ethers.Contract(config_1.checkpointIndexerConfig.legacyMirror, MIRROR_ABI, mainnet);
let addressIndexCache = null;
let addressIndexBuiltAt = 0;
const ADDRESS_INDEX_TTL_MS = 60_000;
function getAddressIndex() {
const now = Date.now();
if (!addressIndexCache || now - addressIndexBuiltAt > ADDRESS_INDEX_TTL_MS) {
addressIndexCache = (0, addressIndex_1.buildAddressIndex)(config_1.checkpointIndexerConfig.batchPayloadDir);
addressIndexBuiltAt = now;
}
return addressIndexCache;
}
function loadBatchPayload(batchId) {
const p = path.join(config_1.checkpointIndexerConfig.batchPayloadDir, `batch-${batchId}.json`);
if (!fs.existsSync(p))
return null;
return JSON.parse(fs.readFileSync(p, 'utf8'));
}
async function payloadWithEnrichedLeaves(batchId, raw) {
if (!raw?.leaves?.length)
return raw;
const chainId = raw.chainId ?? 138;
let leaves = raw.leaves;
if (config_1.checkpointIndexerConfig.enrichTokenTransfers || config_1.checkpointIndexerConfig.usdEnrichEnabled) {
leaves = await (0, tokenEnrich_1.enrichLeaves)(leaves, config_1.checkpointIndexerConfig.blockscoutApi);
}
const hashes = leaves.map((l) => (0, merkle_1.paymentLeafHash)(chainId, {
txHash: String(l.txHash),
from: String(l.from),
to: String(l.to),
value: String(l.value ?? '0'),
nativeValueWei: l.nativeValueWei != null ? String(l.nativeValueWei) : undefined,
onChainValueWei: l.onChainValueWei != null ? String(l.onChainValueWei) : undefined,
tokenValue: l.tokenValue != null ? String(l.tokenValue) : undefined,
blockNumber: Number(l.blockNumber),
blockTimestamp: Number(l.blockTimestamp),
gasUsed: String(l.gasUsed ?? '0'),
success: Boolean(l.success),
}));
const { root, proofs } = (0, merkle_1.merkleProofs)(hashes);
const leavesWithProofs = leaves.map((l, i) => ({
...l,
leafHash: hashes[i],
merkleProof: proofs[i],
}));
return {
...raw,
batchId: raw.batchId ?? batchId,
leaves: leavesWithProofs,
merkleRootComputed: root,
merkleRootMatches: raw.paymentsRoot ? root.toLowerCase() === String(raw.paymentsRoot).toLowerCase() : null,
walletAttestationCopy: 'Balances and payments as of Chain 138 checkpoint block in this batch, attested on Ethereum mainnet.',
};
}
app.get('/health', (_req, res) => {
res.json({ ok: true, proxy: config_1.checkpointIndexerConfig.checkpointProxy || null, batchDir: config_1.checkpointIndexerConfig.batchPayloadDir });
});
/** Etherscan V2 supplement for Chain 138 (unsupported on official chainlist). */
app.get('/v2/chainlist-supplement', etherscanV2Shim_1.chainlistSupplement);
app.get('/v2/api', (req, res) => {
void (0, etherscanV2Shim_1.etherscanV2Api)(req, res);
});
/** Public batch JSON for contentURI resolution (CHECKPOINT_PAYLOAD_PUBLIC_URL). */
app.get('/v1/payload/batch-:batchId.json', (req, res) => {
const raw = loadBatchPayload(req.params.batchId);
if (!raw)
return res.status(404).json({ error: 'batch not found' });
res.type('json').send(JSON.stringify(raw, null, 2));
});
app.get('/v1/checkpoint/latest', async (_req, res) => {
if (!hub)
return res.status(503).json({ error: 'CHAIN138_MAINNET_CHECKPOINT_PROXY not set' });
try {
const batchId = await hub.getLatestBatchId();
const header = await hub.getLatestCheckpoint();
let v1Count = 0n;
try {
v1Count = await mirror.getMirroredTransactionCount();
}
catch {
v1Count = 0n;
}
const raw = batchId > 0n ? loadBatchPayload(batchId.toString()) : null;
const payload = raw ? await payloadWithEnrichedLeaves(batchId.toString(), raw) : null;
res.json({
source: 'v2',
batchId: batchId.toString(),
header: (0, serialize_1.jsonSafe)(header),
legacy: { mirrorCount: v1Count.toString(), tether: config_1.checkpointIndexerConfig.legacyTether },
payload,
});
}
catch (e) {
res.status(500).json({ error: String(e) });
}
});
app.get('/v1/checkpoint/:batchId', async (req, res) => {
if (!hub)
return res.status(503).json({ error: 'proxy not set' });
try {
const batchId = req.params.batchId;
const header = await hub.getCheckpoint(BigInt(batchId));
const raw = loadBatchPayload(batchId);
const payload = raw ? await payloadWithEnrichedLeaves(batchId, raw) : null;
res.json({ batchId, header: (0, serialize_1.jsonSafe)(header), payload });
}
catch (e) {
res.status(500).json({ error: String(e) });
}
});
app.get('/v1/tx/:txHash/attestation', async (req, res) => {
if (!hub)
return res.status(503).json({ error: 'proxy not set' });
try {
const txHash = req.params.txHash;
const [included, batchId] = await hub.isTxIncluded(txHash);
const raw = included && batchId > 0n ? loadBatchPayload(batchId.toString()) : null;
const payload = raw ? await payloadWithEnrichedLeaves(batchId.toString(), raw) : null;
res.json({ txHash, included, batchId: batchId.toString(), payload });
}
catch (e) {
res.status(500).json({ error: String(e) });
}
});
/** Wallet helper: verify leaf against on-chain hub (client may also use @dbis/checkpoint-sdk). */
app.get('/v1/checkpoint/:batchId/verify/:leafIndex', async (req, res) => {
if (!hub)
return res.status(503).json({ error: 'proxy not set' });
try {
const batchId = req.params.batchId;
const leafIndex = parseInt(req.params.leafIndex, 10);
const raw = loadBatchPayload(batchId);
if (!raw?.leaves?.length || leafIndex < 0 || leafIndex >= raw.leaves.length) {
return res.status(404).json({ error: 'leaf not found' });
}
const payload = await payloadWithEnrichedLeaves(batchId, raw);
const leaves = payload.leaves;
const leaf = leaves?.[leafIndex];
if (!leaf || !leaf.merkleProof) {
return res.status(404).json({ error: 'proof missing' });
}
const VERIFY_ABI = [
'function verifyPaymentInBatch(uint64 batchId, tuple(bytes32,address,address,uint256,uint256,uint64,uint256,bool) leaf, bytes32[] proof) view returns (bool)',
];
const verifyHub = new ethers_1.ethers.Contract(config_1.checkpointIndexerConfig.checkpointProxy, VERIFY_ABI, mainnet);
const l = leaf;
const ok = await verifyHub.verifyPaymentInBatch(BigInt(batchId), [
l.txHash,
l.from,
l.to,
(0, checkpoint_core_1.merkleVerifyValueWei)(l),
BigInt(String(l.blockNumber)),
BigInt(String(l.blockTimestamp)),
BigInt(String(l.gasUsed ?? 0)),
Boolean(l.success),
], l.merkleProof);
res.json({ batchId, leafIndex, verified: ok, leaf });
}
catch (e) {
res.status(500).json({ error: String(e) });
}
});
app.get('/v1/account/:address', async (req, res) => {
try {
const addr = req.params.address;
let blockTag = 'latest';
if (req.query.atBatch) {
if (!hub)
return res.status(503).json({ error: 'proxy not set' });
const h = await hub.getCheckpoint(BigInt(String(req.query.atBatch)));
blockTag = Number(h.checkpointBlock);
}
else if (hub) {
blockTag = Number(await hub.latestCheckpointBlock());
}
const balance = await chain138.getBalance(addr, blockTag);
const index = getAddressIndex();
const rows = index.byAddress[addr.toLowerCase()] ?? [];
const activity = (0, addressIndex_1.summarizeAddressActivity)(rows);
res.json({
address: addr,
chainId: 138,
blockTag,
balanceWei: balance.toString(),
attestedActivity: activity,
mainnetSurfaces: {
transactionMirror: config_1.checkpointIndexerConfig.legacyMirror,
addressActivityRegistry: config_1.checkpointIndexerConfig.addressActivityRegistry || null,
checkpointHub: config_1.checkpointIndexerConfig.checkpointProxy || null,
},
walletAttestationCopy: 'Native balance as of Chain 138 checkpoint block. Attested payments (ETH + USD) via checkpoint batches on Ethereum mainnet.',
});
}
catch (e) {
res.status(500).json({ error: String(e) });
}
});
app.get('/v1/account/:address/transactions', async (req, res) => {
try {
const addr = req.params.address;
const limit = Math.min(parseInt(String(req.query.limit ?? '50'), 10) || 50, 200);
const offset = parseInt(String(req.query.offset ?? '0'), 10) || 0;
const index = getAddressIndex();
const { total, items } = (0, addressIndex_1.getAddressTransactions)(index, addr, limit, offset);
res.json({
address: addr,
chainId: 138,
total,
limit,
offset,
items,
indexMeta: {
builtAt: index.builtAt,
batchCount: index.batchCount,
txCount: index.txCount,
},
});
}
catch (e) {
res.status(500).json({ error: String(e) });
}
});
app.get('/v1/account/:address/activity', async (req, res) => {
try {
const addr = req.params.address;
const index = getAddressIndex();
const rows = index.byAddress[addr.toLowerCase()] ?? [];
const summary = (0, addressIndex_1.summarizeAddressActivity)(rows);
res.json({
address: addr,
chainId: 138,
summary,
recent: rows.slice(0, 25).map((r) => ({
...r,
chain138ExplorerUrl: (0, chain138Explorer_1.chain138ExplorerTxUrl)(r.txHash),
})),
chain138Explorer: {
base: (0, chain138Explorer_1.chain138ExplorerBase)(),
txUrlTemplate: `${(0, chain138Explorer_1.chain138ExplorerBase)()}/tx/{txHash}`,
},
etherscan: {
transactionMirrorEvents: `https://etherscan.io/address/${config_1.checkpointIndexerConfig.legacyMirror}#events`,
addressActivityEvents: config_1.checkpointIndexerConfig.addressActivityRegistry
? `https://etherscan.io/address/${config_1.checkpointIndexerConfig.addressActivityRegistry}#events`
: null,
},
});
}
catch (e) {
res.status(500).json({ error: String(e) });
}
});
app.get('/v1/tx/:txHash/logs', async (req, res) => {
try {
const txHash = req.params.txHash;
const receipt = await chain138.getTransactionReceipt(txHash);
if (!receipt)
return res.status(404).json({ error: 'receipt not found on chain 138' });
res.json({
txHash,
chainId: 138,
blockNumber: receipt.blockNumber,
status: receipt.status,
gasUsed: receipt.gasUsed.toString(),
logCount: receipt.logs.length,
logs: receipt.logs.map((log, i) => ({
index: i,
address: log.address,
topics: log.topics,
data: log.data,
})),
});
}
catch (e) {
res.status(500).json({ error: String(e) });
}
});
app.listen(config_1.checkpointIndexerConfig.port, () => {
console.log(`checkpoint-indexer listening on :${config_1.checkpointIndexerConfig.port}`);
});