{"repo":"floor-licker/polyfill-rs","free":true,"listed":false,"github":"https://github.com/floor-licker/polyfill-rs","clone":"git clone https://github.com/floor-licker/polyfill-rs.git","description":"The Fastest Polymarket Rust Client","language":"Rust","stars":218,"topics":["hft","polymarket","prediction-market","trading"],"license":null,"category":"trading_api_client","readme_excerpt":"![polyfill-rs](header.png)\n\n[![Crates.io](https://img.shields.io/crates/v/polyfill-rs.svg)](https://crates.io/crates/polyfill-rs)\n[![Documentation](https://docs.rs/polyfill-rs/badge.svg)](https://docs.rs/polyfill-rs)\n[![License](https://img.shields.io/badge/license-MIT%2FApache--2.0-blue.svg)](LICENSE)\n\nA high-performance Polymarket Rust client with latency-optimized data structures and allocator-conscious hot paths. The `0.4.x` line is V2-native and intentionally breaking for authenticated trading flows.\n\nAt the time that this project was started, `polymarket-rs-client` was a Polymarket Rust Client with a few GitHub stars, but which seemed to be unmaintained. I took on the task of creating a Rust client which could beat the benchmarks quoted in the README.md of that project, with the added constraint of also maintaining zero alloc hot paths.\n\nI also want to take a moment to clarify what zero-alloc means because I've now recieved double digit messages about this on twitter/x and telegram. In this repository the strict claim is limited to tested, warmed hot paths: existing-level book updates and selected read-side calculations are covered by no-heap-traffic tests that count allocations, reallocations, and deallocations. Snapshot churn, first-seen books, and new price levels can still touch the allocator by design.\n\nNotably order book paths that can touch the allocator by design:\n- First time seeing a token/book (HashMap insert + key clone): `src/book.rs`\n- New price levels when a sorted side needs to grow: `src/book.rs`\n- Book removal/drop paths that release owned buffers: `src/book.rs`\n\n\n## Quick Start\n\nAdd to your `Cargo.toml`:\n\n```toml\n[dependencies]\npolyfill-rs = \"0.4.0\"\n```\n\nReplace your imports:\n\n```rust\n// Before: use polymarket_rs_client::{ClobClient, Side, OrderType};\nuse polyfill_rs::{ClobClient, Side, OrderType};\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n    let client = ClobClient::new(\"https://clob.polymarket.com\");\n    let markets = client.get_sampling_markets(None).await?;\n    println!(\"Found {} markets\", markets.data.len());\n    Ok(())\n}\n```\n\n## Performance Comparison\n\n**Real-World API Performance (with network I/O)**\n\nReal-world Polymarket API latency broken down by request phase:\n\n![polyfill-rs benchmark results](assets/benchmark-results.svg)\n\n| Operation | Metric | polyfill-rs | rs-clob-client-v2 | polymarket-rs-client | Official Python Client |\n|-----------|--------|-------------|-------------------|----------------------|------------------------|\n| **Fetch Markets** | mean ± sd | **321.6 ms ± 92.9 ms** | - | 409.3 ms ± 137.6 ms | 1.366 s ± 0.048 s |\n| **Cold Start** | single run | 759.3 ms | **568.0 ms** | - | - |\n| **Warm Connection** | single run | **153.0 ms** | 191.9 ms | - | - |\n| **Steady Typed Total** | p50 / p95 / p99 | **228.2 / 509.9 / 611.2 ms** | 242.3 / 514.2 / 641.3 ms | - | - |\n| **Network-Only Byte Fetch*** | p50 / p95 / p99 | 200.0 / **327.3 / 518.6 ms** | **123.3** / 456.9 / 867.2 ms | - | - |\n| **CPU Parse Only** | p50 / p95 / p99 | **0.5 / 1.1 / 1.3 ms** | 1.3 / 1.6 / 1.7 ms | - | - |\n\n\n**Performance vs polymarket-rs-client:**\n- **21.4% faster** \n- **32.5% more consistent** \n- **4.2x faster** than Official Python Client\n\n**Benchmark Methodology:** The `rs-clob-client-v2` comparison separates cold start, warm connection, steady-state typed requests, network-only byte fetches, and CPU-only parsing. The latest local live-network run was on June 22, 2026 against `https://clob.polymarket.com/simplified-markets?next_cursor=MA==`. Steady-state rows use 40 paired iterations with alternating order and 100ms delay after 5 warmups; parse rows use 300 iterations from a cached 480KB payload. The network-only row is a selected raw HTTP diagnostic, not a typed SDK method result: it compares polyfill's actual HTTP client with a reqwest client using the `rs-clob-client-v2` default headers and no typed deserialization. The benchmark now prints a full network-only transport matrix covering default reqwest, `rs-clob-client-v2` headers, polyfill's actual client, and polyfill-tuned header variants. The CPU parse row compares polyfill's SIMD-backed typed parser against the `rs-clob-client-v2` request-helper parse path; direct serde parsing of the SDK response type measured 0.5 / 0.6 / 0.6 ms. Run it with `cargo run --release --example official_client_side_by_side_benchmark --features official-client-benchmark`. See `examples/side_by_side_benchmark.rs` in commit `a63a170`: https://github.com/floor-licker/polyfill-rs/blob/a63a170/examples/side_by_side_benchmark.rs for the original legacy benchmark implementation.\n\n**Computational Performance (pure CPU, no I/O)**\n\n| Operation | Performance | Notes |\n|-----------|-------------|-------|\n| **Order Book Updates (1000 ops)** | 69.6 µs | ~14.4M updates/sec, no allocator traffic for warmed existing-level paths |\n| **Spread/Mid Calculations** | 26.6 ns | best bid/ask + spread + mid over sorted-vector book sides |\n| **JSON Parsing (480KB)** | ~0.5 ms | SIMD-backed parsing for large REST market responses and benchmarked polyfill typed parse path |\n| **WS `book` hot path (decode + apply)** | ~0.24 µs / 1.56 µs / 5.92 µs | 1 / 16 / 64 levels-per-side, strict fixed-point tape parser with generation-marked snapshot retention (see `benches/ws_hot_path.rs`) |\n\nRun the WS hot-path benchmark locally with `cargo bench --bench ws_hot_path`.\n\n**Parsing paths:** `polyfill-rs` keeps two parsing layers on purpose. The allocation-sensitive WS `book` path uses `WsBookUpdateProcessor` in `src/ws_hot_path.rs`, which walks a reusable `simd-json` tape and applies fixed-point book levels directly. The generic stream parser in `src/decode.rs` is an ergonomic compatibility path: it parses through `serde_json::Value` so it can tolerate batches, unknown event types, and mixed message shapes. Likewise, several generic numeric/decimal deserializers in `src/decode.rs` accept string-or-number API fields through `serde_json::Value`; they are not the zero-allocation hot path.\n\n**WebSocket snapshot ordering:** Polymarket `book` messages expose a millisecond `timestamp` and optional `hash`, but no monotonic server sequence/version. The book applier treats newer timestamps as newer, rejects older timestamps, suppresses exact same-timestamp/same-hash duplicates, and accepts same-timestamp/different-hash snapshots in websocket arrival order. The hash distinguishes duplicate vs distinct state; it is not a logical ordering key.\n\n**Key Performance Optimizations:**\n\nThe 21.4% performance improvement comes from HTTP/2 tuning with 512KB stream windows optimized for 469KB payloads, explicit Polymarket request headers, SIMD-backed parsing where the client uses the typed fast-response helper for large REST market responses, and opt-in connection prewarming/keep-alive support.\n\n### Memory Architecture\n\nConfigurable book depth limiting prevents memory bloat. Hot data structures group frequently-accessed fields for cache line efficiency. Allocation-sensitive hot paths are covered by targeted no-heap-traffic tests where the implementation currently avoids allocation, reallocation, and deallocation.\n\n### Architectural Principles\n\nPrice data converts to fixed-point at ingress boundaries while maintaining tick-aligned precision. The critical path uses integer arithmetic with branchless operations. Data converts back to IEEE 754 at egress for API compatibility. This enables deterministic execution with predictable instruction counts.\n\n### Measured Network Improvements\n\n| Optimization Technique | Performance Gain | Use Case |\n|------------------------|------------------|----------|\n| **Optimized HTTP client** | **11% baseline improvement** | Every API call |\n| **Connection pre-warming** | **70% faster subsequent requests** | Application startup |\n| **Request parallelization** | **200% faster batch operations** | Multi-market data fetching |\n| **Circuit breaker resilience** | **Better uptime during instability** | Production trading systems |\n","default_branch":"main","files":52,"tree":[".env.example",".github/workflows/ci.yml",".gitignore",".spellcheck.yml","Cargo.lock","Cargo.toml","README.md","assets/benchmark-results.svg","benches/book_updates.rs","benches/comparison_benchmarks.rs","benches/fill_processing.rs","benches/network_benchmarks.rs","benches/ws_hot_path.rs","clippy.toml","docs/TESTING.md","examples/benchmark_with_keepalive.rs","examples/demo.rs","examples/final_benchmark.rs","examples/http2_tuning_benchmark.rs","examples/http_transport_matrix.rs","examples/official_client_side_by_side_benchmark.rs","examples/performance_benchmark.rs","examples/quick_demo.rs","examples/side_by_side_benchmark.rs","examples/snipe.rs","header.png","rustfmt.toml","scripts/benchmark_comparison.sh","scripts/network_benchmark.sh","scripts/run_integration_tests.sh","src/auth.rs","src/book.rs","src/client.rs","src/config.rs","src/connection_manager.rs","src/decode.rs","src/errors.rs","src/fill.rs","src/http_config.rs","src/lib.rs","src/orders.rs","src/stream.rs","src/types.rs","src/utils.rs","src/ws_hot_path.rs","tests/common/mod.rs","tests/integration_tests.rs","tests/no_alloc_hot_paths.rs","tests/order_posting_test.rs","tests/prices_history_integration_tests.rs","tests/simple_auth_test.rs","tests/ws_integration_tests.rs"],"storefront":"/r/floor-licker","claimed":false,"request_supported":{"post":"https://gitbuyer.com/r/floor-licker/polyfill-rs/request-supported","requests":0},"note":"indexed from public GitHub; nothing is for sale on this page. Clone it from GitHub. Paid listings live at /search."}