-
Notifications
You must be signed in to change notification settings - Fork 0
WebSocket Streaming
WSClient provides a reconnecting WebSocket transport for Bitget UTA public and private streams. It maintains subscriptions, sends periodic pings, reconnects unexpected disconnects with exponential backoff, and resubscribes previously active channels after reconnecting. 1
| Constructor | Default endpoint | Authentication | Typical use |
|---|---|---|---|
NewPublicWSClient(opts...) |
wss://ws.bitget.com/v3/ws/public |
None | Public tickers, market data, and other public channels. |
NewPrivateWSClient(apiKey, secretKey, passphrase, opts...) |
wss://ws.bitget.com/v3/ws/private |
Automatic during Connect
|
Private fills, positions, orders, and other private channels. |
For Demo WebSocket access, supply WithWSURL(bitget.DemoPublicWSURL) or WithWSURL(bitget.DemoPrivateWSURL). These constants resolve to Bitget's documented wss://wspap.bitget.com/v3/ws/public and /private demo endpoints. Demo WebSocket authentication still requires Demo API credentials. 1 2
The normal lifecycle is: construct the client, Connect, defer Close, call Subscribe, then read the returned channel until the parent context ends. 1 3
package main
import (
"context"
"fmt"
"log"
"os/signal"
"syscall"
bitget "github.com/tigusigalpa/bitget-go"
"github.com/tigusigalpa/bitget-go/models"
)
func main() {
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()
ws := bitget.NewPublicWSClient()
if err := ws.Connect(ctx); err != nil {
log.Fatal(err)
}
defer ws.Close()
pushes, err := ws.Subscribe(ctx, models.WSArg{
InstType: "SPOT",
Topic: "ticker",
Symbol: "BTCUSDT",
})
if err != nil {
log.Fatal(err)
}
for {
select {
case <-ctx.Done():
return
case push, ok := <-pushes:
if !ok {
return
}
fmt.Printf("action=%s data=%s\n", push.Action, push.Data)
}
}
}Subscribe returns a receive-only channel of models.WSPush. A push includes the subscribed Arg, an Action, a raw JSON Data payload, and timestamp Ts. The raw payload shape depends on the selected Bitget channel. 1 4
Private clients log in automatically inside Connect. The login signature is computed over timestamp + "GET" + "/user/verify", matching Bitget's UTA WebSocket login procedure. Connect waits until login succeeds, the login times out, or the supplied context ends. 1 2
ws := bitget.NewPrivateWSClient(
os.Getenv("BITGET_API_KEY"),
os.Getenv("BITGET_SECRET_KEY"),
os.Getenv("BITGET_PASSPHRASE"),
)
if err := ws.Connect(ctx); err != nil {
return err
}
defer ws.Close()
fills, err := ws.Subscribe(ctx, models.WSArg{
InstType: "UTA",
Topic: "fast-fill",
Symbol: "default",
})
if err != nil {
return err
}The current SDK includes a models.FastFill model for Bitget's fast-fill private channel. Other channels can still be subscribed through the generic transport, but callers should decode WSPush.Data using the relevant Bitget channel's documented payload. 3 4
Bitget's published fast-fill event example contains a single object in data. Decode the raw payload directly into models.FastFill: 5
for push := range fills {
var fill models.FastFill
if err := json.Unmarshal(push.Data, &fill); err != nil {
log.Printf("decode fast-fill: %v", err)
continue
}
fmt.Printf(
"fill order=%s symbol=%s qty=%s price=%s\n",
fill.OrderID,
fill.Symbol,
fill.ExecQty,
fill.ExecPrice,
)
}Add the import:
import "encoding/json"
models.FastFill field |
Meaning |
|---|---|
OrderID, ClientOid, ExecID
|
Exchange order, client order, and execution identifiers. |
Symbol, Category, Side, HoldSide
|
Instrument and trade/position context. |
ExecPrice, ExecQty, TradeScope
|
Fill price, executed quantity, and maker/taker scope. |
ExecTime, UpdatedTime
|
Millisecond timestamp strings. |
A subscription is identified by the InstType, Topic, Symbol, and Coin fields of models.WSArg. Reusing the same argument returns the existing local buffered channel while still sending the subscribe operation. Unsubscribe(arg) removes the local subscription and closes its data channel; calling it for an unknown subscription returns nil. 1
arg := models.WSArg{InstType: "SPOT", Topic: "ticker", Symbol: "BTCUSDT"}
pushes, err := ws.Subscribe(ctx, arg)
if err != nil {
return err
}
// Later, when the stream is no longer required:
if err := ws.Unsubscribe(arg); err != nil {
return err
}
_ = pushes| Behavior | SDK implementation | Application implication |
|---|---|---|
| Ping | Sends text ping every 25 seconds. |
Keep Connect active and do not assume an idle stream is disconnected. |
| Auto reconnect | Enabled by default; retry starts at 1 second and caps at 60 seconds. | Retain long-lived clients rather than rebuilding them for every transient failure. |
| Resubscription | Sends all tracked WSArg values after a successful reconnect. |
Design consumers to tolerate duplicate or resumed data. |
| Subscription buffer | 100 WSPush messages per subscription. |
Consume promptly; when full, the SDK drops new push messages and logs a warning. |
| Graceful close |
Close stops loops and is safe to call more than once. |
Always defer ws.Close() after a successful connection. |
Bitget also enforces its own connection, subscription, and message-rate limits and expects a ping/pong keepalive exchange. The SDK implements its own periodic ping, but callers remain responsible for a subscription design that respects exchange limits. 1 2
| Option | Purpose |
|---|---|
WithWSURL(url) |
Override the endpoint; use this for Demo or approved Bitget alternative URLs. |
WithWSLogger(logger) |
Receive structured connection, reconnection, decoding, and backpressure diagnostics. |
WithWSAutoReconnect(false) |
Disable automatic reconnecting when the application must own reconnection policy. |