refactor: move all remaining files to orig/ directory
Completed clean root directory structure: - Root now contains only: .git, .env, docs/, orig/ - Moved all remaining files and directories to orig/: - Config files (.claude, .dockerignore, .drone.yml, etc.) - All .env variants (except active .env) - Git config (.gitconfig, .github, .gitignore, etc.) - Tool configs (.golangci.yml, .revive.toml, etc.) - Documentation (*.md files, @prompts) - Build files (Dockerfiles, Makefile, go.mod, go.sum) - Docker compose files - All source directories (scripts, tests, tools, etc.) - Runtime directories (logs, monitoring, reports) - Dependency files (node_modules, lib, cache) - Special files (--delete) - Removed empty runtime directories (bin/, data/) V2 structure is now clean: - docs/planning/ - V2 planning documents - orig/ - Complete V1 codebase preserved - .env - Active environment config (not in git) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
286
orig/tests/integration/basic_integration_test.go
Normal file
286
orig/tests/integration/basic_integration_test.go
Normal file
@@ -0,0 +1,286 @@
|
||||
//go:build integration && legacy && forked
|
||||
// +build integration,legacy,forked
|
||||
|
||||
// Package integration provides integration tests for the MEV bot using a forked Arbitrum environment
|
||||
package integration
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/ethclient"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/fraktal/mev-beta/internal/config"
|
||||
"github.com/fraktal/mev-beta/internal/logger"
|
||||
"github.com/fraktal/mev-beta/pkg/contracts"
|
||||
"github.com/fraktal/mev-beta/pkg/database"
|
||||
"github.com/fraktal/mev-beta/pkg/pools"
|
||||
"github.com/fraktal/mev-beta/pkg/security"
|
||||
)
|
||||
|
||||
// TestContractExecutorInitialization tests that the contract executor can be initialized
|
||||
func TestContractExecutorInitialization(t *testing.T) {
|
||||
// Skip this test in short mode
|
||||
if testing.Short() {
|
||||
t.Skip("skipping contract executor test in short mode")
|
||||
}
|
||||
|
||||
// Create test logger
|
||||
log := logger.New("debug", "text", "")
|
||||
|
||||
// Create test configuration
|
||||
cfg := &config.Config{
|
||||
Arbitrum: config.ArbitrumConfig{
|
||||
RPCEndpoint: "http://localhost:8545", // Anvil default port
|
||||
ChainID: 31337, // Anvil default chain ID
|
||||
RateLimit: config.RateLimitConfig{
|
||||
RequestsPerSecond: 10,
|
||||
MaxConcurrent: 5,
|
||||
Burst: 20,
|
||||
},
|
||||
},
|
||||
Bot: config.BotConfig{
|
||||
Enabled: true,
|
||||
PollingInterval: 1,
|
||||
MinProfitThreshold: 0.01, // Lower threshold for testing
|
||||
GasPriceMultiplier: 1.2,
|
||||
MaxWorkers: 2,
|
||||
ChannelBufferSize: 10,
|
||||
RPCTimeout: 30,
|
||||
},
|
||||
Ethereum: config.EthereumConfig{
|
||||
PrivateKey: "", // Will be set by environment or test setup
|
||||
AccountAddress: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", // Default Anvil account
|
||||
GasPriceMultiplier: 1.2,
|
||||
},
|
||||
Contracts: config.ContractsConfig{
|
||||
ArbitrageExecutor: "0x0000000000000000000000000000000000000000", // Placeholder
|
||||
FlashSwapper: "0x0000000000000000000000000000000000000000", // Placeholder
|
||||
AuthorizedCallers: []string{
|
||||
"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", // Default Anvil account
|
||||
},
|
||||
AuthorizedDEXes: []string{
|
||||
"0x1F98431c8aD98523631AE4a59f267346ea31F984", // Uniswap V3 Factory
|
||||
"0xf1D7CC64Fb4452F05c498126312eBE29f30Fbcf9", // Uniswap V2 Factory
|
||||
"0xc35DADB65012eC5796536bD9864eD8773aBc74C4", // SushiSwap Factory
|
||||
},
|
||||
},
|
||||
Database: config.DatabaseConfig{
|
||||
File: ":memory:",
|
||||
MaxOpenConnections: 10,
|
||||
MaxIdleConnections: 5,
|
||||
},
|
||||
Uniswap: config.UniswapConfig{
|
||||
FactoryAddress: "0x1F98431c8aD98523631AE4a59f267346ea31F984",
|
||||
PositionManagerAddress: "0xC36442b4a4522E871399CD717aBDD847Ab11FE88",
|
||||
FeeTiers: []int64{500, 3000, 10000},
|
||||
Cache: config.CacheConfig{
|
||||
Enabled: true,
|
||||
Expiration: 300,
|
||||
MaxSize: 10000,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Connect to the forked environment
|
||||
client, err := ethclient.Dial(cfg.Arbitrum.RPCEndpoint)
|
||||
if err != nil {
|
||||
t.Skipf("Skipping test: failed to connect to forked Arbitrum at %s", cfg.Arbitrum.RPCEndpoint)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
// Verify connection by getting chain ID
|
||||
chainID, err := client.ChainID(context.Background())
|
||||
require.NoError(t, err, "failed to get chain ID")
|
||||
log.Info("Connected to forked Arbitrum chain ID:", chainID.String())
|
||||
|
||||
// Test contract executor creation (this might fail in testing but we can verify the setup)
|
||||
// Create a mock key manager for testing
|
||||
keyManager, err := security.NewKeyManager(&security.KeyManagerConfig{
|
||||
KeystorePath: "/tmp/test_keys",
|
||||
EncryptionKey: "test_encryption_key",
|
||||
}, log)
|
||||
require.NoError(t, err)
|
||||
|
||||
contractExecutor, err := contracts.NewContractExecutor(cfg, log, keyManager)
|
||||
if err != nil {
|
||||
// This is expected in testing since we don't have real contracts deployed
|
||||
log.Warn("Contract executor creation failed (expected in testing):", err)
|
||||
} else {
|
||||
defer contractExecutor.Close()
|
||||
assert.NotNil(t, contractExecutor)
|
||||
log.Info("Contract executor created successfully")
|
||||
}
|
||||
|
||||
log.Info("Contract executor initialization test completed")
|
||||
}
|
||||
|
||||
// TestCREATE2Calculator tests the CREATE2 pool address calculation
|
||||
func TestCREATE2Calculator(t *testing.T) {
|
||||
// Create test logger
|
||||
log := logger.New("debug", "text", "")
|
||||
|
||||
// Create CREATE2 calculator
|
||||
calculator := pools.NewCREATE2Calculator(log)
|
||||
|
||||
// Test calculating pool addresses for known token pairs
|
||||
testCases := []struct {
|
||||
name string
|
||||
factoryName string
|
||||
token0 string
|
||||
token1 string
|
||||
fee uint32
|
||||
expectedLen int
|
||||
}{
|
||||
{
|
||||
name: "Uniswap V3 USDC/WETH",
|
||||
factoryName: "uniswap_v3",
|
||||
token0: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
|
||||
token1: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH
|
||||
fee: 3000,
|
||||
expectedLen: 20, // Address should be 20 bytes
|
||||
},
|
||||
{
|
||||
name: "Uniswap V2 USDC/WETH",
|
||||
factoryName: "uniswap_v2",
|
||||
token0: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
|
||||
token1: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH
|
||||
fee: 0, // V2 doesn't use fee in pool calculation
|
||||
expectedLen: 20,
|
||||
},
|
||||
{
|
||||
name: "SushiSwap USDC/WETH",
|
||||
factoryName: "sushiswap",
|
||||
token0: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC
|
||||
token1: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH
|
||||
fee: 0, // SushiSwap V2 doesn't use fee in pool calculation
|
||||
expectedLen: 20,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
// Convert hex addresses to common.Address
|
||||
token0 := common.HexToAddress(tc.token0)
|
||||
token1 := common.HexToAddress(tc.token1)
|
||||
|
||||
// Calculate pool address
|
||||
poolAddr, err := calculator.CalculatePoolAddress(tc.factoryName, token0, token1, tc.fee)
|
||||
require.NoError(t, err, "failed to calculate pool address")
|
||||
|
||||
// Verify the pool address
|
||||
assert.Equal(t, tc.expectedLen, len(poolAddr.Bytes()), "pool address should be 20 bytes")
|
||||
assert.NotEqual(t, common.Address{}, poolAddr, "pool address should not be zero")
|
||||
|
||||
log.Info("Calculated pool address:", poolAddr.Hex(), "for", tc.name)
|
||||
})
|
||||
}
|
||||
|
||||
// Test finding pools for token pairs
|
||||
usdc := common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48")
|
||||
weth := common.HexToAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2")
|
||||
|
||||
pools, err := calculator.FindPoolsForTokenPair(usdc, weth)
|
||||
require.NoError(t, err, "failed to find pools for token pair")
|
||||
|
||||
log.Info("Found", len(pools), "potential pools for USDC/WETH pair")
|
||||
|
||||
// Verify we found some pools
|
||||
assert.True(t, len(pools) > 0, "should find at least one pool for USDC/WETH")
|
||||
|
||||
// Verify each pool has valid data
|
||||
for _, pool := range pools {
|
||||
assert.NotEqual(t, "", pool.Factory, "factory should not be empty")
|
||||
assert.NotEqual(t, common.Address{}, pool.Token0, "token0 should not be zero")
|
||||
assert.NotEqual(t, common.Address{}, pool.Token1, "token1 should not be zero")
|
||||
assert.NotEqual(t, common.Address{}, pool.PoolAddr, "pool address should not be zero")
|
||||
assert.True(t, pool.Fee >= 0, "fee should be non-negative")
|
||||
}
|
||||
|
||||
log.Info("CREATE2 calculator test completed successfully")
|
||||
}
|
||||
|
||||
// TestDatabaseIntegration tests database integration
|
||||
func TestDatabaseIntegration(t *testing.T) {
|
||||
// Create test logger
|
||||
log := logger.New("debug", "text", "")
|
||||
|
||||
// Create test configuration
|
||||
cfg := &config.DatabaseConfig{
|
||||
File: ":memory:", // In-memory database for testing
|
||||
MaxOpenConnections: 10,
|
||||
MaxIdleConnections: 5,
|
||||
}
|
||||
|
||||
// Create database
|
||||
db, err := database.NewDatabase(cfg, log)
|
||||
require.NoError(t, err, "failed to create database")
|
||||
defer db.Close()
|
||||
|
||||
// Test inserting swap event
|
||||
swapEvent := &database.SwapEvent{
|
||||
Timestamp: time.Now(),
|
||||
BlockNumber: 12345678,
|
||||
TxHash: common.HexToHash("0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"),
|
||||
PoolAddress: common.HexToAddress("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640"),
|
||||
Token0: common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"), // USDC
|
||||
Token1: common.HexToAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), // WETH
|
||||
Amount0In: big.NewInt(1000000000), // 1000 USDC
|
||||
Amount1In: big.NewInt(0),
|
||||
Amount0Out: big.NewInt(0),
|
||||
Amount1Out: big.NewInt(500000000000000000), // 0.5 WETH
|
||||
Sender: common.HexToAddress("0x1234567890abcdef1234567890abcdef12345678"),
|
||||
Recipient: common.HexToAddress("0x8765432109fedcba8765432109fedcba87654321"),
|
||||
Protocol: "uniswap_v3",
|
||||
}
|
||||
|
||||
err = db.InsertSwapEvent(swapEvent)
|
||||
assert.NoError(t, err, "failed to insert swap event")
|
||||
|
||||
// Test retrieving recent swap events
|
||||
swaps, err := db.GetRecentSwapEvents(10)
|
||||
assert.NoError(t, err, "failed to get recent swap events")
|
||||
assert.Len(t, swaps, 1, "expected 1 swap event")
|
||||
|
||||
// Verify the retrieved swap event
|
||||
if len(swaps) > 0 {
|
||||
assert.Equal(t, swapEvent.PoolAddress, swaps[0].PoolAddress, "pool address mismatch")
|
||||
assert.Equal(t, swapEvent.Token0, swaps[0].Token0, "token0 mismatch")
|
||||
assert.Equal(t, swapEvent.Token1, swaps[0].Token1, "token1 mismatch")
|
||||
assert.Equal(t, swapEvent.Protocol, swaps[0].Protocol, "protocol mismatch")
|
||||
assert.Equal(t, swapEvent.Amount0In, swaps[0].Amount0In, "amount0 in mismatch")
|
||||
assert.Equal(t, swapEvent.Amount1Out, swaps[0].Amount1Out, "amount1 out mismatch")
|
||||
}
|
||||
|
||||
// Test inserting pool data
|
||||
poolData := &database.PoolData{
|
||||
Address: common.HexToAddress("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640"),
|
||||
Token0: common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"), // USDC
|
||||
Token1: common.HexToAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), // WETH
|
||||
Fee: 3000, // 0.3%
|
||||
Liquidity: big.NewInt(1000000000000000000), // 1 ETH equivalent
|
||||
SqrtPriceX96: big.NewInt(2505414483750470000), // Realistic price
|
||||
Tick: 200000, // Corresponding tick
|
||||
LastUpdated: time.Now(),
|
||||
Protocol: "uniswap_v3",
|
||||
}
|
||||
|
||||
err = db.InsertPoolData(poolData)
|
||||
assert.NoError(t, err, "failed to insert pool data")
|
||||
|
||||
// Test retrieving pool data
|
||||
retrievedPool, err := db.GetPoolData(poolData.Address)
|
||||
assert.NoError(t, err, "failed to get pool data")
|
||||
assert.Equal(t, poolData.Address, retrievedPool.Address, "pool address mismatch")
|
||||
assert.Equal(t, poolData.Token0, retrievedPool.Token0, "token0 mismatch")
|
||||
assert.Equal(t, poolData.Token1, retrievedPool.Token1, "token1 mismatch")
|
||||
assert.Equal(t, poolData.Fee, retrievedPool.Fee, "fee mismatch")
|
||||
assert.Equal(t, poolData.Protocol, retrievedPool.Protocol, "protocol mismatch")
|
||||
|
||||
log.Info("Database integration test completed successfully")
|
||||
}
|
||||
Reference in New Issue
Block a user