Build an authenticated account monitor that keeps exact funding and trading balances separate, tracks reservations and open orders, and uses revisions to reject stale balance updates.
Read and format the balance snapshot
balances, err := client.Balances.List(ctx, nil, nil)
if err != nil { log.Fatal(err) }
for _, balance := range balances.Balances {
available, err := codecs.FormatLedgerU128(balance.Available, codecs.LedgerScale)
if err != nil { log.Fatal(err) }
reserved, err := codecs.FormatLedgerU128(balance.Reserved, codecs.LedgerScale)
if err != nil { log.Fatal(err) }
fmt.Println(
balance.AssetID,
"available", available,
"reserved", reserved,
"trading_revision", balance.TradingRevision,
"funding_revision", balance.FundingRevision,
)
}funding is deposit/withdraw custody state. trading, reserved, and available are execution
state. Their revisions are independent; compare TradingRevision only with trading-state updates
and FundingRevision only with funding-state updates.
Reconcile open orders
open, err := client.Orders.ListOpen(ctx, nil, nil, nil, nil, true, true, nil)
if err != nil { log.Fatal(err) }
for _, order := range open.Orders {
fmt.Println(
order.OrderID,
order.ClientOrderID,
order.SymbolID,
order.Status,
order.OrigQty,
order.CumQty,
order.LeavesQty,
)
}Reserved balance and open-order leaves should move together eventually, but they are served by different read models and can lag briefly. Do not flag a mismatch until a bounded reconciliation window and a fresh read have both completed.
Subscribe for low-latency order changes
sub, err := client.Orders.Subscribe(ctx, accountID)
if err != nil { log.Fatal(err) }
defer sub.Close()
for event := range sub.Messages() {
unit, ok := event.(realtime.OrderUnit)
if !ok {
continue
}
for _, order := range unit.Orders {
scale, found := client.Catalogs.BaseQuantityScaleForSymbolID(order.SymbolID)
if !found {
return fmt.Errorf("stream symbol %d quantity scale is unavailable", order.SymbolID)
}
cum, err := order.CumQty.WithScale(scale).Format()
if err != nil { return err }
leaves, err := order.LeavesQty.WithScale(scale).Format()
if err != nil { return err }
fmt.Println(order.OrderID, order.Status, cum, leaves)
}
}
if err := sub.Err(); err != nil { log.Print(err) }The stream yields realtime.OrderStreamEvent values; handle realtime.OrderSnapshot too, which
replaces your live view. See Orders. The private stream
accelerates the UI; it does not replace snapshots. On queue overflow, discard local assumptions and
reconcile balances plus open orders again. Stream quantities can omit scale, so resolve it from the
hydrated catalog by SymbolID and fail closed if unavailable; never invent a stream scale.
Resolve fills before computing inventory
orderID := "order-id-from-create"
details, err := client.Orders.WaitForOrderTradesComplete(
ctx, nil, models.OrderKeyByID(orderID), nil, 15*time.Second,
)
if err != nil { log.Fatal(err) }
if details.Order != nil {
fmt.Println(details.Order.CumQty, len(details.Trades))
}The order projection can show cumulative quantity before every related trade row is queryable.
Use the completed trade projection for fee-source-aware received inventory and realized execution
reporting. The wait returns only once the order has ended (filled, canceled or rejected) and its
trades add up to CumQty; for an order that is still working, read the trades so far with Orders.Get instead. The timeout bounds the whole wait, and a timeout error matches errors.Is(err, context.DeadlineExceeded).
Poll as a safety net
Poll slowly enough to respect rate limits, add jitter across replicas, and set one overall context deadline per cycle. A useful cycle is balances → open orders → recent history. Publish the new dashboard state atomically only after all required reads succeed; otherwise retain the previous state and mark it stale.
Account-state API map
Balances.List(account scope, subaccount): Funding/trading snapshot and revisionsBalances.GetBalanceHistory(range, ledger, account codes): Auditable balance movementOrders.ListOpen(scope, pagination, attached-risk flags): Current reservation intentOrders.ListHistory(symbol/ID, pagination): Terminal and recent order statesOrders.Get(order ID or client order ID): One order plus related fillsOrders.Subscribe(account ID): Low-latency private lifecycle updatesOrders.WaitForOrderTradesComplete(order identity, timeout): Complete fill projection of an ended orderTrades.List(account filters, pagination): User execution ledger
The snippets on this page compile against polyester-sdk-go v0.11.0.