mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-25 16:25:16 +00:00
kucoin: implement NewStream
This commit is contained in:
parent
0a9575aaca
commit
730ce31e67
|
@ -1,8 +1,10 @@
|
||||||
package kucoin
|
package kucoin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/c9s/bbgo/pkg/exchange/kucoin/kucoinapi"
|
"github.com/c9s/bbgo/pkg/exchange/kucoin/kucoinapi"
|
||||||
"github.com/c9s/bbgo/pkg/types"
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
|
@ -64,6 +66,36 @@ func toGlobalTicker(s kucoinapi.Ticker24H) types.Ticker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertSubscription(s types.Subscription) (WebsocketSubscription, error) {
|
|
||||||
return WebsocketSubscription{}, nil
|
// convertSubscriptions global subscription to local websocket command
|
||||||
|
func convertSubscriptions(ss []types.Subscription) ([]kucoinapi.WebSocketCommand, error) {
|
||||||
|
var id = time.Now().UnixMilli()
|
||||||
|
var cmds []kucoinapi.WebSocketCommand
|
||||||
|
for _, s := range ss {
|
||||||
|
id++
|
||||||
|
|
||||||
|
var subscribeType string
|
||||||
|
switch s.Channel {
|
||||||
|
case types.BookChannel:
|
||||||
|
// see https://docs.kucoin.com/#level-2-market-data
|
||||||
|
subscribeType = "/market/level2" + ":" + toLocalSymbol(s.Symbol)
|
||||||
|
|
||||||
|
case types.KLineChannel:
|
||||||
|
subscribeType = "/market/candles" + ":" + toLocalSymbol(s.Symbol) + "_" + s.Options.Interval
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("websocket channel %s is not supported by kucoin", s.Channel)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmds = append(cmds, kucoinapi.WebSocketCommand{
|
||||||
|
Id: id,
|
||||||
|
Type: subscribeType,
|
||||||
|
Topic: "subscribe",
|
||||||
|
PrivateChannel: false,
|
||||||
|
Response: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmds, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -138,5 +138,5 @@ func (e *Exchange) CancelOrders(ctx context.Context, orders ...types.Order) erro
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Exchange) NewStream() types.Stream {
|
func (e *Exchange) NewStream() types.Stream {
|
||||||
panic("implement me")
|
return NewStream(e.client)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/c9s/bbgo/pkg/exchange/kucoin/kucoinapi"
|
"github.com/c9s/bbgo/pkg/exchange/kucoin/kucoinapi"
|
||||||
"github.com/c9s/bbgo/pkg/types"
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
const readTimeout = 15 * time.Second
|
const readTimeout = 15 * time.Second
|
||||||
|
@ -40,8 +41,6 @@ type Stream struct {
|
||||||
publicOnly bool
|
publicOnly bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type WebsocketSubscription struct{}
|
|
||||||
|
|
||||||
func NewStream(client *kucoinapi.RestClient) *Stream {
|
func NewStream(client *kucoinapi.RestClient) *Stream {
|
||||||
stream := &Stream{
|
stream := &Stream{
|
||||||
client: client,
|
client: client,
|
||||||
|
@ -50,63 +49,34 @@ func NewStream(client *kucoinapi.RestClient) *Stream {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.OnConnect(func() {
|
stream.OnConnect(stream.handleConnect)
|
||||||
if stream.publicOnly {
|
|
||||||
var subs []WebsocketSubscription
|
|
||||||
for _, subscription := range stream.Subscriptions {
|
|
||||||
sub, err := convertSubscription(subscription)
|
|
||||||
if err != nil {
|
|
||||||
log.WithError(err).Errorf("subscription convert error")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
subs = append(subs, sub)
|
|
||||||
}
|
|
||||||
if len(subs) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof("subscribing channels: %+v", subs)
|
|
||||||
err := stream.conn.WriteJSON(WebsocketOp{
|
|
||||||
Op: "subscribe",
|
|
||||||
Args: subs,
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.WithError(err).Error("subscribe error")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// login as private channel
|
|
||||||
// sign example:
|
|
||||||
// sign=CryptoJS.enc.Base64.Stringify(CryptoJS.HmacSHA256(timestamp +'GET'+'/users/self/verify', secretKey))
|
|
||||||
/*
|
|
||||||
msTimestamp := strconv.FormatFloat(float64(time.Now().UnixNano())/float64(time.Second), 'f', -1, 64)
|
|
||||||
payload := msTimestamp + "GET" + "/users/self/verify"
|
|
||||||
sign := okexapi.Sign(payload, stream.client.Secret)
|
|
||||||
op := WebsocketOp{
|
|
||||||
Op: "login",
|
|
||||||
Args: []WebsocketLogin{
|
|
||||||
{
|
|
||||||
Key: stream.client.Key,
|
|
||||||
Passphrase: stream.client.Passphrase,
|
|
||||||
Timestamp: msTimestamp,
|
|
||||||
Sign: sign,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof("sending login request: %+v", op)
|
|
||||||
err := stream.conn.WriteJSON(op)
|
|
||||||
if err != nil {
|
|
||||||
log.WithError(err).Errorf("can not send login message")
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return stream
|
return stream
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Stream) sendSubscriptions() error {
|
||||||
|
cmds, err := convertSubscriptions(s.Subscriptions)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "subscription convert error, subscriptions: %+v", s.Subscriptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, cmd := range cmds {
|
||||||
|
if err := s.conn.WriteJSON(cmd) ; err != nil {
|
||||||
|
return errors.Wrapf(err, "subscribe write error, cmd: %+v", cmd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Stream) handleConnect() {
|
||||||
|
if s.publicOnly {
|
||||||
|
if err := s.sendSubscriptions() ; err != nil {
|
||||||
|
log.WithError(err).Errorf("subscription error")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Stream) SetPublicOnly() {
|
func (s *Stream) SetPublicOnly() {
|
||||||
s.publicOnly = true
|
s.publicOnly = true
|
||||||
}
|
}
|
||||||
|
@ -225,9 +195,7 @@ func (s *Stream) read(ctx context.Context) {
|
||||||
return
|
return
|
||||||
|
|
||||||
default:
|
default:
|
||||||
s.connLock.Lock()
|
conn := s.Conn()
|
||||||
conn := s.conn
|
|
||||||
s.connLock.Unlock()
|
|
||||||
|
|
||||||
if err := conn.SetReadDeadline(time.Now().Add(readTimeout)); err != nil {
|
if err := conn.SetReadDeadline(time.Now().Add(readTimeout)); err != nil {
|
||||||
log.WithError(err).Errorf("set read deadline error: %s", err.Error())
|
log.WithError(err).Errorf("set read deadline error: %s", err.Error())
|
||||||
|
|
Loading…
Reference in New Issue
Block a user