# PolymarketClob

Standalone Elixir client for the Polymarket CLOB API.

This package is being built as the first publishable version of `polymarket_clob`.
It targets Polymarket's current exchange model and starts from fixture-proven auth and
order-signing primitives before adding higher-level HTTP, order construction, and
WebSocket APIs.

## Current Status

Implemented:

- current CLOB contract address config for Polygon and Amoy
- client struct with address derivation and signature type defaults
- L1 ClobAuth signing with `nonce`
- L2 HMAC request signing
- HTTP wrapper with public/private helpers and L2 header injection
- read-only market-data and account endpoint wrappers
- write endpoint wrappers for posting already-built signed orders and cancellations
- float-based order rounding and local limit/market order builders
- order EIP-712 typed data, order hash, and signature generation
- deterministic parity fixtures generated from `Polymarket/py-clob-client-v2`

Not implemented yet:

- allowance updates and write endpoints beyond already-built order posting/cancellation
- WebSocket clients

## Examples

### Client

```elixir
client =
  PolymarketClob.Client.new(
    private_key: System.fetch_env!("POLY_PRIVATE_KEY"),
    api_key: System.get_env("POLY_API_KEY"),
    api_secret: System.get_env("POLY_API_SECRET"),
    api_passphrase: System.get_env("POLY_API_PASSPHRASE")
  )
```

If API credentials are omitted, the client defaults to EOA signature type `0`. If all API
credential fields are present, it defaults to Polymarket Gnosis Safe signature type `2`.
Partial API credentials raise.

### Public Market Data Reads

```elixir
{:ok, book} =
  PolymarketClob.API.MarketData.get_order_book("1234567890")

{:ok, price} =
  PolymarketClob.API.MarketData.get_price("1234567890", :buy)

{:ok, market_info} =
  PolymarketClob.API.MarketData.get_clob_market_info("0xconditionid")
```

### Private Account Reads

```elixir
{:ok, balance} =
  PolymarketClob.API.Account.get_balance_allowance(client,
    asset_type: "CONDITIONAL",
    token_id: "1234567890"
  )

{:ok, open_orders_page} =
  PolymarketClob.API.Account.get_open_orders(client,
    market: "0xconditionid",
    next_cursor: "MA=="
  )

{:ok, trades_page} =
  PolymarketClob.API.Account.get_trades(client,
    market: "0xconditionid",
    next_cursor: "MA=="
  )
```

Private GET requests sign the base endpoint path, matching the official Python client, while
query params are still appended to the URL sent to the CLOB.

### Local Signed Limit Order

```elixir
signed_order =
  PolymarketClob.Order.Builder.build_limit_order(
    client,
    "1234567890",
    10.0,
    0.55,
    :buy,
    tick_size: "0.01",
    neg_risk: false
  )
```

This only builds and signs the order locally. To post an already-built signed order:

```elixir
{:ok, response} =
  PolymarketClob.API.Orders.post_order(client, signed_order)
```

## Endpoint Coverage

Audited against `Polymarket/py-clob-client-v2` commit
`a2ec069fb66096e2b80ff0b7fdf628fc41d6352c`.

Coverage as of the audited commit: 44 of 50 candidate endpoints implemented
(rewards, RFQ, and builder surface are intentionally skipped — see
`ENDPOINT_COVERAGE.md`).

Implemented public read-only endpoints:

- `GET /ok`
- `GET /version`
- `GET /time`
- `GET /markets`
- `GET /simplified-markets`
- `GET /sampling-markets`
- `GET /sampling-simplified-markets`
- `GET /markets/:condition_id`
- `GET /clob-markets/:condition_id`
- `GET /markets-by-token/:token_id`
- `GET /markets/live-activity/:condition_id`
- `GET /book?token_id=...`
- `POST /books`
- `GET /tick-size?token_id=...`
- `GET /neg-risk?token_id=...`
- `GET /fee-rate?token_id=...`
- `GET /midpoint?token_id=...`
- `POST /midpoints`
- `GET /price?token_id=...&side=...`
- `POST /prices`
- `GET /spread?token_id=...`
- `POST /spreads`
- `GET /last-trade-price?token_id=...`
- `POST /last-trades-prices`
- `GET /prices-history?...`

Implemented private read-only endpoints:

- `GET /auth/api-keys`
- `GET /auth/ban-status/closed-only`
- `GET /data/order/:order_id`
- `GET /data/orders?...`
- `GET /data/pre-migration-orders?...`
- `GET /data/trades?...` (also exposed as `Account.get_trades_paginated/3`)
- `GET /order-scoring?order_id=...`
- `GET /balance-allowance?...`
- `GET /notifications?signature_type=...`

Implemented private write endpoints:

- `POST /order` with an already-built signed order map
- `POST /orders` with already-built signed order maps
- `POST /orders-scoring` with a list of order IDs
- `DELETE /order` with an order ID
- `DELETE /orders` with order IDs
- `DELETE /cancel-all`
- `DELETE /cancel-market-orders` with `market` and/or `asset_id`
- `GET /balance-allowance/update?...`
- `DELETE /notifications?ids=...`

Not implemented yet:

- L1/L2 API key lifecycle (`create_api_key`, `derive_api_key`, `delete_api_key`,
  readonly key management) — see `ENDPOINT_COVERAGE.md` for the gating
  product/domain decisions
- reward, RFQ, builder, and WebSocket endpoints (intentionally out of scope for
  this package; see `ENDPOINT_COVERAGE.md`)
- bot integration

Intentional differences from the Python client:

- `get_open_orders/3`, `get_trades/3`, and `get_pre_migration_orders/3` are direct page
  wrappers. They do not auto-paginate yet.
- `get_prices_history/2` accepts caller-supplied CLOB query names such as `:market`,
  `:startTs`, `:endTs`, `:fidelity`, and `:interval`; it does not validate interval
  combinations yet.
- `get_fee_rate/2` is exposed for legacy compatibility; order-building work should prefer
  `get_clob_market_info/2` fee data when fee-aware helpers are added.

## Installation

After publication, add `polymarket_clob` to your dependencies:

```elixir
def deps do
  [
    {:polymarket_clob, "~> 0.1.0"}
  ]
end
```

## Fixture Generation

The checked-in fixtures under `test/fixtures/parity` were generated from the official Python
v2 client at commit `a2ec069fb66096e2b80ff0b7fdf628fc41d6352c`:

```bash
PY_CLOB_CLIENT_V2_PATH=/path/to/py-clob-client-v2 \
  python3 scripts/generate_parity_fixtures.py
```

The script defaults to `/tmp/py-clob-client-v2`, which is useful for local scratch
checkouts during development.
