From 51b9b7458b3fb1f8f038d75e3b6bbb081ebcd3e7 Mon Sep 17 00:00:00 2001 From: defiQUG Date: Tue, 3 Mar 2026 21:12:52 -0800 Subject: [PATCH] fix(token-aggregation): resolve TypeScript build errors - token-mapping: use createRequire(proxmox package.json) and process.cwd(), drop import.meta to allow commonjs build - Add routes/bridge.ts stub (status + metrics) so server.ts import resolves - Add config/cross-chain-bridges.ts with BridgeConfig/BridgeLane and CHAIN_138_BRIDGES from env - cross-chain-indexer: import BridgeLane, add explicit types for .find/.map callbacks, bridgeType fallback to b.type Made-with: Cursor --- .../src/api/routes/bridge.ts | 26 +++++++ .../src/api/routes/token-mapping.ts | 10 +-- .../src/config/cross-chain-bridges.ts | 77 +++++++++++++++++++ .../src/indexer/cross-chain-indexer.ts | 14 ++-- 4 files changed, 114 insertions(+), 13 deletions(-) create mode 100644 services/token-aggregation/src/api/routes/bridge.ts create mode 100644 services/token-aggregation/src/config/cross-chain-bridges.ts diff --git a/services/token-aggregation/src/api/routes/bridge.ts b/services/token-aggregation/src/api/routes/bridge.ts new file mode 100644 index 0000000..52f9447 --- /dev/null +++ b/services/token-aggregation/src/api/routes/bridge.ts @@ -0,0 +1,26 @@ +/** + * Bridge API: cross-chain bridge status and metrics. + * GET /api/v1/bridge/status, /api/v1/bridge/metrics — stubbed or delegated to cross-chain report. + */ + +import { Router, Request, Response } from 'express'; + +const router: Router = Router(); + +router.get('/status', (_req: Request, res: Response) => { + res.json({ + ok: true, + bridges: [], + message: 'Bridge status: use /api/v1/report/cross-chain for volume/lanes.', + }); +}); + +router.get('/metrics', (_req: Request, res: Response) => { + res.json({ + ok: true, + lanes: [], + message: 'Bridge metrics: use /api/v1/report/cross-chain for aggregated data.', + }); +}); + +export default router; diff --git a/services/token-aggregation/src/api/routes/token-mapping.ts b/services/token-aggregation/src/api/routes/token-mapping.ts index 60484ae..2152751 100644 --- a/services/token-aggregation/src/api/routes/token-mapping.ts +++ b/services/token-aggregation/src/api/routes/token-mapping.ts @@ -6,17 +6,15 @@ import { Router, Request, Response } from 'express'; import path from 'path'; -import { fileURLToPath } from 'url'; import { createRequire } from 'module'; import { cacheMiddleware } from '../middleware/cache'; const router: Router = Router(); -const require = createRequire(import.meta.url); -const __dirname = path.dirname(fileURLToPath(import.meta.url)); -/** Resolve path to repo root (proxmox) from token-aggregation src/api/routes -> 5 levels up */ -const PROXMOX_ROOT = path.resolve(__dirname, '../../../../../'); +/** Repo root (proxmox): when run from token-aggregation cwd, 2 levels up to smom-dbis-138, 1 more to proxmox */ +const PROXMOX_ROOT = path.resolve(process.cwd(), '../../..'); const LOADER_PATH = path.join(PROXMOX_ROOT, 'config', 'token-mapping-loader.cjs'); +const requireLoader = createRequire(path.join(PROXMOX_ROOT, 'package.json')); function loadMultichainLoader(): { getTokenMappingForPair: (from: number, to: number) => { tokens: unknown[]; addressMapFromTo: Record; addressMapToFrom: Record } | null; @@ -24,7 +22,7 @@ function loadMultichainLoader(): { getMappedAddress: (from: number, to: number, addr: string) => string | undefined; } | null { try { - const loader = require(LOADER_PATH); + const loader = requireLoader(LOADER_PATH); if (loader?.getTokenMappingForPair && loader?.getAllMultichainPairs && loader?.getMappedAddress) { return loader; } diff --git a/services/token-aggregation/src/config/cross-chain-bridges.ts b/services/token-aggregation/src/config/cross-chain-bridges.ts new file mode 100644 index 0000000..c00ec33 --- /dev/null +++ b/services/token-aggregation/src/config/cross-chain-bridges.ts @@ -0,0 +1,77 @@ +/** + * Cross-chain bridge config for Chain 138 (and optional 651940). + * Used by cross-chain-indexer for CCIP/Alltra/UniversalCCIP event aggregation. + */ + +export interface BridgeLane { + destSelector: string; + destChainId: number; + destChainName: string; + bridgeType?: string; +} + +export interface BridgeConfig { + address: string; + chainId: number; + type: 'ccip_weth9' | 'ccip_weth10' | 'alltra' | 'universal_ccip'; + tokenSymbol?: string; + lanes: BridgeLane[]; +} + +/** Chain 138 bridge addresses from env; lanes can be extended per deployment. */ +const chainId138 = 138; + +function envAddr(key: string): string { + const v = process.env[key]; + return typeof v === 'string' && v.startsWith('0x') ? v : ''; +} + +export const CHAIN_138_BRIDGES: BridgeConfig[] = []; + +if (envAddr('CCIPWETH9_BRIDGE_CHAIN138')) { + CHAIN_138_BRIDGES.push({ + address: envAddr('CCIPWETH9_BRIDGE_CHAIN138'), + chainId: chainId138, + type: 'ccip_weth9', + tokenSymbol: 'WETH', + lanes: [ + { destSelector: '5009297550715157269', destChainId: 1, destChainName: 'Ethereum' }, + { destSelector: '16015286601757825753', destChainId: 651940, destChainName: 'ALL Mainnet' }, + ], + }); +} + +if (envAddr('CCIPWETH10_BRIDGE_CHAIN138')) { + CHAIN_138_BRIDGES.push({ + address: envAddr('CCIPWETH10_BRIDGE_CHAIN138'), + chainId: chainId138, + type: 'ccip_weth10', + tokenSymbol: 'WETH', + lanes: [ + { destSelector: '5009297550715157269', destChainId: 1, destChainName: 'Ethereum' }, + { destSelector: '16015286601757825753', destChainId: 651940, destChainName: 'ALL Mainnet' }, + ], + }); +} + +if (envAddr('ALLTRA_CUSTOM_BRIDGE_ADDRESS') || envAddr('ALLTRA_ADAPTER_ADDRESS')) { + const addr = envAddr('ALLTRA_CUSTOM_BRIDGE_ADDRESS') || envAddr('ALLTRA_ADAPTER_ADDRESS'); + CHAIN_138_BRIDGES.push({ + address: addr, + chainId: chainId138, + type: 'alltra', + lanes: [{ destSelector: '0', destChainId: 651940, destChainName: 'ALL Mainnet' }], + }); +} + +if (envAddr('UNIVERSAL_CCIP_BRIDGE_ADDRESS')) { + CHAIN_138_BRIDGES.push({ + address: envAddr('UNIVERSAL_CCIP_BRIDGE_ADDRESS'), + chainId: chainId138, + type: 'universal_ccip', + lanes: [ + { destSelector: '5009297550715157269', destChainId: 1, destChainName: 'Ethereum' }, + { destSelector: '16015286601757825753', destChainId: 651940, destChainName: 'ALL Mainnet' }, + ], + }); +} diff --git a/services/token-aggregation/src/indexer/cross-chain-indexer.ts b/services/token-aggregation/src/indexer/cross-chain-indexer.ts index 0f4f562..00b80ca 100644 --- a/services/token-aggregation/src/indexer/cross-chain-indexer.ts +++ b/services/token-aggregation/src/indexer/cross-chain-indexer.ts @@ -6,7 +6,7 @@ import { ethers } from 'ethers'; import { getChainConfig } from '../config/chains'; -import { CHAIN_138_BRIDGES, BridgeConfig } from '../config/cross-chain-bridges'; +import { CHAIN_138_BRIDGES, BridgeConfig, BridgeLane } from '../config/cross-chain-bridges'; export interface CrossChainEvent { txHash: string; @@ -104,7 +104,7 @@ async function fetchCCIPEvents( for (const log of logs) { const args = (log as ethers.EventLog).args as unknown as { messageId: string; sender: string; destinationChainSelector: bigint; recipient: string; amount: bigint }; - const lane = bridge.lanes.find((l) => l.destSelector === args.destinationChainSelector?.toString()); + const lane = bridge.lanes.find((l: BridgeLane) => l.destSelector === args.destinationChainSelector?.toString()); const destChainId = lane?.destChainId ?? 0; const destChainName = lane?.destChainName ?? `Chain ${args.destinationChainSelector}`; @@ -253,7 +253,7 @@ async function fetchUniversalCCIPEvents( for (const log of logs) { const args = (log as ethers.EventLog).args as unknown as { messageId: string; token: string; sender: string; amount: bigint; destinationChain: bigint; recipient: string }; const selector = args.destinationChain?.toString(); - const lane = bridge.lanes.find((l) => l.destSelector === selector); + const lane = bridge.lanes.find((l: BridgeLane) => l.destSelector === selector); const destChainId = lane?.destChainId ?? (selector === '5009297550715157269' ? 1 : 651940); const destChainName = lane?.destChainName ?? `Chain ${selector}`; @@ -379,7 +379,7 @@ export async function buildCrossChainReport(chainId: number = 138): Promise b.chainId === chainId); + const bridges = CHAIN_138_BRIDGES.filter((b: BridgeConfig) => b.chainId === chainId); for (const bridge of bridges) { if (bridge.type === 'ccip_weth9' || bridge.type === 'ccip_weth10') { @@ -406,15 +406,15 @@ export async function buildCrossChainReport(chainId: number = 138): Promise - b.lanes.map((lane) => ({ + const crossChainPools = bridges.map((b: BridgeConfig) => + b.lanes.map((lane: BridgeLane) => ({ type: b.type, sourceChainId: b.chainId, destChainId: lane.destChainId, destChainName: lane.destChainName, bridgeAddress: b.address, tokenSymbol: b.tokenSymbol, - bridgeType: lane.bridgeType, + bridgeType: lane.bridgeType ?? b.type, isActive: true, })) ).flat();