Metadata-Version: 2.4
Name: fast-clob-tools
Version: 0.1.0
Summary: Optional native acceleration tools for py-clob-client-v2
Author: Polymarket Rust Client Contributors
License-Expression: MIT
Project-URL: Homepage, https://github.com/tosmart01/fast-clob-tools
Project-URL: Repository, https://github.com/tosmart01/fast-clob-tools
Project-URL: Issues, https://github.com/tosmart01/fast-clob-tools/issues
Keywords: polymarket,clob,secp256k1,signing,latency
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: C
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Office/Business :: Financial
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9.10
Description-Content-Type: text/markdown
Requires-Dist: py-clob-client-v2>=1.0.1

# fast-clob-tools

[中文文档](./README.zh-CN.md)

`fast-clob-tools` provides optional native acceleration tools for
`py-clob-client-v2`. The current release replaces the official `OrderBuilder`
for newly created clients and uses a C-backed `libsecp256k1` implementation for
Polymarket V2 limit-order building and signing.

Current package version: `0.1.0`.

## Benchmark Snapshot

Environment: macOS arm64, Python 3.11, `libsecp256k1` installed by Homebrew.
Numbers are measured with the local `tests/bench_sign.py` style benchmark and
are microseconds (`us`).

Full V2 build+sign path comparison:

| Signature type | Scenario | Python C extension | Rust SDK | Comparison |
| --- | --- | --- | --- | --- |
| `1` | First, no prewarm | ~86-91 us | ~132 us | Python ↓ ~31-35% |
| `1` | First, `prewarm=True` | ~24 us | ~132 us | Python ↓ ~82% |
| `1` | Hot p50 | ~33 us | ~57.5 us | Python ↓ ~43% |
| `1` | After 1s idle | ~128 us, then ~51 us | ~352 us | Python ↓ |
| `3` / Poly1271 | First, no prewarm | ~22 us | ~162 us | Python ↓ ~86% |
| `3` / Poly1271 | Hot p50 | ~15.7 us | ~54.5 us | Python ↓ ~71% |
| `3` / Poly1271 | After 1s idle | ~195 us, ~124 us, then ~64 us | ~342 us | Python ↓ |

`signatureType=3` / Poly1271 produces a 636-character signature hex string.

Interpretation:

- `prewarm=True` moves native signer warmup into builder creation and lowers
  the first real order latency.
- In the hot loop, this C extension is faster than the current Rust SDK full
  build+sign path because it is a narrower V2 limit-order fast path.
- Rust raw/prebuilt sign numbers are not equivalent to this benchmark. They do
  not include Python-style amount conversion, timestamp/salt creation, V2 order
  construction, and full signed-order output.

Benchmark script shape:

```python
import statistics
import time

from fast_clob_tools import FastOrderBuilder, install_patch, is_native_available

# Must run before creating/importing a module-level py-clob-client-v2 client.
install_patch(prewarm=False)

from py_clob_client_v2.clob_types import CreateOrderOptions, OrderArgs
from src.trade.client.poly_client import client

assert is_native_available()
assert isinstance(client.builder, FastOrderBuilder)

order_args = OrderArgs(
    token_id="24483563228660028121020430722896740519524131851526579619586176931221901842798",
    price=0.01,
    side="BUY",
    size=10,
    expiration=0,
)
options = CreateOrderOptions(tick_size="0.01", neg_risk=False)

def sign_us() -> float:
    start = time.perf_counter_ns()
    order = client.builder.build_order(order_args, options, version=2)
    assert order.signature
    return (time.perf_counter_ns() - start) / 1_000

first = sign_us()
samples = [sign_us() for _ in range(1_000)]
time.sleep(1)
after_idle = [sign_us() for _ in range(8)]

print(f"first={first:.3f}us")
print(f"hot_p50={statistics.median(samples):.3f}us")
print("after_idle=", ", ".join(f"{v:.3f}us" for v in after_idle))
```

Benchmark notes:

- `prewarm=False` measures the first real order without a dummy native sign.
- `prewarm=True` creates and warms native signers when `FastOrderBuilder` is
  created, so the first real order is not a cold native sign.
- Sleep/idle measurements include OS scheduling and CPU/cache cold-path effects.
- Numbers are hardware and workload dependent; use them as a rough sanity
  check, not a portable guarantee.

## Scope

Implemented:

- Polymarket V2 limit-order construction and signing.
- `signatureType` 0, 1, 2, and 3.
- Poly1271 wrapped signatures for `signatureType=3`.
- Normal and negative-risk V2 exchange addresses.

Not implemented:

- V1 orders.
- Market orders.
- Posting orders or making Polymarket HTTP calls.
- Silent fallback to the official Python signing path.

Unsupported paths intentionally raise `NotImplementedError` or fail fast.

## Requirements

- Python 3.9.10 or newer.
- A C compiler toolchain for your platform.
- Native `libsecp256k1` development headers and library available at install
  time.

Installation fails if the native extension cannot be compiled. This package does
not ship cross-platform bundled wheels.

## Install

### macOS

Apple Silicon / Homebrew:

```bash
brew install secp256k1
python -m pip install fast-clob-tools
```

If Homebrew is installed in a non-standard location:

```bash
SECP256K1_INCLUDE_DIR=/opt/homebrew/include \
SECP256K1_LIBRARY_DIR=/opt/homebrew/lib \
python -m pip install fast-clob-tools
```

Intel Homebrew commonly uses `/usr/local`:

```bash
SECP256K1_INCLUDE_DIR=/usr/local/include \
SECP256K1_LIBRARY_DIR=/usr/local/lib \
python -m pip install fast-clob-tools
```

Local checkout:

```bash
python -m pip install .
```

### Linux

Debian / Ubuntu package availability varies by distro version. If available:

```bash
sudo apt-get update
sudo apt-get install -y build-essential python3-dev pkg-config libsecp256k1-dev
python -m pip install fast-clob-tools
```

If your distro does not ship `libsecp256k1-dev`, build it first:

```bash
git clone https://github.com/bitcoin-core/secp256k1.git
cd secp256k1
cmake -S . -B build \
  -DCMAKE_BUILD_TYPE=Release \
  -DSECP256K1_ENABLE_MODULE_RECOVERY=ON \
  -DSECP256K1_BUILD_TESTS=OFF \
  -DSECP256K1_BUILD_BENCHMARK=OFF \
  -DSECP256K1_BUILD_EXHAUSTIVE_TESTS=OFF
cmake --build build --parallel
sudo cmake --install build
```

Then install:

```bash
SECP256K1_INCLUDE_DIR=/usr/local/include \
SECP256K1_LIBRARY_DIR=/usr/local/lib \
python -m pip install fast-clob-tools
```

Local checkout:

```bash
python -m pip install .
```

### Windows

Install MSVC build tools, then install `secp256k1` with vcpkg:

```powershell
git clone https://github.com/microsoft/vcpkg C:\vcpkg
C:\vcpkg\bootstrap-vcpkg.bat
C:\vcpkg\vcpkg.exe install secp256k1:x64-windows-static-md
```

From a Developer PowerShell where MSVC is available:

```powershell
$env:SECP256K1_INCLUDE_DIR = "C:\vcpkg\installed\x64-windows-static-md\include"
$env:SECP256K1_LIBRARY_DIR = "C:\vcpkg\installed\x64-windows-static-md\lib"
python -m pip install fast-clob-tools
```

Local checkout:

```powershell
python -m pip install .
```

## Verify

```bash
python - <<'PY'
from fast_clob_tools import __version__, is_native_available

assert is_native_available()
print(f"fast-clob-tools {__version__} native extension ok")
PY
```

## Usage

Patch before creating or importing any module-level `py-clob-client-v2` client:

```python
from fast_clob_tools import install_patch

install_patch(prewarm=True)

from src.trade.client.poly_client import client

# New clients created after install_patch() use FastOrderBuilder.
order = client.builder.build_order(order_args, options, version=2)
```

`prewarm` controls whether native signers run dummy V2 limit-order signing when
`FastOrderBuilder` is created:

```python
install_patch(prewarm=False)  # strict first-sign benchmark
install_patch(prewarm=True)   # lower first real order latency
```

## Minimal Local Demo

This demo uses a fake private key and signs one V2 limit order locally. It does
not submit anything to Polymarket.

```bash
python - <<'PY'
import time

from fast_clob_tools import install_patch, is_native_available
from py_clob_client_v2.clob_types import CreateOrderOptions, OrderArgs
from py_clob_client_v2.order_builder.constants import BUY
from py_clob_client_v2.signer import Signer

install_patch(prewarm=False)
assert is_native_available()

from py_clob_client_v2.order_builder import OrderBuilder

signer = Signer("0x" + "1" * 64, 137)
builder = OrderBuilder(signer=signer)

order_args = OrderArgs(token_id="1", price=0.51, size=5.0, side=BUY)
options = CreateOrderOptions(tick_size="0.01", neg_risk=False)

start = time.perf_counter_ns()
signed_order = builder.build_order(order_args, options, version=2)
elapsed_us = (time.perf_counter_ns() - start) / 1_000

print(f"signature={signed_order.signature[:18]}... chars={len(signed_order.signature)}")
print(f"elapsed_us={elapsed_us:.2f}")
PY
```

## Development

Create a local environment and install the package from the local checkout:

```bash
python -m venv .venv
source .venv/bin/activate
python -m pip install . pytest build
pytest tests
```

Build source and wheel distributions:

```bash
python -m build
```

## License

This package is distributed under the repository license. See `../../LICENSE`.
