mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-06-04 07:26:47 +00:00
exchanges/websocket: Implement subscription configuration (#1394)
* Websockets: Move Subscription to its own package This allows the small type to be imported from both `config` and from `stream` without an import cycle, so we don't have to repeat ourselves * Subs: Renamed Currency to Pair This was being mis-used through much of the code, and since we're already touching everything, we might as well fix it * Websockets: Add Subscription configuration * Binance: Add subscription configuration * Kucoin: Subscription configuration * Simplify GenerateDefaultSubs * Improve TestGenSubs coverage * Test Candle Sub generation * Support Candle intervals * Full responsibility for formatting Channel name on GenerateDefaultSubs OR consumer of Subscribe * Simplify generatePayloads as a result * Fix test coverage of asset types in processMarketSnapshot * Exchanges: Abstract ParallelChanOp * Tests: Generic ws mock instances * Kucoin: Fix intermittent conflict in test currs Use isolated test instance for `TestGetOpenInterest`. `TestGetOpenInterest` would occassionally change pairs before GenerateDefault Subs.
This commit is contained in:
@@ -23,6 +23,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/stream"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/subscription"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/trade"
|
||||
)
|
||||
@@ -624,7 +625,7 @@ func (g *Gateio) processCrossMarginLoans(data []byte) error {
|
||||
}
|
||||
|
||||
// GenerateDefaultSubscriptions returns default subscriptions
|
||||
func (g *Gateio) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, error) {
|
||||
func (g *Gateio) GenerateDefaultSubscriptions() ([]subscription.Subscription, error) {
|
||||
channelsToSubscribe := defaultSubscriptions
|
||||
if g.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
channelsToSubscribe = append(channelsToSubscribe, []string{
|
||||
@@ -637,7 +638,7 @@ func (g *Gateio) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, e
|
||||
channelsToSubscribe = append(channelsToSubscribe, spotTradesChannel)
|
||||
}
|
||||
|
||||
var subscriptions []stream.ChannelSubscription
|
||||
var subscriptions []subscription.Subscription
|
||||
var err error
|
||||
for i := range channelsToSubscribe {
|
||||
var pairs []currency.Pair
|
||||
@@ -677,11 +678,11 @@ func (g *Gateio) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, e
|
||||
return nil, err
|
||||
}
|
||||
|
||||
subscriptions = append(subscriptions, stream.ChannelSubscription{
|
||||
Channel: channelsToSubscribe[i],
|
||||
Currency: fpair.Upper(),
|
||||
Asset: assetType,
|
||||
Params: params,
|
||||
subscriptions = append(subscriptions, subscription.Subscription{
|
||||
Channel: channelsToSubscribe[i],
|
||||
Pair: fpair.Upper(),
|
||||
Asset: assetType,
|
||||
Params: params,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -689,7 +690,7 @@ func (g *Gateio) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, e
|
||||
}
|
||||
|
||||
// handleSubscription sends a websocket message to receive data from the channel
|
||||
func (g *Gateio) handleSubscription(event string, channelsToSubscribe []stream.ChannelSubscription) error {
|
||||
func (g *Gateio) handleSubscription(event string, channelsToSubscribe []subscription.Subscription) error {
|
||||
payloads, err := g.generatePayload(event, channelsToSubscribe)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -719,7 +720,7 @@ func (g *Gateio) handleSubscription(event string, channelsToSubscribe []stream.C
|
||||
return errs
|
||||
}
|
||||
|
||||
func (g *Gateio) generatePayload(event string, channelsToSubscribe []stream.ChannelSubscription) ([]WsInput, error) {
|
||||
func (g *Gateio) generatePayload(event string, channelsToSubscribe []subscription.Subscription) ([]WsInput, error) {
|
||||
if len(channelsToSubscribe) == 0 {
|
||||
return nil, errors.New("cannot generate payload, no channels supplied")
|
||||
}
|
||||
@@ -737,8 +738,8 @@ func (g *Gateio) generatePayload(event string, channelsToSubscribe []stream.Chan
|
||||
for i := range channelsToSubscribe {
|
||||
var auth *WsAuthInput
|
||||
timestamp := time.Now()
|
||||
channelsToSubscribe[i].Currency.Delimiter = currency.UnderscoreDelimiter
|
||||
params := []string{channelsToSubscribe[i].Currency.String()}
|
||||
channelsToSubscribe[i].Pair.Delimiter = currency.UnderscoreDelimiter
|
||||
params := []string{channelsToSubscribe[i].Pair.String()}
|
||||
switch channelsToSubscribe[i].Channel {
|
||||
case spotOrderbookChannel:
|
||||
interval, okay := channelsToSubscribe[i].Params["interval"].(kline.Interval)
|
||||
@@ -836,12 +837,12 @@ func (g *Gateio) generatePayload(event string, channelsToSubscribe []stream.Chan
|
||||
}
|
||||
|
||||
// Subscribe sends a websocket message to stop receiving data from the channel
|
||||
func (g *Gateio) Subscribe(channelsToUnsubscribe []stream.ChannelSubscription) error {
|
||||
func (g *Gateio) Subscribe(channelsToUnsubscribe []subscription.Subscription) error {
|
||||
return g.handleSubscription("subscribe", channelsToUnsubscribe)
|
||||
}
|
||||
|
||||
// Unsubscribe sends a websocket message to stop receiving data from the channel
|
||||
func (g *Gateio) Unsubscribe(channelsToUnsubscribe []stream.ChannelSubscription) error {
|
||||
func (g *Gateio) Unsubscribe(channelsToUnsubscribe []subscription.Subscription) error {
|
||||
return g.handleSubscription("unsubscribe", channelsToUnsubscribe)
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/stream"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/subscription"
|
||||
"github.com/thrasher-corp/gocryptotrader/log"
|
||||
)
|
||||
|
||||
@@ -140,7 +141,7 @@ func (g *Gateio) wsFunnelDeliveryFuturesConnectionData(ws stream.Connection) {
|
||||
}
|
||||
|
||||
// GenerateDeliveryFuturesDefaultSubscriptions returns delivery futures default subscriptions params.
|
||||
func (g *Gateio) GenerateDeliveryFuturesDefaultSubscriptions() ([]stream.ChannelSubscription, error) {
|
||||
func (g *Gateio) GenerateDeliveryFuturesDefaultSubscriptions() ([]subscription.Subscription, error) {
|
||||
_, err := g.GetCredentials(context.Background())
|
||||
if err != nil {
|
||||
g.Websocket.SetCanUseAuthenticatedEndpoints(false)
|
||||
@@ -158,7 +159,7 @@ func (g *Gateio) GenerateDeliveryFuturesDefaultSubscriptions() ([]stream.Channel
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var subscriptions []stream.ChannelSubscription
|
||||
var subscriptions []subscription.Subscription
|
||||
for i := range channelsToSubscribe {
|
||||
for j := range pairs {
|
||||
params := make(map[string]interface{})
|
||||
@@ -173,10 +174,10 @@ func (g *Gateio) GenerateDeliveryFuturesDefaultSubscriptions() ([]stream.Channel
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
subscriptions = append(subscriptions, stream.ChannelSubscription{
|
||||
Channel: channelsToSubscribe[i],
|
||||
Currency: fpair.Upper(),
|
||||
Params: params,
|
||||
subscriptions = append(subscriptions, subscription.Subscription{
|
||||
Channel: channelsToSubscribe[i],
|
||||
Pair: fpair.Upper(),
|
||||
Params: params,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -184,17 +185,17 @@ func (g *Gateio) GenerateDeliveryFuturesDefaultSubscriptions() ([]stream.Channel
|
||||
}
|
||||
|
||||
// DeliveryFuturesSubscribe sends a websocket message to stop receiving data from the channel
|
||||
func (g *Gateio) DeliveryFuturesSubscribe(channelsToUnsubscribe []stream.ChannelSubscription) error {
|
||||
func (g *Gateio) DeliveryFuturesSubscribe(channelsToUnsubscribe []subscription.Subscription) error {
|
||||
return g.handleDeliveryFuturesSubscription("subscribe", channelsToUnsubscribe)
|
||||
}
|
||||
|
||||
// DeliveryFuturesUnsubscribe sends a websocket message to stop receiving data from the channel
|
||||
func (g *Gateio) DeliveryFuturesUnsubscribe(channelsToUnsubscribe []stream.ChannelSubscription) error {
|
||||
func (g *Gateio) DeliveryFuturesUnsubscribe(channelsToUnsubscribe []subscription.Subscription) error {
|
||||
return g.handleDeliveryFuturesSubscription("unsubscribe", channelsToUnsubscribe)
|
||||
}
|
||||
|
||||
// handleDeliveryFuturesSubscription sends a websocket message to receive data from the channel
|
||||
func (g *Gateio) handleDeliveryFuturesSubscription(event string, channelsToSubscribe []stream.ChannelSubscription) error {
|
||||
func (g *Gateio) handleDeliveryFuturesSubscription(event string, channelsToSubscribe []subscription.Subscription) error {
|
||||
payloads, err := g.generateDeliveryFuturesPayload(event, channelsToSubscribe)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -228,7 +229,7 @@ func (g *Gateio) handleDeliveryFuturesSubscription(event string, channelsToSubsc
|
||||
return errs
|
||||
}
|
||||
|
||||
func (g *Gateio) generateDeliveryFuturesPayload(event string, channelsToSubscribe []stream.ChannelSubscription) ([2][]WsInput, error) {
|
||||
func (g *Gateio) generateDeliveryFuturesPayload(event string, channelsToSubscribe []subscription.Subscription) ([2][]WsInput, error) {
|
||||
if len(channelsToSubscribe) == 0 {
|
||||
return [2][]WsInput{}, errors.New("cannot generate payload, no channels supplied")
|
||||
}
|
||||
@@ -245,7 +246,7 @@ func (g *Gateio) generateDeliveryFuturesPayload(event string, channelsToSubscrib
|
||||
var auth *WsAuthInput
|
||||
timestamp := time.Now()
|
||||
var params []string
|
||||
params = []string{channelsToSubscribe[i].Currency.String()}
|
||||
params = []string{channelsToSubscribe[i].Pair.String()}
|
||||
if g.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
switch channelsToSubscribe[i].Channel {
|
||||
case futuresOrdersChannel, futuresUserTradesChannel,
|
||||
@@ -309,7 +310,7 @@ func (g *Gateio) generateDeliveryFuturesPayload(event string, channelsToSubscrib
|
||||
params = append(params, intervalString)
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(channelsToSubscribe[i].Currency.Quote.Upper().String(), "USDT") {
|
||||
if strings.HasPrefix(channelsToSubscribe[i].Pair.Quote.Upper().String(), "USDT") {
|
||||
payloads[0] = append(payloads[0], WsInput{
|
||||
ID: g.Websocket.Conn.GenerateMessageID(false),
|
||||
Event: event,
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/stream"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/subscription"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/trade"
|
||||
"github.com/thrasher-corp/gocryptotrader/log"
|
||||
@@ -121,7 +122,7 @@ func (g *Gateio) WsFuturesConnect() error {
|
||||
}
|
||||
|
||||
// GenerateFuturesDefaultSubscriptions returns default subscriptions information.
|
||||
func (g *Gateio) GenerateFuturesDefaultSubscriptions() ([]stream.ChannelSubscription, error) {
|
||||
func (g *Gateio) GenerateFuturesDefaultSubscriptions() ([]subscription.Subscription, error) {
|
||||
channelsToSubscribe := defaultFuturesSubscriptions
|
||||
if g.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
channelsToSubscribe = append(channelsToSubscribe,
|
||||
@@ -134,7 +135,7 @@ func (g *Gateio) GenerateFuturesDefaultSubscriptions() ([]stream.ChannelSubscrip
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
subscriptions := make([]stream.ChannelSubscription, len(channelsToSubscribe)*len(pairs))
|
||||
subscriptions := make([]subscription.Subscription, len(channelsToSubscribe)*len(pairs))
|
||||
count := 0
|
||||
for i := range channelsToSubscribe {
|
||||
for j := range pairs {
|
||||
@@ -153,10 +154,10 @@ func (g *Gateio) GenerateFuturesDefaultSubscriptions() ([]stream.ChannelSubscrip
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
subscriptions[count] = stream.ChannelSubscription{
|
||||
Channel: channelsToSubscribe[i],
|
||||
Currency: fpair.Upper(),
|
||||
Params: params,
|
||||
subscriptions[count] = subscription.Subscription{
|
||||
Channel: channelsToSubscribe[i],
|
||||
Pair: fpair.Upper(),
|
||||
Params: params,
|
||||
}
|
||||
count++
|
||||
}
|
||||
@@ -165,12 +166,12 @@ func (g *Gateio) GenerateFuturesDefaultSubscriptions() ([]stream.ChannelSubscrip
|
||||
}
|
||||
|
||||
// FuturesSubscribe sends a websocket message to stop receiving data from the channel
|
||||
func (g *Gateio) FuturesSubscribe(channelsToUnsubscribe []stream.ChannelSubscription) error {
|
||||
func (g *Gateio) FuturesSubscribe(channelsToUnsubscribe []subscription.Subscription) error {
|
||||
return g.handleFuturesSubscription("subscribe", channelsToUnsubscribe)
|
||||
}
|
||||
|
||||
// FuturesUnsubscribe sends a websocket message to stop receiving data from the channel
|
||||
func (g *Gateio) FuturesUnsubscribe(channelsToUnsubscribe []stream.ChannelSubscription) error {
|
||||
func (g *Gateio) FuturesUnsubscribe(channelsToUnsubscribe []subscription.Subscription) error {
|
||||
return g.handleFuturesSubscription("unsubscribe", channelsToUnsubscribe)
|
||||
}
|
||||
|
||||
@@ -269,7 +270,7 @@ func (g *Gateio) wsHandleFuturesData(respRaw []byte, assetType asset.Item) error
|
||||
}
|
||||
|
||||
// handleFuturesSubscription sends a websocket message to receive data from the channel
|
||||
func (g *Gateio) handleFuturesSubscription(event string, channelsToSubscribe []stream.ChannelSubscription) error {
|
||||
func (g *Gateio) handleFuturesSubscription(event string, channelsToSubscribe []subscription.Subscription) error {
|
||||
payloads, err := g.generateFuturesPayload(event, channelsToSubscribe)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -306,7 +307,7 @@ func (g *Gateio) handleFuturesSubscription(event string, channelsToSubscribe []s
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) generateFuturesPayload(event string, channelsToSubscribe []stream.ChannelSubscription) ([2][]WsInput, error) {
|
||||
func (g *Gateio) generateFuturesPayload(event string, channelsToSubscribe []subscription.Subscription) ([2][]WsInput, error) {
|
||||
if len(channelsToSubscribe) == 0 {
|
||||
return [2][]WsInput{}, errors.New("cannot generate payload, no channels supplied")
|
||||
}
|
||||
@@ -323,7 +324,7 @@ func (g *Gateio) generateFuturesPayload(event string, channelsToSubscribe []stre
|
||||
var auth *WsAuthInput
|
||||
timestamp := time.Now()
|
||||
var params []string
|
||||
params = []string{channelsToSubscribe[i].Currency.String()}
|
||||
params = []string{channelsToSubscribe[i].Pair.String()}
|
||||
if g.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
switch channelsToSubscribe[i].Channel {
|
||||
case futuresOrdersChannel, futuresUserTradesChannel,
|
||||
@@ -387,7 +388,7 @@ func (g *Gateio) generateFuturesPayload(event string, channelsToSubscribe []stre
|
||||
params = append(params, intervalString)
|
||||
}
|
||||
}
|
||||
if strings.HasPrefix(channelsToSubscribe[i].Currency.Quote.Upper().String(), "USDT") {
|
||||
if strings.HasPrefix(channelsToSubscribe[i].Pair.Quote.Upper().String(), "USDT") {
|
||||
payloads[0] = append(payloads[0], WsInput{
|
||||
ID: g.Websocket.Conn.GenerateMessageID(false),
|
||||
Event: event,
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/stream"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/subscription"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/trade"
|
||||
"github.com/thrasher-corp/gocryptotrader/log"
|
||||
@@ -104,7 +105,7 @@ func (g *Gateio) WsOptionsConnect() error {
|
||||
}
|
||||
|
||||
// GenerateOptionsDefaultSubscriptions generates list of channel subscriptions for options asset type.
|
||||
func (g *Gateio) GenerateOptionsDefaultSubscriptions() ([]stream.ChannelSubscription, error) {
|
||||
func (g *Gateio) GenerateOptionsDefaultSubscriptions() ([]subscription.Subscription, error) {
|
||||
channelsToSubscribe := defaultOptionsSubscriptions
|
||||
var userID int64
|
||||
if g.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
@@ -129,7 +130,7 @@ func (g *Gateio) GenerateOptionsDefaultSubscriptions() ([]stream.ChannelSubscrip
|
||||
}
|
||||
}
|
||||
getEnabledPairs:
|
||||
var subscriptions []stream.ChannelSubscription
|
||||
var subscriptions []subscription.Subscription
|
||||
pairs, err := g.GetEnabledPairs(asset.Options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -162,17 +163,17 @@ getEnabledPairs:
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
subscriptions = append(subscriptions, stream.ChannelSubscription{
|
||||
Channel: channelsToSubscribe[i],
|
||||
Currency: fpair.Upper(),
|
||||
Params: params,
|
||||
subscriptions = append(subscriptions, subscription.Subscription{
|
||||
Channel: channelsToSubscribe[i],
|
||||
Pair: fpair.Upper(),
|
||||
Params: params,
|
||||
})
|
||||
}
|
||||
}
|
||||
return subscriptions, nil
|
||||
}
|
||||
|
||||
func (g *Gateio) generateOptionsPayload(event string, channelsToSubscribe []stream.ChannelSubscription) ([]WsInput, error) {
|
||||
func (g *Gateio) generateOptionsPayload(event string, channelsToSubscribe []subscription.Subscription) ([]WsInput, error) {
|
||||
if len(channelsToSubscribe) == 0 {
|
||||
return nil, errors.New("cannot generate payload, no channels supplied")
|
||||
}
|
||||
@@ -189,7 +190,7 @@ func (g *Gateio) generateOptionsPayload(event string, channelsToSubscribe []stre
|
||||
optionsUnderlyingPriceChannel,
|
||||
optionsUnderlyingCandlesticksChannel:
|
||||
var uly currency.Pair
|
||||
uly, err = g.GetUnderlyingFromCurrencyPair(channelsToSubscribe[i].Currency)
|
||||
uly, err = g.GetUnderlyingFromCurrencyPair(channelsToSubscribe[i].Pair)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -197,8 +198,8 @@ func (g *Gateio) generateOptionsPayload(event string, channelsToSubscribe []stre
|
||||
case optionsBalancesChannel:
|
||||
// options.balance channel does not require underlying or contract
|
||||
default:
|
||||
channelsToSubscribe[i].Currency.Delimiter = currency.UnderscoreDelimiter
|
||||
params = append(params, channelsToSubscribe[i].Currency.String())
|
||||
channelsToSubscribe[i].Pair.Delimiter = currency.UnderscoreDelimiter
|
||||
params = append(params, channelsToSubscribe[i].Pair.String())
|
||||
}
|
||||
switch channelsToSubscribe[i].Channel {
|
||||
case optionsOrderbookChannel:
|
||||
@@ -298,17 +299,17 @@ func (g *Gateio) wsReadOptionsConnData() {
|
||||
}
|
||||
|
||||
// OptionsSubscribe sends a websocket message to stop receiving data for asset type options
|
||||
func (g *Gateio) OptionsSubscribe(channelsToUnsubscribe []stream.ChannelSubscription) error {
|
||||
func (g *Gateio) OptionsSubscribe(channelsToUnsubscribe []subscription.Subscription) error {
|
||||
return g.handleOptionsSubscription("subscribe", channelsToUnsubscribe)
|
||||
}
|
||||
|
||||
// OptionsUnsubscribe sends a websocket message to stop receiving data for asset type options
|
||||
func (g *Gateio) OptionsUnsubscribe(channelsToUnsubscribe []stream.ChannelSubscription) error {
|
||||
func (g *Gateio) OptionsUnsubscribe(channelsToUnsubscribe []subscription.Subscription) error {
|
||||
return g.handleOptionsSubscription("unsubscribe", channelsToUnsubscribe)
|
||||
}
|
||||
|
||||
// handleOptionsSubscription sends a websocket message to receive data from the channel
|
||||
func (g *Gateio) handleOptionsSubscription(event string, channelsToSubscribe []stream.ChannelSubscription) error {
|
||||
func (g *Gateio) handleOptionsSubscription(event string, channelsToSubscribe []subscription.Subscription) error {
|
||||
payloads, err := g.generateOptionsPayload(event, channelsToSubscribe)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
Reference in New Issue
Block a user