polymarket

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 1, 2026 License: MIT Imports: 15 Imported by: 0

README

polymarket-us-go

Go Reference CI

Unofficial Go client library for the Polymarket US exchange API. Not affiliated with Polymarket.

This targets the CFTC-regulated Polymarket US exchange (api.polymarket.us) — not the crypto Polymarket CLOB API, which is a completely different protocol. The wire format follows the official TypeScript and Python SDKs (v0.1.x). Since the upstream API is young, expect this client to track breaking changes until it stabilizes.

Status

Beta — live testing in progress. The API surface is complete and the tests are green, but the client is still accumulating live production usage. See ROADMAP.md for what's being verified and what's planned.

Install

go get github.com/jaracah/polymarket-us-go

Requires Go 1.23+. One dependency: coder/websocket (itself dependency-free).

Full API documentation is on pkg.go.dev.

Public market data (no credentials)

import polymarket "github.com/jaracah/polymarket-us-go"

c := polymarket.NewClient(nil)

markets, err := c.ListMarkets(ctx, polymarket.MarketFilter{ActiveOnly: true, Limit: 20})
market, err := c.FetchMarket(ctx, "btc-100k")
event, err := c.FetchEvent(ctx, "super-bowl-2027")

book, err := c.FetchBook(ctx, "btc-100k") // full depth
bbo, err := c.FetchBBO(ctx, "btc-100k")   // top of book
fmt.Println(bbo.BidC, bbo.AskC)            // integer cents
fmt.Println(bbo.BidPx, bbo.AskPx)          // raw decimal strings

settle, err := c.FetchSettlement(ctx, "btc-100k") // outcome of a resolved market

A client built with NewClient is strictly read-only: it holds no credentials and never touches a trading endpoint.

Trading (authenticated)

Generate an API key at polymarket.us/developer. You get a key ID (UUID) and a base64-encoded Ed25519 secret key; requests are signed with X-PM-* headers automatically.

signer, err := polymarket.NewSigner(os.Getenv("POLYMARKET_KEY_ID"), os.Getenv("POLYMARKET_SECRET_KEY"))
c := polymarket.NewAuthedClient(nil, signer, "", "") // "" = production hosts

// Cheap connectivity/credentials probe
bal, err := c.Balance(ctx)

// Place a limit order: buy 100 LONG contracts at 55¢, immediate-or-cancel
res, err := c.CreateOrder(ctx, polymarket.Order{
    MarketSlug: "btc-100k",
    Intent:     polymarket.IntentBuyLong,
    Quantity:   100,
    PriceC:     55,
})
fmt.Println(res.FillCount, res.AvgPriceC, res.State)

// Resting orders
res, err = c.CreateOrder(ctx, polymarket.Order{
    MarketSlug:  "btc-100k",
    Intent:      polymarket.IntentBuyLong,
    Quantity:    100,
    PriceC:      52,
    TimeInForce: polymarket.TIFGoodTillCancel,
    PostOnly:    true, // reject instead of crossing
})

open, err := c.OpenOrders(ctx)                       // optionally filter by slugs
err = c.CancelOrder(ctx, res.OrderID, "btc-100k")
ids, err := c.CancelAllOrders(ctx)                   // flatten-fast path
res, err = c.ClosePosition(ctx, "btc-100k")          // market-close one position
positions, err := c.Positions(ctx)                   // map[slug]Position, cursor-paginated

The exchange trades LONG and SHORT as separate instruments, so there are four order intents (IntentBuyLong, IntentSellLong, IntentBuyShort, IntentSellShort) and prices always quote the named instrument — no 100 − p mental arithmetic.

WebSocket streams

Both streams require credentials (the exchange authenticates even market data). The API is pull-based: dial, subscribe, then read messages in a loop.

// Market data: books, BBOs, trades
ms, err := c.DialMarkets(ctx)
defer ms.Close()
ms.SubscribeBooks(ctx, "books-1", "btc-100k")
ms.SubscribeTrades(ctx, "tape-1", "btc-100k")
for {
    msg, err := ms.Next(ctx)
    if err != nil {
        break // transport error: redial and re-subscribe
    }
    switch {
    case msg.Book != nil:
        // full-depth refresh
    case msg.Trade != nil:
        // one print off the tape
    case msg.Err != "":
        // server rejected the subscription keyed by msg.RequestID
    }
}

// Private data: order executions, positions, balances
ps, err := c.DialPrivate(ctx)
defer ps.Close()
ps.SubscribeOrders(ctx, "orders-1")
ps.SubscribePositions(ctx, "pos-1")
ps.SubscribeBalance(ctx, "bal-1")
for {
    msg, err := ps.Next(ctx)
    if err != nil {
        break
    }
    if msg.Execution != nil {
        // fills, cancels, rejections as they happen
    }
}

Subscriptions do not survive a reconnect — after a transport error, redial and re-subscribe.

Design notes

  • Prices parse to integer cents (PriceC, AvgPriceC, …) because binary contracts trade in 1–99¢ and integer math avoids float drift in P&L. Every exchange-set number also carries the raw decimal string (Px, Qty, AvgPx, …), so nothing is lost if the exchange ever quotes sub-cent ticks.
  • Order placement never retries. The API has no client order ID, so a retried create would be a brand-new order. CreateOrder and ClosePosition make exactly one attempt; after an ambiguous failure, reconcile with OpenOrders/Positions before re-sending. Reads and cancels are idempotent and retry 429s with backoff.
  • Typed HTTP errors. Non-2xx responses surface as *polymarket.APIError carrying the status code and the exchange's reason — match with errors.As to branch on 401/404/429.
  • Rejections are errors. An order that comes back EXECUTION_TYPE_REJECTED returns an error carrying the exchange's reason, never a quiet zero-fill. A fill reported without a usable average price is also an error rather than a 0¢ cost basis.
  • Strict where money is counted, tolerant where it isn't. Unparseable position quantities error (they feed reconciliation); malformed display fields degrade to zero values.

Contributing

Issues and pull requests are welcome — see CONTRIBUTING.md for the checks to run and the invariants to preserve. The test suite is fully hermetic (go test -race ./... needs no network access or credentials).

Disclaimer

This is an unofficial client, not affiliated with or endorsed by Polymarket. Trading involves risk of loss; use at your own risk, and test against small orders before automating anything with real money.

License

MIT

Documentation

Overview

Request signing for the authenticated endpoints, matching the official polymarket-us SDKs: the message timestampMs + METHOD + path — path EXCLUDES query parameters — is signed with Ed25519 and sent base64-encoded in three X-PM-* headers. The same headers on the HTTP upgrade request (method "GET", the stream path) authenticate WebSocket connections.

Client construction, public market-data endpoints, and the shared HTTP plumbing. Trading endpoints live in trading.go, WebSocket streams in ws.go, request signing in auth.go. See doc.go for the package overview.

Package polymarket is an unofficial Go client for the Polymarket US exchange API (api.polymarket.us). It is not affiliated with Polymarket.

Without a Signer the client is strictly read-only public market data (NewClient — no credentials, nothing is ever sent to trading endpoints). With one (NewAuthedClient) the trading endpoints and the WebSocket streams become available:

c := polymarket.NewClient(nil)
bbo, err := c.FetchBBO(ctx, "some-market-slug")

signer, err := polymarket.NewSigner(keyID, secretKey)
c = polymarket.NewAuthedClient(nil, signer, "", "")
res, err := c.CreateOrder(ctx, polymarket.Order{...})

The wire protocol follows the official polymarket-us TypeScript and Python SDKs (v0.1.x): requests are authenticated with Ed25519-signed X-PM-* headers, public market data is served from a gateway host, and trading plus both WebSocket streams use the api host.

Prices and quantities

Prices cross the wire as decimal-dollar Amount objects ({"value":"0.55", "currency":"USD"}). For convenience this package parses prices to integer cents (and quantities to float64) wherever it decodes a response; fields set by the exchange also carry the raw decimal strings (Px, Qty, AvgPx, ...) so no precision is ever lost to the conversion.

Errors

A non-2xx response surfaces as *APIError, carrying the HTTP status and the exchange's reason; match it with errors.As. Order rejections arrive inside 2xx execution streams and surface as plain errors from CreateOrder/ClosePosition with the reject reason.

Retries

Reads and cancels retry 429s with linear backoff. Order placement makes exactly one attempt: the API has no client order id, so a retried create would be a brand-new order. After an ambiguous failure, reconcile with OpenOrders/Positions before re-sending.

Authenticated trading endpoints: orders, positions, balance. All of these require a Signer (NewAuthedClient); the read-only market-data client never touches them. They hit the api host, not the public gateway.

The exchange has four order intents because LONG and SHORT are separate instruments: BUY_LONG/SELL_LONG open and close a long (yes) position, BUY_SHORT/SELL_SHORT the short side. Prices always quote the named instrument — there is no 100−p inversion anywhere.

Order placement does NOT retry. This API has no client order id, so a retried create is a brand-new order to the exchange — after a 429 or an ambiguous transport failure the only safe recovery is to reconcile via OpenOrders/Positions, which is the caller's job. Cancels and reads are idempotent and keep the retry loop.

WebSocket streams: market data (books, BBOs, trades) and private data (order executions, positions, balances), both on the api host and both requiring a Signer — the exchange authenticates even the market stream. Auth rides the HTTP upgrade request as the same three X-PM-* headers, signed over "GET" + the stream path.

The shape is pull-based: Dial, Subscribe*, then call Next in a loop. Next returns one parsed message; an error from Next about one message's content leaves the stream usable, a transport error does not (redial to recover — subscriptions do not survive a reconnect).

Concurrency: at most one goroutine may call Next at a time. Subscribe*, Unsubscribe, and Close are safe to call concurrently with Next and with each other (the underlying library serializes writes).

Index

Examples

Constants

View Source
const (
	DefaultGatewayURL = "https://gateway.polymarket.us"
	DefaultAPIURL     = "https://api.polymarket.us"
)

Production hosts. Public market data and authenticated trading are served from different bases; the client routes by endpoint, callers never choose.

View Source
const (
	IntentBuyLong   = "ORDER_INTENT_BUY_LONG"
	IntentSellLong  = "ORDER_INTENT_SELL_LONG"
	IntentBuyShort  = "ORDER_INTENT_BUY_SHORT"
	IntentSellShort = "ORDER_INTENT_SELL_SHORT"
)

Order intents. BUY_LONG opens/extends a long (yes) position; SELL_LONG unwinds one. The SHORT pair does the same for the short (no) side.

View Source
const (
	TIFImmediateOrCancel = "TIME_IN_FORCE_IMMEDIATE_OR_CANCEL"
	TIFGoodTillCancel    = "TIME_IN_FORCE_GOOD_TILL_CANCEL"
	TIFFillOrKill        = "TIME_IN_FORCE_FILL_OR_KILL"
)

Time-in-force values (the API also offers GOOD_TILL_DATE, which this client does not support).

View Source
const (
	StateNew             = "ORDER_STATE_NEW"
	StatePartiallyFilled = "ORDER_STATE_PARTIALLY_FILLED"
	StateFilled          = "ORDER_STATE_FILLED"
	StateCanceled        = "ORDER_STATE_CANCELED"
	StateRejected        = "ORDER_STATE_REJECTED"
	StateExpired         = "ORDER_STATE_EXPIRED"
)

Order states (subset — the full machine includes PENDING_* transients).

View Source
const (
	SubMarketData     = "SUBSCRIPTION_TYPE_MARKET_DATA"      // full book refreshes
	SubMarketDataLite = "SUBSCRIPTION_TYPE_MARKET_DATA_LITE" // best bid/ask only
	SubTrade          = "SUBSCRIPTION_TYPE_TRADE"
	SubOrder          = "SUBSCRIPTION_TYPE_ORDER"
	SubPosition       = "SUBSCRIPTION_TYPE_POSITION"
	SubAccountBalance = "SUBSCRIPTION_TYPE_ACCOUNT_BALANCE"
)

Subscription types, matching the exchange's vocabulary.

Variables

This section is empty.

Functions

This section is empty.

Types

type APIError

type APIError struct {
	StatusCode int    // HTTP status
	What       string // request label, e.g. "create order btc-100k"
	Body       string // response body (truncated) — the exchange's reason
}

APIError is a non-2xx response from the exchange. Match with errors.As to branch on StatusCode:

var apiErr *polymarket.APIError
if errors.As(err, &apiErr) && apiErr.StatusCode == 429 { ... }

Order rejections are NOT APIErrors — the exchange reports them inside a 2xx execution stream, and CreateOrder surfaces them as plain errors carrying the reject reason.

func (*APIError) Error

func (e *APIError) Error() string

type Amount

type Amount struct {
	Value    string `json:"value"`
	Currency string `json:"currency"`
}

Amount is the API's money shape: a decimal-dollar string plus currency.

func USD

func USD(cents int) Amount

USD builds an Amount from integer cents (negative cents for debits).

func (Amount) Cents

func (a Amount) Cents() int

Cents returns the amount in nearest integer cents (0 for empty/junk).

type BBO

type BBO struct {
	MarketSlug  string
	BidC        int
	AskC        int
	LastTradeC  int
	BidPx       string
	AskPx       string
	LastTradePx string
}

BBO is a market's top of book. The cents fields are 0 when that side is empty; the Px fields carry the exchange's exact decimals.

type Balance

type Balance struct {
	BalanceC     int64 // settled cash
	BuyingPowerC int64
}

Balance is the account's cash state in cents.

type Book

type Book struct {
	MarketSlug string
	Bids       []Level
	Offers     []Level
	State      string // MARKET_STATE_OPEN | _SUSPENDED | _HALTED | ...
}

Book is a market's full displayed depth. Both sides quote the same instrument (the market's LONG contract): bids are resting buys, offers resting sells. Best-priced level first on each side.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client reads public market data, and — when built by NewAuthedClient — places orders and reads the portfolio. The zero value is not usable.

func NewAuthedClient

func NewAuthedClient(hc *http.Client, signer *Signer, gatewayURL, apiURL string) *Client

NewAuthedClient returns a Client that signs trading requests with signer. gatewayURL/apiURL "" mean production; tests pass their own.

func NewClient

func NewClient(hc *http.Client) *Client

NewClient returns a read-only Client using hc (or a sane default if hc is nil).

Example

Read public market data with no credentials.

package main

import (
	"context"
	"fmt"
	"log"

	polymarket "github.com/jaracah/polymarket-us-go"
)

func main() {
	c := polymarket.NewClient(nil)

	bbo, err := c.FetchBBO(context.Background(), "some-market-slug")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("bid %d¢ ask %d¢ (raw %s/%s)\n", bbo.BidC, bbo.AskC, bbo.BidPx, bbo.AskPx)
}

func (*Client) Balance

func (c *Client) Balance(ctx context.Context) (Balance, error)

Balance returns the account's first (USD) balance. It also serves as a cheap authenticated connectivity probe at startup.

func (*Client) CancelAllOrders

func (c *Client) CancelAllOrders(ctx context.Context, slugs ...string) ([]string, error)

CancelAllOrders cancels every open order (or, with slugs, every open order in those markets) and returns the canceled ids.

func (*Client) CancelOrder

func (c *Client) CancelOrder(ctx context.Context, orderID, marketSlug string) error

CancelOrder cancels one resting order. The API requires the order's market slug alongside its id.

func (*Client) ClosePosition

func (c *Client) ClosePosition(ctx context.Context, marketSlug string) (OrderResult, error)

ClosePosition asks the exchange to flatten the position in one market at market price and reports what executed. Like CreateOrder it is a single attempt — it places an order.

func (*Client) CreateOrder

func (c *Client) CreateOrder(ctx context.Context, o Order) (OrderResult, error)

CreateOrder places o (always a limit order — market orders need slippage-tolerance machinery this client does not implement) and reports what executed synchronously. Single attempt, never retried: with no client order id, a retry is a second order (see the package comment in this file).

Example

Place a limit order with an authenticated client.

package main

import (
	"context"
	"errors"
	"fmt"
	"log"
	"net/http"
	"os"

	polymarket "github.com/jaracah/polymarket-us-go"
)

func main() {
	signer, err := polymarket.NewSigner(
		os.Getenv("POLYMARKET_KEY_ID"),
		os.Getenv("POLYMARKET_SECRET_KEY"),
	)
	if err != nil {
		log.Fatal(err)
	}
	c := polymarket.NewAuthedClient(nil, signer, "", "")

	res, err := c.CreateOrder(context.Background(), polymarket.Order{
		MarketSlug: "some-market-slug",
		Intent:     polymarket.IntentBuyLong,
		Quantity:   100,
		PriceC:     55, // 55¢ limit, zero TimeInForce = immediate-or-cancel
	})
	if err != nil {
		var apiErr *polymarket.APIError
		if errors.As(err, &apiErr) && apiErr.StatusCode == http.StatusTooManyRequests {
			// Rate limited before the order reached the book. Do NOT blindly
			// re-send after an ambiguous failure — reconcile with
			// OpenOrders/Positions first (there is no client order id).
		}
		log.Fatal(err)
	}
	fmt.Printf("order %s: filled %d @ %d¢, %d resting\n",
		res.OrderID, res.FillCount, res.AvgPriceC, res.Remaining)
}

func (*Client) DialMarkets

func (c *Client) DialMarkets(ctx context.Context) (*MarketsStream, error)

DialMarkets opens the market-data stream.

Example

Consume live books and trades from the market-data stream.

package main

import (
	"context"
	"fmt"
	"log"
	"os"

	polymarket "github.com/jaracah/polymarket-us-go"
)

func main() {
	signer, err := polymarket.NewSigner(
		os.Getenv("POLYMARKET_KEY_ID"),
		os.Getenv("POLYMARKET_SECRET_KEY"),
	)
	if err != nil {
		log.Fatal(err)
	}
	c := polymarket.NewAuthedClient(nil, signer, "", "")

	ctx := context.Background()
	st, err := c.DialMarkets(ctx)
	if err != nil {
		log.Fatal(err)
	}
	defer st.Close()

	if err := st.SubscribeBooks(ctx, "books-1", "some-market-slug"); err != nil {
		log.Fatal(err)
	}
	for {
		msg, err := st.Next(ctx)
		if err != nil {
			log.Fatal(err) // transport error: redial and re-subscribe
		}
		switch {
		case msg.Book != nil:
			fmt.Printf("%s: %d bids, %d offers\n",
				msg.Book.MarketSlug, len(msg.Book.Bids), len(msg.Book.Offers))
		case msg.Err != "":
			log.Printf("subscription %s failed: %s", msg.RequestID, msg.Err)
		}
	}
}

func (*Client) DialPrivate

func (c *Client) DialPrivate(ctx context.Context) (*PrivateStream, error)

DialPrivate opens the private stream.

func (*Client) FetchBBO

func (c *Client) FetchBBO(ctx context.Context, slug string) (BBO, error)

FetchBBO returns a market's top of book.

func (*Client) FetchBook

func (c *Client) FetchBook(ctx context.Context, slug string) (Book, error)

FetchBook returns a market's live displayed depth.

func (*Client) FetchEvent

func (c *Client) FetchEvent(ctx context.Context, slug string) (Event, error)

FetchEvent returns one event (with its nested markets) by slug.

func (*Client) FetchMarket

func (c *Client) FetchMarket(ctx context.Context, slug string) (Market, error)

FetchMarket returns one market by slug.

func (*Client) FetchOrder

func (c *Client) FetchOrder(ctx context.Context, orderID string) (OpenOrder, error)

FetchOrder returns one order by id.

func (*Client) FetchSettlement

func (c *Client) FetchSettlement(ctx context.Context, slug string) (Settlement, error)

FetchSettlement returns a settled market's settlement price and time.

func (*Client) ListMarkets

func (c *Client) ListMarkets(ctx context.Context, f MarketFilter) ([]Market, error)

ListMarkets returns markets matching f.

func (*Client) OpenOrders

func (c *Client) OpenOrders(ctx context.Context, slugs ...string) ([]OpenOrder, error)

OpenOrders returns open orders, optionally filtered to the given market slugs.

func (*Client) Positions

func (c *Client) Positions(ctx context.Context) (map[string]Position, error)

Positions returns all positions keyed by market slug, following the cursor until the API reports eof.

type Event

type Event struct {
	ID        int64    `json:"id"`
	Slug      string   `json:"slug"`
	Title     string   `json:"title"`
	StartTime string   `json:"startTime"` // ISO-8601
	EndTime   string   `json:"endTime"`   // ISO-8601
	Active    bool     `json:"active"`
	Closed    bool     `json:"closed"`
	Markets   []Market `json:"markets"`
}

Event groups related markets (e.g. one game, one date's question).

type Level

type Level struct {
	PriceC int     // price in integer cents
	Size   float64 // contracts
	Px     string  // raw decimal-dollar price, e.g. "0.55"
	Qty    string  // raw decimal quantity
}

Level is one resting orderbook level. PriceC and Size are parsed for convenience; Px and Qty are the exchange's exact decimal strings.

type Market

type Market struct {
	ID          int64   `json:"id"`
	Slug        string  `json:"slug"`
	Title       string  `json:"title"`
	Outcome     string  `json:"outcome"`
	Description string  `json:"description"`
	Active      bool    `json:"active"`
	Closed      bool    `json:"closed"`
	Liquidity   float64 `json:"liquidity"`
	Volume      float64 `json:"volume"`
	EventSlug   string  `json:"eventSlug"`
}

Market is one tradeable outcome; an Event groups the related markets.

type MarketFilter

type MarketFilter struct {
	EventSlug  string
	ActiveOnly bool
	Limit      int // 0 = server default
	Offset     int
}

MarketFilter narrows ListMarkets. Zero fields are omitted; ActiveOnly maps to active=true&closed=false.

type MarketsMessage

type MarketsMessage struct {
	RequestID string
	Heartbeat bool
	Err       string // server-reported subscription error
	Book      *Book
	BBO       *BBO
	Trade     *StreamTrade
}

MarketsMessage is one parsed frame off the market stream. Exactly one of Book, BBO, Trade is non-nil unless Heartbeat is set or Err is non-empty.

type MarketsStream

type MarketsStream struct {
	// contains filtered or unexported fields
}

MarketsStream is the market-data stream (path /v1/ws/markets).

func (*MarketsStream) Close

func (s *MarketsStream) Close() error

Close closes the connection.

func (*MarketsStream) Next

Next blocks for one frame and parses it.

func (*MarketsStream) SubscribeBBOs

func (s *MarketsStream) SubscribeBBOs(ctx context.Context, requestID string, slugs ...string) error

SubscribeBBOs streams top-of-book updates for slugs.

func (*MarketsStream) SubscribeBooks

func (s *MarketsStream) SubscribeBooks(ctx context.Context, requestID string, slugs ...string) error

SubscribeBooks streams full-depth Book refreshes for slugs.

func (*MarketsStream) SubscribeTrades

func (s *MarketsStream) SubscribeTrades(ctx context.Context, requestID string, slugs ...string) error

SubscribeTrades streams the tape for slugs.

func (*MarketsStream) Unsubscribe

func (s *MarketsStream) Unsubscribe(ctx context.Context, requestID string) error

Unsubscribe cancels the subscription opened under requestID.

type OpenOrder

type OpenOrder struct {
	ID          string
	MarketSlug  string
	Intent      string
	PriceC      int
	Quantity    int
	CumQuantity int
	Remaining   int
	TimeInForce string
	State       string
	AvgPriceC   int
	AvgPx       string // raw decimal average fill price ("" when no fill)
	CreateTime  string // ISO-8601
}

OpenOrder is one resting or recently-terminal order.

type Order

type Order struct {
	MarketSlug  string
	Intent      string // IntentBuyLong | IntentSellLong | IntentBuyShort | IntentSellShort
	Quantity    int    // whole contracts, > 0
	PriceC      int    // limit price in cents, 1..99
	TimeInForce string // "" (= TIFImmediateOrCancel), TIFGoodTillCancel, or TIFFillOrKill
	PostOnly    bool
}

Order is a limit order in integer cents and whole contracts. The zero TimeInForce is IOC. PostOnly (the API's participateDontInitiate) makes the exchange reject a placement that would cross instead of taking; it requires a resting time-in-force.

type OrderResult

type OrderResult struct {
	OrderID   string
	FillCount int    // contracts filled so far (cumQuantity)
	Remaining int    // contracts still open (leavesQuantity)
	AvgPriceC int    // volume-weighted average fill price, cents (0 when no fill)
	AvgPx     string // raw decimal average fill price ("" when no fill)
	State     string // final ORDER_STATE_* seen, "" if the response carried none
}

OrderResult is the exchange's synchronous answer to an order (the client sends synchronousExecution so IOC outcomes come back in the response).

type OrderSnapshot

type OrderSnapshot struct {
	Orders []OpenOrder
	EOF    bool
}

OrderSnapshot is the subscription-open replay of resting orders. EOF marks the last snapshot frame; updates follow.

type Position

type Position struct {
	Net       int
	NetFP     float64 // netPosition verbatim; fractional while partially unwound
	CostC     int     // aggregate cost basis, cents
	RealizedC int     // realized P&L, cents
	Expired   bool
}

Position is one market's exchange-side position. Net is positive for a long holding and negative for a short one, matching the sign of the exchange's netPosition.

type PositionSnapshot

type PositionSnapshot struct {
	Positions map[string]Position
	EOF       bool
}

PositionSnapshot is the subscription-open replay of positions by slug.

type PositionUpdate

type PositionUpdate struct {
	MarketSlug string
	Position   Position
}

PositionUpdate is one market's position after a change.

type PrivateMessage

type PrivateMessage struct {
	RequestID        string
	Heartbeat        bool
	Err              string
	OrderSnapshot    *OrderSnapshot
	Execution        *StreamExecution
	PositionSnapshot *PositionSnapshot
	PositionUpdate   *PositionUpdate
	Balance          *Balance
}

PrivateMessage is one parsed frame off the private stream. Exactly one payload field is non-nil unless Heartbeat is set or Err is non-empty. Balance covers both the snapshot and update frames (same shape).

type PrivateStream

type PrivateStream struct {
	// contains filtered or unexported fields
}

PrivateStream is the account stream (path /v1/ws/private).

func (*PrivateStream) Close

func (s *PrivateStream) Close() error

Close closes the connection.

func (*PrivateStream) Next

Next blocks for one frame and parses it. A parse error on one frame's content (e.g. an unparseable position) is returned but consumes only that frame — the stream remains readable.

func (*PrivateStream) SubscribeBalance

func (s *PrivateStream) SubscribeBalance(ctx context.Context, requestID string) error

SubscribeBalance streams the account balance.

func (*PrivateStream) SubscribeOrders

func (s *PrivateStream) SubscribeOrders(ctx context.Context, requestID string, slugs ...string) error

SubscribeOrders streams the open-order snapshot then per-execution updates, optionally filtered to slugs.

func (*PrivateStream) SubscribePositions

func (s *PrivateStream) SubscribePositions(ctx context.Context, requestID string, slugs ...string) error

SubscribePositions streams the position snapshot then per-market updates, optionally filtered to slugs.

func (*PrivateStream) Unsubscribe

func (s *PrivateStream) Unsubscribe(ctx context.Context, requestID string) error

Unsubscribe cancels the subscription opened under requestID.

type Settlement

type Settlement struct {
	MarketSlug string
	PriceC     int
	Px         string // raw decimal settlement price
	SettledAt  string // ISO-8601
}

Settlement is a settled market's final price.

type Signer

type Signer struct {
	// contains filtered or unexported fields
}

Signer holds an API key id and its Ed25519 private key, and signs requests in place. Safe for concurrent use. Generate API keys at https://polymarket.us/developer.

func NewSigner

func NewSigner(keyID, secretKey string) (*Signer, error)

NewSigner decodes secretKey (base64; either a 32-byte Ed25519 seed or a 64-byte private key, of which the seed is the first half — both shapes are issued in the wild and both official SDKs accept them) and returns a Signer for keyID. The key material never leaves the process.

type StreamExecution

type StreamExecution struct {
	Type         string // EXECUTION_TYPE_*
	Order        OpenOrder
	LastShares   float64 // contracts in this execution (fills)
	LastQty      string  // raw decimal contracts in this execution
	LastPriceC   int     // price of this execution, cents (fills)
	LastPx       string  // raw decimal price of this execution
	TradeID      string
	Aggressor    bool
	TransactTime string // ISO-8601
	RejectReason string
}

StreamExecution is one execution-report update on an order.

type StreamTrade

type StreamTrade struct {
	MarketSlug  string
	PriceC      int
	Quantity    float64
	Px          string // raw decimal price
	Qty         string // raw decimal quantity
	TradeTime   string // ISO-8601
	TakerIntent string // ORDER_INTENT_* of the aggressor
}

StreamTrade is one print off the tape.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL