WebSockets
The exchange pushes state changes over Phoenix channels. STX.Sdk wraps each topic in a strongly-typed class. Every channel handles:
- Authenticating the connection, by token or by signing the handshake
- Heartbeat and automatic reconnection
- Rejoining its topic after a reconnect
Available channels
Section titled “Available channels”| Channel | Topic | What it pushes |
|---|---|---|
STXPortfolioChannel |
portfolio:{user_id} |
Available balance, escrow, liabilities |
STXActiveOrdersChannel |
active_orders:{user_id} |
Order state transitions |
STXActiveTradesChannel |
active_trades:{user_id} |
Fills as they land |
STXActiveSettlementsChannel |
active_settlements:{user_id} |
Settlements |
STXPositionsChannel |
active_positions:{user_id} |
Position changes |
STXUserInfoChannel |
user_info:{user_id} |
Account updates |
STXMarketChannel |
market_info |
Market state and prices, broadcast rather than user-scoped |
Connect a channel
Section titled “Connect a channel”Register a callback, then start it:
var portfolio = serviceProvider.GetRequiredService<STXPortfolioChannel>();
portfolio.SetOnReceiveAction(p => Console.WriteLine($"Available: {p.AvailableBalance}c Escrow: {p.Escrow}c"));
await portfolio.StartAsync();StartAsync opens the socket, joins the topic, and begins the heartbeat. StopAsync closes it. WebSocketConnected reports the current state, and the SocketDisconnected and SocketReconnected events fire around an automatic reconnect.
Two ways to consume a channel
Section titled “Two ways to consume a channel”Composition: hand the channel a callback, as above. Best when you want each message as it lands.
Inheritance: subclass and override OnReceive:
public class BalanceTracker : STXPortfolioChannel{ public BalanceTracker(STXUserStorage storage, STXEndpointSettings settings) : base(storage, settings) { }
public override void OnReceive(STXPortfolio portfolio) { AvailableBalance = portfolio.AvailableBalance; }
public long AvailableBalance { get; private set; }}Wrappers: every channel also has a …ChannelWrapper registered alongside it, which buffers into a bounded queue instead of calling you back. Use it when you would rather poll than handle a callback:
var wrapper = serviceProvider.GetRequiredService<STXPortfolioChannelWrapper>();await wrapper.StartAsync();
var latest = wrapper.LastItem; // most recent message, or nullvar all = wrapper.Items; // buffered messagesOrders and trades
Section titled “Orders and trades”var orders = serviceProvider.GetRequiredService<STXActiveOrdersChannel>();var trades = serviceProvider.GetRequiredService<STXActiveTradesChannel>();
orders.SetOnReceiveAction(o =>{ foreach (var order in o.Orders) Console.WriteLine($"{order.Id} {order.Status} {order.Filled}/{order.Quantity}");});
trades.SetOnReceiveAction(t =>{ foreach (var trade in t.Trades) Console.WriteLine($"Filled {trade.MarketId} at {trade.Price}c");});
await orders.StartAsync();await trades.StartAsync();Market data
Section titled “Market data”Market info is a broadcast, so it is not keyed on a user and works without GetMeAsync():
var market = serviceProvider.GetRequiredService<STXMarketChannel>();
market.SetOnReceiveAction(m => Console.WriteLine($"{m.MarketId} {m.Status}"));
await market.StartAsync();In a hosted service
Section titled “In a hosted service”public class STXWorker : BackgroundService{ protected override async Task ExecuteAsync(CancellationToken stop) { // Channel topics are keyed on the user id. Under API-key auth there is no // login response, so fetch it once before joining anything. await _identity.GetMeAsync();
_portfolio.SetOnReceiveAction(p => _balance = p.AvailableBalance); // long, in cents _orders.SetOnReceiveAction(HandleOrders);
await _portfolio.StartAsync(); await _orders.StartAsync();
await Task.Delay(Timeout.Infinite, stop); }
public override async Task StopAsync(CancellationToken stop) { await _orders.StopAsync(); await _portfolio.StopAsync(); await base.StopAsync(stop); }}Channels are registered as singletons, so the same instance is shared across your app. Resolve them once and keep them.
See also
Section titled “See also”- Trading: placing the orders these channels report on
- Settlements: settlement history and its channel

