use pyo3::prelude::*;
use pyo3::wrap_pyfunction;
use tokio::sync::Mutex;
use reqwest::Client as HttpClient;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::{collections::HashMap, sync::Arc, error::Error, 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";

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Trade {
    token_address: String,
    amount: u64,
}

// Trading Bot structure
pub struct Bot {
    http_client: HttpClient,
    active_trades: Arc<Mutex<HashMap<String, Trade>>>,
}

// Function to create a new Bot instance
#[pyfunction]
pub fn new_bot() -> Bot {
    let client = HttpClient::new();
    Bot {
        http_client: client,
        active_trades: Arc::new(Mutex::new(HashMap::new())),
    }
}

// Function to execute a trade
#[pyfunction]
pub async fn execute_trade(bot: &Bot, is_buy: bool, amount: u64, token_address: String) -> PyResult<String> {
    let start = Instant::now();
    let trade_type = if is_buy { "BUY" } else { "SELL" };
    let output_mint = if is_buy { token_address.clone() } else { SOL_MINT.to_string() };

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

    info!("Trade executed! Type: {}, Amount: {}, Signature: {}", trade_type, amount, signature);
    Ok(signature)
}

// Function to get quotes from Jupiter API
async fn get_quote(bot: &Bot, input_mint: &str, output_mint: &str, amount: u64) -> Result<Value, Box<dyn Error>> {
    let url = format!(
        "{}/quote?inputMint={}&outputMint={}&amount={}&slippageBps=50&onlyDirectRoutes=true&wrapUnwrapSOL=true",
        JUPITER_API, input_mint, output_mint, amount
    );

    let response = bot.http_client.get(&url).send().await?.json::<Value>().await?;
    Ok(response)
}

// Function to get swap data for a transaction
async fn get_swap_data(bot: &Bot, quote: Value) -> Result<String, Box<dyn Error>> {
    let swap_request = json!({
        "quoteResponse": quote,
        "userPublicKey": WALLET_PUBLIC_KEY,
        "wrapUnwrapSOL": true,
        "computeUnitPriceMicroLamports": 15000,
        "priorityFeeLamports": 15000,
        "asLegacyTransaction": false,
        "maxAccounts": 64
    });

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

    match response.get("swapTransaction") {
        Some(tx) => tx.as_str().map(|s| s.to_string()).ok_or_else(|| "Invalid transaction format".into()),
        None => Err("No swap transaction in response".into()),
    }
}

// Function to send the transaction to Helius
async fn send_priority_tx(bot: &Bot, swap_data: String) -> Result<String, Box<dyn 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 = bot.http_client
        .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().unwrap_or_default().to_string()),
        None => Err("Unexpected response format".into()),
    }
}

// Python module setup
#[pymodule]
fn trading_bot(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_function(wrap_pyfunction!(new_bot, m)?)?;
    m.add_function(wrap_pyfunction!(execute_trade, m)?)?;
    Ok(())
}

Step 2: Python GUI with Enhanced Features

This Python GUI will allow users to execute trades interactively, receive updates, and will also include robust error handling and logging.
Python GUI Code (main.py)

import sys
import asyncio
from PyQt6 import QtWidgets, QtCore
from dotenv import load_dotenv
from trading_bot import new_bot, execute_trade

# Load environment variables
load_dotenv()

class TradingSystemGUI(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Trading System Control Panel")
        self.resize(800, 600)

        # Initialize the Rust Bot
        self.bot = new_bot()

        # Widgets
        self.token_input = QtWidgets.QLineEdit()
        self.amount_input = QtWidgets.QSpinBox()
        self.output_text = QtWidgets.QTextEdit()
        self.output_text.setReadOnly(True)

        self.execute_trade_button = QtWidgets.QPushButton("Execute Trade")
        self.buy_radio = QtWidgets.QRadioButton("Buy")
        self.sell_radio = QtWidgets.QRadioButton("Sell")
        self.buy_radio.setChecked(True)  # Default to buy

        # Connect signals
        self.execute_trade_button.clicked.connect(self.execute_trade)

        # Layout setup
        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(QtWidgets.QLabel("Token Address:"))
        layout.addWidget(self.token_input)
        layout.addWidget(QtWidgets.QLabel("Amount:"))
        layout.addWidget(self.amount_input)
        layout.addWidget(self.buy_radio)
        layout.addWidget(self.sell_radio)
        layout.addWidget(self.execute_trade_button)
        layout.addWidget(QtWidgets.QLabel("Output:"))
        layout.addWidget(self.output_text)

        self.setLayout(layout)

    async def execute_trade_async(self):
        token_address = self.token_input.text()
        amount = self.amount_input.value()
        is_buy = self.buy_radio.isChecked()

        try:
            result = await execute_trade(self.bot, is_buy, amount, token_address)
            self.output_text.append(result)
        except Exception as e:
            self.output_text.append(f"Error executing trade: {str(e)}")

    def execute_trade(self):
        asyncio.run(self.execute_trade_async())

def main():
    app = QtWidgets.QApplication(sys.argv)
    window = TradingSystemGUI()
    window.show()
    sys.exit(app.exec())

if __name__ == '__main finish this up and enhance this 10x