import { Fraction } from '@uniswap/sdk-core'; import { AlgebraIntegralCustomRouter, calculateAmountToSwap, fractionAbsoluteValue, } from '../../src/routers/algebra/algebra-integral-router'; jest.mock('../../src/routers/base/base-router', () => { return { BaseRouter: jest.fn().mockImplementation(() => ({ getSwapAmount: jest .fn() .mockResolvedValue({ amountToSwap: 6n, zeroForOne: false }), })), }; }); const makePool = () => ({ globalState: jest .fn() .mockResolvedValue({ price: 79228162514264337593543950336n }), }); const makeQuoter = () => ({ callStatic: { quoteExactInputSingle: jest.fn().mockResolvedValue({ amountOut: 1n, sqrtPriceX96After: 2n, }), }, }); describe('Algebra integral router helpers', () => { it('fractionAbsoluteValue returns positive numerator and denominator', () => { const frac = new Fraction(-3, 4); const abs = fractionAbsoluteValue(frac); expect(abs.numerator.toString()).toBe('3'); expect(abs.denominator.toString()).toBe('4'); }); it('calculateAmountToSwap handles zero and infinite ratios', () => { const zeroRatio = new Fraction(0, 1); expect(calculateAmountToSwap(zeroRatio, 1n, true, 6n, 2n)).toBe(6n); expect(() => calculateAmountToSwap(zeroRatio, 1n, false, 6n, 2n)).toThrow( 'wrong parameters', ); const infRatio = new Fraction(1, 0); expect(calculateAmountToSwap(infRatio, 1n, false, 6n, 2n)).toBe(2n); expect(() => calculateAmountToSwap(infRatio, 1n, true, 6n, 2n)).toThrow( 'wrong parameters', ); }); }); describe('AlgebraIntegralCustomRouter', () => { const positions = [{ lowerTick: -60, upperTick: 60, weight: 1 }]; it('returns zero when already balanced', async () => { const pool = makePool(); const quoter = makeQuoter(); const logger = { info: jest.fn() } as any; const router = new AlgebraIntegralCustomRouter(quoter as any, logger); const result = await router.getSwapAmount( pool as any, positions as any, 1n, 1n, '0x1', '0x2', 1, new Fraction(1, 1), ); expect(result.amountToSwap).toBe(0n); }); it('falls back to base router when legacy flow fails', async () => { const pool = makePool(); pool.globalState = jest.fn().mockRejectedValue(new Error('fail')); const quoter = makeQuoter(); const logger = { info: jest.fn() } as any; const router = new AlgebraIntegralCustomRouter(quoter as any, logger); const result = await router.getSwapAmount( pool as any, positions as any, 10n, 20n, '0x1', '0x2', 2, ); expect(result).toEqual({ amountToSwap: 6n, zeroForOne: false }); }); it('throws when fallback fails', async () => { const baseRouterModule = require('../../src/routers/base/base-router'); baseRouterModule.BaseRouter.mockImplementationOnce(() => ({ getSwapAmount: jest.fn().mockRejectedValue(new Error('fallback failed')), })); const pool = makePool(); pool.globalState = jest.fn().mockRejectedValue(new Error('fail')); const quoter = makeQuoter(); const logger = { info: jest.fn() } as any; const router = new AlgebraIntegralCustomRouter(quoter as any, logger); await expect( router.getSwapAmount( pool as any, positions as any, 10n, 20n, '0x1', '0x2', 2, ), ).rejects.toThrow('fallback failed'); }); });