2025-07-24 20:29:10 -04:00
|
|
|
//! Polyfill-rs: High-performance Rust client for Polymarket
|
|
|
|
|
//!
|
|
|
|
|
//! # Features
|
|
|
|
|
//!
|
|
|
|
|
//! - **High-performance order book management** with optimized data structures
|
|
|
|
|
//! - **Real-time market data streaming** with WebSocket support
|
|
|
|
|
//! - **Trade execution simulation** with slippage protection
|
|
|
|
|
//! - **Comprehensive error handling** with specific error types
|
|
|
|
|
//! - **Rate limiting and retry logic** for robust API interactions
|
|
|
|
|
//! - **Ethereum integration** with EIP-712 signing support
|
|
|
|
|
//! - **Benchmarking tools** for performance analysis
|
|
|
|
|
//!
|
|
|
|
|
//! # Quick Start
|
|
|
|
|
//!
|
|
|
|
|
//! ```rust
|
|
|
|
|
//! use polyfill_rs::{ClobClient, OrderArgs, Side};
|
|
|
|
|
//! use rust_decimal::Decimal;
|
|
|
|
|
//!
|
|
|
|
|
//! #[tokio::main]
|
|
|
|
|
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
|
|
|
//! // Create client (compatible with polymarket-rs-client)
|
|
|
|
|
//! let mut client = ClobClient::with_l1_headers(
|
|
|
|
|
//! "https://clob.polymarket.com",
|
|
|
|
|
//! "your_private_key",
|
|
|
|
|
//! 137,
|
|
|
|
|
//! );
|
|
|
|
|
//!
|
|
|
|
|
//! // Get API credentials
|
|
|
|
|
//! let api_creds = client.create_or_derive_api_key(None).await?;
|
|
|
|
|
//! client.set_api_creds(api_creds);
|
|
|
|
|
//!
|
|
|
|
|
//! // Create and post order
|
|
|
|
|
//! let order_args = OrderArgs::new(
|
|
|
|
|
//! "token_id",
|
|
|
|
|
//! Decimal::from_str("0.75")?,
|
|
|
|
|
//! Decimal::from_str("100.0")?,
|
|
|
|
|
//! Side::BUY,
|
|
|
|
|
//! );
|
|
|
|
|
//!
|
|
|
|
|
//! let result = client.create_and_post_order(&order_args).await?;
|
|
|
|
|
//! println!("Order posted: {:?}", result);
|
|
|
|
|
//!
|
|
|
|
|
//! Ok(())
|
|
|
|
|
//! }
|
|
|
|
|
//! ```
|
|
|
|
|
//!
|
|
|
|
|
//! # Advanced Usage
|
|
|
|
|
//!
|
|
|
|
|
//! ```rust
|
|
|
|
|
//! use polyfill_rs::{PolyfillClient, ClientConfig};
|
|
|
|
|
//!
|
|
|
|
|
//! #[tokio::main]
|
|
|
|
|
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
|
|
|
//! // Advanced configuration
|
|
|
|
|
//! let config = ClientConfig {
|
|
|
|
|
//! base_url: "https://clob.polymarket.com".to_string(),
|
|
|
|
|
//! chain_id: 137,
|
|
|
|
|
//! private_key: Some("your_private_key".to_string()),
|
|
|
|
|
//! max_slippage: Some(Decimal::from_str("0.001")?),
|
|
|
|
|
//! fee_rate: Some(Decimal::from_str("0.02")?),
|
|
|
|
|
//! ..Default::default()
|
|
|
|
|
//! };
|
|
|
|
|
//!
|
|
|
|
|
//! let mut client = PolyfillClient::with_config(config)?;
|
|
|
|
|
//!
|
|
|
|
|
//! // Subscribe to real-time order book updates
|
|
|
|
|
//! client.subscribe_to_order_book("token_id").await?;
|
|
|
|
|
//!
|
|
|
|
|
//! // Process incoming messages
|
|
|
|
|
//! while let Some(message) = client.get_next_message().await? {
|
|
|
|
|
//! println!("Received: {:?}", message);
|
|
|
|
|
//! }
|
|
|
|
|
//!
|
|
|
|
|
//! Ok(())
|
|
|
|
|
//! }
|
|
|
|
|
//! ```
|
|
|
|
|
|
|
|
|
|
use tracing::info;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Global constants
|
|
|
|
|
pub const DEFAULT_CHAIN_ID: u64 = 137; // Polygon
|
|
|
|
|
pub const DEFAULT_BASE_URL: &str = "https://clob.polymarket.com";
|
|
|
|
|
pub const DEFAULT_TIMEOUT_SECS: u64 = 30;
|
|
|
|
|
pub const DEFAULT_MAX_RETRIES: u32 = 3;
|
|
|
|
|
pub const DEFAULT_RATE_LIMIT_RPS: u32 = 100;
|
|
|
|
|
|
|
|
|
|
// Initialize logging
|
|
|
|
|
pub fn init() {
|
|
|
|
|
tracing_subscriber::fmt::init();
|
|
|
|
|
info!("Polyfill-rs initialized");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Re-export main types
|
|
|
|
|
pub use crate::types::{
|
feat: Add EIP-712 signing for L1 authentication (src/auth.rs), HMAC-SHA256 for L2 API authentication, create_api_key(), derive_api_key(), create_or_derive_api_key(), Add set_api_creds() for credential management, Add create_order() and create_market_order() with EIP-712 signing, Add post_order() and create_and_post_order() for order submission, Add cancel(), cancel_orders(), cancel_all() for order management, Add OrderBuilder with proper tick size validation and rounding, Add get_orders() with filtering by ID, asset, market, Add get_trades() with filtering by time range, maker, asset, Add OpenOrderParams and TradeParams for query flexibility, Add balance_allowance() for balance and allowance queries, Add notifications() for push notification setup, Add get_midpoints() for efficient multi-token midpoint queries, Add get_prices() for batch bid/ask/mid price retrieval, Add BatchMidpointRequest/Response and BatchPriceRequest/Response types, Replace Decimal with u32 (Price) and i64 (Qty) on hot paths, Add decimal_to_price() and decimal_to_qty() conversion functions
2025-10-20 18:31:22 -04:00
|
|
|
ApiCredentials, Balance, BalanceAllowance, BatchMidpointRequest, BatchMidpointResponse,
|
|
|
|
|
BatchPriceRequest, BatchPriceResponse, ClientConfig, FillEvent, MarketSnapshot,
|
|
|
|
|
NotificationParams, OpenOrder, OpenOrderParams, Order, OrderBook, OrderDelta,
|
|
|
|
|
OrderRequest, OrderStatus, OrderType, Side, StreamMessage, TokenPrice, TradeParams,
|
|
|
|
|
WssAuth, WssSubscription, WssChannelType,
|
2025-11-04 18:55:20 -05:00
|
|
|
// Additional compatibility types
|
|
|
|
|
ApiKeysResponse, MidpointResponse, PriceResponse, SpreadResponse, TickSizeResponse,
|
|
|
|
|
NegRiskResponse, BookParams, MarketsResponse, SimplifiedMarketsResponse, Market,
|
2025-11-04 22:57:43 -05:00
|
|
|
SimplifiedMarket, Token, Rewards, ClientResult, OrderBookSummary, OrderSummary,
|
2025-11-04 22:59:20 -05:00
|
|
|
BalanceAllowanceParams, AssetType,
|
2025-07-24 20:29:10 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Re-export client
|
|
|
|
|
pub use crate::client::{ClobClient, PolyfillClient};
|
|
|
|
|
|
|
|
|
|
// Re-export compatibility types (for easy migration from polymarket-rs-client)
|
|
|
|
|
pub use crate::client::{
|
2025-11-04 22:59:20 -05:00
|
|
|
OrderArgs,
|
2025-07-24 20:29:10 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Re-export error types
|
|
|
|
|
pub use crate::errors::{PolyfillError, Result};
|
|
|
|
|
|
|
|
|
|
// Re-export advanced components
|
|
|
|
|
pub use crate::book::{OrderBook as OrderBookImpl, OrderBookManager};
|
|
|
|
|
pub use crate::fill::{FillEngine, FillResult};
|
|
|
|
|
pub use crate::stream::{MarketStream, StreamManager, WebSocketStream};
|
|
|
|
|
pub use crate::decode::Decoder;
|
|
|
|
|
|
|
|
|
|
// Re-export utilities
|
|
|
|
|
pub use crate::utils::{
|
|
|
|
|
crypto, math, retry, time, url, rate_limit,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Module declarations
|
feat: Add EIP-712 signing for L1 authentication (src/auth.rs), HMAC-SHA256 for L2 API authentication, create_api_key(), derive_api_key(), create_or_derive_api_key(), Add set_api_creds() for credential management, Add create_order() and create_market_order() with EIP-712 signing, Add post_order() and create_and_post_order() for order submission, Add cancel(), cancel_orders(), cancel_all() for order management, Add OrderBuilder with proper tick size validation and rounding, Add get_orders() with filtering by ID, asset, market, Add get_trades() with filtering by time range, maker, asset, Add OpenOrderParams and TradeParams for query flexibility, Add balance_allowance() for balance and allowance queries, Add notifications() for push notification setup, Add get_midpoints() for efficient multi-token midpoint queries, Add get_prices() for batch bid/ask/mid price retrieval, Add BatchMidpointRequest/Response and BatchPriceRequest/Response types, Replace Decimal with u32 (Price) and i64 (Qty) on hot paths, Add decimal_to_price() and decimal_to_qty() conversion functions
2025-10-20 18:31:22 -04:00
|
|
|
pub mod auth;
|
2025-07-24 20:29:10 -04:00
|
|
|
pub mod book;
|
|
|
|
|
pub mod client;
|
|
|
|
|
pub mod decode;
|
|
|
|
|
pub mod errors;
|
|
|
|
|
pub mod fill;
|
feat: Add EIP-712 signing for L1 authentication (src/auth.rs), HMAC-SHA256 for L2 API authentication, create_api_key(), derive_api_key(), create_or_derive_api_key(), Add set_api_creds() for credential management, Add create_order() and create_market_order() with EIP-712 signing, Add post_order() and create_and_post_order() for order submission, Add cancel(), cancel_orders(), cancel_all() for order management, Add OrderBuilder with proper tick size validation and rounding, Add get_orders() with filtering by ID, asset, market, Add get_trades() with filtering by time range, maker, asset, Add OpenOrderParams and TradeParams for query flexibility, Add balance_allowance() for balance and allowance queries, Add notifications() for push notification setup, Add get_midpoints() for efficient multi-token midpoint queries, Add get_prices() for batch bid/ask/mid price retrieval, Add BatchMidpointRequest/Response and BatchPriceRequest/Response types, Replace Decimal with u32 (Price) and i64 (Qty) on hot paths, Add decimal_to_price() and decimal_to_qty() conversion functions
2025-10-20 18:31:22 -04:00
|
|
|
pub mod orders;
|
2025-07-24 20:29:10 -04:00
|
|
|
pub mod stream;
|
|
|
|
|
pub mod types;
|
|
|
|
|
pub mod utils;
|
|
|
|
|
|
|
|
|
|
// Benchmarks
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod benches {
|
|
|
|
|
use criterion::{criterion_group, criterion_main};
|
|
|
|
|
use crate::{OrderBookManager, OrderDelta, Side};
|
|
|
|
|
use rust_decimal::Decimal;
|
|
|
|
|
use chrono::Utc;
|
|
|
|
|
use std::str::FromStr;
|
|
|
|
|
|
|
|
|
|
fn order_book_benchmark(c: &mut criterion::Criterion) {
|
|
|
|
|
let mut book_manager = OrderBookManager::new(100);
|
|
|
|
|
|
|
|
|
|
c.bench_function("apply_order_delta", |b| {
|
|
|
|
|
b.iter(|| {
|
|
|
|
|
let delta = OrderDelta {
|
|
|
|
|
token_id: "test_token".to_string(),
|
|
|
|
|
timestamp: Utc::now(),
|
|
|
|
|
side: Side::BUY,
|
|
|
|
|
price: Decimal::from_str("0.75").unwrap(),
|
|
|
|
|
size: Decimal::from_str("100.0").unwrap(),
|
|
|
|
|
sequence: 1,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let _ = book_manager.apply_delta(delta);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
criterion_group!(benches, order_book_benchmark);
|
|
|
|
|
criterion_main!(benches);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
|
|
|
|
use super::*;
|
|
|
|
|
use rust_decimal::Decimal;
|
|
|
|
|
use std::str::FromStr;
|
|
|
|
|
use alloy_primitives::U256;
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_client_creation() {
|
|
|
|
|
let client = ClobClient::new("https://test.example.com");
|
|
|
|
|
// Test that the client was created successfully
|
|
|
|
|
// We can't test private fields, but we can verify the client exists
|
|
|
|
|
assert!(true); // Client creation successful
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_order_args_creation() {
|
|
|
|
|
let args = OrderArgs::new(
|
|
|
|
|
"test_token",
|
|
|
|
|
Decimal::from_str("0.75").unwrap(),
|
|
|
|
|
Decimal::from_str("100.0").unwrap(),
|
|
|
|
|
Side::BUY,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
assert_eq!(args.token_id, "test_token");
|
|
|
|
|
assert_eq!(args.side, Side::BUY);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_order_args_default() {
|
|
|
|
|
let args = OrderArgs::default();
|
|
|
|
|
assert_eq!(args.token_id, "");
|
|
|
|
|
assert_eq!(args.price, Decimal::ZERO);
|
|
|
|
|
assert_eq!(args.size, Decimal::ZERO);
|
|
|
|
|
assert_eq!(args.side, Side::BUY);
|
|
|
|
|
}
|
|
|
|
|
}
|