fix(token-aggregation): merge live Uniswap V2 catalog TVL into CMC pool rows
Some checks failed
CI/CD Pipeline / Solidity Contracts (push) Failing after 1m5s
CI/CD Pipeline / Security Scanning (push) Successful in 2m27s
CI/CD Pipeline / Lint and Format (push) Failing after 36s
CI/CD Pipeline / Terraform Validation (push) Failing after 22s
CI/CD Pipeline / Kubernetes Validation (push) Successful in 26s
HYBX OMNL TypeScript & anchor / token-aggregation build + reconcile artifact (push) Failing after 50s
Validation / validate-genesis (push) Successful in 29s
Validation / validate-terraform (push) Failing after 28s
Validation / validate-kubernetes (push) Failing after 8s
Validation / validate-smart-contracts (push) Failing after 9s
Validation / validate-security (push) Failing after 1m11s
Validation / validate-documentation (push) Failing after 16s
Verify Deployment / Verify Deployment (push) Failing after 53s

Resolve pool catalog from multiple monorepo cwd layouts; prefer catalog
totalLiquidityUsd over lower DB/repo-fallback TVL. Extend CMC report tests
for cWUSDC pair liquidity assertions.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
defiQUG
2026-05-11 21:26:14 -07:00
parent 0f8476f493
commit c3ef31d8f3
2 changed files with 62 additions and 9 deletions

View File

@@ -121,6 +121,12 @@ describe('Report API', () => {
}),
});
expect(cwusdc.tracker_caveats).toEqual(expect.arrayContaining([expect.stringContaining('on-chain supply proof')]));
expect(cwusdc.liquidity_usd).toBeGreaterThan(1_000_000);
const cwusdcUsdc = cwusdc.pairs.find(
(p: Record<string, unknown>) =>
String(p.pair_address).toLowerCase() === '0xc28706f899266b36bc43cc072b3a921bdf2c48d9'
);
expect(cwusdcUsdc?.liquidity_usd).toBeGreaterThan(1_000_000);
});
});
@@ -154,8 +160,10 @@ describe('Report API', () => {
market_data: expect.objectContaining({
current_price: { usd: 1 },
market_cap: 10451316981.309788,
liquidity_usd: expect.any(Number),
}),
});
expect(cwusdc.market_data.liquidity_usd).toBeGreaterThan(1_000_000);
expect(cwusdc.tracker_caveats).toEqual(expect.arrayContaining([expect.stringContaining('No public tracker')]));
});

View File

@@ -164,15 +164,29 @@ function resolveRepoRoot(): string {
return process.cwd();
}
/** Directories that may contain `config/live-uniswap-v2-pool-catalog.json` (package cwd or monorepo layouts). */
function resolveLiveUniswapPoolCatalogRoots(): string[] {
const cwd = process.cwd();
const nestedTa = path.join(cwd, 'smom-dbis-138', 'services', 'token-aggregation');
const ordered = [
cwd,
...(existsSync(path.join(nestedTa, DEFAULT_LIVE_UNISWAP_V2_POOL_CATALOG_RELATIVE_PATH)) ? [nestedTa] : []),
path.resolve(cwd, '..', '..', '..'),
path.resolve(cwd, '..'),
process.env.PROXMOX_REPO_ROOT,
process.env.PROJECT_ROOT,
].filter(Boolean) as string[];
return [...new Set(ordered)];
}
function loadLiveUniswapV2PoolCatalog(): LiveUniswapV2PoolCatalogRow[] {
const configuredCatalog = process.env.TOKEN_AGGREGATION_LIVE_UNISWAP_V2_POOL_CATALOG_JSON?.trim();
const repoRoot = resolveRepoRoot();
const candidates = [
const catalogCandidates = [
configuredCatalog,
path.join(repoRoot, DEFAULT_LIVE_UNISWAP_V2_POOL_CATALOG_RELATIVE_PATH),
...resolveLiveUniswapPoolCatalogRoots().map((root) => path.join(root, DEFAULT_LIVE_UNISWAP_V2_POOL_CATALOG_RELATIVE_PATH)),
].filter(Boolean) as string[];
for (const candidate of candidates) {
for (const candidate of catalogCandidates) {
if (!existsSync(candidate)) continue;
try {
const parsed = JSON.parse(readFileSync(candidate, 'utf8')) as LiveUniswapV2PoolCatalog;
@@ -501,6 +515,29 @@ async function buildGruV2FallbackPoolsForToken(
return Promise.all(pools.map((pool) => enrichGruV2FallbackPoolWithReserves(chainId, pool)));
}
/** Prefer live catalog USD TVL when DB or repo-fallback rows carry the same pool with lower TVL. */
function mergeLiveUniswapCatalogTvlIntoPools(chainId: number, pools: ReportPoolEntry[]): ReportPoolEntry[] {
const catalog = loadLiveUniswapV2PoolCatalog();
const byPool = new Map(
catalog.filter((row) => row.chainId === chainId).map((row) => [row.poolAddress.toLowerCase(), row])
);
return pools.map((pool) => {
const row = byPool.get(pool.poolAddress.toLowerCase());
if (!row) return pool;
const catalogUsd = Number(row.totalLiquidityUsd ?? 0);
if (!Number.isFinite(catalogUsd) || catalogUsd <= (pool.tvl || 0)) {
return pool;
}
const note =
'Live Uniswap V2 pool catalog totalLiquidityUsd merged over lower indexed DB or repo-fallback TVL.';
return {
...pool,
tvl: catalogUsd,
statusReason: pool.statusReason ? `${pool.statusReason} ${note}` : note,
};
});
}
function buildLiveUniswapV2FallbackPoolsForToken(
chainId: number,
tokenAddress: string,
@@ -707,11 +744,16 @@ async function buildTokenReport(chainId: number) {
...dbPoolEntries,
...liveUniswapV2PoolEntries,
]);
const reportPools = [
const reportPools = mergeLiveUniswapCatalogTvlIntoPools(chainId, [
...dbPoolEntries,
...liveUniswapV2PoolEntries,
...gruV2FallbackPoolEntries,
];
]);
const poolTvlSum = reportPools.reduce((sum, p) => sum + (Number.isFinite(p.tvl) ? p.tvl : 0), 0);
if (market && poolTvlSum > (market.liquidityUsd ?? 0)) {
market.liquidityUsd = poolTvlSum;
}
out.push({
chainId,
@@ -1155,7 +1197,9 @@ router.get(
const chainId = parseInt(req.query.chainId as string, 10) || 138;
const tokens = await buildTokenReport(chainId);
const coingeckoFormat = tokens.map((t) => ({
const coingeckoFormat = tokens.map((t) => {
const poolTvlSum = t.pools.reduce((sum, p) => sum + (Number.isFinite(p.tvl) ? p.tvl : 0), 0);
return {
chain_id: chainId,
contract_address: t.address,
id: `${t.symbol.toLowerCase()}-${chainId}`,
@@ -1177,7 +1221,7 @@ router.get(
current_price: { usd: t.market.priceUsd },
total_volume: t.market.volume24h,
market_cap: t.market.marketCapUsd,
liquidity_usd: t.market.liquidityUsd,
liquidity_usd: Math.max(t.market.liquidityUsd ?? 0, poolTvlSum),
last_updated: t.market.lastUpdated,
}
: undefined,
@@ -1195,7 +1239,8 @@ router.get(
base_symbol: p.token0Symbol,
quote_symbol: p.token1Symbol,
})),
}));
};
});
const crossChainReport = await buildCrossChainReport(chainId).catch(() => null);