/** * Tests for PoolStateQuerier * * Verifies pool state retrieval with protocol-specific methods */ describe('PoolStateQuerier', () => { it('should have PoolStateQuerier module available', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); expect(fs.existsSync(poolStateQuerierPath)).toBe(true); }); it('should be exported from helpers index', () => { const fs = require('fs'); const path = require('path'); const indexPath = path.join(__dirname, '../../src/helpers/index.ts'); const indexContent = fs.readFileSync(indexPath, 'utf-8'); expect(indexContent).toContain('PoolStateQuerier'); }); describe('Module structure', () => { it('should import required dependencies', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain( "import { Contract, ContractRunner } from 'ethers'", ); expect(content).toContain( "import { ProtocolDetector } from './ProtocolDetector'", ); }); it('should define PoolStateQuerier class', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain('export class PoolStateQuerier'); }); it('should have constructor with optional ProtocolDetector', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain( 'constructor(protocolDetector?: ProtocolDetector)', ); }); }); describe('getSlot0', () => { it('should define getSlot0 method', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain('getSlot0'); expect(content).toContain('beaconName: string'); expect(content).toContain('poolContract: Contract'); expect(content).toContain('Promise'); }); it('should check for Algebra protocol', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain( 'this.protocolDetector.isAlgebraVault(beaconName)', ); }); it('should check for PoolShark protocol', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain( 'this.protocolDetector.isPoolSharkVault(beaconName)', ); }); it('should use globalState() for Algebra and PoolShark', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain('poolContract.globalState()'); }); it('should use slot0() for other protocols', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain('poolContract.slot0()'); }); it('should have conditional logic for protocol types', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain('if ('); expect(content).toContain('} else {'); }); }); describe('extractSqrtPriceX96', () => { it('should define extractSqrtPriceX96 method', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain('extractSqrtPriceX96'); expect(content).toContain('beaconName: string'); expect(content).toContain('slotData: any'); }); it('should check for Algebra protocol', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain( 'this.protocolDetector.isAlgebraVault(beaconName)', ); }); it('should check for PoolShark protocol', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain( 'this.protocolDetector.isPoolSharkVault(beaconName)', ); }); it('should return slotData.price for Algebra', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain('slotData.price'); }); it('should return slotData.pool.price for PoolShark', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain('slotData?.pool?.price'); }); it('should return slotData.sqrtPriceX96 for other protocols', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain('slotData.sqrtPriceX96'); }); it('should use optional chaining for PoolShark', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain('?.'); }); }); describe('getTickSpacing', () => { it('should define getTickSpacing method', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain('getTickSpacing'); expect(content).toContain('poolAddress: string'); expect(content).toContain('signer: ContractRunner'); expect(content).toContain('Promise'); }); it('should create contract with tickSpacing ABI', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain('new Contract'); expect(content).toContain('tickSpacing'); }); it('should define tickSpacing ABI fragment', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain('inputs: []'); expect(content).toContain("name: 'tickSpacing'"); expect(content).toContain('outputs:'); expect(content).toContain("internalType: 'int24'"); expect(content).toContain("stateMutability: 'view'"); expect(content).toContain("type: 'function'"); }); it('should call tickSpacing() on contract', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain('contract.tickSpacing()'); }); it('should handle errors gracefully', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain('try {'); expect(content).toContain('catch'); expect(content).toContain('return undefined'); }); it('should return tick spacing on success', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain('return tickSpacing'); }); }); describe('Protocol detection integration', () => { it('should use ProtocolDetector for protocol checks', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain('this.protocolDetector'); }); it('should initialize ProtocolDetector if not provided', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain('protocolDetector || new ProtocolDetector()'); }); }); describe('Documentation', () => { it('should have JSDoc comments for class', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain('/**'); expect(content).toContain('* PoolStateQuerier'); }); it('should have JSDoc comments for all methods', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain('* Get slot0/globalState'); expect(content).toContain('* Extract sqrtPriceX96'); expect(content).toContain('* Get tick spacing'); }); it('should document protocol-specific behavior', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain('Algebra'); expect(content).toContain('PoolShark'); expect(content).toContain('Uniswap'); expect(content).toContain('slot0()'); expect(content).toContain('globalState()'); }); it('should document price field locations', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain('slotData.price'); expect(content).toContain('slotData.pool.price'); expect(content).toContain('slotData.sqrtPriceX96'); }); }); describe('Control flow', () => { it('should have if-else if-else structure in extractSqrtPriceX96', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain('if ('); expect(content).toContain('} else if ('); expect(content).toContain('} else {'); }); it('should use OR logic for protocol checks in getSlot0', () => { const fs = require('fs'); const path = require('path'); const poolStateQuerierPath = path.join( __dirname, '../../src/helpers/PoolStateQuerier.ts', ); const content = fs.readFileSync(poolStateQuerierPath, 'utf-8'); expect(content).toContain('||'); }); }); });