Help us shape the future of Go! Take the 2026 Go Developer Survey

bitget

package module
v1.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 7, 2026 License: MIT Imports: 22 Imported by: 0

README

Bitget Golang Client/SDK/Library

Bitget Golang SDK

CI Tests Go Version License CodeQL Codecov GitHub Release GoDoc

An intentionally small, typed Go client for the Bitget Unified Trading Account (UTA) API v3. It takes care of request signing, response envelopes, WebSocket lifecycle, and numeric precision, while leaving trading decisions entirely in your application.

It is not an official Bitget SDK and it does not execute a request during import or client creation.

What this library is for

Think of the SDK as a small transport layer between your Go application and Bitget. It signs private REST requests, turns documented responses into Go types, and keeps a WebSocket connection alive. It deliberately does not make trading decisions, convert prices to float64, or hide reconnects and subscription errors from your application.

That gives you a simple rule of thumb:

  • Use REST when you need a snapshot: balances, an order book, a recent page of orders, candles, or funding history.
  • Use the regular WebSocket subscription channel when a bounded in-process feed is enough.
  • Use the raw-frame and lifecycle handlers when every received payload, its receipt time, and the current connection generation matter to your downstream system.

Start here

Start with a public REST call. It needs no credentials and cannot touch an account. In a new directory, create a tiny Go module and run the program:

mkdir bitget-first-request
cd bitget-first-request
go mod init example.com/bitget-first-request
go get github.com/tigusigalpa/bitget-go
# Save the program below as main.go, then:
go run .

The module requires Go 1.21 or newer. Prices, quantities, balances, fees, and timestamps are represented as strings where the API returns strings. That avoids accidental float64 rounding in financial code.

package main

import (
	"context"
	"fmt"
	"log"

	bitget "github.com/tigusigalpa/bitget-go"
	"github.com/tigusigalpa/bitget-go/models"
)

func main() {
	client := bitget.NewRestClient("", "", "") // public endpoints need no key
	tickers, err := client.Market.GetTickers(context.Background(), models.CategorySpot, "BTCUSDT")
	if err != nil {
		log.Fatal(err)
	}
	if len(tickers) > 0 {
		fmt.Printf("BTC/USDT last price: %s\n", tickers[0].LastPrice)
	}
}

If you prefer to explore the repository examples, clone the project and run go run ./examples/rest. The public REST and public WebSocket examples are safe to run without environment variables.

Choose the smallest client for the job

Need Create Credentials What it does
Snapshot market data NewRestClient("", "", "") No Public REST calls such as tickers and order book
Account, orders, positions NewRestClient(key, secret, passphrase) Yes Signed private REST calls
Live public market feed NewPublicWSClient() No Subscribes to public WebSocket channels
Private fills and account feed NewPrivateWSClient(key, secret, passphrase) Yes Logs in to a private WebSocket and subscribes to its channels

There is no automatic switch between public and private APIs, production and demo endpoints, or REST and WebSocket. You choose the transport and credentials explicitly.

A practical public market query

The market methods return strings for exchange-provided decimals and timestamps. Keep those values as strings until your own domain layer deliberately converts them with the precision rules your application needs. This complete helper needs the market package in addition to the imports from the first example.

import (
	"context"
	"fmt"
	"time"

	bitget "github.com/tigusigalpa/bitget-go"
	"github.com/tigusigalpa/bitget-go/models"
	"github.com/tigusigalpa/bitget-go/rest/market"
)

func printRecentMarket() error {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	client := bitget.NewRestClient("", "", "")
	candles, err := client.Market.GetCandles(ctx, market.GetCandlesOptions{
		Category: models.CategorySpot,
		Symbol:   "BTCUSDT",
		Interval: "1m",
		Limit:    "10",
	})
	if err != nil {
		return err
	}

	for _, candle := range candles {
		// candle = [timestamp, open, high, low, close, base volume, turnover]
		fmt.Printf("close=%s at %s\n", candle[4], candle[0])
	}

	fills, err := client.Market.GetPublicFills(ctx, models.CategorySpot, "BTCUSDT", "20")
	if err != nil {
		return err
	}
	for _, fill := range fills {
		fmt.Printf("%s %s @ %s (exec %s)\n", fill.Side, fill.Size, fill.Price, fill.ExecID)
	}

	return nil
}

GetPublicFills is a recent-data repair source, not a complete historical trade ledger. For futures funding data, call GetFundingRateHistory with the same category and symbol; use the corresponding instrument's FundInterval instead of assuming a fixed settlement schedule.

Demo credentials before production

Create a separate Demo API key in Bitget. Keep all three values outside source control:

  • BITGET_API_KEY
  • BITGET_SECRET_KEY
  • BITGET_PASSPHRASE

Bitget requires the paptrading: 1 header for demo REST requests. WithDemoTrading() adds it. The accompanying private examples additionally refuse to run until BITGET_DEMO=1 is set; this is a guard against accidentally pointing copied code at a production account.

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

client := bitget.NewRestClient(
	os.Getenv("BITGET_API_KEY"),
	os.Getenv("BITGET_SECRET_KEY"),
	os.Getenv("BITGET_PASSPHRASE"),
	bitget.WithDemoTrading(),
)

assets, err := client.Account.GetAssets(ctx)
if err != nil {
	log.Fatal(err)
}
fmt.Println("demo USD equity:", assets.AccountEquity)

Run the complete safe demo-account example with:

BITGET_DEMO=1 BITGET_API_KEY=... BITGET_SECRET_KEY=... BITGET_PASSPHRASE=... go run ./examples/demo-account

Never put keys, passphrases, signatures, or .env files in a repository or issue. Bind an IP address to an API key where possible. See Bitget's API-key security guidance.

Configuration

The defaults target Bitget's regular UTA domains. A supplied *http.Client is used as-is; the SDK does not rewrite its timeout or transport.

Option Default Use it for
WithHTTPClient(*http.Client) Internal client with 15-second timeout Proxy, custom TLS, tracing, or test transport
WithTimeout(time.Duration) 15s Timeout of the internally created HTTP client
WithBaseURL(string) https://api.bitget.com A test server or Bitget VIP base origin
WithDemoTrading() Off REST requests made with a Demo API key
WithLocale(string) en-US Bitget's locale header
WithLogger(Logger) No-op Structured REST lifecycle logs
WithWSURL(string) Public/private production URL Demo, VIP, or test WebSocket endpoint
WithWSAutoReconnect(bool) On Disable automatic reconnect for a short-lived consumer
WithWSLogger(Logger) No-op Structured WebSocket lifecycle logs

WithBaseURL expects an origin, not a path ending in /api/v3: endpoint methods add their own /api/v3/... path. Bitget documents the production, demo, and VIP domains in its Quick Start.

httpClient := &http.Client{Timeout: 30 * time.Second, Transport: myTransport}
client := bitget.NewRestClient("", "", "", bitget.WithHTTPClient(httpClient))

Implemented REST coverage

This is a focused Phase 1 surface. Methods not listed here are not implemented yet.

Service Methods
Market (public) GetInstruments, GetTickers, GetOrderBook, GetCandles, GetHistoryCandles, GetPublicFills, GetFundingRateHistory, GetLiquidations
Account (private) GetAssets, GetSettings, SetLeverage
Trade (private) PlaceOrder, ModifyOrder, CancelOrder, GetOpenOrders, GetOrderHistory, GetPositions

See docs/endpoints.md for the exact HTTP paths and Bitget documentation for each method. Model fields are deliberately forward-compatible strings where a future API value should not be rejected by a closed enum.

Deep candle history with response evidence (v1.2.0)

For candles older than the recent-data window, use GetHistoryCandles. It calls the official /api/v3/market/history-candles route, with a request page limit of 100. GetCandles still calls /api/v3/market/candles with its existing maximum of 1,000. GetFundingRateHistory and custom WithHTTPClient transports also keep their existing behaviour.

Use GetHistoryCandlesWithReceipt if you need both typed candles and evidence of the exact response, without wrapping/intercepting an HTTP transport:

// Imports: context, fmt, time, plus bitget, models and rest/market.
func readHistoricalCandles() error {
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	client := bitget.NewRestClient("", "", "")
	candles, receipt, err := client.Market.GetHistoryCandlesWithReceipt(ctx, market.GetHistoryCandlesOptions{
		Category:   models.CategorySpot,
		Symbol:     "BTCUSDT",
		Interval:   "1m",
		CandleType: "market",
		StartTime:  "1609459200000",
		EndTime:    "1609465200000",
		Limit:      "100",
	})
	if receipt != nil {
		fmt.Printf("HTTP %d, received %s, complete body: %t, bytes: %d\n",
			receipt.StatusCode(), receipt.ReceivedAt(), receipt.Complete(), len(receipt.Payload()))
		// Persist receipt.Payload() and receipt.Request() in your own evidence store.
	}
	if err != nil {
		return err // Never treat an error response as admitted candle data.
	}
	for _, candle := range candles {
		fmt.Printf("timestamp=%s close=%s volume=%s\n", candle[0], candle[4], candle[5])
	}
	return nil
}

The time selectors are Unix millisecond strings and are sent unchanged. Bitget describes them as after/before bounds, but does not explicitly guarantee whether equality is included. It also documents that endTime even 1 ms past an interval boundary may add an earlier candle. The SDK preserves every returned row and its order; it does not trim, round, deduplicate, or silently substitute recent data. Each query window may span at most 90 days even though its data may be older. See Bitget's history contract.

Pagination is explicit: choose the next time window from the returned timestamps, handle overlapping boundary candles in your application, and stop when a page is empty or makes no progress. The endpoint has no response cursor and the SDK does not infer complete historical coverage from a full or empty page.

models.RESTReceipt stores at most bitget.MaxRESTReceiptBytes (10 MiB). Its payload and request metadata accessors return copies. ReceivedAt is local time after the bounded body read and before JSON decoding, separate from candle/event time. Metadata contains method, path and allowlisted market selectors; it excludes credentials, headers, host and URL userinfo. Bytes are the body exposed by net/http, including its automatic decompression, not HTTP/TLS framing.

A receipt can accompany API errors, invalid JSON, interrupted reads and oversize responses. Oversize/interrupted bodies have Complete() == false; oversize keeps only the first 10 MiB and fails the call. A fully received error or malformed JSON body can have Complete() == true: this flag describes byte capture, never market coverage or successful decoding. Validation/cancellation before an HTTP response returns a nil receipt. market.NewClient remains supported for custom injection, but cannot provide receipts without NewClientWithReceipts; NewRestClient wires both transports automatically.

Liquidations are explicitly partial

GetLiquidations and GetLiquidationsWithReceipt call the official public /api/v3/market/liquidations route and return models.PartialLiquidations. Pass market.GetLiquidationsOptions{Category: models.CategoryUSDTFutures, Symbol: "BTCUSDT", Limit: "100"} for a page, then pass the returned Cursor unchanged in the next request. Cursors are opaque; stop on empty/non-progressing pages rather than assuming that pagination proves completeness.

The official REST contract only covers the last three days and allows delayed data. It provides no stable event ID in its documented response, and does not specify amount units or REST aggregation/exhaustiveness. Price, Amount and Ts remain exact provider strings. The SDK creates no execution identity, converts no units, and does not deduplicate indistinguishable observations. Do not label these data complete historical liquidations. WebSocket liquidation aggregation rules must not be assumed to apply to REST.

GetPublicFills remains recent public trades, preserving ExecID, ExecLinkID, Ts and category-dependent size units. The audited UTA market catalog has no documented public deep fills route. The official /api/v3/trade/fills is private account history, not the public market tape; no historical public fills method is fabricated here. Audit sources and classified test fixtures are recorded in testdata/market-history/README.md.

Pages, cursors, and cancellation

Order-list endpoints return a Cursor. Pass it back only after you have processed the current page. Give every request a deadline appropriate for your application.

page, err := client.Trade.GetOpenOrders(ctx, trade.GetOpenOrdersOptions{
	Category: models.CategorySpot,
	Limit:    "100",
})
if err != nil {
	return err
}

for _, order := range page.List {
	// Persist or handle order before asking for the next page.
}
if page.Cursor != "" {
	// Request the next page with Cursor: page.Cursor.
}

Do not automatically retry an order placement after a timeout: the exchange may have accepted it even when your process did not receive a response. Use a unique ClientOid and then query the order state. For read-only requests, build your own retry policy around ErrRateLimited, context cancellation, and the endpoint-specific limits.

Error handling

The package keeps Bitget's response code and message in *bitget.Error; use errors.Is for stable classifications and errors.As for details. A 429 response retains both ErrRateLimited and its API error payload when Bitget supplies one.

assets, err := client.Account.GetAssets(ctx)
if err != nil {
	if errors.Is(err, bitget.ErrRateLimited) {
		// Back off according to the endpoint's documented limit.
		return
	}

	var apiErr *bitget.Error
	if errors.As(err, &apiErr) {
		log.Printf("Bitget rejected the request: code=%s message=%s", apiErr.Code, apiErr.Message)
		return
	}

	log.Printf("transport or decoding failure: %v", err)
}

Available classifications include ErrUnauthorized, ErrInvalidSignature, ErrInvalidTimestamp, ErrPermissionDenied, ErrRateLimited, ErrInvalidParameter, ErrInsufficientFunds, ErrOrderNotFound, and ErrInternalServer.

WebSocket lifecycle

Use a context that you can cancel and always close the client. The client sends ping, expects pong, reconnects with exponential backoff after an unexpected disconnect, and resubscribes its active channels. It does not promise exactly-once or globally ordered delivery: make downstream processing idempotent, and deduplicate events using exchange IDs when a channel provides them.

ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
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.Println(string(push.Data))
	}
}

Each subscription has a 100-message buffer. If the consumer cannot keep up, the SDK drops the newest push and emits a warning through the configured WebSocket logger. For high-volume channels, process messages promptly, keep the handler non-blocking, and use a durable queue in your own application if loss is unacceptable.

For a lossless, provenance-sensitive path, configure WithRawFrameHandler. It is called synchronously with an exact copied payload, immediate local receipt time, and connection generation before the SDK decodes JSON or writes to a subscriber buffer. Pair it with WithWSEventHandler to observe subscription requests, Bitget ACKs/errors and terminal raw-observer failures by channel arg. These callbacks deliberately apply backpressure; keep their work short or hand off to your own durable queue. Mark a subscription ready only after a WSSubscribed event for the current connection generation; an error with an arg closes and removes that rejected subscription.

Wait for a subscription ACK

Subscribe confirms that the SDK wrote the request; it does not mean Bitget has accepted it. For a single, non-reconnecting consumer, wait for WSSubscribed before treating the feed as ready. The example also surfaces a provider rejection instead of silently continuing with an empty channel.

// Imports: context, fmt, sync, plus bitget and models.
// The caller must close the returned client when it no longer needs the feed.
func subscribeWhenReady(ctx context.Context) (*bitget.WSClient, <-chan models.WSPush, error) {
	ready := make(chan struct{})
	providerError := make(chan error, 1)
	var readyOnce sync.Once

	ws := bitget.NewPublicWSClient(
		bitget.WithWSAutoReconnect(false),
		bitget.WithWSEventHandler(func(event bitget.WSLifecycleEvent) {
			switch event.Type {
			case bitget.WSSubscribed:
				if event.Arg != nil && event.Arg.Topic == "ticker" && event.Arg.Symbol == "BTCUSDT" {
					readyOnce.Do(func() { close(ready) })
				}
			case bitget.WSProviderError:
				select {
				case providerError <- fmt.Errorf("Bitget rejected subscription %#v: %s %s", event.Arg, event.Code, event.Message):
				default: // Keep the synchronous lifecycle callback non-blocking.
				}
			}
		}),
	)

	if err := ws.Connect(ctx); err != nil {
		return nil, nil, err
	}

	pushes, err := ws.Subscribe(ctx, models.WSArg{InstType: "SPOT", Topic: "ticker", Symbol: "BTCUSDT"})
	if err != nil {
		_ = ws.Close()
		return nil, nil, err
	}

	select {
	case <-ready:
		// The provider accepted this subscription.
		return ws, pushes, nil
	case err := <-providerError:
		_ = ws.Close()
		return nil, nil, err
	case <-ctx.Done():
		_ = ws.Close()
		return nil, nil, ctx.Err()
	}
}

For reconnecting consumers, track the latest WSConnected generation and accept a WSSubscribed event only from that generation. A reconnect requires a fresh ACK; do not treat a prior connection's acknowledgment as current.

Preserve exact received messages

The regular WSPush route is intentionally convenient and bounded. If you need audit-grade provenance or must hand messages to a durable queue without a decode/re-encode cycle, use the raw handler. It receives a private byte copy before the SDK parses JSON.

// Imports: errors, log, plus bitget.
func newRawClient(rawFrames chan<- bitget.RawFrame) *bitget.WSClient {
	return bitget.NewPublicWSClient(
		bitget.WithRawFrameHandler(func(frame bitget.RawFrame) error {
			// The caller must drain this channel or replace it with a durable queue.
			select {
			case rawFrames <- frame:
				return nil
			default:
				return errors.New("raw-frame consumer is overloaded")
			}
		}),
		bitget.WithWSEventHandler(func(event bitget.WSLifecycleEvent) {
			if event.Type == bitget.WSTerminal {
				log.Printf("raw frame consumer stopped: %v", event.Err)
			}
		}),
	)
}

Returning an error from the raw handler deliberately produces a terminal lifecycle event and disconnects the current connection. That makes overload or storage failure visible to the caller rather than silently losing canonical data. Do not mutate frame.Payload and do not synchronously perform slow I/O unless deliberate backpressure is what you want.

The public examples/websocket program is credential-free. The private examples/websocket-private program uses Bitget's Demo private endpoint explicitly and decodes the typed fast-fill payload.

Bitget documents a maximum of 10 WebSocket messages per second, recommends fewer than 50 channel subscriptions per connection, and publishes connection/subscription caps. Design a connection pool and resubscription cadence around those limits rather than opening a connection per symbol. WebSocket connection guidance

Runnable examples

Program What it demonstrates Credentials
examples/rest Public ticker and safe order-book access None
examples/history One deep candle page with raw receipt metadata None
examples/demo-account Demo-only signed account read Demo key + BITGET_DEMO=1
examples/websocket Public ticker subscription, signal cancellation None
examples/websocket-private Demo private fast-fill subscription and payload decoding Demo key + BITGET_DEMO=1

Development

go test ./...
go test -race ./...
go vet ./...
gofmt -l .

Integration tests are opt-in and never receive a credential in CI:

go test -tags=integration ./...

The public integration test contacts Bitget. The private integration test is skipped unless all three BITGET_* variables are present, and uses demo mode.

Read CONTRIBUTING.md before opening a pull request. For exact endpoint coverage, see docs/endpoints.md. For a security report, see SECURITY.md.

Before opening a pull request

Run the same checks used for the library's core behaviour:

go test ./...
go test -race ./...
golint ./...
go vet ./...

Add a focused test whenever an endpoint, a signed request, or a WebSocket lifecycle branch changes. Tests use local HTTP/WebSocket servers by default; the optional integration suite is the only test path that contacts Bitget.

License and attribution

MIT — see LICENSE. Maintained by Igor Sazonov. This project is not affiliated with Bitget.

Documentation

Overview

Package bitget is an idiomatic Go SDK for the Bitget Unified Trading Account (UTA) API v3.

Docs: https://www.bitget.com/api-doc/uta/intro

Index

Constants

View Source
const (
	DefaultPublicWSURL  = "wss://ws.bitget.com/v3/ws/public"
	DefaultPrivateWSURL = "wss://ws.bitget.com/v3/ws/private"
	DemoPublicWSURL     = "wss://wspap.bitget.com/v3/ws/public"
	DemoPrivateWSURL    = "wss://wspap.bitget.com/v3/ws/private"
)

Public/private WebSocket endpoints.

Docs: https://www.bitget.com/api-doc/uta/guide

View Source
const DefaultBaseURL = "https://api.bitget.com"

DefaultBaseURL is Bitget's production UTA v3 REST endpoint.

Docs: https://www.bitget.com/api-doc/uta/guide

View Source
const DefaultTimeout = 15 * time.Second

DefaultTimeout is applied to the internal *http.Client when none is supplied via WithHTTPClient.

View Source
const MaxRESTReceiptBytes = maxResponseBodySize

MaxRESTReceiptBytes is the maximum number of response-body bytes retained in a RESTReceipt. An oversized response fails with an incomplete bounded receipt.

Variables

View Source
var (
	ErrUnauthorized      = errors.New("bitget: unauthorized: invalid API credentials")
	ErrInvalidSignature  = errors.New("bitget: invalid signature")
	ErrInvalidTimestamp  = errors.New("bitget: invalid or expired timestamp")
	ErrPermissionDenied  = errors.New("bitget: permission denied for this API key")
	ErrRateLimited       = errors.New("bitget: rate limit exceeded")
	ErrInvalidParameter  = errors.New("bitget: invalid request parameter")
	ErrInsufficientFunds = errors.New("bitget: insufficient balance")
	ErrOrderNotFound     = errors.New("bitget: order not found")
	ErrInternalServer    = errors.New("bitget: internal server error")
)

Sentinel errors that callers can match with errors.Is, wrapped alongside the detailed *Error (retrievable via errors.As) on every failed call.

Functions

func MapErrorCode

func MapErrorCode(code string) error

MapErrorCode maps a Bitget API response "code" to a sentinel error so callers can use errors.Is without parsing raw codes themselves. Unknown codes return nil (caller should fall back to the raw *Error).

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is the low-level authenticated HTTP transport shared by every service under RestClient. Most callers should construct a *RestClient via NewRestClient instead of using Client directly.

func NewClient

func NewClient(apiKey, secretKey, passphrase string, opts ...Option) *Client

NewClient creates a low-level Client. apiKey/secretKey/passphrase are the credentials generated for an API key in the Bitget web console (https://www.bitget.com/api-doc/uta/guide). Most callers want NewRestClient instead, which additionally wires up all API services.

type Error added in v1.0.4

type Error struct {
	Code    string
	Message string
	Raw     []byte
}

Error represents a structured error returned by the Bitget UTA API, preserving the exact code/message pair sent back in the response envelope.

Docs: https://www.bitget.com/api-doc/uta/guide

func (*Error) Error added in v1.0.4

func (e *Error) Error() string

type Logger

type Logger interface {
	Debug(msg string, args ...any)
	Info(msg string, args ...any)
	Warn(msg string, args ...any)
	Error(msg string, args ...any)
}

Logger is a minimal structured-logging interface. Pass an adapter (see NewSlogLogger) or your own implementation via WithLogger; the default is a no-op logger.

func NewSlogLogger

func NewSlogLogger(l *slog.Logger) Logger

NewSlogLogger wraps l so it can be passed to WithLogger. A nil logger uses the same no-op behavior as a client without an explicitly configured logger.

type Option

type Option func(*Client)

Option configures a Client at construction time.

func WithBaseURL

func WithBaseURL(baseURL string) Option

WithBaseURL overrides the REST base URL, e.g. for Bitget's VIP endpoint or a test server. Pass an origin without a trailing API path: SDK methods add their own /api/v3/... path.

func WithDemoTrading

func WithDemoTrading() Option

WithDemoTrading enables Bitget's simulated-trading mode by sending the "paptrading: 1" header on every request. Use together with a Demo API key; see https://www.bitget.com/api-doc/uta/guide.

func WithHTTPClient

func WithHTTPClient(hc *http.Client) Option

WithHTTPClient injects a custom *http.Client (for proxies, custom transports, or test doubles). The client is used as-is; DefaultTimeout is not applied when this option is used.

func WithLocale

func WithLocale(locale string) Option

WithLocale sets the "locale" header sent on every request (e.g. "en-US", "zh-CN"). Defaults to "en-US".

func WithLogger

func WithLogger(l Logger) Option

WithLogger sets a structured logger for request/response diagnostics. Never logs ACCESS-KEY, ACCESS-SIGN, or ACCESS-PASSPHRASE values.

func WithTimeout

func WithTimeout(d time.Duration) Option

WithTimeout sets the timeout of the internally constructed *http.Client. Ignored if WithHTTPClient is also used.

type RawFrame added in v1.1.0

type RawFrame struct {
	Payload    []byte
	ReceivedAt time.Time
	Generation uint64
}

RawFrame is an exact WebSocket message received from Bitget before the SDK decodes it. Payload is a private copy and must be treated as read-only. Generation increases after every successful connection; ReceivedAt is taken immediately after the network read completes.

type RawFrameHandler added in v1.1.0

type RawFrameHandler func(RawFrame) error

RawFrameHandler observes every received WebSocket message synchronously. It is the lossless canonical path for consumers that need exact wire data. Keep it short or apply backpressure deliberately. Returning an error emits a terminal lifecycle event and disconnects the current connection.

type RestClient

type RestClient struct {
	*Client

	// Market provides public, unauthenticated market-data endpoints.
	Market *market.Client
	// Account provides private account/balance/leverage endpoints.
	Account *account.Client
	// Trade provides private order-placement and position endpoints.
	Trade *trade.Client
}

RestClient is the main entry point for the REST API, grouping every service under one struct. Construct it with NewRestClient.

func NewRestClient

func NewRestClient(apiKey, secretKey, passphrase string, opts ...Option) *RestClient

NewRestClient creates a fully wired Bitget UTA v3 REST client. apiKey, secretKey, and passphrase come from the API key created in the Bitget web console; see https://www.bitget.com/api-doc/uta/guide.

Public endpoints (RestClient.Market) work even with empty credentials.

type WSClient

type WSClient struct {
	// contains filtered or unexported fields
}

WSClient is a reconnecting WebSocket client for Bitget's public or private UTA v3 streams. Create one with NewPublicWSClient or NewPrivateWSClient.

Docs: https://www.bitget.com/api-doc/uta/websocket/private/Fast-Fill-Channel

func NewPrivateWSClient

func NewPrivateWSClient(apiKey, secretKey, passphrase string, opts ...WSOption) *WSClient

NewPrivateWSClient creates a client for Bitget's private WebSocket streams (order fills, positions, etc.), authenticating automatically on Connect.

func NewPublicWSClient

func NewPublicWSClient(opts ...WSOption) *WSClient

NewPublicWSClient creates a client for Bitget's public market-data WebSocket streams (no authentication).

func (*WSClient) Close

func (c *WSClient) Close() error

Close terminates the connection and stops all background loops. Safe to call multiple times.

func (*WSClient) Connect

func (c *WSClient) Connect(ctx context.Context) error

Connect dials the WebSocket endpoint, logs in (for private clients), and starts the background read/ping/reconnect loops. Connect blocks until the initial connection (and, for private clients, login) succeeds or ctx is done.

func (*WSClient) Subscribe

func (c *WSClient) Subscribe(ctx context.Context, arg models.WSArg) (<-chan models.WSPush, error)

Subscribe subscribes to a channel and returns a buffered channel of data pushes. The subscription is automatically restored after a reconnect.

func (*WSClient) Unsubscribe

func (c *WSClient) Unsubscribe(arg models.WSArg) error

Unsubscribe removes a channel subscription and closes its data channel.

type WSEventHandler added in v1.1.0

type WSEventHandler func(WSLifecycleEvent)

WSEventHandler handles lifecycle events synchronously. It must return promptly and must not panic; the SDK does not buffer or drop these events.

type WSLifecycleEvent added in v1.1.0

type WSLifecycleEvent struct {
	Type       WSLifecycleType
	Arg        *models.WSArg
	Code       string
	Message    string
	Err        error
	ReceivedAt time.Time
	Generation uint64
}

WSLifecycleEvent reports the observable control-plane lifecycle. Arg is copied from Bitget's control event, allowing callers to correlate an ACK or provider error to a subscription. Err is non-nil for local terminal errors.

type WSLifecycleType added in v1.1.0

type WSLifecycleType string

WSLifecycleType identifies a WebSocket connection or subscription event.

const (
	WSConnected               WSLifecycleType = "connected"
	WSDisconnected            WSLifecycleType = "disconnected"
	WSClosed                  WSLifecycleType = "closed"
	WSAuthenticated           WSLifecycleType = "authenticated"
	WSSubscriptionRequested   WSLifecycleType = "subscription_requested"
	WSSubscribed              WSLifecycleType = "subscribed"
	WSUnsubscriptionRequested WSLifecycleType = "unsubscription_requested"
	WSUnsubscribed            WSLifecycleType = "unsubscribed"
	WSProviderError           WSLifecycleType = "provider_error"
	WSTerminal                WSLifecycleType = "terminal"
)

WSLifecycle event types are delivered to a WSEventHandler.

type WSOption

type WSOption func(*WSClient)

WSOption configures a WSClient at construction time.

func WithRawFrameHandler added in v1.1.0

func WithRawFrameHandler(handler RawFrameHandler) WSOption

WithRawFrameHandler installs the canonical, synchronous raw-frame observer. It receives a full immutable copy before JSON decoding and before the bounded WSPush subscriber buffers are considered.

func WithWSAutoReconnect

func WithWSAutoReconnect(enabled bool) WSOption

WithWSAutoReconnect toggles automatic reconnection with exponential backoff on unexpected disconnects. Enabled by default.

func WithWSEventHandler added in v1.1.0

func WithWSEventHandler(handler WSEventHandler) WSOption

WithWSEventHandler installs a synchronous observer for connection and subscription lifecycle events, including subscribe ACKs and provider errors.

func WithWSLogger

func WithWSLogger(l Logger) WSOption

WithWSLogger sets a structured logger for connection lifecycle events.

func WithWSURL

func WithWSURL(url string) WSOption

WithWSURL overrides the WebSocket endpoint, e.g. for Bitget's demo/paper trading WS or the Lo-La VIP endpoint.

Directories

Path Synopsis
examples
demo-account command
Command demo_account reads account data with a Demo API key.
Command demo_account reads account data with a Demo API key.
history command
Command history fetches one public deep-history candle page and reports its bounded receipt.
Command history fetches one public deep-history candle page and reports its bounded receipt.
rest command
Command rest_example demonstrates public market data.
Command rest_example demonstrates public market data.
websocket command
Command websocket_example demonstrates connecting to Bitget's public WebSocket, subscribing to a channel, and handling reconnects.
Command websocket_example demonstrates connecting to Bitget's public WebSocket, subscribing to a channel, and handling reconnects.
websocket-private command
Command websocket_private demonstrates a Demo private WebSocket subscription.
Command websocket_private demonstrates a Demo private WebSocket subscription.
Package models contains typed request/response structures for the Bitget UTA v3 API.
Package models contains typed request/response structures for the Bitget UTA v3 API.
rest
account
Package account implements Bitget UTA v3's private account endpoints.
Package account implements Bitget UTA v3's private account endpoints.
market
Package market implements Bitget UTA v3's public market-data endpoints.
Package market implements Bitget UTA v3's public market-data endpoints.
trade
Package trade implements Bitget UTA v3's private order and position endpoints.
Package trade implements Bitget UTA v3's private order and position endpoints.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL