use kraky::{BalanceUpdate, Credentials, ExecutionUpdate, OrderUpdate};
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("\n╔══════════════════════════════════════════════════════════════╗");
println!("║ 🔐 Kraky Authentication Example ║");
println!("╚══════════════════════════════════════════════════════════════╝\n");
println!("═══════════════════════════════════════════════════════════════");
println!(" STEP 1: Creating Credentials");
println!("═══════════════════════════════════════════════════════════════\n");
let api_key =
std::env::var("KRAKEN_API_KEY").unwrap_or_else(|_| "DEMO_API_KEY_NOT_REAL".to_string());
let api_secret = std::env::var("KRAKEN_API_SECRET")
.unwrap_or_else(|_| "DEMO_API_SECRET_NOT_REAL_BASE64".to_string());
let is_demo = api_key.starts_with("DEMO_");
if is_demo {
println!("⚠️ Running in DEMO mode (no real credentials)");
println!(" To use real credentials, set environment variables:");
println!(" export KRAKEN_API_KEY=\"your_api_key\"");
println!(" export KRAKEN_API_SECRET=\"your_base64_secret\"\n");
}
let credentials = Credentials::new(api_key, api_secret);
println!("✅ Credentials created");
println!(
" API Key: {}...",
&credentials.api_key()[..min(20, credentials.api_key().len())]
);
println!("\n═══════════════════════════════════════════════════════════════");
println!(" STEP 2: Generating Authentication Token");
println!("═══════════════════════════════════════════════════════════════\n");
let nonce = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)?
.as_nanos() as u64;
println!("📝 Nonce generated: {}", nonce);
match credentials.generate_token(nonce) {
Ok(token) => {
println!("✅ Token generated successfully");
println!(
" Token (first 40 chars): {}...",
&token[..min(40, token.len())]
);
println!("\n This token would be sent in WebSocket subscription:");
println!(" {{");
println!(" \"method\": \"subscribe\",");
println!(" \"params\": {{");
println!(" \"channel\": \"balances\",");
println!(
" \"token\": \"{}...\"",
&token[..min(20, token.len())]
);
println!(" }}");
println!(" }}");
}
Err(e) => {
println!("❌ Token generation failed: {}", e);
println!("\n Note: Make sure your API secret is valid base64");
}
}
println!("\n═══════════════════════════════════════════════════════════════");
println!(" STEP 3: Private Channel Message Structures");
println!("═══════════════════════════════════════════════════════════════\n");
let balance_json = r#"{
"channel": "balances",
"type": "update",
"data": [{
"BTC": "1.5432",
"USD": "50000.00",
"ETH": "10.25"
}]
}"#;
println!("💰 Balance Update Example:");
match serde_json::from_str::<BalanceUpdate>(balance_json) {
Ok(update) => {
println!(" Channel: {}", update.channel);
println!(" Assets in update: {:?}", update.assets());
if let Some(btc) = update.get_balance("BTC") {
println!(" BTC Balance: {}", btc);
}
if let Some(usd) = update.get_balance("USD") {
println!(" USD Balance: ${}", usd);
}
}
Err(e) => println!(" Parse error: {}", e),
}
let order_json = r#"{
"channel": "orders",
"type": "update",
"data": [{
"order_id": "O12345-ABCDE-FGHIJ",
"symbol": "BTC/USD",
"side": "buy",
"order_type": "limit",
"limit_price": "95000.00",
"order_qty": "0.5",
"filled_qty": "0.25",
"status": "open",
"timestamp": "2024-01-01T00:00:00Z"
}]
}"#;
println!("\n📋 Order Update Example:");
match serde_json::from_str::<OrderUpdate>(order_json) {
Ok(update) => {
println!(" Channel: {}", update.channel);
if let Some(order) = update.data.first() {
println!(" Order ID: {}", order.order_id);
println!(" Pair: {}", order.symbol);
println!(" Side: {}", order.side);
println!(" Type: {}", order.order_type);
println!(" Status: {}", order.status);
println!(" Filled: {}/{}", order.filled_qty, order.order_qty);
}
println!(" Is Open: {}", update.is_open());
}
Err(e) => println!(" Parse error: {}", e),
}
let execution_json = r#"{
"channel": "executions",
"type": "update",
"data": [{
"exec_id": "E12345-ABCDE",
"order_id": "O12345-ABCDE-FGHIJ",
"symbol": "BTC/USD",
"side": "buy",
"exec_qty": "0.25",
"exec_price": "95000.00",
"timestamp": "2024-01-01T00:00:00Z",
"liquidity": "taker"
}]
}"#;
println!("\n💥 Execution Update Example:");
match serde_json::from_str::<ExecutionUpdate>(execution_json) {
Ok(update) => {
println!(" Channel: {}", update.channel);
if let Some(exec) = update.data.first() {
println!(" Execution ID: {}", exec.exec_id);
println!(" Order ID: {}", exec.order_id);
println!(" Pair: {}", exec.symbol);
println!(" Side: {}", exec.side);
println!(" Quantity: {} BTC", exec.exec_qty);
println!(" Price: ${}", exec.exec_price);
println!(" Liquidity: {}", exec.liquidity);
}
if let Some(value) = update.total_value() {
println!(" Total Value: ${:.2}", value);
}
}
Err(e) => println!(" Parse error: {}", e),
}
println!("\n╔══════════════════════════════════════════════════════════════╗");
println!("║ 📊 SUMMARY ║");
println!("╠══════════════════════════════════════════════════════════════╣");
println!("║ Authentication Infrastructure: ✅ Complete ║");
println!("║ ║");
println!("║ ✅ HMAC-SHA256 token generation ║");
println!("║ ✅ Credentials management ║");
println!("║ ✅ Balance update parsing ║");
println!("║ ✅ Order update parsing ║");
println!("║ ✅ Execution update parsing ║");
println!("║ ║");
println!("║ 🚧 Coming Soon: ║");
println!("║ - WebSocket subscription integration ║");
println!("║ - Real-time balance monitoring ║");
println!("║ - Order placement via WebSocket ║");
println!("╚══════════════════════════════════════════════════════════════╝\n");
Ok(())
}
fn min(a: usize, b: usize) -> usize {
if a < b {
a
} else {
b
}
}