// src/lib.rs - Solana Trading Bot for Python with PyO3
// High-performance trading core with CUDA acceleration support

use log::{debug, error, info, warn};
use pyo3::exceptions::PyValueError;
use pyo3::prelude::*;
use pyo3_log;

// Use bs58 for base58 encoding/decoding
use base64; // Added base64 support for account data decoding
use bs58;
use serde::{Deserialize, Serialize};

use solana_client::nonblocking::rpc_client::RpcClient;
use solana_client::rpc_config::{RpcSendTransactionConfig, RpcSimulateTransactionConfig};
use solana_sdk::{
    commitment_config::{CommitmentConfig, CommitmentLevel},
    compute_budget::ComputeBudgetInstruction,
    instruction::{AccountMeta, Instruction},
    program_pack::Pack, // Added Pack trait for token account unpacking
    pubkey::Pubkey,
    signature::{Keypair, Signer},
    sysvar::SysvarId,
    transaction::Transaction,
};
use solana_transaction_status::UiTransactionEncoding; // Added missing import
use spl_associated_token_account::{
    get_associated_token_address, instruction::create_associated_token_account_idempotent,
};
use spl_token::state::{Account as TokenAccount, Mint};

use dashmap::DashMap;
use std::collections::HashMap;
use std::env;
use std::fs;
use std::str::FromStr;
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::sync::{Arc, RwLock};
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use tokio::sync::Mutex as TokioMutex;

// Constants
const COMPUTE_UNITS: u32 = 50_000; // Maximum compute units
const PRIORITY_FEE: u64 = 950_000; // Optimized priority fee (reduced from 950,000)
const LAMPORTS_PER_SOL: u64 = 1_000_000_000;
const DEFAULT_RPC_RATE_LIMIT: u64 = 5; // 5 RPC calls per second
const MAX_RETRY_COUNT: u8 = 3;
const RAYDIUM_SWAP_INSTRUCTION: u8 = 9; // CRITICAL: This is 9, not 6
const MIN_LIQUIDITY_SOL: f64 = 5.0; // Minimum liquidity in SOL for safety
const MIN_PROFIT_THRESHOLD: f64 = 0.002; // Minimum profit threshold (0.2%)

// Rate limiter for RPC calls
struct RateLimiter {
    call_count: AtomicU64,
    last_reset: AtomicU64,
    limit_per_second: Arc<AtomicU64>,
}

impl RateLimiter {
    fn new(limit_per_second: u64) -> Self {
        Self {
            call_count: AtomicU64::new(0),
            last_reset: AtomicU64::new(
                SystemTime::now()
                    .duration_since(UNIX_EPOCH)
                    .unwrap()
                    .as_secs(),
            ),
            limit_per_second: Arc::new(AtomicU64::new(limit_per_second)),
        }
    }

    fn check_and_increment(&self) -> bool {
        let now = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .unwrap()
            .as_secs();
        let last_reset = self.last_reset.load(Ordering::Relaxed);

        if now > last_reset {
            // Reset counter if we're in a new second
            self.call_count.store(0, Ordering::Relaxed);
            self.last_reset.store(now, Ordering::Relaxed);
        }

        let count = self.call_count.fetch_add(1, Ordering::Relaxed);
        let limit = self.limit_per_second.load(Ordering::Relaxed);

        count < limit
    }

    fn set_limit(&self, limit: u64) {
        self.limit_per_second.store(limit, Ordering::Relaxed);
    }
}

// Define TokenPairSetting
#[pyclass]
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TokenPairSetting {
    #[pyo3(get, set)]
    pub token_mint: String,
    #[pyo3(get, set)]
    pub amm_id: String,
    #[pyo3(get, set)]
    pub amm_authority: String,
    #[pyo3(get, set)]
    pub amm_open_orders: String,
    #[pyo3(get, set)]
    pub amm_target: String,
    #[pyo3(get, set)]
    pub pool_token_account: String,
    #[pyo3(get, set)]
    pub pool_pc_account: String,

    // Serum/OpenBook support
    #[pyo3(get, set)]
    pub serum_program_id: String,
    #[pyo3(get, set)]
    pub serum_market: String,
    #[pyo3(get, set)]
    pub serum_bids: String,
    #[pyo3(get, set)]
    pub serum_asks: String,
    #[pyo3(get, set)]
    pub serum_event_queue: String,
    #[pyo3(get, set)]
    pub serum_coin_vault: String,
    #[pyo3(get, set)]
    pub serum_pc_vault: String,
    #[pyo3(get, set)]
    pub serum_vault_signer: String,

    // Safety parameters
    #[pyo3(get, set)]
    pub min_liquidity_pct: f64,
    #[pyo3(get, set)]
    pub min_exit_liquidity_sol: f64,
    #[pyo3(get, set)]
    pub auth_revoked: bool,
    #[pyo3(get, set)]
    pub buyer_seller_ratio: f64,
    #[pyo3(get, set)]
    pub min_volume_5m: f64,
    #[pyo3(get, set)]
    pub enabled: bool,

    // Token metadata
    #[pyo3(get, set)]
    pub token_decimals: u8,
    #[pyo3(get, set)]
    pub verified: bool,
}

#[pymethods]
impl TokenPairSetting {
    #[new]
    fn new(
        token_mint: String,
        amm_id: String,
        amm_authority: String,
        amm_open_orders: String,
        amm_target: String,
        pool_token_account: String,
        pool_pc_account: String,

        // Serum/OpenBook parameters
        serum_program_id: Option<String>,
        serum_market: Option<String>,
        serum_bids: Option<String>,
        serum_asks: Option<String>,
        serum_event_queue: Option<String>,
        serum_coin_vault: Option<String>,
        serum_pc_vault: Option<String>,
        serum_vault_signer: Option<String>,

        // Safety parameters
        min_liquidity_pct: Option<f64>,
        min_exit_liquidity_sol: Option<f64>,
        auth_revoked: Option<bool>,
        buyer_seller_ratio: Option<f64>,
        min_volume_5m: Option<f64>,
        enabled: Option<bool>,

        // Token metadata
        token_decimals: Option<u8>,
        verified: Option<bool>,
    ) -> Self {
        // Default Serum Program ID (OpenBook)
        let default_serum = "srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX".to_string();

        Self {
            token_mint,
            amm_id,
            amm_authority,
            amm_open_orders,
            amm_target,
            pool_token_account,
            pool_pc_account,

            // Serum/OpenBook fields with defaults
            serum_program_id: serum_program_id.unwrap_or(default_serum),
            serum_market: serum_market.unwrap_or_else(|| "".to_string()),
            serum_bids: serum_bids.unwrap_or_else(|| "".to_string()),
            serum_asks: serum_asks.unwrap_or_else(|| "".to_string()),
            serum_event_queue: serum_event_queue.unwrap_or_else(|| "".to_string()),
            serum_coin_vault: serum_coin_vault.unwrap_or_else(|| "".to_string()),
            serum_pc_vault: serum_pc_vault.unwrap_or_else(|| "".to_string()),
            serum_vault_signer: serum_vault_signer.unwrap_or_else(|| "".to_string()),

            // Safety fields with defaults
            min_liquidity_pct: min_liquidity_pct.unwrap_or(95.0),
            min_exit_liquidity_sol: min_exit_liquidity_sol.unwrap_or(MIN_LIQUIDITY_SOL),
            auth_revoked: auth_revoked.unwrap_or(true), // Default to requiring authority revoked
            buyer_seller_ratio: buyer_seller_ratio.unwrap_or(1.0),
            min_volume_5m: min_volume_5m.unwrap_or(10.0),
            enabled: enabled.unwrap_or(true),

            // Token metadata
            token_decimals: token_decimals.unwrap_or(9),
            verified: verified.unwrap_or(false),
        }
    }
}

// Dynamic configuration structure
#[pyclass]
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct TradingConfig {
    #[pyo3(get, set)]
    pub rpc_url: String,
    #[pyo3(get, set)]
    pub ws_url: String,
    #[pyo3(get, set)]
    pub api_key: String,

    #[pyo3(get, set)]
    pub sol_mint: String,
    #[pyo3(get, set)]
    pub rpc_rate_limit: u64,

    #[pyo3(get, set)]
    pub token_mint: Option<String>,
    #[pyo3(get, set)]
    pub amm_program: Option<String>,

    #[pyo3(get, set)]
    pub compute_limit: u32,
    #[pyo3(get, set)]
    pub priority_fee: u64,
    #[pyo3(get, set)]
    pub skip_preflight: bool,
    #[pyo3(get, set)]
    pub max_retries: u8,

    // Front-running parameters
    #[pyo3(get, set)]
    pub front_run_amount: f64,
    #[pyo3(get, set)]
    pub min_victim_size: f64,
    #[pyo3(get, set)]
    pub max_victim_size: f64,
    #[pyo3(get, set)]
    pub min_profit: f64,
    #[pyo3(get, set)]
    pub slippage_bps: u16,

    // Balance safety thresholds
    #[pyo3(get, set)]
    pub min_sol_balance: f64,
    #[pyo3(get, set)]
    pub min_wsol_balance: f64,

    // Market parameters
    #[pyo3(get, set)]
    pub amm_id: Option<String>,
    #[pyo3(get, set)]
    pub market_amm_authority: Option<String>,
    #[pyo3(get, set)]
    pub market_amm_open_orders: Option<String>,
    #[pyo3(get, set)]
    pub market_amm_target: Option<String>,
    #[pyo3(get, set)]
    pub market_pool_token_account: Option<String>,
    #[pyo3(get, set)]
    pub market_pool_pc_token_account: Option<String>,

    // Serum/OpenBook related fields
    #[pyo3(get, set)]
    pub serum_program_id: Option<String>,
    #[pyo3(get, set)]
    pub serum_market: Option<String>,
    #[pyo3(get, set)]
    pub serum_bids: Option<String>,
    #[pyo3(get, set)]
    pub serum_asks: Option<String>,
    #[pyo3(get, set)]
    pub serum_event_queue: Option<String>,
    #[pyo3(get, set)]
    pub serum_coin_vault: Option<String>,
    #[pyo3(get, set)]
    pub serum_pc_vault: Option<String>,
    #[pyo3(get, set)]
    pub serum_vault_signer: Option<String>,

    // Program IDs
    #[pyo3(get, set)]
    pub raydium_program_id: String,
    #[pyo3(get, set)]
    pub token_program_id: String,
    #[pyo3(get, set)]
    pub system_program_id: String,
    #[pyo3(get, set)]
    pub associated_token_program_id: String,

    // Token pair settings
    #[pyo3(get)]
    pub token_pair_settings: HashMap<String, TokenPairSetting>,
}

#[pymethods]
impl TradingConfig {
    #[new]
    fn new(
        rpc_url: Option<String>,
        ws_url: Option<String>,
        api_key: Option<String>,
        sol_mint: Option<String>,
        rpc_rate_limit: Option<u64>,
        compute_limit: Option<u32>,
        priority_fee: Option<u64>,
        skip_preflight: Option<bool>,
        max_retries: Option<u8>,
        front_run_amount: Option<f64>,
        min_victim_size: Option<f64>,
        max_victim_size: Option<f64>,
        min_profit: Option<f64>,
        slippage_bps: Option<u16>,
        min_sol_balance: Option<f64>,
        min_wsol_balance: Option<f64>,
        raydium_program_id: Option<String>,
        token_program_id: Option<String>,
        system_program_id: Option<String>,
        associated_token_program_id: Option<String>,
        token_mint: Option<String>,
        amm_program: Option<String>,
        amm_id: Option<String>,
        market_amm_authority: Option<String>,
        market_amm_open_orders: Option<String>,
        market_amm_target: Option<String>,
        market_pool_token_account: Option<String>,
        market_pool_pc_token_account: Option<String>,

        // Serum/OpenBook parameters
        serum_program_id: Option<String>,
        serum_market: Option<String>,
        serum_bids: Option<String>,
        serum_asks: Option<String>,
        serum_event_queue: Option<String>,
        serum_coin_vault: Option<String>,
        serum_pc_vault: Option<String>,
        serum_vault_signer: Option<String>,
    ) -> Self {
        // Use a closure to avoid .clone()
        let get_or_default = |key| env::var(key).unwrap_or_else(|_| "".to_string());

        // Fixed SOL_MINT handling with proper fallback
        let sol_mint_value = sol_mint.unwrap_or_else(|| {
            let env_val = get_or_default("SOL_MINT");
            if env_val.is_empty() {
                "So11111111111111111111111111111111111111112".to_string()
            } else {
                env_val
            }
        });

        // Clone amm_program before it's moved
        let amm_program_clone = amm_program.clone();

        // Default to the Raydium V4 program ID if not specified
        let default_raydium_program = "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8".to_string();
        let default_token_program = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA".to_string();
        let default_system_program = "11111111111111111111111111111111".to_string();
        let default_associated_token_program =
            "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL".to_string();
        let default_serum_program = "srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX".to_string();

        // Fix: Handle raydium_program_id properly
        let raydium_program_value = raydium_program_id.unwrap_or_else(|| {
            if let Some(amm) = amm_program_clone {
                amm
            } else {
                let env_val = get_or_default("RAYDIUM_PROGRAM_ID");
                if env_val.is_empty() {
                    default_raydium_program
                } else {
                    env_val
                }
            }
        });

        // Fix: Handle token_program_id properly
        let token_program_value = token_program_id.unwrap_or_else(|| {
            let env_val = get_or_default("TOKEN_PROGRAM_ID");
            if env_val.is_empty() {
                default_token_program
            } else {
                env_val
            }
        });

        // Fix: Handle system_program_id properly
        let system_program_value = system_program_id.unwrap_or_else(|| {
            let env_val = get_or_default("SYSTEM_PROGRAM_ID");
            if env_val.is_empty() {
                default_system_program
            } else {
                env_val
            }
        });

        // Fix: Handle associated_token_program_id properly
        let associated_token_program_value = associated_token_program_id.unwrap_or_else(|| {
            let env_val = get_or_default("ASSOCIATED_TOKEN_PROGRAM_ID");
            if env_val.is_empty() {
                default_associated_token_program
            } else {
                env_val
            }
        });

        // Handle serum_program_id properly
        let serum_program_value = serum_program_id.unwrap_or_else(|| {
            let env_val = get_or_default("SERUM_PROGRAM_ID");
            if env_val.is_empty() {
                default_serum_program
            } else {
                env_val
            }
        });

        Self {
            rpc_url: rpc_url.unwrap_or_else(|| {
                env::var("RPC_URL")
                    .unwrap_or_else(|_| "https://api.mainnet-beta.solana.com".to_string())
            }),
            ws_url: ws_url.unwrap_or_else(|| {
                env::var("WS_URL")
                    .unwrap_or_else(|_| "wss://api.mainnet-beta.solana.com".to_string())
            }),
            api_key: api_key.unwrap_or_else(|| get_or_default("API_KEY")),
            sol_mint: sol_mint_value,
            rpc_rate_limit: rpc_rate_limit.unwrap_or_else(|| {
                env::var("RPC_RATE_LIMIT")
                    .map(|v| v.parse().unwrap_or(DEFAULT_RPC_RATE_LIMIT))
                    .unwrap_or(DEFAULT_RPC_RATE_LIMIT)
            }),
            // Store additional fields
            token_mint,
            amm_program,
            compute_limit: compute_limit.unwrap_or_else(|| {
                env::var("COMPUTE_LIMIT")
                    .map(|v| v.parse().unwrap_or(COMPUTE_UNITS))
                    .unwrap_or(COMPUTE_UNITS)
            }),
            priority_fee: priority_fee.unwrap_or_else(|| {
                env::var("PRIORITY_FEE")
                    .map(|v| v.parse().unwrap_or(PRIORITY_FEE))
                    .unwrap_or(PRIORITY_FEE)
            }),
            skip_preflight: skip_preflight.unwrap_or_else(|| {
                env::var("SKIP_PREFLIGHT")
                    .map(|v| v.parse().unwrap_or(true))
                    .unwrap_or(true)
            }),
            max_retries: max_retries.unwrap_or_else(|| {
                env::var("MAX_RETRIES")
                    .map(|v| v.parse().unwrap_or(MAX_RETRY_COUNT))
                    .unwrap_or(MAX_RETRY_COUNT)
            }),
            front_run_amount: front_run_amount.unwrap_or_else(|| {
                env::var("FRONT_RUN_AMOUNT")
                    .map(|v| v.parse().unwrap_or(0.1))
                    .unwrap_or(0.1)
            }),
            min_victim_size: min_victim_size.unwrap_or_else(|| {
                env::var("MIN_VICTIM_SIZE")
                    .map(|v| v.parse().unwrap_or(1.0))
                    .unwrap_or(1.0)
            }),
            max_victim_size: max_victim_size.unwrap_or_else(|| {
                env::var("MAX_VICTIM_SIZE")
                    .map(|v| v.parse().unwrap_or(1000.0))
                    .unwrap_or(1000.0)
            }),
            min_profit: min_profit.unwrap_or_else(|| {
                env::var("MIN_PROFIT")
                    .map(|v| v.parse().unwrap_or(MIN_PROFIT_THRESHOLD))
                    .unwrap_or(MIN_PROFIT_THRESHOLD)
            }),
            slippage_bps: slippage_bps.unwrap_or_else(|| {
                env::var("SLIPPAGE_BPS")
                    .map(|v| v.parse().unwrap_or(1000))
                    .unwrap_or(1000)
            }),
            min_sol_balance: min_sol_balance.unwrap_or_else(|| {
                env::var("MIN_SOL_BALANCE")
                    .map(|v| v.parse().unwrap_or(0.05))
                    .unwrap_or(0.05)
            }),
            min_wsol_balance: min_wsol_balance.unwrap_or_else(|| {
                env::var("MIN_WSOL_BALANCE")
                    .map(|v| v.parse().unwrap_or(0.02))
                    .unwrap_or(0.02)
            }),
            // Store additional market parameters
            amm_id,
            market_amm_authority,
            market_amm_open_orders,
            market_amm_target,
            market_pool_token_account,
            market_pool_pc_token_account,

            // Store Serum/OpenBook parameters
            serum_program_id: Some(serum_program_value),
            serum_market,
            serum_bids,
            serum_asks,
            serum_event_queue,
            serum_coin_vault,
            serum_pc_vault,
            serum_vault_signer,

            // Store program IDs
            raydium_program_id: raydium_program_value,
            token_program_id: token_program_value,
            system_program_id: system_program_value,
            associated_token_program_id: associated_token_program_value,
            token_pair_settings: HashMap::new(),
        }
    }

    // Add a token pair setting
    fn add_token_pair_setting(&mut self, token_pair: TokenPairSetting) -> PyResult<()> {
        self.token_pair_settings
            .insert(token_pair.token_mint.clone(), token_pair);
        Ok(())
    }

    // Remove a token pair setting
    fn remove_token_pair_setting(&mut self, token_mint: &str) -> PyResult<bool> {
        Ok(self.token_pair_settings.remove(token_mint).is_some())
    }

    // Get a token pair setting
    fn get_token_pair_setting(&self, token_mint: &str) -> PyResult<Option<TokenPairSetting>> {
        Ok(self.token_pair_settings.get(token_mint).cloned())
    }

    // Get all active token mints
    fn get_active_token_mints(&self) -> PyResult<Vec<String>> {
        Ok(self
            .token_pair_settings
            .iter()
            .filter(|(_, v)| v.enabled)
            .map(|(k, _)| k.clone())
            .collect())
    }

    // Save config to file
    fn save_to_file(&self, path: &str) -> PyResult<()> {
        let json = serde_json::to_string_pretty(&self)
            .map_err(|e| PyValueError::new_err(format!("Failed to serialize config: {}", e)))?;

        fs::write(path, json)
            .map_err(|e| PyValueError::new_err(format!("Failed to write config file: {}", e)))?;

        Ok(())
    }

    // Load config from file
    #[staticmethod]
    fn load_from_file(path: &str) -> PyResult<Self> {
        let json = fs::read_to_string(path)
            .map_err(|e| PyValueError::new_err(format!("Failed to read config file: {}", e)))?;

        let config: Self = serde_json::from_str(&json)
            .map_err(|e| PyValueError::new_err(format!("Failed to parse config file: {}", e)))?;

        Ok(config)
    }

    // Load from environment variables
    #[staticmethod]
    fn from_env() -> PyResult<Self> {
        Ok(Self::new(
            None, None, None, None, None, None, None, None, None, None, None, None, None, None,
            None, None, None, None, None, None, None, None, None, None, None, None, None, None,
            None, None, None, None, None, None, None, None,
        ))
    }
}

// Structure to hold swap parameters
#[pyclass]
#[derive(Clone)]
pub struct SwapParams {
    #[pyo3(get, set)]
    pub token_mint: String,
    #[pyo3(get, set)]
    pub amount_in: f64,
    #[pyo3(get, set)]
    pub is_buy: bool,
    #[pyo3(get, set)]
    pub slippage_bps: u16,
    #[pyo3(get, set)]
    pub compute_limit: u32,
    #[pyo3(get, set)]
    pub priority_fee: u64,
    #[pyo3(get, set)]
    pub min_amount_out: Option<u64>,
    #[pyo3(get, set)]
    pub victim_tx: Option<String>, // For front-running, store the victim's tx
}

#[pymethods]
impl SwapParams {
    #[new]
    fn new(
        token_mint: String,
        amount_in: f64,
        is_buy: bool,
        slippage_bps: Option<u16>,
        compute_limit: Option<u32>,
        priority_fee: Option<u64>,
        min_amount_out: Option<u64>,
        victim_tx: Option<String>,
    ) -> Self {
        Self {
            token_mint,
            amount_in,
            is_buy,
            slippage_bps: slippage_bps.unwrap_or(1000),
            compute_limit: compute_limit.unwrap_or(COMPUTE_UNITS),
            priority_fee: priority_fee.unwrap_or(PRIORITY_FEE),
            min_amount_out,
            victim_tx,
        }
    }
}

// Structure for token safety checks
#[pyclass]
#[derive(Clone, Debug)]
pub struct TokenSafetyCheck {
    #[pyo3(get)]
    pub token_mint: String,
    #[pyo3(get)]
    pub is_safe: bool,
    #[pyo3(get)]
    pub auth_revoked: bool,
    #[pyo3(get)]
    pub has_liquidity: bool,
    #[pyo3(get)]
    pub liquidity_sol: f64,
    #[pyo3(get)]
    pub liquidity_locked: bool,
    #[pyo3(get)]
    pub verified: bool,
    #[pyo3(get)]
    pub decimals: u8,
    #[pyo3(get)]
    pub reason: Option<String>,
}

#[pymethods]
impl TokenSafetyCheck {
    #[new]
    fn new(
        token_mint: String,
        is_safe: bool,
        auth_revoked: Option<bool>,
        has_liquidity: Option<bool>,
        liquidity_sol: Option<f64>,
        liquidity_locked: Option<bool>,
        verified: Option<bool>,
        decimals: Option<u8>,
        reason: Option<String>,
    ) -> Self {
        Self {
            token_mint,
            is_safe,
            auth_revoked: auth_revoked.unwrap_or(false),
            has_liquidity: has_liquidity.unwrap_or(false),
            liquidity_sol: liquidity_sol.unwrap_or(0.0),
            liquidity_locked: liquidity_locked.unwrap_or(false),
            verified: verified.unwrap_or(false),
            decimals: decimals.unwrap_or(9),
            reason,
        }
    }
}

#[pyclass]
#[derive(Clone)]
pub struct TransactionStatus {
    #[pyo3(get)]
    pub signature: String,
    #[pyo3(get)]
    pub success: bool,
    #[pyo3(get)]
    pub error: Option<String>,
    #[pyo3(get)]
    pub timestamp: u64,
    #[pyo3(get)]
    pub simulation_only: bool,
    #[pyo3(get)]
    pub logs: Option<Vec<String>>,
}

#[pymethods]
impl TransactionStatus {
    #[new]
    fn new(
        signature: String,
        success: bool,
        error: Option<String>,
        timestamp: Option<u64>,
        simulation_only: Option<bool>,
        logs: Option<Vec<String>>,
    ) -> Self {
        Self {
            signature,
            success,
            error,
            timestamp: timestamp.unwrap_or_else(|| {
                SystemTime::now()
                    .duration_since(UNIX_EPOCH)
                    .unwrap()
                    .as_secs()
            }),
            simulation_only: simulation_only.unwrap_or(false),
            logs,
        }
    }

    // Extract profit information from transaction logs
    fn calculate_profit(&self) -> PyResult<f64> {
        if !self.success || self.logs.is_none() {
            return Ok(0.0);
        }

        // In a real implementation, this would parse the transfer logs
        // to estimate profit based on in/out token amounts
        // For now, we return a placeholder value
        Ok(0.0)
    }
}

// Cache for token metadata
type TokenMetadataCache = Arc<DashMap<String, TokenMetadata>>;

// Simple token metadata for caching
#[derive(Clone, Debug)]
struct TokenMetadata {
    decimals: u8,
    verified: bool,
    last_updated: u64,
}

// Main trading core class
#[pyclass]
pub struct RaydiumTradingCore {
    client: Arc<RpcClient>,
    keypair: Arc<Keypair>,
    config: Arc<RwLock<TradingConfig>>,
    balances: Arc<RwLock<(f64, HashMap<String, f64>)>>, // (SOL, token balances by mint)
    rate_limiter: Arc<RateLimiter>,
    pending_transaction: Arc<AtomicBool>, // Flag to indicate pending transaction
    last_trade_time: Arc<AtomicU64>,      // Store the last trade time
    public_key: String,
    token_cache: TokenMetadataCache,
    transaction_lock: Arc<TokioMutex<bool>>,

    // Front-running related
    last_victim_amount: Arc<AtomicU64>, // Last victim's trade amount in lamports
    last_victim_tx: Arc<RwLock<String>>, // Last victim transaction signature
    profit_tracker: Arc<RwLock<HashMap<String, f64>>>, // Track profit by token mint
}

#[pymethods]
impl RaydiumTradingCore {
    #[new]
    fn new(
        rpc_url: Option<String>,
        private_key: Option<String>,
        keypair_path: Option<String>,
        config: Option<TradingConfig>,
    ) -> PyResult<Self> {
        let config_obj = config.unwrap_or_else(|| {
            TradingConfig::new(
                rpc_url.clone(),
                None, None, None, None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None, None, None, None, None, None, None,
                None, None, None, None, None, None, None, None,
            )
        });

        let client = Arc::new(RpcClient::new_with_commitment(
            rpc_url.unwrap_or_else(|| config_obj.rpc_url.clone()),
            solana_sdk::commitment_config::CommitmentConfig::confirmed(),
        ));

        // Load keypair from either a provided string, file, or environment
        let keypair = if let Some(pk) = private_key {
            let bytes = bs58::decode(pk)
                .into_vec()
                .map_err(|e| PyValueError::new_err(format!("Invalid private key: {:?}", e)))?;

            Keypair::from_bytes(&bytes)
                .map_err(|e| PyValueError::new_err(format!("Invalid keypair: {}", e)))?
        } else if let Some(path) = keypair_path {
            // Ensure path exists before trying to read
            debug!("Trying to load keypair from path: {}", path);
            let path = std::path::Path::new(&path);
            if !path.exists() {
                return Err(PyValueError::new_err(format!(
                    "Keypair file not found: {}",
                    path.display()
                )));
            }

            // Read the 64-byte binary keypair file directly
            debug!("Reading binary keypair file...");
            let bytes = match fs::read(path) {
                Ok(data) => {
                    debug!("Successfully read {} bytes from keypair file", data.len());
                    data
                }
                Err(e) => {
                    return Err(PyValueError::new_err(format!(
                        "Failed to read keypair file: {}",
                        e
                    )));
                }
            };

            // Verify that we have the expected 64 bytes
            if bytes.len() != 64 {
                return Err(PyValueError::new_err(format!(
                    "Invalid keypair file size: expected 64 bytes, got {} bytes",
                    bytes.len()
                )));
            }

            // Load keypair directly from the raw bytes
            debug!("Creating keypair from {} bytes", bytes.len());
            match Keypair::from_bytes(&bytes) {
                Ok(kp) => {
                    debug!("Successfully loaded keypair with pubkey: {}", kp.pubkey());
                    kp
                }
                Err(e) => {
                    return Err(PyValueError::new_err(format!(
                        "Invalid keypair data: {}",
                        e
                    )));
                }
            }
        } else {
            let private_key = env::var("SOLANA_PRIVATE_KEY").map_err(|_| {
                PyValueError::new_err("SOLANA_PRIVATE_KEY not found in environment")
            })?;

            let secret_key_bytes = bs58::decode(&private_key).into_vec().map_err(|e| {
                PyValueError::new_err(format!("Invalid private key encoding: {:?}", e))
            })?;

            Keypair::from_bytes(&secret_key_bytes)
                .map_err(|e| PyValueError::new_err(format!("Invalid keypair: {}", e)))?
        };

        let rate_limiter = Arc::new(RateLimiter::new(config_obj.rpc_rate_limit));
        let public_key = keypair.pubkey().to_string();
        let token_cache = Arc::new(DashMap::new());
        let transaction_lock = Arc::new(TokioMutex::new(false));

        Ok(Self {
            client,
            keypair: Arc::new(keypair),
            config: Arc::new(RwLock::new(config_obj)),
            balances: Arc::new(RwLock::new((0.0, HashMap::new()))),
            rate_limiter,
            pending_transaction: Arc::new(AtomicBool::new(false)),
            last_trade_time: Arc::new(AtomicU64::new(0)),
            public_key,
            token_cache,
            transaction_lock,
            // Initialize front-running related fields
            last_victim_amount: Arc::new(AtomicU64::new(0)),
            last_victim_tx: Arc::new(RwLock::new(String::new())),
            profit_tracker: Arc::new(RwLock::new(HashMap::new())),
        })
    }

    // Get the public key for logging/display
    fn get_public_key(&self) -> String {
        self.public_key.clone()
    }

    // Check if a token is safe to trade
    fn check_token_safety<'py>(&self, py: Python<'py>, token_mint: String) -> PyResult<&'py PyAny> {
        let client = self.client.clone();

        pyo3_asyncio::tokio::future_into_py(py, async move {
            let result = check_token_safety_internal(&client, &token_mint).await;
            match result {
                Ok(safety) => Ok(safety),
                Err(e) => Err(e),
            }
        })
    }

    // Front-run a transaction
    fn front_run_transaction<'py>(
        &self,
        py: Python<'py>,
        victim_tx: String,
        token_mint: String,
        perform_safety_checks: Option<bool>,
    ) -> PyResult<&'py PyAny> {
        let client = self.client.clone();
        let config_arc = self.config.clone();
        let keypair = self.keypair.clone();
        let pending_transaction = self.pending_transaction.clone();
        let transaction_lock = self.transaction_lock.clone();
        let last_victim_amount = self.last_victim_amount.clone();
        let last_victim_tx_arc = self.last_victim_tx.clone();

        let do_safety_checks = perform_safety_checks.unwrap_or(true);

        // Ensure we're not already processing a transaction
        if pending_transaction.load(Ordering::Relaxed) {
            return Err(PyValueError::new_err(
                "A transaction is already in progress",
            ));
        }

        pyo3_asyncio::tokio::future_into_py(py, async move {
            // Acquire transaction lock
            let _lock = transaction_lock.lock().await;

            // Set pending transaction flag
            pending_transaction.store(true, Ordering::Relaxed);

            // Get config
            let config = match config_arc.read() {
                Ok(config) => config.clone(),
                Err(_) => {
                    pending_transaction.store(false, Ordering::Relaxed);
                    return Err(PyValueError::new_err("Failed to read config"));
                }
            };

            // Save the victim tx
            if let Ok(mut last_tx) = last_victim_tx_arc.write() {
                *last_tx = victim_tx.clone();
            }

            // First, get the victim's transaction to analyze
            debug!("Getting victim transaction: {}", victim_tx);
            let tx_info = match client
                .get_transaction_with_config(
                    &victim_tx.parse().unwrap(),
                    solana_client::rpc_config::RpcTransactionConfig {
                        encoding: Some(UiTransactionEncoding::Json),
                        commitment: Some(CommitmentConfig::confirmed()),
                        max_supported_transaction_version: Some(0),
                    },
                )
                .await
            {
                Ok(tx) => tx,
                Err(e) => {
                    pending_transaction.store(false, Ordering::Relaxed);
                    return Err(PyValueError::new_err(format!(
                        "Failed to get victim transaction: {}",
                        e
                    )));
                }
            };

            // Check if transaction data is missing
            if tx_info.transaction.meta.is_none() {
                pending_transaction.store(false, Ordering::Relaxed);
                return Err(PyValueError::new_err("Transaction data is missing"));
            }

            // Perform token safety checks if enabled
            if do_safety_checks {
                // Check if token is safe to trade
                match check_token_safety_internal(&client, &token_mint).await {
                    Ok(safety) => {
                        if !safety.is_safe {
                            pending_transaction.store(false, Ordering::Relaxed);
                            return Err(PyValueError::new_err(format!(
                                "Token failed safety checks: {}",
                                safety.reason.unwrap_or("Unknown reason".to_string())
                            )));
                        }
                    }
                    Err(e) => {
                        pending_transaction.store(false, Ordering::Relaxed);
                        return Err(PyValueError::new_err(format!(
                            "Failed to perform safety checks: {}",
                            e
                        )));
                    }
                }
            }

            // Extract the SOL amount from the victim's transaction
            // For front-running, we'd need to parse the instruction data
            // This simplified implementation uses a fixed amount
            let front_run_amount_sol = config.front_run_amount;

            // Store victim amount for profit calculation
            let victim_amount_lamports = (front_run_amount_sol * LAMPORTS_PER_SOL as f64) as u64;
            last_victim_amount.store(victim_amount_lamports, Ordering::Relaxed);

            // Create instruction data with correct format for Raydium swap (0x09 AMM instructions)
            let amount_lamports = (front_run_amount_sol * LAMPORTS_PER_SOL as f64) as u64;
            let mut instruction_data = Vec::with_capacity(17);
            instruction_data.push(RAYDIUM_SWAP_INSTRUCTION); // Discriminator 9
            instruction_data.extend_from_slice(&amount_lamports.to_le_bytes()); // amountIn
            instruction_data.extend_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0]); // minimumAmountOut = 0

            // Get token pair settings or create default ones if not found
            let token_pair = match config.token_pair_settings.get(&token_mint) {
                Some(settings) => settings.clone(),
                None => {
                    // Create default settings with placeholders
                    debug!(
                        "No token pair settings found for {}. Creating dynamically.",
                        token_mint
                    );

                    TokenPairSetting::new(
                        token_mint.clone(),
                        "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8".to_string(),
                        "5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1".to_string(),
                        "FrR9FBcDuPyMrAtUNWD3MazLyMBvJ3GjWTVLWgYtGjpG".to_string(),
                        "3uahGNzFuzSAo6QpucjfyzJkGCiZbmLEShKDXRMcEjjF".to_string(),
                        "83v8iPyZihDEjDDv9zxcm9P67MkrNfFXQocfaGmh8BSm".to_string(),
                        "8xKCx3SGwWR6BUr9mZFm3xwZUHFAVxeRUHPTpjYMJp6q".to_string(),
                        Some("srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX".to_string()),
                        Some("5S7Ppb3a68QZmRfwVYYeBJT5ZXhBgLnmhjKJi8mdYVBw".to_string()),
                        Some("AobitFHZ7jcRZRox5ACd5yvMMpsiCKd5AX3jMqiP7gdn".to_string()),
                        Some("27862HsjMmtkqa75ugKCq6EUDEskBaN6KofMVkBigJ4K".to_string()),
                        Some("Dy9wg7msvu2BseGcLVnqRsNSmukzMMDJhFgiyNN74YRK".to_string()),
                        Some("Gn2xPhz7fhcPwGaJMtbd3qW4pERksBckt22HHQn7PcZw".to_string()),
                        Some("7t47aqASGpamgRDAqfmfvq4kX9f7HKcyAuyGTH5vDnTJ".to_string()),
                        Some("Z4ygvyqDjV12fz3Sdc18RZg8UnXUvVmedafTynLAk17".to_string()),
                        None,
                        None,
                        None,
                        None,
                        None,
                        None,
                        None,
                        None,
                    )
                }
            };

            // Execute the front-running swap
            debug!(
                "Executing front-running swap for {} SOL",
                front_run_amount_sol
            );
            let result =
                execute_swap_internal(&client, &keypair, &token_pair, &instruction_data).await;

            // Reset pending transaction flag
            pending_transaction.store(false, Ordering::Relaxed);

            match result {
                Ok(signature) => {
                    let status = TransactionStatus::new(
                        signature,
                        true,
                        None,
                        Some(
                            SystemTime::now()
                                .duration_since(UNIX_EPOCH)
                                .unwrap()
                                .as_secs(),
                        ),
                        Some(false),
                        None,
                    );
                    Ok(status)
                }
                Err(e) => {
                    let status = TransactionStatus::new(
                        "failed".to_string(),
                        false,
                        Some(e.to_string()),
                        Some(
                            SystemTime::now()
                                .duration_since(UNIX_EPOCH)
                                .unwrap()
                                .as_secs(),
                        ),
                        Some(false),
                        None,
                    );
                    Ok(status)
                }
            }
        })
    }

    // ENHANCED: execute_with_accounts method that handles all account types properly
    fn execute_with_accounts<'py>(
        &self,
        py: Python<'py>,
        token_mint: String,
        instruction_data: Vec<u8>,
        accounts: Vec<String>,
    ) -> PyResult<&'py PyAny> {
        let client = self.client.clone();
        let keypair = self.keypair.clone();
        let pending_transaction = self.pending_transaction.clone();
        let transaction_lock = self.transaction_lock.clone();
        let config_arc = self.config.clone();

        // Debug information
        debug!(
            "Executing with dynamic accounts: {} accounts for token {}",
            accounts.len(),
            token_mint
        );
        debug!("Instruction data (hex): {}", hex::encode(&instruction_data));
        
        // Debug instruction discriminator specifically
        let instruction_debug = if instruction_data.is_empty() {
            "EMPTY".to_string()
        } else {
            format!("{}", instruction_data[0])
        };
        debug!("Instruction data (first byte): {}", instruction_debug);

        if pending_transaction.load(Ordering::Relaxed) {
            return Err(PyValueError::new_err(
                "A transaction is already in progress",
            ));
        }

        pyo3_asyncio::tokio::future_into_py(py, async move {
            // Use a mutex for transaction processing
            let _lock = transaction_lock.lock().await;

            // Set pending transaction flag
            pending_transaction.store(true, Ordering::Relaxed);

            // Get config for program IDs
            let config = match config_arc.read() {
                Ok(config) => config.clone(),
                Err(_) => {
                    pending_transaction.store(false, Ordering::Relaxed);
                    return Err(PyValueError::new_err("Failed to read config"));
                }
            };

            // Get wallet pubkey
            let wallet_pubkey = keypair.pubkey();

            // Parse the Raydium program ID
            let raydium_program_id = match Pubkey::from_str(&config.raydium_program_id) {
                Ok(pubkey) => pubkey,
                Err(e) => {
                    pending_transaction.store(false, Ordering::Relaxed);
                    return Err(PyValueError::new_err(format!(
                        "Invalid Raydium program ID: {}",
                        e
                    )));
                }
            };

            // Process all dynamic accounts
            let mut account_metas = Vec::with_capacity(accounts.len());
            for (i, account_str) in accounts.iter().enumerate() {
                // Parse the account address
                let account_pubkey = match Pubkey::from_str(account_str) {
                    Ok(pubkey) => pubkey,
                    Err(e) => {
                        pending_transaction.store(false, Ordering::Relaxed);
                        return Err(PyValueError::new_err(format!(
                            "Invalid account at index {}: {}",
                            i, e
                        )));
                    }
                };

                // Determine if this account is our wallet (signer)
                let is_signer = account_pubkey == wallet_pubkey;

                // In Raydium transactions, most accounts are writable except for program IDs
                // The following is a heuristic but works well for most Raydium swaps
                let is_program = account_pubkey == raydium_program_id
                    || account_str == "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
                    || account_str == "11111111111111111111111111111111"
                    || account_str == "srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX"
                    || account_str == "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL";

                // For authority accounts, they should be readonly
                let is_authority = account_str.contains("Authority") || 
                                   account_str.contains("Signer") ||
                                   i == 2 || // AMM Authority is typically 3rd account
                                   i == 14; // Vault Signer is typically 15th account

                let is_writable = !is_program && !is_authority;

                // Add account meta with proper signer and writable flags
                if is_signer {
                    debug!("Account {}: {} (SIGNER, WRITABLE)", i, account_pubkey);
                    account_metas.push(AccountMeta::new(account_pubkey, true));
                } else if is_writable {
                    debug!("Account {}: {} (writable)", i, account_pubkey);
                    account_metas.push(AccountMeta::new(account_pubkey, false));
                } else {
                    debug!("Account {}: {} (readonly)", i, account_pubkey);
                    account_metas.push(AccountMeta::new_readonly(account_pubkey, false));
                }
            }

            // Add compute budget instructions
            let compute_limit_ix =
                ComputeBudgetInstruction::set_compute_unit_limit(config.compute_limit);
            let priority_fee_ix =
                ComputeBudgetInstruction::set_compute_unit_price(config.priority_fee);

            // Create the swap instruction with all dynamic accounts
            let swap_ix = Instruction {
                program_id: raydium_program_id,
                accounts: account_metas,
                data: instruction_data,
            };

            // Create transaction
            let mut instructions = vec![compute_limit_ix, priority_fee_ix];

            // Check if WSOL ATA needs to be created
            let wsol_mint = Pubkey::from_str(&config.sol_mint).unwrap();
            let user_wsol_account = get_associated_token_address(&wallet_pubkey, &wsol_mint);

            let wsol_account_exists = match client.get_account(&user_wsol_account).await {
                Ok(_) => true,
                Err(_) => false,
            };

            if !wsol_account_exists {
                debug!("Creating WSOL ATA account");
                let token_program = Pubkey::from_str(&config.token_program_id).unwrap();
                let ata_ix = create_associated_token_account_idempotent(
                    &wallet_pubkey,
                    &wallet_pubkey,
                    &wsol_mint,
                    &token_program,
                );
                instructions.push(ata_ix);
            }

            // Parse token mint for token ATA creation if needed
            let token_mint_pubkey = match Pubkey::from_str(&token_mint) {
                Ok(pubkey) => pubkey,
                Err(e) => {
                    pending_transaction.store(false, Ordering::Relaxed);
                    return Err(PyValueError::new_err(format!("Invalid token mint: {}", e)));
                }
            };

            // Check if token ATA exists and create if needed
            let user_token_account =
                get_associated_token_address(&wallet_pubkey, &token_mint_pubkey);
            let token_account_exists = match client.get_account(&user_token_account).await {
                Ok(_) => true,
                Err(_) => false,
            };

            if !token_account_exists {
                debug!("Creating token ATA account for {}", token_mint);
                let token_program = Pubkey::from_str(&config.token_program_id).unwrap();
                let ata_ix = create_associated_token_account_idempotent(
                    &wallet_pubkey,
                    &wallet_pubkey,
                    &token_mint_pubkey,
                    &token_program,
                );
                instructions.push(ata_ix);
            }

            // Add the swap instruction
            instructions.push(swap_ix);

            // Create transaction
            let mut transaction = Transaction::new_with_payer(&instructions, Some(&wallet_pubkey));

            // Get recent blockhash
            let blockhash = match client.get_latest_blockhash().await {
                Ok(blockhash) => blockhash,
                Err(e) => {
                    pending_transaction.store(false, Ordering::Relaxed);
                    return Err(PyValueError::new_err(format!(
                        "Failed to get recent blockhash: {}",
                        e
                    )));
                }
            };

            // Sign transaction
            transaction.sign(&[&*keypair], blockhash);

            // Send transaction with options
            let send_options = RpcSendTransactionConfig {
                skip_preflight: config.skip_preflight,
                preflight_commitment: Some(CommitmentLevel::Confirmed),
                encoding: None,
                max_retries: Some(config.max_retries.into()),
                min_context_slot: None,
            };

            debug!("Sending transaction with {} instructions", instructions.len());
            debug!("Transaction data: {:?}", transaction);

            // Optional simulation before sending
            let sim_result = client.simulate_transaction(&transaction).await;
            if let Ok(sim) = sim_result {
                if let Some(err) = sim.value.err {
                    debug!("Simulation failed: {:?}", err);
                    debug!("Logs: {:?}", sim.value.logs);
                } else {
                    debug!(
                        "Simulation successful. Units used: {}",
                        sim.value.units_consumed.unwrap_or(0)
                    );
                }
            }

            // Send transaction
            let result = client
                .send_transaction_with_config(&transaction, send_options)
                .await;

            // Reset pending transaction flag
            pending_transaction.store(false, Ordering::Relaxed);

            match result {
                Ok(signature) => {
                    debug!("Transaction successful: {}", signature);
                    let status = TransactionStatus::new(
                        signature.to_string(),
                        true,
                        None,
                        Some(
                            SystemTime::now()
                                .duration_since(UNIX_EPOCH)
                                .unwrap()
                                .as_secs(),
                        ),
                        Some(false),
                        None,
                    );
                    Ok(status)
                }
                Err(e) => {
                    debug!("Transaction failed: {}", e);
                    let status = TransactionStatus::new(
                        "failed".to_string(),
                        false,
                        Some(e.to_string()),
                        Some(
                            SystemTime::now()
                                .duration_since(UNIX_EPOCH)
                                .unwrap()
                                .as_secs(),
                        ),
                        Some(false),
                        None,
                    );
                    Ok(status)
                }
            }
        })
    }

    // CRITICAL FIX: Updated create_amm_instruction_data method to match discriminator 9 format
    fn create_amm_instruction_data(
        &self,
        amount_sol: f64,
        min_amount_out: Option<u64>,
    ) -> PyResult<Vec<u8>> {
        // Convert SOL to lamports
        let amount_lamports = (amount_sol * LAMPORTS_PER_SOL as f64) as u64;

        // Create instruction data with correct format for discriminator 9
        let mut instruction_data = Vec::with_capacity(17);
        instruction_data.push(RAYDIUM_SWAP_INSTRUCTION); // Discriminator 9

        // Add amount_in bytes in little-endian format
        instruction_data.extend_from_slice(&amount_lamports.to_le_bytes());

        // Add minimum_amount_out (required for discriminator 9)
        let min_out = min_amount_out.unwrap_or(0);
        instruction_data.extend_from_slice(&min_out.to_le_bytes());

        debug!("Created AMM instruction data: {:?}", instruction_data);

        Ok(instruction_data)
    }

    // Execute custom swap with raw instruction data
    fn execute_custom_swap<'py>(
        &self,
        py: Python<'py>,
        token_mint: String,
        instruction_data: Vec<u8>,
    ) -> PyResult<&'py PyAny> {
        let client = self.client.clone();
        let keypair = self.keypair.clone();
        let config_arc = self.config.clone();
        let pending_transaction = self.pending_transaction.clone();
        let transaction_lock = self.transaction_lock.clone();

        // Debug logging for instruction data
        debug!("Custom swap instruction data: {:?}", instruction_data);

        if instruction_data.len() < 17 {
            return Err(PyValueError::new_err(format!(
                "Instruction data too short: {} bytes, need at least 17 for discriminator 9",
                instruction_data.len()
            )));
        }

        // Debug - verify instruction type and amount
        debug!("Instruction type: 0x{:02x}", instruction_data[0]);
        let amount_bytes =
        // Extract amount from instruction data for validation
        let amount_bytes = &instruction_data[1..9];
        
        // Convert amount_bytes to a u64 (little-endian)
        let mut amount_array = [0u8; 8];
        amount_array.copy_from_slice(amount_bytes);
        let amount_lamports = u64::from_le_bytes(amount_array);
        debug!("Amount (lamports): {}", amount_lamports);
        debug!("Amount (SOL): {}", amount_lamports as f64 / LAMPORTS_PER_SOL as f64);

        // Ensure the instruction type is correct for AMM swap
        if instruction_data[0] != RAYDIUM_SWAP_INSTRUCTION {
            debug!(
                "Instruction type is not 0x{:02x}. Received: 0x{:02x}",
                RAYDIUM_SWAP_INSTRUCTION, instruction_data[0]
            );
            debug!("Creating correct instruction data");

            // Fix instruction data by reconstructing with proper discriminator
            let mut fixed_data = vec![RAYDIUM_SWAP_INSTRUCTION];
            fixed_data.extend_from_slice(amount_bytes);

            // Add min amount out (required for discriminator 9)
            fixed_data.extend_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0]); // Min amount out = 0

            debug!("Fixed instruction data: {:?}", fixed_data);

            // Continue with fixed data
            let result = self.execute_custom_swap(py, token_mint, fixed_data);
            return result;
        }

        // Ensure we're not already processing a transaction
        if pending_transaction.load(Ordering::Relaxed) {
            return Err(PyValueError::new_err(
                "A transaction is already in progress",
            ));
        }

        pyo3_asyncio::tokio::future_into_py(py, async move {
            // Use a mutex for transaction processing
            let _lock = transaction_lock.lock().await;

            // Set pending transaction flag
            pending_transaction.store(true, Ordering::Relaxed);

            // Get config
            let config = match config_arc.read() {
                Ok(config) => config.clone(),
                Err(_) => {
                    pending_transaction.store(false, Ordering::Relaxed);
                    return Err(PyValueError::new_err("Failed to read config"));
                }
            };

            // Get token pair settings or create default if not found
            let token_pair = match config.token_pair_settings.get(&token_mint) {
                Some(settings) => settings.clone(),
                None => {
                    // Dynamic creation with placeholders
                    debug!(
                        "No token pair settings found for {}. Creating dynamically.",
                        token_mint
                    );

                    // Create a default token pair setting for this token
                    // This assumes we're trading on the main Raydium V4 program
                    let default_pair = TokenPairSetting::new(
                        token_mint.clone(),
                        "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8".to_string(),
                        "5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1".to_string(),
                        "FrR9FBcDuPyMrAtUNWD3MazLyMBvJ3GjWTVLWgYtGjpG".to_string(),
                        "3uahGNzFuzSAo6QpucjfyzJkGCiZbmLEShKDXRMcEjjF".to_string(),
                        "83v8iPyZihDEjDDv9zxcm9P67MkrNfFXQocfaGmh8BSm".to_string(),
                        "8xKCx3SGwWR6BUr9mZFm3xwZUHFAVxeRUHPTpjYMJp6q".to_string(),
                        Some("srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX".to_string()),
                        Some("5S7Ppb3a68QZmRfwVYYeBJT5ZXhBgLnmhjKJi8mdYVBw".to_string()),
                        Some("AobitFHZ7jcRZRox5ACd5yvMMpsiCKd5AX3jMqiP7gdn".to_string()),
                        Some("27862HsjMmtkqa75ugKCq6EUDEskBaN6KofMVkBigJ4K".to_string()),
                        Some("Dy9wg7msvu2BseGcLVnqRsNSmukzMMDJhFgiyNN74YRK".to_string()),
                        Some("Gn2xPhz7fhcPwGaJMtbd3qW4pERksBckt22HHQn7PcZw".to_string()),
                        Some("7t47aqASGpamgRDAqfmfvq4kX9f7HKcyAuyGTH5vDnTJ".to_string()),
                        Some("Z4ygvyqDjV12fz3Sdc18RZg8UnXUvVmedafTynLAk17".to_string()),
                        None,
                        None,
                        None,
                        None,
                        None,
                        None,
                        None,
                        None,
                    );

                    // Log a warning about using placeholder data
                    debug!(
                        "CAUTION: Using placeholder pool accounts for {}. Transaction may fail.",
                        token_mint
                    );

                    default_pair
                }
            };

            // Parse Pubkeys
            let token_mint_pubkey = match Pubkey::from_str(&token_mint) {
                Ok(pubkey) => pubkey,
                Err(e) => {
                    pending_transaction.store(false, Ordering::Relaxed);
                    return Err(PyValueError::new_err(format!("Invalid token mint: {}", e)));
                }
            };

            // Create accounts for the swap
            let wallet_pubkey = keypair.pubkey();

            // Get user's WSOL account
            let wsol_mint = Pubkey::from_str(&config.sol_mint).unwrap();
            let user_wsol_account = get_associated_token_address(&wallet_pubkey, &wsol_mint);

            // Get user's token account
            let user_token_account =
                get_associated_token_address(&wallet_pubkey, &token_mint_pubkey);

            // Parse other account pubkeys
            let raydium_program = Pubkey::from_str(&config.raydium_program_id).unwrap();
            let token_program = Pubkey::from_str(&config.token_program_id).unwrap_or_else(|_| spl_token::id());

            // Parse all required account pubkeys for Raydium swap with Serum/OpenBook
            let amm_id = Pubkey::from_str(&token_pair.amm_id).unwrap();
            let amm_authority = Pubkey::from_str(&token_pair.amm_authority).unwrap();
            let amm_open_orders = Pubkey::from_str(&token_pair.amm_open_orders).unwrap();
            let amm_target = Pubkey::from_str(&token_pair.amm_target).unwrap();
            let pool_coin = Pubkey::from_str(&token_pair.pool_token_account).unwrap();
            let pool_pc = Pubkey::from_str(&token_pair.pool_pc_account).unwrap();

            // Parse Serum/OpenBook accounts
            let serum_program = Pubkey::from_str(&token_pair.serum_program_id).unwrap();
            let serum_market = Pubkey::from_str(&token_pair.serum_market).unwrap();
            let serum_bids = Pubkey::from_str(&token_pair.serum_bids).unwrap();
            let serum_asks = Pubkey::from_str(&token_pair.serum_asks).unwrap();
            let serum_event_queue = Pubkey::from_str(&token_pair.serum_event_queue).unwrap();
            let serum_coin_vault = Pubkey::from_str(&token_pair.serum_coin_vault).unwrap();
            let serum_pc_vault = Pubkey::from_str(&token_pair.serum_pc_vault).unwrap();
            let serum_vault_signer = Pubkey::from_str(&token_pair.serum_vault_signer).unwrap();

            // Debug logging
            debug!("Preparing AMM swap with accounts:");
            debug!("Token Program: {}", token_program);
            debug!("AMM ID: {}", amm_id);
            debug!("AMM Authority: {}", amm_authority);
            debug!("AMM Open Orders: {}", amm_open_orders);
            debug!("AMM Target: {}", amm_target);
            debug!("Pool Token Account: {}", pool_coin);
            debug!("Pool PC Account: {}", pool_pc);
            debug!("Serum Program: {}", serum_program);
            debug!("Serum Market: {}", serum_market);
            debug!("Serum Bids: {}", serum_bids);
            debug!("Serum Asks: {}", serum_asks);
            debug!("Serum Event Queue: {}", serum_event_queue);
            debug!("Serum Coin Vault: {}", serum_coin_vault);
            debug!("Serum PC Vault: {}", serum_pc_vault);
            debug!("Serum Vault Signer: {}", serum_vault_signer);
            debug!("User WSOL Account: {}", user_wsol_account);
            debug!("User Token Account: {}", user_token_account);
            debug!("Wallet: {}", wallet_pubkey);

            // Create swap instruction with all 18 required accounts in correct order
            // CRITICAL: This matches the exact account structure for Raydium V4 AMM swaps
            let swap_ix = Instruction {
                program_id: raydium_program,
                accounts: vec![
                    AccountMeta::new_readonly(token_program, false), // 1. Token Program
                    AccountMeta::new(amm_id, false),                 // 2. AMM ID (Market)
                    AccountMeta::new_readonly(amm_authority, false), // 3. AMM Authority
                    AccountMeta::new(amm_open_orders, false),        // 4. AMM Open Orders
                    AccountMeta::new(amm_target, false),             // 5. AMM Target
                    AccountMeta::new(pool_coin, false),              // 6. Pool Coin Account
                    AccountMeta::new(pool_pc, false),                // 7. Pool PC Account
                    AccountMeta::new_readonly(serum_program, false), // 8. Serum Program
                    AccountMeta::new(serum_market, false),           // 9. Serum Market
                    AccountMeta::new(serum_bids, false),             // 10. Serum Bids
                    AccountMeta::new(serum_asks, false),             // 11. Serum Asks
                    AccountMeta::new(serum_event_queue, false),      // 12. Serum Event Queue
                    AccountMeta::new(serum_coin_vault, false),       // 13. Serum Coin Vault
                    AccountMeta::new(serum_pc_vault, false),         // 14. Serum PC Vault
                    AccountMeta::new_readonly(serum_vault_signer, false), // 15. Serum Vault Signer
                    AccountMeta::new(user_wsol_account, false),      // 16. User Source Token
                    AccountMeta::new(user_token_account, false),     // 17. User Dest Token
                    AccountMeta::new(wallet_pubkey, true),           // 18. User Source Owner
                ],
                data: instruction_data.clone(),
            };

            // Add compute budget instructions with optimized priority fee
            let compute_limit_ix =
                ComputeBudgetInstruction::set_compute_unit_limit(config.compute_limit);
            let priority_fee_ix =
                ComputeBudgetInstruction::set_compute_unit_price(config.priority_fee);

            // Create ATA instruction if needed
            let mut instructions = vec![compute_limit_ix, priority_fee_ix];

            // Check if WSOL ATA exists and create if needed (idempotent operation)
            let wsol_account_exists = match client.get_account(&user_wsol_account).await {
                Ok(_) => true,
                Err(_) => false,
            };

            if !wsol_account_exists {
                debug!("Creating WSOL ATA account");
                let ata_ix = create_associated_token_account_idempotent(
                    &wallet_pubkey,
                    &wallet_pubkey,
                    &wsol_mint,
                    &token_program,
                );
                instructions.push(ata_ix);
            }

            // Check if token ATA exists and create if needed (idempotent operation)
            let token_account_exists = match client.get_account(&user_token_account).await {
                Ok(_) => true,
                Err(_) => false,
            };

            if !token_account_exists {
                debug!("Creating token ATA account for {}", token_mint);
                let ata_ix = create_associated_token_account_idempotent(
                    &wallet_pubkey,
                    &wallet_pubkey,
                    &token_mint_pubkey,
                    &token_program,
                );
                instructions.push(ata_ix);
            }

            // Add the swap instruction
            instructions.push(swap_ix);

            // Create transaction
            let mut transaction = Transaction::new_with_payer(&instructions, Some(&wallet_pubkey));

            // Get recent blockhash
            let blockhash = match client.get_latest_blockhash().await {
                Ok(blockhash) => blockhash,
                Err(e) => {
                    pending_transaction.store(false, Ordering::Relaxed);
                    return Err(PyValueError::new_err(format!(
                        "Failed to get recent blockhash: {}",
                        e
                    )));
                }
            };

            // Sign transaction
            transaction.sign(&[&*keypair], blockhash);

            // Send transaction
            debug!(
                "Sending transaction with instruction data: {:?}",
                instruction_data
            );
            let send_options = RpcSendTransactionConfig {
                skip_preflight: config.skip_preflight,
                preflight_commitment: Some(CommitmentLevel::Confirmed),
                encoding: None,
                max_retries: Some(config.max_retries.into()),
                min_context_slot: None,
            };

            // Optional simulation before sending for pre-flight validation
            let sim_config = RpcSimulateTransactionConfig {
                sig_verify: false,
                replace_recent_blockhash: true,
                commitment: Some(CommitmentConfig::confirmed()),
                encoding: None,
                accounts: None,
                min_context_slot: None,
                inner_instructions: Some(true),
            };
            
            let sim_result = client.simulate_transaction_with_config(&transaction, sim_config).await;
            if let Ok(sim) = sim_result {
                if let Some(err) = sim.value.err {
                    debug!("Simulation failed: {:?}", err);
                    debug!("Logs: {:?}", sim.value.logs);
                    
                    // Enhanced error diagnostics for Raydium-specific errors
                    if let Some(logs) = &sim.value.logs {
                        for log in logs {
                            if log.contains("Program log: Instruction: Swap") {
                                debug!("Found Raydium Swap instruction in logs");
                            }
                            if log.contains("Program log: Error") {
                                debug!("Found error in program logs: {}", log);
                            }
                        }
                    }
                } else {
                    debug!("Simulation successful");
                }
            }

            // Attempt to send transaction
            let result = client
                .send_transaction_with_config(&transaction, send_options)
                .await;

            // Reset pending transaction flag immediately after sending
            // regardless of outcome to prevent transaction lock
            pending_transaction.store(false, Ordering::Relaxed);

            match result {
                Ok(signature) => {
                    debug!("Transaction successful: {}", signature);
                    // Create successful status object with signature
                    let status = TransactionStatus::new(
                        signature.to_string(),
                        true,
                        None,
                        Some(
                            SystemTime::now()
                                .duration_since(UNIX_EPOCH)
                                .unwrap()
                                .as_secs(),
                        ),
                        Some(false),
                        None,
                    );
                    Ok(status)
                }
                Err(e) => {
                    debug!("Transaction failed: {}", e);
                    let error_msg = e.to_string();

                    // Enhanced error diagnostics for common Raydium failures
                    if error_msg.contains("0x6") {
                        debug!("This appears to be a Raydium swap instruction error. Check the following:");
                        debug!("1. Make sure the token mint address is correct");
                        debug!("2. Make sure the AMM ID is correct");
                        debug!("3. Check if there's enough liquidity in the pool");
                    } else if error_msg.contains("blockhash") {
                        debug!("Blockhash expired - network may be congested");
                    } else if error_msg.contains("insufficient funds") {
                        debug!("Insufficient funds for transaction");
                    }

                    // Create failed status object with error message
                    let status = TransactionStatus::new(
                        "failed".to_string(),
                        false,
                        Some(error_msg),
                        Some(
                            SystemTime::now()
                                .duration_since(UNIX_EPOCH)
                                .unwrap()
                                .as_secs(),
                        ),
                        Some(false),
                        None,
                    );
                    Ok(status)
                }
            }
        })
    }

    // Function to execute a swap on Raydium
    fn execute_swap<'py>(&self, py: Python<'py>, params: SwapParams) -> PyResult<&'py PyAny> {
        let client = self.client.clone();
        let keypair = self.keypair.clone();
        let config_arc = self.config.clone();
        let rate_limiter = self.rate_limiter.clone();
        let pending_transaction = self.pending_transaction.clone();
        let transaction_lock = self.transaction_lock.clone();

        // Apply rate limiting if enabled
        if !rate_limiter.check_and_increment() {
            return Err(PyValueError::new_err(
                "Rate limit exceeded. Please try again later.",
            ));
        }

        // Check if a transaction is already pending
        if pending_transaction.load(Ordering::Relaxed) {
            return Err(PyValueError::new_err(
                "A transaction is already in progress",
            ));
        }

        let params_clone = params.clone();

        pyo3_asyncio::tokio::future_into_py(py, async move {
            // Use a mutex for transaction processing
            let _lock = transaction_lock.lock().await;

            // Set pending transaction flag
            pending_transaction.store(true, Ordering::Relaxed);

            // Get config values
            let config = match config_arc.read() {
                Ok(config) => config.clone(),
                Err(_) => {
                    pending_transaction.store(false, Ordering::Relaxed);
                    return Err(PyValueError::new_err("Failed to read config"));
                }
            };

            // Retrieve token pair settings or dynamically create if not found
            let token_pair = match config.token_pair_settings.get(&params_clone.token_mint) {
                Some(settings) => settings.clone(),
                None => {
                    if Some(params_clone.token_mint.clone()) == config.token_mint {
                        // Handle synthetic token pair logic for default token
                        let all_present = config.amm_id.is_some()
                            && config.market_amm_authority.is_some()
                            && config.market_amm_open_orders.is_some()
                            && config.market_amm_target.is_some()
                            && config.market_pool_token_account.is_some()
                            && config.market_pool_pc_token_account.is_some()
                            && config.serum_program_id.is_some()
                            && config.serum_market.is_some()
                            && config.serum_bids.is_some()
                            && config.serum_asks.is_some()
                            && config.serum_event_queue.is_some()
                            && config.serum_coin_vault.is_some()
                            && config.serum_pc_vault.is_some()
                            && config.serum_vault_signer.is_some();

                        if all_present {
                            // Return synthetic settings from config
                            TokenPairSetting::new(
                                params_clone.token_mint.clone(),
                                config.amm_id.clone().unwrap(),
                                config.market_amm_authority.as_ref().unwrap().clone(),
                                config.market_amm_open_orders.as_ref().unwrap().clone(),
                                config.market_amm_target.as_ref().unwrap().clone(),
                                config.market_pool_token_account.as_ref().unwrap().clone(),
                                config
                                    .market_pool_pc_token_account
                                    .as_ref()
                                    .unwrap()
                                    .clone(),
                                config.serum_program_id.clone(),
                                config.serum_market.clone(),
                                config.serum_bids.clone(),
                                config.serum_asks.clone(),
                                config.serum_event_queue.clone(),
                                config.serum_coin_vault.clone(),
                                config.serum_pc_vault.clone(),
                                config.serum_vault_signer.clone(),
                                None,
                                None,
                                None,
                                None,
                                None,
                                None,
                                None,
                                None,
                            )
                        } else {
                            // Create default settings with placeholders
                            debug!(
                                "No token pair settings found for {}. Creating dynamically.",
                                params_clone.token_mint
                            );

                            // Create a default token pair setting for this token
                            TokenPairSetting::new(
                                params_clone.token_mint.clone(),
                                "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8".to_string(),
                                "5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1".to_string(),
                                "FrR9FBcDuPyMrAtUNWD3MazLyMBvJ3GjWTVLWgYtGjpG".to_string(),
                                "3uahGNzFuzSAo6QpucjfyzJkGCiZbmLEShKDXRMcEjjF".to_string(),
                                "83v8iPyZihDEjDDv9zxcm9P67MkrNfFXQocfaGmh8BSm".to_string(),
                                "8xKCx3SGwWR6BUr9mZFm3xwZUHFAVxeRUHPTpjYMJp6q".to_string(),
                                Some("srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX".to_string()),
                                Some("5S7Ppb3a68QZmRfwVYYeBJT5ZXhBgLnmhjKJi8mdYVBw".to_string()),
                                Some("AobitFHZ7jcRZRox5ACd5yvMMpsiCKd5AX3jMqiP7gdn".to_string()),
                                Some("27862HsjMmtkqa75ugKCq6EUDEskBaN6KofMVkBigJ4K".to_string()),
                                Some("Dy9wg7msvu2BseGcLVnqRsNSmukzMMDJhFgiyNN74YRK".to_string()),
                                Some("Gn2xPhz7fhcPwGaJMtbd3qW4pERksBckt22HHQn7PcZw".to_string()),
                                Some("7t47aqASGpamgRDAqfmfvq4kX9f7HKcyAuyGTH5vDnTJ".to_string()),
                                Some("Z4ygvyqDjV12fz3Sdc18RZg8UnXUvVmedafTynLAk17".to_string()),
                                None,
                                None,
                                None,
                                None,
                                None,
                                None,
                                None,
                                None,
                            )
                        }
                    } else {
                        // Create default settings with placeholders
                        debug!(
                            "No token pair settings found for {}. Creating dynamically.",
                            params_clone.token_mint
                        );

                        // Create a default token pair setting for this token
                        TokenPairSetting::new(
                            params_clone.token_mint.clone(),
                            "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8".to_string(),
                            "5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1".to_string(),
                            "FrR9FBcDuPyMrAtUNWD3MazLyMBvJ3GjWTVLWgYtGjpG".to_string(),
                            "3uahGNzFuzSAo6QpucjfyzJkGCiZbmLEShKDXRMcEjjF".to_string(),
                            "83v8iPyZihDEjDDv9zxcm9P67MkrNfFXQocfaGmh8BSm".to_string(),
                            "8xKCx3SGwWR6BUr9mZFm3xwZUHFAVxeRUHPTpjYMJp6q".to_string(),
                            Some("srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX".to_string()),
                            Some("5S7Ppb3a68QZmRfwVYYeBJT5ZXhBgLnmhjKJi8mdYVBw".to_string()),
                            Some("AobitFHZ7jcRZRox5ACd5yvMMpsiCKd5AX3jMqiP7gdn".to_string()),
                            Some("27862HsjMmtkqa75ugKCq6EUDEskBaN6KofMVkBigJ4K".to_string()),
                            Some("Dy9wg7msvu2BseGcLVnqRsNSmukzMMDJhFgiyNN74YRK".to_string()),
                            Some("Gn2xPhz7fhcPwGaJMtbd3qW4pERksBckt22HHQn7PcZw".to_string()),
                            Some("7t47aqASGpamgRDAqfmfvq4kX9f7HKcyAuyGTH5vDnTJ".to_string()),
                            Some("Z4ygvyqDjV12fz3Sdc18RZg8UnXUvVmedafTynLAk17".to_string()),
                            None,
                            None,
                            None,
                            None,
                            None,
                            None,
                            None,
                            None,
                        )
                    }
                }
            };

            // Generate, sign, and send a transaction to perform the swap
            let token_mint_pubkey = match Pubkey::from_str(&params_clone.token_mint) {
                Ok(pubkey) => pubkey,
                Err(e) => {
                    pending_transaction.store(false, Ordering::Relaxed);
                    return Err(PyValueError::new_err(format!("Invalid token mint: {}", e)));
                }
            };

            // Create proper instruction data for Raydium swap discriminator 9
            // with the correct instruction ID, amount, and min amount out
            let amount_lamports = (params_clone.amount_in * LAMPORTS_PER_SOL as f64) as u64;
            let min_amount_out = params_clone.min_amount_out.unwrap_or(0);

            // Create instruction data with both amountIn and minimumAmountOut
            let mut instruction_data = Vec::with_capacity(17);
            instruction_data.push(RAYDIUM_SWAP_INSTRUCTION); // Discriminator 9 (0x09)
            instruction_data.extend_from_slice(&amount_lamports.to_le_bytes()); // amountIn (8 bytes)
            instruction_data.extend_from_slice(&min_amount_out.to_le_bytes()); // minimumAmountOut (8 bytes)

            debug!("Created swap instruction with data: {:?}", instruction_data);

            // Create and send transaction with the proper instruction data
            let result =
                execute_swap_internal(&client, &keypair, &token_pair, &instruction_data).await;

            // Reset pending transaction flag
            pending_transaction.store(false, Ordering::Relaxed);

            match result {
                Ok(signature) => {
                    let status = TransactionStatus::new(
                        signature,
                        true,
                        None,
                        Some(
                            SystemTime::now()
                                .duration_since(UNIX_EPOCH)
                                .unwrap()
                                .as_secs(),
                        ),
                        Some(false),
                        None,
                    );
                    Ok(status)
                }
                Err(e) => {
                    let status = TransactionStatus::new(
                        "failed".to_string(),
                        false,
                        Some(e.to_string()),
                        Some(
                            SystemTime::now()
                                .duration_since(UNIX_EPOCH)
                                .unwrap()
                                .as_secs(),
                        ),
                        Some(false),
                        None,
                    );
                    Ok(status)
                }
            }
        })
    }

    // Get balances for SOL and SPL tokens with robust error handling
    fn get_balances<'py>(&self, py: Python<'py>) -> PyResult<&'py PyAny> {
        let client = self.client.clone();
        let keypair = self.keypair.clone();
        let config_arc = self.config.clone();
        let balances_arc = self.balances.clone();
        let token_cache = self.token_cache.clone();

        pyo3_asyncio::tokio::future_into_py(py, async move {
            let pubkey = keypair.pubkey();

            // Get SOL balance with proper error propagation
            let sol_balance = client
                .get_balance(&pubkey)
                .await
                .map_err(|e| PyValueError::new_err(format!("Failed to get SOL balance: {}", e)))?;

            let sol_balance_f64 = sol_balance as f64 / LAMPORTS_PER_SOL as f64;

            // Get config with proper error handling
            let config = match config_arc.read() {
                Ok(config) => config.clone(),
                Err(_) => return Err(PyValueError::new_err("Failed to read config")),
            };

            // Get token balances
            let mut token_balances = HashMap::new();

            // Add WSOL balance with special handling
            let wsol_mint_pubkey = Pubkey::from_str(&config.sol_mint).unwrap();
            let wsol_token_account = get_associated_token_address(&pubkey, &wsol_mint_pubkey);

            // Check if WSOL token account exists
            let wsol_account = client.get_account(&wsol_token_account).await;

            if let Ok(account) = wsol_account {
                // Parse token account data with proper error handling
                if let Ok(token_account) = spl_token::state::Account::unpack_from_slice(&account.data) {
                    let wsol_balance = token_account.amount as f64 / LAMPORTS_PER_SOL as f64;
                    token_balances.insert(config.sol_mint.clone(), wsol_balance);
                } else {
                    debug!("Failed to parse WSOL token account data");
                    token_balances.insert(config.sol_mint.clone(), 0.0);
                }
            } else {
                // Account doesn't exist, balance is 0
                token_balances.insert(config.sol_mint.clone(), 0.0);
            }

            // Get token balances for all active tokens with proper error handling
            for token_mint in config.get_active_token_mints()? {
                if token_mint == config.sol_mint {
                    continue; // Already added WSOL above
                }

                // Properly handle token mint parsing
                let token_mint_pubkey = match Pubkey::from_str(&token_mint) {
                    Ok(pubkey) => pubkey,
                    Err(e) => {
                        debug!("Invalid token mint {}: {}", token_mint, e);
                        continue; // Skip invalid mints
                    }
                };

                let token_account = get_associated_token_address(&pubkey, &token_mint_pubkey);

                // Check if token account exists
                let account = client.get_account(&token_account).await;

                if let Ok(account) = account {
                    // Parse token account data with proper error handling
                    if let Ok(token_account) = spl_token::state::Account::unpack_from_slice(&account.data) {
                        // Get token decimals from cache or settings
                        let decimals = if let Some(cached) = token_cache.get(&token_mint) {
                            cached.decimals
                        } else if let Some(pair) = config.token_pair_settings.get(&token_mint) {
                            pair.token_decimals
                        } else {
                            // Use Mint account to get decimals
                            match client.get_account(&token_mint_pubkey).await {
                                Ok(mint_account) => {
                                    if mint_account.data.len() >= 45 {
                                        // SPL Token mint layout has decimals at offset 44
                                        let decimals = mint_account.data[44];
                                        // Cache the result for future use
                                        token_cache.insert(token_mint.clone(), TokenMetadata {
                                            decimals,
                                            verified: false,
                                            last_updated: SystemTime::now()
                                                .duration_since(UNIX_EPOCH)
                                                .unwrap()
                                                .as_secs(),
                                        });
                                        decimals
                                    } else {
                                        9 // Default if mint data is invalid
                                    }
                                }
                                Err(_) => 9, // Default to 9 decimals if mint account fetch fails
                            }
                        };
                        
                        // Calculate balance with proper decimal handling
                        let token_balance = token_account.amount as f64 / 10f64.powf(decimals as f64);
                        token_balances.insert(token_mint.clone(), token_balance);
                    } else {
                        debug!("Failed to parse token account data for {}", token_mint);
                        token_balances.insert(token_mint.clone(), 0.0);
                    }
                } else {
                    // Account doesn't exist, balance is 0
                    token_balances.insert(token_mint.clone(), 0.0);
                }
            }

            // Update cached balances with proper error handling
            if let Ok(mut balances) = balances_arc.write() {
                *balances = (sol_balance_f64, token_balances.clone());
            }

            Ok((sol_balance_f64, token_balances))
        })
    }

    // Create or get associated token account for a token mint
    fn ensure_ata<'py>(&self, py: Python<'py>, token_mint: String) -> PyResult<&'py PyAny> {
        let client = self.client.clone();
        let keypair = self.keypair.clone();
        let config_arc = self.config.clone();

        pyo3_asyncio::tokio::future_into_py(py, async move {
            let pubkey = keypair.pubkey();

            // Parse token mint with proper error handling
            let token_mint_pubkey = Pubkey::from_str(&token_mint)
                .map_err(|e| PyValueError::new_err(format!("Invalid token mint: {}", e)))?;

            // Get associated token account address
            let ata = get_associated_token_address(&pubkey, &token_mint_pubkey);

            // Check if account exists
            let account = client.get_account(&ata).await;
            
            // Get config for token program ID
            let config = match config_arc.read() {
                Ok(config) => config.clone(),
                Err(_) => return Err(PyValueError::new_err("Failed to read config")),
            };

            if account.is_err() {
                // Account doesn't exist, create ATA instruction
                let token_program = Pubkey::from_str(&config.token_program_id)
                    .unwrap_or_else(|_| spl_token::id());
                
                let ix = create_associated_token_account_idempotent(
                    &pubkey,            // Payer
                    &pubkey,            // Owner
                    &token_mint_pubkey, // Mint
                    &token_program,     // Token program
                );

                // Create transaction with compute budget instructions
                let compute_limit_ix =
                    ComputeBudgetInstruction::set_compute_unit_limit(COMPUTE_UNITS);
                let priority_fee_ix =
                    ComputeBudgetInstruction::set_compute_unit_price(PRIORITY_FEE);
                
                let mut transaction = Transaction::new_with_payer(
                    &[compute_limit_ix, priority_fee_ix, ix], 
                    Some(&pubkey)
                );

                // Get recent blockhash with proper error handling
                let blockhash = client.get_latest_blockhash().await.map_err(|e| {
                    PyValueError::new_err(format!("Failed to get blockhash: {}", e))
                })?;

                // Sign transaction
                transaction.sign(&[&*keypair], blockhash);

                // Send transaction with retry logic
                let mut retries = 0;
                let max_retries = 3;
                let mut last_error = None;

                while retries < max_retries {
                    match client.send_transaction(&transaction).await {
                        Ok(signature) => {
                            debug!("Created ATA for {}: {}", token_mint, signature);
                            break;
                        }
                        Err(e) => {
                            retries += 1;
                            last_error = Some(e.to_string());
                            if retries < max_retries {
                                debug!("ATA creation failed, retrying ({}/{}): {}", retries, max_retries, e);
                                // Exponential backoff
                                tokio::time::sleep(tokio::time::Duration::from_millis(500 * (1 << retries))).await;
                            }
                        }
                    }
                }

                if retries == max_retries {
                    return Err(PyValueError::new_err(format!(
                        "Failed to create ATA after {} attempts: {}",
                        max_retries,
                        last_error.unwrap_or_else(|| "Unknown error".to_string())
                    )));
                }
            }

            Ok(ata.to_string())
        })
    }

    // Update ML signal (placeholder for ML integration)
    fn update_ml_signal(&self, key: String, value: f64) -> PyResult<()> {
        // This is a placeholder for ML signal update functionality
        // In a production implementation, this would update an ML model
        debug!("Updated ML signal: {} = {}", key, value);
        Ok(())
    }

    // Simulate transaction before sending for pre-flight validation
    fn simulate_swap<'py>(
        &self,
        py: Python<'py>,
        token_mint: String,
        amount_sol: f64,
    ) -> PyResult<&'py PyAny> {
        let client = self.client.clone();
        let keypair = self.keypair.clone();
        let config_arc = self.config.clone();

        pyo3_asyncio::tokio::future_into_py(py, async move {
            // Get config
            let config = match config_arc.read() {
                Ok(config) => config.clone(),
                Err(_) => return Err(PyValueError::new_err("Failed to read config")),
            };

            // Create instruction data with correct Raydium V4 AMM format
            let amount_lamports = (amount_sol * LAMPORTS_PER_SOL as f64) as u64;
            let mut instruction_data = Vec::with_capacity(17);
            instruction_data.push(RAYDIUM_SWAP_INSTRUCTION); // Discriminator 9
            instruction_data.extend_from_slice(&amount_lamports.to_le_bytes()); // amountIn
            instruction_data.extend_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0]); // minimumAmountOut = 0

            // Get token pair settings or create default with proper error handling
            let token_pair = match config.token_pair_settings.get(&token_mint) {
                Some(settings) => settings.clone(),
                None => {
                    // Create default settings with placeholders
                    debug!(
                        "No token pair settings found for {}. Creating dynamically for simulation.",
                        token_mint
                    );

                    TokenPairSetting::new(
                        token_mint.clone(),
                        "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8".to_string(),
                        "5Q544fKrFoe6tsEbD7S8EmxGTJYAKtTVhAW5Q5pge4j1".to_string(),
                        "FrR9FBcDuPyMrAtUNWD3MazLyMBvJ3GjWTVLWgYtGjpG".to_string(),
                        "3uahGNzFuzSAo6QpucjfyzJkGCiZbmLEShKDXRMcEjjF".to_string(),
                        "83v8iPyZihDEjDDv9zxcm9P67MkrNfFXQocfaGmh8BSm".to_string(),
                        "8xKCx3SGwWR6BUr9mZFm3xwZUHFAVxeRUHPTpjYMJp6q".to_string(),
                        // Add Serum/OpenBook parameters with placeholders
                        Some("srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX".to_string()),
                        Some("5S7Ppb3a68QZmRfwVYYeBJT5ZXhBgLnmhjKJi8mdYVBw".to_string()),
                        Some("AobitFHZ7jcRZRox5ACd5yvMMpsiCKd5AX3jMqiP7gdn".to_string()),
                        Some("27862HsjMmtkqa75ugKCq6EUDEskBaN6KofMVkBigJ4K".to_string()),
                        Some("Dy9wg7msvu2BseGcLVnqRsNSmukzMMDJhFgiyNN74YRK".to_string()),
                        Some("Gn2xPhz7fhcPwGaJMtbd3qW4pERksBckt22HHQn7PcZw".to_string()),
                        Some("7t47aqASGpamgRDAqfmfvq4kX9f7HKcyAuyGTH5vDnTJ".to_string()),
                        Some("Z4ygvyqDjV12fz3Sdc18RZg8UnXUvVmedafTynLAk17".to_string()),
                        None,
                        None,
                        None,
                        None,
                        None,
                        None,
                        None,
                        None,
                    )
                }
            };

            // Build transaction similarly to execute_custom_swap
            let wallet_pubkey = keypair.pubkey();
            let token_mint_pubkey = match Pubkey::from_str(&token_mint) {
                Ok(pubkey) => pubkey,
                Err(e) => return Err(PyValueError::new_err(format!("Invalid token mint: {}", e))),
            };
            let wsol_mint = Pubkey::from_str(&config.sol_mint).unwrap();
            let user_wsol_account = get_associated_token_address(&wallet_pubkey, &wsol_mint);
            let user_token_account =
                get_associated_token_address(&wallet_pubkey, &token_mint_pubkey);

            // Parse all required pubkeys
            let raydium_program = Pubkey::from_str(&config.raydium_program_id).unwrap();
            let token_program = Pubkey::from_str(&config.token_program_id).unwrap_or_else(|_| spl_token::id());

            let amm_id = Pubkey::from_str(&token_pair.amm_id).unwrap();
            let amm_authority = Pubkey::from_str(&token_pair.amm_authority).unwrap();
            let amm_open_orders = Pubkey::from_str(&token_pair.amm_open_orders).unwrap();
            let amm_target = Pubkey::from_str(&token_pair.amm_target).unwrap();
            let pool_coin = Pubkey::from_str(&token_pair.pool_token_account).unwrap();
            let pool_pc = Pubkey::from_str(&token_pair.pool_pc_account).unwrap();

            // Parse Serum/OpenBook accounts
            let serum_program = Pubkey::from_str(&token_pair.serum_program_id).unwrap();
            let serum_market = Pubkey::from_str(&token_pair.serum_market).unwrap();
            let serum_bids = Pubkey::from_str(&token_pair.serum_bids).unwrap();
            let serum_asks = Pubkey::from_str(&token_pair.serum_asks).unwrap();
            let serum_event_queue = Pubkey::from_str(&token_pair.serum_event_queue).unwrap();
            let serum_coin_vault = Pubkey::from_str(&token_pair.serum_coin_vault).unwrap();
            let serum_pc_vault = Pubkey::from_str(&token_pair.serum_pc_vault).unwrap();
            let serum_vault_signer = Pubkey::from_str(&token_pair.serum_vault_signer).unwrap();

            // Create swap instruction with all 18 required accounts in correct Raydium V4 order
            let swap_ix = Instruction {
                program_id: raydium_program,
                accounts: vec![
                    AccountMeta::new_readonly(token_program, false), // 1. Token Program
                    AccountMeta::new(amm_id, false),                 // 2. AMM ID (Market)
                    AccountMeta::new_readonly(amm_authority, false), // 3. AMM Authority
                    AccountMeta::new(amm_open_orders, false),        // 4. AMM Open Orders
                    AccountMeta::new(amm_target, false),             // 5. AMM Target
                    AccountMeta::new(pool_coin, false),              // 6. Pool Coin Account
                    AccountMeta::new(pool_pc, false),                // 7. Pool PC Account
                    AccountMeta::new_readonly(serum_program, false), // 8. Serum Program
                    AccountMeta::new(serum_market, false),           // 9. Serum Market
                    AccountMeta::new(serum_bids, false),             // 10. Serum Bids
                    AccountMeta::new(serum_asks, false),             // 11. Serum Asks
                    AccountMeta::new(serum_event_queue, false),      // 12. Serum Event Queue
                    AccountMeta::new(serum_coin_vault, false),       // 13. Serum Coin Vault
                    AccountMeta::new(serum_pc_vault, false),         // 14. Serum PC Vault
                    AccountMeta::new_readonly(serum_vault_signer, false), // 15. Serum Vault Signer
                    AccountMeta::new(user_wsol_account, false),      // 16. User Source Token
                    AccountMeta::new(user_token_account, false),     // 17. User Dest Token
                    AccountMeta::new(wallet_pubkey, true),           // 18. User Source Owner
                ],
                data: instruction_data,
            };

            // Add compute budget instructions
            let compute_limit_ix =
                ComputeBudgetInstruction::set_compute_unit_limit(config.compute_limit);
            let priority_fee_ix =
                ComputeBudgetInstruction::set_compute_unit_price(config.priority_fee);

            // Create transaction
            let mut instructions = vec![compute_limit_ix, priority_fee_ix];

            // Create ATA instruction if needed with idempotent checks
            let wsol_account_exists = match client.get_account(&user_wsol_account).await {
                Ok(_) => true,
                Err(_) => false,
            };

            if !wsol_account_exists {
                let ata_ix = create_associated_token_account_idempotent(
                    &wallet_pubkey,
                    &wallet_pubkey,
                    &wsol_mint,
                    &token_program,
                );
                instructions.push(ata_ix); // Insert before swap instruction
            }

            // Also check if token ATA needs to be created
            let token_account_exists = match client.get_account(&user_token_account).await {
                Ok(_) => true,
                Err(_) => false,
            };

            if !token_account_exists {
                let ata_ix = create_associated_token_account_idempotent(
                    &wallet_pubkey,
                    &wallet_pubkey,
                    &token_mint_pubkey,
                    &token_program,
                );
                instructions.push(ata_ix); // Insert before swap instruction
            }

            // Add the swap instruction
            instructions.push(swap_ix);

            // Create transaction
            let mut transaction = Transaction::new_with_payer(&instructions, Some(&wallet_pubkey));

            // Get recent blockhash with proper error handling
            let blockhash = match client.get_latest_blockhash().await {
                Ok(blockhash) => blockhash,
                Err(e) => {
                    return Err(PyValueError::new_err(format!(
                        "Failed to get blockhash: {}",
                        e
                    )))
                }
            };
            transaction.sign(&[&*keypair], blockhash);

            // Simulate transaction with enhanced config
            let sim_config = RpcSimulateTransactionConfig {
                sig_verify: false,
                replace_recent_blockhash: true,
                commitment: Some(CommitmentConfig::confirmed()),
                encoding: None,
                accounts: None,
                min_context_slot: None,
                inner_instructions: Some(true),
            };
            
            let sim_result = match client.simulate_transaction_with_config(&transaction, sim_config).await {
                Ok(result) => result,
                Err(e) => return Err(PyValueError::new_err(format!("Simulation failed: {}", e))),
            };

            // Enhanced analysis of simulation results
            let mut swap_success = sim_result.value.err.is_none();
            let mut consumed_units = sim_result.value.units_consumed.unwrap_or(0);
            let logs = sim_result.value.logs.clone().unwrap_or_else(|| vec![]);
            
            // Parse logs for detailed error information and swap result analysis
            let mut detailed_error = None;
            let mut estimated_output_amount = 0u64;
            
            for log in &logs {
                // Check for specific Raydium error codes
                if log.contains("Program log: Error: ") {
                    detailed_error = Some(log.clone());
                }
                
                // Look for successful swap outputs
                if log.contains("Program log: Instruction: Swap") {
                    debug!("Found Raydium Swap instruction execution");
                }
                
                // Parse output amount information (in a production system this would be more detailed)
                if log.contains("Tokens received: ") {
                    if let Some(amount_str) = log.split("Tokens received: ").nth(1) {
                        if let Ok(amount) = amount_str.trim().parse::<u64>() {
                            estimated_output_amount = amount;
                        }
                    }
                }
            }
            
            // Enhanced error analysis
            if let Some(err) = &sim_result.value.err {
                match err {
                    solana_client::client_error::TransactionError::InstructionError(_, _) => {
                        swap_success = false;
                        if detailed_error.is_none() {
                            detailed_error = Some(format!("Instruction error: {:?}", err));
                        }
                    }
                    _ => {
                        swap_success = false;
                        if detailed_error.is_none() {
                            detailed_error = Some(format!("Transaction error: {:?}", err));
                        }
                    }
                }
            }

            // Create enhanced status object with detailed simulation results
            let status = TransactionStatus::new(
                "simulation".to_string(),
                swap_success,
                detailed_error.or_else(|| sim_result.value.err.map(|e| format!("{:?}", e))),
                Some(
                    SystemTime::now()
                        .duration_since(UNIX_EPOCH)
                        .unwrap()
                        .as_secs(),
                ),
                Some(true),
                Some(logs),
            );

            Ok(status)
        })
    }
}

// Internal function to check token safety with comprehensive validation
async fn check_token_safety_internal(
    client: &RpcClient,
    token_mint: &str,
) -> Result<TokenSafetyCheck, PyErr> {
    let mut is_safe = true;
    let mut reason = None;

    // Check if the token mint exists and is valid
    let token_mint_pubkey = match Pubkey::from_str(token_mint) {
        Ok(pubkey) => pubkey,
        Err(e) => {
            return Ok(TokenSafetyCheck::new(
                token_mint.to_string(),
                false,
                None,
                None,
                None,
                None,
                None,
                None,
                Some(format!("Invalid token mint: {}", e)),
            ));
        }
    };

    // Fetch the token mint account data with proper error handling
    let mint_account = match client.get_account(&token_mint_pubkey).await {
        Ok(account) => account,
        Err(e) => {
            return Ok(TokenSafetyCheck::new(
                token_mint.to_string(),
                false,
                None,
                None,
                None,
                None,
                None,
                None,
                Some(format!("Failed to get token mint account: {}", e)),
            ));
        }
    };

    // Parse the mint data
    let mint_data = mint_account.data.clone();

    // Check if mint data is valid SPL token mint
    if mint_data.len() < 82 {
        return Ok(TokenSafetyCheck::new(
            token_mint.to_string(),
            false,
            None,
            None,
            None,
            None,
            None,
            None,
            Some("Invalid token mint data".to_string()),
        ));
    }

    // Validate mint authority revocation - critical for security
    // For a revoked mint authority, offset 0 will be 0
    let auth_revoked = mint_data[0] == 0;

    // Get token decimals for proper amount parsing
    let decimals = mint_data[44];

    // If mint authority is not revoked, token is potentially unsafe
    if !auth_revoked {
        is_safe = false;
        reason = Some("Mint authority not revoked. Token supply can be inflated.".to_string());
    }

    // In a production implementation, perform additional checks:
    // 1. Pool liquidity (fetch pool token accounts)
    // 2. Check if liquidity is locked (check timelock program accounts)
    // 3. Verify the token is known/verified (check against a list)
    // 4. Check mint supply caps
    // 5. Validate transfer fee settings
    // 6. Check for interest-bearing token flags

    // Simplified placeholder implementation for now
    let liquidity_sol = 10.0; // In production: compute actual liquidity from pool accounts
    let has_liquidity = liquidity_sol >= MIN_LIQUIDITY_SOL;
    let liquidity_locked = true; // In production: check timelock program accounts
    let verified = false; // In production: check against verified token registry

    // Check if liquidity is sufficient
    if !has_liquidity {
        is_safe = false;
        reason = Some(format!(
            "Insufficient liquidity. Only {:.2} SOL in pool, minimum required is {:.2}",
            liquidity_sol, MIN_LIQUIDITY_SOL
        ));
    }

    // Create and return comprehensive safety check result
    Ok(TokenSafetyCheck::new(
        token_mint.to_string(),
        is_safe,
        Some(auth_revoked),
        Some(has_liquidity),
        Some(liquidity_sol),
        Some(liquidity_locked),
        Some(verified),
        Some(decimals),
        reason,
    ))
}

// Create transaction with comprehensive validation and error handling
let token_account_exists = match client.get_account(&token_account).await {
    Ok(_) => true,
    Err(_) => {
        debug!("Token account {} not found, creating...", token_account);
        false
    }
};

// Check if WSOL account exists with robust error handling
let wsol_account_exists = match client.get_account(&wsol_account).await {
    Ok(_) => true,
    Err(_) => {
        debug!("WSOL account {} not found, creating...", wsol_account);
        false
    }
};

// Create token account if needed with idempotent initialization
if !token_account_exists {
    debug!("Creating token account for {}", token_mint);
    let ix = create_associated_token_account_idempotent(
        &wallet_pubkey,
        &wallet_pubkey,
        &token_mint,
        &token_program,
    );
    instructions.push(ix);
}

// Create WSOL account if needed with idempotent initialization
if !wsol_account_exists {
    debug!("Creating WSOL account");
    let ix = create_associated_token_account_idempotent(
        &wallet_pubkey,
        &wallet_pubkey,
        &wsol_mint,
        &token_program,
    );
    instructions.push(ix);
}

// Parse all required Raydium and Serum account pubkeys with validation
// CRITICAL: All of these accounts must be valid and exist on-chain
let amm_id = Pubkey::from_str(&token_pair.amm_id)
    .map_err(|e| PyValueError::new_err(format!("Invalid AMM ID: {}", e)))?;
let amm_authority = Pubkey::from_str(&token_pair.amm_authority)
    .map_err(|e| PyValueError::new_err(format!("Invalid AMM authority: {}", e)))?;
let amm_open_orders = Pubkey::from_str(&token_pair.amm_open_orders)
    .map_err(|e| PyValueError::new_err(format!("Invalid AMM open orders: {}", e)))?;
let amm_target = Pubkey::from_str(&token_pair.amm_target)
    .map_err(|e| PyValueError::new_err(format!("Invalid AMM target: {}", e)))?;
let pool_token_account = Pubkey::from_str(&token_pair.pool_token_account)
    .map_err(|e| PyValueError::new_err(format!("Invalid pool token account: {}", e)))?;
let pool_pc_account = Pubkey::from_str(&token_pair.pool_pc_account)
    .map_err(|e| PyValueError::new_err(format!("Invalid pool PC account: {}", e)))?;

// Parse Serum/OpenBook accounts with comprehensive validation
let serum_program = Pubkey::from_str(&token_pair.serum_program_id)
    .map_err(|e| PyValueError::new_err(format!("Invalid Serum program ID: {}", e)))?;
let serum_market = Pubkey::from_str(&token_pair.serum_market)
    .map_err(|e| PyValueError::new_err(format!("Invalid Serum market: {}", e)))?;
let serum_bids = Pubkey::from_str(&token_pair.serum_bids)
    .map_err(|e| PyValueError::new_err(format!("Invalid Serum bids: {}", e)))?;
let serum_asks = Pubkey::from_str(&token_pair.serum_asks)
    .map_err(|e| PyValueError::new_err(format!("Invalid Serum asks: {}", e)))?;
let serum_event_queue = Pubkey::from_str(&token_pair.serum_event_queue)
    .map_err(|e| PyValueError::new_err(format!("Invalid Serum event queue: {}", e)))?;
let serum_coin_vault = Pubkey::from_str(&token_pair.serum_coin_vault)
    .map_err(|e| PyValueError::new_err(format!("Invalid Serum coin vault: {}", e)))?;
let serum_pc_vault = Pubkey::from_str(&token_pair.serum_pc_vault)
    .map_err(|e| PyValueError::new_err(format!("Invalid Serum PC vault: {}", e)))?;
let serum_vault_signer = Pubkey::from_str(&token_pair.serum_vault_signer)
    .map_err(|e| PyValueError::new_err(format!("Invalid Serum vault signer: {}", e)))?;

// Debug log the instruction data for transaction tracing
debug!("Swap instruction data: {:?}", instruction_data);

// Extract the swap amount for validation and logging
let mut amount_bytes = [0u8; 8];
if instruction_data.len() >= 9 {
    amount_bytes.copy_from_slice(&instruction_data[1..9]);
    let amount = u64::from_le_bytes(amount_bytes);
    debug!("Swap amount (lamports): {}", amount);
}

// Create swap instruction with all 18 required accounts in correct order
// CRITICAL: This matches the exact account structure in successful Raydium V4 AMM transactions
// The order and writability flags must be precisely as follows:
let swap_accounts = vec![
    AccountMeta::new_readonly(token_program, false), // 1. Token Program (readonly)
    AccountMeta::new(amm_id, false),                 // 2. AMM ID (Market) (writable)
    AccountMeta::new_readonly(amm_authority, false), // 3. AMM Authority (readonly)
    AccountMeta::new(amm_open_orders, false),        // 4. AMM Open Orders (writable)
    AccountMeta::new(amm_target, false),             // 5. AMM Target (writable)
    AccountMeta::new(pool_token_account, false),     // 6. Pool Coin Account (writable)
    AccountMeta::new(pool_pc_account, false),        // 7. Pool PC Account (writable)
    AccountMeta::new_readonly(serum_program, false), // 8. Serum Program (readonly)
    AccountMeta::new(serum_market, false),           // 9. Serum Market (writable)
    AccountMeta::new(serum_bids, false),             // 10. Serum Bids (writable)
    AccountMeta::new(serum_asks, false),             // 11. Serum Asks (writable)
    AccountMeta::new(serum_event_queue, false),      // 12. Serum Event Queue (writable)
    AccountMeta::new(serum_coin_vault, false),       // 13. Serum Coin Vault (writable)
    AccountMeta::new(serum_pc_vault, false),         // 14. Serum PC Vault (writable)
    AccountMeta::new_readonly(serum_vault_signer, false), // 15. Serum Vault Signer (readonly)
    AccountMeta::new(wsol_account, false),           // 16. User Source Token (writable)
    AccountMeta::new(token_account, false),          // 17. User Dest Token (writable)
    AccountMeta::new(wallet_pubkey, true),           // 18. User Source Owner (signer, writable)
];

// Construct the swap instruction with validated accounts and data
let swap_ix = Instruction {
    program_id: raydium_program,
    accounts: swap_accounts,
    data: instruction_data.clone(),
};

// Add the swap instruction to our transaction
instructions.push(swap_ix);

// Create transaction with all required instructions
let mut transaction = Transaction::new_with_payer(&instructions, Some(&wallet_pubkey));

// Get recent blockhash with proper error handling
let blockhash = client
    .get_latest_blockhash()
    .await
    .map_err(|e| PyValueError::new_err(format!("Failed to get recent blockhash: {}", e)))?;

// Sign transaction with wallet keypair
transaction.sign(&[&*keypair], blockhash);

// Optionally perform transaction simulation for pre-flight validation
debug!("Simulating transaction to check for errors");
let sim_config = RpcSimulateTransactionConfig {
    sig_verify: false,
    replace_recent_blockhash: true,
    commitment: Some(CommitmentConfig::confirmed()),
    encoding: None,
    accounts: None,
    min_context_slot: None,
    inner_instructions: Some(true),
};

// Enhanced simulation error handling and analysis
match client
    .simulate_transaction_with_config(&transaction, sim_config)
    .await
{
    Ok(sim_result) => {
        if let Some(err) = sim_result.value.err {
            debug!("Simulation failed: {:?}", err);
            
            // Detailed error analysis for common Raydium swap failures
            match err {
                solana_client::client_error::TransactionError::InstructionError(_, _) => {
                    debug!("Instruction error - likely an issue with the swap parameters or accounts");
                }
                solana_client::client_error::TransactionError::AccountNotFound => {
                    debug!("Account not found - one of the required accounts doesn't exist");
                }
                solana_client::client_error::TransactionError::AccountInUse => {
                    debug!("Account in use - possible account locking conflict");
                }
                solana_client::client_error::TransactionError::InsufficientFundsForRent => {
                    debug!("Insufficient funds for rent - make sure you have enough SOL");
                }
                solana_client::client_error::TransactionError::InsufficientFundsForFee => {
                    debug!("Insufficient funds for fee - make sure you have enough SOL");
                }
                _ => {
                    debug!("Other transaction error: {:?}", err);
                }
            }
            
            // Log detailed simulation logs if available for debugging
            if let Some(logs) = &sim_result.value.logs {
                debug!("Simulation logs:");
                for (i, log) in logs.iter().enumerate() {
                    if log.contains("Program log: Error:") || log.contains("failed:") {
                        debug!("  Error [{}]: {}", i, log);
                    } else if log.contains("Program log: Instruction: Swap") {
                        debug!("  Swap instruction found at log [{}]", i);
                    }
                }
            }
        } else {
            debug!("Simulation successful");
            if let Some(units) = sim_result.value.units_consumed {
                debug!("Estimated compute units: {}", units);
            }
        }
    }
    Err(e) => {
        debug!("Simulation error: {}", e);
        // Continue anyway - simulation failure doesn't prevent sending
    }
}

// Send transaction with optimized options for Raydium AMM transactions
let send_options = RpcSendTransactionConfig {
    skip_preflight: true,  // Skip preflight since we already simulated
    preflight_commitment: Some(CommitmentLevel::Confirmed),
    encoding: None,
    max_retries: Some(3),  // Retry up to 3 times for network congestion
    min_context_slot: None,
};

debug!("Sending transaction");

// Multi-attempt transaction submission with exponential backoff
let mut attempts = 0;
let max_attempts = 3;
let mut last_error = None;

while attempts < max_attempts {
    match client
        .send_transaction_with_config(&transaction, send_options.clone())
        .await
    {
        Ok(signature) => {
            debug!("Transaction sent successfully: {}", signature);
            return Ok(signature.to_string());
        }
        Err(e) => {
            attempts += 1;
            last_error = Some(e.to_string());
            
            // Enhanced error categorization for client-friendly messages
            if e.to_string().contains("blockhash not found") {
                debug!("Blockhash expired (network congestion): {}", e);
                
                // Get a new blockhash and retry with updated transaction
                if attempts < max_attempts {
                    match client.get_latest_blockhash().await {
                        Ok(new_blockhash) => {
                            transaction.message.recent_blockhash = new_blockhash;
                            // Re-sign with new blockhash
                            transaction.signatures.clear();
                            transaction.sign(&[&*keypair], new_blockhash);
                            debug!("Updated transaction with new blockhash: {}", new_blockhash);
                        }
                        Err(e) => {
                            debug!("Failed to get new blockhash: {}", e);
                        }
                    }
                }
            } else if e.to_string().contains("insufficient funds") {
                debug!("Insufficient funds for transaction: {}", e);
                // No point retrying insufficent funds errors
                break;
            } else {
                debug!("Transaction failed (attempt {}/{}): {}", attempts, max_attempts, e);
            }
            
            if attempts < max_attempts {
                // Exponential backoff to handle network congestion
                let backoff_ms = 500 * (1 << attempts);
                debug!("Retrying in {}ms...", backoff_ms);
                tokio::time::sleep(tokio::time::Duration::from_millis(backoff_ms)).await;
            }
        }
    }
}

// If we reach here, all attempts failed
Err(PyValueError::new_err(format!(
    "Failed to send transaction after {} attempts: {}",
    max_attempts,
    last_error.unwrap_or_else(|| "Unknown error".to_string())
)))
}

// Module configuration with comprehensive registration of all components
#[pymodule]
fn solana_rust_bot(_py: Python, m: &PyModule) -> PyResult<()> {
// Initialize logging for diagnostics and tracing
pyo3_log::init();

// Register all classes and error types
m.add_class::<TradingConfig>()?;
m.add_class::<TokenPairSetting>()?;
m.add_class::<SwapParams>()?;
m.add_class::<TransactionStatus>()?;
m.add_class::<TokenSafetyCheck>()?;
m.add_class::<RaydiumTradingCore>()?;

// Register constants and version information
m.add("VERSION", "1.0.0")?;
m.add("RAYDIUM_SWAP_INSTRUCTION", RAYDIUM_SWAP_INSTRUCTION)?;
m.add("COMPUTE_UNITS", COMPUTE_UNITS)?;
m.add("PRIORITY_FEE", PRIORITY_FEE)?;
m.add("LAMPORTS_PER_SOL", LAMPORTS_PER_SOL)?;

// Register custom error types for granular error handling
m.add("ERR_INVALID_INSTRUCTION", 0x1001)?;
m.add("ERR_INVALID_TOKEN_MINT", 0x1002)?;
m.add("ERR_INSUFFICIENT_FUNDS", 0x1003)?;
m.add("ERR_TRANSACTION_FAILED", 0x1004)?;
m.add("ERR_ACCOUNT_NOT_FOUND", 0x1005)?;
m.add("ERR_RATE_LIMIT_EXCEEDED", 0x1006)?;
m.add("ERR_TOKEN_SAFETY_CHECK_FAILED", 0x1007)?;

// Register utility functions for Python access
m.add_function(wrap_pyfunction!(create_instruction_data, m)?)?;

Ok(())
}

// Utility function for creating instruction data from Python
#[pyfunction]
fn create_instruction_data(swap_type: u8, amount_in: f64, min_amount_out: Option<f64>) -> PyResult<Vec<u8>> {
// Validate swap type - only support Raydium V4 AMM (0x09)
if swap_type != RAYDIUM_SWAP_INSTRUCTION {
    return Err(PyValueError::new_err(format!(
        "Invalid swap type: 0x{:02x}. Only Raydium V4 AMM (0x09) is supported",
        swap_type
    )));
}

// Convert SOL to lamports with proper precision handling
let amount_in_lamports = (amount_in * LAMPORTS_PER_SOL as f64) as u64;

// Convert minimum amount out with proper precision handling
let min_out_lamports = min_amount_out
    .map(|min| (min * LAMPORTS_PER_SOL as f64) as u64)
    .unwrap_or(0);

// Create instruction data buffer with exact capacity
let mut instruction_data = Vec::with_capacity(17);

// Add instruction discriminator (0x09 for Raydium V4 AMM)
instruction_data.push(swap_type);

// Add amount_in bytes in little-endian format
instruction_data.extend_from_slice(&amount_in_lamports.to_le_bytes());

// Add minimum_amount_out in little-endian format
instruction_data.extend_from_slice(&min_out_lamports.to_le_bytes());

Ok(instruction_data)
} fix the spacign please thank you