Skip to content

mdon/polymarket_clob

Repository files navigation

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

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

{: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

{: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

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:

{: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:

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:

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.

About

Standalone Elixir client for the Polymarket CLOB API — EIP-712 order signing, L1/L2 auth, orders, and market data.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages