Compiling solana_rust_bot v0.1.0 (C:\solana_rust_bot)
warning: unused import: `cmp::min`
 --> src/main.rs:8:5
  |
8 |     cmp::min,
  |     ^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

warning: unused import: `tungstenite::protocol::Message`
  --> src/main.rs:18:40
   |
18 | use tokio_tungstenite::{connect_async, tungstenite::protocol::Message};
   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0728]: `await` is only allowed inside `async` functions and blocks
   --> src/main.rs:234:59
    |
233 |             "active_trades": self.active_trades.iter().map(|trade| {
    |                                                            ------- this is not `async`
234 |                 let last_price = *trade.last_price.lock().await;
    |                                                           ^^^^^ only allowed inside `async` functions and blocks

warning: unused variable: `liquidity`
   --> src/main.rs:178:33
    |
178 | ...                   Ok((liquidity, current_price)) => {
    |                           ^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_liquidity`
    |
    = note: `#[warn(unused_variables)]` on by default

warning: unused variable: `ws_stream`
   --> src/main.rs:223:17
    |
223 |         let mut ws_stream = connect_async(ws_url).await?.0;
    |                 ^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_ws_stream`

warning: variable does not need to be mutable
   --> src/main.rs:223:13
    |
223 |         let mut ws_stream = connect_async(ws_url).await?.0;
    |             ----^^^^^^^^^
    |             |
    |             help: remove this `mut`
    |
    = note: `#[warn(unused_mut)]` on by default

error[E0521]: borrowed data escapes outside of method
   --> src/main.rs:214:24
    |
212 |     async fn run(&self) -> Result<()> {
    |                  -----
    |                  |
    |                  `self` is a reference that is only valid in the method body
    |                  let's call the lifetime of this reference `'1`
213 |         let monitor_handle = {
214 |             let this = self.clone();
    |                        ^^^^^^^^^^^^
    |                        |
    |                        `self` escapes the method body here
    |                        argument requires that `'1` must outlive `'static`

warning: unused import: `StreamExt`
 --> src/main.rs:3:20
  |
3 | use futures_util::{StreamExt, SinkExt};
  |                    ^^^^^^^^^

warning: unused import: `SinkExt`
 --> src/main.rs:3:31
  |
3 | use futures_util::{StreamExt, SinkExt};
  |                               ^^^^^^^

Some errors have detailed explanations: E0521, E0728.
For more information about an error, try `rustc --explain E0521`.
warning: `solana_rust_bot` (bin "solana_rust_bot") generated 7 warnings
error: could not compile `solana_rust_bot` (bin "solana_rust_bot") due to 2 previous errors; 7 warnings emitted use anyhow::{anyhow, Result};
use dashmap::DashMap;
use futures_util::{StreamExt, SinkExt};
use log::{error, info, warn};
use serde::{Deserialize, Serialize};
use serde_json::{json, Value};
use std::{
    cmp::min,
    path::PathBuf,
    sync::Arc,
    time::{Duration, Instant, SystemTime},
};
use tokio::{
    fs::File,
    io::{AsyncReadExt, AsyncWriteExt},
    sync::{broadcast, Mutex},
};
use tokio_tungstenite::{connect_async, tungstenite::protocol::Message};
use url::Url;

// Configuration Constants
const JUPITER_API: &str = "https://quote-api.jup.ag/v6";
const HELIUS_RPC: &str = "https://marga-e56m84-fast-mainnet.helius-rpc.com";
const WS_URL: &str = "wss://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";

// Trading Parameters
const MIN_SUPPLY: u64 = 900_000_000;
const LIQUIDITY_MIN: f64 = 4.0; // ~1000 USD at 250 USD/SOL
const LIQUIDITY_MAX: f64 = 80.0; // ~20000 USD at 250 USD/SOL
const TRADE_AMOUNT: u64 = 5_000_000;
const MAX_TRADES: usize = 5;

#[derive(Debug, Clone, Serialize, Deserialize)]
struct TradeState {
    token_mint: String,
    entry_price: f64,
    amount: u64,
    timestamp: u64,
    last_price: f64,
    success_count: u32,
    profit_loss: f64,
}

#[derive(Debug, Clone)]
struct ActiveTrade {
    token_mint: String,
    entry_price: f64,
    amount: u64,
    start_time: Instant,
    last_price: Arc<Mutex<f64>>,
    success_count: u32,
    profit_loss: f64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
struct SystemMetrics {
    total_trades: u32,
    successful_trades: u32,
    failed_trades: u32,
    total_profit_loss: f64,
    start_time: u64,
    last_restart: u64,
}

#[derive(Debug)]
struct TradingSystem {
    active_trades: DashMap<String, ActiveTrade>,
    last_prices: DashMap<String, f64>,
    known_tokens: DashMap<String, Instant>,
    metrics: Arc<Mutex<SystemMetrics>>,
    state_file: PathBuf,
    metrics_file: PathBuf,
    shutdown_signal: broadcast::Sender<()>,
}

impl TradingSystem {
    fn new() -> Self {
        let (shutdown_tx, _) = broadcast::channel(1);
        Self {
            active_trades: DashMap::new(),
            last_prices: DashMap::new(),
            known_tokens: DashMap::new(),
            metrics: Arc::new(Mutex::new(SystemMetrics {
                total_trades: 0,
                successful_trades: 0,
                failed_trades: 0,
                total_profit_loss: 0.0,
                start_time: SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs(),
                last_restart: SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs(),
            })),
            state_file: PathBuf::from("trading_state.json"),
            metrics_file: PathBuf::from("system_metrics.json"),
            shutdown_signal: shutdown_tx,
        }
    }

    async fn check_liquidity_and_price(&self, token_mint: &str) -> Result<(f64, f64)> {
        let quote = get_quote(SOL_MINT, token_mint, TRADE_AMOUNT).await?;

        let in_amount = quote["inAmount"].as_str()
            .ok_or_else(|| anyhow!("Invalid input amount"))?
            .parse::<f64>()? / 1e9;

        let out_amount = quote["outAmount"].as_str()
            .ok_or_else(|| anyhow!("Invalid output amount"))?
            .parse::<f64>()?;

        let price = in_amount / out_amount;
        let liquidity = in_amount * price;

        Ok((liquidity, price))
    }

    async fn execute_trade(&self, token_mint: &str, is_buy: bool, amount: u64) -> Result<String> {
        let (input_mint, output_mint) = if is_buy {
            (SOL_MINT, token_mint)
        } else {
            (token_mint, SOL_MINT)
        };

        let quote = get_quote(input_mint, output_mint, amount).await?;
        let swap_data = get_swap_data(quote).await?;
        let signature = send_priority_tx(swap_data).await?;

        Ok(signature)
    }

    async fn validate_new_token(&self, token_data: &Value) -> Result<bool> {
        let token_mint = token_data["mint"].as_str()
            .ok_or_else(|| anyhow!("Invalid mint address"))?;

        info!("🔍 Validating token: {}", token_mint);

        if self.known_tokens.contains_key(token_mint) || self.active_trades.contains_key(token_mint) {
            return Ok(false);
        }

        let mint_data = token_data
            .get("data")
            .and_then(|d| d.get("parsed"))
            .and_then(|p| p.get("info"))
            .ok_or_else(|| anyhow!("Invalid token data structure"))?;

        let supply = mint_data["supply"].as_str()
            .unwrap_or("0")
            .parse::<u64>()?;

        if supply < MIN_SUPPLY {
            self.known_tokens.insert(token_mint.to_string(), Instant::now());
            return Ok(false);
        }

        let (liquidity, price) = self.check_liquidity_and_price(token_mint).await?;

        if !(LIQUIDITY_MIN..=LIQUIDITY_MAX).contains(&liquidity) {
            self.known_tokens.insert(token_mint.to_string(), Instant::now());
            return Ok(false);
        }

        self.last_prices.insert(token_mint.to_string(), price);
        Ok(true)
    }

    async fn monitor_trades(&self) -> Result<()> {
        let mut interval = tokio::time::interval(Duration::from_secs(1));
        let mut shutdown_rx = self.shutdown_signal.subscribe();

        loop {
            tokio::select! {
                _ = interval.tick() => {
                    for trade in self.active_trades.iter() {
                        let token_mint = &trade.token_mint;

                        match self.check_liquidity_and_price(token_mint).await {
                            Ok((liquidity, current_price)) => {
                                if let Ok(mut last_price) = trade.last_price.try_lock() {
                                    *last_price = current_price;
                                }

                                let profit_percent = (current_price - trade.entry_price) / trade.entry_price * 100.0;

                                if profit_percent >= 20.0 {
                                    info!("🎯 Take profit hit for {}: {:.2}%", token_mint, profit_percent);
                                    if let Ok(sig) = self.execute_trade(token_mint, false, trade.amount).await {
                                        info!("💰 Sold for profit - TX: {}", sig);
                                        self.active_trades.remove(token_mint);
                                    }
                                } else if profit_percent <= -5.0 {
                                    warn!("⚠️ Stop loss hit for {}: {:.2}%", token_mint, profit_percent);
                                    if let Ok(sig) = self.execute_trade(token_mint, false, trade.amount).await {
                                        info!("🛑 Stop loss executed - TX: {}", sig);
                                        self.active_trades.remove(token_mint);
                                    }
                                }
                            }
                            Err(e) => warn!("Failed to fetch price for {}: {}", token_mint, e)
                        }
                    }
                }
                _ = shutdown_rx.recv() => {
                    info!("🛑 Received shutdown signal in monitor_trades");
                    break;
                }
            }
        }
        Ok(())
    }

    async fn run(&self) -> Result<()> {
        let monitor_handle = {
            let this = self.clone();
            tokio::spawn(async move {
                if let Err(e) = this.monitor_trades().await {
                    error!("Trade monitor error: {}", e);
                }
            })
        };

        let ws_url = Url::parse(WS_URL)?;
        let mut ws_stream = connect_async(ws_url).await?.0;

        // WebSocket subscription code here...

        monitor_handle.await?;
        Ok(())
    }

    async fn save_full_state(&self) -> Result<()> {
        let state = json!({
            "active_trades": self.active_trades.iter().map(|trade| {
                let last_price = *trade.last_price.lock().await;
                json!({
                    "token_mint": trade.token_mint,
                    "entry_price": trade.entry_price,
                    "amount": trade.amount,
                    "timestamp": SystemTime::now()
                        .duration_since(SystemTime::UNIX_EPOCH)
                        .unwrap()
                        .as_secs(),
                    "last_price": last_price,
                    "success_count": trade.success_count,
                    "profit_loss": trade.profit_loss
                })
            }).collect::<Vec<_>>(),
            
            "known_tokens": self.known_tokens.iter().map(|entry| {
                json!({
                    "mint": entry.key(),
                    "last_seen": entry.value().elapsed().as_secs(),
                    "reason": "pending_validation" 
                })
            }).collect::<Vec<_>>(),
            
            "metrics": {
                "total_trades": self.metrics.lock().await.total_trades,
                "successful_trades": self.metrics.lock().await.successful_trades,
                "failed_trades": self.metrics.lock().await.failed_trades,
                "total_profit_loss": self.metrics.lock().await.total_profit_loss,
                "start_time": self.metrics.lock().await.start_time,
                "last_restart": self.metrics.lock().await.last_restart
            },
            
            "last_prices": self.last_prices.iter().map(|entry| {
                json!({
                    "mint": entry.key(),
                    "price": entry.value(),
                    "last_update": SystemTime::now()
                        .duration_since(SystemTime::UNIX_EPOCH)
                        .unwrap()
                        .as_secs()
                })
            }).collect::<Vec<_>>(),
            
            "system_info": {
                "uptime_seconds": SystemTime::now()
                    .duration_since(SystemTime::UNIX_EPOCH)
                    .unwrap()
                    .as_secs() - self.metrics.lock().await.start_time,
                "active_trades_count": self.active_trades.len(),
                "known_tokens_count": self.known_tokens.len(),
                "tracked_prices_count": self.last_prices.len(),
                "last_save": SystemTime::now()
                    .duration_since(SystemTime::UNIX_EPOCH)
                    .unwrap()
                    .as_secs()
            },
            
            "trading_parameters": {
                "min_supply": MIN_SUPPLY,
                "liquidity_min": LIQUIDITY_MIN,
                "liquidity_max": LIQUIDITY_MAX,
                "trade_amount": TRADE_AMOUNT,
                "max_trades": MAX_TRADES,
                "take_profit": 20.0,
                "stop_loss": -5.0
            }
        });

        let mut file = File::create(&self.state_file).await?;
        file.write_all(serde_json::to_string_pretty(&state)?.as_bytes()).await?;
        
        info!("💾 Detailed system state saved to {}", self.state_file.display());
        Ok(())
    }

    async fn load_full_state(&self) -> Result<()> {
        if self.state_file.exists() {
            let mut file = File::open(&self.state_file).await?;
            let mut contents = String::new();
            file.read_to_string(&mut contents).await?;
            
            let states: Vec<TradeState> = serde_json::from_str(&contents)?;
            
            for state in states {
                let age = SystemTime::now()
                    .duration_since(SystemTime::UNIX_EPOCH)
                    .unwrap()
                    .as_secs() - state.timestamp;
                    
                if age < 3600 {
                    self.active_trades.insert(
                        state.token_mint.clone(),
                        ActiveTrade {
                            token_mint: state.token_mint,
                            entry_price: state.entry_price,
                            amount: state.amount,
                            start_time: Instant::now(),
                            last_price: Arc::new(Mutex::new(state.last_price)),
                            success_count: state.success_count,
                            profit_loss: state.profit_loss,
                        }
                    );
                }
            }
        }

        if self.metrics_file.exists() {
            let mut file = File::open(&self.metrics_file).await?;
            let mut contents = String::new();
            file.read_to_string(&mut contents).await?;
            
            let stored_metrics: SystemMetrics = serde_json::from_str(&contents)?;
            let mut metrics = self.metrics.lock().await;
            *metrics = stored_metrics;
            metrics.last_restart = SystemTime::now()
                .duration_since(SystemTime::UNIX_EPOCH)
                .unwrap()
                .as_secs();
        }
        
        info!("📂 System state restored successfully");
        Ok(())
    }
}

// Helper Functions
async fn get_quote(input_mint: &str, output_mint: &str, amount: u64) -> Result<Value> {
    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> {
    let swap_request = json!({
        "quoteResponse": quote,
        "userPublicKey": WALLET_PUBLIC_KEY,
        "wrapUnwrapSOL": true,
        "computeUnitPriceMicroLamports": 15000,
        "priorityFeeLamports": 15000,
        "asLegacyTransaction": false,
        "maxAccounts": 64
    });

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

    match response.get("swapTransaction") {
        Some(tx) => Ok(tx.as_str()
            .ok_or_else(|| anyhow!("Invalid transaction format"))?
            .to_string()),
        None => Err(anyhow!("No swap transaction in response"))
    }
}

async fn send_priority_tx(swap_data: String) -> Result<String> {
    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?;

    match response.get("result") {
        Some(result) => Ok(result.as_str()
            .ok_or_else(|| anyhow!("Invalid result format"))?
            .to_string()),
        None => Err(anyhow!("No result in response"))
    }
}

#[tokio::main]
async fn main() -> Result<()> {
    env_logger::init();
    info!("🚀 Starting trading system v2.0");

    let system = Arc::new(TradingSystem::new());
    let shutdown_signal = system.shutdown_signal.clone();

    ctrlc::set_handler(move || {
        info!("Received Ctrl+C, initiating graceful shutdown...");
        let _ = shutdown_signal.send(());
    })?;

    system.load_full_state().await?;
    if let Err(e) = system.run().await {
        error!("System error: {}", e);
    }

    info!("👋 Trading system shutdown complete");
    Ok(())
}