Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
64205ee
chore(cargo): fix manifest and dev dep
floor-licker Jan 29, 2026
e28e1af
fix(auth): only fallback derive on API errors
floor-licker Jan 29, 2026
703bd9f
feat(book): align /book response fields
floor-licker Jan 29, 2026
a7ca8e4
feat(ws): align auth and event_type parsing
floor-licker Jan 29, 2026
da51caa
chore(cargo): use crates.io polymarket-rs-client
floor-licker Jan 29, 2026
41db8ca
chore(fmt): cargo fmt
floor-licker Jan 29, 2026
cc419ac
chore(rustfmt): keep config stable-compatible
floor-licker Jan 30, 2026
dea5016
test(no-alloc): guard hot paths against heap allocs
floor-licker Jan 30, 2026
9594058
feat(book): apply websocket book updates
floor-licker Jan 30, 2026
75ce261
perf(ws): avoid cloning batch stream messages
floor-licker Jan 30, 2026
a0bf317
refactor(ws): replace unbounded channel with bounded queue
floor-licker Jan 30, 2026
0e71182
feat(book): apply ws book updates via OrderBookManager
floor-licker Jan 30, 2026
7145f74
docs: update README.md
floor-licker Jan 31, 2026
c1b7633
chore(security): update lockfile for RustSec advisories
floor-licker Jan 31, 2026
3b0765f
ci: run no-alloc hot-path tests as separate job
floor-licker Jan 31, 2026
9fa4174
docs: update README.md
floor-licker Jan 31, 2026
b523a7f
docs: update README.md
floor-licker Jan 31, 2026
e0b97c5
feat(ws): add tape-based book update processor
floor-licker Jan 31, 2026
d45b202
feat(ws): add book-applier stream
floor-licker Jan 31, 2026
31062b3
docs: align testing guide with CI
floor-licker Jan 31, 2026
2570aa0
docs: clarify integration test env vars
floor-licker Jan 31, 2026
0f577f0
fix(api): improve order endpoint compatibility
floor-licker Jan 31, 2026
2dc3c06
test: make real-api smoke tests robust
floor-licker Jan 31, 2026
1e1ef74
test(ws): add ignored real-market websocket smoke test
floor-licker Jan 31, 2026
d4e2407
test(ws): add user channel and stability checks
floor-licker Jan 31, 2026
65bab0d
docs: update README.md
floor-licker Jan 31, 2026
40b503e
bench(ws): add WS hot-path Criterion benchmark
floor-licker Jan 31, 2026
f5a807c
bench(ws): add serde baseline comparison
floor-licker Jan 31, 2026
25f2689
docs(readme): mention WS hot-path benchmark
floor-licker Jan 31, 2026
9f86e24
docs(readme): add ws_hot_path benchmark command
floor-licker Jan 31, 2026
3dfb65e
feat(api): add /prices-history helper methods
floor-licker Jan 31, 2026
0b2740a
test(api): add /prices-history real API integration test
floor-licker Jan 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ jobs:
- name: Run clippy
run: cargo clippy --lib --bins --tests --benches --all-features -- -D warnings && cargo clippy --example benchmark_with_keepalive --example demo --example final_benchmark --example http2_tuning_benchmark --example performance_benchmark --example quick_demo --example snipe -- -D warnings

- name: Run tests
run: cargo test --all-features
- name: Run tests (excluding no-alloc hot paths)
run: cargo test --all-features -- --skip no_alloc_

- name: Build examples
run: |
Expand Down Expand Up @@ -64,4 +64,24 @@ jobs:
run: cargo install cargo-audit

- name: Run security audit
run: cargo audit
run: cargo audit

no_alloc:
name: No-alloc hot paths
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable

- name: Cache dependencies
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}

- name: Run no-alloc hot path tests
run: cargo test --all-features --test no_alloc_hot_paths
110 changes: 98 additions & 12 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 6 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ keywords = ["polymarket", "trading", "prediction-market", "kalshi", "clob", "cry
categories = ["api-bindings", "network-programming", "finance", "prediction-markets", "polymarket", "kalshi", "clob"]
documentation = "https://docs.rs/polyfill-rs"
homepage = "https://github.com/floor-licker/polyfill-rs"
license = "MIT OR Apache-2.0"
[dependencies]
# Pin base64ct to avoid Edition 2024 requirement
base64ct = "=1.6.0"
Expand Down Expand Up @@ -71,7 +70,7 @@ tokio-test = "0.4"
mockito = "1.0"
proptest = "1.0"
env_logger = "0.10"
# polymarket-rs-client = { path = "external/polymarket-rs-client" } # Uncomment to run side-by-side benchmark
polymarket-rs-client = "0.1.1"

[features]
default = ["stream"]
Expand All @@ -93,6 +92,10 @@ harness = false
name = "network_benchmarks"
harness = false

[[bench]]
name = "ws_hot_path"
harness = false

[profile.release]
# Optimizations for HFT performance
opt-level = 3
Expand All @@ -107,4 +110,4 @@ opt-level = 1
[profile.test]
# Optimizations for test performance
opt-level = 2
debug = true
debug = true
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@

A high-performance drop-in replacement for `polymarket-rs-client` with latency-optimized data structures and zero-allocation hot paths. A 100% API-compatible drop-in replacement for `polymarket-rs-client` with identical method signatures.

At 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.

I 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 general, zero alloc means either zero alloc in hot paths (which can be a bit more arbitrary) or atlernatively it can mean zero alloc after init/warm-up, which is the objective of this repository. Succinctly that means that **the per-message handling loop never touches the heap**.

Copilot AI Jan 31, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spelling: "recieved" -> "received".

Suggested change
I 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 general, zero alloc means either zero alloc in hot paths (which can be a bit more arbitrary) or atlernatively it can mean zero alloc after init/warm-up, which is the objective of this repository. Succinctly that means that **the per-message handling loop never touches the heap**.
I also want to take a moment to clarify what zero-alloc means because I've now received double digit messages about this on twitter/x and telegram. In general, zero alloc means either zero alloc in hot paths (which can be a bit more arbitrary) or atlernatively it can mean zero alloc after init/warm-up, which is the objective of this repository. Succinctly that means that **the per-message handling loop never touches the heap**.

Copilot uses AI. Check for mistakes.

Copilot AI Jan 31, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spelling: "atlernatively" -> "alternatively".

Suggested change
I 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 general, zero alloc means either zero alloc in hot paths (which can be a bit more arbitrary) or atlernatively it can mean zero alloc after init/warm-up, which is the objective of this repository. Succinctly that means that **the per-message handling loop never touches the heap**.
I 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 general, zero alloc means either zero alloc in hot paths (which can be a bit more arbitrary) or alternatively it can mean zero alloc after init/warm-up, which is the objective of this repository. Succinctly that means that **the per-message handling loop never touches the heap**.

Copilot uses AI. Check for mistakes.

Notably order book paths that introduce new allocations by design:
- First time seeing a token/book (HashMap insert + key clone): `src/book.rs:~788`
- New price levels (BTreeMap node growth): `src/book.rs:~409`


## Quick Start

Expand Down Expand Up @@ -56,6 +64,9 @@ End-to-end performance with Polymarket's API, including network latency, JSON pa
| **Order Book Updates (1000 ops)** | 159.6 µs ± 32 µs | 6,260 updates/sec, zero-allocation |
| **Spread/Mid Calculations** | 70 ns ± 77 ns | 14.3M ops/sec, optimized BTreeMap |
| **JSON Parsing (480KB)** | ~2.3 ms | SIMD-accelerated parsing (1.77x faster than serde_json) |
| **WS `book` hot path (decode + apply)** | ~0.28 µs / 2.01 µs / 7.70 µs | 1 / 16 / 64 levels-per-side, ~3.7–4.0x faster vs serde decode+apply (see `benches/ws_hot_path.rs`) |

Run the WS hot-path benchmark locally with `cargo bench --bench ws_hot_path`.

**Key Performance Optimizations:**

Expand Down
Loading