PLEASE REWRITE THIS WITH THE SPACING ISSUES FIXED PLEASE THATS ALL use dotenv::dotenv;
use {
    anyhow::{anyhow, Result},
    colored::*,
    config::{Config, File as ConfigFile},
    dashmap::DashMap,
    futures_util::{SinkExt, StreamExt},
    log::{error, info, warn, debug},
    serde::{Deserialize, Serialize},
    serde_json::{json, Value},
    solana_client::rpc_client::RpcClient,
    solana_sdk::{
        commitment_config::CommitmentConfig,
        signature::{Keypair, Signer},
    },
    std::{
        fs,
        sync::Arc,
        time::{Duration, Instant},
    },
    tokio::{sync::Mutex, time::interval},
    tokio_tungstenite::{connect_async, tungstenite::protocol::Message as WsMessage},
    url::Url,
    uuid::Uuid,
};

// Constants
const RETRY_DELAY: u64 = 200;
const MAX_RETRIES: u8 = 3;
const RAYDIUM_V4_PROGRAM_ID: &str = "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8";
const OPENBOOK_PROGRAM_ID: &str = "srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX";
const JUPITER_PROGRAM_ID: &str = "JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB";

#[derive(Debug, Clone, Serialize, Deserialize)]
struct TradeState {
    active_trades: Vec<ActiveTrade>,
    last_update: chrono::DateTime<chrono::Utc>,
}

#[derive(Debug, Deserialize, Clone)]
struct BotConfig {
    rpc: RpcConfig,
    wallet: WalletConfig,
    trading: TradingConfig,
    token: TokenRequirements,
    websocket: WebsocketConfig,
    logging: LoggingConfig,
}

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

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

#[derive(Debug, Deserialize, Clone)]
struct TradingConfig {
    snipe_amount: u64,
    max_slippage: f64,
    priority_fee: u64,
    profit_target_percent: f64,
    stop_loss_percent: f64,
    max_concurrent_trades: usize,
    min_liquidity: u64,
}

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

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

#[derive(Debug, Deserialize, Clone)]
struct LoggingConfig {
    show_balances: bool,
    debug_mode: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
struct ActiveTrade {
    token_mint: String,
    entry_price: f64,
    amount: u64,
    start_time: chrono::DateTime<chrono::Utc>,
    last_price: f64,
    buy_attempts: u8,
    sell_attempts: u8,
}
struct Bot {
    config: BotConfig,
    rpc_client: Arc<RpcClient>,
    fallback_rpc: Arc<RpcClient>,
    keypair: Arc<Keypair>,
    active_trades: Arc<DashMap<String, ActiveTrade>>,
    http_client: reqwest::Client,
}

impl Bot {
    async fn new() -> Result<Self> {
        dotenv().ok();
        println!("{}", "\n🚀 INITIALIZING SOLANA SNIPER BOT v2.0".bright_green().bold());

        let settings = Config::builder()
            .add_source(ConfigFile::with_name("config.toml"))
            .build()?;

        let config = Self::load_config(&settings)?;
        
        // Properly formatted RPC URLs with API key
        let primary_rpc_url = format!("{}/?api-key={}", config.rpc.solana_rpc_url, config.rpc.api_key);
        let fallback_rpc_url = format!("{}/?api-key={}", config.rpc.fallback_url, config.rpc.api_key);

        let rpc_client = Arc::new(RpcClient::new_with_commitment(
            primary_rpc_url,
            CommitmentConfig::confirmed(),
        ));

        let fallback_rpc = Arc::new(RpcClient::new_with_commitment(
            fallback_rpc_url,
            CommitmentConfig::confirmed(),
        ));

        let keypair = Arc::new(Self::load_keypair(&config.wallet.keypair_path)?);
        println!("{}", format!("💰 Wallet loaded: {}", keypair.pubkey()).yellow());

        let http_client = reqwest::Client::builder()
            .timeout(Duration::from_secs(10))
            .pool_idle_timeout(Duration::from_secs(30))
            .pool_max_idle_per_host(10)
            .build()?;

        Ok(Self {
            config,
            rpc_client,
            fallback_rpc,
            keypair,
            active_trades: Arc::new(DashMap::new()),
            http_client,
        })
    }

    fn load_config(settings: &Config) -> Result<BotConfig> {
        let solana_rpc_url = std::env::var("SOLANA_RPC_URL").unwrap_or_else(|_| {
            settings.get::<String>("rpc.solana_rpc_url")
                .unwrap_or_else(|_| "https://marga-e56m84-fast-mainnet.helius-rpc.com".to_string())
        });

        let fallback_url = std::env::var("FALLBACK_URL").unwrap_or_else(|_| {
            settings.get::<String>("rpc.fallback_url")
                .unwrap_or_else(|_| "https://rpc.helius.xyz".to_string())
        });

        let ws_url = std::env::var("WS_URL").unwrap_or_else(|_| {
            settings.get::<String>("rpc.ws_url")
                .unwrap_or_else(|_| "wss://marga-e56m84-fast-mainnet.helius-rpc.com".to_string())
        });

        let api_key = std::env::var("API_KEY").unwrap_or_else(|_| {
            settings.get::<String>("rpc.api_key")
                .unwrap_or_else(|_| "1ea5843b-9daa-4926-a97a-be021922da2f".to_string())
        });

        Ok(BotConfig {
            rpc: RpcConfig {
                solana_rpc_url,
                fallback_url,
                ws_url,
                api_key,
            },
            wallet: settings.get::<WalletConfig>("wallet")?,
            trading: settings.get::<TradingConfig>("trading")?,
            token: settings.get::<TokenRequirements>("token")?,
            websocket: settings.get::<WebsocketConfig>("websocket")?,
            logging: settings.get::<LoggingConfig>("logging")?,
        })
    }

    fn load_keypair(keypair_path: &str) -> Result<Keypair> {
        let keypair_bytes: Vec<u8> = fs::read_to_string(keypair_path)?
            .parse::<Value>()?
            .as_array()
            .ok_or_else(|| anyhow!("Invalid keypair format in {}", keypair_path))?
            .iter()
            .map(|x| {
                let value = x.as_u64()
                    .ok_or_else(|| anyhow!("Invalid keypair value"))?;
                if value > 255 {
                    return Err(anyhow!("Invalid keypair byte: {} (must be ≤ 255)", value));
                }
                Ok(value as u8)
            })
            .collect::<Result<Vec<u8>, _>>()?;

        Keypair::from_bytes(&keypair_bytes)
            .map_err(|e| anyhow!("Keypair creation failed: {}", e))
    }

    async fn get_priority_fee(&self, token_mint: &str) -> Result<u64> {
        let url = format!("{}/?api-key={}", self.config.rpc.solana_rpc_url, self.config.rpc.api_key);
        
        let priority_response = self.http_client
            .post(&url)
            .json(&json!({
                "jsonrpc": "2.0",
                "id": "helius-priority",
                "method": "getPriorityFeeEstimate",
                "params": [{
                    "accountKeys": [token_mint, "So11111111111111111111111111111111111111112"],
                    "options": {
                        "includeAllPriorityFeeLevels": true,
                        "priorityLevel": "HIGH"
                    }
                }]
            }))
            .send()
            .await?
            .json::<Value>()
            .await?;

        let recommended_fee = priority_response["result"]["priorityFeeLamports"]
            .as_u64()
            .unwrap_or(self.config.trading.priority_fee);

        let priority_fee = (recommended_fee.max(self.config.trading.priority_fee) as f64 * 1.2) as u64;
        info!("💰 Priority fee set: {} lamports", priority_fee);
        
        Ok(priority_fee)
    }

    async fn get_token_price(&self, token_mint: &str) -> Result<f64> {
        let jupiter_price_url = format!(
            "https://price.jup.ag/v6/price?ids={}&vsToken=SOL",
            token_mint
        );

        let response = self.http_client
            .get(&jupiter_price_url)
            .timeout(Duration::from_secs(5))
            .send()
            .await
            .map_err(|e| anyhow!("🔴 Price request failed: {}", e))?
            .json::<Value>()
            .await
            .map_err(|e| anyhow!("🔴 Price parse failed: {}", e))?;

        let price = response["data"][token_mint]["price"]
            .as_f64()
            .ok_or_else(|| anyhow!("Invalid price format"))?;

        info!("💹 Jupiter price: {}", price);
        Ok(price)
    }
    async fn execute_trade(&self, token_mint: &str, is_buy: bool) -> Result<String> {
        let start = Instant::now();
        let mut retries = 0;

        while retries < MAX_RETRIES {
            let sol_balance = self.rpc_client.get_balance(&self.keypair.pubkey())?;
            
            if is_buy && sol_balance < self.config.trading.snipe_amount {
                return Err(anyhow!("Insufficient SOL balance"));
            }

            let priority_fee = self.get_priority_fee(token_mint).await?;
            let (input_mint, output_mint, amount) = if is_buy {
                ("So11111111111111111111111111111111111111112", token_mint, self.config.trading.snipe_amount)
            } else {
                (token_mint, "So11111111111111111111111111111111111111112",
                 self.config.trading.snipe_amount.saturating_mul(98) / 100)
            };

            match self.execute_swap(input_mint, output_mint, amount, priority_fee).await {
                Ok(signature) => {
                    info!("✨ Trade executed in {:?}", start.elapsed());
                    return Ok(signature);
                }
                Err(e) => {
                    retries += 1;
                    if retries == MAX_RETRIES {
                        return Err(anyhow!("Trade failed after {} retries: {}", MAX_RETRIES, e));
                    }
                    tokio::time::sleep(Duration::from_millis(RETRY_DELAY)).await;
                }
            }
        }
        
        Err(anyhow!("Trade execution failed"))
    }

    async fn execute_swap(&self, input_mint: &str, output_mint: &str, amount: u64, priority_fee: u64) -> Result<String> {
        let quote = self.get_quote(input_mint, output_mint, amount).await?;
        let swap_data = self.build_swap_transaction(&quote, priority_fee).await?;
        let signature = self.send_priority_transaction(swap_data, priority_fee).await?;
    
        let sig_bytes = bs58::decode(&signature).into_vec()?;
        let sig = solana_sdk::signature::Signature::try_from(&sig_bytes[..])?;
        
        if self.rpc_client.confirm_transaction(&sig)? {
            info!("✅ Transaction confirmed: {}", signature);
            Ok(signature)
        } else {
            Err(anyhow!("Transaction failed to confirm"))
        }
    }

    async fn connect_and_handle_messages(self: Arc<Self>) -> Result<()> {
        let mut retry_attempts = 0;
        const MAX_RETRIES: u8 = 5;
        const RETRY_DELAY: u64 = 5;

        loop {
            let ws_url = if retry_attempts % 2 == 0 {
                format!("{}/?api-key={}", self.config.rpc.ws_url, self.config.rpc.api_key)
            } else {
                format!("{}/?api-key={}", self.config.rpc.fallback_url, self.config.rpc.api_key)
            };

            let url = Url::parse(&ws_url)?;
            info!("🔌 Connecting to {}", if retry_attempts % 2 == 0 { "Marga Fast Mainnet" } else { "Fallback RPC" });
            
            match connect_async(&url).await {
                Ok((ws_stream, _)) => {
                    info!("✅ Connected successfully");
                    let (mut write, mut read) = ws_stream.split();

                    let subscribe_msg = json!({
                        "jsonrpc": "2.0",
                        "id": Uuid::new_v4().to_string(),
                        "method": "programSubscribe",
                        "params": [
                            RAYDIUM_V4_PROGRAM_ID,
                            {
                                "encoding": "jsonParsed",
                                "commitment": "confirmed",
                                "filters": [{"dataSize": 82}]
                            }
                        ]
                    });

                    write.send(WsMessage::Text(subscribe_msg.to_string())).await?;
                    info!("🎯 Raydium subscription active");

                    let monitor_bot = self.clone();
                    let monitor_handle = tokio::spawn(async move {
                        monitor_bot.monitor_active_trades().await;
                    });

                    let heartbeat_interval = Duration::from_secs(self.config.websocket.heartbeat_interval);
                    let last_msg_time = Arc::new(Mutex::new(Instant::now()));
                    let last_msg_time_clone = last_msg_time.clone();

                    let heartbeat_handle = tokio::spawn(async move {
                        let mut interval = interval(Duration::from_secs(1));
                        loop {
                            interval.tick().await;
                            if last_msg_time_clone.lock().await.elapsed() > heartbeat_interval {
                                error!("⚡ WebSocket heartbeat timeout");
                                break;
                            }
                        }
                    });

                    while let Some(msg_result) = read.next().await {
                        *last_msg_time.lock().await = Instant::now();

                        match msg_result {
                            Ok(msg) => match msg {
                                WsMessage::Text(text) => {
                                    if let Err(e) = self.process_ws_message(&text).await {
                                        warn!("🔄 Message processing error: {}", e);
                                    }
                                }
                                WsMessage::Ping(_) => {
                                    write.send(WsMessage::Pong(vec![])).await?;
                                }
                                WsMessage::Close(frame) => {
                                    info!("🔒 WebSocket closed: {:?}", frame);
                                    break;
                                }
                                _ => {}
                            },
                            Err(e) => {
                                error!("⚠️ WebSocket error: {}", e);
                                break;
                            }
                        }
                    }

                    monitor_handle.abort();
                    heartbeat_handle.abort();
                }
                Err(e) => {
                    error!("Connection failed: {}", e);
                    retry_attempts += 1;
                    if retry_attempts >= MAX_RETRIES {
                        return Err(anyhow!("Maximum connection retries reached"));
                    }
                    info!("Retrying in {} seconds... ({}/{})", 
                        RETRY_DELAY, retry_attempts, MAX_RETRIES);
                    tokio::time::sleep(Duration::from_secs(RETRY_DELAY)).await;
                    continue;
                }
            }
        }
    }
    async fn monitor_active_trades(&self) {
        let mut interval = interval(Duration::from_secs(1));
        
        loop {
            interval.tick().await;
            
            for trade in self.active_trades.iter() {
                if let Ok(current_price) = self.get_token_price(&trade.value().token_mint).await {
                    let profit_percent = ((current_price - trade.value().entry_price) / trade.value().entry_price * 100.0).round();
                    
                    let status = if profit_percent >= 0.0 {
                        format!("📈 +{}%", profit_percent).green()
                    } else {
                        format!("📉 {}%", profit_percent).red()
                    };
                    
                    info!("💰 {}: {}", trade.value().token_mint, status);
                    
                    if profit_percent >= self.config.trading.profit_target_percent {
                        info!("🎯 Take profit triggered for {}", trade.value().token_mint);
                        if let Ok(signature) = self.execute_trade(&trade.value().token_mint, false).await {
                            info!("✨ Take profit executed: {}", signature);
                            self.active_trades.remove(&trade.value().token_mint);
                        }
                    } else if profit_percent <= -self.config.trading.stop_loss_percent {
                        warn!("⚠️ Stop loss triggered for {}", trade.value().token_mint);
                        if let Ok(signature) = self.execute_trade(&trade.value().token_mint, false).await {
                            info!("🛑 Stop loss executed: {}", signature);
                            self.active_trades.remove(&trade.value().token_mint);
                        }
                    }
                }
            }
        }
    }
    
        async fn get_quote(&self, input_mint: &str, output_mint: &str, amount: u64) -> Result<Value> {
            let jupiter_quote_url = format!(
                "https://quote-api.jup.ag/v6/quote?inputMint={}&outputMint={}&amount={}&slippageBps={}",
                input_mint,
                output_mint,
                amount,
                (self.config.trading.max_slippage * 100.0) as u64
            );
    
            let quote = self.http_client
                .get(&jupiter_quote_url)
                .send()
                .await?
                .json::<Value>()
                .await?;
    
            Ok(quote)
        }
    
        async fn build_swap_transaction(&self, quote: &Value, priority_fee: u64) -> Result<String> {
            let swap_request = json!({
                "quoteResponse": quote,
                "userPublicKey": self.keypair.pubkey().to_string(),
                "priorityFee": priority_fee,
                "computeUnits": 300000,
                "useSharedAccounts": true
            });
    
            let swap_response = self.http_client
                .post("https://quote-api.jup.ag/v6/swap")
                .json(&swap_request)
                .send()
                .await?
                .json::<Value>()
                .await?;
    
            Ok(swap_response["swapTransaction"].as_str()
                .ok_or_else(|| anyhow!("Missing swap transaction"))?
                .to_string())
        }
    
        async fn process_ws_message(&self, message: &str) -> Result<()> {
            let parsed: Value = serde_json::from_str(message)?;
    
            if let Some(result) = parsed.get("params").and_then(|p| p.get("result")) {
                if let Some(mint) = result["parsed"]["info"]["mint"].as_str() {
                    if result["parsed"]["info"]["owner"] == RAYDIUM_V4_PROGRAM_ID {
                        if let Ok(price) = self.get_token_price(mint).await {
                            info!("🔍 New Raydium token detected: {} at {} SOL", mint, price);
    
                            if self.active_trades.len() < self.config.trading.max_concurrent_trades {
                                if let Ok(signature) = self.execute_trade(mint, true).await {
                                    let trade = ActiveTrade {
                                        token_mint: mint.to_string(),
                                        entry_price: price,
                                        amount: self.config.trading.snipe_amount,
                                        start_time: chrono::Utc::now(),
                                        last_price: price,
                                        buy_attempts: 1,
                                        sell_attempts: 0,
                                    };
    
                                    self.active_trades.insert(mint.to_string(), trade);
                                    info!("✅ Successfully sniped token: {} ({})", mint, signature);
                                }
                            }
                        }
                    }
                }
            }
            Ok(())
        }
    
        async fn run(self: Arc<Self>) -> Result<()> {
            self.connect_and_handle_messages().await
        }
    }
    
    async fn save_state(&self) -> Result<()> {
        let state = TradeState {
            active_trades: self.active_trades.iter().map(|r| r.value().clone()).collect(),
            last_update: chrono::Utc::now(),
        };
    
        let state_json = serde_json::to_string_pretty(&state)?;
        let temp_path = format!("bot_state_{}.tmp", Uuid::new_v4());
        tokio::fs::write(&temp_path, &state_json).await?;
        tokio::fs::rename(&temp_path, "bot_state.json").await?;
        
        info!("💾 State saved successfully");
        Ok(())
    }
    
    async fn load_state(&self) -> Result<()> {
        if let Ok(state_data) = std::fs::read_to_string("bot_state.json") {
            let state: TradeState = serde_json::from_str(&state_data)?;
            for trade in state.active_trades {
                self.active_trades.insert(trade.token_mint.clone(), trade);
            }
            info!("📥 Loaded {} active trades", self.active_trades.len());
        }
        Ok(())
    }
}

#[tokio::main]
async fn main() -> Result<()> {
    env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info"))
        .format(|buf, record| {
            use std::io::Write;
            writeln!(
                buf,
                "{}  {}  {}",
                chrono::Local::now().format("%Y-%m-%d %H:%M:%S").to_string().bright_blue(),
                match record.level() {
                    log::Level::Error => "ERROR".bright_red(),
                    log::Level::Warn => "WARN".bright_yellow(),
                    log::Level::Info => "INFO".bright_green(),
                    _ => "DEBUG".normal(),
                },
                record.args()
            )
        })
        .init();

    let bot = Arc::new(Bot::new().await?);
    
    let (shutdown_tx, mut shutdown_rx) = tokio::sync::broadcast::channel::<()>(1);
    let shutdown_bot = bot.clone();

    let ctrl_c_tx = shutdown_tx.clone();
    tokio::spawn(async move {
        if let Ok(()) = tokio::signal::ctrl_c().await {
            info!("🛑 INITIATING SHUTDOWN SEQUENCE");
            if let Err(e) = shutdown_bot.save_state().await {
                error!("State save error during shutdown: {}", e);
            }
            info!("👋 SHUTDOWN COMPLETE");
            ctrl_c_tx.send(()).ok();
        }
    });

    if let Err(e) = bot.load_state().await {
        warn!("Could not load previous state: {}", e);
    }
    
    info!("🚀 Bot initialized and ready!");

    let run_handle = tokio::spawn({
        let bot = bot.clone();
        async move {
            bot.run().await
        }
    });

    tokio::select! {
        _ = run_handle => {
            info!("Bot execution completed normally");
        }
        _ = shutdown_rx.recv() => {
            info!("Shutdown signal received");
        }
    }

    std::process::exit(0);
}

 FULL SCRIPT PLEASE