Skip to content

Commit

Permalink
add V5 WS Liquidation (#143)
Browse files Browse the repository at this point in the history
* add V5 WS Liquidation

* update README.md

* add var Intervals

* milliseconds -> int64

* milliseconds -> int64 add

* milliseconds -> int64 add
  • Loading branch information
mmavka authored Oct 28, 2023
1 parent 3edfd58 commit ceddd98
Show file tree
Hide file tree
Showing 10 changed files with 253 additions and 28 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ The following API endpoints have been implemented
- [Kline](https://bybit-exchange.github.io/docs/v5/websocket/public/kline)
- [Ticker](https://bybit-exchange.github.io/docs/v5/websocket/public/ticker)
- [Trade](https://bybit-exchange.github.io/docs/v5/websocket/public/trade)
- [Liquidation](https://bybit-exchange.github.io/docs/v5/websocket/public/liquidation)

#### Private Topics V5

Expand Down
12 changes: 6 additions & 6 deletions derivative_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,8 @@ type DerivativesKlineParam struct {
Symbol SymbolDerivative `url:"symbol"`
Category CategoryDerivative `url:"category"`
Interval Interval `url:"interval"`
Start int `url:"start"` // timestamp point for result, in milliseconds
End int `url:"end"` // timestamp point for result, in milliseconds
Start int64 `url:"start"` // timestamp point for result, in milliseconds
End int64 `url:"end"` // timestamp point for result, in milliseconds

Limit *int `url:"limit,omitempty"`
}
Expand Down Expand Up @@ -479,8 +479,8 @@ type DerivativesMarkPriceKlineParam struct {
Category CategoryDerivative `url:"category"`
Symbol SymbolDerivative `url:"symbol"`
Interval Interval `url:"interval"`
Start int `url:"start"` // timestamp point for result, in milliseconds
End int `url:"end"` // timestamp point for result, in milliseconds
Start int64 `url:"start"` // timestamp point for result, in milliseconds
End int64 `url:"end"` // timestamp point for result, in milliseconds

Limit *int `url:"limit,omitempty"`
}
Expand Down Expand Up @@ -547,8 +547,8 @@ type DerivativesIndexPriceKlineParam struct {
Category CategoryDerivative `url:"category"`
Symbol SymbolDerivative `url:"symbol"`
Interval Interval `url:"interval"`
Start int `url:"start"` // timestamp point for result, in milliseconds
End int `url:"end"` // timestamp point for result, in milliseconds
Start int64 `url:"start"` // timestamp point for result, in milliseconds
End int64 `url:"end"` // timestamp point for result, in milliseconds

Limit *int `url:"limit,omitempty"`
}
Expand Down
16 changes: 16 additions & 0 deletions enum.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,22 @@ const (
// Interval :
type Interval string

var Intervals = []Interval{
Interval1,
Interval3,
Interval5,
Interval15,
Interval30,
Interval60,
Interval120,
Interval240,
Interval360,
Interval720,
IntervalD,
IntervalW,
IntervalM,
}

const (
// Interval1 :
Interval1 = Interval("1")
Expand Down
10 changes: 9 additions & 1 deletion response.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func checkV5ResponseBody(body []byte) error {

switch {
case commonResponse.RetCode == 10006, commonResponse.RetCode == 10018:
rateLimitError := &RateLimitError{}
rateLimitError := &RateLimitV5Error{}
if err := json.Unmarshal(body, rateLimitError); err != nil {
return err
}
Expand Down Expand Up @@ -121,6 +121,14 @@ func (r *RateLimitError) Error() string {
return fmt.Sprintf("%s, %s", r.RetMsg, time.Until(time.Unix(int64(r.RateLimitResetMs/1000), 0)))
}

type RateLimitV5Error struct {
*CommonV5Response `json:",inline"`
}

func (r *RateLimitV5Error) Error() string {
return fmt.Sprintf(r.RetMsg)
}

var (
// ErrPathNotFound : Request path not found
ErrPathNotFound = errors.New("path not found")
Expand Down
13 changes: 7 additions & 6 deletions v5_client_web_socket_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@ func (s *V5WebsocketService) Public(category CategoryV5) (V5WebsocketPublicServi
return nil, err
}
return &V5WebsocketPublicService{
client: s.client,
connection: c,
paramOrderBookMap: make(map[V5WebsocketPublicOrderBookParamKey]func(V5WebsocketPublicOrderBookResponse) error),
paramKlineMap: make(map[V5WebsocketPublicKlineParamKey]func(V5WebsocketPublicKlineResponse) error),
paramTickerMap: make(map[V5WebsocketPublicTickerParamKey]func(V5WebsocketPublicTickerResponse) error),
paramTradeMap: make(map[V5WebsocketPublicTradeParamKey]func(V5WebsocketPublicTradeResponse) error),
client: s.client,
connection: c,
paramOrderBookMap: make(map[V5WebsocketPublicOrderBookParamKey]func(V5WebsocketPublicOrderBookResponse) error),
paramKlineMap: make(map[V5WebsocketPublicKlineParamKey]func(V5WebsocketPublicKlineResponse) error),
paramTickerMap: make(map[V5WebsocketPublicTickerParamKey]func(V5WebsocketPublicTickerResponse) error),
paramTradeMap: make(map[V5WebsocketPublicTradeParamKey]func(V5WebsocketPublicTradeResponse) error),
paramLiquidationMap: make(map[V5WebsocketPublicLiquidationParamKey]func(V5WebsocketPublicLiquidationResponse) error),
}, nil
}

Expand Down
16 changes: 8 additions & 8 deletions v5_market_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ type V5GetKlineParam struct {
Category CategoryV5 `url:"category"`
Symbol SymbolV5 `url:"symbol"`
Interval Interval `url:"interval"`
Start *int `url:"start,omitempty"` // timestamp point for result, in milliseconds
End *int `url:"end,omitempty"` // timestamp point for result, in milliseconds
Start *int64 `url:"start,omitempty"` // timestamp point for result, in milliseconds
End *int64 `url:"end,omitempty"` // timestamp point for result, in milliseconds

Limit *int `url:"limit,omitempty"` // Limit for data size per page. [1, 200]. Default: 200
}
Expand Down Expand Up @@ -113,8 +113,8 @@ type V5GetMarkPriceKlineParam struct {
Category CategoryV5 `url:"category"`
Symbol SymbolV5 `url:"symbol"`
Interval Interval `url:"interval"`
Start *int `url:"start,omitempty"` // timestamp point for result, in milliseconds
End *int `url:"end,omitempty"` // timestamp point for result, in milliseconds
Start *int64 `url:"start,omitempty"` // timestamp point for result, in milliseconds
End *int64 `url:"end,omitempty"` // timestamp point for result, in milliseconds
Limit *int `url:"limit,omitempty"` // Limit for data size per page. [1, 200]. Default: 200
}

Expand Down Expand Up @@ -189,8 +189,8 @@ type V5GetIndexPriceKlineParam struct {
Category CategoryV5 `url:"category"`
Symbol SymbolV5 `url:"symbol"`
Interval Interval `url:"interval"`
Start *int `url:"start,omitempty"` // timestamp point for result, in milliseconds
End *int `url:"end,omitempty"` // timestamp point for result, in milliseconds
Start *int64 `url:"start,omitempty"` // timestamp point for result, in milliseconds
End *int64 `url:"end,omitempty"` // timestamp point for result, in milliseconds
Limit *int `url:"limit,omitempty"` // Limit for data size per page. [1, 200]. Default: 200
}

Expand Down Expand Up @@ -265,8 +265,8 @@ type V5GetPremiumIndexPriceKlineParam struct {
Category CategoryV5 `url:"category"`
Symbol SymbolV5 `url:"symbol"`
Interval Interval `url:"interval"`
Start *int `url:"start,omitempty"` // timestamp point for result, in milliseconds
End *int `url:"end,omitempty"` // timestamp point for result, in milliseconds
Start *int64 `url:"start,omitempty"` // timestamp point for result, in milliseconds
End *int64 `url:"end,omitempty"` // timestamp point for result, in milliseconds
Limit *int `url:"limit,omitempty"` // Limit for data size per page. [1, 200]. Default: 200
}

Expand Down
33 changes: 29 additions & 4 deletions v5_ws_public.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ type V5WebsocketPublicServiceI interface {
V5WebsocketPublicTradeParamKey,
func(V5WebsocketPublicTradeResponse) error,
) (func() error, error)

SubscribeLiquidation(
V5WebsocketPublicLiquidationParamKey,
func(V5WebsocketPublicLiquidationResponse) error,
) (func() error, error)
}

// V5WebsocketPublicService :
Expand All @@ -49,10 +54,11 @@ type V5WebsocketPublicService struct {

mu sync.Mutex

paramOrderBookMap map[V5WebsocketPublicOrderBookParamKey]func(V5WebsocketPublicOrderBookResponse) error
paramKlineMap map[V5WebsocketPublicKlineParamKey]func(V5WebsocketPublicKlineResponse) error
paramTickerMap map[V5WebsocketPublicTickerParamKey]func(V5WebsocketPublicTickerResponse) error
paramTradeMap map[V5WebsocketPublicTradeParamKey]func(V5WebsocketPublicTradeResponse) error
paramOrderBookMap map[V5WebsocketPublicOrderBookParamKey]func(V5WebsocketPublicOrderBookResponse) error
paramKlineMap map[V5WebsocketPublicKlineParamKey]func(V5WebsocketPublicKlineResponse) error
paramTickerMap map[V5WebsocketPublicTickerParamKey]func(V5WebsocketPublicTickerResponse) error
paramTradeMap map[V5WebsocketPublicTradeParamKey]func(V5WebsocketPublicTradeResponse) error
paramLiquidationMap map[V5WebsocketPublicLiquidationParamKey]func(V5WebsocketPublicLiquidationResponse) error
}

const (
Expand Down Expand Up @@ -80,6 +86,9 @@ const (

// V5WebsocketPublicTopicTrade :
V5WebsocketPublicTopicTrade = V5WebsocketPublicTopic("publicTrade")

// V5WebsocketPublicTopicLiquidation :
V5WebsocketPublicTopicLiquidation = V5WebsocketPublicTopic("liquidation")
)

func (t V5WebsocketPublicTopic) String() string {
Expand All @@ -102,6 +111,8 @@ func (s *V5WebsocketPublicService) judgeTopic(respBody []byte) (V5WebsocketPubli
return V5WebsocketPublicTopicTicker, nil
case strings.Contains(topic, V5WebsocketPublicTopicTrade.String()):
return V5WebsocketPublicTopicTrade, nil
case strings.Contains(topic, V5WebsocketPublicTopicLiquidation.String()):
return V5WebsocketPublicTopicLiquidation, nil
}
}
return "", nil
Expand Down Expand Up @@ -251,6 +262,20 @@ func (s *V5WebsocketPublicService) Run() error {
return err
}

if err := f(resp); err != nil {
return err
}
case V5WebsocketPublicTopicLiquidation:
var resp V5WebsocketPublicLiquidationResponse
if err := s.parseResponse(message, &resp); err != nil {
return err
}

f, err := s.retrieveLiquidationFunc(resp.Key())
if err != nil {
return err
}

if err := f(resp); err != nil {
return err
}
Expand Down
6 changes: 3 additions & 3 deletions v5_ws_public_kline.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ type V5WebsocketPublicKlineResponse struct {

// V5WebsocketPublicKlineData :
type V5WebsocketPublicKlineData struct {
Start int `json:"start"`
End int `json:"end"`
Start int64 `json:"start"`
End int64 `json:"end"`
Interval Interval `json:"interval"`
Open string `json:"open"`
Close string `json:"close"`
Expand All @@ -82,7 +82,7 @@ type V5WebsocketPublicKlineData struct {
Volume string `json:"volume"`
Turnover string `json:"turnover"`
Confirm bool `json:"confirm"`
Timestamp int `json:"timestamp"`
Timestamp int64 `json:"timestamp"`
}

// Key :
Expand Down
115 changes: 115 additions & 0 deletions v5_ws_public_liquidation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package bybit

import (
"encoding/json"
"errors"
"fmt"
"strings"

"github.com/gorilla/websocket"
)

// SubscribeLiquidation :
func (s *V5WebsocketPublicService) SubscribeLiquidation(
key V5WebsocketPublicLiquidationParamKey,
f func(V5WebsocketPublicLiquidationResponse) error,
) (func() error, error) {
if err := s.addParamLiquidationFunc(key, f); err != nil {
return nil, err
}
param := struct {
Op string `json:"op"`
Args []interface{} `json:"args"`
}{
Op: "subscribe",
Args: []interface{}{key.Topic()},
}
buf, err := json.Marshal(param)
if err != nil {
return nil, err
}
if err := s.writeMessage(websocket.TextMessage, buf); err != nil {
return nil, err
}
return func() error {
param := struct {
Op string `json:"op"`
Args []interface{} `json:"args"`
}{
Op: "unsubscribe",
Args: []interface{}{key.Topic()},
}
buf, err := json.Marshal(param)
if err != nil {
return err
}
if err := s.writeMessage(websocket.TextMessage, []byte(buf)); err != nil {
return err
}
s.removeParamLiquidationFunc(key)
return nil
}, nil
}

// V5WebsocketPublicLiquidationParamKey :
type V5WebsocketPublicLiquidationParamKey struct {
Symbol SymbolV5
}

// Topic :
func (k *V5WebsocketPublicLiquidationParamKey) Topic() string {
return fmt.Sprintf("%s.%s", V5WebsocketPublicTopicLiquidation, k.Symbol)
}

// V5WebsocketPublicLiquidationResponse :
type V5WebsocketPublicLiquidationResponse struct {
Topic string `json:"topic"`
Type string `json:"type"`
TimeStamp int64 `json:"ts"`
Data []V5WebsocketPublicLiquidationData `json:"data"`
}

// V5WebsocketPublicLiquidationData :
type V5WebsocketPublicLiquidationData struct {
UpdatedTime uint64 `json:"updatedTime"` // The updated timestamp (ms)
Symbol SymbolV5 `json:"symbol"` // Symbol name
Side Side `json:"side"` // Position side. Buy,Sell. When you receive a Buy update, this means that a long position has been liquidated
Size string `json:"size"` // Executed size
Price string `json:"price"` // Bankruptcy price
}

// Key :
func (r *V5WebsocketPublicLiquidationResponse) Key() V5WebsocketPublicLiquidationParamKey {
topic := r.Topic
arr := strings.Split(topic, ".")
if arr[0] != V5WebsocketPublicTopicLiquidation.String() || len(arr) != 2 {
return V5WebsocketPublicLiquidationParamKey{}
}

return V5WebsocketPublicLiquidationParamKey{
Symbol: SymbolV5(arr[1]),
}
}

// addParamLiquidationFunc :
func (s *V5WebsocketPublicService) addParamLiquidationFunc(key V5WebsocketPublicLiquidationParamKey, f func(V5WebsocketPublicLiquidationResponse) error) error {
if _, exist := s.paramLiquidationMap[key]; exist {
return errors.New("already registered for this key")
}
s.paramLiquidationMap[key] = f
return nil
}

// removeParamLiquidationFunc :
func (s *V5WebsocketPublicService) removeParamLiquidationFunc(key V5WebsocketPublicLiquidationParamKey) {
delete(s.paramLiquidationMap, key)
}

// retrievePositionFunc :
func (s *V5WebsocketPublicService) retrieveLiquidationFunc(key V5WebsocketPublicLiquidationParamKey) (func(V5WebsocketPublicLiquidationResponse) error, error) {
f, exist := s.paramLiquidationMap[key]
if !exist {
return nil, errors.New("func not found")
}
return f, nil
}
Loading

0 comments on commit ceddd98

Please sign in to comment.