please fix this use solana_client::rpc_client::RpcClient;
use solana_sdk::{
    commitment_config::CommitmentConfig,
    pubkey::Pubkey,
    signature::{Keypair, Signer},
    transaction::Transaction,
    instruction::{Instruction, AccountMeta},
    message::Message,
};
use spl_associated_token_account::get_associated_token_address;
use std::{str::FromStr, fs, time::Duration};
use serde::Deserialize;
use log::{info, error};

const RAYDIUM_SWAP_V2: &str = "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8";

#[derive(Deserialize)]
struct Config {
    rpc_url: String,
    keypair_64: String,
    amount_to_trade: f64,
    priority_fee: u64,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize logging
    env_logger::init();

    // Load configuration
    let config: Config = toml::from_str(&fs::read_to_string("config.toml")?)?;

    let client = RpcClient::new_with_commitment(&config.rpc_url, CommitmentConfig::confirmed());

    // Load keypair directly from the 64-byte key
    let keypair_bytes: Vec<u8> = config.keypair_64.split(',')
        .map(|s| s.trim().parse::<u8>().unwrap())
        .collect();
    let keypair = Keypair::from_bytes(&keypair_bytes)?;

    // SOL and USDC mint addresses
    let sol_mint = Pubkey::from_str("So11111111111111111111111111111111111111112")?;
    let usdc_mint = Pubkey::from_str("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v")?;

    // Raydium SOL/USDC pool address
    let pool_address = Pubkey::from_str("58oQChx4yWmvKdwLLZzBi4ChoCc2fqCUWBkwMihLYQo2")?;

    // Check SOL balance
    let sol_balance = client.get_balance(&keypair.pubkey())?;
    info!("SOL balance: {} SOL", sol_balance as f64 / 1e9);

    // Perform buy (SOL to USDC)
    info!("Performing buy (SOL to USDC)...");
    let sol_amount_in = (config.amount_to_trade * 1e9) as u64; // Convert SOL to lamports
    
    if sol_amount_in + 5000 > sol_balance {  // 5000 lamports for fee
        error!("Insufficient SOL balance for trade and fee");
        return Err("Insufficient balance".into());
    }

    match swap(&client, &keypair, &pool_address, &sol_mint, &usdc_mint, sol_amount_in, config.priority_fee) {
        Ok(signature) => info!("Buy transaction signature: {}", signature),
        Err(e) => {
            error!("Buy transaction failed: {}", e);
            return Err(e);
        }
    }

    // Wait a bit before selling
    std::thread::sleep(Duration::from_secs(5));

    // Check USDC balance
    let usdc_account = get_associated_token_address(&keypair.pubkey(), &usdc_mint);
    let usdc_balance = client.get_token_account_balance(&usdc_account)?;
    info!("USDC balance: {} USDC", usdc_balance.amount.parse::<f64>()? / 1e6);

    // Perform sell (USDC to SOL)
    info!("Performing sell (USDC to SOL)...");
    let usdc_amount_in = (usdc_balance.amount.parse::<f64>()? * 0.99 * 1e6) as u64; // Sell 99% of USDC balance
    
    if usdc_amount_in == 0 {
        error!("Insufficient USDC balance for trade");
        return Err("Insufficient USDC balance".into());
    }

    match swap(&client, &keypair, &pool_address, &usdc_mint, &sol_mint, usdc_amount_in, config.priority_fee) {
        Ok(signature) => info!("Sell transaction signature: {}", signature),
        Err(e) => {
            error!("Sell transaction failed: {}", e);
            return Err(e);
        }
    }

    Ok(())
}

fn swap(
    client: &RpcClient,
    keypair: &Keypair,
    pool_address: &Pubkey,
    token_in_mint: &Pubkey,
    token_out_mint: &Pubkey,
    amount_in: u64,
    priority_fee: u64,
) -> Result<String, Box<dyn std::error::Error>> {
    let raydium_program_id = Pubkey::from_str(RAYDIUM_SWAP_V2)?;

    // Get associated token accounts
    let token_in_account = get_associated_token_address(&keypair.pubkey(), token_in_mint);
    let token_out_account = get_associated_token_address(&keypair.pubkey(), token_out_mint);

        // Fetch pool info
        let pool_info = client.get_account(pool_address)?;
        let pool_data: Vec<u8> = pool_info.data.clone();
    
        // Extract necessary pubkeys from pool data
        let amm_authority = Pubkey::new(&pool_data[8..40]);
        let amm_open_orders = Pubkey::new(&pool_data[40..72]);
        let amm_target_orders = Pubkey::new(&pool_data[72..104]);
        let pool_coin_token_account = Pubkey::new(&pool_data[104..136]);
        let pool_pc_token_account = Pubkey::new(&pool_data[136..168]);
        let serum_program_id = Pubkey::new(&pool_data[168..200]);
        let serum_market = Pubkey::new(&pool_data[200..232]);
        let serum_bids = Pubkey::new(&pool_data[232..264]);
        let serum_asks = Pubkey::new(&pool_data[264..296]);
        let serum_event_queue = Pubkey::new(&pool_data[296..328]);
        let serum_coin_vault_account = Pubkey::new(&pool_data[328..360]);
        let serum_pc_vault_account = Pubkey::new(&pool_data[360..392]);
        let serum_vault_signer = Pubkey::new(&pool_data[392..424]);
    
        // Construct instruction data
        let mut instruction_data = vec![2]; // Swap instruction
        instruction_data.extend_from_slice(&amount_in.to_le_bytes());
        instruction_data.extend_from_slice(&0u64.to_le_bytes()); // minimum_amount_out, set to 0 for simplicity
    
        // Construct Raydium swap instruction
        let swap_instruction = Instruction {
            program_id: raydium_program_id,
            accounts: vec![
                AccountMeta::new(*pool_address, false),
                AccountMeta::new_readonly(amm_authority, false),
                AccountMeta::new_readonly(amm_open_orders, false),
                AccountMeta::new_readonly(amm_target_orders, false),
                AccountMeta::new(pool_coin_token_account, false),
                AccountMeta::new(pool_pc_token_account, false),
                AccountMeta::new_readonly(serum_program_id, false),
                AccountMeta::new(serum_market, false),
                AccountMeta::new(serum_bids, false),
                AccountMeta::new(serum_asks, false),
                AccountMeta::new(serum_event_queue, false),
                AccountMeta::new(serum_coin_vault_account, false),
                AccountMeta::new(serum_pc_vault_account, false),
                AccountMeta::new_readonly(serum_vault_signer, false),
                AccountMeta::new(token_in_account, false),
                AccountMeta::new(token_out_account, false),
                AccountMeta::new(keypair.pubkey(), true),
                AccountMeta::new_readonly(spl_token::id(), false),
            ],
            data: instruction_data,
        };
    
        // Create compute budget instruction
        let compute_budget_instruction = solana_sdk::compute_budget::ComputeBudgetInstruction::set_compute_unit_price(priority_fee);
    
        // Combine instructions
        let instructions = vec![compute_budget_instruction, swap_instruction];
    
        // Retry loop
        for attempt in 1..=10 {
            info!("Attempt {} of 10", attempt);
            
            // Get a fresh blockhash
            let recent_blockhash = client.get_latest_blockhash()?;
            
            let message = Message::new(&instructions, Some(&keypair.pubkey()));
            let mut transaction = Transaction::new(&[keypair], message, recent_blockhash);
    
            // Sign and send transaction
            transaction.sign(&[keypair], recent_blockhash);
            
            match client.send_and_confirm_transaction_with_spinner_and_commitment(&transaction, CommitmentConfig::confirmed()) {
                Ok(signature) => return Ok(signature.to_string()),
                Err(e) => {
                    if e.to_string().contains("BlockhashNotFound") || e.to_string().contains("Blockhash not found") {
                        error!("Blockhash not found, retrying...");
                        std::thread::sleep(Duration::from_secs(1));
                        continue;
                    } else {
                        error!("Transaction error: {}", e);
                        return Err(e.into());
                    }
                }
            }
        }
    
        Err("Failed to send transaction after multiple attempts".into())
    }