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 class | Topic | What it pushes |
|---|
STXPortfolioChannel | portfolio:{user_id} | Available balance, escrow, total P&L |
STXActiveOrdersChannel | active_orders:{user_id} | Order state transitions |
STXActiveTradesChannel | active_trades:{user_id} | Fills as they land |
STXActiveSettlementsChannelWrapper | active_settlements:{user_id} | Market settlement events |
STXPositionsChannel | active_positions:{user_id} | Position changes |
STXUserInfoChannel | user_info:{user_id} | Profile and account updates |
STXMarketChannel | markets / market_info / market_updates | Market 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:
Retries with exponential backoff
Reconnect attempts start at 250 ms and cap at 5 s.
Rejoins all topics
Every previously-joined topic is rejoined automatically on reconnect.
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
- Settlements —
STXActiveSettlementsChannelWrapper for live settlement events