CAN U WRITE THIS SCRIPT WITHOUT LIMIT ORDERS AND WITHOUT THE USE OF WSOL SINCE I USE PHANTOM WALLET ITS NOT NEEDED AND ALSO MAKE IT JUST USE JUPITER V6 PLEASE TO BUY AND SELL AND PRICE FETCH AND USE MY HELIUS PRIORITY FEE TRANSACTION PLEASE SO INTEGRADE THE METHOD AFTER THIS SCRIPT HERE use std::borrow::Borrow;
use std::sync::Arc;
use std::time::{Instant, Duration};
use futures_util::{StreamExt, SinkExt};
use tokio::sync::{Mutex, mpsc};
use tokio::time::sleep;
use solana_sdk::{
    signature::{Keypair, Signer},
    pubkey::Pubkey,
    transaction::Transaction,
    instruction::{Instruction, AccountMeta},
    system_instruction,
    commitment_config::CommitmentConfig,
};
use solana_client::{
    rpc_client::RpcClient,
    rpc_request::TokenAccountsFilter,
};
use solana_transaction_status::option_serializer::OptionSerializer;
use solana_transaction_status::UiTransactionEncoding;
use spl_token::{
    instruction as token_instruction,
    state::Mint,
};
use spl_associated_token_account::get_associated_token_address;
use anyhow::{Result, Context};
use serde::Deserialize;
use tracing::{info, error, warn};
use std::{
    collections::HashMap,
    str::FromStr,
};
use reqwest::Client;
use tokio_tungstenite::{connect_async, tungstenite::protocol::Message};
use url::Url;
use toml;
use solana_sdk::program_pack::Pack;
use solana_sdk::compute_budget::ComputeBudgetInstruction;

const SERUM_AMM_PROGRAM_ID: &str = "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8";
const RAYDIUM_AMM_PROGRAM_ID: &str = "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8"; // Replace with actual Raydium program ID

#[derive(Deserialize, Clone)]
struct Config {
    rpc: RpcConfig,
    urls: UrlsConfig,
    wallet: WalletConfig,
    api_keys: ApiKeysConfig,
    accounts: AccountsConfig,
    trading: TradingConfig,
    websocket: WebsocketConfig,
}

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

#[derive(Deserialize, Clone)]
struct UrlsConfig {
    ws_url: String,
}

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

#[derive(Deserialize, Clone)]
struct ApiKeysConfig {
    helius_api_key: String,
}

#[derive(Deserialize, Clone)]
struct AccountsConfig {
    wsol_account: String,
    wsol_mint: String,  
}

#[derive(Deserialize, Clone)]
struct TradingConfig {
    min_liquidity: u64,
    max_liquidity: u64,
    snipe_amount: f64,
    profit_target_percent: f64,
    max_retry_attempts: u8,
    stop_loss_percent: f64,
    max_slippage: f64,
    priority_fee: u64,
    min_sol_balance: f64,
    gas_fee_for_sell: u64,
}

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

#[derive(Deserialize, Debug)]
struct HeliusEvent {
    description: String,
    event_type: String,
    source: String,
    #[serde(rename = "tokenAddress")]
    token_address: String,
    #[serde(rename = "poolAddress")]
    pool_address: String,
    timestamp: i64,
    slot: u64,
    signature: String,
}

#[derive(Debug)]
struct TradeOpportunity {
    token_address: String,
    pool_address: String,
}

#[derive(Debug, Clone)]
struct TokenInfo {
    mint_authority: Option<Pubkey>,
    liquidity: u64,
    total_supply: u64,
    decimals: u8,
    price: f64,
}

struct ApiMonitor {
    call_count: u64,
    last_reset: Instant,
}

impl ApiMonitor {
    fn new() -> Self {
        Self {
            call_count: 0,
            last_reset: Instant::now(),
        }
    }

    fn increment(&mut self) {
        self.call_count += 1;
        if self.last_reset.elapsed() >= Duration::from_secs(60) {
            info!("API calls in the last minute: {}", self.call_count);
            self.call_count = 0;
            self.last_reset = Instant::now();
        }
    }
}

struct Bot {
    client: RpcClient,
    solana_client: RpcClient,
    keypair: Keypair,
    config: Config,
    token_cache: HashMap<String, TokenInfo>,
    http_client: Client,
    buy_prices: HashMap<String, f64>,
    api_monitor: Arc<Mutex<ApiMonitor>>,
}

impl Bot {
    fn new(config_path: &str) -> Result<Self> {
        let config_str = std::fs::read_to_string(config_path).context("Failed to read config file")?;
        let config: Config = toml::from_str(&config_str).context("Failed to parse TOML")?;

        info!("Loaded config:");
        info!("  min_liquidity: {}", config.trading.min_liquidity);
        info!("  max_liquidity: {}", config.trading.max_liquidity);
        info!("  snipe_amount: {}", config.trading.snipe_amount);
        info!("  profit_target_percent: {}", config.trading.profit_target_percent);
        info!("  stop_loss_percent: {}", config.trading.stop_loss_percent);
        info!("  max_slippage: {}", config.trading.max_slippage);
        info!("  priority_fee: {}", config.trading.priority_fee);
        info!("  min_sol_balance: {}", config.trading.min_sol_balance);
        info!("  gas_fee_for_sell: {}", config.trading.gas_fee_for_sell);

        let rpc_client = RpcClient::new_with_commitment(&config.rpc.rpc_url, CommitmentConfig::confirmed());
        let solana_client = RpcClient::new_with_commitment(&config.rpc.solana_rpc_url, CommitmentConfig::confirmed());
        let keypair = load_keypair_from_file(&config.wallet.keypair)?;
        let http_client = Client::new();

        Ok(Self {
            client: rpc_client,
            solana_client,
            keypair,
            config,
            token_cache: HashMap::new(),
            http_client,
            buy_prices: HashMap::new(),
            api_monitor: Arc::new(Mutex::new(ApiMonitor::new())),
        })
    }

    async fn run(&mut self) -> Result<()> {
        self.ensure_wsol_balance().await?;
   
        let ws_url = format!("{}?api-key={}", self.config.urls.ws_url, self.config.api_keys.helius_api_key);
        let (ws_stream, _) = connect_async(Url::parse(&ws_url)?).await?;
        let (mut write, read) = ws_stream.split();

        let subscribe_msg = serde_json::json!({
            "jsonrpc": "2.0",
            "id": 1,
            "method": "subscribePoolCreations",
            "params": []
        });
        write.send(Message::Text(subscribe_msg.to_string())).await?;

        let (tx, mut rx) = mpsc::channel(100);
        let tx_clone = tx.clone();

        tokio::spawn(async move {
            let mut read = read.fuse();
            while let Some(message) = read.next().await {
                match message {
                    Ok(msg) => {
                        if let Err(e) = tx.send(msg).await {
                            error!("Failed to send message to channel: {}", e);
                            break;
                        }
                    },
                    Err(e) => {
                        error!("WebSocket error: {}", e);
                        break;
                    }
                }
            }
        });

        tokio::spawn(async move {
            loop {
                sleep(Duration::from_secs(30)).await;
                if let Err(e) = tx_clone.send(Message::Ping(vec![])).await {
                    error!("Failed to send ping: {}", e);
                    break;
                }
            }
        });

        while let Some(msg) = rx.recv().await {
            match msg {
                Message::Text(text) => {
                    info!("Received message: {}", text);
                    let parsed: serde_json::Value = serde_json::from_str(&text)?;
                   
                    if let Some(params) = parsed.get("params") {
                        if let Some(result) = params.get("result") {
                            match serde_json::from_value::<HeliusEvent>(result.clone()) {
                                Ok(helius_event) => {
                                    info!("Parsed Helius event: {:?}", helius_event);
                                    if let Some(opportunity) = self.analyze_event(&helius_event).await? {
                                        self.execute_trade(&opportunity).await?;
                                    }
                                },
                                Err(e) => {
                                    warn!("Failed to parse Helius event: {:?}", e);
                                    continue;
                                }
                            }
                        }
                    }
                },
                Message::Binary(_) => info!("Received binary message"),
                Message::Ping(_) => {
                    write.send(Message::Pong(vec![])).await?;
                },
                Message::Pong(_) => info!("Received pong"),
                Message::Close(_) => {
                    info!("WebSocket closed");
                    break;
                },
                _ => info!("Received other type of message"),
            }
        }

        Ok(())
    }

    async fn analyze_event(&self, event: &HeliusEvent) -> Result<Option<TradeOpportunity>> {
        if event.description.contains("InitializePool") && !event.description.contains("Deposit") {
            let token_info = self.get_token_info(&event.token_address).await?;
       
            if self.is_liquidity_pool_burnt(&event.pool_address, &token_info).await? &&
               self.is_valid_token(&token_info).await? {
                return Ok(Some(TradeOpportunity {
                    token_address: event.token_address.clone(),
                    pool_address: event.pool_address.clone(),
                }));
            }
        }
        Ok(None)
    }

    async fn ensure_wsol_balance(&self) -> Result<()> {
        let wsol_account = Pubkey::from_str(&self.config.accounts.wsol_account)?;
        let balance = self.client.get_token_account_balance(&wsol_account)?;
        let min_wsol_balance = (self.config.trading.min_sol_balance * 1e9) as u64;

        if balance.amount.parse::<u64>()? < min_wsol_balance {
            self.wrap_sol(min_wsol_balance - balance.amount.parse::<u64>()?).await?;
        }

        Ok(())
    }

    async fn wrap_sol(&self, amount: u64) -> Result<()> {
        let wsol_account = Pubkey::from_str(&self.config.accounts.wsol_account)?;

        let instructions = vec![
            system_instruction::transfer(&self.keypair.pubkey(), &wsol_account, amount),
            token_instruction::sync_native(&spl_token::id(), &wsol_account)?,
        ];

        let recent_blockhash = self.client.get_latest_blockhash()?;
        let transaction = Transaction::new_signed_with_payer(
            &instructions,
            Some(&self.keypair.pubkey()),
            &[&self.keypair],
            recent_blockhash,
        );

        self.client.send_and_confirm_transaction(&transaction)?;
        info!("Wrapped {} SOL to WSOL", amount as f64 / 1e9);
        Ok(())
    }

    async fn is_liquidity_pool_burnt(&self, pool_address: &str, token_info: &TokenInfo) -> Result<bool> {
        let pool_pubkey = Pubkey::from_str(pool_address)?;
        let pool_token_account = get_associated_token_address(&pool_pubkey, &Pubkey::from_str(&self.config.accounts.wsol_mint)?);
        let pool_balance = self.client.get_token_account_balance(&pool_token_account)?;
        let liquidity_percentage = pool_balance.ui_amount.unwrap_or(0.0) / token_info.total_supply as f64;
       
        if liquidity_percentage >= 0.99 {
            return Ok(true);
        }
   
        let recent_signatures = self.client.get_signatures_for_address(&pool_pubkey)?;
        for signature in recent_signatures.iter().take(5) {  // Check only the last 5 transactions for efficiency
            let tx = self.client.get_transaction(&signature.signature, UiTransactionEncoding::Json)?;
            if let Some(meta) = tx.transaction.meta {
                if let Some(messages) = meta.log_messages {
                    if messages.iter().any(|msg| msg.contains("Burn")) {
                        return Ok(true);
                    }
                }
            }
        }
        Ok(false)
    }

    async fn is_valid_token(&self, token_info: &TokenInfo) -> Result<bool> {
        if token_info.total_supply < 1_000_000_000 || token_info.total_supply > 1_000_000_000_000_000 {
            return Ok(false);
        }
        
        let token_pubkey = token_info.mint_authority.ok_or_else(|| anyhow::anyhow!("No mint authority"))?;
        let token_accounts = self.client.get_token_accounts_by_owner(&token_pubkey, TokenAccountsFilter::Mint(token_pubkey))?;
        
        let total_supply = token_info.total_supply as f64;
        let mut largest_holder_percentage = 0.0;

        for account in token_accounts {
            let pubkey = Pubkey::from_str(&account.pubkey)?;
            let balance = self.client.get_token_account_balance(&pubkey)?;
            let percentage = balance.ui_amount.unwrap_or(0.0) / total_supply;
            largest_holder_percentage = largest_holder_percentage.max(percentage);
            
            if percentage > 0.1 {
                return Ok(false);
            }
        }

        // Check if the token has a reasonable distribution
        if largest_holder_percentage > 0.5 {
            return Ok(false);
        }

        Ok(true)
    }

    async fn execute_trade(&mut self, opportunity: &TradeOpportunity) -> Result<()> {
        let amount = (self.config.trading.snipe_amount * 1e9) as u64;
        
        // Step 1: Interact with Raydium
        self.interact_with_raydium(&opportunity.token_address, amount).await?;
        
        // Step 2: Create pre-signed orders
        let (take_profit_tx, stop_loss_tx) = self.create_presigned_orders(&opportunity.token_address, amount).await?;
        
        // Step 3: Monitor and potentially execute the pre-signed orders
        self.monitor_and_execute_orders(&opportunity.token_address, take_profit_tx, stop_loss_tx).await?;
        
        Ok(())
    }

    async fn interact_with_raydium(&self, token_address: &str, amount: u64) -> Result<()> {
        let token_pubkey = Pubkey::from_str(token_address)?;
        let user_ata = get_associated_token_address(&self.keypair.pubkey(), &token_pubkey);
        
        // Construct Raydium swap instruction (this is a simplified version)
        let swap_instruction = Instruction::new_with_borsh(
            Pubkey::from_str(RAYDIUM_AMM_PROGRAM_ID)?,
            &amount.to_le_bytes(),
            vec![
                AccountMeta::new(self.keypair.pubkey(), true),
                AccountMeta::new(user_ata, false),
                // Add other necessary accounts for Raydium swap
            ],
        );

        let priority_fee_instruction = self.get_and_apply_priority_fee().await?;
        
        let recent_blockhash = self.client.get_latest_blockhash()?;
        let transaction = Transaction::new_signed_with_payer(
            &[priority_fee_instruction, swap_instruction],
            Some(&self.keypair.pubkey()),
            &[&self.keypair],
            recent_blockhash,
        );

        self.client.send_and_confirm_transaction(&transaction)?;
        info!("Executed Raydium swap for token {}", token_address);
        
        Ok(())
    }

    async fn create_presigned_orders(&self, token_address: &str, amount: u64) -> Result<(Transaction, Transaction)> {
        let token_pubkey = Pubkey::from_str(token_address)?;
        let user_ata = get_associated_token_address(&self.keypair.pubkey(), &token_pubkey);
        
        let take_profit_price = self.calculate_take_profit_price(token_address)?;
        let stop_loss_price = self.calculate_stop_loss_price(token_address)?;
        
        let take_profit_ix = self.create_limit_order_instruction(token_address, amount, take_profit_price, true)?;
        let stop_loss_ix = self.create_limit_order_instruction(token_address, amount, stop_loss_price, false)?;
        
        let recent_blockhash = self.client.get_latest_blockhash()?;
        
        let take_profit_tx = Transaction::new_signed_with_payer(
            &[take_profit_ix],
            Some(&self.keypair.pubkey()),
            &[&self.keypair],
            recent_blockhash,
        );
        
        let stop_loss_tx = Transaction::new_signed_with_payer(
            &[stop_loss_ix],
            Some(&self.keypair.pubkey()),
            &[&self.keypair],
            recent_blockhash,
        );
        
        Ok((take_profit_tx, stop_loss_tx))
    }

    async fn monitor_and_execute_orders(&self, token_address: &str, take_profit_tx: Transaction, stop_loss_tx: Transaction) -> Result<()> {
        let mut interval = tokio::time::interval(Duration::from_secs(10));
        loop {
            interval.tick().await;
            let current_price = self.get_token_price(token_address).await?;
            
            if self.should_execute_take_profit(current_price, token_address)? {
                info!("Executing take profit order for {}", token_address);
                self.client.send_and_confirm_transaction(&take_profit_tx)?;
                break;
            } else if self.should_execute_stop_loss(current_price, token_address)? {
                info!("Executing stop loss order for {}", token_address);
                self.client.send_and_confirm_transaction(&stop_loss_tx)?;
                break;
            }
        }
        Ok(())
    }

    async fn get_and_apply_priority_fee(&self) -> Result<Instruction> {
        let priority_fee = self.get_priority_fee().await?;
        Ok(ComputeBudgetInstruction::set_compute_unit_price(priority_fee))
    }

    async fn get_priority_fee(&self) -> Result<u64> {
        let url = format!("https://rpc.helius.xyz/v0/priority-fee?api-key={}", self.config.api_keys.helius_api_key);
        let response = self.http_client.get(&url).send().await?.json::<serde_json::Value>().await?;
        Ok(response["priorityFee"].as_u64().ok_or_else(|| anyhow::anyhow!("Invalid priority fee"))?)
    }

    fn calculate_take_profit_price(&self, token_address: &str) -> Result<f64> {
        let buy_price = self.buy_prices.get(token_address)
            .ok_or_else(|| anyhow::anyhow!("Buy price not found for token"))?;
        Ok(buy_price * (1.0 + self.config.trading.profit_target_percent / 100.0))
    }

    fn calculate_stop_loss_price(&self, token_address: &str) -> Result<f64> {
        let buy_price = self.buy_prices.get(token_address)
            .ok_or_else(|| anyhow::anyhow!("Buy price not found for token"))?;
        Ok(buy_price * (1.0 - self.config.trading.stop_loss_percent / 100.0))
    }

    fn create_limit_order_instruction(&self, token_address: &str, amount: u64, price: f64, is_buy: bool) -> Result<Instruction> {
        // This is a placeholder. You'll need to implement the actual limit order creation logic
        // based on the DEX you're using (e.g., Serum, Raydium, etc.)
        unimplemented!("Limit order creation not yet implemented")
    }

    fn should_execute_take_profit(&self, current_price: f64, token_address: &str) -> Result<bool> {
        let take_profit_price = self.calculate_take_profit_price(token_address)?;
        Ok(current_price >= take_profit_price)
    }

    fn should_execute_stop_loss(&self, current_price: f64, token_address: &str) -> Result<bool> {
        let stop_loss_price = self.calculate_stop_loss_price(token_address)?;
        Ok(current_price <= stop_loss_price)
    }

    async fn get_token_price(&self, token_address: &str) -> Result<f64> {
        // Implement your price fetching logic here. This could involve querying a DEX, 
        // using an oracle, or calculating based on pool ratios.
        unimplemented!("Token price fetching not yet implemented")
    }
}

impl Clone for Bot {
    fn clone(&self) -> Self {
        Self {
            client: RpcClient::new(self.client.url()),
            solana_client: RpcClient::new(self.solana_client.url()),
            keypair: Keypair::from_bytes(&self.keypair.to_bytes()).unwrap(),
            config: self.config.clone(),
            token_cache: self.token_cache.clone(),
            http_client: self.http_client.clone(),
            buy_prices: self.buy_prices.clone(),
            api_monitor: self.api_monitor.clone(),
        }
    }
}

#[tokio::main]
async fn main() -> Result<()> {
    tracing_subscriber::fmt::init();
    let mut bot = Bot::new("config.toml")?;
    info!("Bot initialized with keypair: {:?}", bot.keypair.pubkey());
   
    let (tx, mut rx) = mpsc::channel(1);
    ctrlc::set_handler(move || {
        let _ = tx.try_send(());
    }).expect("Error setting Ctrl-C handler");

    tokio::select! {
        result = bot.run() => {
            if let Err(e) = result {
                error!("Bot error: {}", e);
            }
        }
        _ = rx.recv() => {
            info!("Received shutdown signal. Gracefully shutting down...");
        }
    }

    info!("Bot has shut down.");
    Ok(())
}

fn load_keypair_from_file(keypair_str: &str) -> Result<Keypair> {
    let keypair_bytes: Vec<u8> = keypair_str
        .trim_matches(|c| c == '[' || c == ']')
        .split(',')
        .map(|s| s.trim().parse::<u8>())
        .collect::<std::result::Result<Vec<u8>, _>>()?;
   
    Ok(Keypair::from_bytes(&keypair_bytes)?)
}use serde_json::{json, Value};
use std::time::Instant;

const JUPITER_API: &str = "https://quote-api.jup.ag/v6";
const HELIUS_RPC: &str = "https://marga-e56m84-fast-mainnet.helius-rpc.com";
const WALLET_PUBLIC_KEY: &str = "EHrpEhiBU13CygunXsmeGnzR6ircuYFQcFYPZT5BWUMA";
const HELIUS_API_KEY: &str = "1ea5843b-9daa-4926-a97a-be021922da2f";
const SOL_MINT: &str = "So11111111111111111111111111111111111111112";
const BONK_MINT: &str = "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263";

async fn get_quote(input_mint: &str, output_mint: &str, amount: u64) -> Result<Value, Box<dyn std::error::Error>> {
    let url = format!(
        "{}/quote?inputMint={}&outputMint={}&amount={}&slippageBps=50&onlyDirectRoutes=true&wrapUnwrapSOL=true",
        JUPITER_API, input_mint, output_mint, amount
    );
    
    let response = reqwest::get(&url)
        .await?
        .json::<Value>()
        .await?;
    
    Ok(response)
}

async fn get_swap_data(quote: Value) -> Result<String, Box<dyn std::error::Error>> {
    let swap_request = json!({
        "quoteResponse": quote,  // Change back to quoteResponse
        "userPublicKey": WALLET_PUBLIC_KEY,
        "wrapUnwrapSOL": true,
        "computeUnitPriceMicroLamports": 15000,
        "priorityFeeLamports": 15000,
        "asLegacyTransaction": false,
        "maxAccounts": 64
    });

    // Print what we're sending
    println!("Sending to Jupiter: {:?}", swap_request);

    let response = reqwest::Client::new()
        .post(format!("{}/swap", JUPITER_API))
        .json(&swap_request)
        .send()
        .await?
        .json::<Value>()
        .await?;

    println!("Swap Response: {:?}", response);

    match response.get("swapTransaction") {
        Some(tx) => tx.as_str()
            .ok_or_else(|| "Invalid transaction format".into())
            .map(String::from),
        None => {
            println!("Full Jupiter Response: {:?}", response);
            Err("No swap transaction in response".into())
        }
    }
}

async fn send_priority_tx(swap_data: String) -> Result<String, Box<dyn std::error::Error>> {
    let helius_request = json!({
        "jsonrpc": "2.0",
        "id": "helius-priority",
        "method": "sendTransaction",
        "params": [
            swap_data,
            {
                "encoding": "base64",
                "maxRetries": 0,
                "skipPreflight": true,
                "preflightCommitment": "processed",
                "priorityFee": 15000
            }
        ]
    });

    let response = reqwest::Client::new()
        .post(HELIUS_RPC)
        .header("Authorization", format!("Bearer {}", HELIUS_API_KEY))
        .json(&helius_request)
        .send()
        .await?
        .json::<Value>()
        .await?;

    println!("Response: {:?}", response);

    match response.get("result") {
        Some(result) => Ok(result.as_str().unwrap_or_default().to_string()),
        None => {
            if let Some(error) = response.get("error") {
                Err(format!("Helius error: {:?}", error).into())
            } else {
                Err("Unexpected response format".into())
            }
        }
    }
}

async fn execute_trade(is_buy: bool, amount: u64) -> Result<String, Box<dyn std::error::Error>> {
    let start = Instant::now();
    let trade_type = if is_buy { "BUY" } else { "SELL" };
    
    let (input_mint, output_mint) = if is_buy {
        (SOL_MINT, BONK_MINT)  // Direct SOL -> BONK
    } else {
        (BONK_MINT, SOL_MINT)  // Direct BONK -> SOL
    };

    println!("🚀 Getting quote for {trade_type}...");
    let quote_start = Instant::now();
    let quote = get_quote(input_mint, output_mint, amount).await?;
    println!("⚡ Quote fetched in: {:?}", quote_start.elapsed());
    
    println!("🔄 Building atomic swap transaction...");
    let swap_start = Instant::now();
    let swap_data = get_swap_data(quote).await?;
    println!("⚡ Swap built in: {:?}", swap_start.elapsed());
    
    println!("💨 Sending priority transaction...");
    let tx_start = Instant::now();
    let signature = send_priority_tx(swap_data).await?;
    println!("⚡ Transaction sent in: {:?}", tx_start.elapsed());
    
    println!("✨ Total {trade_type} execution time: {:?}", start.elapsed());
    
    Ok(signature)
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("🚀 Starting atomic swap sequence");
    let total_start = Instant::now();
    
    // Direct SOL -> BONK atomic swap
    let buy_signature = execute_trade(true, 5_000_000).await?;
    println!("✅ Buy executed! Signature: {}", buy_signature);

    tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;

    // Direct BONK -> SOL atomic swap
    let sell_signature = execute_trade(false, 5_000_000).await?;
    println!("✅ Sell executed! Signature: {}", sell_signature);

    println!("🏁 Total execution time: {:?}", total_start.elapsed());
    Ok(())
}