import { describe, it, expect, beforeEach } from 'vitest' import { EthereumTransactionBuilder } from './ethereum-transaction-builder' import type { EVMNativeTransferRequest, EVMContractCallRequest, EVMDataTransferRequest } from '@meshconnect/uwc-types' describe('EthereumTransactionBuilder', () => { let builder: EthereumTransactionBuilder beforeEach(() => { builder = new EthereumTransactionBuilder() }) describe('getNativeTransaction', () => { it('should build a native transaction request', async () => { const request: EVMNativeTransferRequest = { from: '0x1234567890123456789012345678901234567890', to: '0x0987654321098765432109876543210987654321', amount: BigInt('1000000000000000000'), // 1 ETH gasConfig: { gasLimit: 21000, maxFeePerGas: 50000000000, maxPriorityFeePerGas: 2000000000 } } const result = await builder.getNativeTransaction(request) expect(result).toEqual({ to: request.to, value: request.amount, gasLimit: BigInt(21000), maxFeePerGas: BigInt(50000000000), maxPriorityFeePerGas: BigInt(2000000000) }) }) it('should build a native transaction without gas config', async () => { const request: EVMNativeTransferRequest = { from: '0x1234567890123456789012345678901234567890', to: '0x0987654321098765432109876543210987654321', amount: BigInt('500000000000000000') // 0.5 ETH } const result = await builder.getNativeTransaction(request) expect(result).toEqual({ to: request.to, value: request.amount }) }) }) describe('getContractTransaction', () => { it('should build a contract transaction request', async () => { const erc20ABI = [ { inputs: [ { name: 'recipient', type: 'address' }, { name: 'amount', type: 'uint256' } ], name: 'transfer', outputs: [{ name: '', type: 'bool' }], stateMutability: 'nonpayable', type: 'function' } ] const request: EVMContractCallRequest = { from: '0x1234567890123456789012345678901234567890', contractAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', abi: erc20ABI, functionName: 'transfer', args: ['0x0987654321098765432109876543210987654321', BigInt(1000000)], gasConfig: { gasLimit: 100000 } } const result = await builder.getContractTransaction(request) expect(result.to).toBe(request.contractAddress) expect(result.data).toBeDefined() expect(result.data).toContain('0xa9059cbb') // transfer function selector expect(result.value).toBe(0n) expect(result.gasLimit).toBe(BigInt(100000)) }) it('should build a payable contract transaction', async () => { const payableABI = [ { inputs: [], name: 'deposit', outputs: [], stateMutability: 'payable', type: 'function' } ] const request: EVMContractCallRequest = { from: '0x1234567890123456789012345678901234567890', contractAddress: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', abi: payableABI, functionName: 'deposit', args: [], value: BigInt('1000000000000000000') // 1 ETH } const result = await builder.getContractTransaction(request) expect(result.to).toBe(request.contractAddress) expect(result.data).toBeDefined() expect(result.value).toBe(request.value) }) }) describe('getDataTransaction', () => { it('should build a data transaction request with all fields', async () => { const request: EVMDataTransferRequest = { from: '0x1234567890123456789012345678901234567890', to: '0x0987654321098765432109876543210987654321', data: '0xa9059cbb000000000000000000000000123456789012345678901234567890123456789000000000000000000000000000000000000000000000000000000000000f4240', chainId: '1', value: BigInt('500000000000000000'), // 0.5 ETH gasConfig: { gasLimit: 100000, maxFeePerGas: 50000000000, maxPriorityFeePerGas: 2000000000 } } const result = await builder.getDataTransaction(request) expect(result).toEqual({ to: request.to, data: request.data, value: request.value, gasLimit: BigInt(100000), maxFeePerGas: BigInt(50000000000), maxPriorityFeePerGas: BigInt(2000000000) }) }) it('should build a data transaction without value', async () => { const request: EVMDataTransferRequest = { from: '0x1234567890123456789012345678901234567890', to: '0x0987654321098765432109876543210987654321', data: '0xa9059cbb', chainId: '137' // Polygon } const result = await builder.getDataTransaction(request) expect(result).toEqual({ to: request.to, data: request.data, value: 0n }) }) it('should build a data transaction with minimal gas config', async () => { const request: EVMDataTransferRequest = { from: '0x1234567890123456789012345678901234567890', to: '0x0987654321098765432109876543210987654321', data: '0x00', chainId: '8453', // Base gasConfig: { gasLimit: 50000 } } const result = await builder.getDataTransaction(request) expect(result.gasLimit).toBe(BigInt(50000)) expect(result.maxFeePerGas).toBeUndefined() expect(result.maxPriorityFeePerGas).toBeUndefined() }) it('should handle empty data field', async () => { const request: EVMDataTransferRequest = { from: '0x1234567890123456789012345678901234567890', to: '0x0987654321098765432109876543210987654321', data: '0x', chainId: '1' } const result = await builder.getDataTransaction(request) expect(result.data).toBe('0x') expect(result.to).toBe(request.to) expect(result.value).toBe(0n) }) it('should handle complex encoded data', async () => { const complexData = '0x' + 'a'.repeat(1000) // Long hex string const request: EVMDataTransferRequest = { from: '0x1234567890123456789012345678901234567890', to: '0x0987654321098765432109876543210987654321', data: complexData, chainId: '42161' // Arbitrum } const result = await builder.getDataTransaction(request) expect(result.data).toBe(complexData) expect(result.value).toBe(0n) }) }) describe('formatGasConfig', () => { it('should handle null gas config values', async () => { const request: EVMNativeTransferRequest = { from: '0x1234567890123456789012345678901234567890', to: '0x0987654321098765432109876543210987654321', amount: BigInt('1000000000000000000'), gasConfig: { gasLimit: null, maxFeePerGas: null, maxPriorityFeePerGas: null } } const result = await builder.getNativeTransaction(request) expect(result.gasLimit).toBeUndefined() expect(result.maxFeePerGas).toBeUndefined() expect(result.maxPriorityFeePerGas).toBeUndefined() }) it('should floor decimal gas values', async () => { const request: EVMNativeTransferRequest = { from: '0x1234567890123456789012345678901234567890', to: '0x0987654321098765432109876543210987654321', amount: BigInt('1000000000000000000'), gasConfig: { gasLimit: 21000.7, maxFeePerGas: 50000000000.9, maxPriorityFeePerGas: 2000000000.1 } } const result = await builder.getNativeTransaction(request) expect(result.gasLimit).toBe(BigInt(21000)) expect(result.maxFeePerGas).toBe(BigInt(50000000000)) expect(result.maxPriorityFeePerGas).toBe(BigInt(2000000000)) }) }) })