package market import ( "context" "testing" "time" "github.com/fraktal/mev-beta/internal/config" "github.com/fraktal/mev-beta/internal/logger" "github.com/ethereum/go-ethereum/common" "github.com/holiman/uint256" "github.com/stretchr/testify/assert" ) func TestNewMarketManager(t *testing.T) { // Create test config cfg := &config.UniswapConfig{ Cache: config.CacheConfig{ Expiration: 300, MaxSize: 10000, }, } // Create test logger logger := logger.New("info", "text", "") // Create market manager manager := NewMarketManager(cfg, logger) // Verify manager was created correctly assert.NotNil(t, manager) assert.Equal(t, cfg, manager.config) assert.NotNil(t, manager.pools) assert.Equal(t, time.Duration(cfg.Cache.Expiration)*time.Second, manager.cacheDuration) assert.Equal(t, cfg.Cache.MaxSize, manager.maxCacheSize) } func TestGetPoolCacheHit(t *testing.T) { // Create market manager cfg := &config.UniswapConfig{ Cache: config.CacheConfig{ Expiration: 300, MaxSize: 10000, }, } logger := logger.New("info", "text", "") manager := NewMarketManager(cfg, logger) // Add a pool to the cache poolAddress := common.HexToAddress("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") pool := &PoolData{ Address: poolAddress, Token0: common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"), Token1: common.HexToAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), Fee: 3000, Liquidity: uint256.NewInt(1000000000000000000), SqrtPriceX96: uint256.NewInt(2505414483750470000), Tick: 200000, TickSpacing: 60, LastUpdated: time.Now(), } manager.pools[poolAddress.Hex()] = pool // Get the pool (should be a cache hit) ctx := context.Background() result, err := manager.GetPool(ctx, poolAddress) // Verify results assert.NoError(t, err) assert.Equal(t, pool, result) } func TestGetPoolCacheMiss(t *testing.T) { // Create market manager cfg := &config.UniswapConfig{ Cache: config.CacheConfig{ Expiration: 300, MaxSize: 10000, }, } logger := logger.New("info", "text", "") manager := NewMarketManager(cfg, logger) // Get a pool that's not in the cache (should trigger fetch) poolAddress := common.HexToAddress("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") ctx := context.Background() result, err := manager.GetPool(ctx, poolAddress) // Verify results (should get mock data) assert.NoError(t, err) assert.NotNil(t, result) assert.Equal(t, poolAddress, result.Address) assert.Equal(t, "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", result.Token0.Hex()) assert.Equal(t, "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", result.Token1.Hex()) } func TestGetPoolsByTokens(t *testing.T) { // Create market manager cfg := &config.UniswapConfig{ Cache: config.CacheConfig{ Expiration: 300, MaxSize: 10000, }, } logger := logger.New("info", "text", "") manager := NewMarketManager(cfg, logger) // Add some pools to the cache token0 := common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48") // USDC token1 := common.HexToAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") // WETH pool1 := &PoolData{ Address: common.HexToAddress("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640"), Token0: token0, Token1: token1, Fee: 3000, } manager.pools[pool1.Address.Hex()] = pool1 pool2 := &PoolData{ Address: common.HexToAddress("0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc"), Token0: token0, Token1: token1, Fee: 500, } manager.pools[pool2.Address.Hex()] = pool2 // Add a pool with different tokens token2 := common.HexToAddress("0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984") // UNI pool3 := &PoolData{ Address: common.HexToAddress("0x1234567890123456789012345678901234567890"), Token0: token0, Token1: token2, Fee: 3000, } manager.pools[pool3.Address.Hex()] = pool3 // Get pools for the token pair pools := manager.GetPoolsByTokens(token0, token1) // Verify results assert.Len(t, pools, 2) // Check that both pools are in the result pool1Found := false pool2Found := false for _, pool := range pools { if pool.Address == pool1.Address { pool1Found = true } if pool.Address == pool2.Address { pool2Found = true } } assert.True(t, pool1Found) assert.True(t, pool2Found) } func TestGetAllPools(t *testing.T) { // Create market manager cfg := &config.UniswapConfig{ Cache: config.CacheConfig{ Expiration: 300, MaxSize: 10000, }, } logger := logger.New("info", "text", "") manager := NewMarketManager(cfg, logger) // Add some pools to the cache pool1 := &PoolData{ Address: common.HexToAddress("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640"), Token0: common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"), Token1: common.HexToAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), Fee: 3000, } manager.pools[pool1.Address.Hex()] = pool1 pool2 := &PoolData{ Address: common.HexToAddress("0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc"), Token0: common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"), Token1: common.HexToAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), Fee: 500, } manager.pools[pool2.Address.Hex()] = pool2 // Get all pools pools := manager.GetAllPools() // Verify results assert.Len(t, pools, 2) } func TestUpdatePoolExisting(t *testing.T) { // Create market manager cfg := &config.UniswapConfig{ Cache: config.CacheConfig{ Expiration: 300, MaxSize: 10000, }, } logger := logger.New("info", "text", "") manager := NewMarketManager(cfg, logger) // Add a pool to the cache poolAddress := common.HexToAddress("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") originalLiquidity := uint256.NewInt(1000000000000000000) originalSqrtPrice := uint256.NewInt(2505414483750470000) originalTick := 200000 pool := &PoolData{ Address: poolAddress, Liquidity: originalLiquidity, SqrtPriceX96: originalSqrtPrice, Tick: originalTick, LastUpdated: time.Now().Add(-time.Hour), // Set to past time } manager.pools[poolAddress.Hex()] = pool // Update the pool newLiquidity := uint256.NewInt(2000000000000000000) newSqrtPrice := uint256.NewInt(3000000000000000000) newTick := 250000 manager.UpdatePool(poolAddress, newLiquidity, newSqrtPrice, newTick) // Verify the pool was updated updatedPool := manager.pools[poolAddress.Hex()] assert.Equal(t, newLiquidity, updatedPool.Liquidity) assert.Equal(t, newSqrtPrice, updatedPool.SqrtPriceX96) assert.Equal(t, newTick, updatedPool.Tick) // Check that the last updated time is more recent (allowing for small time differences) assert.True(t, updatedPool.LastUpdated.Unix() >= pool.LastUpdated.Unix()) } func TestUpdatePoolNew(t *testing.T) { // Create market manager cfg := &config.UniswapConfig{ Cache: config.CacheConfig{ Expiration: 300, MaxSize: 10000, }, } logger := logger.New("info", "text", "") manager := NewMarketManager(cfg, logger) // Update a pool that doesn't exist yet poolAddress := common.HexToAddress("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") liquidity := uint256.NewInt(1000000000000000000) sqrtPrice := uint256.NewInt(2505414483750470000) tick := 200000 manager.UpdatePool(poolAddress, liquidity, sqrtPrice, tick) // Verify the pool was created createdPool := manager.pools[poolAddress.Hex()] assert.NotNil(t, createdPool) assert.Equal(t, poolAddress, createdPool.Address) assert.Equal(t, liquidity, createdPool.Liquidity) assert.Equal(t, sqrtPrice, createdPool.SqrtPriceX96) assert.Equal(t, tick, createdPool.Tick) } func TestGetCacheStats(t *testing.T) { // Create market manager cfg := &config.UniswapConfig{ Cache: config.CacheConfig{ Expiration: 300, MaxSize: 10000, }, } logger := logger.New("info", "text", "") manager := NewMarketManager(cfg, logger) // Add some pools to the cache pool1 := &PoolData{ Address: common.HexToAddress("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640"), } manager.pools[pool1.Address.Hex()] = pool1 pool2 := &PoolData{ Address: common.HexToAddress("0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc"), } manager.pools[pool2.Address.Hex()] = pool2 // Get cache stats currentSize, maxSize := manager.GetCacheStats() // Verify results assert.Equal(t, 2, currentSize) assert.Equal(t, 10000, maxSize) }