#[pymodule]
fn solana_rust_bot(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_class::<QuantumCore>()?;
    Ok(())
}

#[pyclass]
struct QuantumCore {
    // Your existing fields
}

#[pymethods]
impl QuantumCore {
    #[new]
    fn new(pool_id: String) -> Self {
        // Your existing new() implementation
    }

    // Add other methods with #[pymethods]      #![allow(non_snake_case)]
// Rest of your lib.rs content
use pyo3::prelude::*;
use {
    std::{sync::Arc, time::{Duration, Instant}, path::PathBuf, fs::create_dir_all},
    tokio::time::sleep,
    serde_json::{json, Value},
    anyhow::{anyhow, Result},
    log::{error, info, warn},
    dashmap::DashMap,
    solana_client::rpc_client::RpcClient,
    solana_sdk::{
        signature::Keypair,
        signer::Signer,
        commitment_config::CommitmentConfig,
    },
    tokio_tungstenite::{
        connect_async,
        WebSocketStream,
        MaybeTlsStream,
    },
    tokio::net::TcpStream,
};

// Constants
pub const JUPITER_V6_API: &str = "https://quote-api.jup.ag/v6";
pub const HELIUS_RPC: &str = "https://marga-e56m84-fast-mainnet.helius-rpc.com";
pub const WS_URL: &str = "wss://marga-e56m84-fast-mainnet.helius-rpc.com";
pub const SOL_MINT: &str = "So11111111111111111111111111111111111111112";
pub const PRIORITY_FEE: u64 = 15000;
pub const RETRY_ATTEMPTS: u32 = 3;
pub const RETRY_DELAY: Duration = Duration::from_millis(100);
pub const TRADE_AMOUNT_SOL: f64 = 0.01;
pub const MIN_LIQUIDITY_USD: f64 = 1000.0;
pub const MAX_LIQUIDITY_USD: f64 = 20000.0;
pub const SLIPPAGE_BPS: u32 = 1000; // 10%
pub const POLL_INTERVAL: Duration = Duration::from_secs(1);

type WebSocketConnection = WebSocketStream<MaybeTlsStream<TcpStream>>;

#[derive(Debug, Clone)]
struct ActiveTrade {
    token_mint: String,
    entry_price: f64,
    amount: u64,
    timestamp: i64,
    last_price: f64,
    take_profit: f64,
    stop_loss: f64,
    volume_24h: f64,
    liquidity: f64,
}

#[derive(Debug, Clone)]
struct TradeMetrics {
    total_trades: u64,
    successful_trades: u64,
    total_profit: f64,
    avg_execution_time: Duration,
}

pub struct TradeManager {
    rpc_client: Arc<RpcClient>,
    keypair: Arc<Keypair>,
    active_trades: Arc<DashMap<String, ActiveTrade>>,  // Make DashMap Arc
    trade_metrics: Arc<DashMap<String, TradeMetrics>>, // Make DashMap Arc
    ws_connection: Arc<tokio::sync::Mutex<Option<WebSocketConnection>>>,
    http_client: Arc<reqwest::Client>, // Make client Arc
}

impl Clone for TradeManager {
    fn clone(&self) -> Self {
        Self {
            rpc_client: self.rpc_client.clone(),
            keypair: self.keypair.clone(),
            active_trades: self.active_trades.clone(),
            trade_metrics: self.trade_metrics.clone(),
            ws_connection: self.ws_connection.clone(),
            http_client: self.http_client.clone(),
        }
    }
}

impl TradeManager {
    pub fn new(keypair: Keypair) -> Self {
        let rpc_client = RpcClient::new_with_commitment(
            HELIUS_RPC.to_string(),
            CommitmentConfig::confirmed(),
        );

        Self {
            rpc_client: Arc::new(rpc_client),
            keypair: Arc::new(keypair),
            active_trades: Arc::new(DashMap::new()),
            trade_metrics: Arc::new(DashMap::new()),
            ws_connection: Arc::new(tokio::sync::Mutex::new(None)),
            http_client: Arc::new(reqwest::Client::new()),
        }
    }

    // Add this method to get data directory
    fn get_data_dir() -> PathBuf {
        let mut path = std::env::current_dir()
            .expect("Failed to get current directory")
            .join("data");
        
        // Create data directory if it doesn't exist
        if !path.exists() {
            create_dir_all(&path)
                .expect("Failed to create data directory");
        }
        
        path
    }

    // Add this method to get state file path
    fn get_state_file_path() -> PathBuf {
        Self::get_data_dir().join("trade_state.json")
    }

    pub async fn start(&self) -> Result<()> {
        info!("🚀 Starting trading system");
        self.log_paths(); // Log paths on startup
        
        // Ensure data directory exists
        let data_dir = Self::get_data_dir();
        if !data_dir.exists() {
            tokio::fs::create_dir_all(&data_dir)
                .await
                .map_err(|e| anyhow!("Failed to create data directory: {}", e))?;
        }

        // Initialize state file if it doesn't exist
        let state_path = Self::get_state_file_path();
        if !state_path.exists() {
            info!("Initializing new trade state file");
            self.save_state().await?;
        }
        
        // Load previous state with proper error handling
        match self.load_state().await {
            Ok(()) => info!("Successfully loaded previous state"),
            Err(e) => {
                warn!("Could not load previous state: {}. Starting fresh.", e);
                // Initialize empty state
                self.save_state().await?;
            }
        }
        
        // Report active trades
        if self.active_trades.is_empty() {
            info!("No active trades");
        } else {
            for trade in self.active_trades.iter() {
                info!(
                    "📊 Active trade: {} | Entry: ${:.6} | Current: ${:.6}",
                    trade.key(),
                    trade.value().entry_price,
                    trade.value().last_price
                );
            }
        }
    
        // Start monitoring in separate task
        let trade_manager = Self {
            rpc_client: self.rpc_client.clone(),
            keypair: self.keypair.clone(),
            active_trades: self.active_trades.clone(),
            trade_metrics: self.trade_metrics.clone(),
            ws_connection: self.ws_connection.clone(),
            http_client: self.http_client.clone(),
        };
    
        tokio::spawn(async move {
            if let Err(e) = trade_manager.monitor_trades().await {
                error!("Trade monitoring error: {}", e);
            }
        });
    
        Ok(())
    }

    fn log_paths(&self) {
        let current_dir = std::env::current_dir()
            .unwrap_or_else(|_| PathBuf::from("unknown"));
        let data_dir = Self::get_data_dir();
        let state_path = Self::get_state_file_path();

        info!("📂 Current directory: {:?}", current_dir);
        info!("📂 Data directory: {:?}", data_dir);
        info!("📄 State file path: {:?}", state_path);
    }

    async fn monitor_trades(&self) -> Result<()> {
        let mut interval = tokio::time::interval(POLL_INTERVAL);

        loop {
            interval.tick().await;

            for trade in self.active_trades.iter() {
                let token_mint = trade.key().clone();
                let mut trade_data = trade.value().clone();

                match self.fetch_token_price(&token_mint).await {
                    Ok(current_price) => {
                        trade_data.last_price = current_price;
                        let pl_percent = (current_price - trade_data.entry_price) / trade_data.entry_price * 100.0;

                        info!(
                            "Token: {} | Price: ${:.6} | P/L: {:.2}% | Volume: ${:.2}",
                            token_mint, current_price, pl_percent, trade_data.volume_24h
                        );

                        if current_price <= trade_data.stop_loss {
                            info!("🛑 Stop loss triggered for {}", token_mint);
                            if let Err(e) = self.execute_sell(&token_mint).await {
                                error!("Failed to execute stop loss: {}", e);
                            }
                        } else if current_price >= trade_data.take_profit {
                            info!("🎯 Take profit triggered for {}", token_mint);
                            if let Err(e) = self.execute_sell(&token_mint).await {
                                error!("Failed to execute take profit: {}", e);
                            }
                        }

                        // Update trade data
                        self.active_trades.insert(token_mint.clone(), trade_data);
                    }
                    Err(e) => {
                        error!("Failed to fetch price for {}: {}", token_mint, e);
                        continue;
                    }
                }
            }

            // Save state periodically
            if let Err(e) = self.save_state().await {
                error!("Failed to save state: {}", e);
            }
        }
    }

    async fn setup_websocket(&self) -> Result<()> {
        let mut ws_guard = self.ws_connection.lock().await;
        if ws_guard.is_none() {
            let (ws_stream, _) = connect_async(WS_URL).await?;
            *ws_guard = Some(ws_stream);
        }
        Ok(())
    }

    pub async fn execute_buy(&self, token_mint: &str) -> Result<String> {
        let start = Instant::now();
        info!("🚀 Initiating buy for {}", token_mint);

        // Validate token and get pool data
        let (volume, liquidity) = self.get_token_metrics(token_mint).await?;
        if !self.validate_trading_requirements(volume, liquidity)? {
            return Err(anyhow!("Token doesn't meet trading requirements"));
        }

        // Get quote with retries
        let amount_lamports = (TRADE_AMOUNT_SOL * 1e9) as u64;
        let quote = self.get_quote_with_retry(
            SOL_MINT,
            token_mint,
            amount_lamports
        ).await?;

        // Build and send transaction
        let swap_data = self.get_swap_data(&quote).await?;
        let signature = self.send_priority_tx(&swap_data).await?;

        // Verify transaction
        self.verify_transaction(&signature).await?;

        // Record trade
        let price = self.fetch_token_price(token_mint).await?;
        self.record_trade(token_mint, price, amount_lamports, volume, liquidity).await;

        info!("✅ Buy executed in {:?} | Signature: {}", start.elapsed(), signature);
        Ok(signature)
    }

    async fn get_token_metrics(&self, token_mint: &str) -> Result<(f64, f64)> {
        let request = json!({
            "jsonrpc": "2.0",
            "id": "metrics",
            "method": "getTokenData",
            "params": [token_mint]
        });

        let response = self.http_client
            .post(HELIUS_RPC)
            .json(&request)
            .send()
            .await?
            .json::<Value>()
            .await?;

        let volume = response["result"]["volume24h"]
            .as_f64()
            .ok_or_else(|| anyhow!("Invalid volume data"))?;
            
        let liquidity = response["result"]["liquidity"]
            .as_f64()
            .ok_or_else(|| anyhow!("Invalid liquidity data"))?;

        Ok((volume, liquidity))
    }

    fn validate_trading_requirements(&self, volume: f64, liquidity: f64) -> Result<bool> {
        if liquidity < MIN_LIQUIDITY_USD || liquidity > MAX_LIQUIDITY_USD {
            warn!("Liquidity outside range: ${}", liquidity);
            return Ok(false);
        }

        if volume < MIN_LIQUIDITY_USD * 0.1 {  // Require at least 10% of min liquidity in volume
            warn!("Insufficient 24h volume: ${}", volume);
            return Ok(false);
        }

        Ok(true)
    }

    async fn get_quote_with_retry(&self, input_mint: &str, output_mint: &str, amount: u64) -> Result<Value> {
        let mut attempts = 0;
        const MAX_ATTEMPTS: u32 = 3;

        while attempts < MAX_ATTEMPTS {
            match self.get_quote(input_mint, output_mint, amount).await {
                Ok(quote) => return Ok(quote),
                Err(e) => {
                    attempts += 1;
                    warn!("Quote attempt {} failed: {}", attempts, e);
                    if attempts < MAX_ATTEMPTS {
                        sleep(Duration::from_millis(100)).await;
                    }
                }
            }
        }

        Err(anyhow!("Failed to get quote after {} attempts", MAX_ATTEMPTS))
    }

    async fn get_quote(&self, input_mint: &str, output_mint: &str, amount: u64) -> Result<Value> {
        let url = format!(
            "{}/quote?inputMint={}&outputMint={}&amount={}&slippageBps={}&onlyDirectRoutes=true",
            JUPITER_V6_API, input_mint, output_mint, amount, SLIPPAGE_BPS
        );

        let response = self.http_client
            .get(&url)
            .send()
            .await?
            .json::<Value>()
            .await?;

        if response.get("error").is_some() {
            return Err(anyhow!("Jupiter error: {}", response["error"]));
        }

        Ok(response)
    }

    async fn get_swap_data(&self, quote: &Value) -> Result<String> {
        let swap_request = json!({
            "quoteResponse": quote,
            "userPublicKey": self.keypair.pubkey().to_string(),
            "computeUnitPriceMicroLamports": PRIORITY_FEE,
            "asLegacyTransaction": false
        });

        let response = self.http_client
            .post(format!("{}/swap", JUPITER_V6_API))
            .json(&swap_request)
            .send()
            .await?
            .json::<Value>()
            .await?;

        response["swapTransaction"]
            .as_str()
            .ok_or_else(|| anyhow!("Invalid swap response"))
            .map(String::from)
    }

    async fn send_priority_tx(&self, swap_data: &str) -> Result<String> {
        let request = json!({
            "jsonrpc": "2.0",
            "id": "helius-priority",
            "method": "sendTransaction",
            "params": [
                swap_data,
                {
                    "encoding": "base64",
                    "maxRetries": 0,
                    "skipPreflight": true,
                    "priorityFee": PRIORITY_FEE
                }
            ]
        });

        let response = self.http_client
            .post(HELIUS_RPC)
            .json(&request)
            .send()
            .await?
            .json::<Value>()
            .await?;

        response["result"]
            .as_str()
            .ok_or_else(|| anyhow!("Invalid transaction response"))
            .map(String::from)
    }

    async fn verify_transaction(&self, signature: &str) -> Result<()> {
        for _ in 0..10 {
            match self.rpc_client.get_signature_status(&signature.parse()?)? {
                Some(Ok(_)) => return Ok(()),
                Some(Err(e)) => return Err(anyhow!("Transaction failed: {}", e)),
                None => sleep(Duration::from_millis(500)).await,
            }
        }
        Err(anyhow!("Transaction verification timeout"))
    }

    async fn record_trade(&self, token_mint: &str, price: f64, amount: u64, volume: f64, liquidity: f64) {
        let trade = ActiveTrade {
            token_mint: token_mint.to_string(),
            entry_price: price,
            amount,
            timestamp: chrono::Utc::now().timestamp(),
            last_price: price,
            take_profit: price * 1.20,  // 20% profit target
            stop_loss: price * 0.95,    // 5% stop loss
            volume_24h: volume,
            liquidity,
        };

        self.active_trades.insert(token_mint.to_string(), trade);
        self.save_state().await.unwrap_or_else(|e| error!("Failed to save state: {}", e));
    }

    pub async fn execute_sell(&self, token_mint: &str) -> Result<String> {
        let trade = match self.active_trades.get(token_mint) {
            Some(t) => t,
            None => return Err(anyhow!("No active trade found for {}", token_mint))
        };

        info!("🔄 Executing sell for {} | Amount: {}", token_mint, trade.amount);
        
        let quote = self.get_quote_with_retry(
            token_mint,
            "So11111111111111111111111111111111111111112", // SOL
            trade.amount
        ).await?;

        let swap_data = self.get_swap_data(&quote).await?;
        let signature = self.send_priority_tx(&swap_data).await?;
        self.verify_transaction(&signature).await?;

        // Calculate final P/L
        let exit_price = self.fetch_token_price(token_mint).await?;
        let profit_loss = (exit_price - trade.entry_price) / trade.entry_price * 100.0;

        info!("💰 Trade closed | P/L: {:.2}% | Signature: {}", profit_loss, signature);

        // Update metrics
        self.update_trade_metrics(token_mint, profit_loss > 0.0, profit_loss);

        // Remove from active trades
        self.active_trades.remove(token_mint);
        self.save_state().await?;

        Ok(signature)
    }

    async fn fetch_token_price(&self, token_mint: &str) -> Result<f64> {
        let request = json!({
            "jsonrpc": "2.0",
            "id": "price-check",
            "method": "getTokenPrice",
            "params": [token_mint]
        });

        let response = self.http_client
            .post(HELIUS_RPC)
            .json(&request)
            .send()
            .await?
            .json::<Value>()
            .await?;

        response["result"]["price"]
            .as_f64()
            .ok_or_else(|| anyhow!("Invalid price response"))
    }

    fn update_trade_metrics(&self, token_mint: &str, is_profit: bool, profit_loss: f64) {
        self.trade_metrics
            .entry(token_mint.to_string())
            .and_modify(|metrics| {
                metrics.total_trades += 1;
                if is_profit {
                    metrics.successful_trades += 1;
                }
                metrics.total_profit += profit_loss;
            })
            .or_insert(TradeMetrics {
                total_trades: 1,
                successful_trades: if is_profit { 1 } else { 0 },
                total_profit: profit_loss,
                avg_execution_time: Duration::from_secs(0),
            });
    }

    pub async fn save_state(&self) -> Result<()> {
        // Get paths
        let data_dir = Self::get_data_dir();
        let state_path = Self::get_state_file_path();
        let temp_path = data_dir.join("trade_state.json.tmp");

        // Ensure data directory exists
        if !data_dir.exists() {
            tokio::fs::create_dir_all(&data_dir).await?;
        }

        let state = json!({
            "version": "1.0",
            "timestamp": chrono::Utc::now().timestamp(),
            "active_trades": self.active_trades
                .iter()
                .map(|ref_multi| {
                    let trade = ref_multi.value();
                    json!({
                        "token_mint": trade.token_mint,
                        "entry_price": trade.entry_price,
                        "amount": trade.amount,
                        "timestamp": trade.timestamp,
                        "last_price": trade.last_price,
                        "take_profit": trade.take_profit,
                        "stop_loss": trade.stop_loss,
                        "volume_24h": trade.volume_24h,
                        "liquidity": trade.liquidity
                    })
                })
                .collect::<Vec<_>>(),
            "metrics": self.trade_metrics
                .iter()
                .map(|ref_multi| {
                    let (token, metrics) = (ref_multi.key(), ref_multi.value());
                    json!({
                        "token_mint": token,
                        "total_trades": metrics.total_trades,
                        "successful_trades": metrics.successful_trades,
                        "total_profit": metrics.total_profit,
                        "avg_execution_time": metrics.avg_execution_time.as_secs_f64()
                    })
                })
                .collect::<Vec<_>>()
        });

        // Write to temporary file
        tokio::fs::write(
            &temp_path,
            serde_json::to_string_pretty(&state)?
        ).await.map_err(|e| anyhow!("Failed to write temporary state file: {}", e))?;

        // Atomically rename
        tokio::fs::rename(&temp_path, &state_path)
            .await
            .map_err(|e| anyhow!("Failed to save state file: {}", e))?;

        info!("📝 State saved successfully to {:?}", state_path);
        Ok(())
    }

    pub async fn load_state(&self) -> Result<()> {
        let state_path = Self::get_state_file_path();

        // Check if state file exists
        if !state_path.exists() {
            info!("No existing state file found at {:?}, starting fresh", state_path);
            return Ok(());
        }

        let data = tokio::fs::read_to_string(&state_path)
            .await
            .map_err(|e| anyhow!("Failed to read state file: {}", e))?;

        let state: Value = serde_json::from_str(&data)
            .map_err(|e| anyhow!("Failed to parse state file: {}", e))?;

        // Validate state version
        let version = state["version"]
            .as_str()
            .ok_or_else(|| anyhow!("Invalid state file: missing version"))?;
        if version != "1.0" {
            return Err(anyhow!("Unsupported state file version: {}", version));
        }
        
        // Clear existing state
        self.active_trades.clear();
        self.trade_metrics.clear();
    
        // Load active trades
        if let Some(trades) = state["active_trades"].as_array() {
            for trade in trades {
                let active_trade = ActiveTrade {
                    token_mint: trade["token_mint"].as_str()
                        .ok_or_else(|| anyhow!("Invalid trade: missing token_mint"))?
                        .to_string(),
                    entry_price: trade["entry_price"].as_f64()
                        .ok_or_else(|| anyhow!("Invalid trade: missing entry_price"))?,
                    amount: trade["amount"].as_u64()
                        .ok_or_else(|| anyhow!("Invalid trade: missing amount"))?,
                    timestamp: trade["timestamp"].as_i64()
                        .ok_or_else(|| anyhow!("Invalid trade: missing timestamp"))?,
                    last_price: trade["last_price"].as_f64()
                        .ok_or_else(|| anyhow!("Invalid trade: missing last_price"))?,
                    take_profit: trade["take_profit"].as_f64()
                        .ok_or_else(|| anyhow!("Invalid trade: missing take_profit"))?,
                    stop_loss: trade["stop_loss"].as_f64()
                        .ok_or_else(|| anyhow!("Invalid trade: missing stop_loss"))?,
                    volume_24h: trade["volume_24h"].as_f64()
                        .ok_or_else(|| anyhow!("Invalid trade: missing volume_24h"))?,
                    liquidity: trade["liquidity"].as_f64()
                        .ok_or_else(|| anyhow!("Invalid trade: missing liquidity"))?,
                };
                self.active_trades.insert(active_trade.token_mint.clone(), active_trade);
            }
        }
    
        // Load metrics
        if let Some(metrics) = state["metrics"].as_array() {
            for metric in metrics {
                let trade_metrics = TradeMetrics {
                    total_trades: metric["total_trades"].as_u64()
                        .ok_or_else(|| anyhow!("Invalid metrics: missing total_trades"))?,
                    successful_trades: metric["successful_trades"].as_u64()
                        .ok_or_else(|| anyhow!("Invalid metrics: missing successful_trades"))?,
                    total_profit: metric["total_profit"].as_f64()
                        .ok_or_else(|| anyhow!("Invalid metrics: missing total_profit"))?,
                    avg_execution_time: Duration::from_secs_f64(
                        metric["avg_execution_time"].as_f64()
                            .ok_or_else(|| anyhow!("Invalid metrics: missing avg_execution_time"))?
                    ),
                };
                self.trade_metrics.insert(
                    metric["token_mint"].as_str()
                        .ok_or_else(|| anyhow!("Invalid metrics: missing token_mint"))?
                        .to_string(),
                    trade_metrics
                );
            }
        }
    
        info!("📥 State loaded successfully");
        Ok(())
    }

    pub async fn get_trade_stats(&self) -> Result<Value> {
        Ok(json!({
            "active_trades": self.active_trades.len(),
            "total_trades": self.trade_metrics.iter().map(|m| m.total_trades).sum::<u64>(),
            "successful_trades": self.trade_metrics.iter().map(|m| m.successful_trades).sum::<u64>(),
            "total_profit": self.trade_metrics.iter().map(|m| m.total_profit).sum::<f64>(),
            "current_positions": self.active_trades.iter().map(|trade| {
                json!({
                    "token": trade.token_mint,
                    "entry_price": trade.entry_price,
                    "current_price": trade.last_price,
                    "profit_loss": ((trade.last_price - trade.entry_price) / trade.entry_price * 100.0),
                    "volume_24h": trade.volume_24h,
                    "liquidity": trade.liquidity
                })
            }).collect::<Vec<_>>()
        }))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use tokio::runtime::Runtime;

    #[test]
    fn test_trade_manager_creation() {
        let keypair = Keypair::new();
        let manager = TradeManager::new(keypair);
        assert!(manager.active_trades.is_empty());
    }

    #[test]
    fn test_trade_validation() {
        let rt = Runtime::new().unwrap();
        let manager = TradeManager::new(Keypair::new());
        
        rt.block_on(async {
            let result = manager.validate_trading_requirements(2000.0, 5000.0);
            assert!(result.is_ok());
            assert!(result.unwrap());

            let result = manager.validate_trading_requirements(100.0, 500.0);
            assert!(result.is_ok());
            assert!(!result.unwrap());
        });
    }

    #[test]
    fn test_state_management() {
        let rt = Runtime::new().unwrap();
        let manager = TradeManager::new(Keypair::new());
        
        rt.block_on(async {
            // Add test trade
            let trade = ActiveTrade {
                token_mint: "test_mint".to_string(),
                entry_price: 1.0,
                amount: 1000000,
                timestamp: chrono::Utc::now().timestamp(),
                last_price: 1.0,
                take_profit: 1.2,
                stop_loss: 0.95,
                volume_24h: 5000.0,
                liquidity: 10000.0,
            };
            manager.active_trades.insert("test_mint".to_string(), trade);

            // Save and load state
            manager.save_state().await.unwrap();
            manager.active_trades.clear();
            manager.load_state().await.unwrap();

            assert_eq!(manager.active_trades.len(), 1);
            assert!(manager.active_trades.contains_key("test_mint"));
        });
    }
}  please give me the full script with the edits in place thank you