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
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:
@@ -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')]));
|
||||
});
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user