diff --git a/pkg/exchange/bitget/bitgetapi/v2/client.go b/pkg/exchange/bitget/bitgetapi/v2/client.go index d15cd889b..921b50131 100644 --- a/pkg/exchange/bitget/bitgetapi/v2/client.go +++ b/pkg/exchange/bitget/bitgetapi/v2/client.go @@ -8,6 +8,7 @@ import ( const ( PrivateWebSocketURL = "wss://ws.bitget.com/v2/ws/private" + PublicWebSocketURL = "wss://ws.bitget.com/v2/ws/public" ) type APIResponse = bitgetapi.APIResponse diff --git a/pkg/exchange/bitget/stream.go b/pkg/exchange/bitget/stream.go index b4df9b835..bc62bb920 100644 --- a/pkg/exchange/bitget/stream.go +++ b/pkg/exchange/bitget/stream.go @@ -120,7 +120,7 @@ func (s *Stream) Unsubscribe() { func (s *Stream) createEndpoint(_ context.Context) (string, error) { var url string if s.PublicOnly { - url = bitgetapi.PublicWebSocketURL + url = v2.PublicWebSocketURL } else { url = v2.PrivateWebSocketURL } @@ -245,7 +245,7 @@ func (s *Stream) ping(conn *websocket.Conn) error { func convertSubscription(sub types.Subscription) (WsArg, error) { arg := WsArg{ // support spot only - InstType: instSp, + InstType: instSpV2, Channel: "", InstId: sub.Symbol, } diff --git a/pkg/exchange/bitget/stream_test.go b/pkg/exchange/bitget/stream_test.go index c605ad32a..b6a6721b8 100644 --- a/pkg/exchange/bitget/stream_test.go +++ b/pkg/exchange/bitget/stream_test.go @@ -179,7 +179,7 @@ func TestStream_parseWebSocketEvent(t *testing.T) { input := `{ "event":"subscribe", "arg":{ - "instType":"sp", + "instType":"SPOT", "channel":"books5", "instId":"BTCUSDT" } @@ -191,7 +191,7 @@ func TestStream_parseWebSocketEvent(t *testing.T) { assert.Equal(t, WsEvent{ Event: WsEventSubscribe, Arg: WsArg{ - InstType: instSp, + InstType: instSpV2, Channel: ChannelOrderBook5, InstId: "BTCUSDT", }, @@ -204,7 +204,7 @@ func TestStream_parseWebSocketEvent(t *testing.T) { input := `{ "event":"unsubscribe", "arg":{ - "instType":"sp", + "instType":"SPOT", "channel":"books5", "instId":"BTCUSDT" } @@ -216,7 +216,7 @@ func TestStream_parseWebSocketEvent(t *testing.T) { assert.Equal(t, WsEvent{ Event: WsEventUnsubscribe, Arg: WsArg{ - InstType: instSp, + InstType: instSpV2, Channel: ChannelOrderBook5, InstId: "BTCUSDT", }, @@ -227,7 +227,7 @@ func TestStream_parseWebSocketEvent(t *testing.T) { input := `{ "event":"error", "arg":{ - "instType":"sp", + "instType":"SPOT", "channel":"books5", "instId":"BTCUSDT-" }, @@ -245,7 +245,7 @@ func TestStream_parseWebSocketEvent(t *testing.T) { Msg: "instType:sp,channel:books5,instId:BTCUSDT- doesn't exist", Op: "subscribe", Arg: WsArg{ - InstType: instSp, + InstType: instSpV2, Channel: ChannelOrderBook5, InstId: "BTCUSDT-", }, @@ -256,7 +256,7 @@ func TestStream_parseWebSocketEvent(t *testing.T) { input := `{ "action":"%s", "arg":{ - "instType":"sp", + "instType":"SPOT", "channel":"books5", "instId":"BTCUSDT" }, @@ -349,7 +349,7 @@ func Test_parseWebSocketEvent_MarketTrade(t *testing.T) { input := `{ "action":"%s", "arg":{ - "instType":"sp", + "instType":"SPOT", "channel":"trade", "instId":"BTCUSDT" }, @@ -434,7 +434,7 @@ func Test_parseWebSocketEvent_MarketTrade(t *testing.T) { input := `{ "action":"%s", "arg":{ - "instType":"sp", + "instType":"SPOT", "channel":"trade", "instId":"BTCUSDT" }, @@ -456,7 +456,7 @@ func Test_parseWebSocketEvent_MarketTrade(t *testing.T) { input := `{ "action":"%s", "arg":{ - "instType":"sp", + "instType":"SPOT", "channel":"trade", "instId":"BTCUSDT" }, @@ -478,7 +478,7 @@ func Test_parseWebSocketEvent_MarketTrade(t *testing.T) { input := `{ "action":"%s", "arg":{ - "instType":"sp", + "instType":"SPOT", "channel":"trade", "instId":"BTCUSDT" }, @@ -500,7 +500,7 @@ func Test_parseWebSocketEvent_MarketTrade(t *testing.T) { input := `{ "action":"%s", "arg":{ - "instType":"sp", + "instType":"SPOT", "channel":"trade", "instId":"BTCUSDT" }, @@ -524,12 +524,12 @@ func Test_parseWebSocketEvent_KLine(t *testing.T) { input := `{ "action":"%s", "arg":{ - "instType":"sp", + "instType":"SPOT", "channel":"candle5m", "instId":"BTCUSDT" }, "data":[ - ["1698744600000","34361.49","34458.98","34355.53","34416.41","99.6631"] + ["1698744600000","34361.49","34458.98","34355.53","34416.41","99.6631", "123456", "123"] ], "ts":1697697791670 }` @@ -549,6 +549,7 @@ func Test_parseWebSocketEvent_KLine(t *testing.T) { LowestPrice: fixedpoint.NewFromFloat(34355.53), ClosePrice: fixedpoint.NewFromFloat(34416.41), Volume: fixedpoint.NewFromFloat(99.6631), + QuoteVolume: fixedpoint.NewFromFloat(123456), }, }, actionType: actionType, @@ -571,12 +572,12 @@ func Test_parseWebSocketEvent_KLine(t *testing.T) { input := `{ "action":"%s", "arg":{ - "instType":"sp", + "instType":"SPOT", "channel":"candle5m", "instId":"BTCUSDT" }, "data":[ - ["1698744600000","34361.45","34458.98","34355.53","34416.41","99.6631", "123456"] + ["1698744600000","34361.49","34458.98","34355.53","34416.41","99.6631", "123456", "123", "123"] ], "ts":1697697791670 }` @@ -588,12 +589,12 @@ func Test_parseWebSocketEvent_KLine(t *testing.T) { input := `{ "action":"%s", "arg":{ - "instType":"sp", + "instType":"SPOT", "channel":"candle5m", "instId":"BTCUSDT" }, "data":[ - ["timestamp","34361.49","34458.98","34355.53","34416.41","99.6631"] + ["timestamp","34361.49","34458.98","34355.53","34416.41","99.6631", "123456", "123"] ], "ts":1697697791670 }` @@ -605,12 +606,12 @@ func Test_parseWebSocketEvent_KLine(t *testing.T) { input := `{ "action":"%s", "arg":{ - "instType":"sp", + "instType":"SPOT", "channel":"candle5m", "instId":"BTCUSDT" }, "data":[ - ["1698744600000","1p","34458.98","34355.53","34416.41","99.6631"] + ["1698744600000","1p","34458.98","34355.53","34416.41","99.6631", "123456", "123"] ], "ts":1697697791670 }` @@ -622,12 +623,12 @@ func Test_parseWebSocketEvent_KLine(t *testing.T) { input := `{ "action":"%s", "arg":{ - "instType":"sp", + "instType":"SPOT", "channel":"candle5m", "instId":"BTCUSDT" }, "data":[ - ["1698744600000","34361.45","3p","34355.53","34416.41","99.6631"] + ["1698744600000","34361.49","3p","34355.53","34416.41","99.6631", "123456", "123"] ], "ts":1697697791670 }` @@ -639,12 +640,12 @@ func Test_parseWebSocketEvent_KLine(t *testing.T) { input := `{ "action":"%s", "arg":{ - "instType":"sp", + "instType":"SPOT", "channel":"candle5m", "instId":"BTCUSDT" }, "data":[ - ["1698744600000","34361.45","34458.98","1p","34416.41","99.6631"] + ["1698744600000","34361.49","34458.98","1p","34416.41","99.6631", "123456", "123"] ], "ts":1697697791670 }` @@ -656,12 +657,12 @@ func Test_parseWebSocketEvent_KLine(t *testing.T) { input := `{ "action":"%s", "arg":{ - "instType":"sp", + "instType":"SPOT", "channel":"candle5m", "instId":"BTCUSDT" }, "data":[ - ["1698744600000","34361.45","34458.98","34355.53","1c","99.6631"] + ["1698744600000","34361.49","34458.98","34355.53","1c","99.6631", "123456", "123"] ], "ts":1697697791670 }` @@ -673,12 +674,12 @@ func Test_parseWebSocketEvent_KLine(t *testing.T) { input := `{ "action":"%s", "arg":{ - "instType":"sp", + "instType":"SPOT", "channel":"candle5m", "instId":"BTCUSDT" }, "data":[ - ["1698744600000","34361.45","34458.98","34355.53","34416.41", "1v"] + ["1698744600000","34361.49","34458.98","34355.53","34416.41","1v", "123456", "123"] ], "ts":1697697791670 }` @@ -698,7 +699,7 @@ func Test_convertSubscription(t *testing.T) { }) assert.NoError(t, err) assert.Equal(t, WsArg{ - InstType: instSp, + InstType: instSpV2, Channel: ChannelOrderBook5, InstId: "BTCUSDT", }, res) @@ -713,7 +714,7 @@ func Test_convertSubscription(t *testing.T) { }) assert.NoError(t, err) assert.Equal(t, WsArg{ - InstType: instSp, + InstType: instSpV2, Channel: ChannelOrderBook15, InstId: "BTCUSDT", }, res) @@ -728,7 +729,7 @@ func Test_convertSubscription(t *testing.T) { }) assert.NoError(t, err) assert.Equal(t, WsArg{ - InstType: instSp, + InstType: instSpV2, Channel: ChannelOrderBook, InstId: "BTCUSDT", }, res) @@ -741,7 +742,7 @@ func Test_convertSubscription(t *testing.T) { }) assert.NoError(t, err) assert.Equal(t, WsArg{ - InstType: instSp, + InstType: instSpV2, Channel: ChannelTrade, InstId: "BTCUSDT", }, res) @@ -757,7 +758,7 @@ func Test_convertSubscription(t *testing.T) { }) assert.NoError(t, err) assert.Equal(t, WsArg{ - InstType: instSp, + InstType: instSpV2, Channel: ChannelType(localInterval), InstId: "BTCUSDT", }, res) diff --git a/pkg/exchange/bitget/types.go b/pkg/exchange/bitget/types.go index 309ffe4ab..478942efe 100644 --- a/pkg/exchange/bitget/types.go +++ b/pkg/exchange/bitget/types.go @@ -14,7 +14,6 @@ import ( type InstType string const ( - instSp InstType = "sp" instSpV2 InstType = "SPOT" ) @@ -285,21 +284,27 @@ var ( types.Interval30m: "candle30m", types.Interval1h: "candle1H", types.Interval4h: "candle4H", - types.Interval12h: "candle12H", - types.Interval1d: "candle1D", - types.Interval1w: "candle1W", + types.Interval6h: "candle6Hutc", + types.Interval12h: "candle12Hutc", + types.Interval1d: "candle1Dutc", + types.Interval3d: "candle3Dutc", + types.Interval1w: "candle1Wutc", + types.Interval1mo: "candle1Mutc", } toGlobalInterval = map[string]types.Interval{ - "candle1m": types.Interval1m, - "candle5m": types.Interval5m, - "candle15m": types.Interval15m, - "candle30m": types.Interval30m, - "candle1H": types.Interval1h, - "candle4H": types.Interval4h, - "candle12H": types.Interval12h, - "candle1D": types.Interval1d, - "candle1W": types.Interval1w, + "candle1m": types.Interval1m, + "candle5m": types.Interval5m, + "candle15m": types.Interval15m, + "candle30m": types.Interval30m, + "candle1H": types.Interval1h, + "candle4H": types.Interval4h, + "candle6Hutc": types.Interval6h, + "candle12Hutc": types.Interval12h, + "candle1Dutc": types.Interval1d, + "candle3Dutc": types.Interval3d, + "candle1Wutc": types.Interval1w, + "candle1Mutc": types.Interval1mo, } // we align utc time zone @@ -345,6 +350,7 @@ type KLine struct { LowestPrice fixedpoint.Value ClosePrice fixedpoint.Value Volume fixedpoint.Value + QuoteVolume fixedpoint.Value } func (k KLine) ToGlobal(interval types.Interval, symbol string) types.KLine { @@ -361,7 +367,7 @@ func (k KLine) ToGlobal(interval types.Interval, symbol string) types.KLine { High: k.HighestPrice, Low: k.LowestPrice, Volume: k.Volume, - QuoteVolume: fixedpoint.Zero, // not supported + QuoteVolume: k.QuoteVolume, TakerBuyBaseAssetVolume: fixedpoint.Zero, // not supported TakerBuyQuoteAssetVolume: fixedpoint.Zero, // not supported LastTradeID: 0, // not supported @@ -400,9 +406,10 @@ func parseKLineSliceJSON(in []byte) (slice KLineSlice, err error) { } for _, raw := range rawKLines { - if len(raw) != 6 { + if len(raw) != 8 { return nil, fmt.Errorf("unexpected kline length: %d, data: %q", len(raw), raw) } + // even though it supports 8 fields, we only parse the ones we need. var kline KLine if err = json.Unmarshal(raw[0], &kline.StartTime); err != nil { return nil, fmt.Errorf("failed to unmarshal into timestamp: %q", raw[0]) @@ -422,6 +429,9 @@ func parseKLineSliceJSON(in []byte) (slice KLineSlice, err error) { if err = json.Unmarshal(raw[5], &kline.Volume); err != nil { return nil, fmt.Errorf("failed to unmarshal into volume: %q", raw[5]) } + if err = json.Unmarshal(raw[6], &kline.QuoteVolume); err != nil { + return nil, fmt.Errorf("failed to unmarshal into quote volume: %q", raw[6]) + } slice = append(slice, kline) }