120 lines
3.0 KiB
Go
120 lines
3.0 KiB
Go
//go:build validation
|
|
// +build validation
|
|
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/fraktal/mev-beta/internal/config"
|
|
)
|
|
|
|
func main() {
|
|
if len(os.Args) != 2 {
|
|
fmt.Fprintf(os.Stderr, "Usage: %s <config-file>\n", os.Args[0])
|
|
os.Exit(1)
|
|
}
|
|
|
|
configFile := os.Args[1]
|
|
|
|
// Load configuration
|
|
cfg, err := config.Load(configFile)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "Failed to load config: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
// Validate configuration
|
|
if err := validateConfig(cfg); err != nil {
|
|
fmt.Fprintf(os.Stderr, "Configuration validation failed: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
fmt.Println("Configuration validation successful")
|
|
}
|
|
|
|
func validateConfig(cfg *config.Config) error {
|
|
// Validate Arbitrum configuration
|
|
if err := validateArbitrumConfig(&cfg.Arbitrum); err != nil {
|
|
return fmt.Errorf("arbitrum config: %w", err)
|
|
}
|
|
|
|
// Validate bot configuration
|
|
if err := validateBotConfig(&cfg.Bot); err != nil {
|
|
return fmt.Errorf("bot config: %w", err)
|
|
}
|
|
|
|
// Validate other configurations...
|
|
return nil
|
|
}
|
|
|
|
func validateArbitrumConfig(cfg *config.ArbitrumConfig) error {
|
|
// Validate RPC endpoint format
|
|
if cfg.RPCEndpoint == "" {
|
|
return fmt.Errorf("rpc_endpoint is required")
|
|
}
|
|
|
|
if !isValidEndpoint(cfg.RPCEndpoint) {
|
|
return fmt.Errorf("invalid rpc_endpoint format: %s", cfg.RPCEndpoint)
|
|
}
|
|
|
|
// Validate chain ID
|
|
if cfg.ChainID != 42161 {
|
|
return fmt.Errorf("chain_id must be 42161 for Arbitrum mainnet, got: %d", cfg.ChainID)
|
|
}
|
|
|
|
// Validate rate limits
|
|
if cfg.RateLimit.RequestsPerSecond <= 0 {
|
|
return fmt.Errorf("requests_per_second must be positive, got: %d", cfg.RateLimit.RequestsPerSecond)
|
|
}
|
|
|
|
if cfg.RateLimit.MaxConcurrent <= 0 {
|
|
return fmt.Errorf("max_concurrent must be positive, got: %d", cfg.RateLimit.MaxConcurrent)
|
|
}
|
|
|
|
// Validate fallback endpoints
|
|
for i, endpoint := range cfg.FallbackEndpoints {
|
|
if !isValidEndpoint(endpoint.URL) {
|
|
return fmt.Errorf("invalid fallback endpoint %d: %s", i, endpoint.URL)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func validateBotConfig(cfg *config.BotConfig) error {
|
|
// Validate worker count
|
|
if cfg.MaxWorkers <= 0 {
|
|
return fmt.Errorf("max_workers must be positive, got: %d", cfg.MaxWorkers)
|
|
}
|
|
|
|
if cfg.MaxWorkers > 100 {
|
|
return fmt.Errorf("max_workers should not exceed 100 for stability, got: %d", cfg.MaxWorkers)
|
|
}
|
|
|
|
// Validate buffer size
|
|
if cfg.ChannelBufferSize <= 0 {
|
|
return fmt.Errorf("channel_buffer_size must be positive, got: %d", cfg.ChannelBufferSize)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func isValidEndpoint(endpoint string) bool {
|
|
// Remove environment variable syntax if present
|
|
endpoint = strings.TrimSpace(endpoint)
|
|
if strings.Contains(endpoint, "${") {
|
|
// Skip validation for environment variables
|
|
return true
|
|
}
|
|
|
|
// Check if it's a valid HTTP/HTTPS/WS/WSS URL
|
|
httpRegex := regexp.MustCompile(`^https?://[a-zA-Z0-9.-]+[a-zA-Z0-9.-]*[a-zA-Z0-9]/?(.*)?$`)
|
|
wsRegex := regexp.MustCompile(`^wss?://[a-zA-Z0-9.-]+[a-zA-Z0-9.-]*[a-zA-Z0-9]/?(.*)?$`)
|
|
|
|
return httpRegex.MatchString(endpoint) || wsRegex.MatchString(endpoint)
|
|
}
|