use std::time::Duration;
use webull_rs::models::order::{OrderRequest, OrderSide, TimeInForce};
use webull_rs::{WebullClient, WebullError};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = WebullClient::builder()
.with_api_key("your-api-key")
.with_api_secret("your-api-secret")
.with_timeout(Duration::from_secs(30))
.build()?;
println!("Example 1: Handle authentication errors");
match client.login("invalid-username", "invalid-password").await {
Ok(_) => {
println!("Login successful (unexpected)");
}
Err(WebullError::Unauthorized) => {
println!("✓ Correctly handled unauthorized error: Invalid credentials");
}
Err(WebullError::InvalidRequest(msg)) => {
println!("API not yet implemented: {}", msg);
}
Err(e) => {
println!("Other error: {}", e);
}
}
println!("\nExample 2: Handle network errors");
let bad_client = WebullClient::builder()
.with_api_key("your-api-key")
.with_api_secret("your-api-secret")
.with_custom_url("https://invalid-url.example.com")
.with_timeout(Duration::from_secs(5))
.build()?;
match bad_client.login("username", "password").await {
Ok(_) => {
println!("Login successful (unexpected)");
}
Err(WebullError::NetworkError(e)) => {
println!("✓ Correctly handled network error: {}", e);
}
Err(e) => {
println!("Other error: {}", e);
}
}
println!("\nExample 3: Handle API errors");
let invalid_order = OrderRequest::market()
.symbol("AAPL")
.quantity(-1.0)
.side(OrderSide::Buy)
.time_in_force(TimeInForce::Day);
match client.orders().place_order(&invalid_order).await {
Ok(_) => {
println!("Order placed successfully (unexpected)");
}
Err(WebullError::ApiError { code, message }) => {
println!("✓ Correctly handled API error: {} - {}", code, message);
}
Err(WebullError::InvalidRequest(msg)) => {
println!("API not yet implemented: {}", msg);
}
Err(e) => {
println!("Other error: {}", e);
}
}
println!("\nExample 4: Handle rate limit errors");
for i in 1..=5 {
println!("Request {}/5...", i);
match client.market_data().get_quote("AAPL").await {
Ok(_) => {
println!(" Quote retrieved successfully");
}
Err(WebullError::RateLimitExceeded) => {
println!("✓ Correctly handled rate limit error");
let backoff_seconds = 2_u64.pow(i);
println!(" Backing off for {} seconds", backoff_seconds);
tokio::time::sleep(Duration::from_secs(backoff_seconds)).await;
}
Err(WebullError::InvalidRequest(msg)) => {
println!(" API not yet implemented: {}", msg);
}
Err(e) => {
println!(" Other error: {}", e);
}
}
}
println!("\nExample 5: Handle validation errors");
let invalid_symbol_order = OrderRequest::market()
.symbol("")
.quantity(1.0)
.side(OrderSide::Buy)
.time_in_force(TimeInForce::Day);
match client.orders().place_order(&invalid_symbol_order).await {
Ok(_) => {
println!("Order placed successfully (unexpected)");
}
Err(WebullError::SerializationError(msg)) => {
println!("✓ Correctly handled serialization error: {}", msg);
}
Err(WebullError::InvalidRequest(msg)) => {
println!("API not yet implemented: {}", msg);
}
Err(e) => {
println!("Other error: {}", e);
}
}
println!("\nExample 6: Handle token expiration and refresh");
match client.market_data().get_quote("AAPL").await {
Ok(_) => {
println!("Quote retrieved successfully");
}
Err(WebullError::Unauthorized) => {
println!("Token expired, refreshing...");
match client.refresh_token().await {
Ok(_) => {
println!("✓ Token refreshed successfully");
match client.market_data().get_quote("AAPL").await {
Ok(_) => {
println!("✓ Quote retrieved successfully after token refresh");
}
Err(e) => {
println!("Error after token refresh: {}", e);
}
}
}
Err(e) => {
println!("Error refreshing token: {}", e);
}
}
}
Err(WebullError::InvalidRequest(msg)) => {
println!("API not yet implemented: {}", msg);
}
Err(e) => {
println!("Other error: {}", e);
}
}
println!("\nExample 7: Comprehensive error handling with a custom function");
async fn get_quote_with_retry(
client: &WebullClient,
symbol: &str,
max_retries: u32,
) -> Result<(), WebullError> {
let mut retries = 0;
loop {
match client.market_data().get_quote(symbol).await {
Ok(_) => {
println!("Quote retrieved successfully");
return Ok(());
}
Err(WebullError::Unauthorized) => {
println!("Token expired, refreshing...");
client.refresh_token().await?;
println!("Token refreshed, retrying...");
}
Err(WebullError::RateLimitExceeded) => {
retries += 1;
if retries > max_retries {
return Err(WebullError::RateLimitExceeded);
}
let backoff_seconds = 2_u64.pow(retries);
println!(
"Rate limit exceeded, backing off for {} seconds",
backoff_seconds
);
tokio::time::sleep(Duration::from_secs(backoff_seconds)).await;
}
Err(WebullError::NetworkError(e)) => {
retries += 1;
if retries > max_retries {
return Err(WebullError::NetworkError(e));
}
println!("Network error: {}, retrying in 2 seconds", e);
tokio::time::sleep(Duration::from_secs(2)).await;
}
Err(e) => {
return Err(e);
}
}
}
}
match get_quote_with_retry(&client, "AAPL", 3).await {
Ok(_) => {
println!("✓ Successfully retrieved quote with retry logic");
}
Err(e) => {
println!("Failed to retrieve quote after retries: {}", e);
}
}
Ok(())
}