https://github.com/gtg7784/dr-manhattan-rust
A CCXT-style unified API for prediction markets (Polymarket, Limitless, Opinion, Kalshi and Predict.fun) with Rust
https://github.com/gtg7784/dr-manhattan-rust
arbitrage ccxt ccxt-rust kalshi kalshi-api limitless opinion polymarket predictfun prediction prediction-market prediction-market-arbitrage rust
Last synced: 5 months ago
JSON representation
A CCXT-style unified API for prediction markets (Polymarket, Limitless, Opinion, Kalshi and Predict.fun) with Rust
- Host: GitHub
- URL: https://github.com/gtg7784/dr-manhattan-rust
- Owner: gtg7784
- Created: 2025-12-24T08:38:25.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2026-01-04T17:05:23.000Z (5 months ago)
- Last Synced: 2026-01-13T19:46:40.378Z (5 months ago)
- Topics: arbitrage, ccxt, ccxt-rust, kalshi, kalshi-api, limitless, opinion, polymarket, predictfun, prediction, prediction-market, prediction-market-arbitrage, rust
- Language: Rust
- Homepage: https://crates.io/crates/drm-core
- Size: 182 KB
- Stars: 25
- Watchers: 0
- Forks: 4
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# dr-manhattan-rust 🦀
[](https://github.com/gtg7784/dr-manhattan-rust/actions/workflows/ci.yml)
CCXT-style unified API for prediction markets, rewritten in Rust.
## Inspiration
This project is a Rust port of [guzus/dr-manhattan](https://github.com/guzus/dr-manhattan), an excellent Python library that provides a unified interface for prediction markets (similar to how CCXT unifies crypto exchange APIs). Full credit to the original authors for the design and architecture.
## Features
- **Unified API**: Same interface across all supported prediction market exchanges
- **Type-safe**: Leverage Rust's type system for compile-time safety
- **Async-first**: Built on tokio for high-performance async operations
- **WebSocket support**: Real-time orderbook and trade streaming
- **Rate limiting**: Built-in rate limiter to respect exchange limits
## Architecture
```
dr-manhattan-rust/
├── drm-core/ # Core traits, models, and errors
│ ├── models/ # Market, Order, Position, Orderbook
│ ├── exchange/ # Exchange trait, config, rate limiting
│ ├── websocket/ # WebSocket trait for orderbook streaming
│ ├── strategy/ # Strategy trait and order tracker
│ └── error.rs # DrmError hierarchy
├── drm-exchange-polymarket/ # Polymarket implementation
├── drm-exchange-limitless/ # Limitless implementation
├── drm-exchange-opinion/ # Opinion implementation
├── drm-exchange-kalshi/ # Kalshi implementation
├── drm-exchange-predictfun/ # Predict.fun implementation
├── drm-examples/ # Example binaries
└── Cargo.toml # Workspace configuration
```
## Quick Start
```rust
use drm_core::Exchange;
use drm_exchange_polymarket::{Polymarket, PolymarketConfig};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let exchange = Polymarket::with_default_config()?;
let markets = exchange.fetch_markets(None).await?;
for market in markets.iter().take(5) {
println!("{}: {:?}", market.question, market.prices);
}
Ok(())
}
```
## Supported Exchanges
| Exchange | Status | REST | WebSocket |
|----------|--------|------|-----------|
| Polymarket | ✅ Complete | ✅ All endpoints | ✅ Orderbook |
| Limitless | ✅ Complete | ✅ All endpoints | ✅ Orderbook |
| Opinion | ✅ Complete | ✅ All endpoints | - |
| Kalshi | ✅ Complete | ✅ All endpoints | - |
| Predict.fun | ✅ Complete | ✅ All endpoints | - |
## Running Examples
```bash
# List markets from any exchange
cargo run -p drm-examples --bin list-markets -- -l
# Examples:
cargo run -p drm-examples --bin list-markets -- polymarket -l 5
cargo run -p drm-examples --bin list-markets -- kalshi -l 10
PREDICTFUN_API_KEY= cargo run -p drm-examples --bin list-markets -- predictfun -l 5
# Watch orderbook updates (Polymarket)
cargo run -p drm-examples --bin watch-orderbook
```
## Development
```bash
# Build all crates
cargo build
# Run tests
cargo test
# Run clippy
cargo clippy
# Format code
cargo fmt
```
## Configuration
### Polymarket
```rust
use drm_exchange_polymarket::{Polymarket, PolymarketConfig};
// Public API (no auth required)
let exchange = Polymarket::with_default_config()?;
// Authenticated (for trading)
let config = PolymarketConfig::new()
.with_private_key("0x...")
.with_funder("0x...");
let exchange = Polymarket::new(config)?;
exchange.init_trading().await?;
```
### Limitless
```rust
use drm_exchange_limitless::{Limitless, LimitlessConfig};
// Public API
let exchange = Limitless::with_default_config()?;
// Authenticated
let config = LimitlessConfig::new()
.with_private_key("0x...");
let exchange = Limitless::new(config)?;
exchange.authenticate().await?;
```
### Opinion
```rust
use drm_exchange_opinion::{Opinion, OpinionConfig};
// Public API
let exchange = Opinion::with_default_config()?;
// Authenticated
let config = OpinionConfig::new()
.with_api_key("your-api-key")
.with_private_key("0x...")
.with_multi_sig_addr("0x...");
let exchange = Opinion::new(config)?;
```
### Kalshi
```rust
use drm_exchange_kalshi::{Kalshi, KalshiConfig};
// Production API
let config = KalshiConfig::new("your-api-key-id", "/path/to/private-key.pem");
let exchange = Kalshi::new(config)?;
// Demo environment
let config = KalshiConfig::demo("your-api-key-id", "/path/to/private-key.pem");
let exchange = Kalshi::new(config)?;
// With PEM string directly
let config = KalshiConfig::new("your-api-key-id", "")
.with_private_key_pem("-----BEGIN PRIVATE KEY-----\n...");
let exchange = Kalshi::new(config)?;
```
### Predict.fun
```rust
use drm_exchange_predictfun::{PredictFun, PredictFunConfig};
// Public API
let exchange = PredictFun::with_default_config()?;
// Authenticated (for trading)
let config = PredictFunConfig::new()
.with_api_key("your-api-key")
.with_private_key("0x...");
let exchange = PredictFun::new(config)?;
exchange.authenticate().await?;
// Testnet
let config = PredictFunConfig::testnet()
.with_api_key("your-api-key")
.with_private_key("0x...");
let exchange = PredictFun::new(config)?;
```
## API Reference
### Exchange Trait
All exchanges implement the `Exchange` trait:
```rust
#[async_trait]
pub trait Exchange: Send + Sync {
fn id(&self) -> &'static str;
fn name(&self) -> &'static str;
async fn fetch_markets(&self, params: Option) -> Result, DrmError>;
async fn fetch_market(&self, market_id: &str) -> Result;
async fn fetch_markets_by_slug(&self, slug: &str) -> Result, DrmError>;
async fn create_order(&self, market_id: &str, outcome: &str, side: OrderSide, price: f64, size: f64, params: HashMap) -> Result;
async fn cancel_order(&self, order_id: &str, market_id: Option<&str>) -> Result;
async fn fetch_order(&self, order_id: &str, market_id: Option<&str>) -> Result;
async fn fetch_open_orders(&self, params: Option) -> Result, DrmError>;
async fn fetch_positions(&self, market_id: Option<&str>) -> Result, DrmError>;
async fn fetch_balance(&self) -> Result, DrmError>;
}
```
### Models
- `Market`: Prediction market with question, outcomes, prices, volume
- `Order`: Order with price, size, status, timestamps
- `Position`: Position with size, average price, current price
- `Orderbook`: Orderbook with bids and asks
## License
MIT
## Acknowledgments
- [guzus/dr-manhattan](https://github.com/guzus/dr-manhattan) - Original Python implementation
- [CCXT](https://github.com/ccxt/ccxt) - Inspiration for the unified exchange API pattern