export type DexType = 'uniswap_v2' | 'uniswap_v3' | 'sushiswap' | 'dodo' | 'custom'; export interface UniswapV2Config { factory: string; router: string; startBlock: number; } export interface UniswapV3Config { factory: string; router: string; startBlock: number; } export interface DodoConfig { poolManager?: string; // DODO PoolManager contract (allPools + poolRegistry ABI) dodoPmmIntegration?: string; // DODOPMMIntegration contract (getAllPools + getPoolConfig + getPoolReserves) dodoVendingMachine?: string; // DODO Vending Machine Factory dodoApprove?: string; // DODO Approve contract startBlock: number; } export interface CustomDexConfig { factory: string; router?: string; startBlock: number; pairCreatedEvent?: string; // Event signature for pair creation } export interface DexFactoryConfig { uniswap_v2?: UniswapV2Config[]; uniswap_v3?: UniswapV3Config[]; sushiswap?: UniswapV2Config[]; dodo?: DodoConfig[]; custom?: CustomDexConfig[]; } /** Canonical DODOPMMIntegration on Chain 138 — see docs/11-references/CONTRACT_ADDRESSES_REFERENCE.md */ const CANONICAL_CHAIN138_DODO_PMM_INTEGRATION = '0x86ADA6Ef91A3B450F89f2b751e93B1b7A3218895'; function getUniswapV2Config(chainId: number): UniswapV2Config[] | undefined { const factory = process.env[`CHAIN_${chainId}_UNISWAP_V2_FACTORY`]; if (!factory) return undefined; return [ { factory, router: process.env[`CHAIN_${chainId}_UNISWAP_V2_ROUTER`] || '', startBlock: parseInt(process.env[`CHAIN_${chainId}_UNISWAP_V2_START_BLOCK`] || '0', 10), }, ]; } function getDodoConfig(chainId: number): DodoConfig[] | undefined { const poolManager = process.env[`CHAIN_${chainId}_DODO_POOL_MANAGER`] || ''; const dodoPmmIntegration = process.env[`CHAIN_${chainId}_DODO_PMM_INTEGRATION`] || ''; if (!poolManager && !dodoPmmIntegration) return undefined; return [ { poolManager, dodoPmmIntegration, dodoVendingMachine: process.env[`CHAIN_${chainId}_DODO_VENDING_MACHINE`] || '', startBlock: parseInt(process.env[`CHAIN_${chainId}_DODO_START_BLOCK`] || '0', 10), }, ]; } export const DEX_FACTORIES: Record = { 138: { // DODO PMM Integration - index from DODOPMMIntegration or PoolManager dodo: [ { poolManager: process.env.CHAIN_138_DODO_POOL_MANAGER || '', dodoPmmIntegration: process.env.CHAIN_138_DODO_PMM_INTEGRATION || CANONICAL_CHAIN138_DODO_PMM_INTEGRATION, dodoVendingMachine: process.env.CHAIN_138_DODO_VENDING_MACHINE || '', startBlock: 0, }, ], // UniswapV2 - if deployed uniswap_v2: getUniswapV2Config(138), sushiswap: process.env.CHAIN_138_SUSHISWAP_FACTORY ? [ { factory: process.env.CHAIN_138_SUSHISWAP_FACTORY, router: process.env.CHAIN_138_SUSHISWAP_ROUTER || '', startBlock: parseInt(process.env.CHAIN_138_SUSHISWAP_START_BLOCK || '0', 10), }, ] : undefined, // UniswapV3 - if deployed uniswap_v3: process.env.CHAIN_138_UNISWAP_V3_FACTORY ? [ { factory: process.env.CHAIN_138_UNISWAP_V3_FACTORY, router: process.env.CHAIN_138_UNISWAP_V3_ROUTER || '', startBlock: parseInt(process.env.CHAIN_138_UNISWAP_V3_START_BLOCK || '0', 10), }, ] : undefined, }, 651940: { // ALL Mainnet - DEX factories to be discovered/configured // These can be set via environment variables or discovered on-chain uniswap_v2: getUniswapV2Config(651940), uniswap_v3: process.env.CHAIN_651940_UNISWAP_V3_FACTORY ? [ { factory: process.env.CHAIN_651940_UNISWAP_V3_FACTORY, router: process.env.CHAIN_651940_UNISWAP_V3_ROUTER || '', startBlock: parseInt(process.env.CHAIN_651940_UNISWAP_V3_START_BLOCK || '0', 10), }, ] : undefined, dodo: process.env.CHAIN_651940_DODO_POOL_MANAGER ? [ { poolManager: process.env.CHAIN_651940_DODO_POOL_MANAGER, dodoVendingMachine: process.env.CHAIN_651940_DODO_VENDING_MACHINE || '', startBlock: parseInt(process.env.CHAIN_651940_DODO_START_BLOCK || '0', 10), }, ] : undefined, custom: process.env.CHAIN_651940_HYDX_FACTORY ? [ { factory: process.env.CHAIN_651940_HYDX_FACTORY, router: process.env.CHAIN_651940_HYDX_ROUTER || '', startBlock: parseInt(process.env.CHAIN_651940_HYDX_START_BLOCK || '0', 10), pairCreatedEvent: process.env.CHAIN_651940_HYDX_PAIR_CREATED_EVENT || '', }, ] : undefined, }, // cW* edge chains (1, 10, 56, 100, 137): set CHAIN_*_DODO_PMM_INTEGRATION or CHAIN_*_DODO_POOL_MANAGER to index DODO/pools 1: { uniswap_v2: getUniswapV2Config(1), dodo: getDodoConfig(1), }, 10: { uniswap_v2: getUniswapV2Config(10), dodo: getDodoConfig(10), }, 25: { uniswap_v2: getUniswapV2Config(25), dodo: getDodoConfig(25), }, 56: { uniswap_v2: getUniswapV2Config(56), dodo: getDodoConfig(56), }, 100: { uniswap_v2: getUniswapV2Config(100), dodo: getDodoConfig(100), }, 137: { uniswap_v2: getUniswapV2Config(137), dodo: getDodoConfig(137), }, 8453: { uniswap_v2: getUniswapV2Config(8453), dodo: getDodoConfig(8453), }, 42161: { uniswap_v2: getUniswapV2Config(42161), dodo: getDodoConfig(42161), }, 42220: { uniswap_v2: getUniswapV2Config(42220), dodo: getDodoConfig(42220), }, 43114: { uniswap_v2: getUniswapV2Config(43114), dodo: getDodoConfig(43114), }, 1111: { uniswap_v2: getUniswapV2Config(1111), dodo: getDodoConfig(1111), }, }; /** * Get DEX factory configuration for a chain */ export function getDexFactories(chainId: number): DexFactoryConfig | undefined { return DEX_FACTORIES[chainId]; } /** * Check if a DEX type is configured for a chain */ export function hasDexType(chainId: number, dexType: DexType): boolean { const config = DEX_FACTORIES[chainId]; if (!config) return false; switch (dexType) { case 'uniswap_v2': return !!config.uniswap_v2 && config.uniswap_v2.length > 0; case 'uniswap_v3': return !!config.uniswap_v3 && config.uniswap_v3.length > 0; case 'sushiswap': return !!config.sushiswap && config.sushiswap.length > 0; case 'dodo': return !!config.dodo && config.dodo.length > 0; case 'custom': return !!config.custom && config.custom.length > 0; default: return false; } } /** * Get all configured DEX types for a chain */ export function getConfiguredDexTypes(chainId: number): DexType[] { const config = DEX_FACTORIES[chainId]; if (!config) return []; const types: DexType[] = []; if (hasDexType(chainId, 'uniswap_v2')) types.push('uniswap_v2'); if (hasDexType(chainId, 'uniswap_v3')) types.push('uniswap_v3'); if (hasDexType(chainId, 'sushiswap')) types.push('sushiswap'); if (hasDexType(chainId, 'dodo')) types.push('dodo'); if (hasDexType(chainId, 'custom')) types.push('custom'); return types; }