KEY_METRICS = {
    "base_supply": "SOL amount in pool",
    "quote_supply": "wSOL amount in pool",
    "volume_24h": "24-hour trading volume",
    "liquidity": "Total USD value locked",
    "price": "Current SOL/wSOL ratio",
    "last_update": "Unix timestamp of update"
}

# Byte positions in pool data
METRIC_POSITIONS = {
    "BASE_SUPPLY": [8, 16],    # SOL reserve
    "QUOTE_SUPPLY": [16, 24],  # wSOL reserve
    "VOLUME_24H": [112, 120],  # 24h volume
    "LIQUIDITY": [128, 136]    # Total liquidity
}

# Solana Trading Bot Keypair Implementation Guide

## Overview
When implementing a Solana trading bot that bridges Python and Rust components, the key to successful keypair handling lies in leveraging the native capabilities of the Rust layer rather than attempting complex keypair manipulation in Python. The solution involves a streamlined approach where configuration management happens in Python while delegating all cryptographic and keypair-specific operations to the Rust engine.

## Detailed Implementation Notes

### Configuration Structure
The trading bot relies on a config.json file that contains all necessary wallet information, including the wallet address, environment variable flags, and keypair paths. This configuration serves as the single source of truth for both Python and Rust components. The wallet configuration supports multiple authentication methods including environment variables and keypair files, allowing for flexible deployment scenarios.

### Keypair Handling
Instead of manually manipulating keypairs in Python (which led to issues with byte length validation and format conversion), we allow the Rust TradingEngine to handle all keypair-related operations. The Rust layer is specifically designed to work with Solana's cryptographic requirements and can properly handle the base58 encoding, byte length validation, and proper keypair formatting that Solana requires.

### Environment Variables
The system supports environment variable-based authentication using SOLANA_PRIVATE_KEY and SOLANA_PUBLIC_KEY. When these are set, the Rust engine automatically detects and uses them, removing the need for manual keypair file management. This is particularly useful in production environments where secure use log::{info, warn};
use pyo3::{exceptions::PyValueError, prelude::*};
use pyo3_asyncio::tokio::future_into_py;
use solana_client::nonblocking::rpc_client::RpcClient;
use solana_sdk::{
    commitment_config::{CommitmentConfig, CommitmentLevel},
    compute_budget::ComputeBudgetInstruction,
    instruction::Instruction,
    message::Message,
    pubkey::Pubkey,
    signature::{Keypair, Signer},
    transaction::Transaction,
};
use spl_associated_token_account::{
    get_associated_token_address,
    instruction::create_associated_token_account_idempotent,
};
use spl_token;
use std::{
    env,
    str::FromStr,
    sync::Arc,
    time::Duration,
};
use base58::FromBase58;

// Constants
const COMPUTE_UNITS: u32 = 200_000;
const PRIORITY_FEE: u64 = 1_000_000;
const CONFIRM_TIMEOUT: u64 = 30; // seconds

#[pyclass]
#[derive(Clone)]
pub struct TradeParams {
    #[pyo3(get, set)]
    pub accounts: Vec<String>,
    #[pyo3(get, set)]
    pub amount_in: Option<u64>,
    #[pyo3(get, set)]
    pub is_buy: bool,
    #[pyo3(get, set)]
    pub token_a_mint: String,
    #[pyo3(get, set)]
    pub token_b_mint: String,
    #[pyo3(get, set)]
    pub sell_all: bool,
    #[pyo3(get, set)]
    pub victim_data: Option<Vec<u8>>,
}

#[pyclass]
pub struct TradingCore {
    client: Arc<RpcClient>,
    keypair: Arc<Keypair>,
}

impl TradingCore {
    fn load_keypair_from_env() -> PyResult<Keypair> {
        let private_key = env::var("SOLANA_PRIVATE_KEY")
            .map_err(|_| PyValueError::new_err("SOLANA_PRIVATE_KEY not found"))?;
        
        let secret_key: Vec<u8> = private_key.from_base58()
            .map_err(|e| PyValueError::new_err(format!("Invalid private key: {}", e)))?;
        
        Keypair::from_bytes(&secret_key)
            .map_err(|e| PyValueError::new_err(format!("Keypair error: {}", e)))
    }

    async fn ensure_ata_exists(
        &self, 
        mint: &Pubkey
    ) -> PyResult<Pubkey> {
        let owner = self.keypair.pubkey();
        let ata = get_associated_token_address(&owner, mint);
        
        // Check if ATA exists
        if self.client.get_account(&ata).await.is_ok() {
            info!("ATA exists: {}", ata);
            return Ok(ata);
        }

        // Create ATA instruction
        let ix = create_associated_token_account_idempotent(
            &self.keypair.pubkey(),
            &owner,
            mint,
            &spl_token::ID
        );

        let blockhash = self.client.get_latest_blockhash().await
            .map_err(|e| PyValueError::new_err(format!("Blockhash error: {}", e)))?;

        let mut tx = Transaction::new_with_payer(&[ix], Some(&self.keypair.pubkey()));
        tx.sign(&[self.keypair.as_ref()], blockhash);

        // Send and confirm transaction
        let sig = self.client.send_transaction_with_config(
            &tx,
            solana_client::rpc_config::RpcSendTransactionConfig {
                skip_preflight: false,
                preflight_commitment: Some(CommitmentLevel::Confirmed),
                encoding: None,
                max_retries: Some(5),
                min_context_slot: None,
            },
        )
        .await
        .map_err(|e| PyValueError::new_err(format!("Send error: {}", e)))?;

        // Wait for confirmation
        let start = std::time::Instant::now();
        loop {
            let status = self.client.get_signature_status(&sig).await
                .map_err(|e| PyValueError::new_err(format!("Status error: {}", e)))?;
            
            if status.is_some() {
                info!("ATA created: {}", ata);
                return Ok(ata);
            }
            
            if start.elapsed().as_secs() > CONFIRM_TIMEOUT {
                return Err(PyValueError::new_err("ATA creation timeout"));
            }
            
            tokio::time::sleep(Duration::from_secs(1)).await;
        }
    }

    fn create_swap_instruction(
        &self,
        program_id: &Pubkey,
        accounts: &[Pubkey],
        amount: u64,
        is_buy: bool,
        source_ata: Pubkey,
        dest_ata: Pubkey,
        victim_data: Option<&[u8]>,
    ) -> Instruction {
        let mut data = vec![if is_buy { 9u8 } else { 11u8 }];
        if let Some(vdata) = victim_data {
            data.extend_from_slice(vdata);
        } else {
            data.extend_from_slice(&amount.to_le_bytes());
        }

        let mut metas = accounts.iter().map(|a| {
            solana_sdk::instruction::AccountMeta::new_readonly(*a, false)
        }).collect::<Vec<_>>();

        // Update source and destination accounts
        if is_buy {
            metas[15] = solana_sdk::instruction::AccountMeta::new(source_ata, false);
            metas[16] = solana_sdk::instruction::AccountMeta::new(dest_ata, false);
        } else {
            metas[15] = solana_sdk::instruction::AccountMeta::new(dest_ata, false);
            metas[16] = solana_sdk::instruction::AccountMeta::new(source_ata, false);
        }

        metas[17] = solana_sdk::instruction::AccountMeta::new(self.keypair.pubkey(), true);

        Instruction {
            program_id: *program_id,
            accounts: metas,
            data,
        }
    }
}

#[pymethods]
impl TradingCore {
    #[new]
    fn new(rpc_url: &str) -> PyResult<Self> {
        let keypair = Self::load_keypair_from_env()?;
        info!("Loaded keypair: {}", keypair.pubkey());
        
        Ok(Self {
            client: Arc::new(RpcClient::new_with_commitment(
                rpc_url.to_string(),
                CommitmentConfig::confirmed(),
            )),
            keypair: Arc::new(keypair),
        })
    }

    fn execute_trade_py<'py>(&self, params: &TradeParams, py: Python<'py>) -> PyResult<&'py PyAny> {
        let params = params.clone();
        let self_clone = Self {
            client: self.client.clone(),
            keypair: self.keypair.clone(),
        };
        
        future_into_py(py, async move {
            // Convert accounts
            let accounts = params.accounts.iter()
                .map(|a| Pubkey::from_str(a))
                .collect::<Result<Vec<_>, _>>()
                .map_err(|e| PyValueError::new_err(format!("Invalid account: {}", e)))?;

            // Get token mints
            let token_a = Pubkey::from_str(&params.token_a_mint)
                .map_err(|e| PyValueError::new_err(format!("Invalid token A: {}", e)))?;
            let token_b = Pubkey::from_str(&params.token_b_mint)
                .map_err(|e| PyValueError::new_err(format!("Invalid token B: {}", e)))?;

            // Ensure ATAs exist
            let (source_mint, dest_mint) = if params.is_buy {
                (&token_b, &token_a)
            } else {
                (&token_a, &token_b)
            };
            
            let source_ata = self_clone.ensure_ata_exists(source_mint).await?;
            let dest_ata = self_clone.ensure_ata_exists(dest_mint).await?;

            // Prepare instructions
            let mut instructions = vec![
                ComputeBudgetInstruction::set_compute_unit_limit(COMPUTE_UNITS),
                ComputeBudgetInstruction::set_compute_unit_price(PRIORITY_FEE),
            ];

            // Get swap amount
            let amount = if let Some(amt) = params.amount_in {
                amt
            } else if params.sell_all {
                self_clone.client.get_token_account_balance(&source_ata).await
                    .map_err(|e| PyValueError::new_err(format!("Balance error: {}", e)))?
                    .amount.parse::<u64>()
                    .map_err(|e| PyValueError::new_err(format!("Parse error: {}", e)))?
            } else {
                return Err(PyValueError::new_err("No amount specified"));
            };

            // Create swap instruction
            let swap_ix = self_clone.create_swap_instruction(
                &accounts[0],
                &accounts,
                amount,
                params.is_buy,
                source_ata,
                dest_ata,
                params.victim_data.as_deref(),
            );
            instructions.push(swap_ix);

            // Create and send transaction
            let blockhash = self_clone.client.get_latest_blockhash().await
                .map_err(|e| PyValueError::new_err(format!("Blockhash error: {}", e)))?;

            let msg = Message::new_with_blockhash(
                &instructions,
                Some(&self_clone.keypair.pubkey()),
                &blockhash,
            );

            let mut tx = Transaction::new_unsigned(msg);
            tx.sign(&[self_clone.keypair.as_ref()], blockhash)
                .map_err(|e| PyValueError::new_err(format!("Sign error: {:?}", e)))?;

            let sig = self_clone.client.send_transaction_with_config(
                &tx,
                solana_client::rpc_config::RpcSendTransactionConfig {
                    skip_preflight: false,
                    preflight_commitment: Some(CommitmentLevel::Confirmed),
                    encoding: None,
                    max_retries: Some(5),
                    min_context_slot: None,
                },
            )
            .await
            .map_err(|e| PyValueError::new_err(format!("Send error: {}", e)))?;

            // Confirm transaction
            let _ = self_clone.client.confirm_transaction_with_commitment(
                &sig,
                CommitmentConfig::confirmed(),
            )
            .await
            .map_err(|e| PyValueError::new_err(format!("Confirmation error: {}", e)))?;

            Ok(sig.to_string())
        })
    }

    // ... rest of the methods ...
}key management is critical.use log::{info, warn};
use pyo3::{exceptions::PyValueError, prelude::*};
use pyo3_asyncio::tokio::future_into_py;
use solana_client::nonblocking::rpc_client::RpcClient;
use solana_sdk::{
    commitment_config::{CommitmentConfig, CommitmentLevel},
    compute_budget::ComputeBudgetInstruction,
    instruction::Instruction,
    message::Message,
    pubkey::Pubkey,
    signature::{Keypair, Signer},
    transaction::Transaction,
};
use spl_associated_token_account::{
    get_associated_token_address,
    instruction::create_associated_token_account_idempotent,
};
use spl_token;
use std::{
    env,
    str::FromStr,
    sync::Arc,
    time::Duration,
};
use base58::FromBase58;

// Constants
const COMPUTE_UNITS: u32 = 200_000;
const PRIORITY_FEE: u64 = 1_000_000;
const CONFIRM_TIMEOUT: u64 = 30; // seconds

#[pyclass]
#[derive(Clone)]
pub struct TradeParams {
    #[pyo3(get, set)]
    pub accounts: Vec<String>,
    #[pyo3(get, set)]
    pub amount_in: Option<u64>,
    #[pyo3(get, set)]
    pub is_buy: bool,
    #[pyo3(get, set)]
    pub token_a_mint: String,
    #[pyo3(get, set)]
    pub token_b_mint: String,
    #[pyo3(get, set)]
    pub sell_all: bool,
    #[pyo3(get, set)]
    pub victim_data: Option<Vec<u8>>,
}

#[pyclass]
pub struct TradingCore {
    client: Arc<RpcClient>,
    keypair: Arc<Keypair>,
}

impl TradingCore {
    fn load_keypair_from_env() -> PyResult<Keypair> {
        let private_key = env::var("SOLANA_PRIVATE_KEY")
            .map_err(|_| PyValueError::new_err("SOLANA_PRIVATE_KEY not found"))?;
        
        let secret_key: Vec<u8> = private_key.from_base58()
            .map_err(|e| PyValueError::new_err(format!("Invalid private key: {}", e)))?;
        
        Keypair::from_bytes(&secret_key)
            .map_err(|e| PyValueError::new_err(format!("Keypair error: {}", e)))
    }

    async fn ensure_ata_exists(
        &self, 
        mint: &Pubkey
    ) -> PyResult<Pubkey> {
        let owner = self.keypair.pubkey();
        let ata = get_associated_token_address(&owner, mint);
        
        // Check if ATA exists
        if self.client.get_account(&ata).await.is_ok() {
            info!("ATA exists: {}", ata);
            return Ok(ata);
        }

        // Create ATA instruction
        let ix = create_associated_token_account_idempotent(
            &self.keypair.pubkey(),
            &owner,
            mint,
            &spl_token::ID
        );

        let blockhash = self.client.get_latest_blockhash().await
            .map_err(|e| PyValueError::new_err(format!("Blockhash error: {}", e)))?;

        let mut tx = Transaction::new_with_payer(&[ix], Some(&self.keypair.pubkey()));
        tx.sign(&[self.keypair.as_ref()], blockhash);

        // Send and confirm transaction
        let sig = self.client.send_transaction_with_config(
            &tx,
            solana_client::rpc_config::RpcSendTransactionConfig {
                skip_preflight: false,
                preflight_commitment: Some(CommitmentLevel::Confirmed),
                encoding: None,
                max_retries: Some(5),
                min_context_slot: None,
            },
        )
        .await
        .map_err(|e| PyValueError::new_err(format!("Send error: {}", e)))?;

        // Wait for confirmation
        let start = std::time::Instant::now();
        loop {
            let status = self.client.get_signature_status(&sig).await
                .map_err(|e| PyValueError::new_err(format!("Status error: {}", e)))?;
            
            if status.is_some() {
                info!("ATA created: {}", ata);
                return Ok(ata);
            }
            
            if start.elapsed().as_secs() > CONFIRM_TIMEOUT {
                return Err(PyValueError::new_err("ATA creation timeout"));
            }
            
            tokio::time::sleep(Duration::from_secs(1)).await;
        }
    }

    fn create_swap_instruction(
        &self,
        program_id: &Pubkey,
        accounts: &[Pubkey],
        amount: u64,
        is_buy: bool,
        source_ata: Pubkey,
        dest_ata: Pubkey,
        victim_data: Option<&[u8]>,
    ) -> Instruction {
        let mut data = vec![if is_buy { 9u8 } else { 11u8 }];
        if let Some(vdata) = victim_data {
            data.extend_from_slice(vdata);
        } else {
            data.extend_from_slice(&amount.to_le_bytes());
        }

        let mut metas = accounts.iter().map(|a| {
            solana_sdk::instruction::AccountMeta::new_readonly(*a, false)
        }).collect::<Vec<_>>();

        // Update source and destination accounts
        if is_buy {
            metas[15] = solana_sdk::instruction::AccountMeta::new(source_ata, false);
            metas[16] = solana_sdk::instruction::AccountMeta::new(dest_ata, false);
        } else {
            metas[15] = solana_sdk::instruction::AccountMeta::new(dest_ata, false);
            metas[16] = solana_sdk::instruction::AccountMeta::new(source_ata, false);
        }

        metas[17] = solana_sdk::instruction::AccountMeta::new(self.keypair.pubkey(), true);

        Instruction {
            program_id: *program_id,
            accounts: metas,
            data,
        }
    }
}

#[pymethods]
impl TradingCore {
    #[new]
    fn new(rpc_url: &str) -> PyResult<Self> {
        let keypair = Self::load_keypair_from_env()?;
        info!("Loaded keypair: {}", keypair.pubkey());
        
        Ok(Self {
            client: Arc::new(RpcClient::new_with_commitment(
                rpc_url.to_string(),
                CommitmentConfig::confirmed(),
            )),
            keypair: Arc::new(keypair),
        })
    }

    fn execute_trade_py<'py>(&self, params: &TradeParams, py: Python<'py>) -> PyResult<&'py PyAny> {
        let params = params.clone();
        let self_clone = Self {
            client: self.client.clone(),
            keypair: self.keypair.clone(),
        };
        
        future_into_py(py, async move {
            // Convert accounts
            let accounts = params.accounts.iter()
                .map(|a| Pubkey::from_str(a))
                .collect::<Result<Vec<_>, _>>()
                .map_err(|e| PyValueError::new_err(format!("Invalid account: {}", e)))?;

            // Get token mints
            let token_a = Pubkey::from_str(&params.token_a_mint)
                .map_err(|e| PyValueError::new_err(format!("Invalid token A: {}", e)))?;
            let token_b = Pubkey::from_str(&params.token_b_mint)
                .map_err(|e| PyValueError::new_err(format!("Invalid token B: {}", e)))?;

            // Ensure ATAs exist
            let (source_mint, dest_mint) = if params.is_buy {
                (&token_b, &token_a)
            } else {
                (&token_a, &token_b)
            };
            
            let source_ata = self_clone.ensure_ata_exists(source_mint).await?;
            let dest_ata = self_clone.ensure_ata_exists(dest_mint).await?;

            // Prepare instructions
            let mut instructions = vec![
                ComputeBudgetInstruction::set_compute_unit_limit(COMPUTE_UNITS),
                ComputeBudgetInstruction::set_compute_unit_price(PRIORITY_FEE),
            ];

            // Get swap amount
            let amount = if let Some(amt) = params.amount_in {
                amt
            } else if params.sell_all {
                self_clone.client.get_token_account_balance(&source_ata).await
                    .map_err(|e| PyValueError::new_err(format!("Balance error: {}", e)))?
                    .amount.parse::<u64>()
                    .map_err(|e| PyValueError::new_err(format!("Parse error: {}", e)))?
            } else {
                return Err(PyValueError::new_err("No amount specified"));
            };

            // Create swap instruction
            let swap_ix = self_clone.create_swap_instruction(
                &accounts[0],
                &accounts,
                amount,
                params.is_buy,
                source_ata,
                dest_ata,
                params.victim_data.as_deref(),
            );
            instructions.push(swap_ix);

            // Create and send transaction
            let blockhash = self_clone.client.get_latest_blockhash().await
                .map_err(|e| PyValueError::new_err(format!("Blockhash error: {}", e)))?;

            let msg = Message::new_with_blockhash(
                &instructions,
                Some(&self_clone.keypair.pubkey()),
                &blockhash,
            );

            let mut tx = Transaction::new_unsigned(msg);
            tx.sign(&[self_clone.keypair.as_ref()], blockhash)
                .map_err(|e| PyValueError::new_err(format!("Sign error: {:?}", e)))?;

            let sig = self_clone.client.send_transaction_with_config(
                &tx,
                solana_client::rpc_config::RpcSendTransactionConfig {
                    skip_preflight: false,
                    preflight_commitment: Some(CommitmentLevel::Confirmed),
                    encoding: None,
                    max_retries: Some(5),
                    min_context_slot: None,
                },
            )
            .await
            .map_err(|e| PyValueError::new_err(format!("Send error: {}", e)))?;

            // Confirm transaction
            let _ = self_clone.client.confirm_transaction_with_commitment(
                &sig,
                CommitmentConfig::confirmed(),
            )
            .await
            .map_err(|e| PyValueError::new_err(format!("Confirmation error: {}", e)))?;

            Ok(sig.to_string())
        })
    }

    #[pyo3(name = "get_sol_balance")]
    fn get_sol_balance_py<'py>(&self, py: Python<'py>) -> PyResult<&'py PyAny> {
        let self_clone = Self {
            client: self.client.clone(),
            keypair: self.keypair.clone(),
        };
        
        future_into_py(py, async move {
            let balance = self_clone.client.get_balance(&self_clone.keypair.pubkey())
                .await
                .map_err(|e| PyValueError::new_err(format!("Failed to get SOL balance: {}", e)))?;
                
            Ok(balance as f64 / 1e9)  // Convert lamports to SOL
        })
    }

    #[pyo3(name = "get_wsol_balance")]
    fn get_wsol_balance_py<'py>(&self, py: Python<'py>) -> PyResult<&'py PyAny> {
        let self_clone = Self {
            client: self.client.clone(),
            keypair: self.keypair.clone(),
        };
        
        future_into_py(py, async move {
            let wsol_account = env::var("WSOL_TOKEN_ACCOUNT")
                .map_err(|_| PyValueError::new_err("WSOL_TOKEN_ACCOUNT not found"))?;
                
            let pubkey = Pubkey::from_str(&wsol_account)
                .map_err(|e| PyValueError::new_err(format!("Invalid WSOL account: {}", e)))?;
                
            let balance = self_clone.client.get_token_account_balance(&pubkey)
                .await
                .map_err(|e| PyValueError::new_err(format!("Failed to get WSOL balance: {}", e)))?;
                
            let amount = balance.amount.parse::<u64>()
                .map_err(|e| PyValueError::new_err(format!("Invalid balance format: {}", e)))?;
                
            Ok(amount as f64 / 1e9)  // Convert lamports to SOL
        })
    }
}

#[pymodule]
fn solana_rust_bot(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
    pyo3_log::init();
    m.add_class::<TradingCore>()?;
    m.add_class::<TradeParams>()?;
    Ok(())
} fix full script please and then for the python script here u go fix this one too import os
import json
import asyncio
import base64
import base58
from datetime import datetime
import websockets
import torch
from typing import Optional
from dataclasses import dataclass
from solana_logger import logger
from config_loader import config
from solana_rust_bot import TradingCore, TradeParams


@dataclass
class TradeOpportunity:
    victim_data: bytes
    amount: float
    token_a_mint: str
    token_b_mint: str
    net_profit: float
    instruction_type: int
    transaction_id: str


class MEVBot:
    def __init__(self):
        self.load_config()
        self.init_components()
        self.init_trade_params()
        self.reset_performance_metrics()
        self.trade_lock = asyncio.Lock()
        self.active = True
        self.active_trades = 0
        self.MAX_ACTIVE_TRADES = 1
        self._setup_cuda()
        self.log_startup()

        # State for WSOL setup
        self.known_atas = set()  # Track ATAs we've verified
        self.wsol_checked = False  # Track if WSOL setup has been done

    def load_config(self):
        """Load configuration and network settings"""
        network_config = config.get_network_config()
        self.ws_url = network_config["ws_url"]
        self.api_key = network_config["api_key"]
        self.program_id = config.get("raydium")
        self.wallet = config.get("wallet")

        # Define WSOL mint address
        self.WSOL_MINT = (
            "So11111111111111111111111111111111111111112"  # Correct WSOL mint address
        )

    def init_components(self):
        """Initialize core components"""
        try:
            self.trading_core = TradingCore(config.get_network_config()["rpc_url"])
            logger.system("Core components initialized successfully")
        except Exception as e:
            raise RuntimeError(f"Failed to initialize components: {e}")

    def init_trade_params(self):
        """Initialize trading parameters from configuration"""
        trade_config = config.get_trade_config()
        self.POSITION_SIZE = trade_config["front_run_amount"]
        self.MIN_VICTIM_SIZE = trade_config["min_victim_size"]
        self.MAX_VICTIM_SIZE = trade_config["max_victim_size"]
        self.MIN_PROFIT = trade_config["min_profit"]
        self.LAMPORTS_PER_SOL = 1_000_000_000

        # Track processed transactions
        self.processed_txs = set()

    def reset_performance_metrics(self):
        """Reset performance metrics before starting operations"""
        self.trades_found = 0
        self.trades_executed = 0
        self.successful_trades = 0
        self.total_profit = 0.0
        self.start_time = datetime.now()

        # Balance monitoring
        balance_config = config.get_balance_config()
        self.min_sol_balance = balance_config["min_sol_balance"]
        self.min_wsol_balance = balance_config["min_wsol_balance"]
        self.balances = {"SOL": 0.0, "WSOL": 0.0}
        self.is_trading_paused = False

    def _setup_cuda(self):
        """Configure CUDA for optimal performance"""
        if not torch.cuda.is_available():
            raise RuntimeError("CUDA required!")
        torch.cuda.empty_cache()
        torch.set_float32_matmul_precision("high")
        torch.backends.cudnn.benchmark = True
        torch.backends.cudnn.enabled = True
        self.cuda_stream = torch.cuda.Stream(priority=-1)
        logger.system(f"Using GPU: {torch.cuda.get_device_name(0)}")

    def log_startup(self):
        """Log startup information"""
        logger.system(
            f"""
🚀 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
====================
Wallet: {self.wallet}
====================
"""
        )

    async def check_wsol_setup(self):
        """Check the WSOL setup for trading"""
        if self.wsol_checked:
            return
        await self.check_initial_balances()
        self.known_atas.add(self.WSOL_MINT)  # WSOL mint should be tracked
        self.wsol_checked = True

    async def check_initial_balances(self):
        """Check initial balances via RPC"""
        try:
            sol_balance = await self.trading_core.get_sol_balance()
            wsol_balance = await self.trading_core.get_wsol_balance()

            self.balances["SOL"] = sol_balance
            self.balances["WSOL"] = wsol_balance

            logger.info(
                f"Initial Balance Check: SOL: {sol_balance:.4f}, WSOL: {wsol_balance:.4f}"
            )

            if sol_balance < self.min_sol_balance:
                logger.warning(f"Low SOL balance detected: {sol_balance:.4f}")
                await self._handle_rebalance()

        except Exception as e:
            logger.error(f"Balance check error: {e}")

    def calculate_profit(self, amount: float) -> float:
        """Calculate potential trade profit"""
        with torch.cuda.stream(self.cuda_stream):
            amount_tensor = torch.tensor(amount, device="cuda")

            if amount >= 40:
                profit_rate = 0.025
            elif amount >= 20:
                profit_rate = 0.020
            elif amount >= 5:
                profit_rate = 0.015
            else:
                return 0.0

            entry_impact = 0.001 * amount_tensor
            exit_impact = entry_impact
            priority_fee = 0.002

            net_profit = (amount_tensor * profit_rate) - (
                entry_impact + exit_impact + priority_fee
            )
            return float(net_profit) if net_profit > self.MIN_PROFIT else 0.0

    def decode_trade_data(
        self, raw_data: bytes, tx_id: str
    ) -> Optional[TradeOpportunity]:
        """Decode and validate trade data"""
        try:
            if tx_id in self.processed_txs:
                return None

            if len(raw_data) < 40:
                return None

            instruction = raw_data[0]
            amount = int.from_bytes(raw_data[1:9], "little") / 1e9

            if instruction != 0x03 or not (
                self.MIN_VICTIM_SIZE <= amount <= self.MAX_VICTIM_SIZE
            ):
                return None

            token_a_bytes = raw_data[40:72] if len(raw_data) >= 72 else raw_data[-32:]
            token_b_bytes = raw_data[72:104] if len(raw_data) >= 104 else None

            token_a_mint = base58.b58encode(token_a_bytes).decode()
            token_b_mint = (
                self.WSOL_MINT
                if token_b_bytes is None
                else base58.b58encode(token_b_bytes).decode()
            )

            profit = self.calculate_profit(amount)
            if profit <= 0:
                return None

            self.processed_txs.add(tx_id)

            return TradeOpportunity(
                victim_data=raw_data,
                amount=amount,
                token_a_mint=token_a_mint,
                token_b_mint=token_b_mint,
                net_profit=profit,
                instruction_type=instruction,
                transaction_id=tx_id,
            )

        except Exception as e:
            logger.error(f"Trade data decode error: {e}")
            return None

    async def execute_trade(self, trade: TradeOpportunity) -> bool:
        """Execute a trade"""
        if not self.wsol_checked:
            await self.check_wsol_setup()  # Ensure WSOL is set up before trading

        if self.balances["WSOL"] < self.POSITION_SIZE:
            logger.warning(
                f"Insufficient WSOL balance: {self.balances['WSOL']:.4f}. Required: {self.POSITION_SIZE:.4f}."
            )
            return False

        async with self.trade_lock:
            try:
                if self.active_trades >= self.MAX_ACTIVE_TRADES:
                    logger.warning(
                        "Max active trades reached, skipping trade execution."
                    )
                    return False

                self.active_trades += 1
                position_lamports = int(self.POSITION_SIZE * self.LAMPORTS_PER_SOL)

                logger.trade(
                    f"""
🎯 Trade Found:
Size: {trade.amount:.4f} SOL
Position: {self.POSITION_SIZE} SOL ({position_lamports} lamports)
Token A: {trade.token_a_mint}
Token B: {trade.token_b_mint}
Est. Profit: {trade.net_profit:.6f} SOL
TX ID: {trade.transaction_id}
"""
                )

                # Use environment variables for Raydium accounts
                raydium_accounts = [
                    self.program_id,
                    os.getenv("AMM_AUTHORITY"),
                    os.getenv("AMM_OPEN_ORDERS"),
                    os.getenv("AMM_TARGET"),
                    os.getenv("MARKET"),
                ]

                entry_params = TradeParams(
                    accounts=raydium_accounts,
                    amount_in=position_lamports,
                    is_buy=True,
                    token_a_mint=trade.token_a_mint,
                    token_b_mint=trade.token_b_mint,
                    victim_data=trade.victim_data,
                    sell_all=False,
                )

                entry_result = await self.trading_core.execute_trade_py(entry_params)
                if entry_result:
                    await asyncio.sleep(0.0001)

                    exit_params = TradeParams(
                        accounts=raydium_accounts,
                        amount_in=None,
                        is_buy=False,
                        token_a_mint=trade.token_a_mint,
                        token_b_mint=trade.token_b_mint,
                        victim_data=None,
                        sell_all=True,
                    )

                    exit_result = await self.trading_core.execute_trade_py(exit_params)
                    if exit_result:
                        self.trades_executed += 1
                        self.successful_trades += 1
                        self.total_profit += trade.net_profit

                        logger.trade(
                            f"""
💰 Trade Completed:
Entry TX: {entry_result}
Exit TX: {exit_result}
Original TX: {trade.transaction_id}
Profit: {trade.net_profit:.6f} SOL
Total Profit: {self.total_profit:.6f} SOL
Success Rate: {(self.successful_trades/self.trades_executed*100):.1f}%
"""
                        )
                        return True

                return False

            except Exception as e:
                logger.error(f"Trade execution error: {e}")
                return False
            finally:
                self.active_trades -= 1

    async def monitor_balances(self):
        """Monitor SOL and WSOL balances using WebSocket"""
        while self.active:
            try:
                async with websockets.connect(
                    self.ws_url, extra_headers={"api-key": self.api_key}
                ) as ws:
                    accounts = {
                        "SOL": self.wallet,
                        "WSOL": config.get("wsol_token_account"),
                    }

                    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",
                                        },
                                    ],
                                }
                            )
                        )

                    subs = {}
                    while self.active:
                        msg = await ws.recv()
                        data = json.loads(msg)

                        if "result" in data:
                            subs[data["result"]] = "SOL" if data["id"] == 1 else "WSOL"
                            continue

                        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]
                                lamports = params["result"]["value"]["lamports"]
                                balance = lamports / 1e9

                                old_balance = self.balances.get(acc_type, 0)
                                self.balances[acc_type] = balance

                                if balance != old_balance:
                                    change = balance - old_balance
                                    logger.info(
                                        f"{acc_type} Balance: {balance:.4f} ({'+' if change >= 0 else ''}{change:.4f})"
                                    )

                                if (
                                    self.balances["SOL"] < self.min_sol_balance
                                    or self.balances["WSOL"] < self.min_wsol_balance
                                ):
                                    if not self.is_trading_paused:
                                        logger.warning(
                                            f"Trading paused - Low balance detected"
                                        )
                                        logger.warning(
                                            f"SOL: {self.balances['SOL']:.4f}, WSOL: {self.balances['WSOL']:.4f}"
                                        )
                                        self.is_trading_paused = True
                                else:
                                    if self.is_trading_paused:
                                        logger.info(
                                            "Trading resumed - Balances restored"
                                        )
                                        self.is_trading_paused = False

            except websockets.ConnectionClosed:
                logger.warning("Balance monitor disconnected, reconnecting...")
                await asyncio.sleep(1)
            except Exception as e:
                logger.error(f"Balance monitor error: {e}")
                await asyncio.sleep(1)

    async def process_mempool(self):
        """Process Raydium mempool data"""
        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=5,
                    ping_timeout=10,
                    compression=None,
                ) as ws:
                    logger.info("Mempool WebSocket Connected")

                    await ws.send(
                        json.dumps(
                            {
                                "jsonrpc": "2.0",
                                "id": 1,
                                "method": "logsSubscribe",
                                "params": [
                                    {"mentions": [self.program_id]},
                                    {"commitment": "processed"},
                                ],
                            }
                        )
                    )

                    await ws.recv()  # Subscription confirmation

                    while self.active:
                        try:
                            msg = await ws.recv()
                            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"
                                )

                                for log in logs:
                                    logger.info(
                                        f"Found opportunity: {log}"
                                    )  # You can further filter what you log
                                    if "ray_log:" in log:
                                        raw_data = base64.b64decode(
                                            log.split("ray_log:")[1].strip()
                                        )
                                        trade = self.decode_trade_data(raw_data, tx_id)
                                        if trade:
                                            self.trades_found += 1
                                            await self.execute_trade(trade)

                        except Exception as e:
                            logger.info(f"Message processing error: {e}")
                            continue

            except websockets.ConnectionClosed:
                logger.warning("Mempool WebSocket disconnected, reconnecting...")
                await asyncio.sleep(1)
            except Exception as e:
                logger.error(f"Mempool connection error: {e}")
                await asyncio.sleep(1)

    def show_performance(self):
        """Display trading performance metrics"""
        runtime = (datetime.now() - self.start_time).total_seconds()

        hours = int(runtime // 3600)
        minutes = int((runtime % 3600) // 60)
        seconds = int(runtime % 60)

        logger.system(
            f"""
🏁 Trading Performance Report
============================
Runtime: {hours:02d}:{minutes:02d}:{seconds:02d}

Trade Statistics:
----------------
Opportunities Found: {self.trades_found}
Trades Executed: {self.trades_executed}
Successful Trades: {self.successful_trades}
Success Rate: {(self.successful_trades/max(1,self.trades_executed)*100):.1f}%

Profit Metrics:
--------------
Total Profit: {self.total_profit:.6f} SOL
Profit per Hour: {(self.total_profit/(runtime/3600)):.6f} SOL/hr
Average Profit per Trade: {(self.total_profit/max(1,self.successful_trades)):.6f} SOL

Current Balances:
----------------
SOL: {self.balances['SOL']:.4f}
WSOL: {self.balances['WSOL']:.4f}
============================
"""
        )

    async def run(self):
        """Start bot with all monitoring systems"""
        try:
            await self.check_initial_balances()
            balance_task = asyncio.create_task(self.monitor_balances())
            mempool_task = asyncio.create_task(self.process_mempool())

            await asyncio.gather(balance_task, mempool_task)
        except asyncio.CancelledError:
            logger.system("Tasks cancelled")
        except Exception as e:
            logger.error(f"Task error: {e}")
        finally:
            self.show_performance()
            await self.cleanup()

    async def cleanup(self):
        """Cleanup resources"""
        self.active = False
        if torch.cuda.is_available():
            torch.cuda.empty_cache()
        logger.system("Cleanup completed")


async def main():
    if os.name == "nt":
        asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

    try:
        bot = MEVBot()
        await bot.run()
    except KeyboardInterrupt:
        logger.system("Bot stopping gracefully...")
    except Exception as e:
        logger.error(f"Fatal error: {e}")
    finally:
        if torch.cuda.is_available():
            torch.cuda.empty_cache()
        logger.system("Bot stopped")


if __name__ == "__main__":
    asyncio.run(main())
import os
import json
import asyncio
import base64
from datetime import datetime
from typing import Optional
import websockets
import torch
from dataclasses import dataclass
from solana_logger import logger
from config_loader import config
from solana_rust_bot import TradingCore, TradeParams

@dataclass
class TradeOpportunity:
    victim_data: bytes
    amount: float
    token_a_mint: str
    token_b_mint: str
    net_profit: float
    transaction_id: str

class MEVBot:
    def __init__(self):
        self.load_config()
        self.init_components()
        self.init_trade_params()
        self.reset_metrics()
        self.trade_lock = asyncio.Lock()
        self.active = True
        self.active_trades = 0
        self.MAX_ACTIVE_TRADES = 2
        self._setup_cuda()
        self.log_startup()

    def load_config(self):
        network_config = config.get_network_config()
        self.ws_url = network_config["ws_url"]
        self.api_key = network_config["api_key"]
        self.program_id = config.get("raydium")
        self.wallet = config.get("wallet")
        self.WSOL_MINT = "So11111111111111111111111111111111111111112"

    def init_components(self):
        try:
            self.trading_core = TradingCore(config.get_network_config()["rpc_url"])
            logger.system("Core initialized")
        except Exception as e:
            raise RuntimeError(f"Init error: {e}")

    def init_trade_params(self):
        trade_config = config.get_trade_config()
        self.POSITION_SIZE = trade_config["front_run_amount"]
        self.MIN_VICTIM_SIZE = trade_config["min_victim_size"]
        self.MAX_VICTIM_SIZE = trade_config["max_victim_size"]
        self.MIN_PROFIT = trade_config["min_profit"]
        self.LAMPORTS_PER_SOL = 1_000_000_000
        self.processed_txs = set()

    async def check_balances(self):
        for _ in range(3):  # Retry mechanism
            try:
                sol = await self.trading_core.get_sol_balance()
                wsol = await self.trading_core.get_wsol_balance()
                self.balances = {"SOL": sol, "WSOL": wsol}
                logger.info(f"Balances: SOL={sol:.4f}, WSOL={wsol:.4f}")
                if wsol >= self.POSITION_SIZE:
                    return True
                await asyncio.sleep(0.5)
            except Exception as e:
                logger.warning(f"Balance check failed: {e}")
                await asyncio.sleep(1)
        return False

    async def execute_trade(self, trade: TradeOpportunity) -> bool:
        async with self.trade_lock:
            if self.active_trades >= self.MAX_ACTIVE_TRADES:
                return False

            self.active_trades += 1
            try:
                if not await self.check_balances():
                    logger.warning("Insufficient balance after retries")
                    return False

                position_lamports = int(self.POSITION_SIZE * self.LAMPORTS_PER_SOL)
                logger.trade(f"""
🎯 Trade Found:
Size: {trade.amount:.4f} SOL
Position: {self.POSITION_SIZE} SOL
Token A: {trade.token_a_mint}
Token B: {trade.token_b_mint}
Profit: {trade.net_profit:.6f} SOL
TX: {trade.transaction_id}
""")

                # Execute trade
                entry_params = TradeParams(
                    accounts=[
                        self.program_id,
                        os.getenv("AMM_AUTHORITY"),
                        os.getenv("AMM_OPEN_ORDERS"),
                        os.getenv("AMM_TARGET"),
                        os.getenv("MARKET"),
                    ],
                    amount_in=position_lamports,
                    is_buy=True,
                    token_a_mint=trade.token_a_mint,
                    token_b_mint=trade.token_b_mint,
                    victim_data=trade.victim_data,
                    sell_all=False,
                )

                entry_tx = await self.trading_core.execute_trade_py(entry_params)
                await asyncio.sleep(0.1)  # Minimal delay

                exit_params = TradeParams(
                    accounts=[
                        self.program_id,
                        os.getenv("AMM_AUTHORITY"),
                        os.getenv("AMM_OPEN_ORDERS"),
                        os.getenv("AMM_TARGET"),
                        os.getenv("MARKET"),
                    ],
                    amount_in=None,
                    is_buy=False,
                    token_a_mint=trade.token_a_mint,
                    token_b_mint=trade.token_b_mint,
                    sell_all=True,
                )

                exit_tx = await self.trading_core.execute_trade_py(exit_params)
                
                logger.trade(f"""
💰 Trade Completed:
Entry: {entry_tx}
Exit: {exit_tx}
Profit: {trade.net_profit:.6f} SOL
""")
                return True

            except Exception as e:
                logger.error(f"Trade failed: {e}")
                return False
            finally:
                self.active_trades -= 1

    async def process_mempool(self):
        while self.active:
            try:
                async with websockets.connect(
                    self.ws_url,
                    extra_headers={"api-key": self.api_key},
                    ping_interval=5,
                    ping_timeout=10,
                ) as ws:
                    await ws.send(json.dumps({
                        "jsonrpc": "2.0",
                        "id": 1,
                        "method": "logsSubscribe",
                        "params": [{"mentions": [self.program_id]}]
                    }))
                    await ws.recv()

                    while self.active:
                        msg = await ws.recv()
                        data = json.loads(msg)
                        
                        if "params" in data:
                            result = data["params"]["result"]
                            logs = result["value"]["logs"]
                            tx_id = result["value"]["signature"]
                            
                            for log in logs:
                                if "ray_log:" in log:
                                    raw_data = base64.b64decode(log.split("ray_log:")[1])
                                    trade = self.decode_trade_data(raw_data, tx_id)
                                    if trade:
                                        await self.execute_trade(trade)

            except Exception as e:
                logger.error(f"Mempool error: {e}")
                await asyncio.sleep(1)

    def decode_trade_data(self, data: bytes, tx_id: str) -> Optional[TradeOpportunity]:
        try:
            if tx_id in self.processed_txs:
                return None

            if len(data) < 40 or data[0] != 0x03:
                return None

            amount = int.from_bytes(data[1:9], "little") / 1e9
            if not (self.MIN_VICTIM_SIZE <= amount <= self.MAX_VICTIM_SIZE):
                return None

            token_a = base58.b58encode(data[40:72]).decode()
            token_b = self.WSOL_MINT

            profit = self.calculate_profit(amount)
            if profit < self.MIN_PROFIT:
                return None

            self.processed_txs.add(tx_id)
            return TradeOpportunity(
                victim_data=data,
                amount=amount,
                token_a_mint=token_a,
                token_b_mint=token_b,
                net_profit=profit,
                transaction_id=tx_id,
            )
        except Exception as e:
            logger.error(f"Decode error: {e}")
            return None

    # ... rest fix both scripts fully please and thank you sir 

### Best Practices & Lessons Learned
1. Configuration Management:
   - Keep all wallet and keypair configuration in one central config file
   - Use environment variables for sensitive data in production
   - Maintain clear separation between Python configuration management and Rust cryptographic operations

2. Error Prevention:
   - Avoid manual keypair manipulation in Python
   - Let the Rust engine handle all Solana-specific cryptographic operations
   - Use proper error handling and logging at both Python and Rust layers

3. Security Considerations:
   - Never hardcode private keys
   - Use environment variables or secure key stores in production
   - Implement proper cleanup procedures for any temporary files

### Example Implementation Workflow:
1. Configuration Setup:
```json
{
    "wallet": {
        "address": "YOUR_WALLET_ADDRESS",
        "use_env_key": true,
        "private_key": "",
        "keypair_path": "./id.json"
    }
}
```

2. Python Implementation:
```python
# Simple configuration loading
with open(config_path, 'r') as f:
    config = json.load(f)

# Direct initialization of trading engine
engine = TradingEngine(json.dumps(config))
```

### Troubleshooting Common Issues
- 32-byte length errors typically indicate manual keypair manipulation - let Rust handle it
- Base58 decoding issues are resolved by using the Rust layer's native handling
- Configuration path issues can be resolved by using absolute paths in config files

### Production Deployment Notes
When deploying to production, consider:
1. Using environment variables for key management
2. Implementing secure key rotation procedures
3. Setting up proper logging and monitoring
4. Using separate configurations for development and production

### System Architecture Implications
This solution promotes a clean separation of concerns:
- Python handles high-level business logic and trading strategies
- Rust manages low-level cryptographic operations and blockchain interactions
- Configuration serves as the clean interface between layers

### Performance Considerations
By delegating keypair operations to Rust, we achieve:
- Better performance due to Rust's native speed
- Reduced memory overhead from avoiding Python cryptographic operations
- More reliable operation through native Solana library usage

### Future Maintenance
When maintaining or upgrading the system:
1. Keep the configuration structure consistent
2. Update Rust dependencies for security patches
3. Maintain backward compatibility in configuration changes
4. Document any changes to environment variable requirements

This implementation approach significantly simplifies the system architecture while improving reliability and maintainability. By understanding and respecting the strengths of each layer (Python for high-level operations, Rust for cryptographic and blockchain interactions), we create a more robust and maintainable trading system.
 can u please fix this so it loads it in python pelase and passes to the lib.rs ?????