Skip to main content

polynode

Python SDK for the PolyNode real-time prediction market data platform.

New in v0.11.0: Current-production parity. Trading now defaults to CLOB V2 on clob.polymarket.com, uses PolyNode's public builder attribution unless overridden, omits removed V1 wire fields, and supports V2 GTD expiration. Managed 5-minute, 15-minute, and 4-hour streams select the required 30/60-second Chainlink TWAP lookbacks on a dedicated connection and reconnect/resubscribe at every market rotation. WebSocket models, presets, and filters now cover current redemption, position-conversion, dome/fill, and PM2 combo events. REST position queries now include redeemable/condition filters, multi-wallet batches, and market-holder views; connection and status observability match the current public API.

New in v0.10.8: POLY_1271 V2 order signatures now normalize the ERC-7739 TypedDataSign recovery byte to Ethereum v=27/28 for on-chain ERC-1271 validation.

In v0.10.7: Polymarket V2 deposit-wallet trading fixes. ensure_ready() detects deployed POLY_1271 wallets correctly, V2 type-3 orders use the deposit wallet as both maker and signer, and existing local credentials can be repaired by rerunning ensure_ready().

Install

pip install polynode

For trading support:

pip install polynode[trading]

Quick Start

REST API

from polynode import PolyNode

with PolyNode(api_key="pn_live_...") as pn:
    status = pn.status()
    connections = pn.connections()
    markets = pn.markets(count=10)
    settlements = pn.recent_settlements(count=5)
    wallet_positions = pn.wallet_positions(
        address, redeemable=True, condition_id=condition_id
    )
    batch_positions = pn.multi_wallet_positions([address, second_address], limit=100)
    market_positions = pn.market_positions(
        condition_id, sort_by="CURRENT_VALUE", min_size=0.01
    )
    onchain_positions = pn.wallet_onchain_positions(
        address, since=window_start, tag_slug="crypto"
    )

Sports and Online Context

from polynode import PolyNode

with PolyNode(api_key="pn_live_...") as pn:
    state = pn.sports_game_state(
        "nba-cle-nyk-2026-05-31",
        price_limit_tokens=20,
    )

    context = pn.sports_game_context(
        "nba-cle-nyk-2026-05-31",
        sources=["online"],
        query_set="injuries",
        max_queries=2,
        max_per_query=5,
        include_state=True,
    )

    web = pn.search_online(
        "Cavaliers Knicks injury news",
        max_results=5,
    )

Async REST

import asyncio
from polynode import AsyncPolyNode

async def main():
    async with AsyncPolyNode(api_key="pn_live_...") as pn:
        status = await pn.status()
        markets = await pn.markets(count=10)

asyncio.run(main())

Current presets include dome, fills, combos, redemptions, and deposits. Current filters include since(), combo_condition_ids(), leg_position_ids(), event_ids(), module_ids(), action(), and direction().

dome and fills change settlement delivery into a flat, per-fill wire format. Use one of those presets on a dedicated PolyNodeWS connection when also consuming non-fill events; the server deduplicates delivery per connection and cannot deliver both wire formats for the same settlement.

Chainlink TWAP and short-form markets

The TWAP values are lookback windows, not update cadence: 5-minute markets use 30 seconds; 15-minute and 4-hour markets use 60 seconds.

async def stream_short_markets(pn):
    prices = await (
        pn.ws.subscribe("chainlink")
        .feeds(["BTC/USD", "ETH/USD"])
        .twap_windows([30])
        .send()
    )
    print(prices.price_source, prices.twap_windows, prices.warnings)
    prices.on("price_feed", lambda event: print(event.feed, event.price))

    stream = pn.ws.short_form("5m", coins=["btc", "eth"])
    stream.on("rotation", lambda rotation: print([m.slug for m in rotation.markets]))
    stream.on("price_feed", lambda event: print(event.feed, event.price))
    stream.on("settlement", lambda event: print(event.market_slug, event.status))

A Chainlink selection is scoped to its WebSocket connection, so combine feeds and windows into one Chainlink subscription per connection. The resolved subscription exposes the server acknowledgement through price_source, twap_windows, and warnings. short_form() handles rotation safely with its own socket. At each market boundary it closes that socket, discovers the new slugs, reconnects, and subscribes to the exact settlement and TWAP filters again.

WebSocket Streaming

import asyncio
from polynode import AsyncPolyNode

async def main():
    async with AsyncPolyNode(api_key="pn_live_...") as pn:
        sub = await pn.ws.subscribe("settlements").min_size(1000).send()

        async for event in sub:
            print(event.event_type, event.market_title, event.taker_price)

asyncio.run(main())

Orderbook

import asyncio
from polynode import OrderbookEngine

async def main():
    engine = OrderbookEngine(api_key="pn_live_...")
    await engine.subscribe(["token_id_1", "token_id_2"])

    engine.on("ready", lambda: print(f"Tracking {engine.size} books"))
    engine.on("update", lambda u: print(f"{u.asset_id}: {engine.midpoint(u.asset_id)}"))

asyncio.run(main())

Trading

import asyncio
from polynode.trading import PolyNodeTrader, TraderConfig, OrderParams, ExchangeVersion

async def main():
    # CLOB V2 (pUSD collateral) is the current production default.
    trader = PolyNodeTrader(TraderConfig(
        polynode_key="pn_live_...",
        # exchange_version=ExchangeVersion.V2,
        # builder_code=None,  # disables default public PolyNode attribution
    ))
    status = await trader.ensure_ready("0xYourPrivateKey...")

    result = await trader.order(OrderParams(
        token_id="...",
        side="BUY",
        price=0.55,
        size=100,
        builder="0x<your_builder_code_bytes32>",  # V2 only; omit for V1
    ))
    print(result)

    trader.close()

asyncio.run(main())

For the V2 order flow — required approvals, EIP-712 struct, fee math, and common failure modes — see polynode/trading/V2_ORDER_FLOW.md in the installed package.

V2 fees are determined at match time and are not signed into an order, so V2 payloads omit feeRateBps, nonce, and taker. Explicit legacy V1 mode still signs feeRateBps; for that path the SDK fetches /fee-rate and fails closed if fee, tick-size, or neg-risk metadata is unavailable or malformed.

Documentation

Full docs at docs.polynode.dev

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

polynode-0.11.0.tar.gz (65.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

polynode-0.11.0-py3-none-any.whl (82.0 kB view details)

Uploaded Python 3

File details

Details for the file polynode-0.11.0.tar.gz.

File metadata

  • Download URL: polynode-0.11.0.tar.gz
  • Upload date:
  • Size: 65.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.3

File hashes

Hashes for polynode-0.11.0.tar.gz
Algorithm Hash digest
SHA256 3f2f3cf8c1ed7c5a0a4d4db179bced723f21f197b47e93d702102c3bfb99eb55
MD5 3f1675945dcff147f5414214326f6fe3
BLAKE2b-256 99336d9ee6c9d5d88e3eaaa5ff9f6fe8a0faca0b4e81de2ea98edb4a27e6fa5f

See more details on using hashes here.

File details

Details for the file polynode-0.11.0-py3-none-any.whl.

File metadata

  • Download URL: polynode-0.11.0-py3-none-any.whl
  • Upload date:
  • Size: 82.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.3

File hashes

Hashes for polynode-0.11.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a086eb3ad27d7b250be201a174c7b8ba716b3b2030c26b789198b30503e01595
MD5 63a0e1e93fceeea6641f1acfdc0bdb97
BLAKE2b-256 f956b1fe5cacb4c58200344ea248b07825ada0ac2f05cf70b1b9e892dbba4d7a

See more details on using hashes here.

Release history Release notifications | RSS feed

0.14.1

2 files

0.14.0

2 files

0.13.0

2 files

0.12.2

2 files

0.12.1

2 files

0.12.0

2 files

This release

0.11.0 This release

2 files

0.10.8

2 files

0.10.7

2 files

0.10.6

2 files

0.10.5

2 files

0.10.4

2 files

0.10.3

2 files

0.10.2

2 files

0.10.1

2 files

0.10.0

2 files

0.9.3

2 files

0.9.2

2 files

0.9.1

1 file

0.9.0

1 file

0.8.0

1 file

0.7.4

2 files

0.7.3

2 files

0.7.2

2 files

0.7.1

2 files

0.7.0

2 files

0.6.3

2 files

0.6.2

2 files

0.6.1

2 files

0.6.0

2 files

0.5.5

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page