Startseite

Erste Schritte

SDKs für Python und Rust

Offizielle Seeryx-SDKs für Python und Rust: Marktdaten, Sign-In With Solana, signierte Orders, vor dem Signieren geprüfte Ein- und Auszahlungen, Live-Daten.

Überblick

Die offiziellen SDKs bündeln die API dieser Seiten für Python und Rust, mit denselben Begriffen und Namen in beiden Sprachen. Sie sind Open Source unter der MIT-Lizenz: github.com/Seeryx/seeryx-python und github.com/Seeryx/seeryx-rust.

  • Marktdaten: Märkte, laufende und vergangene Runden, Orderbücher, Trades, Volumen, Gebühren, Statistiken, die Rangliste, Profile und Ereignismärkte, ohne Konto.
  • Sign-In With Solana mit dem Schlüsselpaar deiner Wallet; läuft das Token ab, meldet sich das SDK selbst neu an.
  • Handel: eine Handelssitzung, die mit einer Wallet-Signatur geöffnet wird, dann Limit-, Market- und Post-Only-Orders, Pakete mit bis zu 15 Orders, Stornierungen, Aufteilungen und Zusammenlegungen, alles auf deinem Rechner signiert.
  • Guthaben: Einzahlungen aus deiner Wallet, Abhebungen an deine eigene Wallet und verzögerte Abhebungen; jede Transaktion wird vor dem Signieren geprüft.
  • Live: WebSocket-Streams einer Runde und deines Kontos, die sich selbst neu verbinden.
  • Hilfsfunktionen: das Preisraster, Gebühren, Slugs und Zeiten der Runden.

Installieren

Python 3.9 oder neuer (ein blockierender Client und ein asyncio-AsyncClient mit denselben Methoden) oder Rust 1.88 oder neuer (asynchron, auf tokio). Beide werden von GitHub installiert:

# Python 3.9 or newer
pip install "git+https://github.com/Seeryx/seeryx-python"

Einen Markt lesen

Marktdaten brauchen kein Konto. Preise sind in Cent; die Stufen eines Orderbuchs sind [Preis, Anteile], die besten zuerst.

quickstart.py
"""The live BTC 5-minute round, its order book and its last trades. No account needed.

    python quickstart.py
"""
from seeryx import Client

with Client() as client:
    rnd = client.current_round("BTC", "5m")
    book = client.order_book(rnd["slug"], "up")  # levels are [cents, shares], best first
    trades = client.trades(rnd["slug"])

    bid = book["bids"][0][0] if book["bids"] else None
    ask = book["asks"][0][0] if book["asks"] else None
    print(rnd["slug"], "opened at", rnd["open"], "ends at", rnd["end"])
    print("Up bid", bid, "ask", ask, "chance of Up", f"{(bid + ask) / 2}%" if bid and ask else "no quotes yet")
    print("last trade", trades[0] if trades else "none yet")
    print("taker fee", client.fees()["rateBps"] / 100, "% of p x (1 - p) per share")

Anmelden

Lade deine Wallet aus einer Schlüsselpaar-Datei der Solana CLI oder aus einem geheimen Schlüssel in base58; sie verlässt deinen Prozess nie. Bevor die Wallet den Anmeldetext signiert, prüft das SDK, dass er diese Website, diese Wallet und die eben ausgegebene Nonce nennt, und behält dann das 7-Tage-Token.

Wo GET /api/funds onChainTrading meldet, öffnet eine Wallet-Signatur eine Handelssitzung; ihr Schlüssel entsteht auf deinem Rechner und signiert danach jede Order. Mit einem Pfad wird die Sitzung gespeichert (nur für dich lesbar) und beim nächsten Start wiederverwendet; ohne Pfad bleibt sie nur im Speicher.

from seeryx import Client, Keypair

client = Client()  # https://seeryx.com
wallet = Keypair.from_file("wallet.json")  # a solana-keygen file; it never leaves this process
client.sign_in(wallet)  # checks the sign-in text, signs it, keeps the 7-day token
if client.funds().get("onChainTrading"):
    # one wallet signature; the session key then signs every order. Saved with mode 0600 and reused next time
    session = client.open_session(wallet, path="session.json")
    print("session key", session.address, "until", session.expires_at)

Eine Order platzieren

Preise sind Cent (Zehntelcent, wo der Markt sie zulässt), Größen sind Anteile, Beträge sind USDC. Das SDK wählt die signierte Form (PMO2, PMO3 oder PMO4), die Order-ID und den Ablauf; eine Market-Order braucht cap, den schlechtesten Preis, den du akzeptierst.

limit_order.py
"""Sign in, rest a small post-only buy below the market, list it, then cancel it.

    SEERYX_WALLET=~/.config/solana/id.json python limit_order.py
"""
import os

from seeryx import Client, Keypair

wallet = Keypair.from_file(os.path.expanduser(os.environ.get("SEERYX_WALLET", "wallet.json")))

with Client() as client:
    client.sign_in(wallet)
    if client.funds().get("onChainTrading"):
        # one wallet signature opens a trading session; its key then signs every order. Saved (mode 0600) so the
        # next run reuses it; leave out `path` to keep the key in memory only.
        client.open_session(wallet, path="session.json")

    rnd = client.current_round("BTC", "5m")
    book = client.order_book(rnd["slug"], "up")
    bid = book["bids"][0][0] if book["bids"] else 10
    limit = max(1, int(bid) - 5)  # 5c under the best bid: it rests in the book
    placed = client.buy(rnd["slug"], "up", shares=5, limit=limit, post_only=True)  # post_only: never trades at once
    print("resting order", placed["order"], "at", limit, "c")

    print("open orders", client.open_orders())
    if placed["order"]:
        print(client.cancel_order(placed["order"]))
market_buy.py
"""Spend up to $5 on Up now, paying at most 2c over the best ask. What the book cannot fill is dropped.

    SEERYX_WALLET=~/.config/solana/id.json python market_buy.py
"""
import os

from seeryx import Client, Keypair

wallet = Keypair.from_file(os.path.expanduser(os.environ.get("SEERYX_WALLET", "wallet.json")))

with Client() as client:
    client.sign_in(wallet)
    if client.funds().get("onChainTrading"):
        client.open_session(wallet, path="session.json")
    slug = client.current_round("BTC", "5m")["slug"]
    cap = client.market_cap(slug, "up", "buy", slippage=2)  # the worst price you accept, on the price grid
    result = client.market_buy(slug, "up", amount=5, cap=cap)
    print(result["status"], "filled", result["filled"], "shares for", result["spent"], "USDC, average", result.get("avgPrice"))

Live-Updates

Ein Stream folgt einer Runde oder einem Ereignismarkt (beide Orderbücher, Trades, Volumen) und, sobald du angemeldet bist, deinem Konto. Er verbindet sich mit wachsender Verzögerung neu und abonniert erneut; endet eine Runde, folge der nächsten über dieselbe Verbindung.

stream.py
"""Live books and trades of the BTC 5-minute rounds, and your account, over the WebSocket. Reconnects by itself.

    python stream.py                                           # market data only
    SEERYX_WALLET=~/.config/solana/id.json python stream.py    # and your account
"""
import asyncio
import os
import time

from seeryx import AsyncClient, Keypair


async def main() -> None:
    async with AsyncClient() as client:
        path = os.environ.get("SEERYX_WALLET")
        if path:
            await client.sign_in(Keypair.from_file(os.path.expanduser(path)))
        rnd = await client.current_round("BTC", "5m")
        async with client.stream(rnd["slug"], account=bool(path)) as stream:
            while True:
                # a message comes only when something changed: wait at most until the round ends
                message = await stream.next(timeout=max(1.0, rnd["end"] - time.time()))
                if message is None or time.time() >= rnd["end"]:
                    rnd = await client.current_round("BTC", "5m")  # follow the next round, same connection
                    await stream.watch_round(rnd["slug"])
                    continue
                if message["type"] == "round":
                    up = message["up"]
                    print(message["slug"], "bid", up["bids"][:1], "ask", up["asks"][:1], "volume", message["volume"])
                elif message["type"] == "account":
                    print("cash", message["balance"]["available"], "open orders", len(message["orders"]))
                else:
                    print("error", message["error"])


asyncio.run(main())

Einzahlen und abheben

Die Börse bereitet jede Transaktion vor und zahlt ihre Netzwerkgebühr, deine Wallet braucht also kein SOL. Das SDK gleicht sie genau mit dem ab, was du angefordert hast, und signiert nichts anderes. Eine Abhebung signiert der Sitzungsschlüssel, wo sessionWithdraw aktiv ist (mindestens 1 USDC, nur an deine eigene Wallet), sonst deine Wallet.

withdraw.py
"""Deposit USDC from your wallet, then withdraw some of it to the same wallet. The exchange pays every network fee:
the wallet needs no SOL. Every transaction is inspected before it is signed.

    SEERYX_WALLET=~/.config/solana/id.json python withdraw.py
"""
import os

from seeryx import Client, Keypair

wallet = Keypair.from_file(os.path.expanduser(os.environ.get("SEERYX_WALLET", "wallet.json")))

with Client(before_sign=lambda review: print("signing:", review.headline) or True) as client:
    client.sign_in(wallet)
    print("wallet", client.wallet_funds())  # USDC in the wallet; "account" is None until the first deposit

    print("deposit", client.deposit(wallet, 10))  # the first deposit is at least 1 USDC
    print("balance", client.balance())

    # signed by the trading session key when one is open and the server allows it, else by the wallet;
    # max_fee refuses a withdrawal fee above 1 USDC
    if client.funds().get("onChainTrading"):
        client.open_session(wallet, path="session.json")
    print("withdrawal", client.withdraw(4, wallet=wallet, max_fee=1))
    print("balance", client.balance())

Fehler und Wiederholungen

Eine Ablehnung kommt als Fehler mit dem Status, dem Text des Servers und seinem code; die Codes der Fehlerliste haben eigene Typen. Antworten mit 429 und 503 werden wiederholt, wie Retry-After es angibt, und schreibende Anfragen behalten bei jeder Wiederholung ihren Idempotency-Key, damit nichts doppelt platziert wird.

from seeryx import ApiError, BelowMinimum, WouldTake

try:
    client.buy(slug, "up", shares=5, limit=60, post_only=True)
except WouldTake:
    print("it would trade at once: post only refused it")
except BelowMinimum as e:
    print("the smallest order is", e.minimum, "shares")
except ApiError as e:
    print(e.status, e.code, e.message)  # 429 and 503 were already retried as Retry-After said

Schlüssel und Prüfungen

  • Der Schlüssel deiner Wallet und der Sitzungsschlüssel verlassen deinen Prozess nie: Gesendet werden nur öffentliche Schlüssel und Signaturen.
  • Jede vorbereitete Transaktion wird dekodiert und muss die eigene Anweisung des Seeryx-Programms mit deinen Konten und deinen Beträgen sein: Eine Freigabe, eine Überweisung, ein weiterer Unterzeichner oder ein anderes Programm wird abgelehnt.
  • Auf seeryx.com sind das Programm, der USDC-Mint und der Solana-Cluster fest vorgegeben, egal was der Server meldet.
  • Nichts, was ein Geheimnis enthält, wird ausgegeben oder protokolliert, und eine gespeicherte Sitzungsdatei kann nur ihr Besitzer lesen.

Beispiele

Beide Sprachen haben dieselben Programme in ihren examples-Ordnern:

BeispielWas es tut
quickstartDie laufende 5-Minuten-Runde von BTC, ihr Orderbuch und ihre letzten Trades, ohne Konto
limit_orderAnmelden, einen Post-Only-Kauf unter dem Markt ins Orderbuch legen, anzeigen und stornieren
market_buySofort bis zu 5 $ ausgeben und höchstens 2¢ über dem besten Ask zahlen
streamOrderbücher, Trades und dein Konto live über den WebSocket
market_makerEine kleine beidseitige Quotierungsschleife mit Post-Only-Orders und Zusammenlegungen
withdrawAus deiner Wallet einzahlen und wieder an sie abheben

Quellcode, alle Methoden, die Tests und das Änderungsprotokoll: github.com/Seeryx/seeryx-python und github.com/Seeryx/seeryx-rust.