use ostium_rust_sdk::{
ClosePositionParams, Network, OpenPositionParams, OstiumClient, PositionSide, Result,
UpdateTPSLParams,
};
use rust_decimal_macros::dec;
use std::env;
#[tokio::main]
async fn main() -> Result<()> {
tracing_subscriber::fmt::init();
println!("🚀 Ostium Rust SDK - Trading Example (MAINNET)");
println!("===============================================");
println!("⚠️ WARNING: This example uses MAINNET with REAL MONEY!");
println!(" Only proceed if you understand the risks involved.");
let private_key = env::var("OSTIUM_PRIVATE_KEY").unwrap_or_else(|_| {
println!("❌ CRITICAL: No OSTIUM_PRIVATE_KEY environment variable found!");
println!(" This example requires a REAL private key for mainnet trading.");
println!(" Set it with: export OSTIUM_PRIVATE_KEY=your_private_key_here");
println!(" ⚠️ WARNING: This will use REAL MONEY on mainnet!");
println!(" Exiting to prevent accidental transactions with dummy key...");
std::process::exit(1);
});
println!("\n📡 Connecting to Ostium mainnet with signer...");
let client = OstiumClient::builder(Network::Mainnet)
.with_private_key(&private_key)?
.build()
.await?;
println!("✅ Connected to network: {:?}", client.config().network);
println!("🔗 RPC URL: {}", client.config().rpc_url);
if let Some(address) = client.signer_address() {
println!("👤 Signer address: {}", address);
} else {
println!("❌ No signer configured");
return Ok(());
}
println!("\n🔍 Checking mainnet trading pairs availability...");
let pairs = client.get_pairs().await?;
let active_pairs: Vec<_> = pairs.iter().filter(|p| p.is_active).collect();
if active_pairs.is_empty() {
println!("⚠️ No active trading pairs found on mainnet.");
println!(" This is unexpected for mainnet - please check network connectivity.");
println!(" Available pairs:");
for (i, pair) in pairs.iter().take(5).enumerate() {
println!(
" {}. {} (Status: {})",
i + 1,
pair.symbol,
if pair.is_active { "Active" } else { "Inactive" }
);
}
} else {
println!("✅ Found {} active trading pairs", active_pairs.len());
for pair in &active_pairs {
println!(" • {}", pair.symbol);
}
}
let test_symbol = if active_pairs.is_empty() {
"BTC/USD".to_string() } else {
active_pairs[0].symbol.clone() };
println!("\n💳 Checking account balance...");
match client.get_balance(None).await {
Ok(balance) => {
println!("✅ Account Balance:");
println!(" • Asset: {}", balance.asset);
println!(" • Available: {}", balance.available);
println!(" • Locked: {}", balance.locked);
println!(" • Total: {}", balance.total);
if balance.total < dec!(100) {
println!("⚠️ Low balance detected. You may need more USDC for trading.");
println!(" Current balance: {} USDC", balance.total);
println!(" Recommended minimum: 100 USDC for safe testing");
}
}
Err(e) => {
println!("⚠️ Failed to fetch balance: {}", e);
}
}
println!("\n📊 Checking current positions...");
match client.get_positions(None).await {
Ok(positions) => {
if positions.is_empty() {
println!("✅ No open positions");
} else {
println!("✅ Found {} open positions:", positions.len());
for position in &positions {
println!(
" • {} {} {} @ ${}",
position.symbol,
match position.side {
PositionSide::Long => "LONG",
PositionSide::Short => "SHORT",
},
position.size,
position.entry_price
);
}
}
}
Err(e) => {
println!("⚠️ Failed to fetch positions: {}", e);
}
}
println!("\n📊 Getting current {} price...", test_symbol);
let current_price = match client.get_price(&test_symbol).await {
Ok(price) => {
println!("✅ Current {} price: ${}", test_symbol, price.mark_price);
price.mark_price
}
Err(e) => {
println!("⚠️ Failed to get price: {}", e);
println!(" Using default price for demonstration");
dec!(50000) }
};
println!(
"\n📈 Example: Opening a long position on {}...",
test_symbol
);
println!("⚠️ WARNING: This will place a REAL trade with REAL money!");
let open_params = OpenPositionParams {
symbol: test_symbol.clone(),
side: PositionSide::Long,
size: dec!(0.001), leverage: dec!(2.0), take_profit: Some(current_price * dec!(1.05)), stop_loss: Some(current_price * dec!(0.95)), slippage_tolerance: dec!(0.02), };
println!("📋 Position Parameters:");
println!(" • Symbol: {}", open_params.symbol);
println!(" • Side: {:?}", open_params.side);
println!(" • Size: {} (VERY SMALL for safety)", open_params.size);
println!(" • Leverage: {}x (Conservative)", open_params.leverage);
println!(
" • Take Profit: ${} (5% gain)",
open_params.take_profit.unwrap_or_default()
);
println!(
" • Stop Loss: ${} (5% loss protection)",
open_params.stop_loss.unwrap_or_default()
);
println!(
" • Slippage Tolerance: {}%",
open_params.slippage_tolerance * dec!(100)
);
match client.open_position(open_params).await {
Ok(tx_hash) => {
println!("✅ Position opened successfully!");
println!(" • Transaction Hash: {}", tx_hash);
let position_id = format!("{}:0:0", client.signer_address().unwrap());
println!("\n🎯 Example: Updating take profit and stop loss...");
let update_params = UpdateTPSLParams {
position_id: position_id.clone(),
take_profit: Some(current_price * dec!(1.08)), stop_loss: Some(current_price * dec!(0.92)), };
println!("📋 Update Parameters:");
println!(" • Position ID: {}", update_params.position_id);
println!(
" • New Take Profit: ${} (8% gain)",
update_params.take_profit.unwrap_or_default()
);
println!(
" • New Stop Loss: ${} (8% loss protection)",
update_params.stop_loss.unwrap_or_default()
);
match client.update_tp_sl(update_params).await {
Ok(tx_hash) => {
println!("✅ TP/SL updated successfully!");
println!(" • Transaction Hash: {}", tx_hash);
}
Err(e) => {
println!("⚠️ Failed to update TP/SL: {}", e);
if e.to_string().contains("execution reverted") {
println!(" This is expected when the position doesn't exist or has already been executed.");
}
}
}
println!("\n🔒 Example: Closing the position...");
let close_params = ClosePositionParams {
position_id,
size: None, slippage_tolerance: dec!(0.02), };
println!("📋 Close Parameters:");
println!(" • Position ID: {}", close_params.position_id);
println!(" • Size: Full position");
println!(" • Slippage Tolerance: 2%");
match client.close_position(close_params).await {
Ok(tx_hash) => {
println!("✅ Position closed successfully!");
println!(" • Transaction Hash: {}", tx_hash);
}
Err(e) => {
println!("⚠️ Failed to close position: {}", e);
if e.to_string().contains("execution reverted") {
println!(" This is expected when the position doesn't exist or has already been executed.");
}
}
}
}
Err(e) => {
println!("⚠️ Failed to open position: {}", e);
if e.to_string().contains("Failed to get pair index") {
println!(" This indicates the trading pair may not be properly configured.");
println!(" Please check if the symbol is correct and the pair is active.");
} else {
println!(" This might be due to:");
println!(" • Insufficient balance");
println!(" • Invalid private key");
println!(" • Network issues");
println!(" • Contract interaction errors");
println!(" • Market conditions");
}
}
}
println!("\n✨ Trading example completed!");
println!("\n📚 CRITICAL SAFETY REMINDERS:");
println!(" 🚨 This example uses MAINNET - REAL MONEY IS INVOLVED!");
println!(" 🚨 Positions opened will be actual trades with real funds");
println!(" 🚨 Always verify your private key and account balance before running");
println!(" 🚨 Start with very small amounts to test functionality");
println!(" 🚨 Keep your private keys secure and never commit them to code");
println!(" 🚨 Monitor your positions actively");
println!(" 🚨 Use appropriate risk management strategies");
println!(" 🚨 Consider market conditions and volatility");
println!(" 🚨 Never risk more than you can afford to lose");
println!("\n🔧 Technical Notes:");
println!(" • Symbol format: Use 'BTC/USD' format - the SDK handles conversion internally");
println!(" • Position sizes are intentionally small for safety");
println!(" • Leverage is kept conservative (2x) for risk management");
println!(" • Stop losses are set to limit potential losses");
println!(" • Always test on testnet first before using mainnet");
Ok(())
}