add websocket message parser

This commit is contained in:
c9s 2021-12-23 02:37:11 +08:00
parent 3fb2e12c24
commit cec4b3dd1e
2 changed files with 162 additions and 67 deletions

View File

@ -1,82 +1,118 @@
package kucoinapi
import "encoding/json"
import (
"encoding/json"
"github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/c9s/bbgo/pkg/types"
)
type WebSocketMessageType string
const (
WebSocketMessageTypePing WebSocketMessageType = "ping"
WebSocketMessageTypeSubscribe WebSocketMessageType = "subscribe"
WebSocketMessageTypeUnsubscribe WebSocketMessageType = "unsubscribe"
WebSocketMessageTypeAck WebSocketMessageType = "ack"
WebSocketMessageTypePong WebSocketMessageType = "pong"
WebSocketMessageTypeWelcome WebSocketMessageType = "welcome"
WebSocketMessageTypeMessage WebSocketMessageType = "message"
)
type WebSocketSubject string
const (
WebSocketSubjectTradeTicker WebSocketSubject = "trade.ticker"
WebSocketSubjectTradeSnapshot WebSocketSubject = "trade.snapshot" // ticker snapshot
WebSocketSubjectTradeL2Update WebSocketSubject = "trade.l2update" // order book L2
WebSocketSubjectLevel2 WebSocketSubject = "level2" // level2
WebSocketSubjectTradeCandlesUpdate WebSocketSubject = "trade.candles.update"
// private subjects
WebSocketSubjectOrderChange WebSocketSubject = "orderChange"
WebSocketSubjectAccountBalance WebSocketSubject = "account.balance"
WebSocketSubjectStopOrder WebSocketSubject = "stopOrder"
)
type WebSocketCommand struct {
Id int64 `json:"id"`
Type string `json:"type"`
Topic string `json:"topic"`
PrivateChannel bool `json:"privateChannel"`
Response bool `json:"response"`
Id int64 `json:"id"`
Type string `json:"type"`
Topic string `json:"topic"`
PrivateChannel bool `json:"privateChannel"`
Response bool `json:"response"`
}
func (c *WebSocketCommand) JSON() ([]byte, error) {
type tt WebSocketCommand
var a = (*tt)(c)
return json.Marshal(a)
type tt WebSocketCommand
var a = (*tt)(c)
return json.Marshal(a)
}
type WebSocketResponse struct {
Type string `json:"type"`
Topic string `json:"topic"`
Subject string `json:"subject"`
Type WebSocketMessageType `json:"type"`
Topic string `json:"topic"`
Subject WebSocketSubject `json:"subject"`
Data json.RawMessage `json:"data"`
// Object is used for storing the parsed Data
Object interface{} `json:"-"`
}
type WebSocketTicker struct {
Sequence string `json:"sequence"`
Price string `json:"price"`
Size string `json:"size"`
BestAsk string `json:"bestAsk"`
BestAskSize string `json:"bestAskSize"`
BestBid string `json:"bestBid"`
BestBidSize string `json:"bestBidSize"`
Sequence string `json:"sequence"`
Price fixedpoint.Value `json:"price"`
Size fixedpoint.Value `json:"size"`
BestAsk fixedpoint.Value `json:"bestAsk"`
BestAskSize fixedpoint.Value `json:"bestAskSize"`
BestBid fixedpoint.Value `json:"bestBid"`
BestBidSize fixedpoint.Value `json:"bestBidSize"`
}
type WebSocketOrderBook struct {
SequenceStart int64 `json:"sequenceStart"`
SequenceEnd int64 `json:"sequenceEnd"`
Symbol string `json:"symbol"`
Changes struct {
Asks [][]string `json:"asks"`
Bids [][]string `json:"bids"`
} `json:"changes"`
type WebSocketOrderBookL2 struct {
SequenceStart int64 `json:"sequenceStart"`
SequenceEnd int64 `json:"sequenceEnd"`
Symbol string `json:"symbol"`
Changes struct {
Asks [][]string `json:"asks"`
Bids [][]string `json:"bids"`
} `json:"changes"`
}
type WebSocketKLine struct {
Symbol string `json:"symbol"`
Candles []string `json:"candles"`
Time int64 `json:"time"`
Symbol string `json:"symbol"`
Candles []string `json:"candles"`
Time int64 `json:"time"`
}
type WebSocketPrivateOrder struct {
Symbol string `json:"symbol"`
OrderType string `json:"orderType"`
Side string `json:"side"`
OrderId string `json:"orderId"`
Type string `json:"type"`
OrderTime int64 `json:"orderTime"`
Size string `json:"size"`
FilledSize string `json:"filledSize"`
Price string `json:"price"`
ClientOid string `json:"clientOid"`
RemainSize string `json:"remainSize"`
Status string `json:"status"`
Ts int64 `json:"ts"`
Symbol string `json:"symbol"`
OrderType string `json:"orderType"`
Side string `json:"side"`
OrderId string `json:"orderId"`
Type string `json:"type"`
OrderTime types.MillisecondTimestamp `json:"orderTime"`
Price fixedpoint.Value `json:"price"`
Size fixedpoint.Value `json:"size"`
FilledSize fixedpoint.Value `json:"filledSize"`
RemainSize fixedpoint.Value `json:"remainSize"`
ClientOid string `json:"clientOid"`
Status string `json:"status"`
Ts types.MillisecondTimestamp `json:"ts"`
}
type WebSocketAccountBalance struct {
Total string `json:"total"`
Available string `json:"available"`
AvailableChange string `json:"availableChange"`
Currency string `json:"currency"`
Hold string `json:"hold"`
HoldChange string `json:"holdChange"`
RelationEvent string `json:"relationEvent"`
RelationEventId string `json:"relationEventId"`
RelationContext struct {
Symbol string `json:"symbol"`
TradeId string `json:"tradeId"`
OrderId string `json:"orderId"`
} `json:"relationContext"`
Time string `json:"time"`
}
Total fixedpoint.Value `json:"total"`
Available fixedpoint.Value `json:"available"`
AvailableChange fixedpoint.Value `json:"availableChange"`
Currency string `json:"currency"`
Hold fixedpoint.Value `json:"hold"`
HoldChange fixedpoint.Value `json:"holdChange"`
RelationEvent string `json:"relationEvent"`
RelationEventId string `json:"relationEventId"`
RelationContext struct {
Symbol string `json:"symbol"`
TradeId string `json:"tradeId"`
OrderId string `json:"orderId"`
} `json:"relationContext"`
Time string `json:"time"`
}

View File

@ -2,6 +2,7 @@ package kucoin
import (
"context"
"encoding/json"
"net"
"sync"
"time"
@ -235,18 +236,23 @@ func (s *Stream) read(ctx context.Context) {
continue
}
e, err := parseWebsocketPayload(string(message))
e, err := parseWebsocketPayload(message)
if err != nil {
log.WithError(err).Error("message parse error")
continue
}
if e != nil {
switch et := e.(type) {
log.Infof("event: %+v", e)
if e != nil && e.Object != nil {
switch et := e.Object.(type) {
case *kucoinapi.WebSocketTicker:
case *kucoinapi.WebSocketOrderBookL2:
case *kucoinapi.WebSocketKLine:
case *kucoinapi.WebSocketAccountBalance:
case *kucoinapi.WebSocketPrivateOrder:
/*
case *AccountEvent:
s.EmitOrderDetails(et)
*/
default:
log.Warnf("unhandled event: %+v", et)
@ -300,6 +306,59 @@ func ping(ctx context.Context, w WebSocketConnector, interval time.Duration) {
}
}
func parseWebsocketPayload(in string) (interface{}, error) {
return nil, nil
func parseWebsocketPayload(in []byte) (*kucoinapi.WebSocketResponse, error) {
var resp kucoinapi.WebSocketResponse
var err = json.Unmarshal(in, &resp)
if err != nil {
return nil, err
}
switch resp.Type {
case kucoinapi.WebSocketMessageTypeAck:
return &resp, nil
case kucoinapi.WebSocketMessageTypeMessage:
switch resp.Subject {
case kucoinapi.WebSocketSubjectOrderChange:
var o kucoinapi.WebSocketPrivateOrder
if err := json.Unmarshal(resp.Data, &o) ; err != nil {
return &resp, err
}
resp.Object = &o
case kucoinapi.WebSocketSubjectAccountBalance:
var o kucoinapi.WebSocketAccountBalance
if err := json.Unmarshal(resp.Data, &o) ; err != nil {
return &resp, err
}
resp.Object = &o
case kucoinapi.WebSocketSubjectTradeCandlesUpdate:
var o kucoinapi.WebSocketKLine
if err := json.Unmarshal(resp.Data, &o) ; err != nil {
return &resp, err
}
resp.Object = &o
case kucoinapi.WebSocketSubjectTradeL2Update:
var o kucoinapi.WebSocketOrderBookL2
if err := json.Unmarshal(resp.Data, &o) ; err != nil {
return &resp, err
}
resp.Object = &o
case kucoinapi.WebSocketSubjectTradeTicker:
var o kucoinapi.WebSocketTicker
if err := json.Unmarshal(resp.Data, &o) ; err != nil {
return &resp, err
}
resp.Object = &o
default:
// return nil, fmt.Errorf("kucoin: unsupported subject: %s", resp.Subject)
}
}
return &resp, nil
}