ostium-rust-sdk 0.1.0

Rust SDK for interacting with the Ostium trading platform on Arbitrum
Documentation
//! Example demonstrating unsigned transaction generation for frontend integration
//!
//! This example shows how to build unsigned transactions that can be sent to
//! a frontend for signing, without requiring the SDK to have access to private keys.

use alloy_primitives::Address;
use alloy_primitives::U256;
use ostium_rust_sdk::{
    Network, OpenPositionParams, OstiumClient, PositionSide, UnsignedTransactionParams,
};
use rust_decimal::Decimal;
use std::str::FromStr;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize logging
    tracing_subscriber::fmt::init();

    println!("🔧 Unsigned Transaction Example");
    println!("===============================");

    // Create client without a signer (read-only mode)
    let client = OstiumClient::new(Network::Testnet).await?;
    println!("✅ Connected to Ostium testnet (no signer required)");

    // Simulate a trader address (this would come from your frontend)
    let trader_address = Address::from_str("0x742d35Cc6634C0532925a3b8D53A2e1c5Bc2D8db")?;
    println!("👤 Using trader address: {}", trader_address);

    // Example 1: Build unsigned transaction for opening a position
    println!("\n📈 Building unsigned transaction for opening a position...");

    let position_params = OpenPositionParams {
        symbol: "BTC/USD".to_string(),
        side: PositionSide::Long,
        size: Decimal::from(1000),   // $1000 position
        leverage: Decimal::from(10), // 10x leverage
        take_profit: Some(Decimal::from(45000)),
        stop_loss: Some(Decimal::from(35000)),
        slippage_tolerance: Decimal::from(1) / Decimal::from(100), // 1%
    };

    let tx_params = UnsignedTransactionParams {
        from: trader_address,
        include_gas_estimates: true,
        include_nonce: true,
    };

    match client
        .open_position_unsigned(position_params, trader_address, tx_params.clone())
        .await
    {
        Ok(unsigned_tx) => {
            println!("✅ Unsigned transaction built successfully!");
            println!("📋 Transaction Details:");
            println!("   To: {}", unsigned_tx.to);
            println!("   Data length: {} bytes", unsigned_tx.data.len());
            println!("   Value: {} ETH", unsigned_tx.value);
            println!("   Chain ID: {}", unsigned_tx.chain_id);

            if let Some(gas_limit) = unsigned_tx.gas_limit {
                println!("   Estimated gas: {}", gas_limit);
            }
            if let Some(gas_price) = unsigned_tx.gas_price {
                println!(
                    "   Gas price: {} gwei",
                    gas_price / U256::from(1_000_000_000u64)
                );
            }
            if let Some(nonce) = unsigned_tx.nonce {
                println!("   Nonce: {}", nonce);
            }

            // In a real application, you would send this data to the frontend
            let frontend_payload = serde_json::to_string_pretty(&unsigned_tx)?;
            println!("\n📤 JSON payload for frontend:");
            println!("{}", frontend_payload);
        }
        Err(e) => {
            println!("❌ Failed to build unsigned transaction: {}", e);
        }
    }

    // Example 2: Build multiple unsigned transactions (batch operations)
    println!("\n🔄 Building multiple unsigned transactions...");

    // Simulate updating TP/SL for an existing position
    use ostium_rust_sdk::UpdateTPSLParams;

    let update_params = UpdateTPSLParams {
        position_id: format!("{}:0:0", trader_address), // Example position ID
        take_profit: Some(Decimal::from(50000)),
        stop_loss: Some(Decimal::from(30000)),
    };

    match client
        .update_tp_sl_unsigned(update_params, tx_params.clone())
        .await
    {
        Ok(unsigned_txs) => {
            println!(
                "✅ Built {} unsigned transactions for TP/SL update",
                unsigned_txs.len()
            );

            for (i, tx) in unsigned_txs.iter().enumerate() {
                println!("   Transaction {}: {} bytes", i + 1, tx.data.len());
            }

            // In a real application, you could batch these transactions
            let batch_payload = serde_json::to_string_pretty(&unsigned_txs)?;
            println!("\n📤 Batch transactions JSON:");
            println!("{}", batch_payload);
        }
        Err(e) => {
            println!("❌ Failed to build TP/SL update transactions: {}", e);
        }
    }

    // Example 3: Advanced order with different parameters
    println!("\n📊 Building unsigned transaction for limit order...");

    use ostium_rust_sdk::{AdvancedOrderParams, OrderExecutionType};

    let limit_order_params = AdvancedOrderParams {
        symbol: "ETH/USD".to_string(),
        side: PositionSide::Short,
        size: Decimal::from(2000),  // $2000 position
        leverage: Decimal::from(5), // 5x leverage
        order_type: OrderExecutionType::Limit,
        price: Some(Decimal::from(2200)), // Limit price
        take_profit: Some(Decimal::from(2000)),
        stop_loss: Some(Decimal::from(2400)),
        slippage_tolerance: Decimal::from(1) / Decimal::from(100), // 1%
    };

    match client
        .place_advanced_order_unsigned(limit_order_params, trader_address, tx_params)
        .await
    {
        Ok(unsigned_tx) => {
            println!("✅ Limit order unsigned transaction built!");
            println!("   Gas estimate: {:?}", unsigned_tx.gas_limit);

            // Frontend integration example
            println!("\n🌐 Frontend Integration Example:");
            println!("   1. Send this transaction data to your frontend");
            println!("   2. Frontend prompts user to sign with their wallet");
            println!("   3. Frontend broadcasts the signed transaction");
            println!("   4. Monitor transaction status via transaction hash");
        }
        Err(e) => {
            println!("❌ Failed to build limit order transaction: {}", e);
        }
    }

    println!("\n✨ Unsigned transaction example completed!");
    println!("📚 This demonstrates how to build transactions for frontend signing");
    println!("🔐 The SDK never needs access to private keys in this mode");

    Ok(())
}