Update module name to github.com/fraktal/mev-beta and fix channel closing issues in pipeline stages
This commit is contained in:
131
test/e2e/e2e_test.go
Normal file
131
test/e2e/e2e_test.go
Normal file
@@ -0,0 +1,131 @@
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/fraktal/mev-beta/internal/config"
|
||||
"github.com/fraktal/mev-beta/internal/logger"
|
||||
"github.com/fraktal/mev-beta/internal/ratelimit"
|
||||
"github.com/fraktal/mev-beta/pkg/market"
|
||||
"github.com/fraktal/mev-beta/pkg/monitor"
|
||||
"github.com/fraktal/mev-beta/pkg/scanner"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestEndToEndPipeline(t *testing.T) {
|
||||
// Skip this test in short mode
|
||||
if testing.Short() {
|
||||
t.Skip("skipping end-to-end test in short mode")
|
||||
}
|
||||
|
||||
// Create test config
|
||||
arbCfg := &config.ArbitrumConfig{
|
||||
RPCEndpoint: "https://arb1.arbitrum.io/rpc",
|
||||
ChainID: 42161,
|
||||
RateLimit: config.RateLimitConfig{
|
||||
RequestsPerSecond: 10,
|
||||
MaxConcurrent: 5,
|
||||
Burst: 20,
|
||||
},
|
||||
}
|
||||
botCfg := &config.BotConfig{
|
||||
Enabled: true,
|
||||
PollingInterval: 1,
|
||||
MinProfitThreshold: 10.0,
|
||||
GasPriceMultiplier: 1.2,
|
||||
MaxWorkers: 2, // Use fewer workers for testing
|
||||
ChannelBufferSize: 5,
|
||||
RPCTimeout: 30,
|
||||
}
|
||||
uniswapCfg := &config.UniswapConfig{
|
||||
FactoryAddress: "0x1F98431c8aD98523631AE4a59f267346ea31F984",
|
||||
PositionManagerAddress: "0xC36442b4a4522E871399CD717aBDD847Ab11FE88",
|
||||
FeeTiers: []int64{500, 3000, 10000},
|
||||
Cache: config.CacheConfig{
|
||||
Enabled: true,
|
||||
Expiration: 300,
|
||||
MaxSize: 10000,
|
||||
},
|
||||
}
|
||||
|
||||
// Create test logger
|
||||
log := logger.New("info", "text", "")
|
||||
|
||||
// Create rate limiter manager
|
||||
rateLimiter := ratelimit.NewLimiterManager(arbCfg)
|
||||
|
||||
// Create market manager
|
||||
marketMgr := market.NewMarketManager(uniswapCfg, log)
|
||||
|
||||
// Create market scanner
|
||||
scanner := scanner.NewMarketScanner(botCfg, log)
|
||||
|
||||
// Create monitor (this would normally connect to a real RPC endpoint)
|
||||
// For testing, we'll just verify it can be created
|
||||
monitor, err := monitor.NewArbitrumMonitor(
|
||||
arbCfg,
|
||||
botCfg,
|
||||
log,
|
||||
rateLimiter,
|
||||
marketMgr,
|
||||
scanner,
|
||||
)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, monitor)
|
||||
|
||||
// Test that we can process a block of transactions
|
||||
// Create test transactions
|
||||
transactions := make([]*types.Transaction, 0)
|
||||
|
||||
// Create a transaction that interacts with a DEX
|
||||
to := common.HexToAddress("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") // Uniswap V3 pool
|
||||
tx := types.NewTransaction(0, to, big.NewInt(0), 0, big.NewInt(0), nil)
|
||||
transactions = append(transactions, tx)
|
||||
|
||||
// Create pipeline
|
||||
pipeline := market.NewPipeline(botCfg, log, marketMgr, scanner)
|
||||
pipeline.AddDefaultStages()
|
||||
|
||||
// Process transactions through the pipeline
|
||||
ctx := context.Background()
|
||||
blockNumber := uint64(12345)
|
||||
timestamp := uint64(time.Now().Unix())
|
||||
err = pipeline.ProcessTransactions(ctx, transactions, blockNumber, timestamp)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestConfigurationLoading(t *testing.T) {
|
||||
// This test would normally load a real config file
|
||||
// For now, we'll just test that the config package works
|
||||
cfg := &config.Config{
|
||||
Arbitrum: config.ArbitrumConfig{
|
||||
RPCEndpoint: "https://arb1.arbitrum.io/rpc",
|
||||
ChainID: 42161,
|
||||
},
|
||||
Bot: config.BotConfig{
|
||||
Enabled: true,
|
||||
},
|
||||
Uniswap: config.UniswapConfig{
|
||||
FactoryAddress: "0x1F98431c8aD98523631AE4a59f267346ea31F984",
|
||||
},
|
||||
Log: config.LogConfig{
|
||||
Level: "info",
|
||||
},
|
||||
Database: config.DatabaseConfig{
|
||||
File: "mev-bot.db",
|
||||
},
|
||||
}
|
||||
|
||||
// Verify the config was created correctly
|
||||
assert.Equal(t, "https://arb1.arbitrum.io/rpc", cfg.Arbitrum.RPCEndpoint)
|
||||
assert.Equal(t, int64(42161), cfg.Arbitrum.ChainID)
|
||||
assert.True(t, cfg.Bot.Enabled)
|
||||
assert.Equal(t, "0x1F98431c8aD98523631AE4a59f267346ea31F984", cfg.Uniswap.FactoryAddress)
|
||||
assert.Equal(t, "info", cfg.Log.Level)
|
||||
assert.Equal(t, "mev-bot.db", cfg.Database.File)
|
||||
}
|
||||
152
test/integration/pipeline_test.go
Normal file
152
test/integration/pipeline_test.go
Normal file
@@ -0,0 +1,152 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/fraktal/mev-beta/internal/config"
|
||||
"github.com/fraktal/mev-beta/internal/logger"
|
||||
"github.com/fraktal/mev-beta/pkg/events"
|
||||
"github.com/fraktal/mev-beta/pkg/market"
|
||||
"github.com/fraktal/mev-beta/pkg/scanner"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPipelineIntegration(t *testing.T) {
|
||||
// Create test config
|
||||
cfg := &config.BotConfig{
|
||||
MaxWorkers: 2,
|
||||
ChannelBufferSize: 5,
|
||||
MinProfitThreshold: 10.0,
|
||||
}
|
||||
|
||||
// Create test logger
|
||||
logger := logger.New("info", "text", "")
|
||||
|
||||
// Create market manager
|
||||
marketMgr := market.NewMarketManager(&config.UniswapConfig{
|
||||
Cache: config.CacheConfig{
|
||||
Expiration: 300,
|
||||
MaxSize: 10000,
|
||||
},
|
||||
}, logger)
|
||||
|
||||
// Create market scanner
|
||||
scanner := scanner.NewMarketScanner(cfg, logger)
|
||||
|
||||
// Create pipeline
|
||||
pipeline := market.NewPipeline(cfg, logger, marketMgr, scanner)
|
||||
|
||||
// Add default stages
|
||||
pipeline.AddDefaultStages()
|
||||
|
||||
// Create test transactions
|
||||
transactions := make([]*types.Transaction, 0)
|
||||
|
||||
// Create a transaction that interacts with a DEX
|
||||
to := common.HexToAddress("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") // Uniswap V3 pool
|
||||
tx := types.NewTransaction(0, to, big.NewInt(0), 0, big.NewInt(0), nil)
|
||||
transactions = append(transactions, tx)
|
||||
|
||||
// Process transactions through the pipeline
|
||||
ctx := context.Background()
|
||||
blockNumber := uint64(12345)
|
||||
timestamp := uint64(time.Now().Unix())
|
||||
err := pipeline.ProcessTransactions(ctx, transactions, blockNumber, timestamp)
|
||||
|
||||
// Verify no error
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestMarketManagerAndScannerIntegration(t *testing.T) {
|
||||
// Create test config
|
||||
cfg := &config.BotConfig{
|
||||
MinProfitThreshold: 10.0,
|
||||
}
|
||||
|
||||
// Create test logger
|
||||
logger := logger.New("info", "text", "")
|
||||
|
||||
// Create market manager
|
||||
marketMgr := market.NewMarketManager(&config.UniswapConfig{
|
||||
Cache: config.CacheConfig{
|
||||
Expiration: 300,
|
||||
MaxSize: 10000,
|
||||
},
|
||||
}, logger)
|
||||
|
||||
// Create market scanner
|
||||
scnr := scanner.NewMarketScanner(cfg, logger)
|
||||
|
||||
// Get a pool from the market manager
|
||||
ctx := context.Background()
|
||||
poolAddress := common.HexToAddress("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640")
|
||||
pool, err := marketMgr.GetPool(ctx, poolAddress)
|
||||
|
||||
// Verify no error and pool is not nil
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, pool)
|
||||
|
||||
// Get pools by tokens
|
||||
token0 := common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48") // USDC
|
||||
token1 := common.HexToAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2") // WETH
|
||||
pools := marketMgr.GetPoolsByTokens(token0, token1)
|
||||
|
||||
// Verify pools are returned
|
||||
assert.NotNil(t, pools)
|
||||
|
||||
// Use the variables to avoid unused variable warnings
|
||||
_ = scnr
|
||||
}
|
||||
|
||||
func TestEventParserAndPipelineIntegration(t *testing.T) {
|
||||
// Create test config
|
||||
cfg := &config.BotConfig{
|
||||
MaxWorkers: 2,
|
||||
ChannelBufferSize: 5,
|
||||
}
|
||||
|
||||
// Create test logger
|
||||
logger := logger.New("info", "text", "")
|
||||
|
||||
// Create market manager
|
||||
marketMgr := market.NewMarketManager(&config.UniswapConfig{
|
||||
Cache: config.CacheConfig{
|
||||
Expiration: 300,
|
||||
MaxSize: 10000,
|
||||
},
|
||||
}, logger)
|
||||
|
||||
// Create market scanner
|
||||
scnr := scanner.NewMarketScanner(cfg, logger)
|
||||
|
||||
// Create pipeline
|
||||
pipe := market.NewPipeline(cfg, logger, marketMgr, scnr)
|
||||
pipe.AddDefaultStages()
|
||||
|
||||
// Create event parser
|
||||
parser := events.NewEventParser()
|
||||
|
||||
// Create a transaction that interacts with a DEX
|
||||
to := common.HexToAddress("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640") // Uniswap V3 pool
|
||||
tx := types.NewTransaction(0, to, big.NewInt(0), 0, big.NewInt(0), nil)
|
||||
blockNumber := uint64(12345)
|
||||
timestamp := uint64(time.Now().Unix())
|
||||
|
||||
// Parse the transaction
|
||||
parsedEvents, err := parser.ParseTransaction(tx, blockNumber, timestamp)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, parsedEvents, 1)
|
||||
|
||||
// Verify the parsed event
|
||||
event := parsedEvents[0]
|
||||
assert.Equal(t, events.Swap, event.Type)
|
||||
assert.Equal(t, "UniswapV3", event.Protocol)
|
||||
assert.Equal(t, to, event.PoolAddress)
|
||||
assert.Equal(t, blockNumber, event.BlockNumber)
|
||||
assert.Equal(t, timestamp, event.Timestamp)
|
||||
}
|
||||
15
test/suite_test.go
Normal file
15
test/suite_test.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Test all packages
|
||||
func TestAllPackages(t *testing.T) {
|
||||
// This is a placeholder test that will run all package tests
|
||||
// when using go test ./...
|
||||
}
|
||||
|
||||
// Example of how to run tests with coverage:
|
||||
// go test -coverprofile=coverage.out ./...
|
||||
// go tool cover -html=coverage.out -o coverage.html
|
||||
131
test/testutils/testutils.go
Normal file
131
test/testutils/testutils.go
Normal file
@@ -0,0 +1,131 @@
|
||||
package testutils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/fraktal/mev-beta/internal/config"
|
||||
"github.com/fraktal/mev-beta/internal/logger"
|
||||
"github.com/fraktal/mev-beta/pkg/events"
|
||||
"github.com/fraktal/mev-beta/pkg/market"
|
||||
"github.com/fraktal/mev-beta/pkg/scanner"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
// CreateTestConfig creates a test configuration
|
||||
func CreateTestConfig() *config.Config {
|
||||
return &config.Config{
|
||||
Arbitrum: config.ArbitrumConfig{
|
||||
RPCEndpoint: "https://arb1.arbitrum.io/rpc",
|
||||
ChainID: 42161,
|
||||
RateLimit: config.RateLimitConfig{
|
||||
RequestsPerSecond: 10,
|
||||
MaxConcurrent: 5,
|
||||
Burst: 20,
|
||||
},
|
||||
},
|
||||
Bot: config.BotConfig{
|
||||
Enabled: true,
|
||||
PollingInterval: 1,
|
||||
MinProfitThreshold: 10.0,
|
||||
GasPriceMultiplier: 1.2,
|
||||
MaxWorkers: 10,
|
||||
ChannelBufferSize: 100,
|
||||
RPCTimeout: 30,
|
||||
},
|
||||
Uniswap: config.UniswapConfig{
|
||||
FactoryAddress: "0x1F98431c8aD98523631AE4a59f267346ea31F984",
|
||||
PositionManagerAddress: "0xC36442b4a4522E871399CD717aBDD847Ab11FE88",
|
||||
FeeTiers: []int64{500, 3000, 10000},
|
||||
Cache: config.CacheConfig{
|
||||
Enabled: true,
|
||||
Expiration: 300,
|
||||
MaxSize: 10000,
|
||||
},
|
||||
},
|
||||
Log: config.LogConfig{
|
||||
Level: "info",
|
||||
Format: "text",
|
||||
File: "",
|
||||
},
|
||||
Database: config.DatabaseConfig{
|
||||
File: "mev-bot.db",
|
||||
MaxOpenConnections: 10,
|
||||
MaxIdleConnections: 5,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// CreateTestLogger creates a test logger
|
||||
func CreateTestLogger() *logger.Logger {
|
||||
return logger.New("info", "text", "")
|
||||
}
|
||||
|
||||
// CreateTestEvent creates a test event
|
||||
func CreateTestEvent() *events.Event {
|
||||
return &events.Event{
|
||||
Type: events.Swap,
|
||||
Protocol: "UniswapV3",
|
||||
PoolAddress: common.HexToAddress("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640"),
|
||||
Token0: common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"),
|
||||
Token1: common.HexToAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"),
|
||||
Amount0: big.NewInt(1000000000),
|
||||
Amount1: big.NewInt(500000000000000000),
|
||||
SqrtPriceX96: uint256.NewInt(2505414483750470000),
|
||||
Liquidity: uint256.NewInt(1000000000000000000),
|
||||
Tick: 200000,
|
||||
Timestamp: uint64(time.Now().Unix()),
|
||||
TransactionHash: common.HexToHash("0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"),
|
||||
BlockNumber: 12345,
|
||||
}
|
||||
}
|
||||
|
||||
// CreateTestTransaction creates a test transaction
|
||||
func CreateTestTransaction() *types.Transaction {
|
||||
to := common.HexToAddress("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640")
|
||||
return types.NewTransaction(0, to, big.NewInt(0), 0, big.NewInt(0), nil)
|
||||
}
|
||||
|
||||
// CreateTestMarketManager creates a test market manager
|
||||
func CreateTestMarketManager() *market.MarketManager {
|
||||
cfg := &config.UniswapConfig{
|
||||
Cache: config.CacheConfig{
|
||||
Expiration: 300,
|
||||
MaxSize: 10000,
|
||||
},
|
||||
}
|
||||
logger := CreateTestLogger()
|
||||
return market.NewMarketManager(cfg, logger)
|
||||
}
|
||||
|
||||
// CreateTestScanner creates a test market scanner
|
||||
func CreateTestScanner() *scanner.MarketScanner {
|
||||
cfg := &config.BotConfig{
|
||||
MaxWorkers: 5,
|
||||
ChannelBufferSize: 10,
|
||||
RPCTimeout: 30,
|
||||
MinProfitThreshold: 10.0,
|
||||
}
|
||||
logger := CreateTestLogger()
|
||||
return scanner.NewMarketScanner(cfg, logger)
|
||||
}
|
||||
|
||||
// CreateTestPipeline creates a test pipeline
|
||||
func CreateTestPipeline() *market.Pipeline {
|
||||
cfg := &config.BotConfig{
|
||||
MaxWorkers: 5,
|
||||
ChannelBufferSize: 10,
|
||||
}
|
||||
logger := CreateTestLogger()
|
||||
marketMgr := CreateTestMarketManager()
|
||||
scanner := CreateTestScanner()
|
||||
return market.NewPipeline(cfg, logger, marketMgr, scanner)
|
||||
}
|
||||
|
||||
// CreateTestContext creates a test context
|
||||
func CreateTestContext() context.Context {
|
||||
return context.Background()
|
||||
}
|
||||
Reference in New Issue
Block a user