# polymarket-sdk
A comprehensive Rust SDK for the [Polymarket CLOB API](https://docs.polymarket.com) — programmatic trading on prediction markets.
## Features
- **Type-level auth guards**: Compile-time safety prevents calling trading endpoints without authentication.
- **Robust error handling**: Automatic retry with exponential backoff, strict rate-limit handling (429 + `Retry-After`), and an `is_retryable()` helper.
- **WebSocket streaming**: Real-time market data, price changes, and order book updates.
- **Modular builds**: Feature flags (`clob`, `gamma`, `data`, `ws`) let you compile only what you need.
- **Complete API coverage**: Full support for CLOB order management, EIP-712 signing, Gamma market discovery, Data API (trades, positions), and L1/L2 authentication.
## Installation
```toml
[dependencies]
polymarket-sdk = { path = "." }
tokio = { version = "1", features = ["full"] }
```
### Feature Flags
| `clob` | ✅ | CLOB REST endpoints (orders, book, prices) |
| `gamma` | ✅ | Gamma market discovery (events, search) |
| `data` | ❌ | Data API (trades, positions, balances) |
| `ws` | ❌ | WebSocket streaming via `tokio-tungstenite` |
| `full` | ❌ | Everything above |
```toml
# Just streaming:
polymarket-sdk = { path = ".", features = ["ws"] }
# Everything:
polymarket-sdk = { path = ".", features = ["full"] }
```
## Quick Start
### Public Market Data (no auth)
```rust
use polymarket_sdk::PolymarketClient;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = PolymarketClient::new_public(None)?;
// Fetch markets
let markets = client.get_sampling_simplified_markets(None).await?;
println!("Found {} markets", markets.len());
// Get order book
let book = client.get_order_book("TOKEN_ID").await?;
println!("Bids: {}, Asks: {}", book.bids.len(), book.asks.len());
Ok(())
}
```
### Authenticated Trading
```rust
use polymarket_sdk::{ApiCredentials, PolymarketClient, TradeParams, OrderSide};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let creds = ApiCredentials {
api_key: "your-key".into(),
secret: "your-secret".into(),
passphrase: "your-passphrase".into(),
};
// Type-level auth: public → authenticated upgrade
let public = PolymarketClient::new_public(None)?;
let client = public.authenticate(creds);
// Now you can call trading endpoints
let orders = client.get_orders().await?;
println!("Open orders: {}", orders.len());
Ok(())
}
```
### Compile-Time Safety
```rust
use polymarket_sdk::PolymarketClient;
// This is a public-only client
let public = PolymarketClient::new_public(None).unwrap();
// ✅ Market data works
// let book = public.get_order_book("token").await;
// ❌ This would NOT compile — trading requires authentication!
// let orders = public.get_orders().await; // compile error!
```
### WebSocket Streaming (requires `ws` feature)
```rust
use polymarket_sdk::stream::PolymarketStream;
async fn stream_example() -> Result<(), Box<dyn std::error::Error>> {
let mut stream = PolymarketStream::connect(None).await?;
stream.subscribe_market("TOKEN_ID").await?;
while let Some(event) = stream.next().await {
match event {
Ok(msg) => println!("[{}] {:?}", msg.event_type, msg.data),
Err(e) => {
if !e.is_retryable() { break; }
}
}
}
Ok(())
}
```
## API Reference
### Public Endpoints (`PolymarketClient<Public>`)
| `get_markets()` | List CLOB markets |
| `get_market(id)` | Single market by condition ID |
| `get_order_book(token)` | Order book snapshot |
| `get_price(token)` | Current price |
| `get_midpoint(token)` | Midpoint price |
| `get_spread(token)` | Bid-ask spread |
| `get_last_trade_price(token)` | Last trade price |
| `get_prices_history(token, ...)` | Price history |
| `get_gamma_markets(...)` | Gamma market discovery |
| `get_events(...)` | Gamma event groupings |
| `search_markets(query)` | Full-text market search |
| `create_or_derive_api_key(signer)` | L1 key management |
### Authenticated Endpoints (`PolymarketClient<Authenticated>`)
*All public methods, plus:*
| `get_orders()` | Open orders |
| `get_order(id)` | Single order |
| `post_order(signed)` | Submit signed order |
| `create_and_post_order(signer, params)` | Build + sign + submit |
| `cancel_order(id)` | Cancel one order |
| `cancel_orders(ids)` | Cancel multiple |
| `cancel_all_orders()` | Cancel all |
| `get_trades()` | Trade history (data feature) |
| `get_positions()` | Current positions (data feature) |
| `get_balance_allowances(...)` | Token balances (data feature) |
## Architecture
```
polymarket-sdk/
├── src/
│ ├── lib.rs # Crate root, feature-gated modules
│ ├── error.rs # PolymarketError with is_retryable()
│ ├── http.rs # reqwest wrapper with retry + rate-limit
│ ├── types.rs # All data models
│ ├── stream.rs # WebSocket streaming (ws feature)
│ ├── auth/
│ │ ├── l1.rs # EIP-712 ClobAuth signing
│ │ └── l2.rs # HMAC-SHA256 request signing
│ └── signing/
│ ├── eip712.rs # EIP-712 Order (alloy::sol!)
│ └── order_builder.rs # TradeParams → SignedOrder
├── examples/
│ ├── get_markets.rs # Public market data
│ ├── place_order.rs # Full trading flow
│ └── stream_prices.rs # Live WebSocket streaming
├── Cargo.toml
├── LICENSE
└── README.md
```
## License
MIT