Restructured project for V2 refactor: **Structure Changes:** - Moved all V1 code to orig/ folder (preserved with git mv) - Created docs/planning/ directory - Added orig/README_V1.md explaining V1 preservation **Planning Documents:** - 00_V2_MASTER_PLAN.md: Complete architecture overview - Executive summary of critical V1 issues - High-level component architecture diagrams - 5-phase implementation roadmap - Success metrics and risk mitigation - 07_TASK_BREAKDOWN.md: Atomic task breakdown - 99+ hours of detailed tasks - Every task < 2 hours (atomic) - Clear dependencies and success criteria - Organized by implementation phase **V2 Key Improvements:** - Per-exchange parsers (factory pattern) - Multi-layer strict validation - Multi-index pool cache - Background validation pipeline - Comprehensive observability **Critical Issues Addressed:** - Zero address tokens (strict validation + cache enrichment) - Parsing accuracy (protocol-specific parsers) - No audit trail (background validation channel) - Inefficient lookups (multi-index cache) - Stats disconnection (event-driven metrics) Next Steps: 1. Review planning documents 2. Begin Phase 1: Foundation (P1-001 through P1-010) 3. Implement parsers in Phase 2 4. Build cache system in Phase 3 5. Add validation pipeline in Phase 4 6. Migrate and test in Phase 5 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
123 lines
4.4 KiB
Go
123 lines
4.4 KiB
Go
// Package main for initializing the exchange system
|
|
package exchanges
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/ethereum/go-ethereum/ethclient"
|
|
|
|
"github.com/fraktal/mev-beta/internal/logger"
|
|
"github.com/fraktal/mev-beta/pkg/math"
|
|
)
|
|
|
|
// InitializeExchangeSystem initializes the complete exchange system with all components
|
|
func InitializeExchangeSystem(client *ethclient.Client, logger *logger.Logger, config *DeploymentConfig) (*ExchangeRegistry, *CrossExchangeArbitrageFinder, error) {
|
|
// Validate configuration
|
|
if err := config.Validate(); err != nil {
|
|
return nil, nil, fmt.Errorf("invalid configuration: %w", err)
|
|
}
|
|
|
|
// Create exchange registry
|
|
registry := NewExchangeRegistry(client, logger)
|
|
|
|
// Load exchange configurations for the target chain
|
|
// This uses the existing LoadArbitrumExchanges function which already has
|
|
// configurations for Uniswap V3, SushiSwap, Curve, and Balancer on Arbitrum
|
|
if err := registry.LoadArbitrumExchanges(); err != nil {
|
|
return nil, nil, fmt.Errorf("failed to load exchange configurations: %w", err)
|
|
}
|
|
|
|
// Initialize pricing engine (this is already implemented in math package)
|
|
engine := math.NewExchangePricingEngine()
|
|
|
|
// Register Uniswap V2 (if not already registered in LoadArbitrumExchanges)
|
|
if _, exists := registry.exchanges[math.ExchangeUniswapV2]; !exists {
|
|
RegisterUniswapV2WithRegistry(registry)
|
|
}
|
|
|
|
// Initialize all exchange components
|
|
if err := registry.InitializeExchangeComponents(engine); err != nil {
|
|
return nil, nil, fmt.Errorf("failed to initialize exchange components: %w", err)
|
|
}
|
|
|
|
// Register additional exchange implementations
|
|
RegisterBalancerWithRegistry(registry)
|
|
RegisterPancakeSwapWithRegistry(registry)
|
|
RegisterDexAggregatorWithRegistry(registry)
|
|
|
|
// Create arbitrage finder
|
|
arbitrageFinder := NewCrossExchangeArbitrageFinder(client, logger, registry, engine)
|
|
|
|
// Set arbitrage parameters from config
|
|
arbitrageFinder.minSpread.SetFloat64(config.Arbitrage.MinSpreadPercentage / 100) // Convert percentage to decimal
|
|
arbitrageFinder.minProfit.SetUint64(uint64(config.MinProfit * 1e18)) // Convert ETH to wei
|
|
|
|
return registry, arbitrageFinder, nil
|
|
}
|
|
|
|
// RunArbitrageOpportunitySearch runs a search for arbitrage opportunities
|
|
func RunArbitrageOpportunitySearch(ctx context.Context, finder *CrossExchangeArbitrageFinder, tokenA, tokenB string) error {
|
|
tokenAAddr := StringToAddress(tokenA)
|
|
tokenBAddr := StringToAddress(tokenB)
|
|
|
|
opportunities, err := finder.FindArbitrageOpportunities(ctx, tokenAAddr, tokenBAddr)
|
|
if err != nil {
|
|
return fmt.Errorf("error finding arbitrage opportunities: %w", err)
|
|
}
|
|
|
|
// Process and log opportunities
|
|
for _, opp := range opportunities {
|
|
fmt.Printf("Arbitrage Opportunity Found:\n")
|
|
fmt.Printf(" Token Pair: %s -> %s\n", opp.TokenIn.Hex(), opp.TokenOut.Hex())
|
|
fmt.Printf(" Buy Exchange: %s\n", opp.BuyExchange)
|
|
fmt.Printf(" Sell Exchange: %s\n", opp.SellExchange)
|
|
spreadPercentFloat, _ := opp.SpreadPercent.Float64()
|
|
fmt.Printf(" Spread: %.4f%%\n", spreadPercentFloat*100)
|
|
fmt.Printf(" Estimated Profit: %s ETH\n", opp.Profit.String())
|
|
fmt.Printf(" Net Profit: %s ETH (after gas)\n", opp.NetProfit.String())
|
|
fmt.Printf(" ROI: %.4f%%\n", opp.ROI)
|
|
fmt.Printf(" Confidence: %.2f\n", opp.Confidence)
|
|
fmt.Println()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// StringToAddress converts a string to common.Address
|
|
func StringToAddress(s string) [20]byte {
|
|
// In a real implementation, this would properly validate the string
|
|
// and return the address. For this example, we'll use a simplified version.
|
|
addr := [20]byte{}
|
|
for i := 0; i < len(s) && i < 20; i++ {
|
|
addr[i] = s[i]
|
|
}
|
|
return addr
|
|
}
|
|
|
|
// RunSystemHealthCheck performs a health check of the exchange system
|
|
func RunSystemHealthCheck(registry *ExchangeRegistry) map[string]interface{} {
|
|
health := make(map[string]interface{})
|
|
|
|
// Check if registry has exchanges
|
|
exchanges := registry.GetAllExchanges()
|
|
health["exchanges_count"] = len(exchanges)
|
|
health["exchanges"] = func() []string {
|
|
var names []string
|
|
for _, ex := range exchanges {
|
|
names = append(names, ex.Name)
|
|
}
|
|
return names
|
|
}()
|
|
|
|
// Check if all required interfaces are registered
|
|
health["pool_detectors_registered"] = len(registry.poolDetectors) > 0
|
|
health["liquidity_fetchers_registered"] = len(registry.liquidityFetchers) > 0
|
|
health["swap_routers_registered"] = len(registry.swapRouters) > 0
|
|
|
|
// Add more health checks as needed
|
|
health["status"] = "healthy"
|
|
|
|
return health
|
|
}
|