Some checks failed
CI/CD Pipeline / Solidity Contracts (push) Failing after 1m25s
CI/CD Pipeline / Security Scanning (push) Successful in 3m28s
CI/CD Pipeline / Lint and Format (push) Failing after 43s
CI/CD Pipeline / Terraform Validation (push) Failing after 25s
CI/CD Pipeline / Kubernetes Validation (push) Successful in 28s
Deploy ChainID 138 / Deploy ChainID 138 (push) Failing after 45s
HYBX OMNL TypeScript & anchor / token-aggregation build + reconcile artifact (push) Failing after 29s
Validation / validate-genesis (push) Successful in 32s
Validation / validate-terraform (push) Failing after 30s
Validation / validate-kubernetes (push) Failing after 10s
Validation / validate-smart-contracts (push) Failing after 10s
Validation / validate-security (push) Failing after 1m36s
Validation / validate-documentation (push) Failing after 17s
Verify Deployment / Verify Deployment (push) Failing after 48s
Wire live 0x2BBe3c… address into canonical tokens, pool catalog merge from mesh health, and bridge/cWBTC explorer verification helpers. Co-authored-by: Cursor <cursoragent@cursor.com>
259 lines
9.0 KiB
TypeScript
259 lines
9.0 KiB
TypeScript
import fs from 'fs';
|
|
import path from 'path';
|
|
|
|
type DiscoveryPayload = {
|
|
generated_at?: string;
|
|
entries?: Array<{
|
|
chain_id: number;
|
|
network?: string;
|
|
factoryAddress?: string;
|
|
routerAddress?: string;
|
|
pairsChecked?: Array<{
|
|
base: string;
|
|
quote: string;
|
|
poolAddress: string;
|
|
live: boolean;
|
|
health?: {
|
|
baseReserveRaw?: string;
|
|
quoteReserveRaw?: string;
|
|
baseReserveUnits?: string;
|
|
quoteReserveUnits?: string;
|
|
priceQuotePerBase?: string;
|
|
deviationBps?: string;
|
|
healthy?: boolean;
|
|
depthOk?: boolean;
|
|
parityOk?: boolean;
|
|
};
|
|
}>;
|
|
}>;
|
|
};
|
|
|
|
type DeploymentStatusChain = {
|
|
name?: string;
|
|
cwTokens?: Record<string, string>;
|
|
anchorAddresses?: Record<string, string>;
|
|
gasMirrors?: Record<string, string>;
|
|
gasQuoteAddresses?: Record<string, string>;
|
|
};
|
|
|
|
type DeploymentStatus = {
|
|
chains?: Record<string, DeploymentStatusChain>;
|
|
};
|
|
|
|
const PRICE_USD: Record<string, number> = {
|
|
USDC: 1,
|
|
USDT: 1,
|
|
cUSDC: 1,
|
|
cUSDT: 1,
|
|
cWUSDC: 1,
|
|
cWUSDT: 1,
|
|
cWAUSDT: 1,
|
|
BTC: Number(process.env.CANONICAL_PRICE_USD_BTC || process.env.BTC_PRICE_USD || 90000),
|
|
cWBTC: Number(process.env.CANONICAL_PRICE_USD_BTC || process.env.BTC_PRICE_USD || 90000),
|
|
};
|
|
|
|
function findRepoRoot(): string {
|
|
const candidates = [
|
|
process.env.PROXMOX_REPO_ROOT,
|
|
process.env.PROJECT_ROOT,
|
|
path.resolve(process.cwd(), '..', '..', '..'),
|
|
path.resolve(process.cwd(), '..'),
|
|
process.cwd(),
|
|
].filter(Boolean) as string[];
|
|
|
|
for (const candidate of candidates) {
|
|
if (fs.existsSync(path.join(candidate, 'reports/extraction/promod-uniswap-v2-live-pair-discovery-latest.json'))) {
|
|
return candidate;
|
|
}
|
|
}
|
|
return path.resolve(process.cwd(), '..', '..', '..');
|
|
}
|
|
|
|
function readJson<T>(filePath: string): T {
|
|
return JSON.parse(fs.readFileSync(filePath, 'utf8')) as T;
|
|
}
|
|
|
|
function resolveTokenAddress(chain: DeploymentStatusChain, symbol: string): string | undefined {
|
|
return (
|
|
chain.cwTokens?.[symbol] ||
|
|
chain.anchorAddresses?.[symbol] ||
|
|
chain.gasMirrors?.[symbol] ||
|
|
chain.gasQuoteAddresses?.[symbol]
|
|
);
|
|
}
|
|
|
|
function parsePositiveNumber(value?: string): number {
|
|
const parsed = Number(value);
|
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : 0;
|
|
}
|
|
|
|
type CwbtcPoolHealth = {
|
|
id?: string;
|
|
pair?: string;
|
|
venue?: string;
|
|
poolAddress?: string;
|
|
live?: boolean;
|
|
baseReserveRaw?: string;
|
|
quoteReserveRaw?: string;
|
|
errors?: string[];
|
|
};
|
|
|
|
type CwbtcPoolsHealthPayload = {
|
|
chainId?: number;
|
|
tokenAddress?: string;
|
|
token?: { symbol?: string; addressDefault?: string; decimals?: number };
|
|
quoteTokens?: Record<string, string>;
|
|
pools?: CwbtcPoolHealth[];
|
|
};
|
|
|
|
function mergeCwbtcMeshPools(repoRoot: string, pools: Array<Record<string, unknown>>): void {
|
|
const healthPath = path.join(repoRoot, 'reports/status/mainnet-cwbtc-pools-health-latest.json');
|
|
const poolsConfigPath = path.join(repoRoot, 'config/engine/mainnet-cwbtc-pools.v1.json');
|
|
if (!fs.existsSync(healthPath) || !fs.existsSync(poolsConfigPath)) return;
|
|
|
|
const health = readJson<CwbtcPoolsHealthPayload>(healthPath);
|
|
const poolsConfig = readJson<{ quoteTokens?: Record<string, string> }>(poolsConfigPath);
|
|
const chainId = Number(health.chainId ?? 1);
|
|
const cwbtcAddress = String(health.tokenAddress ?? health.token?.addressDefault ?? '').toLowerCase();
|
|
const quoteTokens = { ...(poolsConfig.quoteTokens ?? {}), ...(health.quoteTokens ?? {}) };
|
|
const existing = new Set(pools.map((pool) => String(pool.poolAddress).toLowerCase()));
|
|
|
|
for (const row of health.pools ?? []) {
|
|
if (!row.live || row.venue !== 'uniswap_v2') continue;
|
|
const poolAddress = String(row.poolAddress ?? '').toLowerCase();
|
|
if (!poolAddress.startsWith('0x') || existing.has(poolAddress)) continue;
|
|
|
|
const [baseSymbol, quoteSymbol] = String(row.pair ?? '/').split('/');
|
|
const baseAddress =
|
|
baseSymbol === 'cWBTC' ? cwbtcAddress : String(quoteTokens[baseSymbol] ?? '').toLowerCase();
|
|
const quoteAddress =
|
|
quoteSymbol === 'cWBTC' ? cwbtcAddress : String(quoteTokens[quoteSymbol] ?? '').toLowerCase();
|
|
if (!baseAddress.startsWith('0x') || !quoteAddress.startsWith('0x')) continue;
|
|
|
|
const baseDecimals = baseSymbol === 'cWBTC' ? 8 : 6;
|
|
const quoteDecimals = quoteSymbol === 'cWBTC' ? 8 : 6;
|
|
const baseReserveRaw = parsePositiveNumber(row.baseReserveRaw);
|
|
const quoteReserveRaw = parsePositiveNumber(row.quoteReserveRaw);
|
|
if (baseReserveRaw <= 0 && quoteReserveRaw <= 0) continue;
|
|
|
|
const baseReserveUnits = baseReserveRaw / 10 ** baseDecimals;
|
|
const quoteReserveUnits = quoteReserveRaw / 10 ** quoteDecimals;
|
|
const basePriceUsd = PRICE_USD[baseSymbol] ?? 0;
|
|
const quotePriceUsd = PRICE_USD[quoteSymbol] ?? 0;
|
|
const reserve0Usd = baseReserveUnits * basePriceUsd;
|
|
const reserve1Usd = quoteReserveUnits * quotePriceUsd;
|
|
const totalLiquidityUsd = reserve0Usd + reserve1Usd;
|
|
if (totalLiquidityUsd <= 0) continue;
|
|
|
|
pools.push({
|
|
chainId,
|
|
chainName: 'Ethereum Mainnet',
|
|
poolAddress,
|
|
dex: 'uniswap_v2',
|
|
baseSymbol,
|
|
quoteSymbol,
|
|
baseAddress,
|
|
quoteAddress,
|
|
baseReserveRaw: String(row.baseReserveRaw ?? ''),
|
|
quoteReserveRaw: String(row.quoteReserveRaw ?? ''),
|
|
baseReserveUnits: String(baseReserveUnits),
|
|
quoteReserveUnits: String(quoteReserveUnits),
|
|
healthy: true,
|
|
depthOk: true,
|
|
parityOk: true,
|
|
reserve0Usd,
|
|
reserve1Usd,
|
|
totalLiquidityUsd,
|
|
sourceArtifact: 'reports/status/mainnet-cwbtc-pools-health-latest.json',
|
|
});
|
|
existing.add(poolAddress);
|
|
}
|
|
}
|
|
|
|
function main(): void {
|
|
const repoRoot = findRepoRoot();
|
|
const discoveryPath = path.join(repoRoot, 'reports/extraction/promod-uniswap-v2-live-pair-discovery-latest.json');
|
|
const deploymentStatusPath = path.join(repoRoot, 'cross-chain-pmm-lps/config/deployment-status.json');
|
|
const outPath = path.join(process.cwd(), 'config/live-uniswap-v2-pool-catalog.json');
|
|
|
|
const pools: Array<Record<string, unknown>> = [];
|
|
|
|
if (fs.existsSync(discoveryPath) && fs.existsSync(deploymentStatusPath)) {
|
|
const discovery = readJson<DiscoveryPayload>(discoveryPath);
|
|
const deploymentStatus = readJson<DeploymentStatus>(deploymentStatusPath);
|
|
|
|
for (const entry of discovery.entries ?? []) {
|
|
const chainId = Number(entry.chain_id);
|
|
const chain = deploymentStatus.chains?.[String(chainId)];
|
|
if (!chain) continue;
|
|
|
|
for (const pair of entry.pairsChecked ?? []) {
|
|
if (!pair.live || !pair.poolAddress?.startsWith('0x') || !pair.health) continue;
|
|
const baseAddress = resolveTokenAddress(chain, pair.base);
|
|
const quoteAddress = resolveTokenAddress(chain, pair.quote);
|
|
if (!baseAddress || !quoteAddress) continue;
|
|
|
|
const baseReserveUnits = parsePositiveNumber(pair.health.baseReserveUnits);
|
|
const quoteReserveUnits = parsePositiveNumber(pair.health.quoteReserveUnits);
|
|
const basePriceUsd = PRICE_USD[pair.base] ?? 0;
|
|
const quotePriceUsd = PRICE_USD[pair.quote] ?? 0;
|
|
const reserve0Usd = baseReserveUnits * basePriceUsd;
|
|
const reserve1Usd = quoteReserveUnits * quotePriceUsd;
|
|
const totalLiquidityUsd = reserve0Usd + reserve1Usd;
|
|
if (totalLiquidityUsd <= 0) continue;
|
|
|
|
pools.push({
|
|
chainId,
|
|
chainName: entry.network ?? chain.name ?? `Chain ${chainId}`,
|
|
poolAddress: pair.poolAddress.toLowerCase(),
|
|
dex: 'uniswap_v2',
|
|
factoryAddress: entry.factoryAddress,
|
|
routerAddress: entry.routerAddress,
|
|
baseSymbol: pair.base,
|
|
quoteSymbol: pair.quote,
|
|
baseAddress: baseAddress.toLowerCase(),
|
|
quoteAddress: quoteAddress.toLowerCase(),
|
|
baseReserveRaw: pair.health.baseReserveRaw,
|
|
quoteReserveRaw: pair.health.quoteReserveRaw,
|
|
baseReserveUnits: pair.health.baseReserveUnits,
|
|
quoteReserveUnits: pair.health.quoteReserveUnits,
|
|
priceQuotePerBase: pair.health.priceQuotePerBase,
|
|
deviationBps: pair.health.deviationBps,
|
|
depthOk: pair.health.depthOk,
|
|
parityOk: pair.health.parityOk,
|
|
healthy: pair.health.healthy,
|
|
reserve0Usd,
|
|
reserve1Usd,
|
|
totalLiquidityUsd,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
mergeCwbtcMeshPools(repoRoot, pools);
|
|
|
|
pools.sort(
|
|
(a, b) =>
|
|
Number(a.chainId) - Number(b.chainId) ||
|
|
String(a.poolAddress).localeCompare(String(b.poolAddress))
|
|
);
|
|
const payload = {
|
|
schema: 'token-aggregation-live-uniswap-v2-pool-catalog/v1',
|
|
generatedAt: new Date().toISOString(),
|
|
sourceArtifacts: [
|
|
'reports/extraction/promod-uniswap-v2-live-pair-discovery-latest.json',
|
|
'cross-chain-pmm-lps/config/deployment-status.json',
|
|
'reports/status/mainnet-cwbtc-pools-health-latest.json',
|
|
],
|
|
poolCount: pools.length,
|
|
positiveLiquidityPoolCount: pools.filter((pool) => Number(pool.totalLiquidityUsd) > 0).length,
|
|
pools,
|
|
};
|
|
|
|
fs.mkdirSync(path.dirname(outPath), { recursive: true });
|
|
fs.writeFileSync(outPath, `${JSON.stringify(payload, null, 2)}\n`);
|
|
console.log(outPath);
|
|
}
|
|
|
|
main();
|