// Define a concrete type for try_rpc
fn try_rpc<'a>(&self, operation: Box<dyn Fn(&RpcClient) -> Result<u64, solana_client::client_error::ClientError> + 'a>) -> Result<u64, String> {
    match operation(&self.primary_client) {
        Ok(result) => Ok(result),
        Err(_) => operation(&self.fallback_client).map_err(|e| e.to_string())
    }
}

// Fix get_wallet_balance
fn get_wallet_balance(&self) -> PyResult<f64> {
    let balance = self.try_rpc(Box::new(|client| client.get_balance(&self.keypair.pubkey())))
        .map_err(|e| PyValueError::new_err(e.to_string()))?;
    Ok(balance as f64 / 1e9)
}

// Fix get_token_balance
fn get_token_balance(&self, token_mint: &str) -> PyResult<f64> {
    let token_mint_bytes: [u8; 32] = token_mint.as_bytes().try_into()
        .map_err(|_| PyValueError::new_err("Failed to convert token mint to bytes"))?;
    
    let filter = TokenAccountsFilter::Mint(Pubkey::from(token_mint_bytes));
    
    let accounts = self.try_rpc(Box::new(move |client| 
        client.get_token_accounts_by_owner(&self.keypair.pubkey(), filter)
    )).map_err(|e| PyValueError::new_err(e.to_string()))?;

    // Process accounts here
    Ok(accounts as f64 / 1e9)
} use pyo3::prelude::*;
use pyo3::exceptions::PyValueError;
use solana_client::rpc_client::RpcClient;
use solana_client::rpc_request::TokenAccountsFilter;
use solana_sdk::commitment_config::CommitmentConfig;
use solana_sdk::signature::{Keypair, read_keypair_file, Signer};
use solana_sdk::pubkey::Pubkey;
use std::collections::{HashMap, VecDeque};
use tokio::runtime::Runtime;
use reqwest::header::{HeaderMap, HeaderValue, AUTHORIZATION};
use serde_json::json;
use chrono::{DateTime, Utc};
use std::sync::{Arc, Mutex};
use serde::{Serialize, Deserialize};
use base64::engine::general_purpose::STANDARD as base64_engine;
use base64::Engine;

// Constants with fallback RPCs
const PRIMARY_RPC: &str = "https://marga-e56m84-fast-mainnet.helius-rpc.com";
const FALLBACK_RPC: &str = "https://api.helius.xyz/v0";
const HELIUS_API_KEY: &str = "1ea5843b-9daa-4926-a97a-be021922da2f";
const JUPITER_API_V6: &str = "https://quote-api.jup.ag/v6";
const RAYDIUM_PROGRAM_ID: &str = "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8";
const SOL_USDC_POOL: &str = "EGZ7tiLeH62TPV1gL8WwbXGzEPa9zmcpVnnkPKKnrE2U";
const KEYPAIR_PATH: &str = "C:\\solana_rust_bot\\id.json";

const COMMITMENT: CommitmentConfig = CommitmentConfig::confirmed();

#[derive(Debug, Clone, Serialize, Deserialize)]
struct Position {
    entry_price: f64,
    size: f64,
    timestamp: DateTime<Utc>,
    tx_signature: String,
    pnl: f64,
    status: String,
}

#[pyclass(name = "PyHeliusBot")]
struct PyHeliusBot {
    primary_client: RpcClient,
    fallback_client: RpcClient,
    runtime: Runtime,
    headers: HeaderMap,
    keypair: Keypair,
    positions: Arc<Mutex<VecDeque<Position>>>,
    last_prices: Arc<Mutex<VecDeque<f64>>>,
}

#[pymethods]
impl PyHeliusBot {
    #[new]
    fn new() -> PyResult<Self> {
        let mut headers = HeaderMap::new();
        headers.insert(
            AUTHORIZATION,
            HeaderValue::from_str(&format!("Bearer {}", HELIUS_API_KEY))
                .map_err(|e| PyValueError::new_err(e.to_string()))?
        );

        // Use read_keypair_file directly
        let keypair = Keypair::from_bytes(&std::fs::read(KEYPAIR_PATH)
            .map_err(|e| PyValueError::new_err(format!("Failed to read keypair file: {}", e)))?)
            .map_err(|e| PyValueError::new_err(format!("Failed to create keypair: {}", e)))?;

        let primary_client = RpcClient::new_with_commitment(PRIMARY_RPC.to_string(), COMMITMENT);
        let fallback_client = RpcClient::new_with_commitment(FALLBACK_RPC.to_string(), COMMITMENT);
        let runtime = Runtime::new()
            .map_err(|e| PyValueError::new_err(e.to_string()))?;

        Ok(PyHeliusBot {
            primary_client,
            fallback_client,
            runtime,
            headers,
            keypair,
            positions: Arc::new(Mutex::new(VecDeque::with_capacity(100))),
            last_prices: Arc::new(Mutex::new(VecDeque::with_capacity(1000))),
        })
    }
    fn get_wallet_balance(&self) -> PyResult<f64> {
        let balance = self.try_rpc(|client| client.get_balance(&self.keypair.pubkey()))
            .map_err(|e| PyValueError::new_err(e.to_string()))?;
        Ok(balance as f64 / 1e9)
    }

    fn get_token_balance(&self, token_mint: &str) -> PyResult<f64> {
        let token_mint_bytes: [u8; 32] = token_mint.as_bytes().try_into()
            .map_err(|_| PyValueError::new_err("Failed to convert token mint to bytes"))?;
        
        let filter = TokenAccountsFilter::Mint(Pubkey::from(token_mint_bytes));
        
        let token_accounts = self.try_rpc(|client| 
            client.get_token_accounts_by_owner(&self.keypair.pubkey(), filter)
        ).map_err(|e| PyValueError::new_err(e.to_string()))?;
    
        for account in token_accounts.iter() {
            if account.pubkey.to_string() == token_mint {
                return Ok(account.account.lamports as f64 / 1e9);
            }
        }
        Ok(0.0)
    }
    fn get_pool_price(&self) -> PyResult<f64> {
        let request = json!({
            "jsonrpc": "2.0",
            "id": "price-check",
            "method": "getAccountInfo",
            "params": [
                SOL_USDC_POOL,
                {
                    "encoding": "base64",
                    "commitment": "confirmed"
                }
            ]
        });

        let response = self.runtime.block_on(async {
            let resp = reqwest::Client::new()
                .post(PRIMARY_RPC)
                .headers(self.headers.clone())
                .json(&request)
                .send()
                .await
                .map_err(|e| PyValueError::new_err(e.to_string()))?
                .json::<serde_json::Value>()
                .await
                .map_err(|e| PyValueError::new_err(e.to_string()))?;

            if let Some(data) = resp.get("result").and_then(|r| r.get("data")) {
                if let Some(data_str) = data.get(0).and_then(|d| d.as_str()) {
                    let decoded = base64_engine.decode(data_str)
                        .map_err(|e| PyValueError::new_err(e.to_string()))?;
                    if decoded.len() >= 40 {
                        let sol_reserves = u64::from_le_bytes(decoded[8..16].try_into()
                            .map_err(|_| PyValueError::new_err("Failed to read SOL reserves"))?);
                        let usdc_reserves = u64::from_le_bytes(decoded[16..24].try_into()
                            .map_err(|_| PyValueError::new_err("Failed to read USDC reserves"))?);
                        
                        let price = (usdc_reserves as f64) / (sol_reserves as f64);
                        let mut prices = self.last_prices.lock().unwrap();
                        prices.push_back(price);
                        if prices.len() > 1000 {
                            prices.pop_front();
                        }
                        return Ok(price);
                    }
                }
            }
            Err(PyValueError::new_err("Failed to parse pool data"))
        })?;

        Ok(response)
    }

    // Helper method to try both RPCs
    fn try_rpc(&self, operation: impl Fn(&RpcClient) -> Result<T, solana_client::client_error::ClientError>) -> Result<String, String> {
        match operation(&self.primary_client) {
            Ok(result) => Ok(result.to_string()),
            Err(_) => operation(&self.fallback_client).map(|r| r.to_string()).map_err(|e| e.to_string())
        }
    }

    fn get_jupiter_quote(&self, input_mint: &str, output_mint: &str, amount: u64) -> PyResult<String> {
        let url = format!(
            "{}/quote?inputMint={}&outputMint={}&amount={}&slippageBps=50&onlyDirectRoutes=true&asLegacyTransaction=false",
            JUPITER_API_V6, input_mint, output_mint, amount
        );

        let quote = self.runtime.block_on(async {
            reqwest::get(&url)
                .await
                .map_err(|e| PyValueError::new_err(e.to_string()))?
                .json::<serde_json::Value>()
                .await
                .map_err(|e| PyValueError::new_err(e.to_string()))
        })?;

        Ok(serde_json::to_string(&quote)
            .map_err(|e| PyValueError::new_err(e.to_string()))?)
    }

    fn send_priority_transaction(&self, transaction_data: &str) -> PyResult<String> {
        let request = json!({
            "jsonrpc": "2.0",
            "id": "helius-priority",
            "method": "sendTransaction",
            "params": [
                transaction_data,
                {
                    "encoding": "base64",
                    "maxRetries": 0,
                    "skipPreflight": true,
                    "preflightCommitment": "confirmed",
                    "priorityFee": 15000
                }
            ]
        });

        let response = self.runtime.block_on(async {
            reqwest::Client::new()
                .post(PRIMARY_RPC)
                .headers(self.headers.clone())
                .json(&request)
                .send()
                .await
                .map_err(|e| PyValueError::new_err(e.to_string()))?
                .json::<serde_json::Value>()
                .await
                .map_err(|e| PyValueError::new_err(e.to_string()))
        })?;

        Ok(response["result"].to_string())
    }

    fn open_position(&self, size: f64) -> PyResult<String> {
        let current_price = self.get_pool_price()?;
        let quote = self.get_jupiter_quote(
            "So11111111111111111111111111111111111111112",
            "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
            (size * 1e9) as u64
        )?;

        let tx = self.send_priority_transaction(&quote)?;
        let position = Position {
            entry_price: current_price,
            size,
            timestamp: Utc::now(),
            tx_signature: tx.clone(),
            pnl: 0.0,
            status: "OPEN".to_string(),
        };

        let mut positions = self.positions.lock().unwrap();
        positions.push_back(position);
        Ok(tx)
    }

    fn close_position(&self, position_index: usize) -> PyResult<String> {
        let mut positions = self.positions.lock().unwrap();
        if let Some(position) = positions.get_mut(position_index) {
            let current_price = self.get_pool_price()?;
            let quote = self.get_jupiter_quote(
                "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
                "So11111111111111111111111111111111111111112",
                (position.size * 1e9) as u64
            )?;

            let tx = self.send_priority_transaction(&quote)?;
            position.pnl = (current_price - position.entry_price) * position.size;
            position.status = "CLOSED".to_string();
            Ok(tx)
        } else {
            Err(PyValueError::new_err("Invalid position index"))
        }
    }

    fn get_positions(&self) -> PyResult<String> {
        let positions = self.positions.lock().unwrap();
        let positions_json = serde_json::to_string(&*positions)
            .map_err(|e| PyValueError::new_err(e.to_string()))?;
        Ok(positions_json)
    }

    fn get_market_metrics(&self) -> PyResult<HashMap<String, f64>> {
        let prices = self.last_prices.lock().unwrap();
        let prices_vec: Vec<f64> = prices.iter().cloned().collect();
        let mut metrics = HashMap::new();

        if !prices_vec.is_empty() {
            metrics.insert("current_price".to_string(), *prices_vec.last().unwrap());
            metrics.insert("price_change".to_string(), 
                (prices_vec.last().unwrap() - prices_vec.first().unwrap()) / 
                prices_vec.first().unwrap());

            if prices_vec.len() > 1 {
                let returns: Vec<f64> = prices_vec.windows(2)
                    .map(|w| (w[1] - w[0]) / w[0])
                    .collect();
                let volatility = returns.iter()
                    .map(|r| r * r)
                    .sum::<f64>()
                    .sqrt() * (252.0_f64).sqrt();
                metrics.insert("volatility".to_string(), volatility);
            }
        }

        Ok(metrics)
    }
}

#[pymodule]
fn solana_rust_bot(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_class::<PyHeliusBot>()?;
    Ok(())
} can u fix this please ???? i need the full script though how i have it here just fix the errors please     Compiling solana_rust_bot v0.1.0 (C:\solana_rust_bot)
error: Python functions cannot have `impl Trait` arguments
   --> src\lib.rs:157:34
    |
157 |     fn try_rpc(&self, operation: impl Fn(&RpcClient) -> Result<T, solana_client::client_error::ClientError>) -...
    |                                  ^^^^

error[E0412]: cannot find type `T` in this scope
   --> src\lib.rs:157:64
    |
157 |     fn try_rpc(&self, operation: impl Fn(&RpcClient) -> Result<T, solana_client::client_error::ClientError>) -...
    |                                                                ^ not found in this scope
    |
help: you might be missing a type parameter
    |
51  | impl<T> PyHeliusBot {
    |     +++

warning: unused import: `read_keypair_file`
 --> src\lib.rs:6:38
  |
6 | use solana_sdk::signature::{Keypair, read_keypair_file, Signer};
  |                                      ^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

error[E0605]: non-primitive cast: `std::string::String` as `f64`
  --> src\lib.rs:84:12
   |
84 |         Ok(balance as f64 / 1e9)
   |            ^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object

error[E0599]: no method named `iter` found for struct `std::string::String` in the current scope
  --> src\lib.rs:97:39
   |
97 |         for account in token_accounts.iter() {
   |                                       ^^^^ method not found in `String`
   |
help: because of the in-memory representation of `&str`, to obtain an `Iterator` over each of its codepoint use method `chars`
   |
97 |         for account in token_accounts.chars() {
   |                                       ~~~~~

Some errors have detailed explanations: E0412, E0599, E0605.
For more information about an error, try `rustc --explain E0412`.
warning: `solana_rust_bot` (lib) generated 1 warning
error: could not compile `solana_rust_bot` (lib) due to 4 previous errors; 1 warning emitted
2024-11-14T08:31:06.924477Z  INFO build_wheels: maturin::build_context: close time.busy=572ms time.idle=1.30µs
💥 maturin failed
  Caused by: Failed to build a native library through cargo
  Caused by: Cargo build finished with "exit code: 101": `"cargo" "rustc" "--jobs" "9" "--features" "pyo3/extension-module" "--message-format" "json-render-diagnostics" "--manifest-path" "C:\\solana_rust_bot\\Cargo.toml" "--release" "--lib"`

(pytorch_cuda) C:\solana_rust_bot>