Skip to main content

Official Python SDK for Polyester APIs.

Project description

Polyester Python SDK

Official Python SDK for Polyester APIs, built for trading bots, backend jobs, research notebooks, and automation.

Status: Alpha (0.1.0a0). The repo is public (visible on GitHub) under a proprietary license — not open source. API-key-only; no browser or JWT flows.

Generated protobuf types and ConnectRPC clients live in src/polyester/gen/ and are updated automatically when public API protos change. Hand-written SDK code (client, services, models, codecs) lives alongside them under src/polyester/.

Install

Install the SDK from PyPI:

pip install "polyester-sdk[realtime]"

For local development from a checkout:

cd polyester-sdk-python
python3.11 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev,realtime]"

Authentication

Pass credentials to the client from your app's config or secrets manager:

from polyester import AsyncPolyester

client = AsyncPolyester(
    api_key_id="ak_...",
    api_private_key="...",  # 64-char hex Ed25519 secret or raw 32-byte key
)

If your app uses environment variables, read them in your application code and pass them explicitly:

import os

from polyester import AsyncPolyester

client = AsyncPolyester(
    api_key_id=os.environ["POLYESTER_API_KEY_ID"],
    api_private_key=os.environ["POLYESTER_API_PRIVATE_KEY"],
    default_account_id=os.getenv("POLYESTER_ACCOUNT_ID"),
)

For scripts and local tests, AsyncPolyester.from_env() and Polyester.from_env() are convenience helpers that read POLYESTER_* from os.environ. The plain constructor does not implicitly read environment variables.

Quickstart

from polyester import AsyncPolyester

async with AsyncPolyester(
    api_key_id="ak_...",
    api_private_key="...",
) as client:
    overview = await client.market_overview.list(limit=5)
    for market in overview.markets:
        print(market.symbol, market.last_price_ticks)

    open_orders = await client.orders.list_open()
    print(f"{len(open_orders.orders)} open orders")

Create And Cancel

from polyester import AsyncPolyester

async with AsyncPolyester(
    api_key_id="ak_...",
    api_private_key="...",
    default_sub_account_id="",
) as client:
    result = await client.orders.create(
        symbol="BNB-USDT",
        side="buy",
        order_type="limit",
        tif="gtc",
        qty="0.01",
        price="100",
        post_only=True,
        client_order_id="my-bot-001",
    )
    print(result.status, result.order_id)

    await client.orders.cancel(client_order_id="my-bot-001")

Use decimal strings for qty and price. Do not pass floats.

Balances: funding vs trading

Ledger balances expose separate funding and trading buckets per asset. Spot orders spend trading balance. Deposits land in funding until you move them (Funding → Unified Trading in the UI or on-chain via the funding wallet).

  • Funding → trading: on-chain TradingGateway.deposit (not an API-key RPC).
  • Trading → funding: client.trading_withdraws.create_to_funding(...) with a signed intent payload.
  • Trading → trading (another account): client.internal_transfers.create(...) or client.ledger_write.transfer_trading_to_trading(...).

Format u128 wire amounts with the public helper (18-decimal scale):

from polyester import format_ledger_u128

print(format_ledger_u128(balance.funding), format_ledger_u128(balance.trading))

Set POLYESTER_ACCOUNT_ID to your profile base58 id (not a raw decimal uint64) for bucket transfers.

Public Market Data

candles = await client.market_data.get_candles(symbol="BTC-USDT", timeframe="1m", limit=50)
current = await client.market_data.get_current_candle(symbol="BTC-USDT", timeframe="1m")
trades = await client.market_data.get_trades(symbol="BTC-USDT", limit=20)
health = await client.balances.get_health()

async with client.market_data.subscribe_trades(symbol="BNB-USDT") as sub:
    async for trade in sub:
        print(trade.price_ticks, trade.qty_scaled)
        break

Realtime requires pip install polyester-sdk[realtime] (websockets).

Merged market overview stream (snapshot + live updates):

sub = await client.market_overview.create_subscription()
async for markets in sub:
    print(len(markets), "rows")
    break
await sub.aclose()

Testing

CI (no network): pytest tests/unit -q, plus ruff and package build.

Full local suite: devnet integration/e2e tests read .env in the test harness and pass credentials to the client as explicit constructor parameters.

cp .env.example .env
# POLYESTER_API_KEY_ID, POLYESTER_API_PRIVATE_KEY, POLYESTER_ACCOUNT_ID

pip install -e ".[dev,realtime]"

./scripts/test_all.sh          # unit + tiered live (reads .env flags)
# or
pytest tests/unit -q           # CI-equivalent
pytest tests/ -v               # full suite
python scripts/smoke_test.py   # backwards-compatible read/mutation wrapper

Useful markers include smoke, mutation, funded, treasury, optional, realtime, and jwt_session.

Known devnet skips (not SDK failures)

Skip reason Tests affected
OMS read never indexes after orders.create test_order_round_trip, test_batch_create_and_cancel
No open orders on book test_orders_get_round_trips_list_open
list_holds unmounted balance holds tests
JWT/session-only routes profile, whiteboard, resolve, etc.
Guard signer not on account test_guard_signer_get_status
No BTC-USDT asks / POLYESTER_TEST_TRADE_E2E test_spot_fill

Attach a read/trade policy to your API key. Spot orders need USDT in unified trading (not BTC).

Some RPCs return HTTP 404 on devnet. The SDK raises PolyesterRouteNotFoundError with a clearer message than [unimplemented]: Not Found.

Changelog

See CHANGELOG.md.

Transport

Connect RPC over HTTP via generated clients in src/polyester/gen/. Wire format defaults to binary protobuf; pass wire_format="json" for debugging.

Project details


Download files

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

Source Distribution

polyester_sdk-0.1.0a0.tar.gz (285.1 kB view details)

Uploaded Source

Built Distribution

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

polyester_sdk-0.1.0a0-py3-none-any.whl (397.4 kB view details)

Uploaded Python 3

File details

Details for the file polyester_sdk-0.1.0a0.tar.gz.

File metadata

  • Download URL: polyester_sdk-0.1.0a0.tar.gz
  • Upload date:
  • Size: 285.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for polyester_sdk-0.1.0a0.tar.gz
Algorithm Hash digest
SHA256 3cf5ec82e8b7beaf870b52dd8af2044376deb0acc9b3788ef251eb91e7cb6c59
MD5 868108ff0fe909580c44178ad67a7c8a
BLAKE2b-256 3d277571a4e40c6ad859630b9fd2e54feda54c9fb210bd523b8ae19f41433fea

See more details on using hashes here.

File details

Details for the file polyester_sdk-0.1.0a0-py3-none-any.whl.

File metadata

File hashes

Hashes for polyester_sdk-0.1.0a0-py3-none-any.whl
Algorithm Hash digest
SHA256 60e66c1c4e4111740906882cf8be195620e9fded345819a90e807bdd1ce994b1
MD5 d31b7cc5cd6c0485e0f0c32546ccf923
BLAKE2b-256 66306ccc01cb50363f11c74c893ca0e1ac78ecb972532363c696ef020417e56a

See more details on using hashes here.

Supported by

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