import { ethers } from "ethers"; import { Logger } from "../utils/logger"; import { Protocol } from "@steerprotocol/sdk"; // Import all routers from their new locations import { UniswapCustomRouter } from "../routers/uniswap/uniswap-v3-router"; import { UniswapCustomRouterV2 } from "../routers/uniswap/uniswap-v4-router"; import { AlgebraCustomRouter } from "../routers/algebra/algebra-router"; import { AlgebraIntegralCustomRouter } from "../routers/algebra/algebra-integral-router"; import { AlgebraIntegralV2CustomRouter } from "../routers/algebra/algebra-integral-v2-router"; import { PoolSharkCustomRouter } from "../routers/poolshark/poolshark-router"; import { AerodromeCustomRouter } from "../routers/aerodrome/aerodrome-router"; import { ShadowCustomRouter } from "../routers/shadow/shadow-router"; import { ThickV2CustomRouter } from "../routers/thickv2/thickv2-router"; import { ProtocolDetector } from "./protocol-detector"; import { CreateCustomRouterParams, ProtocolSpecificParams } from "./types"; export type CustomRouter = | ThickV2CustomRouter | AlgebraCustomRouter | UniswapCustomRouter | PoolSharkCustomRouter | AlgebraIntegralCustomRouter | ShadowCustomRouter | AlgebraIntegralV2CustomRouter | AerodromeCustomRouter | UniswapCustomRouterV2; export class CustomRouterFactory { private protocolDetector: ProtocolDetector; private logger: Logger; constructor(logger: Logger) { this.protocolDetector = new ProtocolDetector(); this.logger = logger; } /** * Create a custom router based on beacon name and protocol-specific parameters * * @example * // Using object parameter (recommended) * const router = factory.createCustomRouter({ * beaconName: "AlgebraIntegral_v2_0", * quoterV2: quoterContract, * poolObj: poolContract, * protocolParams: { * algebraIntegralV2Deployer: "0x1234..." * } * }); * * @example * // Using positional parameters (legacy, for backwards compatibility) * const router = factory.createCustomRouter(beaconName, quoterV2, poolObj); */ createCustomRouter(params: CreateCustomRouterParams): CustomRouter; createCustomRouter( beaconName: string, quoterV2: ethers.Contract, poolObj: ethers.Contract, protocolParams?: ProtocolSpecificParams ): CustomRouter; createCustomRouter( paramsOrBeaconName: CreateCustomRouterParams | string, quoterV2?: ethers.Contract, poolObj?: ethers.Contract, protocolParams?: ProtocolSpecificParams ): CustomRouter { // Normalize parameters let beaconName: string; let normalizedQuoterV2: ethers.Contract; let normalizedPoolObj: ethers.Contract; let normalizedProtocolParams: ProtocolSpecificParams | undefined; if (typeof paramsOrBeaconName === 'string') { // Legacy positional parameters beaconName = paramsOrBeaconName; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion normalizedQuoterV2 = quoterV2!; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion normalizedPoolObj = poolObj!; normalizedProtocolParams = protocolParams; } else { // New object parameter beaconName = paramsOrBeaconName.beaconName; normalizedQuoterV2 = paramsOrBeaconName.quoterV2; normalizedPoolObj = paramsOrBeaconName.poolObj; normalizedProtocolParams = paramsOrBeaconName.protocolParams; } // Create appropriate router based on protocol if (this.protocolDetector.isAlgebraIntegral19Vault(beaconName)) { const deployer = normalizedProtocolParams?.algebraIntegralV2Deployer; // If deployer is explicitly provided, use it if (deployer) { return new AlgebraIntegralV2CustomRouter(normalizedQuoterV2, this.logger, deployer); } // Otherwise, check if it's Blackhole protocol and handle accordingly const protocol = this.protocolDetector.getProtocol(beaconName); if (protocol === Protocol.Blackhole) { this.logger.warn( { logType: "custom-router-factory" }, "Blackhole protocol detected but no deployer address provided. Using ZERO_ADDRESS as fallback. " + "Consider providing algebraIntegralV2Deployer in protocolParams for proper configuration." ); } return new AlgebraIntegralV2CustomRouter(normalizedQuoterV2, this.logger, deployer); } else if (this.protocolDetector.isAlgebraIntegralVault(beaconName)) { return new AlgebraIntegralCustomRouter(normalizedQuoterV2, this.logger); } else if (this.protocolDetector.isAlgebraVault(beaconName)) { return new AlgebraCustomRouter(normalizedQuoterV2, this.logger); } else if (this.protocolDetector.isPoolSharkVault(beaconName)) { return new PoolSharkCustomRouter(normalizedPoolObj, this.logger); } else if (this.protocolDetector.isThickV2Vault(beaconName)) { return new ThickV2CustomRouter(normalizedQuoterV2, this.logger); } else if (this.protocolDetector.isShadowVault(beaconName)) { return new ShadowCustomRouter(normalizedQuoterV2, this.logger); } else if (this.protocolDetector.isAerodromeVault(beaconName)) { return new AerodromeCustomRouter(normalizedQuoterV2, this.logger); } else { return new UniswapCustomRouter(normalizedQuoterV2, this.logger); } } }