Compiling solana_rust_bot v0.1.0 (C:\solana_rust_bot)
error[E0433]: failed to resolve: use of undeclared type `File`
   --> src/main.rs:151:20
    |
151 |     settings.merge(File::with_name(CONFIG_PATH))?;
    |                    ^^^^ use of undeclared type `File`
    |
help: consider importing one of these structs
    |
1   + use std::fs::File;
    |
1   + use config::File;
    |
1   + use tokio::fs::File;
    |

error[E0425]: cannot find value `SNIPE_AMOUNT` in this scope
   --> src/main.rs:323:47
    |
323 |             self.execute_buy(&token_address, (SNIPE_AMOUNT * 1e9) as u64).await?;
    |                                               ^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find value `TAKING_PROFIT_PERCENT` in this scope
   --> src/main.rs:474:45
    |
474 |         let take_profit_price = buy_price * TAKING_PROFIT_PERCENT;
    |                                             ^^^^^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find value `STOP_LOSS_PERCENT` in this scope
   --> src/main.rs:475:43
    |
475 |         let stop_loss_price = buy_price * STOP_LOSS_PERCENT;
    |                                           ^^^^^^^^^^^^^^^^^ not found in this scope

error[E0599]: no method named `extract_token_address` found for reference `&Bot` in the current scope
   --> src/main.rs:283:59
    |
283 |                         if let Some(token_address) = self.extract_token_address(log) {
    |                                                      -----^^^^^^^^^^^^^^^^^^^^^-----
    |                                                      |    |
    |                                                      |    this is an associated function, not a method
    |                                                      help: use associated function syntax instead: `Bot::extract_token_address(log)`
    |
    = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
note: the candidate is defined in an impl for the type `Bot`
   --> src/main.rs:311:5
    |
311 |     fn extract_token_address(log: &serde_json::Value) -> Option<String> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0277]: the size for values of type `str` cannot be known at compilation time
   --> src/main.rs:283:32
    |
283 |                         if let Some(token_address) = self.extract_token_address(log) {
    |                                ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `str`
note: required by a bound in `std::prelude::v1::Some`
   --> C:\Users\Orsen\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\core\src\option.rs:571:17
    |
571 | pub enum Option<T> {
    |                 ^ required by this bound in `std::prelude::v1::Some`
...
579 |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
    |     ---- required by a bound in this tuple variant

error[E0308]: mismatched types
   --> src/main.rs:299:52
    |
299 | ...                   self.process_token(token_address).await?;
    |                            ------------- ^^^^^^^^^^^^^- help: try using a conversion method: `.to_string()`
    |                            |             |
    |                            |             expected `String`, found `str`
    |                            arguments to this method are incorrect
    |
note: method defined here
   --> src/main.rs:318:14
    |
318 |     async fn process_token(&self, token_address: String) -> Result<()> {
    |              ^^^^^^^^^^^^^        ---------------------

error[E0609]: no field `rpc_url` on type `RpcConfig`
   --> src/main.rs:352:60
    |
352 |         let url = format!("{}?api-key={}", self.config.rpc.rpc_url, self.config.api_keys.helius_api_key);
    |                                                            ^^^^^^^ unknown field
    |
    = note: available fields are: `solana_rpc_url`, `fallback_url`

error[E0609]: no field `rpc_url` on type `RpcConfig`
   --> src/main.rs:331:60
    |
331 |         let url = format!("{}?api-key={}", self.config.rpc.rpc_url, self.config.api_keys.helius_api_key);
    |                                                            ^^^^^^^ unknown field
    |
    = note: available fields are: `solana_rpc_url`, `fallback_url`

error[E0609]: no field `min_liquidity` on type `TradingConfig`
   --> src/main.rs:397:57
    |
397 |         let is_valid = liquidity >= self.config.trading.min_liquidity &&
    |                                                         ^^^^^^^^^^^^^ unknown field
    |
    = note: available fields are: `snipe_amount`, `profit_target_percent`, `max_retry_attempts`, `stop_loss_percent`, `max_slippage` ... and 2 others

error[E0609]: no field `max_liquidity` on type `TradingConfig`
   --> src/main.rs:398:56
    |
398 |                       liquidity <= self.config.trading.max_liquidity;
    |                                                        ^^^^^^^^^^^^^ unknown field
    |
    = note: available fields are: `snipe_amount`, `profit_target_percent`, `max_retry_attempts`, `stop_loss_percent`, `max_slippage` ... and 2 others

error[E0308]: mismatched types
    --> src/main.rs:453:27
     |
453  |         instructions.push(ComputeBudgetInstruction::set_compute_unit_limit(COMPUTE_UNIT_LIMIT));
     |                      ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `CompiledInstruction`, found `Instruction`
     |                      |
     |                      arguments to this method are incorrect
     |
note: method defined here
    --> C:\Users\Orsen\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\alloc\src\vec\mod.rs:2003:12
     |
2003 |     pub fn push(&mut self, value: T) {
     |            ^^^^

error[E0308]: mismatched types
    --> src/main.rs:454:27
     |
454  |         instructions.push(ComputeBudgetInstruction::set_compute_unit_price(self.config.trading.priority_fee));
     |                      ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `CompiledInstruction`, found `Instruction`     
     |                      |
     |                      arguments to this method are incorrect
     |
note: method defined here
    --> C:\Users\Orsen\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\alloc\src\vec\mod.rs:2003:12
     |
2003 |     pub fn push(&mut self, value: T) {
     |            ^^^^

error[E0277]: the `?` operator can only be applied to values that implement `Try`
   --> src/main.rs:469:25
    |
469 |         let signature = self.rpc_client.send_and_confirm_transaction_with_spinner(&transaction)?;
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `impl futures_util::Future<Output = Result<Signature, solana_client::client_error::ClientError>>`
    |
    = help: the trait `Try` is not implemented for `impl futures_util::Future<Output = Result<Signature, solana_client::client_error::ClientError>>`
help: consider `await`ing on the `Future`
    |
469 |         let signature = self.rpc_client.send_and_confirm_transaction_with_spinner(&transaction).await?;
    |                                                                                                ++++++

error[E0599]: no method named `map_err` found for opaque type `impl futures_util::Future<Output = Result<u64, solana_client::client_error::ClientError>>` in the current scope
   --> src/main.rs:543:14
    |
541 |           let balance = self.rpc_client
    |  _______________________-
542 | |             .get_balance(&self.keypair.pubkey())
543 | |             .map_err(|e| anyhow!("Failed to get SOL balance: {}", e))?;
    | |             -^^^^^^^ method not found in `impl Future<Output = Result<u64, ClientError>>`
    | |_____________|
    |
    |
   ::: C:\Users\Orsen\.cargo\registry\src\index.crates.io-6f17d22bba15001f\futures-util-0.3.31\src\future\try_future\mod.rs:308:8
    |
308 |       fn map_err<E, F>(self, f: F) -> MapErr<Self, F>
    |          ------- the method is available for `impl futures_util::Future<Output = Result<u64, solana_client::client_error::ClientError>>` here
    |
    = help: items from traits can only be used if the trait is in scope
help: consider `await`ing on the `Future` and calling the method on its `Output`
    |
543 |             .await.map_err(|e| anyhow!("Failed to get SOL balance: {}", e))?;
    |              ++++++
help: trait `TryFutureExt` which provides `map_err` is implemented but not in scope; perhaps you want to import it
    |
1   + use futures_util::TryFutureExt;
    |

error[E0277]: the `?` operator can only be applied to values that implement `Try`
   --> src/main.rs:551:29
    |
551 |             let blockhash = self.rpc_client.get_latest_blockhash()?;
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the `?` operator cannot be applied to type `impl futures_util::Future<Output = Result<solana_sdk::hash::Hash, solana_client::client_error::ClientError>>`
    |
    = help: the trait `Try` is not implemented for `impl futures_util::Future<Output = Result<solana_sdk::hash::Hash, solana_client::client_error::ClientError>>`
help: consider `await`ing on the `Future`
    |
551 |             let blockhash = self.rpc_client.get_latest_blockhash().await?;
    |                                                                   ++++++

Some errors have detailed explanations: E0277, E0308, E0425, E0433, E0599, E0609.
For more information about an error, try `rustc --explain E0277`. 
error: could not compile `solana_rust_bot` (bin "solana_rust_bot") due to 16 previous errors      please rewrite this correctly to work this time please use {
    anyhow::{anyhow, Result},
    base64,
    bincode,
    config::Config,
    ctrlc,
    env_logger::Builder,
    futures_util::{SinkExt, StreamExt},
    log::{debug, error, info, warn},
    reqwest::Client as HttpClient,
    serde::{Deserialize, Serialize},
    serde_json::json,
    solana_client::nonblocking::rpc_client::RpcClient,
    solana_sdk::{
        compute_budget::ComputeBudgetInstruction,
        commitment_config::CommitmentConfig,
        hash::Hash,
        instruction::CompiledInstruction,
        signer::{keypair::Keypair, Signer},
        transaction::Transaction,
    },
    std::{
        collections::HashMap,
        fs::OpenOptions,
        io::{Read, Write},
        sync::Arc,
        time::{Duration, Instant, SystemTime},
    },
    tokio::{sync::Mutex, time::interval},
    tokio_tungstenite::{connect_async, tungstenite::protocol::Message as WsMessage},
};

// Constants
const WSOL_MINT: &str = "So11111111111111111111111111111111111111112"; // Wrapped Solana
const RAYDIUM_AMM_PROGRAM_ID: &str = "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"; // Raydium
const MAX_ACTIVE_TRADES: usize = 5; // max active trades
const STATE_FILE: &str = "bot_state.json"; // Bot state file
const PRICE_CHECK_INTERVAL: Duration = Duration::from_secs(1); // Price check interval
const COMPUTE_UNIT_LIMIT: u32 = 200_000; // Compute unit limit

// Paths for keypair and config
const KEYPAIR_PATH: &str = "C:\\Users\\Orsen\\.config\\solana\\id.json";
const CONFIG_PATH: &str = "C:\\solana_rust_bot\\config.toml";

// Bot Configuration Structure
#[derive(Debug, Deserialize, Clone)]
pub struct BotConfig {
    rpc: RpcConfig,
    urls: UrlConfig,
    wallet: WalletConfig,
    api_keys: ApiKeys,
    trading: TradingConfig,
    websocket: WebsocketConfig,
    token_requirements: TokenRequirements,
}

#[derive(Debug, Deserialize, Clone)]
pub struct RpcConfig {
    solana_rpc_url: String,
    fallback_url: String,
}

#[derive(Debug, Deserialize, Clone)]
pub struct UrlConfig {
    ws_url: String,
    rpc_url: String,
}

#[derive(Debug, Deserialize, Clone)]
pub struct WalletConfig {
    keypair_path: String,
    public_key: String,
}

#[derive(Debug, Deserialize, Clone)]
pub struct ApiKeys {
    helius_api_key: String,
}

#[derive(Debug, Deserialize, Clone)]
pub struct TradingConfig {
    snipe_amount: u64,
    profit_target_percent: f64,
    max_retry_attempts: u32,
    stop_loss_percent: f64,
    max_slippage: f64,
    priority_fee: u64,
    min_sol_balance: f64,
}

#[derive(Debug, Deserialize, Clone)]
pub struct WebsocketConfig {
    reconnect_interval: u64,
}

#[derive(Debug, Deserialize, Clone)]
pub struct TokenRequirements {
    mutable: bool,
    burnt: bool,
    frozen: bool,
    min_supply: u64,
}

#[derive(Clone, Serialize, Deserialize, Debug)]
struct Trade {
    token_address: String,
    amount: u64,
    buy_price: f64,
    take_profit_price: f64,
    stop_loss_price: f64,
    timestamp: u64,
}

// Main Bot Struct
struct Bot {
    config: BotConfig,
    rpc_client: Arc<RpcClient>,
    keypair: Arc<Keypair>,
    active_trades: Arc<Mutex<HashMap<String, Trade>>>,
    last_blockhash: Arc<Mutex<(Hash, Instant)>>,
    swap_limiter: Arc<Mutex<()>>,
    http_client: HttpClient,
}

// Setup logging
fn setup_logging() -> Result<()> {
    Builder::new()
        .format(|buf, record| {
            writeln!(
                buf,
                "[{}] {} - {}",
                record.level(),
                SystemTime::now()
                    .duration_since(SystemTime::UNIX_EPOCH)
                    .unwrap_or_else(|_| Duration::from_secs(0))
                    .as_secs(),
                record.args()
            )
        })
        .filter(None, log::LevelFilter::Info)
        .init();

    info!("🚀 Logging system initialized");
    Ok(())
}

// Load configuration
fn load_config() -> Result<BotConfig> {
    info!("📚 Loading configuration from {}", CONFIG_PATH);
    let mut settings = Config::new();
    settings.merge(File::with_name(CONFIG_PATH))?;

    let config: BotConfig = settings.try_into()?;
    info!("✅ Configuration loaded successfully");
    debug!("📊 Config details: {:?}", config);
    Ok(config)
}

// Load keypair from file
fn load_keypair(path: &str) -> Result<Keypair> {
    info!("🔑 Loading keypair from {}", path);
    let data = std::fs::read(path)?;
    let json: Vec<u8> = serde_json::from_slice(&data)?;

    Keypair::from_bytes(&json)
        .map_err(|e| anyhow!("Failed to load keypair: {}", e))
}

// Implementation of Bot functionality
impl Bot {
    async fn new() -> Result<Self> {
        info!("🚀 Initializing Raydium Sniper Bot");
        setup_logging()?;

        // Load configuration
        let config = load_config()?;

        // Setup RPC client
        info!("🌐 Setting up RPC client with URL: {}", config.rpc.solana_rpc_url);
        let rpc_client = Arc::new(RpcClient::new_with_commitment(
            config.rpc.solana_rpc_url.clone(),
            CommitmentConfig::confirmed(),
        ));

        info!("🌍 Setting up HTTP client");
        let http_client = HttpClient::builder()
            .timeout(Duration::from_secs(10))
            .build()?;

        // Load keypair
        let keypair = Arc::new(load_keypair(&config.wallet.keypair_path)?);

        let bot = Self {
            config,
            rpc_client,
            keypair,
            active_trades: Arc::new(Mutex::new(HashMap::new())),
            last_blockhash: Arc::new(Mutex::new((Hash::default(), Instant::now()))),
            swap_limiter: Arc::new(Mutex::new(())),
            http_client,
        };

        info!("💾 Loading previous bot state");
        bot.load_state().await?;
        info!("✅ Bot initialization complete");
        Ok(bot)
    }

    async fn run(&self) -> Result<()> {
        info!("🚀 Starting Raydium Sniper Bot");

        loop {
            info!("🔌 Connecting to Helius WebSocket...");
            match connect_async(&self.config.urls.ws_url).await {
                Ok((ws_stream, _)) => {
                    let (mut write, mut read) = ws_stream.split();
                    info!("✅ Connected to Helius WebSocket");

                    // Subscribe to Raydium AMM logs
                    let subscribe_message = json!({
                        "jsonrpc": "2.0",
                        "id": 1,
                        "method": "logsSubscribe",
                        "params": [
                            {"mentions": [RAYDIUM_AMM_PROGRAM_ID]},
                            {"commitment": "confirmed"}
                        ]
                    });

                    write.send(WsMessage::Text(subscribe_message.to_string())).await?;
                    info!("📡 Subscribed to Raydium AMM logs");

                    let mut interval = interval(PRICE_CHECK_INTERVAL);
                    loop {
                        tokio::select! {
                            Some(msg) = read.next() => {
                                match msg {
                                    Ok(WsMessage::Text(text)) => {
                                        debug!("📥 Received message: {}", text);
                                        if let Err(e) = self.handle_event(&text).await {
                                            error!("❌ Error handling event: {}", e);
                                        }
                                    }
                                    Ok(WsMessage::Close(_)) => {
                                        warn!("🚪 WebSocket connection closed");
                                        break;
                                    }
                                    Ok(_) => {},
                                    Err(e) => {
                                        error!("❌ WebSocket error: {}", e);
                                        break;
                                    }
                                }
                            }
                            // Check active trades at specified intervals
                            _ = interval.tick(), if !self.active_trades.lock().await.is_empty() => {
                                if let Err(e) = self.check_active_trades().await {
                                    error!("❌ Error checking active trades: {}", e);
                                }
                            }
                        }
                    }
                }
                Err(e) => {
                    error!("❌ WebSocket connect error: {}. Retrying in 5 seconds...", e);
                    tokio::time::sleep(Duration::from_secs(5)).await;
                }
            }
        }
    }

    async fn handle_event(&self, text: &str) -> Result<()> {
        let event: serde_json::Value = serde_json::from_str(text)?;

        if let Some(error) = event.get("error") {
            return Err(anyhow!("WebSocket error received: {:?}", error));
        }

        if let Some(result) = event.get("result") {
            if let Some(logs) = result.get("logs") {
                if let Some(logs_array) = logs.as_array() {
                    for log in logs_array {
                        if let Some(token_address) = self.extract_token_address(log) {
                            info!("💎 Found potential token: {}", token_address);

                            let token_metadata = match self.get_token_metadata(&token_address).await {
                                Ok(metadata) => metadata,
                                Err(e) => {
                                    warn!("❌ Failed to get metadata for {}: {}", token_address, e);
                                    continue;
                                }
                            };

                            let mutable = token_metadata.get("mutable").map_or(true, |v| v.as_bool().unwrap_or(true));
                            let burnt = token_metadata.get("burnt").map_or(false, |v| v.as_bool().unwrap_or(false));

                            if !mutable && burnt {
                                info!("✅ Token {} passed validation", token_address);
                                self.process_token(token_address).await?;
                            } else {
                                info!("❌ Token {} failed validation", token_address);
                            }
                        }
                    }
                }
            }
        }
        Ok(())
    }

    fn extract_token_address(log: &serde_json::Value) -> Option<String> {
        log.get("GetAsset")
            .and_then(|asset| asset.get("tokenAddress"))
            .and_then(|addr| addr.as_str())
            .map(String::from)
    }

    async fn process_token(&self, token_address: String) -> Result<()> {
        info!("🔄 Processing token {}", token_address);

        if self.is_valid_pool(&token_address).await? {
            info!("✅ Pool validation passed for {}", token_address);
            self.execute_buy(&token_address, (SNIPE_AMOUNT * 1e9) as u64).await?;
        } else {
            info!("❌ Pool validation failed for {}", token_address);
        }
        Ok(())
    }

    async fn get_token_metadata(&self, token_address: &str) -> Result<serde_json::Value> {
        let url = format!("{}?api-key={}", self.config.rpc.rpc_url, self.config.api_keys.helius_api_key);
        let body = json!({
            "jsonrpc": "2.0",
            "id": "get-token-metadata",
            "method": "getTokenMetadata",
            "params": [[token_address]]
        });

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

        Ok(response["result"].as_array().ok_or_else(|| anyhow!("Invalid metadata response format"))?
            .first().cloned().unwrap_or_default())
    }

    async fn get_token_price(&self, token_address: &str) -> Result<f64> {
        let url = format!("{}?api-key={}", self.config.rpc.rpc_url, self.config.api_keys.helius_api_key);
        let body = json!({
            "jsonrpc": "2.0",
            "id": "get-token-price",
            "method": "getTokenMetadata",
            "params": [[token_address]]
        });

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

        if let Some(price) = response["result"][0]["price"].as_f64() {
            Ok(price)
        } else {
            Err(anyhow!("Price not found for token {}", token_address))
        }
    }

    async fn get_pool_liquidity(&self, token_address: &str) -> Result<f64> {
        let url = "https://api.raydium.io/pairs";
        let response: serde_json::Value = self.http_client.get(url).send().await?.json().await?;

        let pairs = response["data"].as_array()
            .ok_or_else(|| anyhow!("Invalid response format"))?;

        for pair in pairs {
            if pair["token0"].as_str() == Some(token_address) || 
               pair["token1"].as_str() == Some(token_address) {
                if let Some(liquidity) = pair["liquidity"]["liquidity"].as_f64() {
                    debug!("💧 Found liquidity for {}: {}", token_address, liquidity);
                    return Ok(liquidity);
                }
            }
        }

        Err(anyhow!("Liquidity pool not found for token: {}", token_address))
    }

    async fn is_valid_pool(&self, token_address: &str) -> Result<bool> {
        let liquidity = self.get_pool_liquidity(token_address).await?;
        let is_valid = liquidity >= self.config.trading.min_liquidity && 
                      liquidity <= self.config.trading.max_liquidity;
        
        info!("🔍 Pool validation for {}: {} ({})", 
            token_address, 
            if is_valid { "passed" } else { "failed" },
            liquidity
        );

        Ok(is_valid)
    }

    async fn execute_buy(&self, token_address: &str, amount: u64) -> Result<()> {
        info!("🛍️ Executing buy for {} SOL of token {}", amount as f64 / 1e9, token_address);
        let _guard = self.swap_limiter.lock().await;

        let jupiter_quote_url = format!(
            "https://quote-api.jup.ag/v4/quote?inputMint={}&outputMint={}&amount={}&slippageBps={}",
            WSOL_MINT,
            token_address,
            amount,
            (self.config.trading.max_slippage * 100.0) as u64
        );

        let quote: serde_json::Value = self.http_client.get(&jupiter_quote_url).send().await?.json().await?;
        debug!("📋 Jupiter quote received: {:?}", quote);

        let route = quote["data"].as_array()
            .and_then(|arr| arr.first())
            .ok_or_else(|| anyhow!("No route found"))?;

        let jupiter_swap_url = "https://quote-api.jup.ag/v4/swap";
        let swap_request = json!({
            "route": route,
            "userPublicKey": self.keypair.pubkey().to_string(),
            "wrapUnwrapSOL": true
        });

        let swap_response: serde_json::Value = self.http_client
            .post(jupiter_swap_url)
            .json(&swap_request)
            .send()
            .await?
            .json()
            .await?;

        let swap_transaction = swap_response["swapTransaction"].as_str()
            .ok_or_else(|| anyhow!("Swap transaction not found in response"))?;

        let decoded_transaction = base64::decode(swap_transaction)?;
        let mut transaction: Transaction = bincode::deserialize(&decoded_transaction)?;

        // Create new instructions
        let mut instructions: Vec<CompiledInstruction> = vec![];

        // Add the necessary compute budget instructions
        instructions.push(ComputeBudgetInstruction::set_compute_unit_limit(COMPUTE_UNIT_LIMIT));
        instructions.push(ComputeBudgetInstruction::set_compute_unit_price(self.config.trading.priority_fee));

        // Extend with existing instructions
        instructions.extend(transaction.message.instructions.iter().cloned());

        // Set the updated instructions back to the transaction
        transaction.message.instructions = instructions;

        let (blockhash, _) = self.get_latest_blockhash().await?;
        transaction.message.recent_blockhash = blockhash;

        // Sign the transaction with the correct Keypair reference
        transaction.sign(&[&*self.keypair], transaction.message.recent_blockhash);
        
        info!("💰 Sending transaction with priority fee: {} lamports/CU", self.config.trading.priority_fee);
        let signature = self.rpc_client.send_and_confirm_transaction_with_spinner(&transaction)?;
        info!("✅ Transaction confirmed: {}", signature);

        // Calculate buy prices and set trade details
        let buy_price = self.get_token_price(token_address).await?;
        let take_profit_price = buy_price * TAKING_PROFIT_PERCENT;
        let stop_loss_price = buy_price * STOP_LOSS_PERCENT;

        let trade = Trade {
            token_address: token_address.to_string(),
            amount,
            buy_price,
            take_profit_price,
            stop_loss_price,
            timestamp: chrono::Utc::now().timestamp() as u64,
        };

        self.active_trades.lock().await.insert(token_address.to_string(), trade);
        self.save_state().await?;

        Ok(())
    }

    async fn check_active_trades(&self) -> Result<()> {
        let trades = self.active_trades.lock().await;
        if !trades.is_empty() {
            info!("🔄 Checking {} active trades", trades.len());
            
            for (token_address, trade) in trades.iter() {
                match self.get_token_price(token_address).await {
                    Ok(current_price) => {
                        let profit_percent = ((current_price - trade.buy_price) / trade.buy_price * 100.0).round();
                        info!("📊 Token {}: {}% P/L", token_address, profit_percent);
                    }
                    Err(e) => warn!("❌ Failed to get price for {}: {}", token_address, e),
                }
            }
        }
        Ok(())
    }

    async fn load_state(&self) -> Result<()> {
        match OpenOptions::new().read(true).open(STATE_FILE) {
            Ok(mut file) => {
                let mut contents = String::new();
                file.read_to_string(&mut contents)?;
                let state: HashMap<String, Trade> = serde_json::from_str(&contents)?;
                let len = state.len();
                *self.active_trades.lock().await = state;
                info!("📥 Loaded {} active trades from state file", len);
            }
            Err(_) => {
                info!("📝 No existing state file found, starting fresh");
            }
        }
        Ok(())
    }

    async fn save_state(&self) -> Result<()> {
        let state = self.active_trades.lock().await.clone();
        let serialized = serde_json::to_string(&state)?;
        let mut file = OpenOptions::new()
            .write(true)
            .create(true)
            .truncate(true)
            .open(STATE_FILE)?;
        file.write_all(serialized.as_bytes())?;
        debug!("💾 Saved {} active trades to state file", state.len());
        Ok(())
    }

    async fn get_sol_balance(&self) -> Result<u64> {
        let balance = self.rpc_client
            .get_balance(&self.keypair.pubkey())
            .map_err(|e| anyhow!("Failed to get SOL balance: {}", e))?;
        info!("💰 Current SOL balance: {} SOL", balance as f64 / 1e9);
        Ok(balance)
    }

    async fn get_latest_blockhash(&self) -> Result<(Hash, Instant)> {
        let mut guard = self.last_blockhash.lock().await;
        if guard.1.elapsed() > Duration::from_secs(120) {
            let blockhash = self.rpc_client.get_latest_blockhash()?;
            *guard = (blockhash, Instant::now());
            debug!("🔄 Updated blockhash: {}", blockhash);
        }
        Ok(guard.clone())
    }
}

#[tokio::main]
async fn main() -> Result<()> {
    info!("🚀 Starting Raydium Sniper Bot");
    
    let bot = Arc::new(Bot::new().await?);
    let bot_clone = Arc::clone(&bot);

    ctrlc::set_handler(move || {
        info!("👋 Received Ctrl+C, shutting down...");
        std::process::exit(0);
    })?;

    info!("🏃 Running bot...");
    bot_clone.run().await?;

    Ok(())
} thank you make sure it all works this time