import { describe, it, expect, beforeEach, vi } from 'vitest'; import { Address, Hex, PublicClient, zeroAddress } from 'viem'; import { DutchOrder } from '@prex0/prex-structs'; import { PrexApiService } from '../api'; import { PrexClient } from '../prex-client'; import { SwapAction } from './swap'; vi.mock('@prex0/prex-structs', async (importOriginal) => { const actual = await importOriginal(); return { DutchOrder: (actual as any).DutchOrder, getFeePercentage: (actual as any).getFeePercentage, OrderBuilder: (actual as any).OrderBuilder, SwapQuoter: vi.fn().mockImplementation(() => ({ estimateSwap: vi.fn().mockResolvedValue({ amountCalculated: BigInt(900), route: '0xRoute' as Hex, }), })), }; }); describe('SwapAction', () => { let swapAction: SwapAction; let mockClient: PrexClient; let mockEvmClient: PublicClient; let mockApiService: PrexApiService; beforeEach(() => { mockClient = { loadConfig: vi.fn().mockResolvedValue({ feeTiers: [], }), getPermit2Nonce: vi.fn().mockResolvedValue(BigInt(1)), updatePermit2Nonce: vi.fn().mockResolvedValue(BigInt(1)), fetchBalance: vi.fn().mockResolvedValue({ value: BigInt(1000) }), } as unknown as PrexClient; mockEvmClient = { chain: { id: 1337, }, } as PublicClient; mockApiService = { getFeeTiers: vi.fn().mockResolvedValue({ fee: [ { address: zeroAddress, feeTiers: [{ fee: BigInt(10), minAmount: BigInt(100) }], }, ], }), swap: vi.fn().mockResolvedValue({ hash: '0xHash' }), } as unknown as PrexApiService; swapAction = new SwapAction(mockClient, mockEvmClient, mockApiService); }); describe('quoteSwap', () => { it('should return a quote, route, and order for EXACT_INPUT trade type', async () => { const params = { tokenIn: '0x0000000000000000000000000000000000000001' as Address, tokenOut: '0x0000000000000000000000000000000000000002' as Address, amount: BigInt(1000), tradeType: 'EXACT_INPUT' as const, swapper: '0xSwapper' as Address, recipient: '0xRecipient' as Address, }; const result = await swapAction.quoteSwap(params); expect(result).toHaveProperty('quote'); expect(result).toHaveProperty('route'); expect(result).toHaveProperty('order'); }); }); describe('swap', () => { it('should throw an error if signer is not found', async () => { const order = {} as DutchOrder; const route = '0xRoute' as Hex; await expect(swapAction.swap(order, route)).rejects.toThrow( 'Signer not found' ); }); it('should return a receipt after successful swap', async () => { const order = new DutchOrder( { input: { token: '0x0000000000000000000000000000000000000001' as Address, startAmount: BigInt(1000), endAmount: BigInt(1000), }, outputs: [ { token: '0x0000000000000000000000000000000000000002' as Address, startAmount: BigInt(1000), endAmount: BigInt(1000), recipient: '0xRecipient' as Address, }, ], reactor: zeroAddress, swapper: zeroAddress, nonce: 100n, deadline: 100n, additionalValidationContract: zeroAddress, additionalValidationData: '0x', decayStartTime: 100n, decayEndTime: 100n, exclusiveFiller: zeroAddress, exclusivityOverrideBps: 0n, }, 1337 ); const route = '0xRoute' as Hex; mockClient.signer = { signTypedData: vi.fn().mockResolvedValue('0xSignature'), } as any; vi.spyOn(mockClient as any, 'updatePermit2Nonce').mockResolvedValue( BigInt(1) ); const result = await swapAction.swap(order, route); expect(result).toHaveProperty('hash'); }); }); });