From ec57509dd2376fedf639fa8e2f5982b9ee39edc2 Mon Sep 17 00:00:00 2001 From: Gareth Kirwan Date: Mon, 23 Oct 2023 18:29:35 +0700 Subject: [PATCH] fixup! Websockets: Add Subscription configuration Websockets: Switch to kline.Interval for interval There's a slight hack here that we're probably going to abuse Interval for orderbook intervals too. It that's too distasteful can break that out into rate, but honestly think we'd end up using the same mechanics. Maybe better to break kline.Interval out into common/interval/* in that case --- config/config_types.go | 9 +++++---- exchanges/binance/binance_test.go | 4 +++- exchanges/binance/binance_websocket.go | 16 ++++++---------- exchanges/binance/binance_wrapper.go | 4 ++-- exchanges/kline/kline.go | 11 +++++++++++ exchanges/stream/stream_types.go | 3 ++- 6 files changed, 29 insertions(+), 18 deletions(-) diff --git a/config/config_types.go b/config/config_types.go index 2e7455e1deb..fe73c1e5a1c 100644 --- a/config/config_types.go +++ b/config/config_types.go @@ -8,6 +8,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/communications/base" "github.com/thrasher-corp/gocryptotrader/currency" "github.com/thrasher-corp/gocryptotrader/database" + "github.com/thrasher-corp/gocryptotrader/exchanges/kline" "github.com/thrasher-corp/gocryptotrader/exchanges/protocol" gctscript "github.com/thrasher-corp/gocryptotrader/gctscript/vm" "github.com/thrasher-corp/gocryptotrader/log" @@ -314,10 +315,10 @@ type FeaturesEnabledConfig struct { } type EnabledSubscriptionConfig struct { - Channel string `json:"channel"` - Interval string `json:"interval,omitempty"` - Levels int `json:"levels,omitempty"` - Authenticated bool `json:"authenticated,omitempty"` + Channel string `json:"channel"` + Interval kline.Interval `json:"interval,omitempty"` + Levels int `json:"levels,omitempty"` + Authenticated bool `json:"authenticated,omitempty"` } // FeaturesConfig stores the exchanges supported and enabled features diff --git a/exchanges/binance/binance_test.go b/exchanges/binance/binance_test.go index 30bb9d1c77e..554f3525ed6 100644 --- a/exchanges/binance/binance_test.go +++ b/exchanges/binance/binance_test.go @@ -2443,7 +2443,9 @@ func TestGenerateSubscriptions(t *testing.T) { } } } - assert.ElementsMatch(t, subs, expected, "Should get the correct subscriptions") + if assert.Len(t, subs, len(expected), "Should have the correct number of subs") { + assert.ElementsMatch(t, subs, expected, "Should get the correct subscriptions") + } } var websocketDepthUpdate = []byte(`{"E":1608001030784,"U":7145637266,"a":[["19455.19000000","0.59490200"],["19455.37000000","0.00000000"],["19456.11000000","0.00000000"],["19456.16000000","0.00000000"],["19458.67000000","0.06400000"],["19460.73000000","0.05139800"],["19461.43000000","0.00000000"],["19464.59000000","0.00000000"],["19466.03000000","0.45000000"],["19466.36000000","0.00000000"],["19508.67000000","0.00000000"],["19572.96000000","0.00217200"],["24386.00000000","0.00256600"]],"b":[["19455.18000000","2.94649200"],["19453.15000000","0.01233600"],["19451.18000000","0.00000000"],["19446.85000000","0.11427900"],["19446.74000000","0.00000000"],["19446.73000000","0.00000000"],["19444.45000000","0.14937800"],["19426.75000000","0.00000000"],["19416.36000000","0.36052100"]],"e":"depthUpdate","s":"BTCUSDT","u":7145637297}`) diff --git a/exchanges/binance/binance_websocket.go b/exchanges/binance/binance_websocket.go index a4651741d26..1ad18128c82 100644 --- a/exchanges/binance/binance_websocket.go +++ b/exchanges/binance/binance_websocket.go @@ -586,7 +586,7 @@ func (b *Binance) GenerateSubscriptions() ([]stream.ChannelSubscription, error) func channelName(s stream.ChannelSubscription) (string, error) { name, ok := subscriptionNames[s.Channel] if !ok { - // TODO: Name error + // TODO: const err type please return name, fmt.Errorf("%w: %s", errors.New("Unsupported subscription channel"), s.Channel) } @@ -595,17 +595,13 @@ func channelName(s stream.ChannelSubscription) (string, error) { if s.Levels != 0 { name += "@" + strconv.Itoa(s.Levels) } - interval := s.Interval - if interval == "" { - interval = "100ms" + if s.Interval.Duration() == time.Second { + name += "@1000ms" + } else { + name += "@" + s.Interval.Short() } - name += "@" + interval case stream.CandlesSubscription: - interval := s.Interval - if interval == "" { - interval = "1m" - } - name += "_" + interval + name += "_" + s.Interval.Short() } return name, nil } diff --git a/exchanges/binance/binance_wrapper.go b/exchanges/binance/binance_wrapper.go index 19743c25858..6aefb8d03ab 100644 --- a/exchanges/binance/binance_wrapper.go +++ b/exchanges/binance/binance_wrapper.go @@ -201,8 +201,8 @@ func (b *Binance) SetDefaults() { Subscriptions: []stream.ChannelSubscription{ {Channel: stream.TickerSubscription}, {Channel: stream.AllTradesSubscription}, - {Channel: stream.CandlesSubscription, Interval: "1m"}, - {Channel: stream.OrderbookSubscription, Interval: "100ms"}, + {Channel: stream.CandlesSubscription, Interval: kline.OneMin}, + {Channel: stream.OrderbookSubscription, Interval: kline.HundredMilliseconds}, }, }, } diff --git a/exchanges/kline/kline.go b/exchanges/kline/kline.go index 5a816e7e842..d14259e8809 100644 --- a/exchanges/kline/kline.go +++ b/exchanges/kline/kline.go @@ -143,6 +143,17 @@ func (i Interval) Short() string { return s } +// UnmarshalText implements the TextUnmarshaller interface for Intervals +// It does not validate the duration is aligned, only that it is a parsable duration +func (i *Interval) UnmarshalText(text []byte) error { + d, err := time.ParseDuration(string(text)) + if err != nil { + return err + } + *i = Interval(d) + return nil +} + // addPadding inserts padding time aligned when exchanges do not supply all data // when there is no activity in a certain time interval. // Start defines the request start and due to potential no activity from this diff --git a/exchanges/stream/stream_types.go b/exchanges/stream/stream_types.go index e7d5f8467a4..61659580565 100644 --- a/exchanges/stream/stream_types.go +++ b/exchanges/stream/stream_types.go @@ -7,6 +7,7 @@ import ( "github.com/gorilla/websocket" "github.com/thrasher-corp/gocryptotrader/currency" "github.com/thrasher-corp/gocryptotrader/exchanges/asset" + "github.com/thrasher-corp/gocryptotrader/exchanges/kline" "github.com/thrasher-corp/gocryptotrader/exchanges/order" ) @@ -47,7 +48,7 @@ type ChannelSubscription struct { Currency currency.Pair Asset asset.Item Params map[string]interface{} - Interval string + Interval kline.Interval Levels int Authenticated bool }