Files
mev-beta/tests/integration/arbitrage_test.go
Krypto Kajun 3f69aeafcf fix: resolve all compilation issues across transport and lifecycle packages
- Fixed duplicate type declarations in transport package
- Removed unused variables in lifecycle and dependency injection
- Fixed big.Int arithmetic operations in uniswap contracts
- Added missing methods to MetricsCollector (IncrementCounter, RecordLatency, etc.)
- Fixed jitter calculation in TCP transport retry logic
- Updated ComponentHealth field access to use transport type
- Ensured all core packages build successfully

All major compilation errors resolved:
 Transport package builds clean
 Lifecycle package builds clean
 Main MEV bot application builds clean
 Fixed method signature mismatches
 Resolved type conflicts and duplications

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-19 17:23:14 -05:00

259 lines
8.2 KiB
Go

package integration
import (
"context"
"fmt"
"math/big"
"os"
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/fraktal/mev-beta/internal/config"
"github.com/fraktal/mev-beta/internal/logger"
"github.com/fraktal/mev-beta/pkg/arbitrage"
"github.com/fraktal/mev-beta/pkg/security"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// Test configuration for forked environment
const (
TestRPCEndpoint = "http://localhost:8545"
TestChainID = 31337
)
// Arbitrum One token addresses for testing
var (
WETH = common.HexToAddress("0x82aF49447D8A07e3bd95BD0d56f35241523fBab1")
USDC = common.HexToAddress("0xA0b86a33E6417aB7d461a67E4d3F14F6b49d3e8B") // USDC.e
USDT = common.HexToAddress("0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9")
)
func TestMain(m *testing.M) {
// Check if we're in test mode
if os.Getenv("TEST_MODE") != "true" {
fmt.Println("Skipping integration tests - set TEST_MODE=true to run")
os.Exit(0)
}
// Run tests
code := m.Run()
os.Exit(code)
}
func setupTestEnvironment(t *testing.T) (*arbitrage.ArbitrageService, func()) {
// Create test logger
log := logger.New("debug", "text", "")
// Create test configuration
cfg := &config.ArbitrageConfig{
Enabled: true,
ArbitrageContractAddress: "0x0000000000000000000000000000000000000001", // Placeholder
FlashSwapContractAddress: "0x0000000000000000000000000000000000000002", // Placeholder
MinProfitWei: 1000000000000000, // 0.001 ETH
MinROIPercent: 1.0, // 1%
MinSignificantSwapSize: 1000000000000000000, // 1 ETH
SlippageTolerance: 0.005, // 0.5%
MinScanAmountWei: 100000000000000000, // 0.1 ETH
MaxScanAmountWei: 10000000000000000000, // 10 ETH
MaxGasPriceWei: 100000000000, // 100 gwei
MaxConcurrentExecutions: 1, // Single execution for testing
MaxOpportunitiesPerEvent: 3,
OpportunityTTL: 30 * time.Second,
MaxPathAge: 60 * time.Second,
StatsUpdateInterval: 10 * time.Second,
}
// Create Ethereum client
client, err := ethclient.Dial(TestRPCEndpoint)
require.NoError(t, err, "Failed to connect to test RPC")
// Create key manager
keyManagerConfig := &security.KeyManagerConfig{
KeystorePath: "test_keystore",
EncryptionKey: "test-encryption-key",
KeyRotationDays: 30,
MaxSigningRate: 100,
SessionTimeout: time.Hour,
}
keyManager, err := security.NewKeyManager(keyManagerConfig, log)
require.NoError(t, err, "Failed to create key manager")
// Create test database
database, err := arbitrage.NewSQLiteDatabase(":memory:", log)
require.NoError(t, err, "Failed to create test database")
// Create arbitrage service
service, err := arbitrage.NewArbitrageService(
client,
log,
cfg,
keyManager,
database,
)
require.NoError(t, err, "Failed to create arbitrage service")
// Start the service
err = service.Start()
require.NoError(t, err, "Failed to start arbitrage service")
// Cleanup function
cleanup := func() {
service.Stop()
database.Close()
client.Close()
}
return service, cleanup
}
func TestArbitrageServiceIntegration(t *testing.T) {
service, cleanup := setupTestEnvironment(t)
defer cleanup()
t.Run("ServiceHealthCheck", func(t *testing.T) {
assert.True(t, service.IsRunning(), "Service should be running")
stats := service.GetStats()
assert.NotNil(t, stats, "Stats should not be nil")
assert.Equal(t, int64(0), stats.TotalOpportunitiesDetected, "Initial opportunities should be zero")
})
t.Run("TokenValidation", func(t *testing.T) {
// Test that we can validate token addresses
tokens := []common.Address{WETH, USDC, USDT}
for _, token := range tokens {
assert.False(t, token.String() == "0x0000000000000000000000000000000000000000",
"Token address should not be zero: %s", token.String())
}
})
}
func TestSwapEventProcessing(t *testing.T) {
service, cleanup := setupTestEnvironment(t)
defer cleanup()
t.Run("ProcessLargeSwapEvent", func(t *testing.T) {
// Create a simulated large swap event
swapEvent := &arbitrage.SimpleSwapEvent{
TxHash: common.HexToHash("0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"),
PoolAddress: common.HexToAddress("0xC6962004f452bE9203591991D15f6b388e09E8D0"), // Example pool
Token0: WETH,
Token1: USDC,
Amount0: big.NewInt(-5000000000000000000), // -5 ETH
Amount1: big.NewInt(12500000000), // +12500 USDC
SqrtPriceX96: big.NewInt(1000000000000000000000), // Example price
Liquidity: big.NewInt(50000000000000000000000), // Example liquidity
Tick: int32(-85000), // Example tick
BlockNumber: 12345678,
LogIndex: 1,
Timestamp: time.Now(),
}
// Process the swap event
err := service.ProcessSwapEvent(swapEvent)
assert.NoError(t, err, "Should process swap event without error")
// Allow time for processing
time.Sleep(1 * time.Second)
// Check that the event was processed
stats := service.GetStats()
t.Logf("Opportunities detected: %d", stats.TotalOpportunitiesDetected)
})
}
func TestPoolDataRetrieval(t *testing.T) {
service, cleanup := setupTestEnvironment(t)
defer cleanup()
t.Run("SaveAndRetrievePoolData", func(t *testing.T) {
// Create test pool data
poolData := &arbitrage.SimplePoolData{
Address: common.HexToAddress("0xC6962004f452bE9203591991D15f6b388e09E8D0"),
Token0: WETH,
Token1: USDC,
Fee: 500, // 0.05%
Liquidity: big.NewInt(50000000000000000000000),
SqrtPriceX96: big.NewInt(1000000000000000000000),
Tick: -85000,
BlockNumber: 12345678,
TxHash: common.HexToHash("0xabcdef"),
LogIndex: 1,
LastUpdated: time.Now(),
}
// This test would require database access through the service
// For now, we verify the structure is correct
assert.Equal(t, WETH, poolData.Token0, "Token0 should be WETH")
assert.Equal(t, USDC, poolData.Token1, "Token1 should be USDC")
assert.Equal(t, int64(500), poolData.Fee, "Fee should be 500 (0.05%)")
})
}
func TestRealTimeArbitrageDetection(t *testing.T) {
if testing.Short() {
t.Skip("Skipping real-time test in short mode")
}
service, cleanup := setupTestEnvironment(t)
defer cleanup()
t.Run("ContinuousMonitoring", func(t *testing.T) {
// Run service for a short period to test real-time processing
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
initialStats := service.GetStats()
// Simulate periodic swap events
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
go func() {
eventCount := 0
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
eventCount++
// Create varied swap events
swapEvent := &arbitrage.SimpleSwapEvent{
TxHash: common.HexToHash(fmt.Sprintf("0x%064d", eventCount)),
PoolAddress: common.HexToAddress("0xC6962004f452bE9203591991D15f6b388e09E8D0"),
Token0: WETH,
Token1: USDC,
Amount0: big.NewInt(int64(-1000000000000000000 * eventCount)), // Varying amounts
Amount1: big.NewInt(int64(2500000000 * eventCount)),
SqrtPriceX96: big.NewInt(1000000000000000000000),
Liquidity: big.NewInt(50000000000000000000000),
Tick: int32(-85000 + eventCount*100),
BlockNumber: 12345678 + uint64(eventCount),
LogIndex: uint(eventCount),
Timestamp: time.Now(),
}
service.ProcessSwapEvent(swapEvent)
}
}
}()
// Wait for test duration
<-ctx.Done()
// Check final stats
finalStats := service.GetStats()
t.Logf("Initial opportunities: %d", initialStats.TotalOpportunitiesDetected)
t.Logf("Final opportunities: %d", finalStats.TotalOpportunitiesDetected)
// We expect some processing activity
assert.True(t, finalStats.TotalOpportunitiesDetected >= initialStats.TotalOpportunitiesDetected,
"Should have processed some opportunities")
})
}