retry_delay = min(retry_delay * 2, max_retry_delay)
    
    async def precompute_token_allowlist(self):
        """
        Precompute a list of safe tokens to trade
        """
        try:
            # Initialize safe token list
            self.safe_tokens = set()
            self.safe_tokens.add(self.WSOL_MINT)  # WSOL is always safe
            
            # Add other known safe tokens
            known_safe_tokens = [
                # USDC
                "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
                # USDT
                "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
                # SOL (wrapped)
                "So11111111111111111111111111111111111111112",
            ]
            
            for token in known_safe_tokens:
                self.safe_tokens.add(token)
                
            logger.info(f"Precomputed {len(self.safe_#!/usr/bin/env python3
"""
🚀 Quantum Raydium MEV Bot - Ultra-Optimized Trading System
Enhanced for high-performance sandwich trading on Raydium AMM
Configured for RTX 4070 Ti with CUDA 11.8 acceleration
"""

import os
import json
import asyncio
import base64
import base58
import time
import signal
import sys
import traceback
import re
from datetime import datetime
from typing import Dict, List, Optional, Tuple, Any, Set, Union
import websockets

# Import custom modules
from config_loader import config
from solana_logger import logger

# GPU acceleration imports
try:
    import torch
    import numpy as np
    CUDA_AVAILABLE = torch.cuda.is_available()
    if CUDA_AVAILABLE:
        # Setup maximum CUDA performance
        torch.backends.cuda.matmul.allow_tf32 = True
        torch.backends.cudnn.benchmark = True
        torch.backends.cudnn.deterministic = False
        torch.backends.cuda.memory_stats = False
        # Create high-priority CUDA stream
        CUDA_STREAM = torch.cuda.Stream(priority=-3)
        logger.system(f"✅ CUDA {torch.version.cuda} initialized with PyTorch {torch.__version__}")
except ImportError:
    CUDA_AVAILABLE = False
    CUDA_STREAM = None
    logger.warning("PyTorch or NumPy not available, using CPU calculations only")

# Attempt to import the Rust trading core
try:
    from solana_rust_bot import TradingCore, TradeParams
    RUST_CORE_AVAILABLE = True
    logger.system("✅ Rust trading core loaded successfully")
except ImportError as e:
    # Use the minimal implementation from config_loader
    from config_loader import TradingCore, TradeParams
    RUST_CORE_AVAILABLE = False
    logger.warning(f"Rust trading core not available, using Python fallback: {e}")


class QuantumBlockhashManager:
    """
    Ultra-optimized blockhash acquisition and caching for minimal-latency transaction submission
    """
    def __init__(self, rpc_client, reuse_interval: float = 0.5):
        """
        Initialize the blockhash manager with optimized caching
        
        Args:
            rpc_client: The RPC client to use for blockhash queries
            reuse_interval: How long (in seconds) to reuse a blockhash before fetching a new one
        """
        self.rpc_client = rpc_client
        self.reuse_interval = reuse_interval
        self.latest_blockhash = None
        self.last_update_time = 0
        self.lock = asyncio.Lock()
        self.prefetch_task = None
        self.fetch_in_progress = False
        
    async def get_fresh_blockhash(self) -> str:
        """
        Always fetch a fresh blockhash from the network with optimized error handling
        
        Returns:
            str: The latest blockhash
        """
        if self.fetch_in_progress:
            # Wait a tiny bit to avoid multiple concurrent requests
            await asyncio.sleep(0.001)
            return await self.get_cached_blockhash()
            
        try:
            self.fetch_in_progress = True
            blockhash = await self.rpc_client.get_latest_blockhash()
            self.latest_blockhash = blockhash
            self.last_update_time = time.time()
            return blockhash
        except Exception as e:
            # If error, try cached value if available
            if self.latest_blockhash:
                logger.warning(f"Failed to get fresh blockhash, using cached one: {e}")
                return self.latest_blockhash
            else:
                raise ValueError(f"Failed to get blockhash: {e}")
        finally:
            self.fetch_in_progress = False
    
    async def get_cached_blockhash(self) -> str:
        """
        Get a cached blockhash if it's recent enough, otherwise fetch a new one
        
        Returns:
            str: The blockhash to use
        """
        current_time = time.time()
        
        # If we already have a recent blockhash, use it
        if (self.latest_blockhash and 
            current_time - self.last_update_time < self.reuse_interval):
            # Start prefetching the next one if we're halfway through the validity period
            if (current_time - self.last_update_time > self.reuse_interval/2 and
                not self.fetch_in_progress and not self.prefetch_task):
                self.prefetch_task = asyncio.create_task(self._prefetch_next_blockhash())
            return self.latest_blockhash
            
        # Otherwise, get a fresh blockhash
        return await self.get_fresh_blockhash()
        
    async def _prefetch_next_blockhash(self):
        """Prefetch the next blockhash in the background to reduce latency"""
        try:
            await self.get_fresh_blockhash()
        except Exception:
            pass  # Ignore errors in prefetch
        finally:
            self.prefetch_task = None
    
    async def get_blockhash(self, force_fresh: bool = False) -> str:
        """
        Get a blockhash with proper locking to prevent concurrent RPC requests
        
        Args:
            force_fresh: Whether to force fetching a fresh blockhash
            
        Returns:
            str: The blockhash to use
        """
        async with self.lock:
            if force_fresh:
                return await self.get_fresh_blockhash()
            else:
                return await self.get_cached_blockhash()


class QuantumProfitCalculator:
    """High-performance profit calculator leveraging GPU acceleration when available"""
    
    def __init__(self, default_min_profit: float = 0.002):
        self.default_min_profit = default_min_profit
        self.profit_cache = {}
        self.cache_hits = 0
        self.cache_misses = 0
        
        # Setup GPU acceleration if available
        if CUDA_AVAILABLE:
            # Create tensors for batch computation
            self.setup_cuda_tensors()
        
    def setup_cuda_tensors(self):
        """Setup CUDA tensors for rapid computation"""
        if not CUDA_AVAILABLE:
            return
            
        # Constants for profit calculation - optimized tensor shape (176)
        # Precompute all possible profit rates and costs
        amounts = torch.linspace(5.0, 320.0, 176, device='cuda')
        
        # Profit rates based on amount tiers
        profit_rates = torch.zeros_like(amounts)
        profit_rates[(amounts >= 5) & (amounts < 20)] = 0.015  # 1.5% for 5-20 SOL
        profit_rates[(amounts >= 20) & (amounts < 40)] = 0.020  # 2.0% for 20-40 SOL
        profit_rates[(amounts >= 40)] = 0.025  # 2.5% for 40+ SOL
        
        # Price impact and base costs
        impact_multiplier = 0.001  # Price impact (0.1%)
        base_cost = 0.002  # Base transaction cost
        
        # Precompute gross profit as tensor operation
        self.cuda_amounts = amounts
        self.cuda_profit_rates = profit_rates
        self.cuda_impact_multiplier = impact_multiplier
        self.cuda_base_cost = base_cost
            
        # Run warmup calculations
        with torch.cuda.stream(CUDA_STREAM):
            for _ in range(100):  # Warmup the GPU
                self._calculate_profit_cuda(50.0)
        
        logger.debug("GPU profit calculator initialized and warmed up")
        
    def _calculate_profit_cpu(self, amount: float) -> float:
        """CPU-based profit calculation for when GPU is unavailable"""
        # Determine profit rate based on amount
        if amount >= 40:
            profit_rate = 0.025  # 2.5% for large amounts
        elif amount >= 20:
            profit_rate = 0.020  # 2.0% for medium amounts
        elif amount >= 5:
            profit_rate = 0.015  # 1.5% for small amounts
        else:
            return 0.0  # Below minimum tradeable amount
            
        # Calculate costs
        base_cost = 0.002  # Base transaction cost (gas + priority)
        impact = 0.001 * amount  # Price impact (0.1%)
        
        # Calculate net profit
        gross_profit = amount * profit_rate
        net_profit = gross_profit - (impact * 2) - base_cost
        
        return max(0, net_profit)
    
    def _calculate_profit_cuda(self, amount: float) -> float:
        """CUDA-accelerated profit calculation for faster execution"""
        if amount < 5.0 or amount > 320.0:
            # Outside our precomputed range, fallback to CPU
            return self._calculate_profit_cpu(amount)
            
        with torch.cuda.stream(CUDA_STREAM):
            # Find closest precomputed amount
            idx = torch.abs(self.cuda_amounts - amount).argmin().item()
            
            # Get the profit rate for this amount
            profit_rate = self.cuda_profit_rates[idx].item()
            
            # Calculate impact and profit
            impact = self.cuda_impact_multiplier * amount
            gross_profit = amount * profit_rate
            net_profit = gross_profit - (impact * 2) - self.cuda_base_cost
            
        return max(0, net_profit)
    
    def calculate_profit(self, amount: float) -> float:
        """
        Calculate estimated profit for a trade opportunity using the fastest available method
        """
        # Check the cache first for exact matches
        cache_key = round(amount, 2)  # Round to 2 decimal places for caching
        if cache_key in self.profit_cache:
            self.cache_hits += 1
            return self.profit_cache[cache_key]
        
        self.cache_misses += 1
        
        # Calculate profit using the appropriate method
        if CUDA_AVAILABLE:
            profit = self._calculate_profit_cuda(amount)
        else:
            profit = self._calculate_profit_cpu(amount)
            
        # Cache the result
        self.profit_cache[cache_key] = profit
        
        # Only keep the most recent 1000 calculations
        if len(self.profit_cache) > 1000:
            # Simple LRU-like behavior: remove oldest entry
            oldest_key = next(iter(self.profit_cache))
            del self.profit_cache[oldest_key]
            
        return profit
    
    def get_cache_stats(self) -> Dict[str, int]:
        """Get cache performance statistics"""
        total = self.cache_hits + self.cache_misses
        hit_rate = (self.cache_hits / total) * 100 if total > 0 else 0
        return {
            "hits": self.cache_hits,
            "misses": self.cache_misses,
            "hit_rate": hit_rate,
            "cache_size": len(self.profit_cache)
        }


class RaydiumMEVBot:
    """Quantum Raydium MEV Bot for high-frequency sandwich trading with GPU acceleration"""
    
    def __init__(self):
        """Initialize the Quantum Raydium MEV bot with ultra-optimized components"""
        try:
            # Load configuration
            self.setup_environment()
            # Initialize trading components
            self.init_components()
            # Setup performance tracking
            self.setup_metrics()
            # Setup safety features
            self.setup_safety_features()
            # Log startup information
            self.log_startup_info()
        except Exception as e:
            logger.error(f"Initialization error: {e}")
            logger.debug(traceback.format_exc())
            raise
        
    def setup_environment(self):
        """Setup environment and load configuration"""
        # Core addresses and constants
        self.WSOL_MINT = "So11111111111111111111111111111111111111112"
        self.LAMPORTS_PER_SOL = 1_000_000_000
        
        # Network settings
        network_config = config.get_network_config()
        self.RPC_URL = network_config.get("rpc_url")
        self.WS_URL = network_config.get("ws_url")
        self.API_KEY = network_config.get("api_key")
        self.WALLET = config.get("SOLANA_PUBLIC_KEY")
        self.WSOL_ACCOUNT = config.get("WSOL_TOKEN_ACCOUNT")
        
        # Raydium program ID
        self.RAYDIUM_PROGRAM_ID = config.get("RAYDIUM_PROGRAM_ID")
        
        # Trading parameters
        trade_config = config.get_trade_config()
        self.POSITION_SIZE = trade_config.get("front_run_amount", 0.4)
        self.MIN_VICTIM_SIZE = trade_config.get("min_victim_size", 5.0)
        self.MAX_VICTIM_SIZE = trade_config.get("max_victim_size", 320.0)
        self.MIN_PROFIT = trade_config.get("min_profit", 0.002)
        self.COMPUTE_LIMIT = trade_config.get("compute_limit", 50000)
        self.PRIORITY_FEE = trade_config.get("priority_fee", 750000)
        
        # Solana price tracking
        self.PRICE_UPDATE_INTERVAL = 60  # seconds
        self.solana_price_usd = 0.0
        self.last_price_update = 0
        
        # Debugging options
        self.debug_mode = os.environ.get("DEBUG_MODE", "0") == "1"

        # Validate required accounts are present
        self._validate_required_accounts()
        
    def _validate_required_accounts(self):
        """Validate all required Raydium accounts are present"""
        required_accounts = [
            "RAYDIUM_PROGRAM_ID",
            "AMM_ID",
            "MARKET_AMM_AUTHORITY",
            "MARKET_AMM_OPEN_ORDERS",
            "MARKET_AMM_TARGET",
            "MARKET_POOL_TOKEN_ACCOUNT",
            "MARKET_POOL_PC_TOKEN_ACCOUNT",
            "SERUM_PROGRAM_ID",
            "MARKET_SERUM_MARKET",
            "MARKET_SERUM_BIDS",
            "MARKET_SERUM_ASKS",
            "MARKET_EVENT_QUEUE",
            "MARKET_BASE_VAULT",
            "MARKET_QUOTE_VAULT",
            "BASE_VAULT_SIGNER",
        ]
        
        missing_accounts = []
        for acc in required_accounts:
            if not config.get(acc):
                missing_accounts.append(acc)
                
        if missing_accounts:
            logger.warning(f"Missing required Raydium accounts: {', '.join(missing_accounts)}")
            logger.warning("These accounts must be added to your .env configuration")
            
    def init_components(self):
        """Initialize core trading components with performance optimizations"""
        try:
            # Initialize trading core with RPC URL
            self.trading_core = TradingCore(self.RPC_URL)
            
            # Initialize basic state
            self.active = True
            self.shutdown_requested = False
            
            # Initialize token validation cache
            self.validation_cache = {}
            
            # Initialize blockhash manager with optimized settings
            try:
                self.blockhash_manager = QuantumBlockhashManager(
                    self.trading_core,
                    reuse_interval=config.get_float("BLOCKHASH_REUSE_INTERVAL", 0.5)
                )
                logger.debug("Quantum BlockhashManager initialized successfully")
            except Exception as e:
                logger.warning(f"Failed to initialize BlockhashManager, using default: {e}")
                class FallbackBlockhashManager:
                    """Minimal fallback implementation"""
                    def __init__(self):
                        self.latest_blockhash = None
                        self.last_update_time = 0
                    
                    async def get_blockhash(self, force_fresh: bool = False) -> str:
                        import random
                        return f"fallback_blockhash_{int(time.time())}_{random.randint(1000, 9999)}"
                
                self.blockhash_manager = FallbackBlockhashManager()
            
            # Initialize GPU-accelerated profit calculator
            self.profit_calculator = QuantumProfitCalculator(default_min_profit=self.MIN_PROFIT)
            
            # Initialize ATA cache for token accounts
            self.ata_cache = {}
            
            # Initialize trading state caches
            self.processed_txs: Set[str] = set()
            self.recent_trades: List[Dict[str, Any]] = []
            
            # Initialize memory-efficient trade filtering
            self.ray_log_pattern = re.compile(r'ray_log:\s*([A-Za-z0-9+/=]+)')
            
            logger.system("Core components initialized with quantum optimizations")
        except Exception as e:
            logger.error(f"Component initialization error: {e}")
            logger.debug(traceback.format_exc())
            raise RuntimeError(f"Failed to initialize components: {e}")
            
    def setup_metrics(self):
        """Initialize performance metrics with enhanced tracking"""
        self.trades_found = 0
        self.trades_executed = 0
        self.successful_trades = 0
        self.total_profit = 0.0
        self.start_time = datetime.now()
        self.balances = {"SOL": 0.0, "WSOL": 0.0}
        self.execution_times = []
        self.profit_hist = []
        
        # Enhanced trade metrics
        self.trade_metrics = {
            "avg_front_run_time": 0,
            "avg_back_run_time": 0,
            "avg_total_time": 0,
            "front_run_times": [],
            "back_run_times": [],
            "total_times": [],
            "success_rate": 0,
            # Performance metrics for optimization tuning
            "ray_log_parse_times": [],
            "trade_validation_times": [],
            "blockhash_fetch_times": [],
        }
        
        # Track memory usage if CUDA is available
        if CUDA_AVAILABLE:
            self.peak_gpu_memory = 0
        
    def setup_safety_features(self):
        """Setup safety features to prevent trading errors"""
        # Concurrency controls with advanced semaphore
        self.trade_lock = asyncio.Lock()
        self.active_trades = 0
        self.MAX_ACTIVE_TRADES = config.get_int("MAX_ACTIVE_MEVS", 1)
        
        # Minimum balance thresholds
        balance_config = config.get_balance_config()
        self.min_sol_balance = balance_config.get("min_sol_balance", 0.03)
        self.min_wsol_balance = balance_config.get("min_wsol_balance", 0.02)
        
        # Trading state
        self.is_trading_paused = False
        self.last_trade_time = 0
        
        # Circuit breaker with advanced auto-recovery
        self.consecutive_failures = 0
        self.MAX_CONSECUTIVE_FAILURES = 5
        
        # Market sentiment tracking
        self.network_congestion = 0.3  # Medium congestion (0-1 scale)
        
        # Safe tokens set
        self.safe_tokens = set([self.WSOL_MINT])
        
        # Profit threshold
        self.min_profit_multiplier = 1.0  # Can be adjusted dynamically based on market conditions
        
    def log_startup_info(self):
        """Log startup information and configuration"""
        gpu_info = ""
        if CUDA_AVAILABLE:
            device = torch.cuda.get_device_properties(0)
            gpu_info = f"\nGPU: {device.name} | {device.total_memory/1024/1024/1024:.1f}GB VRAM | CUDA {torch.version.cuda}"
        
        logger.system(f"""
🚀 Quantum Raydium MEV Bot Starting
============================
Position Size: {self.POSITION_SIZE} SOL
Trade Range: {self.MIN_VICTIM_SIZE}-{self.MAX_VICTIM_SIZE} SOL
Min Profit: {self.MIN_PROFIT} SOL
Rust Core: {RUST_CORE_AVAILABLE}
GPU Acceleration: {CUDA_AVAILABLE}{gpu_info}
============================
Wallet: {self.WALLET}
WSOL Account: {self.WSOL_ACCOUNT}
============================
""")
        
    def extract_ray_log_data(self, log_line: str) -> Optional[bytes]:
        """Extract raw data from ray_log message with improved parsing"""
        try:
            if "ray_log:" not in log_line:
                return None
                
            # Use pre-compiled regex pattern for faster extraction
            match = self.ray_log_pattern.search(log_line)
            if not match:
                return None
                
            raw_base64 = match.group(1).strip()
            
            # Decode the base64 data
            raw_data = base64.b64decode(raw_base64)
            
            if len(raw_data) < 9:
                return None
                
            return raw_data
                
        except Exception as e:
            if self.debug_mode:
                logger.error(f"Error extracting ray_log data: {e}")
            return None
    
    async def validate_token(self, token_mint: str) -> bool:
        """
        Ultra-fast token validation with multi-level caching
        Returns True if token is valid, False otherwise
        """
        # Fast cache check
        if token_mint in self.validation_cache:
            return self.validation_cache[token_mint]
            
        # Always allow WSOL
        if token_mint == self.WSOL_MINT:
            self.validation_cache[token_mint] = True
            return True
            
        try:
            # Check if token is in our safe tokens set
            if token_mint in self.safe_tokens:
                self.validation_cache[token_mint] = True
                return True
                
            except Exception as e:
                # Record error details
                error_details = {
                    "error_type": type(e).__name__, 
                    "tx_id": tx_id,
                    "token": trade_data.get("token_a_mint", "unknown")
                }
                
                # Increment failure counter
                self.consecutive_failures += 1
                
                # Check if we need to trigger circuit breaker
                if self.consecutive_failures >= self.MAX_CONSECUTIVE_FAILURES:
                    logger.warning(f"Circuit breaker triggered after {self.consecutive_failures} consecutive failures")
                    self.is_trading_paused = True
                    # Auto-resume after delay
                    asyncio.create_task(self.auto_resume_trading(300))  # 5 minutes
                
                # Handle partial trade errors (front-run succeeded but back-run failed)
                if front_tx_id and not back_tx_id:
                    error_details["front_tx"] = front_tx_id
                    logger.error(f"Partial trade error (front-run sent but back-run failed): {e}", error_details)
                else:
                    logger.error(f"Trade execution error: {e}", error_details)
                    
                if self.debug_mode:
                    logger.debug(traceback.format_exc())
                    
                return trade_success
                
            finally:
                # Always decrement active trades counter
                self.active_trades -= 1
                self.last_trade_time = time.time()
    
    async def monitor_balances(self):
        """Monitor SOL and WSOL balances with optimized WebSocket handling"""
        retry_delay = 1
        max_retry_delay = 30
        
        while self.active:
            try:
                async with websockets.connect(
                    self.WS_URL,
                    extra_headers={
                        "api-key": self.API_KEY,
                        "User-Agent": "solana-client/1.18.23",
                    },
                    ping_interval=20,
                    ping_timeout=30,
                    close_timeout=60
                ) as ws:
                    # Reset retry delay on successful connection
                    retry_delay = 1
                    
                    # Define accounts to monitor
                    accounts = {
                        "SOL": self.WALLET,
                        "WSOL": self.WSOL_ACCOUNT
                    }
                    
                    # Subscribe to account changes
                    for acc_type, address in accounts.items():
                        await ws.send(json.dumps({
                            "jsonrpc": "2.0",
                            "id": 1 if acc_type == "SOL" else 2,
                            "method": "accountSubscribe",
                            "params": [
                                address,
                                {"encoding": "base64", "commitment": "confirmed"}
                            ]
                        }))
                        
                    # Track subscriptions
                    subs = {}
                    
                    # Process messages
                    while self.active:
                        try:
                            msg = await ws.recv()
                            data = json.loads(msg)
                            
                            # Handle subscription confirmation
                            if "result" in data:
                                sub_id = data["result"]
                                acc_type = "SOL" if data["id"] == 1 else "WSOL"
                                subs[sub_id] = acc_type
                                logger.debug(f"{acc_type} subscription active (ID: {sub_id})")
                                continue
                            
                            # Handle account notification
                            if "method" in data and data["method"] == "accountNotification":
                                params = data["params"]
                                sub_id = params["subscription"]
                                
                                if sub_id in subs:
                                    acc_type = subs[sub_id]
                                    value = params["result"]["value"]
                                    
                                    # Update SOL balance
                                    if acc_type == "SOL":
                                        lamports = int(value["lamports"])
                                        balance = lamports / self.LAMPORTS_PER_SOL
                                        
                                        # Skip if no significant change
                                        if abs(balance - self.balances[acc_type]) < 0.00001:
                                            continue
                                            
                                        # Record change
                                        old_balance = self.balances[acc_type]
                                        self.balances[acc_type] = balance
                                        change = balance - old_balance
                                        
                                        logger.info(f"SOL Balance: {balance:.4f} ({'+' if change >= 0 else ''}{change:.4f})")
                                    
                                    # Update WSOL balance  
                                    elif acc_type == "WSOL":
                                        try:
                                            if "data" in value:
                                                token_data = base64.b64decode(value["data"][0])
                                                if len(token_data) >= 72:
                                                    amount = int.from_bytes(token_data[64:72], "little")
                                                    balance = amount / self.LAMPORTS_PER_SOL
                                                    
                                                    # Skip if no significant change
                                                    if abs(balance - self.balances[acc_type]) < 0.00001:
                                                        continue
                                                        
                                                    # Record change
                                                    old_balance = self.balances[acc_type]
                                                    self.balances[acc_type] = balance
                                                    change = balance - old_balance
                                                    
                                                    logger.info(f"WSOL Balance: {balance:.4f} ({'+' if change >= 0 else ''}{change:.4f})")
                                        except Exception as e:
                                            logger.warning(f"WSOL data parse error: {e}")
                                            continue
                                    
                                    # Check for low balances
                                    if self.balances["SOL"] < self.min_sol_balance:
                                        logger.warning(f"Low SOL balance: {self.balances['SOL']:.4f}")
                                        
                                    if self.balances["WSOL"] < self.POSITION_SIZE:
                                        if not self.is_trading_paused:
                                            logger.warning(f"WSOL balance below position size, pausing trading: {self.balances['WSOL']:.4f}")
                                            self.is_trading_paused = True
                                    elif self.is_trading_paused and self.balances["WSOL"] >= self.POSITION_SIZE:
                                        logger.info(f"WSOL balance restored, resuming trading: {self.balances['WSOL']:.4f}")
                                        self.is_trading_paused = False
                        
                        except json.JSONDecodeError:
                            logger.warning("Invalid JSON received in balance WebSocket")
                            continue
                        except Exception as e:
                            if not self.shutdown_requested:
                                logger.error(f"Balance monitoring error: {e}")
                            break
                    
            except websockets.ConnectionClosed:
                logger.warning(f"Balance WebSocket disconnected, reconnecting in {retry_delay}s...")
                await asyncio.sleep(retry_delay)
                retry_delay = min(retry_delay * 2, max_retry_delay)
    
    async def update_solana_price(self):
        """Update Solana price periodically with optimized update scheduling"""
        retry_delay = 5
        max_retry_delay = 60
        
        while self.active:
            try:
                # If we already have a price, only update after the interval passes
                current_time = time.time()
                if self.solana_price_usd > 0 and current_time - self.last_price_update < self.PRICE_UPDATE_INTERVAL:
                    await asyncio.sleep(5)  # Short sleep if we don't need to update yet
                    continue
                    
                # Fetch price (simplified implementation)
                self.solana_price_usd = 140.04  # Placeholder price
                self.last_price_update = time.time()
                logger.info(f"Updated SOL price: ${self.solana_price_usd:.2f}")
                
                # Wait before next update
                await asyncio.sleep(self.PRICE_UPDATE_INTERVAL)
                
            except Exception as e:
                logger.warning(f"Solana price update failed: {e}")
                await asyncio.sleep(retry_delay)
                retry_delay = min(retry_delay * 2, max_retry_delay)
    
    async def monitor_market_conditions(self):
        """
        Monitor market conditions with dynamic parameter adjustment
        """
        update_interval = config.get_int("MARKET_UPDATE_INTERVAL", 300)  # 5 minutes default
        
        while self.active:
            try:
                # Get network status through latency check
                rpc_latency_start = time.time()
                try:
                    await self.trading_core.get_sol_balance()
                except Exception:
                    await asyncio.sleep(0.1)
                
                rpc_latency = time.time() - rpc_latency_start
                
                # Normalize latency to 0-1 scale 
                normalized_latency = min(rpc_latency, 1.0)
                
                # Exponential moving average for stability
                self.network_congestion = 0.8 * self.network_congestion + 0.2 * normalized_latency
                
                # Log significant changes
                if abs(normalized_latency - self.network_congestion) > 0.2:
                    logger.info(f"Network congestion update: {self.network_congestion:.2f} (latency: {rpc_latency*1000:.1f}ms)")
                
                # Dynamically adjust trading parameters based on network conditions
                
                # 1. Adjust priority fee based on network congestion
                if self.network_congestion > 0.8:  # High congestion
                    new_priority_fee = 3_000_000
                    # Also increase profit threshold in high congestion
                    self.min_profit_multiplier = 1.5
                elif self.network_congestion > 0.5:  # Medium congestion
                    new_priority_fee = 1_500_000
                    self.min_profit_multiplier = 1.2
                else:  # Low congestion
                    new_priority_fee = 750_000
                    self.min_profit_multiplier = 1.0
                    
                if new_priority_fee != self.PRIORITY_FEE:
                    logger.info(f"Adjusting priority fee: {self.PRIORITY_FEE} → {new_priority_fee}")
                    self.PRIORITY_FEE = new_priority_fee
                
                # Log cache performance periodically
                cache_stats = self.profit_calculator.get_cache_stats()
                logger.debug(f"Profit calculator cache: {cache_stats['hit_rate']:.1f}% hit rate, {cache_stats['cache_size']} entries")
                
                # Log GPU memory usage if available
                if CUDA_AVAILABLE:
                    current_mem = torch.cuda.memory_allocated() / (1024 * 1024)
                    logger.debug(f"GPU memory usage: {current_mem:.2f}MB, peak: {self.peak_gpu_memory:.2f}MB")
                    
                    # Periodically clear unused GPU cache to prevent memory issues
                    if current_mem > 500:  # If using more than 500MB
                        torch.cuda.empty_cache()
                        logger.debug("Cleared GPU cache")
                
                # Wait for next update
                await asyncio.sleep(update_interval)
                
            except Exception as e:
                logger.error(f"Market monitoring error: {e}")
                await asyncio.sleep(60)
    
    async def monitor_raydium_swaps(self):
        """Monitor Raydium program for swap opportunities with ultra-optimized parsing"""
        retry_delay = 1
        max_retry_delay = 30
        
        # Performance tracking
        logs_processed = 0
        opportunities_found = 0
        parse_times = []
        
        while self.active:
            try:
                async with websockets.connect(
                    self.WS_URL,
                    extra_headers={
                        "api-key": self.API_KEY,
                        "User-Agent": "solana-client/1.18.23",
                    },
                    ping_interval=20,
                    ping_timeout=30,
                    close_timeout=60
                ) as ws:
                    # Reset retry delay on successful connection
                    retry_delay = 1
                    logger.info("Connected to mempool WebSocket")
                    
                    # Subscribe to Raydium program logs
                    await ws.send(json.dumps({
                        "jsonrpc": "2.0",
                        "id": 1,
                        "method": "logsSubscribe",
                        "params": [
                            {"mentions": [self.RAYDIUM_PROGRAM_ID]},
                            {"commitment": "processed"}
                        ]
                    }))
                    
                    # Wait for subscription confirmation
                    confirmation = await ws.recv()
                    logger.info("Raydium logs subscription active")
                    
                    # Process messages with ultra-optimized parsing
                    while self.active:
                        try:
                            msg = await ws.recv()
                            
                            # Ultra-fast pre-check for relevant data before full JSON parsing
                            if '"ray_log:' not in msg:
                                continue
                                
                            data = json.loads(msg)
                            
                            if "params" in data:
                                result = data["params"].get("result", {})
                                logs = result.get("value", {}).get("logs", [])
                                tx_id = result.get("value", {}).get("signature", "unknown")
                                
                                # Skip if no logs (shouldn't happen with pre-check)
                                if not logs:
                                    continue
                                    
                                # Skip if not from Raydium (shouldn't happen with subscription)
                                if not logs[0].startswith(f"Program {self.RAYDIUM_PROGRAM_ID}"):
                                    continue
                                
                                # Skip if Jupiter is involved (avoid competing with aggregators)
                                if any("Program JUP" in log for log in logs):
                                    continue
                                
                                # Skip if already processed transaction
                                if tx_id in self.processed_txs:
                                    continue
                                    
                                logs_processed += 1
                                
                                # Check for ray_logs in transaction logs with optimized search
                                for log in logs:
                                    if "ray_log:" in log:
                                        parse_start = time.time()
                                        
                                        # Decode raw data
                                        raw_data = self.extract_ray_log_data(log)
                                        if not raw_data:
                                            continue
                                        
                                        # Try to parse trade data
                                        trade = await self.parse_trade_data(raw_data, tx_id)
                                        
                                        parse_time = time.time() - parse_start
                                        parse_times.append(parse_time)
                                        
                                        # Process valid trade opportunity
                                        if trade:
                                            self.trades_found += 1
                                            opportunities_found += 1
                                            
                                            logger.info(f"Found trade: {trade['amount']:.2f} SOL, estimated profit: {trade['net_profit']:.4f} SOL")
                                            
                                            # Check if we should execute this trade
                                            if (not self.is_trading_paused and 
                                                self.balances["WSOL"] >= self.POSITION_SIZE and
                                                self.balances["SOL"] >= self.min_sol_balance and
                                                self.active_trades < self.MAX_ACTIVE_TRADES):
                                                
                                                # Execute the trade in a separate task
                                                asyncio.create_task(self.execute_sandwich_trade(trade))
                                                
                                # Log performance periodically
                                if logs_processed % 1000 == 0:
                                    if parse_times:
                                        avg_parse_time = sum(parse_times) / len(parse_times)
                                        logger.debug(f"Mempool stats: {logs_processed} logs, {opportunities_found} opportunities, avg parse: {avg_parse_time*1000:.2f}ms")
                                        parse_times = parse_times[-100:]  # Keep only recent times
                                                
                        except json.JSONDecodeError:
                            continue
                        except Exception as e:
                            if not self.shutdown_requested:
                                logger.error(f"WebSocket message processing error: {e}")
                                if self.debug_mode:
                                    logger.debug(traceback.format_exc())
                            continue
                    
            except websockets.ConnectionClosed:
                logger.warning(f"WebSocket disconnected, reconnecting in {retry_delay}s...")
                await asyncio.sleep(retry_delay)
                retry_delay = min(retry_delay * 2, max_retry_delay)
            except Exception as e:
                if not self.shutdown_requested:
                    logger.error(f"Raydium monitor error: {e}")
                await asyncio.sleep(retry_delay)
                retry_delay = min(retry_delay * 2, max_retry_delay)
            except Exception as e:
                if not self.shutdown_requested:
                    logger.error(f"Balance monitor error: {e}")
                await asyncio.sleep(retry_delay)
                retry_delay = min(retry_delay * 2, max_retry_delay)
                
            # In production, you would add more comprehensive validation here
            # For now, we'll always validate tokens for maximum opportunity capture
            
            # Cache the result and return True
            self.validation_cache[token_mint] = True
            return True
            
        except Exception as e:
            if self.debug_mode:
                logger.error(f"Token validation error for {token_mint}: {e}")
            self.validation_cache[token_mint] = False
            return False
            
    async def parse_trade_data(self, raw_data: bytes, tx_id: str = None) -> Optional[dict]:
        """
        Ultra-optimized Raydium trade data parser with GPU acceleration
        
        Args:
            raw_data: Raw bytes from ray_log
            tx_id: Optional transaction ID for tracking
            
        Returns:
            Dictionary with trade details or None if invalid
        """
        try:
            # Skip if already processed
            if tx_id and tx_id in self.processed_txs:
                return None
            
            # Validate minimum data length for instruction type and amount
            if len(raw_data) < 9:
                return None
            
            # Extract instruction type and amount
            instruction_type = raw_data[0]
            amount = int.from_bytes(raw_data[1:9], "little") / self.LAMPORTS_PER_SOL
            
            # Fast filter: check instruction type and amount range
            valid_instructions = [0x03, 0x04, 0x09, 0x0a]
            if instruction_type not in valid_instructions:
                return None
            
            if not (self.MIN_VICTIM_SIZE <= amount <= self.MAX_VICTIM_SIZE):
                return None
            
            # Extract token mints with ultra-fast Rust decoder
            token_a_mint = ""
            token_b_mint = self.WSOL_MINT
            
            try:
                if RUST_CORE_AVAILABLE:
                    # Use our high-performance Rust implementation
                    token_a_mint, token_b_mint, _ = self.trading_core.decode_ray_log_py(raw_data)
                else:
                    # Fallback to Python extraction
                    if len(raw_data) >= 72:
                        token_a_bytes = raw_data[40:72]
                        token_a_mint = base58.b58encode(token_a_bytes).decode()
            except Exception:
                # Try fallback Python extraction if Rust decoder fails
                if len(raw_data) >= 72:
                    try:
                        token_a_bytes = raw_data[40:72]
                        token_a_mint = base58.b58encode(token_a_bytes).decode()
                    except Exception:
                        pass
            
            # If no token_a_mint, we can't process this trade
            if not token_a_mint:
                return None
            
            # Ultra-fast token validation
            is_valid = await self.validate_token(token_a_mint)
            if not is_valid:
                return None
                
            # Calculate profit potential using our GPU-accelerated calculator
            net_profit = self.profit_calculator.calculate_profit(amount)
            
            # Skip if not profitable
            adjusted_min_profit = self.MIN_PROFIT * self.min_profit_multiplier
            if net_profit <= adjusted_min_profit:
                return None
            
            # Mark as processed if tx_id provided
            if tx_id:
                self.processed_txs.add(tx_id)
                
                # Prevent the processed_txs set from growing too large
                if len(self.processed_txs) > 10000:
                    # Keep only the most recent transactions
                    self.processed_txs = set(list(self.processed_txs)[-5000:])
            
            # Return trade opportunity
            trade_data = {
                "victim_data": raw_data,
                "amount": amount,
                "token_a_mint": token_a_mint,
                "token_b_mint": token_b_mint,
                "net_profit": net_profit,
                "instruction_type": instruction_type,
                "transaction_id": tx_id or "unknown",
                "timestamp": time.time(),
                "profit_usd": net_profit * self.solana_price_usd
            }
            
            return trade_data
            
        except Exception as e:
            if self.debug_mode:
                logger.error(f"Trade data parse error: {e}")
                logger.debug(traceback.format_exc())
            return None

    async def check_initial_balances(self):
        """Check initial SOL and WSOL balances"""
        try:
            # Get SOL balance
            sol_balance = await self.trading_core.get_sol_balance()
            if sol_balance is not None:
                self.balances["SOL"] = sol_balance
            else:
                logger.error("Failed to get SOL balance")
            
            # Get WSOL balance
            wsol_balance = await self.trading_core.get_wsol_balance()
            if wsol_balance is not None:
                self.balances["WSOL"] = wsol_balance
            else:
                logger.error("Failed to get WSOL balance")
            
            # Log initial balances
            logger.info(f"Initial balances - SOL: {self.balances['SOL']:.4f}, WSOL: {self.balances['WSOL']:.4f}")
            
            # Check if balances are sufficient
            if self.balances["SOL"] < self.min_sol_balance:
                logger.warning(f"Low SOL balance: {self.balances['SOL']:.4f}")
                
            if self.balances["WSOL"] < self.POSITION_SIZE:
                logger.warning(f"WSOL balance below position size: {self.balances['WSOL']:.4f}")
            
            return self.balances
        except Exception as e:
            logger.error(f"Balance check error: {e}")
            if self.debug_mode:
                logger.debug(traceback.format_exc())
            return self.balances
    
    def calculate_profit(self, amount: float) -> float:
        """Proxy to the quantum profit calculator"""
        return self.profit_calculator.calculate_profit(amount)
    
    async def ensure_atas_for_trade(self, token_a_mint: str, token_b_mint: str) -> Tuple[bool, Optional[str]]:
        """
        Ultra-optimized ATA creation with caching
        
        Args:
            token_a_mint: The mint address of token A
            token_b_mint: The mint address of token B (usually WSOL)
            
        Returns:
            Tuple[bool, Optional[str]]: (Success status, Error message if any)
        """
        try:
            # Use Rust core to ensure ATAs exist if available
            if hasattr(self.trading_core, "ensure_ata_exists"):
                # Fast cache check
                if token_a_mint in self.ata_cache and token_b_mint in self.ata_cache:
                    return True, None
                
                # Ensure token A ATA exists
                token_a_ata = await self.trading_core.ensure_ata_exists(token_a_mint)
                # Cache the result
                self.ata_cache[token_a_mint] = token_a_ata
                
                # Ensure token B ATA exists (usually WSOL)
                token_b_ata = await self.trading_core.ensure_ata_exists(token_b_mint)
                # Cache the result
                self.ata_cache[token_b_mint] = token_b_ata
                
                return True, None
            else:
                # ATA creation is handled by the trading core automatically
                return True, None
                
        except Exception as e:
            error_msg = f"ATA preparation error: {str(e)}"
            logger.error(error_msg)
            return False, error_msg
    
    async def execute_trade_rust_core(self, trade_data: Dict[str, Any], is_buy: bool, 
                                     amount: int, blockhash: str = None) -> Optional[str]:
        """
        Execute a trade using the Rust core with explicit blockhash control
    
        Args:
            trade_data: Trade data dictionary
            is_buy: Whether this is a buy (True) or sell (False) trade
            amount: Amount in lamports (0 for sell_all)
            blockhash: Optional blockhash to use
        
        Returns:
            Optional[str]: Transaction signature if successful, None otherwise
        """
        try:
            # Prepare account list
            account_list = [
                config.get("RAYDIUM_PROGRAM_ID"),
                config.get("AMM_ID"),
                config.get("MARKET_AMM_AUTHORITY"),
                config.get("MARKET_AMM_OPEN_ORDERS"),
                config.get("MARKET_AMM_TARGET"),
                config.get("MARKET_POOL_TOKEN_ACCOUNT"),
                config.get("MARKET_POOL_PC_TOKEN_ACCOUNT"),
                config.get("SERUM_PROGRAM_ID"),
                config.get("MARKET_SERUM_MARKET"),
                config.get("MARKET_SERUM_BIDS"),
                config.get("MARKET_SERUM_ASKS"),
                config.get("MARKET_EVENT_QUEUE"),
                config.get("MARKET_BASE_VAULT"),
                config.get("MARKET_QUOTE_VAULT"),
                config.get("BASE_VAULT_SIGNER")
            ]
            
            # For sell_all, provide a minimal amount_in
            if not is_buy and amount == 0:
                amount_in = 1
            else:
                amount_in = amount if is_buy or amount > 0 else None
            
            # Create trade parameters
            params = TradeParams(
                accounts=account_list,
                amount_in=amount_in,
                is_buy=is_buy,
                token_a_mint=trade_data["token_a_mint"],
                token_b_mint=trade_data["token_b_mint"],
                victim_data=None,
                sell_all=not is_buy or amount == 0
            )
            
            # Set blockhash if provided
            try:
                if blockhash:
                    params.blockhash = blockhash
            except (AttributeError, TypeError):
                logger.debug("TradeParams does not support blockhash attribute, ignoring")
            
            # Execute the trade with optimized retries
            max_retries = min(3, config.get_int("MAX_RETRIES", 3))
            
            for attempt in range(max_retries):
                try:
                    tx_id = await self.trading_core.execute_trade_py(params)
                    if tx_id:
                        return tx_id
                except Exception as e:
                    retry_msg = f", retrying ({attempt+1}/{max_retries})" if attempt < max_retries - 1 else ""
                    logger.warning(f"Trade execution attempt failed: {e}{retry_msg}")
                    
                    if attempt < max_retries - 1:
                        # Short delay before retry - using exponential backoff
                        await asyncio.sleep(0.05 * (2 ** attempt))
        
            return None
            
        except Exception as e:
            logger.error(f"Trade execution error: {str(e)}")
            if self.debug_mode:
                logger.debug(traceback.format_exc())
            return None
    
    async def execute_sandwich_trade(self, trade_data: Dict[str, Any]) -> bool:
        """
        Execute a sandwich trade with ultra-optimized blockhash handling
        
        Args:
            trade_data: Dictionary containing details about the trade opportunity
            
        Returns:
            bool: True if trade was successful, False otherwise
        """
        if self.active_trades >= self.MAX_ACTIVE_TRADES:
            logger.warning(f"Too many active trades ({self.active_trades}), skipping opportunity")
            return False
            
        async with self.trade_lock:
            if self.is_trading_paused:
                logger.warning("Trading is paused, skipping opportunity")
                return False
                
            # Mark that we're starting a trade
            self.active_trades += 1
            tx_id = trade_data["transaction_id"]
            start_time = time.time()
            
            # Initialize tracking variables
            front_tx_id = None
            back_tx_id = None
            trade_success = False
            
            try:
                # Quick validation of balances
                if self.balances["WSOL"] < self.POSITION_SIZE:
                    logger.warning(f"Insufficient WSOL balance for trade: {self.balances['WSOL']:.4f} SOL")
                    return False
                    
                if self.balances["SOL"] < self.min_sol_balance:
                    logger.warning(f"Insufficient SOL balance for gas: {self.balances['SOL']:.4f} SOL")
                    return False
                
                # Ensure ATAs exist for both tokens
                atas_ready, error = await self.ensure_atas_for_trade(
                    trade_data["token_a_mint"],
                    trade_data["token_b_mint"]
                )
                
                if not atas_ready:
                    logger.error(f"Cannot execute trade - ATA preparation failed: {error}")
                    return False
                
                # Get a cached blockhash for front-run (faster entry)
                blockhash_start = time.time()
                cached_blockhash = await self.blockhash_manager.get_blockhash(force_fresh=False)
                blockhash_time = time.time() - blockhash_start
                self.trade_metrics["blockhash_fetch_times"].append(blockhash_time)
                
                # Execute front-run transaction
                front_run_start = time.time()
                front_tx_id = await self.execute_trade_rust_core(
                    trade_data,
                    is_buy=True,
                    amount=int(self.POSITION_SIZE * self.LAMPORTS_PER_SOL),
                    blockhash=cached_blockhash
                )
                    
                if not front_tx_id:
                    logger.error("Front-run transaction failed")
                    return False
                    
                front_run_time = time.time() - front_run_start
                self.trade_metrics["front_run_times"].append(front_run_time)
                logger.info(f"Front-run transaction sent: {front_tx_id} in {front_run_time*1000:.1f}ms")
                self.trades_executed += 1
                
                # Wait for victim transaction
                victim_wait_time = config.get_float("VICTIM_WAIT_TIME", 0.05)
                await asyncio.sleep(victim_wait_time)
                
                # Get a fresh blockhash for back-run
                fresh_blockhash = await self.blockhash_manager.get_blockhash(force_fresh=True)
                
                # Execute back-run transaction
                back_run_start = time.time()
                back_tx_id = await self.execute_trade_rust_core(
                    trade_data,
                    is_buy=False,  # Sell
                    amount=0,  # Sell all
                    blockhash=fresh_blockhash
                )
                    
                if not back_tx_id:
                    logger.error("Back-run transaction failed")
                    return False
                    
                back_run_time = time.time() - back_run_start
                self.trade_metrics["back_run_times"].append(back_run_time)
                logger.info(f"Back-run transaction sent: {back_tx_id} in {back_run_time*1000:.1f}ms")
                
                # Record success
                self.successful_trades += 1
                self.total_profit += trade_data["net_profit"]
                trade_success = True
                
                # Reset failure counter on success
                self.consecutive_failures = 0
                
                # Record execution time
                execution_time = time.time() - start_time
                self.execution_times.append(execution_time)
                self.trade_metrics["total_times"].append(execution_time)
                
                # Update average metrics
                self.trade_metrics["avg_front_run_time"] = sum(self.trade_metrics["front_run_times"][-20:]) / max(1, len(self.trade_metrics["front_run_times"][-20:]))
                self.trade_metrics["avg_back_run_time"] = sum(self.trade_metrics["back_run_times"][-20:]) / max(1, len(self.trade_metrics["back_run_times"][-20:]))
                self.trade_metrics["avg_total_time"] = sum(self.trade_metrics["total_times"][-20:]) / max(1, len(self.trade_metrics["total_times"][-20:]))
                self.trade_metrics["success_rate"] = (self.successful_trades / max(1, self.trades_executed)) * 100
                
                # Update GPU memory tracking
                if CUDA_AVAILABLE:
                    current_gpu_memory = torch.cuda.max_memory_allocated() / (1024 * 1024)  # MB
                    self.peak_gpu_memory = max(self.peak_gpu_memory, current_gpu_memory)
                
                # Log trade success with metrics
                trade_metrics = {
                    "front_tx": front_tx_id,
                    "back_tx": back_tx_id,
                    "victim_tx": tx_id,
                    "token": trade_data["token_a_mint"],
                    "amount": trade_data["amount"],
                    "profit": trade_data["net_profit"],
                    "front_run_time": front_run_time,
                    "back_run_time": back_run_time,
                    "total_time": execution_time,
                    "profit_usd": trade_data["net_profit"] * self.solana_price_usd
                }
                
                logger.trade(f"Sandwich complete in {execution_time*1000:.1f}ms - Profit: {trade_data['net_profit']:.6f} SOL (${trade_data['net_profit'] * self.solana_price_usd:.2f})", trade_metrics)
                
                # Add to recent trades list
                trade_summary = {
                    "time": datetime.now().strftime("%H:%M:%S"),
                    "token": trade_data["token_a_mint"][-5:],  # Last 5 chars of token address
                    "amount": trade_data["amount"],
                    "profit": trade_data["net_profit"],
                    "profit_usd": trade_data["net_profit"] * self.solana_price_usd,
                    "execution_time": execution_time,
                    "front_tx": front_tx_id[:8] + "...",  # First 8 chars of tx ID
                    "back_tx": back_tx_id[:8] + "..."     # First 8 chars of tx ID
                }
                
                self.recent_trades.append(trade_summary)
                if len(self.recent_trades) > 20:
                    self.recent_trades = self.recent_trades[-20:]
                
                # Add to profit history for analysis
                self.profit_hist.append(trade_data["net_profit"])
                
                return True("RAYDIUM_PROGRAM_ID"),
                config.get("AMM_ID"),
                config.get("MARKET_AMM_AUTHORITY"),
                config.get("MARKET_AMM_OPEN_ORDERS"),
                config.get("MARKET_AMM_TARGET"),
                config.get("MARKET_POOL_TOKEN_ACCOUNT"),
                config.get fix full script proper spacing please