Polymarket

Higher-level Elixir SDK for Polymarket.

This package builds on polymarket_clob, which owns the low-level CLOB surface (auth, EIP-712 order signing, order placement, balances, order books, prices, market metadata). Use polymarket_clob directly if you only need that surface.

polymarket is for users who want the broader Polymarket SDK — market discovery, normalized public data, P&L helpers, on-chain CTF and pUSD operations, and the real-time trade feed — without bringing in the runnable trading bot.

Status — 0.1.0

The package compiles, depends on polymarket_clob, exposes Polymarket.Config for shared host configuration, and provides the first read-only slice of Polymarket.Gamma for market discovery. Subsequent phases will add the Data API, CTF/pUSD helpers, RTDS, and a higher-level facade.

Implemented:

Not implemented yet:

Response contract

All Polymarket.Gamma and Polymarket.Data wrappers return one of:

See Polymarket.HTTP's @moduledoc for the full options list (:host, :plug, :timeout, :retry, :max_retries, :headers).

Gamma usage

{:ok, markets} =
Polymarket.Gamma.get_markets(
params: [limit: 100, active: true, closed: false, order: "volume24hr"]
)
{:ok, market} = Polymarket.Gamma.get_market("will-x-happen")
{:ok, events} = Polymarket.Gamma.get_events(params: [limit: 50, active: true])

Data API usage

address = "0x8f70343472CC7Fd382DE383723A0E6Ee02e2CAe5"
{:ok, positions} = Polymarket.Data.get_positions(address)
# `usdcSize` on TRADE events is fee-inclusive; this is the source of
# truth for P&L on completed BUY → REDEEM cycles.
{:ok, activity} = Polymarket.Data.get_activity(address, limit: 200)
{:ok, trades} = Polymarket.Data.get_trades(address, limit: 50)

Activity normalization usage

Polymarket.Activity is pure: it consumes whatever maps you have and does not fetch from the network. Pair it with the wrappers above:

{:ok, activity} = Polymarket.Data.get_activity(address)
{:ok, fills} = PolymarketClob.API.Account.get_trades(client, market: market_id)
# Fee-inclusive cost (matches the wallet debit, not the CLOB fill price).
cost = Polymarket.Activity.cost_for_order(activity, order_id, fills["data"] || [])
# Sum of REDEEM payouts for a resolved market.
payout = Polymarket.Activity.redemption_for_market(activity, condition_id)
# Typed events for downstream consumers.
events = Polymarket.Activity.normalize(activity)

All four functions return nil when no event matches, distinguishing "no activity yet" from "events that summed to 0".

RTDS usage

{:ok, _pid} = Polymarket.RTDS.start_link(callback: self())
receive do
{:polymarket_rtds, :trade, payload} ->
IO.inspect(payload, label: "rtds trade")
end

The payload is the raw map sent by Polymarket. Apply Polymarket.Activity.normalize([payload]) if you need a typed Polymarket.Activity.Event struct.

Layered architecture

polymarketthis package (Gamma, Data, CTF, pUSD, RTDS, facade)
└── polymarket_clob (CLOB auth, signing, orders, books, prices)

What this package is NOT

Installation

After publication:

def deps do
[
{:polymarket, "~> 0.1.0"}
]
end

License

MIT.