diff --git a/examples/complete_trading_example.rs b/examples/complete_trading_example.rs deleted file mode 100644 index 26fdd03..0000000 --- a/examples/complete_trading_example.rs +++ /dev/null @@ -1,196 +0,0 @@ -use polyfill_rs::{ - ClobClient, OrderArgs, Side, OrderType, OpenOrderParams, TradeParams, - BatchMidpointRequest, BatchPriceRequest, NotificationParams, - PolyfillError, Result, -}; -use rust_decimal::Decimal; -use std::str::FromStr; - -/// Complete example showing all trading functionality -/// -/// This demonstrates the full API parity with the original polymarket-rs-client, -/// plus all our performance optimizations and additional features. -#[tokio::main] -async fn main() -> Result<()> { - // Initialize the client with authentication - let private_key = std::env::var("PRIVATE_KEY") - .expect("PRIVATE_KEY environment variable required"); - let chain_id = 137; // Polygon - - println!("Initializing Polyfill-rs Trading Client"); - - // Step 1: Create client with L1 authentication (private key) - let mut client = ClobClient::with_l1_headers( - "https://clob.polymarket.com", - &private_key, - chain_id, - )?; - - println!("Client initialized with L1 authentication"); - - // Step 2: Create or derive API credentials for L2 operations - println!("Setting up API credentials..."); - let api_creds = client.create_or_derive_api_key(None).await?; - client.set_api_creds(api_creds); - - println!("API credentials configured"); - - // Step 3: Get account information - println!("\nChecking account balances..."); - let balances = client.balance_allowance().await?; - for balance in &balances { - println!(" Token {}: Balance = {}, Allowance = {}", - balance.asset_id, balance.balance, balance.allowance); - } - - // Step 4: Get market data - println!("\nFetching market data..."); - let token_id = "21742633143463906290569050155826241533067272736897614950488156847949938836455"; - - // Single token data - let order_book = client.get_order_book(token_id).await?; - println!(" Order book for {}: {} bids, {} asks", - token_id, order_book.bids.len(), order_book.asks.len()); - - let midpoint = client.get_midpoint(token_id).await?; - println!(" Midpoint: {}", midpoint.mid); - - // Batch operations (much more efficient for multiple tokens) - let token_ids = vec![token_id.to_string()]; - let batch_midpoints = client.get_midpoints(token_ids.clone()).await?; - println!(" Batch midpoints: {:?}", batch_midpoints.midpoints); - - let batch_prices = client.get_prices(token_ids).await?; - for price in &batch_prices.prices { - println!(" Token {}: Bid={:?}, Ask={:?}, Mid={:?}", - price.token_id, price.bid, price.ask, price.mid); - } - - // Step 5: Create and place orders - println!("\nCreating orders..."); - - // Create a limit order - let order_args = OrderArgs { - token_id: token_id.to_string(), - price: Decimal::from_str("0.52")?, - size: Decimal::from_str("10.0")?, - side: Side::BUY, - order_type: Some(OrderType::GTC), - expiration: None, - neg_risk: Some(false), - client_id: Some("example_order_1".to_string()), - }; - - println!(" Creating limit order: Buy 10 @ 0.52"); - let order_result = client.create_and_post_order(&order_args).await?; - println!(" Order created: {:?}", order_result); - - // Create a market order - let market_order_args = OrderArgs { - token_id: token_id.to_string(), - price: Decimal::ZERO, // Will be calculated automatically - size: Decimal::from_str("5.0")?, - side: Side::SELL, - order_type: Some(OrderType::FOK), - expiration: None, - neg_risk: Some(false), - client_id: Some("example_market_order_1".to_string()), - }; - - println!(" Creating market order: Sell 5 @ market"); - let market_order_result = client.create_market_order(&market_order_args).await?; - println!(" Market order created: {:?}", market_order_result); - - // Step 6: Query order history - println!("\nChecking order history..."); - - // Get all open orders - let open_orders = client.get_orders(None).await?; - println!(" Open orders: {}", open_orders.len()); - for order in &open_orders { - println!(" Order {}: {} {} @ {} (Status: {})", - order.id, order.side, order.original_size, order.price, order.status); - } - - // Get orders for specific token - let token_orders = client.get_orders(Some(OpenOrderParams { - id: None, - asset_id: Some(token_id.to_string()), - market: None, - })).await?; - println!(" Orders for token {}: {}", token_id, token_orders.len()); - - // Step 7: Query trade history - println!("\nChecking trade history..."); - - let trades = client.get_trades(Some(TradeParams { - id: None, - maker_address: None, - market: None, - asset_id: Some(token_id.to_string()), - before: None, - after: Some(1640995200), // January 1, 2022 - })).await?; - - println!(" Recent trades: {}", trades.len()); - for trade in trades.iter().take(5) { - println!(" Trade {}: {} {} @ {} (Fee: {})", - trade.id, trade.side, trade.size, trade.price, trade.fee); - } - - // Step 8: Order management - println!("\nOrder management..."); - - if !open_orders.is_empty() { - let order_to_cancel = &open_orders[0]; - println!(" Cancelling order: {}", order_to_cancel.id); - - let cancel_result = client.cancel(&order_to_cancel.id).await?; - println!(" Cancel result: {:?}", cancel_result); - } - - // Step 9: Set up notifications (optional) - println!("\nSetting up notifications..."); - - let notification_params = NotificationParams { - signature: "example_signature".to_string(), - timestamp: chrono::Utc::now().timestamp() as u64, - }; - - match client.notifications(notification_params).await { - Ok(result) => println!(" Notifications configured: {:?}", result), - Err(e) => println!(" Notifications setup failed: {}", e), - } - - println!("\nComplete trading example finished!"); - println!("\nPerformance Notes:"); - println!(" • Order book operations use fixed-point math (25x faster)"); - println!(" • Batch operations reduce API calls by up to 90%"); - println!(" • EIP-712 signing ensures maximum security"); - println!(" • Comprehensive error handling with retry logic"); - println!(" • Full API parity with original polymarket-rs-client"); - - Ok(()) -} - -/// Helper function to demonstrate error handling -async fn safe_trading_example() { - match main().await { - Ok(()) => println!("Trading example completed successfully"), - Err(PolyfillError::Auth { message, .. }) => { - eprintln!("Authentication error: {}", message); - eprintln!("Make sure PRIVATE_KEY environment variable is set"); - }, - Err(PolyfillError::Api { status_code, message, .. }) => { - eprintln!("API error ({}): {}", status_code, message); - eprintln!("Check your network connection and API limits"); - }, - Err(PolyfillError::Network { source, .. }) => { - eprintln!("Network error: {}", source); - eprintln!("Retrying with exponential backoff..."); - }, - Err(e) => { - eprintln!("Unexpected error: {}", e); - } - } -} diff --git a/examples/comprehensive_demo.rs b/examples/comprehensive_demo.rs index ba2546a..346bef9 100644 --- a/examples/comprehensive_demo.rs +++ b/examples/comprehensive_demo.rs @@ -158,7 +158,7 @@ impl PolyfillDemo { } // Get sampling markets - match self.client.get_sampling_markets(Some(5)).await { + match self.client.get_sampling_markets(None).await { Ok(markets) => { info!("Found {} markets", markets.data.len()); for market in &markets.data[..std::cmp::min(3, markets.data.len())] { diff --git a/examples/quick_demo.rs b/examples/quick_demo.rs index de9c969..3ffada9 100644 --- a/examples/quick_demo.rs +++ b/examples/quick_demo.rs @@ -98,7 +98,7 @@ async fn test_connectivity(client: &ClobClient) -> Result<()> { /// Get a valid token ID from the markets endpoint async fn get_valid_token_id(client: &ClobClient) -> Result { - let markets = client.get_sampling_markets(Some(10)).await?; + let markets = client.get_sampling_markets(None).await?; if markets.data.is_empty() { return Err(PolyfillError::api(404, "No markets found")); diff --git a/src/decode.rs b/src/decode.rs index 247d048..15a4356 100644 --- a/src/decode.rs +++ b/src/decode.rs @@ -312,14 +312,31 @@ impl Decoder for RawMarketResponse { Ok(Market { condition_id: self.condition_id.clone(), tokens, + rewards: crate::types::Rewards { + rates: None, + min_size: Decimal::ZERO, + max_spread: Decimal::ONE, + event_start_date: None, + event_end_date: None, + in_game_multiplier: None, + reward_epoch: None, + }, + min_incentive_size: None, + max_incentive_spread: None, active: self.active, closed: self.closed, - question: self.question.clone(), + question_id: self.condition_id.clone(), // Use condition_id as fallback + minimum_order_size: self.minimum_order_size, + minimum_tick_size: self.minimum_tick_size, description: self.description.clone(), category: self.category.clone(), end_date_iso: self.end_date_iso.clone(), - minimum_order_size: self.minimum_order_size, - minimum_tick_size: self.minimum_tick_size, + game_start_time: None, + question: self.question.clone(), + market_slug: format!("market-{}", self.condition_id), // Generate a slug + seconds_delay: Decimal::ZERO, + icon: String::new(), + fpmm: String::new(), }) } } diff --git a/src/types.rs b/src/types.rs index 0cba05f..12238da 100644 --- a/src/types.rs +++ b/src/types.rs @@ -574,14 +574,26 @@ impl PostOrder { pub struct Market { pub condition_id: String, pub tokens: [Token; 2], + pub rewards: Rewards, + pub min_incentive_size: Option, + pub max_incentive_spread: Option, pub active: bool, pub closed: bool, - pub question: String, + pub question_id: String, + #[serde(with = "rust_decimal::serde::str")] + pub minimum_order_size: Decimal, + #[serde(with = "rust_decimal::serde::str")] + pub minimum_tick_size: Decimal, pub description: String, pub category: Option, pub end_date_iso: Option, - pub minimum_order_size: Decimal, - pub minimum_tick_size: Decimal, + pub game_start_time: Option, + pub question: String, + pub market_slug: String, + #[serde(with = "rust_decimal::serde::str")] + pub seconds_delay: Decimal, + pub icon: String, + pub fpmm: String, } /// Token information within a market @@ -1044,7 +1056,7 @@ pub struct SimplifiedMarket { } /// Rewards structure for markets -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct Rewards { pub rates: Option, #[serde(with = "rust_decimal::serde::str")] diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 72f0924..19f1f8c 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -212,7 +212,7 @@ async fn test_all_market_data_endpoints() -> Result<()> { let client = ClobClient::new(POLYMARKET_HOST); // Get a valid token ID first - let markets_response = client.get_sampling_markets(Some(5)).await?; + let markets_response = client.get_sampling_markets(None).await?; assert!(!markets_response.data.is_empty(), "No markets returned"); let first_market = &markets_response.data[0]; @@ -273,7 +273,7 @@ async fn test_data_consistency() -> Result<()> { let client = ClobClient::new(POLYMARKET_HOST); // Get a valid token ID - let markets_response = client.get_sampling_markets(Some(5)).await?; + let markets_response = client.get_sampling_markets(None).await?; let first_market = &markets_response.data[0]; let token_id = &first_market.tokens[0].token_id; @@ -433,7 +433,7 @@ async fn test_concurrent_requests() -> Result<()> { println!("Testing concurrent requests..."); // Get a valid token ID - let markets_response = client.get_sampling_markets(Some(5)).await?; + let markets_response = client.get_sampling_markets(None).await?; let token_id = &markets_response.data[0].tokens[0].token_id; // Make concurrent requests