fix the order of this script i accidently scrambled it up use log::{debug, info};
use pyo3::exceptions::PyValueError;
use pyo3::prelude::*;
use pyo3_log;

use base58::FromBase58;
use serde::{Deserialize, Serialize};

use solana_client::nonblocking::rpc_client::RpcClient;
use solana_client::rpc_config::RpcSendTransactionConfig;
use solana_sdk::{
    commitment_config::{CommitmentConfig, CommitmentLevel},
    compute_budget::ComputeBudgetInstruction,
    instruction::{AccountMeta, Instruction},
    pubkey::Pubkey,
    signature::{Keypair, Signer},
    system_instruction,
    transaction::Transaction,
};
use spl_associated_token_account::{
    get_associated_token_address, instruction::create_associated_token_account_idempotent,
};
use spl_token::instruction as token_instruction;

use std::collections::HashMap;
use std::env;
use std::fs;
use std::path::Path;
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::time::sleep;

// Constants
const COMPUTE_UNITS: u32 = 50_000;
const PRIORITY_FEE: u64 = 750_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 RETRY_DELAY_MS: u64 = 100;

// Rate limiter for RPC calls
struct RateLimiter {
    call_count: AtomicU64,
    last_reset: AtomicU64,
    limit_per_second: 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: 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);
    }
}

// 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 compute_limit: u32,
    #[pyo3(get, set)]
    pub priority_fee: u64,
    #[pyo3(get, set)]
    pub skip_preflight: bool,
    #[pyo3(get, set)]
    pub max_retries: u8,

    #[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,

    #[pyo3(get, set)]
    pub min_sol_balance: f64,
    #[pyo3(get, set)]
    pub min_wsol_balance: f64,

    #[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,

    // For storing token pair specific settings
    #[pyo3(get)]
    pub token_pair_settings: HashMap<String, 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,
    #[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,
}

#[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,
        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>,
    ) -> Self {
        Self {
            token_mint,
            amm_id,
            amm_authority,
            amm_open_orders,
            amm_target,
            pool_token_account,
            pool_pc_account,
            min_liquidity_pct: min_liquidity_pct.unwrap_or(95.0),
            min_exit_liquidity_sol: min_exit_liquidity_sol.unwrap_or(5.0),
            auth_revoked: auth_revoked.unwrap_or(true),
            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),
        }
    }
}

#[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>,
    ) -> Self {
        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(|| env::var("API_KEY").unwrap_or_else(|_| "".to_string())),
            sol_mint: sol_mint.unwrap_or_else(|| {
                env::var("SOL_MINT")
                    .unwrap_or_else(|_| "So11111111111111111111111111111111111111112".to_string())
            }),
            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)
            }),
            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.35))
                    .unwrap_or(0.35)
            }),
            min_victim_size: min_victim_size.unwrap_or_else(|| {
                env::var("MIN_VICTIM_SIZE")
                    .map(|v| v.parse().unwrap_or(5.0))
                    .unwrap_or(5.0)
            }),
            max_victim_size: max_victim_size.unwrap_or_else(|| {
                env::var("MAX_VICTIM_SIZE")
                    .map(|v| v.parse().unwrap_or(320.0))
                    .unwrap_or(320.0)
            }),
            min_profit: min_profit.unwrap_or_else(|| {
                env::var("MIN_PROFIT")
                    .map(|v| v.parse().unwrap_or(0.002))
                    .unwrap_or(0.002)
            }),
            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.03))
                    .unwrap_or(0.03)
            }),
            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)
            }),
            raydium_program_id: raydium_program_id.unwrap_or_else(|| {
                env::var("RAYDIUM_PROGRAM_ID")
                    .unwrap_or_else(|_| "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8".to_string())
            }),
            token_program_id: token_program_id.unwrap_or_else(|| {
                env::var("TOKEN_PROGRAM_ID")
                    .unwrap_or_else(|_| "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA".to_string())
            }),
            system_program_id: system_program_id.unwrap_or_else(|| {
                env::var("SYSTEM_PROGRAM_ID")
                    .unwrap_or_else(|_| "11111111111111111111111111111111".to_string())
            }),
            associated_token_program_id: associated_token_program_id.unwrap_or_else(|| {
                env::var("ASSOCIATED_TOKEN_PROGRAM_ID")
                    .unwrap_or_else(|_| "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL".to_string())
            }),
            token_pair_settings: HashMap::new(),
        }
    }

    // Add a token pair setting
    fn add_token_pair_setting(&mut self, token_pair: TokenPairSetting) -> PyResult<()> {
        // Use token mint as key
        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,
        ))
    }
}

// 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,
}

#[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>,
    ) -> 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),
        }
    }
}

// Structure for transaction status tracking
#[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,
}

#[pymethods]
impl TransactionStatus {
    #[new]
    fn new(
        signature: String,
        success: bool,
        error: Option<String>,
        timestamp: Option<u64>,
        simulation_only: Option<bool>,
    ) -> 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),
        }
    }
}

// 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>, // Changed from AtomicBool to Arc<AtomicBool>
    last_trade_time: Arc<AtomicU64>,      // Changed from AtomicU64 to Arc<AtomicU64>
    public_key: String,
}

// Create swap instruction for Raydium
fn create_raydium_swap_instruction(
    raydium_program_id: &Pubkey,
    user_source_token: &Pubkey,
    user_destination_token: &Pubkey,
    _amm_id: &Pubkey,
    amm_authority: &Pubkey,
    amm_open_orders: &Pubkey,
    amm_target: &Pubkey,
    pool_token_account: &Pubkey,
    pool_pc_account: &Pubkey,
    amount: u64,
    is_buy: bool,
    wallet_pubkey: &Pubkey, // Add wallet pubkey as parameter
) -> Instruction {
    // Use instruction code 9 (0x09) for Raydium swap
    let mut data = vec![0x09];

    // Append amount as little-endian u64
    data.extend_from_slice(&amount.to_le_bytes());

    // Append minimum amount out (0 for simplicity) as little-endian u64
    let min_amount_out: u64 = 0;
    data.extend_from_slice(&min_amount_out.to_le_bytes());

    // Append swap direction (1 for buy, 0 for sell) as a single byte
    data.push(if is_buy { 1 } else { 0 });

    // Create account metas in the correct order
    let account_metas = vec![
        AccountMeta::new_readonly(*raydium_program_id, false),
        AccountMeta::new_readonly(*amm_authority, false),
        AccountMeta::new(*amm_open_orders, false),
        AccountMeta::new(*amm_target, false),
        AccountMeta::new(*pool_token_account, false),
        AccountMeta::new(*pool_pc_account, false),
        AccountMeta::new(*user_source_token, false),
        AccountMeta::new(*user_destination_token, false),
        AccountMeta::new_readonly(*wallet_pubkey, true), // Use actual wallet pubkey as signer
        AccountMeta::new_readonly(spl_token::id(), false),
    ];

    Instruction {
        program_id: *raydium_program_id,
        accounts: account_metas,
        data,
    }
}

// Python-exposed methods
#[pymethods]
impl RaydiumTradingCore {
    #[new]
    fn new(
        rpc_url: Option<String>,
        private_key: Option<String>,
        keypair_path: Option<String>,
        config: Option<TradingConfig>,
    ) -> PyResult<Self> {
        // Use provided config or create default
        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,
            )
        });

        // Create RPC client
        let rpc_url = rpc_url.unwrap_or_else(|| config_obj.rpc_url.clone());

        let client = Arc::new(RpcClient::new_with_commitment(
            rpc_url,
            CommitmentConfig::confirmed(),
        ));

        // Load keypair
        let keypair = if let Some(pk) = private_key {
            // Load from base58 string
            let bytes = pk
                .from_base58()
                .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 {
            // Load from file
            if !Path::new(&path).exists() {
                return Err(PyValueError::new_err(format!(
                    "Keypair file not found: {}",
                    path
                )));
            }

            let keypair = if path.ends_with(".json") {
                let file_content = std::fs::read_to_string(&path).map_err(|e| {
                    PyValueError::new_err(format!("Failed to read keypair file: {}", e))
                })?;

                let bytes: Vec<u8> = serde_json::from_str(&file_content)
                    .map_err(|e| PyValueError::new_err(format!("Invalid JSON keypair: {}", e)))?;

                Keypair::from_bytes(&bytes)
                    .map_err(|e| PyValueError::new_err(format!("Invalid keypair: {}", e)))?
            } else {
                let bytes = std::fs::read(&path).map_err(|e| {
                    PyValueError::new_err(format!("Failed to read keypair file: {}", e))
                })?;

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

            keypair
        } else {
            // Try from environment
            let private_key = env::var("SOLANA_PRIVATE_KEY").map_err(|_| {
                PyValueError::new_err("SOLANA_PRIVATE_KEY not found in environment")
            })?;

            let secret_key_bytes = private_key.from_base58().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();

        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)), // Update initialization
            last_trade_time: Arc::new(AtomicU64::new(0)),          // Update initialization
            public_key,
        })
    }

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

    // Static method to get common keypair paths
    #[staticmethod]
    fn get_keypair_paths() -> Vec<String> {
        vec![
            "keypair.bin".to_string(),
            "id.json".to_string(),
            "../id.json".to_string(),
            "wallet.json".to_string(),
            "wallet.bin".to_string(),
            format!(
                "{}/.config/solana/id.json",
                env::var("HOME").unwrap_or_else(|_| ".".to_string())
            ),
            format!(
                "{}/.config/solana/wallet.json",
                env::var("HOME").unwrap_or_else(|_| ".".to_string())
            ),
        ]
    }

    // Update configuration
    fn update_config(&self, config: TradingConfig) -> PyResult<()> {
        // Update rate limiter
        self.rate_limiter.set_limit(config.rpc_rate_limit);

        // Update config
        match self.config.write() {
            Ok(mut current_config) => {
                *current_config = config;
                Ok(())
            }
            Err(_) => Err(PyValueError::new_err(
                "Failed to update config - lock error",
            )),
        }
    }

    // Get SOL and token balances - Fixed for the lifetime issue
    fn get_balances<'py>(
        &self,
        py: Python<'py>,
        token_mints: Option<Vec<String>>,
    ) -> PyResult<&'py PyAny> {
        // Create strong clones of all needed fields
        let client = self.client.clone();
        let keypair_pubkey = self.keypair.pubkey();
        let balances_arc = self.balances.clone();
        let rate_limiter = self.rate_limiter.clone();

        // Extract SOL mint from config
        let sol_mint_str = match self.config.read() {
            Ok(config) => config.sol_mint.clone(),
            Err(_) => return Err(PyValueError::new_err("Failed to read config")),
        };

        // Convert to owned values
        let token_mints_owned = token_mints.unwrap_or_else(|| vec![]);

        pyo3_asyncio::tokio::future_into_py(py, async move {
            // Check rate limit
            if !rate_limiter.check_and_increment() {
                return Err(PyValueError::new_err("RPC rate limit exceeded"));
            }

            // Get SOL balance
            let sol_balance = match client.get_balance(&keypair_pubkey).await {
                Ok(balance) => balance,
                Err(e) => {
                    return Err(PyValueError::new_err(format!(
                        "Failed to get SOL balance: {}",
                        e
                    )))
                }
            }
        })
    }

    // Execute front-run and back-run trade sequence - Fixed for the lifetime issue
    fn execute_front_run_trade<'py>(
        &self,
        py: Python<'py>,
        token_mint: String,
        amount: f64,
        slippage_bps: Option<u16>,
    ) -> 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(); // Clone the Arc instead of referencing &self

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

        // Clone parameters for async block
        let token_mint_clone = token_mint.clone();
        let slippage = slippage_bps.unwrap_or(1000);

        pyo3_asyncio::tokio::future_into_py(py, async move {
            // 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"));
                }
            };

            // Create buy params
            let buy_params = SwapParams {
                token_mint: token_mint_clone.clone(),
                amount_in: amount,
                is_buy: true,
                slippage_bps: slippage,
                compute_limit: config.compute_limit,
                priority_fee: config.priority_fee,
            };

            // Execute buy transaction
            let buy_result =
                execute_swap_internal(&client, &keypair, &config, &rate_limiter, &buy_params).await;

            // Check if buy was successful
            match buy_result {
                Ok(status) => {
                    if !status.success {
                        pending_transaction.store(false, Ordering::Relaxed);
                        return Ok(status);
                    }

                    // Wait for the victim transaction (small delay)
                    sleep(Duration::from_millis(500)).await;

                    // Create sell params (sell all tokens)
                    let sell_params = SwapParams {
                        token_mint: token_mint_clone,
                        amount_in: 0.0, // Sell all tokens
                        is_buy: false,
                        slippage_bps: slippage,
                        compute_limit: config.compute_limit,
                        priority_fee: config.priority_fee,
                    };

                    // Execute sell transaction
                    let sell_result = execute_swap_internal(
                        &client,
                        &keypair,
                        &config,
                        &rate_limiter,
                        &sell_params,
                    )
                    .await;

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

                    // Return sell result
                    match sell_result {
                        Ok(sell_status) => Ok(sell_status),
                        Err(e) => {
                            // Create a failed status
                            let failed_status = TransactionStatus::new(
                                "sell_failed".to_string(),
                                false,
                                Some(format!("Buy succeeded but sell failed: {}", e)),
                                None,
                                None,
                            );
                            Ok(failed_status)
                        }
                    }
                }
                Err(e) => {
                    // Reset pending transaction flag
                    pending_transaction.store(false, Ordering::Relaxed);

                    // Return the error
                    Err(e)
                }
            }
        })
    }

    // Get the market state for a token pair - Fixed for the lifetime issue
    fn get_market_state<'py>(&self, py: Python<'py>, token_mint: String) -> PyResult<&'py PyAny> {
        let client = self.client.clone();
        let config_arc = self.config.clone();
        let rate_limiter = self.rate_limiter.clone();
        let token_mint_clone = token_mint.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")),
            };

            // Get the token pair settings
            let token_pair = match config.token_pair_settings.get(&token_mint_clone) {
                Some(settings) => settings.clone(),
                None => {
                    return Err(PyValueError::new_err(format!(
                        "Token pair settings not found for {}",
                        token_mint_clone
                    )))
                }
            };

            // Parse pubkeys
            let pool_token_account = match Pubkey::from_str(&token_pair.pool_token_account) {
                Ok(pubkey) => pubkey,
                Err(e) => {
                    return Err(PyValueError::new_err(format!(
                        "Invalid pool token account: {}",
                        e
                    )))
                }
            };

            let pool_pc_account = match Pubkey::from_str(&token_pair.pool_pc_account) {
                Ok(pubkey) => pubkey,
                Err(e) => {
                    return Err(PyValueError::new_err(format!(
                        "Invalid pool PC account: {}",
                        e
                    )))
                }
            };

            // Check rate limit
            if !rate_limiter.check_and_increment() {
                return Err(PyValueError::new_err("RPC rate limit exceeded"));
            }

            // Get pool token account balance
            let token_pool_balance =
                match client.get_token_account_balance(&pool_token_account).await {
                    Ok(balance) => match balance.amount.parse::<u64>() {
                        Ok(amount) => amount,
                        Err(_) => 0,
                    },
                    Err(e) => {
                        return Err(PyValueError::new_err(format!(
                            "Failed to get pool token balance: {}",
                            e
                        )))
                    }
                };

            // Check rate limit
            if !rate_limiter.check_and_increment() {
                return Err(PyValueError::new_err("RPC rate limit exceeded"));
            }

            // Get pool SOL account balance
            let sol_pool_balance = match client.get_token_account_balance(&pool_pc_account).await {
                Ok(balance) => match balance.amount.parse::<u64>() {
                    Ok(amount) => amount,
                    Err(_) => 0,
                },
                Err(e) => {
                    return Err(PyValueError::new_err(format!(
                        "Failed to get pool SOL balance: {}",
                        e
                    )))
                }
            };

            // Calculate liquidity percentage
            let token_pool_balance_f64 = token_pool_balance as f64;
            let sol_pool_balance_f64 = sol_pool_balance as f64 / LAMPORTS_PER_SOL as f64;

            // Return as HashMap
            let mut result = HashMap::new();
            result.insert("token_mint".to_string(), token_mint_clone);
            result.insert(
                "token_pool_balance".to_string(),
                token_pool_balance_f64.to_string(),
            );
            result.insert(
                "sol_pool_balance".to_string(),
                sol_pool_balance_f64.to_string(),
            );
            result.insert(
                "exit_liquidity".to_string(),
                sol_pool_balance_f64.to_string(),
            );

            Ok(result)
        })
    }
}

// Full corrected version of execute_swap_internal function
async fn execute_swap_internal(
    client: &RpcClient,
    keypair: &Arc<Keypair>,
    config: &TradingConfig,
    rate_limiter: &RateLimiter,
    params: &SwapParams,
) -> PyResult<TransactionStatus> {
    // Get the token pair settings
    let token_pair = match config.token_pair_settings.get(&params.token_mint) {
        Some(settings) => settings.clone(),
        None => {
            return Err(PyValueError::new_err(format!(
                "Token pair settings not found for {}",
                params.token_mint
            )))
        }
    };

    // Check if token is enabled
    if !token_pair.enabled {
        return Err(PyValueError::new_err(format!(
            "Token {} is disabled",
            params.token_mint
        )));
    }

    // Parse all the pubkeys
    let token_mint_pubkey = match Pubkey::from_str(&params.token_mint) {
        Ok(pubkey) => pubkey,
        Err(e) => return Err(PyValueError::new_err(format!("Invalid token mint: {}", e))),
    };

    let sol_mint_pubkey = match Pubkey::from_str(&config.sol_mint) {
        Ok(pubkey) => pubkey,
        Err(e) => return Err(PyValueError::new_err(format!("Invalid SOL mint: {}", e))),
    };

    let raydium_program_id = match Pubkey::from_str(&config.raydium_program_id) {
        Ok(pubkey) => pubkey,
        Err(e) => {
            return Err(PyValueError::new_err(format!(
                "Invalid Raydium program ID: {}",
                e
            )))
        }
    };

    let token_program_id = match Pubkey::from_str(&config.token_program_id) {
        Ok(pubkey) => pubkey,
        Err(e) => {
            return Err(PyValueError::new_err(format!(
                "Invalid token program ID: {}",
                e
            )))
        }
    };

    let amm_id = match Pubkey::from_str(&token_pair.amm_id) {
        Ok(pubkey) => pubkey,
        Err(e) => return Err(PyValueError::new_err(format!("Invalid AMM ID: {}", e))),
    };

    let amm_authority = match Pubkey::from_str(&token_pair.amm_authority) {
        Ok(pubkey) => pubkey,
        Err(e) => {
            return Err(PyValueError::new_err(format!(
                "Invalid AMM authority: {}",
                e
            )))
        }
    };

    let amm_open_orders = match Pubkey::from_str(&token_pair.amm_open_orders) {
        Ok(pubkey) => pubkey,
        Err(e) => {
            return Err(PyValueError::new_err(format!(
                "Invalid AMM open orders: {}",
                e
            )))
        }
    };

    let amm_target = match Pubkey::from_str(&token_pair.amm_target) {
        Ok(pubkey) => pubkey,
        Err(e) => return Err(PyValueError::new_err(format!("Invalid AMM target: {}", e))),
    };

    let pool_token_account = match Pubkey::from_str(&token_pair.pool_token_account) {
        Ok(pubkey) => pubkey,
        Err(e) => {
            return Err(PyValueError::new_err(format!(
                "Invalid pool token account: {}",
                e
            )))
        }
    };

    let pool_pc_account = match Pubkey::from_str(&token_pair.pool_pc_account) {
        Ok(pubkey) => pubkey,
        Err(e) => {
            return Err(PyValueError::new_err(format!(
                "Invalid pool PC account: {}",
                e
            )))
        }
    };

    // Get associated token accounts
    let user_wsol_ata = get_associated_token_address(&keypair.pubkey(), &sol_mint_pubkey);
    let user_token_ata = get_associated_token_address(&keypair.pubkey(), &token_mint_pubkey);

    // Prepare instructions for creating ATAs if needed
    let mut instructions = Vec::new();

    // Check if ATAs exist and add creation instructions if needed
    if !rate_limiter.check_and_increment() {
        return Err(PyValueError::new_err("RPC rate limit exceeded"));
    }

    let wsol_account_exists = client.get_account(&user_wsol_ata).await.is_ok();
    if !wsol_account_exists {
        let create_wsol_ata_ix = create_associated_token_account_idempotent(
            &keypair.pubkey(),
            &keypair.pubkey(),
            &sol_mint_pubkey,
            &token_program_id,
        );
        instructions.push(create_wsol_ata_ix);
    }

    if !rate_limiter.check_and_increment() {
        return Err(PyValueError::new_err("RPC rate limit exceeded"));
    }

    let token_account_exists = client.get_account(&user_token_ata).await.is_ok();
    if !token_account_exists {
        let create_token_ata_ix = create_associated_token_account_idempotent(
            &keypair.pubkey(),
            &keypair.pubkey(),
            &token_mint_pubkey,
            &token_program_id,
        );
        instructions.push(create_token_ata_ix);
    }

    // Convert amount to lamports
    let amount_lamports = (params.amount_in * LAMPORTS_PER_SOL as f64) as u64;

    // If buying and amount > 0, we need to wrap SOL first
    if params.is_buy && amount_lamports > 0 {
        // Transfer SOL to WSOL ATA
        let transfer_ix =
            system_instruction::transfer(&keypair.pubkey(), &user_wsol_ata, amount_lamports);
        instructions.push(transfer_ix);

        // Synchronize WSOL
        let sync_ix = match token_instruction::sync_native(&token_program_id, &user_wsol_ata) {
            Ok(ix) => ix,
            Err(e) => {
                return Err(PyValueError::new_err(format!(
                    "Failed to create sync instruction: {}",
                    e
                )))
            }
        };
        instructions.push(sync_ix);
    }

    // For sells with amount_in == 0, we need to get current token balance
    let actual_amount = if !params.is_buy && params.amount_in == 0.0 {
        if !rate_limiter.check_and_increment() {
            return Err(PyValueError::new_err("RPC rate limit exceeded"));
        }

        match client.get_token_account_balance(&user_token_ata).await {
            Ok(balance) => match balance.amount.parse::<u64>() {
                Ok(amount) => amount,
                Err(_) => return Err(PyValueError::new_err("Failed to parse token balance")),
            },
            Err(e) => {
                return Err(PyValueError::new_err(format!(
                    "Failed to get token balance: {}",
                    e
                )))
            }
        }
    } else {
        amount_lamports
    };

    // Create the Raydium swap instruction
    let swap_instruction = create_raydium_swap_instruction(
        &raydium_program_id,
        if params.is_buy {
            &user_wsol_ata
        } else {
            &user_token_ata
        },
        if params.is_buy {
            &user_token_ata
        } else {
            &user_wsol_ata
        },
        &amm_id,
        &amm_authority,
        &amm_open_orders,
        &amm_target,
        &pool_token_account,
        &pool_pc_account,
        actual_amount,
        params.is_buy,
        &keypair.pubkey(), // Add wallet pubkey as the 12th parameter
    );

    instructions.push(swap_instruction);

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

    instructions.insert(0, priority_fee_ix);
    instructions.insert(0, compute_budget_ix);

    // Get recent blockhash
    if !rate_limiter.check_and_increment() {
        return Err(PyValueError::new_err("RPC rate limit exceeded"));
    }

    let blockhash = match client.get_latest_blockhash().await {
        Ok(blockhash) => blockhash,
        Err(e) => {
            return Err(PyValueError::new_err(format!(
                "Failed to get latest blockhash: {}",
                e
            )))
        }
    };

    // Create transaction
    let mut tx = Transaction::new_with_payer(&instructions, Some(&keypair.pubkey()));

    // Sign transaction - FIXED: Proper way to access Arc<Keypair>
    tx.sign(&[keypair.as_ref()], blockhash);

    // Send transaction
    if !rate_limiter.check_and_increment() {
        return Err(PyValueError::new_err("RPC rate limit exceeded"));
    }

    let result = client
        .send_transaction_with_config(
            &tx,
            RpcSendTransactionConfig {
                skip_preflight: config.skip_preflight,
                preflight_commitment: Some(CommitmentLevel::Processed),
                encoding: None,
                max_retries: Some(config.max_retries as usize),
                min_context_slot: None,
            },
        )
        .await;

    match result {
        Ok(signature) => {
            let status = TransactionStatus::new(
                signature.to_string(),
                true,
                None,
                Some(
                    SystemTime::now()
                        .duration_since(UNIX_EPOCH)
                        .unwrap()
                        .as_secs(),
                ),
                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(),
                ),
                None,
            );
            Ok(status)
        }
    }
}

// Module configuration
#[pymodule]
fn solana_rust_bot(_py: Python, m: &PyModule) -> PyResult<()> {
    pyo3_log::init();

    m.add_class::<TradingConfig>()?;
    m.add_class::<TokenPairSetting>()?;
    m.add_class::<SwapParams>()?;
    m.add_class::<TransactionStatus>()?;
    m.add_class::<RaydiumTradingCore>()?;

    Ok(())
};

            let sol_balance_f64 = sol_balance as f64 / LAMPORTS_PER_SOL as f64;

            // Get token balances
            let mut token_balances: HashMap<String, f64> = HashMap::new();

            for token_mint_str in token_mints_owned.iter() {
                // Parse token mint
                let token_mint = match Pubkey::from_str(token_mint_str) {
                    Ok(pubkey) => pubkey,
                    Err(e) => {
                        return Err(PyValueError::new_err(format!(
                            "Invalid token mint {}: {}",
                            token_mint_str, e
                        )))
                    }
                };

                // Get ATA
                let token_ata = get_associated_token_address(&keypair_pubkey, &token_mint);

                // Check rate limit before each RPC call
                if !rate_limiter.check_and_increment() {
                    return Err(PyValueError::new_err("RPC rate limit exceeded"));
                }

                // Get token balance
                let token_balance = match client.get_token_account_balance(&token_ata).await {
                    Ok(balance) => {
                        match balance.amount.parse::<u64>() {
                            Ok(amount) => {
                                // Get token decimals (usually 9 for most SPL tokens, 6 for USDC, etc.)
                                let decimals = balance
                                    .ui_amount_string
                                    .len()
                                    .saturating_sub(balance.amount.len() + 1);
                                let divisor = 10u64.pow(decimals as u32) as f64;
                                amount as f64 / divisor
                            }
                            Err(_) => 0.0,
                        }
                    }
                    Err(_) => 0.0, // ATA might not exist yet
                };

                token_balances.insert(token_mint_str.clone(), token_balance);
            }

            // Don't forget WSOL
            let wsol_pubkey = match Pubkey::from_str(&sol_mint_str) {
                Ok(pk) => pk,
                Err(e) => return Err(PyValueError::new_err(format!("Invalid WSOL pubkey: {}", e))),
            };

            let wsol_ata = get_associated_token_address(&keypair_pubkey, &wsol_pubkey);

            // Check rate limit before RPC call
            if !rate_limiter.check_and_increment() {
                return Err(PyValueError::new_err("RPC rate limit exceeded"));
            }

            // Get WSOL balance
            let wsol_balance = match client.get_token_account_balance(&wsol_ata).await {
                Ok(balance) => match balance.amount.parse::<u64>() {
                    Ok(amount) => amount as f64 / LAMPORTS_PER_SOL as f64,
                    Err(_) => 0.0,
                },
                Err(_) => 0.0, // ATA might not exist yet
            };

            token_balances.insert(sol_mint_str.clone(), wsol_balance);

            // Update stored balances
            if let Ok(mut balances) = balances_arc.write() {
                *balances = (sol_balance_f64, token_balances.clone());
            }

            // Return as tuple (SOL balance, token balances hashmap)
            Ok((sol_balance_f64, token_balances))
        })
    }

    // Create or ensure Associated Token Account exists - Fixed for the lifetime issue
    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 rate_limiter = self.rate_limiter.clone();
        let token_mint_clone = token_mint.clone();

        // Parse token mint
        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))),
        };

        // Extract program IDs from config
        let token_program_id_str = match self.config.read() {
            Ok(config) => config.token_program_id.clone(),
            Err(_) => return Err(PyValueError::new_err("Failed to read config")),
        };

        pyo3_asyncio::tokio::future_into_py(py, async move {
            // Parse program IDs
            let token_program = match Pubkey::from_str(&token_program_id_str) {
                Ok(pubkey) => pubkey,
                Err(e) => {
                    return Err(PyValueError::new_err(format!(
                        "Invalid token program ID: {}",
                        e
                    )))
                }
            };

            // Calculate ATA address
            let ata = get_associated_token_address(&keypair.pubkey(), &token_mint_pubkey);

            // Check if ATA already exists
            if !rate_limiter.check_and_increment() {
                return Err(PyValueError::new_err("RPC rate limit exceeded"));
            }

            match client.get_account(&ata).await {
                Ok(_) => {
                    // ATA already exists
                    debug!("ATA already exists for token {}: {}", token_mint_clone, ata);
                    return Ok(ata.to_string());
                }
                Err(_) => {
                    // Need to create ATA
                    info!("Creating ATA for token {}", token_mint_clone);

                    // Create instruction for ATA creation
                    let create_ata_ix = create_associated_token_account_idempotent(
                        &keypair.pubkey(),  // Funding address (payer)
                        &keypair.pubkey(),  // Wallet address
                        &token_mint_pubkey, // Token mint
                        &token_program,     // Token program
                    );

                    // Check rate limit before getting blockhash
                    if !rate_limiter.check_and_increment() {
                        return Err(PyValueError::new_err("RPC rate limit exceeded"));
                    }

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

                    // Create transaction
                    let mut tx =
                        Transaction::new_with_payer(&[create_ata_ix], Some(&keypair.pubkey()));

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

                    // Send transaction
                    if !rate_limiter.check_and_increment() {
                        return Err(PyValueError::new_err("RPC rate limit exceeded"));
                    }

                    match client
                        .send_transaction_with_config(
                            &tx,
                            RpcSendTransactionConfig {
                                skip_preflight: true,
                                preflight_commitment: Some(CommitmentLevel::Confirmed),
                                encoding: None,
                                max_retries: Some(3),
                                min_context_slot: None,
                            },
                        )
                        .await
                    {
                        Ok(sig) => {
                            info!(
                                "Created ATA for token {}: {} (tx: {})",
                                token_mint_clone, ata, sig
                            );
                            Ok(ata.to_string())
                        }
                        Err(e) => {
                            // Check if ATA exists now (could be created by another transaction)
                            if e.to_string().contains("already in use") {
                                Ok(ata.to_string())
                            } else {
                                Err(PyValueError::new_err(format!(
                                    "Failed to create ATA: {}",
                                    e
                                )))
                            }
                        }
                    }
                }
            }
        })
    }

    // Execute a Raydium swap transaction - Fixed for the lifetime issue
    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(); // Clone the Arc instead of referencing &self

        // 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 {
            // 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"));
                }
            };

            // Get the token pair settings
            let token_pair = match config.token_pair_settings.get(&params_clone.token_mint) {
                Some(settings) => settings.clone(),
                None => {
                    pending_transaction.store(false, Ordering::Relaxed);
                    return Err(PyValueError::new_err(format!(
                        "Token pair settings not found for {}",
                        params_clone.token_mint
                    )));
                }
            };

            // Check if token is enabled
            if !token_pair.enabled {
                pending_transaction.store(false, Ordering::Relaxed);
                return Err(PyValueError::new_err(format!(
                    "Token {} is disabled",
                    params_clone.token_mint
                )));
            }

            // Parse all the pubkeys
            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)));
                }
            };

            let sol_mint_pubkey = match Pubkey::from_str(&config.sol_mint) {
                Ok(pubkey) => pubkey,
                Err(e) => {
                    pending_transaction.store(false, Ordering::Relaxed);
                    return Err(PyValueError::new_err(format!("Invalid SOL mint: {}", e)));
                }
            };

            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
                    )));
                }
            };

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

            let amm_id = match Pubkey::from_str(&token_pair.amm_id) {
                Ok(pubkey) => pubkey,
                Err(e) => {
                    pending_transaction.store(false, Ordering::Relaxed);
                    return Err(PyValueError::new_err(format!("Invalid AMM ID: {}", e)));
                }
            };

            let amm_authority = match Pubkey::from_str(&token_pair.amm_authority) {
                Ok(pubkey) => pubkey,
                Err(e) => {
                    pending_transaction.store(false, Ordering::Relaxed);
                    return Err(PyValueError::new_err(format!(
                        "Invalid AMM authority: {}",
                        e
                    )));
                }
            };

            let amm_open_orders = match Pubkey::from_str(&token_pair.amm_open_orders) {
                Ok(pubkey) => pubkey,
                Err(e) => {
                    pending_transaction.store(false, Ordering::Relaxed);
                    return Err(PyValueError::new_err(format!(
                        "Invalid AMM open orders: {}",
                        e
                    )));
                }
            };

            let amm_target = match Pubkey::from_str(&token_pair.amm_target) {
                Ok(pubkey) => pubkey,
                Err(e) => {
                    pending_transaction.store(false, Ordering::Relaxed);
                    return Err(PyValueError::new_err(format!("Invalid AMM target: {}", e)));
                }
            };

            let pool_token_account = match Pubkey::from_str(&token_pair.pool_token_account) {
                Ok(pubkey) => pubkey,
                Err(e) => {
                    pending_transaction.store(false, Ordering::Relaxed);
                    return Err(PyValueError::new_err(format!(
                        "Invalid pool token account: {}",
                        e
                    )));
                }
            };

            let pool_pc_account = match Pubkey::from_str(&token_pair.pool_pc_account) {
                Ok(pubkey) => pubkey,
                Err(e) => {
                    pending_transaction.store(false, Ordering::Relaxed);
                    return Err(PyValueError::new_err(format!(
                        "Invalid pool PC account: {}",
                        e
                    )));
                }
            };

            // Get associated token accounts
            let user_wsol_ata = get_associated_token_address(&keypair.pubkey(), &sol_mint_pubkey);
            let user_token_ata =
                get_associated_token_address(&keypair.pubkey(), &token_mint_pubkey);

            // Prepare instructions for creating ATAs if needed
            let mut instructions = Vec::new();

            // Check if ATAs exist and add creation instructions if needed
            if !rate_limiter.check_and_increment() {
                pending_transaction.store(false, Ordering::Relaxed);
                return Err(PyValueError::new_err("RPC rate limit exceeded"));
            }

            let wsol_account_exists = client.get_account(&user_wsol_ata).await.is_ok();
            if !wsol_account_exists {
                let create_wsol_ata_ix = create_associated_token_account_idempotent(
                    &keypair.pubkey(),
                    &keypair.pubkey(),
                    &sol_mint_pubkey,
                    &token_program_id,
                );
                instructions.push(create_wsol_ata_ix);
            }

            if !rate_limiter.check_and_increment() {
                pending_transaction.store(false, Ordering::Relaxed);
                return Err(PyValueError::new_err("RPC rate limit exceeded"));
            }

            let token_account_exists = client.get_account(&user_token_ata).await.is_ok();
            if !token_account_exists {
                let create_token_ata_ix = create_associated_token_account_idempotent(
                    &keypair.pubkey(),
                    &keypair.pubkey(),
                    &token_mint_pubkey,
                    &token_program_id,
                );
                instructions.push(create_token_ata_ix);
            }

            // Convert amount to lamports
            let amount_lamports = (params_clone.amount_in * LAMPORTS_PER_SOL as f64) as u64;

            // If buying and amount > 0, we need to wrap SOL first
            if params_clone.is_buy && amount_lamports > 0 {
                // Transfer SOL to WSOL ATA
                let transfer_ix = system_instruction::transfer(
                    &keypair.pubkey(),
                    &user_wsol_ata,
                    amount_lamports,
                );
                instructions.push(transfer_ix);

                // Synchronize WSOL
                let sync_ix =
                    match token_instruction::sync_native(&token_program_id, &user_wsol_ata) {
                        Ok(ix) => ix,
                        Err(e) => {
                            pending_transaction.store(false, Ordering::Relaxed);
                            return Err(PyValueError::new_err(format!(
                                "Failed to create sync instruction: {}",
                                e
                            )));
                        }
                    };
                instructions.push(sync_ix);
            }

            // For sells with amount_in == 0, we need to get current token balance
            let actual_amount = if !params_clone.is_buy && params_clone.amount_in == 0.0 {
                if !rate_limiter.check_and_increment() {
                    pending_transaction.store(false, Ordering::Relaxed);
                    return Err(PyValueError::new_err("RPC rate limit exceeded"));
                }

                match client.get_token_account_balance(&user_token_ata).await {
                    Ok(balance) => match balance.amount.parse::<u64>() {
                        Ok(amount) => amount,
                        Err(_) => {
                            pending_transaction.store(false, Ordering::Relaxed);
                            return Err(PyValueError::new_err("Failed to parse token balance"));
                        }
                    },
                    Err(e) => {
                        pending_transaction.store(false, Ordering::Relaxed);
                        return Err(PyValueError::new_err(format!(
                            "Failed to get token balance: {}",
                            e
                        )));
                    }
                }
            } else {
                amount_lamports
            };

            // Create the Raydium swap instruction
            let swap_instruction = create_raydium_swap_instruction(
                &raydium_program_id,
                if params_clone.is_buy {
                    &user_wsol_ata
                } else {
                    &user_token_ata
                },
                if params_clone.is_buy {
                    &user_token_ata
                } else {
                    &user_wsol_ata
                },
                &amm_id,
                &amm_authority,
                &amm_open_orders,
                &amm_target,
                &pool_token_account,
                &pool_pc_account,
                actual_amount,
                params_clone.is_buy,
                &keypair.pubkey(), // Add wallet pubkey as the 12th parameter
            );

            instructions.push(swap_instruction);

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

            instructions.insert(0, priority_fee_ix);
            instructions.insert(0, compute_budget_ix);

            // Get recent blockhash
            if !rate_limiter.check_and_increment() {
                pending_transaction.store(false, Ordering::Relaxed);
                return Err(PyValueError::new_err("RPC rate limit exceeded"));
            }

            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 latest blockhash: {}",
                        e
                    )));
                }
            };

            // Create transaction
            let mut tx = Transaction::new_with_payer(&instructions, Some(&keypair.pubkey()));

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

            // Send transaction
            if !rate_limiter.check_and_increment() {
                pending_transaction.store(false, Ordering::Relaxed);
                return Err(PyValueError::new_err("RPC rate limit exceeded"));
            }

            let result = client
                .send_transaction_with_config(
                    &tx,
                    RpcSendTransactionConfig {
                        skip_preflight: config.skip_preflight,
                        preflight_commitment: Some(CommitmentLevel::Processed),
                        encoding: None,
                        max_retries: Some(config.max_retries as usize),
                        min_context_slot: None,
                    },
                )
                .await;

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

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