import { Contract, ContractRunner } from 'ethers'; import { ProtocolDetector } from './ProtocolDetector'; /** * PoolStateQuerier retrieves pool state data * * Handles protocol-specific differences in pool state queries: * - Uniswap V3/V4: slot0() * - Algebra, PoolShark: globalState() * - Different sqrtPriceX96 field locations per protocol */ export class PoolStateQuerier { private protocolDetector: ProtocolDetector; constructor(protocolDetector?: ProtocolDetector) { this.protocolDetector = protocolDetector || new ProtocolDetector(); } /** * Get slot0/globalState data from pool contract * * Uses protocol-specific method: * - Algebra, PoolShark: globalState() * - Other protocols: slot0() * * @param beaconName - The beacon name to determine protocol * @param poolContract - The pool contract instance * @returns Promise - Slot0 or globalState data */ async getSlot0(beaconName: string, poolContract: Contract): Promise { if ( this.protocolDetector.isAlgebraVault(beaconName) || this.protocolDetector.isPoolSharkVault(beaconName) ) { return await poolContract.globalState(); } else { return await poolContract.slot0(); } } /** * Extract sqrtPriceX96 from slot data * * Different protocols store price in different fields: * - Algebra: slotData.price * - PoolShark: slotData.pool.price * - Other protocols: slotData.sqrtPriceX96 * * @param beaconName - The beacon name to determine protocol * @param slotData - The slot0/globalState data * @returns any - The sqrtPriceX96 value */ extractSqrtPriceX96(beaconName: string, slotData: any): any { if (this.protocolDetector.isAlgebraVault(beaconName)) { return slotData.price; } else if (this.protocolDetector.isPoolSharkVault(beaconName)) { return slotData?.pool?.price; } else { return slotData.sqrtPriceX96; } } /** * Get tick spacing from pool contract * * Useful for protocols like ThickV2 that require tick spacing * for swap calculations. * * @param poolAddress - The pool contract address * @param signer - The ethers signer * @returns Promise - Tick spacing or undefined if query fails */ async getTickSpacing( poolAddress: string, signer: ContractRunner, ): Promise { try { const contract = new Contract( poolAddress, [ { inputs: [], name: 'tickSpacing', outputs: [ { internalType: 'int24', name: '', type: 'int24', }, ], stateMutability: 'view', type: 'function', }, ], signer, ); const tickSpacing = await contract.tickSpacing(); return tickSpacing; } catch (e) { // Return undefined if tickSpacing query fails return undefined; } } }