Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.sportsxapp.com/llms.txt

Use this file to discover all available pages before exploring further.

The SportsX exchange pushes state changes over Phoenix WebSocket channels. STX.Sdk wraps each topic in a strongly-typed class with event callbacks and handles the low-level details for you: JWT attachment on the connection URL, 30-second heartbeats, exponential-backoff reconnection, and automatic topic resubscription after a reconnect.

Available channels

Channel classTopicWhat it pushes
STXPortfolioChannelportfolio:{user_id}Available balance, escrow, total P&L
STXActiveOrdersChannelactive_orders:{user_id}Order state transitions
STXActiveTradesChannelactive_trades:{user_id}Fills as they land
STXActiveSettlementsChannelWrapperactive_settlements:{user_id}Market settlement events
STXPositionsChannelactive_positions:{user_id}Position changes
STXUserInfoChanneluser_info:{user_id}Profile and account updates
STXMarketChannelmarkets / market_info / market_updatesMarket state and price ticks
All channel classes are registered as singletons in the DI container, so the socket and subscription state are shared across your app.

Connect a channel

The pattern is the same for every channel: resolve it, register event handlers, then call ConnectAsync. ConnectAsync is idempotent — calling it more than once is a no-op.
var portfolio = serviceProvider.GetRequiredService<STXPortfolioChannel>();

portfolio.OnSummary += summary =>
    Console.WriteLine($"Available: {summary.AvailableBalance}c  Escrow: {summary.Escrow}c");

portfolio.OnUpdate += summary =>
    Console.WriteLine($"Balance tick: {summary.AvailableBalance}c");

await portfolio.ConnectAsync();

Portfolio channel

The portfolio channel streams your account’s financial state. The server pushes a summary event on join and an update event on every state change (order placed, fill, deposit, withdrawal, settlement):
public class BalanceTracker
{
    private readonly STXPortfolioChannel _portfolio;
    public long AvailableBalance { get; private set; }

    public BalanceTracker(STXPortfolioChannel portfolio)
    {
        _portfolio = portfolio;
        _portfolio.OnSummary += s => AvailableBalance = s.AvailableBalance;
        _portfolio.OnUpdate  += s => AvailableBalance = s.AvailableBalance;
    }

    public Task StartAsync() => _portfolio.ConnectAsync();
}

Active orders and trades

Wire both channels together for a complete trading loop:
var orders = serviceProvider.GetRequiredService<STXActiveOrdersChannel>();
var trades = serviceProvider.GetRequiredService<STXActiveTradesChannel>();

orders.OnOrderUpdate += o =>
    _logger.LogInformation("Order {Id} -> {Status}", o.Id, o.Status);

trades.OnTrade += t =>
    _logger.LogInformation("Fill {TradeId}: {MarketId} {Price}c x {Quantity}",
        t.Id, t.MarketId, t.Price, t.Quantity);

await orders.ConnectAsync();
await trades.ConnectAsync();
Both channels require an authenticated session. The JWT is pulled from STXUserStorage automatically — call LoginAsync before ConnectAsync.

Market channel (price ticks)

Subscribe to specific market IDs to receive live bid/ask updates and market state changes:
var market = serviceProvider.GetRequiredService<STXMarketChannel>();

market.OnPriceUpdate += tick =>
{
    // tick carries: MarketId, BestBid, BestAsk, LastTrade, MarketStatus, ...
    Console.WriteLine($"{tick.MarketId}  bid={tick.BestBid}  ask={tick.BestAsk}");
};

await market.ConnectAsync();
await market.SubscribeAsync("mkt_abc", "mkt_def");
You can subscribe and unsubscribe at runtime as your market universe changes. The channel deduplicates subscriptions and only sends the delta to the server.

Full startup sequence

The BackgroundService pattern from cssdk-console shows the recommended order for connecting all channels at startup and cleanly disconnecting on shutdown:
public class STXWorker : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stop)
    {
        await _login.LoginAsync(email, password, keepSessionAlive: true);

        await _portfolio.ConnectAsync();
        await _orders.ConnectAsync();
        await _trades.ConnectAsync();
        await _market.ConnectAsync();

        stop.WaitHandle.WaitOne();   // block until the host shuts down

        await _market.DisconnectAsync();
        await _trades.DisconnectAsync();
        await _orders.DisconnectAsync();
        await _portfolio.DisconnectAsync();
    }
}

Reconnection behavior

When the underlying socket drops, the SDK:
1

Retries with exponential backoff

Reconnect attempts start at 250 ms and cap at 5 s.
2

Rejoins all topics

Every previously-joined topic is rejoined automatically on reconnect.
3

Preserves event handlers

Your registered callbacks stay bound — no re-registration is needed.
If the session JWT expired during the outage and you started with keepSessionAlive: true, STXSessionBackgroundService refreshes the token before the next connect attempt.

See also

  • Authentication — why keepSessionAlive matters for long-running channel connections
  • Trading — using STXActiveOrdersChannel with cancelOnDisconnect
  • SettlementsSTXActiveSettlementsChannelWrapper for live settlement events