mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-23 07:26:47 +00:00
gateio: websocket updates (#1282)
* gateio: websocket updates * Update exchanges/gateio/gateio_websocket.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * glorious: nits * revert that trick * glorious:nits * Update exchanges/gateio/gateio_ws_futures.go Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io> * Update exchanges/gateio/gateio_ws_futures.go Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io> * Update exchanges/gateio/gateio_websocket.go Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io> * Update exchanges/gateio/gateio_websocket.go Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io> * Update exchanges/gateio/gateio_ws_option.go Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io> * Update exchanges/gateio/gateio_ws_option.go Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io> * Update exchanges/gateio/gateio_websocket.go Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io> * Update exchanges/gateio/gateio_websocket.go Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io> * thrasher-nits * Update exchanges/gateio/gateio_ws_futures.go Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io> * Update exchanges/gateio/gateio_ws_futures.go Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io> * thrasher: nits rides again chapter 2 volume 1 * rm unmarshaljson method for orderbook * use gateio time where it can and update tests * math.trunc and lower time frame on big books * :eagle --------- Co-authored-by: Ryan O'Hara-Reid <ryan.oharareid@thrasher.io> Co-authored-by: Scott <gloriousCode@users.noreply.github.com> Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io>
This commit is contained in:
@@ -45,13 +45,8 @@ func (p *Pair) UnmarshalJSON(d []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
newPair, err := NewPairFromString(pair)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*p = newPair
|
||||
return nil
|
||||
*p, err = NewPairFromString(pair)
|
||||
return err
|
||||
}
|
||||
|
||||
// MarshalJSON conforms type to the marshaler interface
|
||||
|
||||
@@ -669,7 +669,7 @@ func (b *Bithumb) WithdrawFiatFunds(ctx context.Context, withdrawRequest *withdr
|
||||
if err := withdrawRequest.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if math.Mod(withdrawRequest.Amount, 1) != 0 {
|
||||
if math.Trunc(withdrawRequest.Amount) != withdrawRequest.Amount {
|
||||
return nil, errors.New("currency KRW does not support decimal places")
|
||||
}
|
||||
if !withdrawRequest.Currency.Equal(currency.KRW) {
|
||||
|
||||
@@ -728,7 +728,7 @@ func (b *Bitmex) SubmitOrder(ctx context.Context, s *order.Submit) (*order.Submi
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if math.Mod(s.Amount, 1) != 0 {
|
||||
if math.Trunc(s.Amount) != s.Amount {
|
||||
return nil,
|
||||
errors.New("order contract amount can not have decimals")
|
||||
}
|
||||
@@ -763,7 +763,7 @@ func (b *Bitmex) ModifyOrder(ctx context.Context, action *order.Modify) (*order.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if math.Mod(action.Amount, 1) != 0 {
|
||||
if math.Trunc(action.Amount) != action.Amount {
|
||||
return nil, errors.New("contract amount can not have decimals")
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package gateio
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
@@ -19,11 +20,11 @@ func (a *gateioTime) UnmarshalJSON(data []byte) error {
|
||||
var standard int64
|
||||
switch val := value.(type) {
|
||||
case float64:
|
||||
standard = int64(val)
|
||||
case int64:
|
||||
standard = val
|
||||
case int32:
|
||||
standard = int64(val)
|
||||
if math.Trunc(val) != val {
|
||||
standard = int64(val * 1e3) // Account for 1684981731.098
|
||||
} else {
|
||||
standard = int64(val)
|
||||
}
|
||||
case string:
|
||||
if val == "" {
|
||||
return nil
|
||||
@@ -32,6 +33,10 @@ func (a *gateioTime) UnmarshalJSON(data []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if math.Trunc(parsedValue) != parsedValue {
|
||||
*a = gateioTime(time.UnixMicro(int64(parsedValue * 1e3))) // Account for "1691122380942.173000" microseconds
|
||||
return nil
|
||||
}
|
||||
standard = int64(parsedValue)
|
||||
default:
|
||||
return fmt.Errorf("cannot unmarshal %T into gateioTime", val)
|
||||
@@ -45,7 +50,7 @@ func (a *gateioTime) UnmarshalJSON(data []byte) error {
|
||||
}
|
||||
|
||||
// Time represents a time instance.
|
||||
func (a *gateioTime) Time() time.Time { return time.Time(*a) }
|
||||
func (a gateioTime) Time() time.Time { return time.Time(a) }
|
||||
|
||||
type gateioNumericalValue float64
|
||||
|
||||
@@ -75,59 +80,4 @@ func (a *gateioNumericalValue) UnmarshalJSON(data []byte) error {
|
||||
}
|
||||
|
||||
// Float64 returns float64 value from gateioNumericalValue instance.
|
||||
func (a *gateioNumericalValue) Float64() float64 { return float64(*a) }
|
||||
|
||||
// UnmarshalJSON to deserialize timestamp information and create OrderbookItem instance from the list of asks and bids data.
|
||||
func (a *Orderbook) UnmarshalJSON(data []byte) error {
|
||||
type Alias Orderbook
|
||||
type askorbid struct {
|
||||
Price gateioNumericalValue `json:"p"`
|
||||
Size float64 `json:"s"`
|
||||
}
|
||||
chil := &struct {
|
||||
*Alias
|
||||
Current float64 `json:"current"`
|
||||
Update float64 `json:"update"`
|
||||
Asks []askorbid `json:"asks"`
|
||||
Bids []askorbid `json:"bids"`
|
||||
}{
|
||||
Alias: (*Alias)(a),
|
||||
}
|
||||
err := json.Unmarshal(data, &chil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.Current = time.UnixMilli(int64(chil.Current * 1000))
|
||||
a.Update = time.UnixMilli(int64(chil.Update * 1000))
|
||||
a.Asks = make([]OrderbookItem, len(chil.Asks))
|
||||
a.Bids = make([]OrderbookItem, len(chil.Bids))
|
||||
for x := range chil.Asks {
|
||||
a.Asks[x] = OrderbookItem{
|
||||
Amount: chil.Asks[x].Size,
|
||||
Price: chil.Asks[x].Price.Float64(),
|
||||
}
|
||||
}
|
||||
for x := range chil.Bids {
|
||||
a.Bids[x] = OrderbookItem{
|
||||
Amount: chil.Bids[x].Size,
|
||||
Price: chil.Bids[x].Price.Float64(),
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON deserialises the JSON info, including the timestamp
|
||||
func (a *WsUserPersonalTrade) UnmarshalJSON(data []byte) error {
|
||||
type Alias WsUserPersonalTrade
|
||||
chil := &struct {
|
||||
*Alias
|
||||
CreateTimeMicroS float64 `json:"create_time_ms,string"`
|
||||
}{
|
||||
Alias: (*Alias)(a),
|
||||
}
|
||||
if err := json.Unmarshal(data, chil); err != nil {
|
||||
return err
|
||||
}
|
||||
a.CreateTimeMicroS = time.UnixMicro(int64(chil.CreateTimeMicroS * 1000))
|
||||
return nil
|
||||
}
|
||||
func (a gateioNumericalValue) Float64() float64 { return float64(a) }
|
||||
|
||||
@@ -3206,9 +3206,9 @@ func TestSettlement(t *testing.T) {
|
||||
func TestParseGateioMilliSecTimeUnmarshal(t *testing.T) {
|
||||
t.Parallel()
|
||||
var timeWhenTesting int64 = 1684981731098
|
||||
timeWhenTestingString := "1684981731098"
|
||||
timeWhenTestingString := `"1684981731098"` // Normal string
|
||||
integerJSON := `{"number": 1684981731098}`
|
||||
float64JSON := `{"number": 1684981731098.234}`
|
||||
float64JSON := `{"number": 1684981731.098}`
|
||||
|
||||
time := time.UnixMilli(timeWhenTesting)
|
||||
var in gateioTime
|
||||
@@ -3245,18 +3245,19 @@ func TestParseGateioMilliSecTimeUnmarshal(t *testing.T) {
|
||||
func TestParseGateioTimeUnmarshal(t *testing.T) {
|
||||
t.Parallel()
|
||||
var timeWhenTesting int64 = 1684981731
|
||||
timeWhenTestingString := "1684981731"
|
||||
timeWhenTestingString := `"1684981731"`
|
||||
integerJSON := `{"number": 1684981731}`
|
||||
float64JSON := `{"number": 1684981731.234}`
|
||||
timeWhenTestingStringMicroSecond := `"1691122380942.173000"`
|
||||
|
||||
time := time.Unix(timeWhenTesting, 0)
|
||||
whenTime := time.Unix(timeWhenTesting, 0)
|
||||
var in gateioTime
|
||||
err := json.Unmarshal([]byte(timeWhenTestingString), &in)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !in.Time().Equal(time) {
|
||||
t.Fatalf("found %v, but expected %v", in.Time(), time)
|
||||
if !in.Time().Equal(whenTime) {
|
||||
t.Fatalf("found %v, but expected %v", in.Time(), whenTime)
|
||||
}
|
||||
inInteger := struct {
|
||||
Number gateioTime `json:"number"`
|
||||
@@ -3265,8 +3266,8 @@ func TestParseGateioTimeUnmarshal(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !inInteger.Number.Time().Equal(time) {
|
||||
t.Fatalf("found %v, but expected %v", inInteger.Number.Time(), time)
|
||||
if !inInteger.Number.Time().Equal(whenTime) {
|
||||
t.Fatalf("found %v, but expected %v", inInteger.Number.Time(), whenTime)
|
||||
}
|
||||
|
||||
inFloat64 := struct {
|
||||
@@ -3276,8 +3277,18 @@ func TestParseGateioTimeUnmarshal(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !inFloat64.Number.Time().Equal(time) {
|
||||
t.Fatalf("found %v, but expected %v", inFloat64.Number.Time(), time)
|
||||
msTime := time.UnixMilli(1684981731234)
|
||||
if !inFloat64.Number.Time().Equal(time.UnixMilli(1684981731234)) {
|
||||
t.Fatalf("found %v, but expected %v", inFloat64.Number.Time(), msTime)
|
||||
}
|
||||
|
||||
var microSeconds gateioTime
|
||||
err = json.Unmarshal([]byte(timeWhenTestingStringMicroSecond), µSeconds)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !microSeconds.Time().Equal(time.UnixMicro(1691122380942173)) {
|
||||
t.Fatalf("found %v, but expected %v", microSeconds.Time(), time.UnixMicro(1691122380942173))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package gateio
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
@@ -535,8 +536,8 @@ type OrderbookData struct {
|
||||
func (a *OrderbookData) MakeOrderbook() (*Orderbook, error) {
|
||||
ob := &Orderbook{
|
||||
ID: a.ID,
|
||||
Current: a.Current.Time(),
|
||||
Update: a.Update.Time(),
|
||||
Current: a.Current,
|
||||
Update: a.Update,
|
||||
}
|
||||
ob.Asks = make([]OrderbookItem, len(a.Asks))
|
||||
ob.Bids = make([]OrderbookItem, len(a.Bids))
|
||||
@@ -550,7 +551,7 @@ func (a *OrderbookData) MakeOrderbook() (*Orderbook, error) {
|
||||
return nil, err
|
||||
}
|
||||
ob.Asks[x] = OrderbookItem{
|
||||
Price: price,
|
||||
Price: gateioNumericalValue(price),
|
||||
Amount: amount,
|
||||
}
|
||||
}
|
||||
@@ -564,7 +565,7 @@ func (a *OrderbookData) MakeOrderbook() (*Orderbook, error) {
|
||||
return nil, err
|
||||
}
|
||||
ob.Bids[x] = OrderbookItem{
|
||||
Price: price,
|
||||
Price: gateioNumericalValue(price),
|
||||
Amount: amount,
|
||||
}
|
||||
}
|
||||
@@ -573,15 +574,15 @@ func (a *OrderbookData) MakeOrderbook() (*Orderbook, error) {
|
||||
|
||||
// OrderbookItem stores an orderbook item
|
||||
type OrderbookItem struct {
|
||||
Price float64 `json:"p"`
|
||||
Amount float64 `json:"s"`
|
||||
Price gateioNumericalValue `json:"p"`
|
||||
Amount float64 `json:"s"`
|
||||
}
|
||||
|
||||
// Orderbook stores the orderbook data
|
||||
type Orderbook struct {
|
||||
ID int64 `json:"id"`
|
||||
Current time.Time `json:"current"` // The timestamp of the response data being generated (in milliseconds)
|
||||
Update time.Time `json:"update"` // The timestamp of when the orderbook last changed (in milliseconds)
|
||||
Current gateioTime `json:"current"` // The timestamp of the response data being generated (in milliseconds)
|
||||
Update gateioTime `json:"update"` // The timestamp of when the orderbook last changed (in milliseconds)
|
||||
Bids []OrderbookItem `json:"bids"`
|
||||
Asks []OrderbookItem `json:"asks"`
|
||||
}
|
||||
@@ -904,20 +905,20 @@ type SwapCurrencies struct {
|
||||
|
||||
// MyOptionSettlement represents option private settlement
|
||||
type MyOptionSettlement struct {
|
||||
Size float64 `json:"size"`
|
||||
SettleProfit float64 `json:"settle_profit,string"`
|
||||
Contract string `json:"contract"`
|
||||
StrikePrice float64 `json:"strike_price,string"`
|
||||
Time time.Time `json:"time"`
|
||||
SettlePrice float64 `json:"settle_price,string"`
|
||||
Underlying string `json:"underlying"`
|
||||
RealisedPnl string `json:"realised_pnl"`
|
||||
Fee float64 `json:"fee,string"`
|
||||
Size float64 `json:"size"`
|
||||
SettleProfit float64 `json:"settle_profit,string"`
|
||||
Contract string `json:"contract"`
|
||||
StrikePrice float64 `json:"strike_price,string"`
|
||||
Time gateioTime `json:"time"`
|
||||
SettlePrice float64 `json:"settle_price,string"`
|
||||
Underlying string `json:"underlying"`
|
||||
RealisedPnl string `json:"realised_pnl"`
|
||||
Fee float64 `json:"fee,string"`
|
||||
}
|
||||
|
||||
// OptionsTicker represents tickers of options contracts
|
||||
type OptionsTicker struct {
|
||||
Name string `json:"name"`
|
||||
Name currency.Pair `json:"name"`
|
||||
LastPrice gateioNumericalValue `json:"last_price"`
|
||||
MarkPrice gateioNumericalValue `json:"mark_price"`
|
||||
PositionSize float64 `json:"position_size"`
|
||||
@@ -1088,16 +1089,16 @@ type MultiChainAddressItem struct {
|
||||
|
||||
// DepositRecord represents deposit record item
|
||||
type DepositRecord struct {
|
||||
ID string `json:"id"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Currency string `json:"currency"`
|
||||
Address string `json:"address"`
|
||||
TransactionID string `json:"txid"`
|
||||
Amount float64 `json:"amount,string"`
|
||||
Memo string `json:"memo"`
|
||||
Status string `json:"status"`
|
||||
Chain string `json:"chain"`
|
||||
Fee float64 `json:"fee,string"`
|
||||
ID string `json:"id"`
|
||||
Timestamp gateioTime `json:"timestamp"`
|
||||
Currency string `json:"currency"`
|
||||
Address string `json:"address"`
|
||||
TransactionID string `json:"txid"`
|
||||
Amount float64 `json:"amount,string"`
|
||||
Memo string `json:"memo"`
|
||||
Status string `json:"status"`
|
||||
Chain string `json:"chain"`
|
||||
Fee float64 `json:"fee,string"`
|
||||
}
|
||||
|
||||
// TransferCurrencyParam represents currency transfer.
|
||||
@@ -1989,35 +1990,35 @@ type WsEventResponse struct {
|
||||
|
||||
// WsResponse represents generalized websocket push data from the server.
|
||||
type WsResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
Time int64 `json:"time"`
|
||||
Channel string `json:"channel"`
|
||||
Event string `json:"event"`
|
||||
Result interface{} `json:"result"`
|
||||
ID int64 `json:"id"`
|
||||
Time int64 `json:"time"`
|
||||
Channel string `json:"channel"`
|
||||
Event string `json:"event"`
|
||||
Result json.RawMessage `json:"result"`
|
||||
}
|
||||
|
||||
// WsTicker websocket ticker information.
|
||||
type WsTicker struct {
|
||||
CurrencyPair string `json:"currency_pair"`
|
||||
Last float64 `json:"last,string"`
|
||||
LowestAsk float64 `json:"lowest_ask,string"`
|
||||
HighestBid float64 `json:"highest_bid,string"`
|
||||
ChangePercentage float64 `json:"change_percentage,string"`
|
||||
BaseVolume float64 `json:"base_volume,string"`
|
||||
QuoteVolume float64 `json:"quote_volume,string"`
|
||||
High24H float64 `json:"high_24h,string"`
|
||||
Low24H float64 `json:"low_24h,string"`
|
||||
CurrencyPair currency.Pair `json:"currency_pair"`
|
||||
Last float64 `json:"last,string"`
|
||||
LowestAsk float64 `json:"lowest_ask,string"`
|
||||
HighestBid float64 `json:"highest_bid,string"`
|
||||
ChangePercentage float64 `json:"change_percentage,string"`
|
||||
BaseVolume float64 `json:"base_volume,string"`
|
||||
QuoteVolume float64 `json:"quote_volume,string"`
|
||||
High24H float64 `json:"high_24h,string"`
|
||||
Low24H float64 `json:"low_24h,string"`
|
||||
}
|
||||
|
||||
// WsTrade represents a websocket push data response for a trade
|
||||
type WsTrade struct {
|
||||
ID int64 `json:"id"`
|
||||
CreateTime int64 `json:"create_time"`
|
||||
CreateTimeMs float64 `json:"create_time_ms,string"`
|
||||
Side string `json:"side"`
|
||||
CurrencyPair string `json:"currency_pair"`
|
||||
Amount float64 `json:"amount,string"`
|
||||
Price float64 `json:"price,string"`
|
||||
ID int64 `json:"id"`
|
||||
CreateTime gateioTime `json:"create_time"`
|
||||
CreateTimeMs gateioTime `json:"create_time_ms"`
|
||||
Side string `json:"side"`
|
||||
CurrencyPair currency.Pair `json:"currency_pair"`
|
||||
Amount float64 `json:"amount,string"`
|
||||
Price float64 `json:"price,string"`
|
||||
}
|
||||
|
||||
// WsCandlesticks represents the candlestick data for spot, margin and cross margin trades pushed through the websocket channel.
|
||||
@@ -2033,34 +2034,34 @@ type WsCandlesticks struct {
|
||||
|
||||
// WsOrderbookTickerData represents the websocket orderbook best bid or best ask push data
|
||||
type WsOrderbookTickerData struct {
|
||||
UpdateTimeMS int64 `json:"t"`
|
||||
UpdateOrderID int64 `json:"u"`
|
||||
CurrencyPair string `json:"s"`
|
||||
BestBidPrice float64 `json:"b,string"`
|
||||
BestBidAmount float64 `json:"B,string"`
|
||||
BestAskPrice float64 `json:"a,string"`
|
||||
BestAskAmount float64 `json:"A,string"`
|
||||
UpdateTimeMS int64 `json:"t"`
|
||||
UpdateOrderID int64 `json:"u"`
|
||||
CurrencyPair currency.Pair `json:"s"`
|
||||
BestBidPrice float64 `json:"b,string"`
|
||||
BestBidAmount float64 `json:"B,string"`
|
||||
BestAskPrice float64 `json:"a,string"`
|
||||
BestAskAmount float64 `json:"A,string"`
|
||||
}
|
||||
|
||||
// WsOrderbookUpdate represents websocket orderbook update push data
|
||||
type WsOrderbookUpdate struct {
|
||||
UpdateTimeMs gateioTime `json:"t"`
|
||||
IgnoreField string `json:"e"`
|
||||
UpdateTime gateioTime `json:"E"`
|
||||
CurrencyPair string `json:"s"`
|
||||
FirstOrderbookUpdatedID int64 `json:"U"` // First update order book id in this event since last update
|
||||
LastOrderbookUpdatedID int64 `json:"u"`
|
||||
Bids [][2]string `json:"b"`
|
||||
Asks [][2]string `json:"a"`
|
||||
UpdateTimeMs gateioTime `json:"t"`
|
||||
IgnoreField string `json:"e"`
|
||||
UpdateTime gateioTime `json:"E"`
|
||||
CurrencyPair currency.Pair `json:"s"`
|
||||
FirstOrderbookUpdatedID int64 `json:"U"` // First update order book id in this event since last update
|
||||
LastOrderbookUpdatedID int64 `json:"u"`
|
||||
Bids [][2]string `json:"b"`
|
||||
Asks [][2]string `json:"a"`
|
||||
}
|
||||
|
||||
// WsOrderbookSnapshot represents a websocket orderbook snapshot push data
|
||||
type WsOrderbookSnapshot struct {
|
||||
UpdateTimeMs gateioTime `json:"t"`
|
||||
LastUpdateID int64 `json:"lastUpdateId"`
|
||||
CurrencyPair string `json:"s"`
|
||||
Bids [][2]string `json:"bids"`
|
||||
Asks [][2]string `json:"asks"`
|
||||
UpdateTimeMs gateioTime `json:"t"`
|
||||
LastUpdateID int64 `json:"lastUpdateId"`
|
||||
CurrencyPair currency.Pair `json:"s"`
|
||||
Bids [][2]string `json:"bids"`
|
||||
Asks [][2]string `json:"asks"`
|
||||
}
|
||||
|
||||
// WsSpotOrder represents an order push data through the websocket channel.
|
||||
@@ -2071,7 +2072,7 @@ type WsSpotOrder struct {
|
||||
Succeeded bool `json:"succeeded,omitempty"`
|
||||
Label string `json:"label,omitempty"`
|
||||
Message string `json:"message,omitempty"`
|
||||
CurrencyPair string `json:"currency_pair,omitempty"`
|
||||
CurrencyPair currency.Pair `json:"currency_pair,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
Account string `json:"account,omitempty"`
|
||||
Side string `json:"side,omitempty"`
|
||||
@@ -2097,20 +2098,20 @@ type WsSpotOrder struct {
|
||||
|
||||
// WsUserPersonalTrade represents a user's personal trade pushed through the websocket connection.
|
||||
type WsUserPersonalTrade struct {
|
||||
ID int64 `json:"id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
OrderID string `json:"order_id"`
|
||||
CurrencyPair string `json:"currency_pair"`
|
||||
CreateTime int64 `json:"create_time"`
|
||||
CreateTimeMicroS time.Time `json:"create_time_ms"`
|
||||
Side string `json:"side"`
|
||||
Amount float64 `json:"amount,string"`
|
||||
Role string `json:"role"`
|
||||
Price float64 `json:"price,string"`
|
||||
Fee float64 `json:"fee,string"`
|
||||
PointFee float64 `json:"point_fee,string"`
|
||||
GtFee string `json:"gt_fee"`
|
||||
Text string `json:"text"`
|
||||
ID int64 `json:"id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
OrderID string `json:"order_id"`
|
||||
CurrencyPair currency.Pair `json:"currency_pair"`
|
||||
CreateTime int64 `json:"create_time"`
|
||||
CreateTimeMs gateioTime `json:"create_time_ms"`
|
||||
Side string `json:"side"`
|
||||
Amount float64 `json:"amount,string"`
|
||||
Role string `json:"role"`
|
||||
Price float64 `json:"price,string"`
|
||||
Fee float64 `json:"fee,string"`
|
||||
PointFee float64 `json:"point_fee,string"`
|
||||
GtFee string `json:"gt_fee"`
|
||||
Text string `json:"text"`
|
||||
}
|
||||
|
||||
// WsSpotBalance represents a spot balance.
|
||||
@@ -2174,33 +2175,33 @@ type WsCrossMarginLoan struct {
|
||||
|
||||
// WsFutureTicker represents a futures push data.
|
||||
type WsFutureTicker struct {
|
||||
Contract string `json:"contract"`
|
||||
Last float64 `json:"last,string"`
|
||||
ChangePercentage string `json:"change_percentage"`
|
||||
FundingRate string `json:"funding_rate"`
|
||||
FundingRateIndicative string `json:"funding_rate_indicative"`
|
||||
MarkPrice float64 `json:"mark_price,string"`
|
||||
IndexPrice float64 `json:"index_price,string"`
|
||||
TotalSize float64 `json:"total_size,string"`
|
||||
Volume24H float64 `json:"volume_24h,string"`
|
||||
Volume24HBtc float64 `json:"volume_24h_btc,string"`
|
||||
Volume24HUsd float64 `json:"volume_24h_usd,string"`
|
||||
QuantoBaseRate string `json:"quanto_base_rate"`
|
||||
Volume24HQuote float64 `json:"volume_24h_quote,string"`
|
||||
Volume24HSettle string `json:"volume_24h_settle"`
|
||||
Volume24HBase float64 `json:"volume_24h_base,string"`
|
||||
Low24H float64 `json:"low_24h,string"`
|
||||
High24H float64 `json:"high_24h,string"`
|
||||
Contract currency.Pair `json:"contract"`
|
||||
Last float64 `json:"last,string"`
|
||||
ChangePercentage string `json:"change_percentage"`
|
||||
FundingRate string `json:"funding_rate"`
|
||||
FundingRateIndicative string `json:"funding_rate_indicative"`
|
||||
MarkPrice float64 `json:"mark_price,string"`
|
||||
IndexPrice float64 `json:"index_price,string"`
|
||||
TotalSize float64 `json:"total_size,string"`
|
||||
Volume24H float64 `json:"volume_24h,string"`
|
||||
Volume24HBtc float64 `json:"volume_24h_btc,string"`
|
||||
Volume24HUsd float64 `json:"volume_24h_usd,string"`
|
||||
QuantoBaseRate string `json:"quanto_base_rate"`
|
||||
Volume24HQuote float64 `json:"volume_24h_quote,string"`
|
||||
Volume24HSettle string `json:"volume_24h_settle"`
|
||||
Volume24HBase float64 `json:"volume_24h_base,string"`
|
||||
Low24H float64 `json:"low_24h,string"`
|
||||
High24H float64 `json:"high_24h,string"`
|
||||
}
|
||||
|
||||
// WsFuturesTrades represents a list of trades push data
|
||||
type WsFuturesTrades struct {
|
||||
Size float64 `json:"size"`
|
||||
ID int64 `json:"id"`
|
||||
CreateTime gateioTime `json:"create_time"`
|
||||
CreateTimeMs gateioTime `json:"create_time_ms"`
|
||||
Price float64 `json:"price,string"`
|
||||
Contract string `json:"contract"`
|
||||
Size float64 `json:"size"`
|
||||
ID int64 `json:"id"`
|
||||
CreateTime gateioTime `json:"create_time"`
|
||||
CreateTimeMs gateioTime `json:"create_time_ms"`
|
||||
Price float64 `json:"price,string"`
|
||||
Contract currency.Pair `json:"contract"`
|
||||
}
|
||||
|
||||
// WsFuturesOrderbookTicker represents the orderbook ticker push data
|
||||
@@ -2216,10 +2217,10 @@ type WsFuturesOrderbookTicker struct {
|
||||
|
||||
// WsFuturesAndOptionsOrderbookUpdate represents futures and options account orderbook update push data
|
||||
type WsFuturesAndOptionsOrderbookUpdate struct {
|
||||
TimestampInMs int64 `json:"t"`
|
||||
ContractName string `json:"s"`
|
||||
FirstUpdatedID int64 `json:"U"`
|
||||
LastUpdatedID int64 `json:"u"`
|
||||
TimestampInMs int64 `json:"t"`
|
||||
ContractName currency.Pair `json:"s"`
|
||||
FirstUpdatedID int64 `json:"U"`
|
||||
LastUpdatedID int64 `json:"u"`
|
||||
Bids []struct {
|
||||
Price float64 `json:"p,string"`
|
||||
Size float64 `json:"s"`
|
||||
@@ -2232,9 +2233,9 @@ type WsFuturesAndOptionsOrderbookUpdate struct {
|
||||
|
||||
// WsFuturesOrderbookSnapshot represents a futures orderbook snapshot push data
|
||||
type WsFuturesOrderbookSnapshot struct {
|
||||
TimestampInMs gateioTime `json:"t"`
|
||||
Contract string `json:"contract"`
|
||||
OrderbookID int64 `json:"id"`
|
||||
TimestampInMs gateioTime `json:"t"`
|
||||
Contract currency.Pair `json:"contract"`
|
||||
OrderbookID int64 `json:"id"`
|
||||
Asks []struct {
|
||||
Price float64 `json:"p,string"`
|
||||
Size float64 `json:"s"`
|
||||
@@ -2255,44 +2256,44 @@ type WsFuturesOrderbookUpdateEvent struct {
|
||||
|
||||
// WsFuturesOrder represents futures order
|
||||
type WsFuturesOrder struct {
|
||||
Contract string `json:"contract"`
|
||||
CreateTime gateioTime `json:"create_time"`
|
||||
CreateTimeMs gateioTime `json:"create_time_ms"`
|
||||
FillPrice float64 `json:"fill_price"`
|
||||
FinishAs string `json:"finish_as"`
|
||||
FinishTime int64 `json:"finish_time"`
|
||||
FinishTimeMs gateioTime `json:"finish_time_ms"`
|
||||
Iceberg int64 `json:"iceberg"`
|
||||
ID int64 `json:"id"`
|
||||
IsClose bool `json:"is_close"`
|
||||
IsLiq bool `json:"is_liq"`
|
||||
IsReduceOnly bool `json:"is_reduce_only"`
|
||||
Left float64 `json:"left"`
|
||||
Mkfr float64 `json:"mkfr"`
|
||||
Price float64 `json:"price"`
|
||||
Refr int64 `json:"refr"`
|
||||
Refu int64 `json:"refu"`
|
||||
Size float64 `json:"size"`
|
||||
Status string `json:"status"`
|
||||
Text string `json:"text"`
|
||||
TimeInForce string `json:"tif"`
|
||||
Tkfr float64 `json:"tkfr"`
|
||||
User string `json:"user"`
|
||||
Contract currency.Pair `json:"contract"`
|
||||
CreateTime gateioTime `json:"create_time"`
|
||||
CreateTimeMs gateioTime `json:"create_time_ms"`
|
||||
FillPrice float64 `json:"fill_price"`
|
||||
FinishAs string `json:"finish_as"`
|
||||
FinishTime int64 `json:"finish_time"`
|
||||
FinishTimeMs gateioTime `json:"finish_time_ms"`
|
||||
Iceberg int64 `json:"iceberg"`
|
||||
ID int64 `json:"id"`
|
||||
IsClose bool `json:"is_close"`
|
||||
IsLiq bool `json:"is_liq"`
|
||||
IsReduceOnly bool `json:"is_reduce_only"`
|
||||
Left float64 `json:"left"`
|
||||
Mkfr float64 `json:"mkfr"`
|
||||
Price float64 `json:"price"`
|
||||
Refr int64 `json:"refr"`
|
||||
Refu int64 `json:"refu"`
|
||||
Size float64 `json:"size"`
|
||||
Status string `json:"status"`
|
||||
Text string `json:"text"`
|
||||
TimeInForce string `json:"tif"`
|
||||
Tkfr float64 `json:"tkfr"`
|
||||
User string `json:"user"`
|
||||
}
|
||||
|
||||
// WsFuturesUserTrade represents a futures account user trade push data
|
||||
type WsFuturesUserTrade struct {
|
||||
ID string `json:"id"`
|
||||
CreateTime gateioTime `json:"create_time"`
|
||||
CreateTimeMs gateioTime `json:"create_time_ms"`
|
||||
Contract string `json:"contract"`
|
||||
OrderID string `json:"order_id"`
|
||||
Size float64 `json:"size"`
|
||||
Price float64 `json:"price,string"`
|
||||
Role string `json:"role"`
|
||||
Text string `json:"text"`
|
||||
Fee float64 `json:"fee"`
|
||||
PointFee int64 `json:"point_fee"`
|
||||
ID string `json:"id"`
|
||||
CreateTime gateioTime `json:"create_time"`
|
||||
CreateTimeMs gateioTime `json:"create_time_ms"`
|
||||
Contract currency.Pair `json:"contract"`
|
||||
OrderID string `json:"order_id"`
|
||||
Size float64 `json:"size"`
|
||||
Price float64 `json:"price,string"`
|
||||
Role string `json:"role"`
|
||||
Text string `json:"text"`
|
||||
Fee float64 `json:"fee"`
|
||||
PointFee int64 `json:"point_fee"`
|
||||
}
|
||||
|
||||
// WsFuturesLiquidationNotification represents a liquidation notification push data
|
||||
@@ -2431,11 +2432,11 @@ type WsOptionUnderlyingTicker struct {
|
||||
|
||||
// WsOptionsTrades represents options trades for websocket push data.
|
||||
type WsOptionsTrades struct {
|
||||
ID int64 `json:"id"`
|
||||
CreateTime gateioTime `json:"create_time"`
|
||||
Contract string `json:"contract"`
|
||||
Size float64 `json:"size"`
|
||||
Price float64 `json:"price"`
|
||||
ID int64 `json:"id"`
|
||||
CreateTime gateioTime `json:"create_time"`
|
||||
Contract currency.Pair `json:"contract"`
|
||||
Size float64 `json:"size"`
|
||||
Price float64 `json:"price"`
|
||||
|
||||
// Added in options websocket push data
|
||||
CreateTimeMs gateioTime `json:"create_time_ms"`
|
||||
@@ -2529,9 +2530,9 @@ type WsOptionsOrderbookTicker struct {
|
||||
|
||||
// WsOptionsOrderbookSnapshot represents the options orderbook snapshot push data.
|
||||
type WsOptionsOrderbookSnapshot struct {
|
||||
Timestamp gateioTime `json:"t"`
|
||||
Contract string `json:"contract"`
|
||||
ID int64 `json:"id"`
|
||||
Timestamp gateioTime `json:"t"`
|
||||
Contract currency.Pair `json:"contract"`
|
||||
ID int64 `json:"id"`
|
||||
Asks []struct {
|
||||
Price float64 `json:"p,string"`
|
||||
Size float64 `json:"s"`
|
||||
@@ -2544,42 +2545,42 @@ type WsOptionsOrderbookSnapshot struct {
|
||||
|
||||
// WsOptionsOrder represents options order push data.
|
||||
type WsOptionsOrder struct {
|
||||
ID int64 `json:"id"`
|
||||
Contract string `json:"contract"`
|
||||
CreateTime int64 `json:"create_time"`
|
||||
FillPrice float64 `json:"fill_price"`
|
||||
FinishAs string `json:"finish_as"`
|
||||
Iceberg float64 `json:"iceberg"`
|
||||
IsClose bool `json:"is_close"`
|
||||
IsLiq bool `json:"is_liq"`
|
||||
IsReduceOnly bool `json:"is_reduce_only"`
|
||||
Left float64 `json:"left"`
|
||||
Mkfr float64 `json:"mkfr"`
|
||||
Price float64 `json:"price"`
|
||||
Refr float64 `json:"refr"`
|
||||
Refu float64 `json:"refu"`
|
||||
Size float64 `json:"size"`
|
||||
Status string `json:"status"`
|
||||
Text string `json:"text"`
|
||||
Tif string `json:"tif"`
|
||||
Tkfr float64 `json:"tkfr"`
|
||||
Underlying string `json:"underlying"`
|
||||
User string `json:"user"`
|
||||
CreationTime gateioTime `json:"time"`
|
||||
CreationTimeMs gateioTime `json:"time_ms"`
|
||||
ID int64 `json:"id"`
|
||||
Contract currency.Pair `json:"contract"`
|
||||
CreateTime int64 `json:"create_time"`
|
||||
FillPrice float64 `json:"fill_price"`
|
||||
FinishAs string `json:"finish_as"`
|
||||
Iceberg float64 `json:"iceberg"`
|
||||
IsClose bool `json:"is_close"`
|
||||
IsLiq bool `json:"is_liq"`
|
||||
IsReduceOnly bool `json:"is_reduce_only"`
|
||||
Left float64 `json:"left"`
|
||||
Mkfr float64 `json:"mkfr"`
|
||||
Price float64 `json:"price"`
|
||||
Refr float64 `json:"refr"`
|
||||
Refu float64 `json:"refu"`
|
||||
Size float64 `json:"size"`
|
||||
Status string `json:"status"`
|
||||
Text string `json:"text"`
|
||||
Tif string `json:"tif"`
|
||||
Tkfr float64 `json:"tkfr"`
|
||||
Underlying string `json:"underlying"`
|
||||
User string `json:"user"`
|
||||
CreationTime gateioTime `json:"time"`
|
||||
CreationTimeMs gateioTime `json:"time_ms"`
|
||||
}
|
||||
|
||||
// WsOptionsUserTrade represents user's personal trades of option account.
|
||||
type WsOptionsUserTrade struct {
|
||||
ID string `json:"id"`
|
||||
Underlying string `json:"underlying"`
|
||||
OrderID string `json:"order"`
|
||||
Contract string `json:"contract"`
|
||||
CreateTime gateioTime `json:"create_time"`
|
||||
CreateTimeMs gateioTime `json:"create_time_ms"`
|
||||
Price float64 `json:"price,string"`
|
||||
Role string `json:"role"`
|
||||
Size float64 `json:"size"`
|
||||
ID string `json:"id"`
|
||||
Underlying string `json:"underlying"`
|
||||
OrderID string `json:"order"`
|
||||
Contract currency.Pair `json:"contract"`
|
||||
CreateTime gateioTime `json:"create_time"`
|
||||
CreateTimeMs gateioTime `json:"create_time_ms"`
|
||||
Price float64 `json:"price,string"`
|
||||
Role string `json:"role"`
|
||||
Size float64 `json:"size"`
|
||||
}
|
||||
|
||||
// WsOptionsLiquidates represents the liquidates push data of option account.
|
||||
|
||||
@@ -52,7 +52,7 @@ var defaultSubscriptions = []string{
|
||||
spotTickerChannel,
|
||||
spotCandlesticksChannel,
|
||||
spotTradesChannel,
|
||||
spotOrderbookChannel,
|
||||
spotOrderbookTickerChannel,
|
||||
}
|
||||
|
||||
var fetchedCurrencyPairSnapshotOrderbook = make(map[string]bool)
|
||||
@@ -66,14 +66,11 @@ func (g *Gateio) WsConnect() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var dialer websocket.Dialer
|
||||
err = g.Websocket.Conn.Dial(&dialer, http.Header{})
|
||||
err = g.Websocket.Conn.Dial(&websocket.Dialer{}, http.Header{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pingMessage, err := json.Marshal(WsInput{
|
||||
Channel: spotPingChannel,
|
||||
})
|
||||
pingMessage, err := json.Marshal(WsInput{Channel: spotPingChannel})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -113,34 +110,32 @@ func (g *Gateio) wsReadConnData() {
|
||||
}
|
||||
|
||||
func (g *Gateio) wsHandleData(respRaw []byte) error {
|
||||
var result WsResponse
|
||||
var eventResponse WsEventResponse
|
||||
err := json.Unmarshal(respRaw, &eventResponse)
|
||||
if err == nil &&
|
||||
(eventResponse.Result != nil || eventResponse.Error != nil) &&
|
||||
(eventResponse.Event == "subscribe" || eventResponse.Event == "unsubscribe") {
|
||||
if !g.Websocket.Match.IncomingWithData(eventResponse.ID, respRaw) {
|
||||
return fmt.Errorf("couldn't match subscription message with ID: %d", eventResponse.ID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
err = json.Unmarshal(respRaw, &result)
|
||||
var push WsResponse
|
||||
err := json.Unmarshal(respRaw, &push)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch result.Channel {
|
||||
|
||||
if push.Event == "subscribe" || push.Event == "unsubscribe" {
|
||||
if !g.Websocket.Match.IncomingWithData(push.ID, respRaw) {
|
||||
return fmt.Errorf("couldn't match subscription message with ID: %d", push.ID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
switch push.Channel { // TODO: Convert function params below to only use push.Result
|
||||
case spotTickerChannel:
|
||||
return g.processTicker(respRaw)
|
||||
return g.processTicker(push.Result, push.Time)
|
||||
case spotTradesChannel:
|
||||
return g.processTrades(respRaw)
|
||||
return g.processTrades(push.Result)
|
||||
case spotCandlesticksChannel:
|
||||
return g.processCandlestick(respRaw)
|
||||
return g.processCandlestick(push.Result)
|
||||
case spotOrderbookTickerChannel:
|
||||
return g.processOrderbookTicker(respRaw)
|
||||
return g.processOrderbookTicker(push.Result)
|
||||
case spotOrderbookUpdateChannel:
|
||||
return g.processOrderbookUpdate(respRaw)
|
||||
return g.processOrderbookUpdate(push.Result)
|
||||
case spotOrderbookChannel:
|
||||
return g.processOrderbookSnapshot(respRaw)
|
||||
return g.processOrderbookSnapshot(push.Result)
|
||||
case spotOrdersChannel:
|
||||
return g.processSpotOrders(respRaw)
|
||||
case spotUserTradesChannel:
|
||||
@@ -165,32 +160,26 @@ func (g *Gateio) wsHandleData(respRaw []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processTicker(data []byte) error {
|
||||
var response WsResponse
|
||||
tickerData := &WsTicker{}
|
||||
response.Result = tickerData
|
||||
err := json.Unmarshal(data, &response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
currencyPair, err := currency.NewPairFromString(tickerData.CurrencyPair)
|
||||
func (g *Gateio) processTicker(incoming []byte, pushTime int64) error {
|
||||
var data WsTicker
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tickerPrice := ticker.Price{
|
||||
ExchangeName: g.Name,
|
||||
Volume: tickerData.BaseVolume,
|
||||
QuoteVolume: tickerData.QuoteVolume,
|
||||
High: tickerData.High24H,
|
||||
Low: tickerData.Low24H,
|
||||
Last: tickerData.Last,
|
||||
Bid: tickerData.HighestBid,
|
||||
Ask: tickerData.LowestAsk,
|
||||
Volume: data.BaseVolume,
|
||||
QuoteVolume: data.QuoteVolume,
|
||||
High: data.High24H,
|
||||
Low: data.Low24H,
|
||||
Last: data.Last,
|
||||
Bid: data.HighestBid,
|
||||
Ask: data.LowestAsk,
|
||||
AssetType: asset.Spot,
|
||||
Pair: currencyPair,
|
||||
LastUpdated: time.Unix(response.Time, 0),
|
||||
Pair: data.CurrencyPair,
|
||||
LastUpdated: time.Unix(pushTime, 0),
|
||||
}
|
||||
assetPairEnabled := g.listOfAssetsCurrencyPairEnabledFor(currencyPair)
|
||||
assetPairEnabled := g.listOfAssetsCurrencyPairEnabledFor(data.CurrencyPair)
|
||||
if assetPairEnabled[asset.Spot] {
|
||||
g.Websocket.DataHandler <- &tickerPrice
|
||||
}
|
||||
@@ -207,33 +196,28 @@ func (g *Gateio) processTicker(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processTrades(data []byte) error {
|
||||
var response WsResponse
|
||||
tradeData := &WsTrade{}
|
||||
response.Result = tradeData
|
||||
err := json.Unmarshal(data, &response)
|
||||
func (g *Gateio) processTrades(incoming []byte) error {
|
||||
var data WsTrade
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
currencyPair, err := currency.NewPairFromString(tradeData.CurrencyPair)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
side, err := order.StringToOrderSide(tradeData.Side)
|
||||
|
||||
side, err := order.StringToOrderSide(data.Side)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
spotTradeData := trade.Data{
|
||||
Timestamp: time.UnixMicro(int64(tradeData.CreateTimeMs * 1e3)), // the timestamp data is coming as a floating number.
|
||||
CurrencyPair: currencyPair,
|
||||
Timestamp: data.CreateTimeMs.Time(),
|
||||
CurrencyPair: data.CurrencyPair,
|
||||
AssetType: asset.Spot,
|
||||
Exchange: g.Name,
|
||||
Price: tradeData.Price,
|
||||
Amount: tradeData.Amount,
|
||||
Price: data.Price,
|
||||
Amount: data.Amount,
|
||||
Side: side,
|
||||
TID: strconv.FormatInt(tradeData.ID, 10),
|
||||
TID: strconv.FormatInt(data.ID, 10),
|
||||
}
|
||||
assetPairEnabled := g.listOfAssetsCurrencyPairEnabledFor(currencyPair)
|
||||
assetPairEnabled := g.listOfAssetsCurrencyPairEnabledFor(data.CurrencyPair)
|
||||
if assetPairEnabled[asset.Spot] {
|
||||
err = trade.AddTradesToBuffer(g.Name, spotTradeData)
|
||||
if err != nil {
|
||||
@@ -259,15 +243,13 @@ func (g *Gateio) processTrades(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processCandlestick(data []byte) error {
|
||||
var response WsResponse
|
||||
candleData := &WsCandlesticks{}
|
||||
response.Result = candleData
|
||||
err := json.Unmarshal(data, &response)
|
||||
func (g *Gateio) processCandlestick(incoming []byte) error {
|
||||
var data WsCandlesticks
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
icp := strings.Split(candleData.NameOfSubscription, currency.UnderscoreDelimiter)
|
||||
icp := strings.Split(data.NameOfSubscription, currency.UnderscoreDelimiter)
|
||||
if len(icp) < 3 {
|
||||
return errors.New("malformed candlestick websocket push data")
|
||||
}
|
||||
@@ -279,13 +261,13 @@ func (g *Gateio) processCandlestick(data []byte) error {
|
||||
Pair: currencyPair,
|
||||
AssetType: asset.Spot,
|
||||
Exchange: g.Name,
|
||||
StartTime: time.Unix(candleData.Timestamp, 0),
|
||||
StartTime: time.Unix(data.Timestamp, 0),
|
||||
Interval: icp[0],
|
||||
OpenPrice: candleData.OpenPrice,
|
||||
ClosePrice: candleData.ClosePrice,
|
||||
HighPrice: candleData.HighestPrice,
|
||||
LowPrice: candleData.LowestPrice,
|
||||
Volume: candleData.TotalVolume,
|
||||
OpenPrice: data.OpenPrice,
|
||||
ClosePrice: data.ClosePrice,
|
||||
HighPrice: data.HighestPrice,
|
||||
LowPrice: data.LowestPrice,
|
||||
Volume: data.TotalVolume,
|
||||
}
|
||||
assetPairEnabled := g.listOfAssetsCurrencyPairEnabledFor(currencyPair)
|
||||
if assetPairEnabled[asset.Spot] {
|
||||
@@ -304,34 +286,33 @@ func (g *Gateio) processCandlestick(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processOrderbookTicker(data []byte) error {
|
||||
var response WsResponse
|
||||
tickerData := &WsOrderbookTickerData{}
|
||||
response.Result = tickerData
|
||||
err := json.Unmarshal(data, &response)
|
||||
func (g *Gateio) processOrderbookTicker(incoming []byte) error {
|
||||
var data WsOrderbookTickerData
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- tickerData
|
||||
return nil
|
||||
|
||||
return g.Websocket.Orderbook.LoadSnapshot(&orderbook.Base{
|
||||
Exchange: g.Name,
|
||||
Pair: data.CurrencyPair,
|
||||
Asset: asset.Spot,
|
||||
LastUpdated: time.UnixMilli(data.UpdateTimeMS),
|
||||
Bids: []orderbook.Item{{Price: data.BestBidPrice, Amount: data.BestBidAmount}},
|
||||
Asks: []orderbook.Item{{Price: data.BestAskPrice, Amount: data.BestAskAmount}},
|
||||
})
|
||||
}
|
||||
|
||||
func (g *Gateio) processOrderbookUpdate(data []byte) error {
|
||||
var response WsResponse
|
||||
update := new(WsOrderbookUpdate)
|
||||
response.Result = update
|
||||
err := json.Unmarshal(data, &response)
|
||||
func (g *Gateio) processOrderbookUpdate(incoming []byte) error {
|
||||
var data WsOrderbookUpdate
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pair, err := currency.NewPairFromString(update.CurrencyPair)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
assetPairEnabled := g.listOfAssetsCurrencyPairEnabledFor(pair)
|
||||
if !fetchedCurrencyPairSnapshotOrderbook[update.CurrencyPair] {
|
||||
assetPairEnabled := g.listOfAssetsCurrencyPairEnabledFor(data.CurrencyPair)
|
||||
if !fetchedCurrencyPairSnapshotOrderbook[data.CurrencyPair.String()] {
|
||||
var orderbooks *orderbook.Base
|
||||
orderbooks, err = g.FetchOrderbook(context.Background(), pair, asset.Spot) // currency pair orderbook data for Spot, Margin, and Cross Margin is same
|
||||
orderbooks, err = g.FetchOrderbook(context.Background(), data.CurrencyPair, asset.Spot) // currency pair orderbook data for Spot, Margin, and Cross Margin is same
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -347,43 +328,33 @@ func (g *Gateio) processOrderbookUpdate(data []byte) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
fetchedCurrencyPairSnapshotOrderbook[update.CurrencyPair] = true
|
||||
fetchedCurrencyPairSnapshotOrderbook[data.CurrencyPair.String()] = true
|
||||
}
|
||||
updates := orderbook.Update{
|
||||
UpdateTime: update.UpdateTimeMs.Time(),
|
||||
Pair: pair,
|
||||
UpdateTime: data.UpdateTimeMs.Time(),
|
||||
Pair: data.CurrencyPair,
|
||||
}
|
||||
updates.Bids = make([]orderbook.Item, len(update.Bids))
|
||||
updates.Asks = make([]orderbook.Item, len(update.Asks))
|
||||
var price float64
|
||||
var amount float64
|
||||
for x := range updates.Asks {
|
||||
price, err = strconv.ParseFloat(update.Asks[x][0], 64)
|
||||
updates.Asks = make([]orderbook.Item, len(data.Asks))
|
||||
for x := range data.Asks {
|
||||
updates.Asks[x].Price, err = strconv.ParseFloat(data.Asks[x][0], 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
amount, err = strconv.ParseFloat(update.Asks[x][1], 64)
|
||||
updates.Asks[x].Amount, err = strconv.ParseFloat(data.Asks[x][1], 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
updates.Asks[x] = orderbook.Item{
|
||||
Amount: amount,
|
||||
Price: price,
|
||||
}
|
||||
}
|
||||
for x := range updates.Bids {
|
||||
price, err = strconv.ParseFloat(update.Bids[x][0], 64)
|
||||
updates.Bids = make([]orderbook.Item, len(data.Bids))
|
||||
for x := range data.Bids {
|
||||
updates.Bids[x].Price, err = strconv.ParseFloat(data.Bids[x][0], 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
amount, err = strconv.ParseFloat(update.Bids[x][1], 64)
|
||||
updates.Bids[x].Amount, err = strconv.ParseFloat(data.Bids[x][1], 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
updates.Bids[x] = orderbook.Item{
|
||||
Amount: amount,
|
||||
Price: price,
|
||||
}
|
||||
}
|
||||
if len(updates.Asks) == 0 && len(updates.Bids) == 0 {
|
||||
return nil
|
||||
@@ -414,58 +385,42 @@ func (g *Gateio) processOrderbookUpdate(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processOrderbookSnapshot(data []byte) error {
|
||||
var response WsResponse
|
||||
snapshot := &WsOrderbookSnapshot{}
|
||||
response.Result = snapshot
|
||||
err := json.Unmarshal(data, &response)
|
||||
func (g *Gateio) processOrderbookSnapshot(incoming []byte) error {
|
||||
var data WsOrderbookSnapshot
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pair, err := currency.NewPairFromString(snapshot.CurrencyPair)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
assetPairEnabled := g.listOfAssetsCurrencyPairEnabledFor(pair)
|
||||
assetPairEnabled := g.listOfAssetsCurrencyPairEnabledFor(data.CurrencyPair)
|
||||
bases := orderbook.Base{
|
||||
Exchange: g.Name,
|
||||
Pair: pair,
|
||||
Pair: data.CurrencyPair,
|
||||
Asset: asset.Spot,
|
||||
LastUpdated: snapshot.UpdateTimeMs.Time(),
|
||||
LastUpdateID: snapshot.LastUpdateID,
|
||||
LastUpdated: data.UpdateTimeMs.Time(),
|
||||
LastUpdateID: data.LastUpdateID,
|
||||
VerifyOrderbook: g.CanVerifyOrderbook,
|
||||
}
|
||||
bases.Bids = make([]orderbook.Item, len(snapshot.Bids))
|
||||
bases.Asks = make([]orderbook.Item, len(snapshot.Asks))
|
||||
var price float64
|
||||
var amount float64
|
||||
for x := range bases.Asks {
|
||||
price, err = strconv.ParseFloat(snapshot.Asks[x][0], 64)
|
||||
bases.Asks = make([]orderbook.Item, len(data.Asks))
|
||||
for x := range data.Asks {
|
||||
bases.Asks[x].Price, err = strconv.ParseFloat(data.Asks[x][0], 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
amount, err = strconv.ParseFloat(snapshot.Asks[x][1], 64)
|
||||
bases.Asks[x].Amount, err = strconv.ParseFloat(data.Asks[x][1], 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bases.Asks[x] = orderbook.Item{
|
||||
Amount: amount,
|
||||
Price: price,
|
||||
}
|
||||
}
|
||||
for x := range bases.Bids {
|
||||
price, err = strconv.ParseFloat(snapshot.Bids[x][0], 64)
|
||||
bases.Bids = make([]orderbook.Item, len(data.Bids))
|
||||
for x := range data.Bids {
|
||||
bases.Bids[x].Price, err = strconv.ParseFloat(data.Bids[x][0], 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
amount, err = strconv.ParseFloat(snapshot.Bids[x][1], 64)
|
||||
bases.Bids[x].Amount, err = strconv.ParseFloat(data.Bids[x][1], 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bases.Bids[x] = orderbook.Item{
|
||||
Amount: amount,
|
||||
Price: price,
|
||||
}
|
||||
}
|
||||
if assetPairEnabled[asset.Spot] {
|
||||
err = g.Websocket.Orderbook.LoadSnapshot(&bases)
|
||||
@@ -505,10 +460,6 @@ func (g *Gateio) processSpotOrders(data []byte) error {
|
||||
}
|
||||
details := make([]order.Detail, len(resp.Result))
|
||||
for x := range resp.Result {
|
||||
pair, err := currency.NewPairFromString(resp.Result[x].CurrencyPair)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
side, err := order.StringToOrderSide(resp.Result[x].Side)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -527,7 +478,7 @@ func (g *Gateio) processSpotOrders(data []byte) error {
|
||||
OrderID: resp.Result[x].ID,
|
||||
Side: side,
|
||||
Type: orderType,
|
||||
Pair: pair,
|
||||
Pair: resp.Result[x].CurrencyPair,
|
||||
Cost: resp.Result[x].Fee,
|
||||
AssetType: a,
|
||||
Price: resp.Result[x].Price,
|
||||
@@ -553,18 +504,14 @@ func (g *Gateio) processUserPersonalTrades(data []byte) error {
|
||||
}
|
||||
fills := make([]fill.Data, len(resp.Result))
|
||||
for x := range fills {
|
||||
currencyPair, err := currency.NewPairFromString(resp.Result[x].CurrencyPair)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
side, err := order.StringToOrderSide(resp.Result[x].Side)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fills[x] = fill.Data{
|
||||
Timestamp: resp.Result[x].CreateTimeMicroS,
|
||||
Timestamp: resp.Result[x].CreateTimeMs.Time(),
|
||||
Exchange: g.Name,
|
||||
CurrencyPair: currencyPair,
|
||||
CurrencyPair: resp.Result[x].CurrencyPair,
|
||||
Side: side,
|
||||
OrderID: resp.Result[x].OrderID,
|
||||
TradeID: strconv.FormatInt(resp.Result[x].ID, 10),
|
||||
@@ -691,29 +638,28 @@ func (g *Gateio) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, e
|
||||
spotBalancesChannel}...)
|
||||
}
|
||||
var subscriptions []stream.ChannelSubscription
|
||||
var pairs []currency.Pair
|
||||
var crossMarginPairs, spotPairs currency.Pairs
|
||||
marginPairs, err := g.GetEnabledPairs(asset.Margin)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
crossMarginPairs, err = g.GetEnabledPairs(asset.CrossMargin)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
spotPairs, err = g.GetEnabledPairs(asset.Spot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var err error
|
||||
for i := range channelsToSubscribe {
|
||||
var pairs []currency.Pair
|
||||
var assetType asset.Item
|
||||
switch channelsToSubscribe[i] {
|
||||
case marginBalancesChannel:
|
||||
pairs = marginPairs
|
||||
assetType = asset.Margin
|
||||
pairs, err = g.GetEnabledPairs(asset.Margin)
|
||||
case crossMarginBalanceChannel:
|
||||
pairs = crossMarginPairs
|
||||
assetType = asset.CrossMargin
|
||||
pairs, err = g.GetEnabledPairs(asset.CrossMargin)
|
||||
default:
|
||||
pairs = spotPairs
|
||||
assetType = asset.Spot
|
||||
pairs, err = g.GetEnabledPairs(asset.Spot)
|
||||
}
|
||||
if err != nil {
|
||||
if errors.Is(err, asset.ErrNotEnabled) {
|
||||
continue // Skip if asset is not enabled.
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for j := range pairs {
|
||||
params := make(map[string]interface{})
|
||||
switch channelsToSubscribe[i] {
|
||||
@@ -723,7 +669,7 @@ func (g *Gateio) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, e
|
||||
case spotCandlesticksChannel:
|
||||
params["interval"] = kline.FiveMin
|
||||
case spotOrderbookUpdateChannel:
|
||||
params["interval"] = kline.ThousandMilliseconds
|
||||
params["interval"] = kline.HundredMilliseconds
|
||||
}
|
||||
if spotTradesChannel == channelsToSubscribe[i] {
|
||||
if !g.IsSaveTradeDataEnabled() {
|
||||
@@ -738,6 +684,7 @@ func (g *Gateio) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, e
|
||||
subscriptions = append(subscriptions, stream.ChannelSubscription{
|
||||
Channel: channelsToSubscribe[i],
|
||||
Currency: fpair.Upper(),
|
||||
Asset: assetType,
|
||||
Params: params,
|
||||
})
|
||||
}
|
||||
@@ -788,8 +735,9 @@ func (g *Gateio) generatePayload(event string, channelsToSubscribe []stream.Chan
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
var batch *[]string
|
||||
var intervalString string
|
||||
payloads := make([]WsInput, len(channelsToSubscribe))
|
||||
payloads := make([]WsInput, 0, len(channelsToSubscribe))
|
||||
for i := range channelsToSubscribe {
|
||||
var auth *WsAuthInput
|
||||
timestamp := time.Now()
|
||||
@@ -863,7 +811,8 @@ func (g *Gateio) generatePayload(event string, channelsToSubscribe []stream.Chan
|
||||
}
|
||||
params = append(params, intervalString)
|
||||
}
|
||||
payloads[i] = WsInput{
|
||||
|
||||
payload := WsInput{
|
||||
ID: g.Websocket.Conn.GenerateMessageID(false),
|
||||
Event: event,
|
||||
Channel: channelsToSubscribe[i].Channel,
|
||||
@@ -871,6 +820,21 @@ func (g *Gateio) generatePayload(event string, channelsToSubscribe []stream.Chan
|
||||
Auth: auth,
|
||||
Time: timestamp.Unix(),
|
||||
}
|
||||
|
||||
if channelsToSubscribe[i].Channel == "spot.book_ticker" {
|
||||
// To get all orderbook assets subscribed it needs to be batched and
|
||||
// only spot.book_ticker can be batched, if not it will take about
|
||||
// half an hour for initital sync.
|
||||
if batch != nil {
|
||||
*batch = append(*batch, params...)
|
||||
} else {
|
||||
// Sets up pointer to the field for the outbound payload.
|
||||
payloads = append(payloads, payload)
|
||||
batch = &payloads[len(payloads)-1].Payload
|
||||
}
|
||||
continue
|
||||
}
|
||||
payloads = append(payloads, payload)
|
||||
}
|
||||
return payloads, nil
|
||||
}
|
||||
|
||||
@@ -331,20 +331,16 @@ func (g *Gateio) UpdateTicker(ctx context.Context, p currency.Pair, a asset.Item
|
||||
return nil, err
|
||||
}
|
||||
for x := range tickers {
|
||||
if tickers[x].Name != fPair.String() {
|
||||
if !tickers[x].Name.Equal(fPair) {
|
||||
continue
|
||||
}
|
||||
var cp currency.Pair
|
||||
cp, err = currency.NewPairFromString(strings.ReplaceAll(tickers[x].Name, currency.DashDelimiter, currency.UnderscoreDelimiter))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cp.Quote = currency.NewCode(strings.ReplaceAll(cp.Quote.String(), currency.UnderscoreDelimiter, currency.DashDelimiter))
|
||||
cleanQuote := strings.ReplaceAll(tickers[x].Name.Quote.String(), currency.UnderscoreDelimiter, currency.DashDelimiter)
|
||||
tickers[x].Name.Quote = currency.NewCode(cleanQuote)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tickerData = &ticker.Price{
|
||||
Pair: cp,
|
||||
Pair: tickers[x].Name,
|
||||
Last: tickers[x].LastPrice.Float64(),
|
||||
Bid: tickers[x].Bid1Price,
|
||||
Ask: tickers[x].Ask1Price,
|
||||
@@ -644,17 +640,13 @@ func (g *Gateio) UpdateTickers(ctx context.Context, a asset.Item) error {
|
||||
return err
|
||||
}
|
||||
for x := range tickers {
|
||||
currencyPair, err := currency.NewPairFromString(tickers[x].Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ticker.ProcessTicker(&ticker.Price{
|
||||
Last: tickers[x].LastPrice.Float64(),
|
||||
Ask: tickers[x].Ask1Price,
|
||||
AskSize: tickers[x].Ask1Size,
|
||||
Bid: tickers[x].Bid1Price,
|
||||
BidSize: tickers[x].Bid1Size,
|
||||
Pair: currencyPair,
|
||||
Pair: tickers[x].Name,
|
||||
ExchangeName: g.Name,
|
||||
AssetType: a,
|
||||
})
|
||||
@@ -724,20 +716,20 @@ func (g *Gateio) UpdateOrderbook(ctx context.Context, p currency.Pair, a asset.I
|
||||
VerifyOrderbook: g.CanVerifyOrderbook,
|
||||
Pair: p.Upper(),
|
||||
LastUpdateID: orderbookNew.ID,
|
||||
LastUpdated: orderbookNew.Update,
|
||||
LastUpdated: orderbookNew.Update.Time(),
|
||||
}
|
||||
book.Bids = make(orderbook.Items, len(orderbookNew.Bids))
|
||||
for x := range orderbookNew.Bids {
|
||||
book.Bids[x] = orderbook.Item{
|
||||
Amount: orderbookNew.Bids[x].Amount,
|
||||
Price: orderbookNew.Bids[x].Price,
|
||||
Price: orderbookNew.Bids[x].Price.Float64(),
|
||||
}
|
||||
}
|
||||
book.Asks = make(orderbook.Items, len(orderbookNew.Asks))
|
||||
for x := range orderbookNew.Asks {
|
||||
book.Asks[x] = orderbook.Item{
|
||||
Amount: orderbookNew.Asks[x].Amount,
|
||||
Price: orderbookNew.Asks[x].Price,
|
||||
Price: orderbookNew.Asks[x].Price.Float64(),
|
||||
}
|
||||
}
|
||||
err = book.Process()
|
||||
|
||||
@@ -216,33 +216,30 @@ func (g *Gateio) wsFunnelFuturesConnectionData(ws stream.Connection) {
|
||||
}
|
||||
|
||||
func (g *Gateio) wsHandleFuturesData(respRaw []byte, assetType asset.Item) error {
|
||||
var result WsResponse
|
||||
var eventResponse WsEventResponse
|
||||
err := json.Unmarshal(respRaw, &eventResponse)
|
||||
if err == nil &&
|
||||
(eventResponse.Result != nil || eventResponse.Error != nil) &&
|
||||
(eventResponse.Event == "subscribe" || eventResponse.Event == "unsubscribe") {
|
||||
if !g.Websocket.Match.IncomingWithData(eventResponse.ID, respRaw) {
|
||||
return fmt.Errorf("couldn't match subscription message with ID: %d", eventResponse.ID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
err = json.Unmarshal(respRaw, &result)
|
||||
var push WsResponse
|
||||
err := json.Unmarshal(respRaw, &push)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch result.Channel {
|
||||
// Futures push datas.
|
||||
|
||||
if push.Event == "subscribe" || push.Event == "unsubscribe" {
|
||||
if !g.Websocket.Match.IncomingWithData(push.ID, respRaw) {
|
||||
return fmt.Errorf("couldn't match subscription message with ID: %d", push.ID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
switch push.Channel {
|
||||
case futuresTickersChannel:
|
||||
return g.processFuturesTickers(respRaw, assetType)
|
||||
case futuresTradesChannel:
|
||||
return g.processFuturesTrades(respRaw, assetType)
|
||||
case futuresOrderbookChannel:
|
||||
return g.processFuturesOrderbookSnapshot(result.Event, respRaw, assetType)
|
||||
return g.processFuturesOrderbookSnapshot(push.Event, push.Result, assetType, push.Time)
|
||||
case futuresOrderbookTickerChannel:
|
||||
return g.processFuturesOrderbookTicker(respRaw)
|
||||
return g.processFuturesOrderbookTicker(push.Result)
|
||||
case futuresOrderbookUpdateChannel:
|
||||
return g.processFuturesAndOptionsOrderbookUpdate(respRaw, assetType)
|
||||
return g.processFuturesAndOptionsOrderbookUpdate(push.Result, assetType)
|
||||
case futuresCandlesticksChannel:
|
||||
return g.processFuturesCandlesticks(respRaw, assetType)
|
||||
case futuresOrdersChannel:
|
||||
@@ -426,10 +423,6 @@ func (g *Gateio) processFuturesTickers(data []byte, assetType asset.Item) error
|
||||
}
|
||||
tickerPriceDatas := make([]ticker.Price, len(resp.Result))
|
||||
for x := range resp.Result {
|
||||
currencyPair, err := currency.NewPairFromString(resp.Result[x].Contract)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tickerPriceDatas[x] = ticker.Price{
|
||||
ExchangeName: g.Name,
|
||||
Volume: resp.Result[x].Volume24HBase,
|
||||
@@ -438,7 +431,7 @@ func (g *Gateio) processFuturesTickers(data []byte, assetType asset.Item) error
|
||||
Low: resp.Result[x].Low24H,
|
||||
Last: resp.Result[x].Last,
|
||||
AssetType: assetType,
|
||||
Pair: currencyPair,
|
||||
Pair: resp.Result[x].Contract,
|
||||
LastUpdated: time.Unix(resp.Time, 0),
|
||||
}
|
||||
}
|
||||
@@ -459,13 +452,9 @@ func (g *Gateio) processFuturesTrades(data []byte, assetType asset.Item) error {
|
||||
}
|
||||
trades := make([]trade.Data, len(resp.Result))
|
||||
for x := range resp.Result {
|
||||
currencyPair, err := currency.NewPairFromString(resp.Result[x].Contract)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
trades[x] = trade.Data{
|
||||
Timestamp: resp.Result[x].CreateTimeMs.Time(),
|
||||
CurrencyPair: currencyPair,
|
||||
CurrencyPair: resp.Result[x].Contract,
|
||||
AssetType: assetType,
|
||||
Exchange: g.Name,
|
||||
Price: resp.Result[x].Price,
|
||||
@@ -514,37 +503,29 @@ func (g *Gateio) processFuturesCandlesticks(data []byte, assetType asset.Item) e
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processFuturesOrderbookTicker(data []byte) error {
|
||||
var response WsResponse
|
||||
orderbookTicker := &WsFuturesOrderbookTicker{}
|
||||
response.Result = orderbookTicker
|
||||
err := json.Unmarshal(data, &response)
|
||||
func (g *Gateio) processFuturesOrderbookTicker(incoming []byte) error {
|
||||
var data WsFuturesOrderbookTicker
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- response
|
||||
g.Websocket.DataHandler <- data
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processFuturesAndOptionsOrderbookUpdate(data []byte, assetType asset.Item) error {
|
||||
var response WsResponse
|
||||
update := &WsFuturesAndOptionsOrderbookUpdate{}
|
||||
response.Result = update
|
||||
err := json.Unmarshal(data, &response)
|
||||
func (g *Gateio) processFuturesAndOptionsOrderbookUpdate(incoming []byte, assetType asset.Item) error {
|
||||
var data WsFuturesAndOptionsOrderbookUpdate
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pair, err := currency.NewPairFromString(update.ContractName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (assetType == asset.Options && !fetchedOptionsCurrencyPairSnapshotOrderbook[update.ContractName]) ||
|
||||
(assetType != asset.Options && !fetchedFuturesCurrencyPairSnapshotOrderbook[update.ContractName]) {
|
||||
orderbooks, err := g.FetchOrderbook(context.Background(), pair, assetType)
|
||||
if (assetType == asset.Options && !fetchedOptionsCurrencyPairSnapshotOrderbook[data.ContractName.String()]) ||
|
||||
(assetType != asset.Options && !fetchedFuturesCurrencyPairSnapshotOrderbook[data.ContractName.String()]) {
|
||||
orderbooks, err := g.FetchOrderbook(context.Background(), data.ContractName, assetType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if orderbooks.LastUpdateID < update.FirstUpdatedID || orderbooks.LastUpdateID > update.LastUpdatedID {
|
||||
if orderbooks.LastUpdateID < data.FirstUpdatedID || orderbooks.LastUpdateID > data.LastUpdatedID {
|
||||
return nil
|
||||
}
|
||||
err = g.Websocket.Orderbook.LoadSnapshot(orderbooks)
|
||||
@@ -552,29 +533,25 @@ func (g *Gateio) processFuturesAndOptionsOrderbookUpdate(data []byte, assetType
|
||||
return err
|
||||
}
|
||||
if assetType == asset.Options {
|
||||
fetchedOptionsCurrencyPairSnapshotOrderbook[update.ContractName] = true
|
||||
fetchedOptionsCurrencyPairSnapshotOrderbook[data.ContractName.String()] = true
|
||||
} else {
|
||||
fetchedFuturesCurrencyPairSnapshotOrderbook[update.ContractName] = true
|
||||
fetchedFuturesCurrencyPairSnapshotOrderbook[data.ContractName.String()] = true
|
||||
}
|
||||
}
|
||||
updates := orderbook.Update{
|
||||
UpdateTime: time.UnixMilli(update.TimestampInMs),
|
||||
Pair: pair,
|
||||
UpdateTime: time.UnixMilli(data.TimestampInMs),
|
||||
Pair: data.ContractName,
|
||||
Asset: assetType,
|
||||
}
|
||||
updates.Bids = make([]orderbook.Item, len(update.Bids))
|
||||
updates.Asks = make([]orderbook.Item, len(update.Asks))
|
||||
for x := range updates.Asks {
|
||||
updates.Asks[x] = orderbook.Item{
|
||||
Amount: update.Asks[x].Size,
|
||||
Price: update.Asks[x].Price,
|
||||
}
|
||||
updates.Asks = make([]orderbook.Item, len(data.Asks))
|
||||
for x := range data.Asks {
|
||||
updates.Asks[x].Amount = data.Asks[x].Size
|
||||
updates.Asks[x].Price = data.Asks[x].Price
|
||||
}
|
||||
for x := range updates.Bids {
|
||||
updates.Bids[x] = orderbook.Item{
|
||||
Amount: update.Bids[x].Size,
|
||||
Price: update.Bids[x].Price,
|
||||
}
|
||||
updates.Bids = make([]orderbook.Item, len(data.Bids))
|
||||
for x := range data.Bids {
|
||||
updates.Bids[x].Amount = data.Bids[x].Size
|
||||
updates.Bids[x].Price = data.Bids[x].Price
|
||||
}
|
||||
if len(updates.Asks) == 0 && len(updates.Bids) == 0 {
|
||||
return errors.New("malformed orderbook data")
|
||||
@@ -582,71 +559,56 @@ func (g *Gateio) processFuturesAndOptionsOrderbookUpdate(data []byte, assetType
|
||||
return g.Websocket.Orderbook.Update(&updates)
|
||||
}
|
||||
|
||||
func (g *Gateio) processFuturesOrderbookSnapshot(event string, data []byte, assetType asset.Item) error {
|
||||
func (g *Gateio) processFuturesOrderbookSnapshot(event string, incoming []byte, assetType asset.Item, pushTime int64) error {
|
||||
if event == "all" {
|
||||
var response WsResponse
|
||||
snapshot := &WsFuturesOrderbookSnapshot{}
|
||||
response.Result = snapshot
|
||||
err := json.Unmarshal(data, &response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pair, err := currency.NewPairFromString(snapshot.Contract)
|
||||
var data WsFuturesOrderbookSnapshot
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
base := orderbook.Base{
|
||||
Asset: assetType,
|
||||
Exchange: g.Name,
|
||||
Pair: pair,
|
||||
LastUpdated: snapshot.TimestampInMs.Time(),
|
||||
Pair: data.Contract,
|
||||
LastUpdated: data.TimestampInMs.Time(),
|
||||
VerifyOrderbook: g.CanVerifyOrderbook,
|
||||
}
|
||||
base.Bids = make([]orderbook.Item, len(snapshot.Bids))
|
||||
base.Asks = make([]orderbook.Item, len(snapshot.Asks))
|
||||
for x := range base.Asks {
|
||||
base.Asks[x] = orderbook.Item{
|
||||
Amount: snapshot.Asks[x].Size,
|
||||
Price: snapshot.Asks[x].Price,
|
||||
}
|
||||
base.Asks = make([]orderbook.Item, len(data.Asks))
|
||||
for x := range data.Asks {
|
||||
base.Asks[x].Amount = data.Asks[x].Size
|
||||
base.Asks[x].Price = data.Asks[x].Price
|
||||
}
|
||||
for x := range base.Bids {
|
||||
base.Bids[x] = orderbook.Item{
|
||||
Amount: snapshot.Bids[x].Size,
|
||||
Price: snapshot.Bids[x].Price,
|
||||
}
|
||||
base.Bids = make([]orderbook.Item, len(data.Bids))
|
||||
for x := range data.Bids {
|
||||
base.Bids[x].Amount = data.Bids[x].Size
|
||||
base.Bids[x].Price = data.Bids[x].Price
|
||||
}
|
||||
return g.Websocket.Orderbook.LoadSnapshot(&base)
|
||||
}
|
||||
resp := struct {
|
||||
Time int64 `json:"time"`
|
||||
Channel string `json:"channel"`
|
||||
Event string `json:"event"`
|
||||
Result []WsFuturesOrderbookUpdateEvent `json:"result"`
|
||||
}{}
|
||||
err := json.Unmarshal(data, &resp)
|
||||
var data []WsFuturesOrderbookUpdateEvent
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dataMap := map[string][2][]orderbook.Item{}
|
||||
for x := range resp.Result {
|
||||
ab, ok := dataMap[resp.Result[x].CurrencyPair]
|
||||
for x := range data {
|
||||
ab, ok := dataMap[data[x].CurrencyPair]
|
||||
if !ok {
|
||||
ab = [2][]orderbook.Item{}
|
||||
}
|
||||
if resp.Result[x].Amount > 0 {
|
||||
if data[x].Amount > 0 {
|
||||
ab[1] = append(ab[1], orderbook.Item{
|
||||
Price: resp.Result[x].Price,
|
||||
Amount: resp.Result[x].Amount,
|
||||
Price: data[x].Price,
|
||||
Amount: data[x].Amount,
|
||||
})
|
||||
} else {
|
||||
ab[0] = append(ab[0], orderbook.Item{
|
||||
Price: resp.Result[x].Price,
|
||||
Amount: -resp.Result[x].Amount,
|
||||
Price: data[x].Price,
|
||||
Amount: -data[x].Amount,
|
||||
})
|
||||
}
|
||||
if !ok {
|
||||
dataMap[resp.Result[x].CurrencyPair] = ab
|
||||
dataMap[data[x].CurrencyPair] = ab
|
||||
}
|
||||
}
|
||||
if len(dataMap) == 0 {
|
||||
@@ -663,7 +625,7 @@ func (g *Gateio) processFuturesOrderbookSnapshot(event string, data []byte, asse
|
||||
Asset: assetType,
|
||||
Exchange: g.Name,
|
||||
Pair: currencyPair,
|
||||
LastUpdated: time.Unix(resp.Time, 0),
|
||||
LastUpdated: time.Unix(pushTime, 0),
|
||||
VerifyOrderbook: g.CanVerifyOrderbook,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -686,10 +648,6 @@ func (g *Gateio) processFuturesOrdersPushData(data []byte, assetType asset.Item)
|
||||
}
|
||||
orderDetails := make([]order.Detail, len(resp.Result))
|
||||
for x := range resp.Result {
|
||||
currencyPair, err := currency.NewPairFromString(resp.Result[x].Contract)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
status, err := order.StringToOrderStatus(func() string {
|
||||
if resp.Result[x].Status == "finished" {
|
||||
return "cancelled"
|
||||
@@ -704,7 +662,7 @@ func (g *Gateio) processFuturesOrdersPushData(data []byte, assetType asset.Item)
|
||||
Exchange: g.Name,
|
||||
OrderID: strconv.FormatInt(resp.Result[x].ID, 10),
|
||||
Status: status,
|
||||
Pair: currencyPair,
|
||||
Pair: resp.Result[x].Contract,
|
||||
LastUpdated: resp.Result[x].FinishTimeMs.Time(),
|
||||
Date: resp.Result[x].CreateTimeMs.Time(),
|
||||
ExecutedAmount: resp.Result[x].Size - resp.Result[x].Left,
|
||||
@@ -731,14 +689,10 @@ func (g *Gateio) procesFuturesUserTrades(data []byte, assetType asset.Item) erro
|
||||
}
|
||||
fills := make([]fill.Data, len(resp.Result))
|
||||
for x := range resp.Result {
|
||||
currencyPair, err := currency.NewPairFromString(resp.Result[x].Contract)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fills[x] = fill.Data{
|
||||
Timestamp: resp.Result[x].CreateTimeMs.Time(),
|
||||
Exchange: g.Name,
|
||||
CurrencyPair: currencyPair,
|
||||
CurrencyPair: resp.Result[x].Contract,
|
||||
OrderID: resp.Result[x].OrderID,
|
||||
TradeID: resp.Result[x].ID,
|
||||
Price: resp.Result[x].Price,
|
||||
|
||||
@@ -339,46 +339,44 @@ func (g *Gateio) handleOptionsSubscription(event string, channelsToSubscribe []s
|
||||
}
|
||||
|
||||
func (g *Gateio) wsHandleOptionsData(respRaw []byte) error {
|
||||
var result WsResponse
|
||||
var eventResponse WsEventResponse
|
||||
err := json.Unmarshal(respRaw, &eventResponse)
|
||||
if err == nil &&
|
||||
(eventResponse.Result != nil || eventResponse.Error != nil) &&
|
||||
(eventResponse.Event == "subscribe" || eventResponse.Event == "unsubscribe") {
|
||||
if !g.Websocket.Match.IncomingWithData(eventResponse.ID, respRaw) {
|
||||
return fmt.Errorf("couldn't match subscription message with ID: %d", eventResponse.ID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
err = json.Unmarshal(respRaw, &result)
|
||||
var push WsResponse
|
||||
err := json.Unmarshal(respRaw, &push)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch result.Channel {
|
||||
|
||||
if push.Event == "subscribe" || push.Event == "unsubscribe" {
|
||||
if !g.Websocket.Match.IncomingWithData(push.ID, respRaw) {
|
||||
return fmt.Errorf("couldn't match subscription message with ID: %d", push.ID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
switch push.Channel {
|
||||
case optionsContractTickersChannel:
|
||||
return g.processOptionsContractTickers(respRaw)
|
||||
return g.processOptionsContractTickers(push.Result)
|
||||
case optionsUnderlyingTickersChannel:
|
||||
return g.processOptionsUnderlyingTicker(respRaw)
|
||||
return g.processOptionsUnderlyingTicker(push.Result)
|
||||
case optionsTradesChannel,
|
||||
optionsUnderlyingTradesChannel:
|
||||
return g.processOptionsTradesPushData(respRaw)
|
||||
case optionsUnderlyingPriceChannel:
|
||||
return g.processOptionsUnderlyingPricePushData(respRaw)
|
||||
return g.processOptionsUnderlyingPricePushData(push.Result)
|
||||
case optionsMarkPriceChannel:
|
||||
return g.processOptionsMarkPrice(respRaw)
|
||||
return g.processOptionsMarkPrice(push.Result)
|
||||
case optionsSettlementChannel:
|
||||
return g.processOptionsSettlementPushData(respRaw)
|
||||
return g.processOptionsSettlementPushData(push.Result)
|
||||
case optionsContractsChannel:
|
||||
return g.processOptionsContractPushData(respRaw)
|
||||
return g.processOptionsContractPushData(push.Result)
|
||||
case optionsContractCandlesticksChannel,
|
||||
optionsUnderlyingCandlesticksChannel:
|
||||
return g.processOptionsCandlestickPushData(respRaw)
|
||||
case optionsOrderbookChannel:
|
||||
return g.processOptionsOrderbookSnapshotPushData(result.Event, respRaw)
|
||||
return g.processOptionsOrderbookSnapshotPushData(push.Event, push.Result, push.Time)
|
||||
case optionsOrderbookTickerChannel:
|
||||
return g.processOrderbookTickerPushData(respRaw)
|
||||
case optionsOrderbookUpdateChannel:
|
||||
return g.processFuturesAndOptionsOrderbookUpdate(respRaw, asset.Options)
|
||||
return g.processFuturesAndOptionsOrderbookUpdate(push.Result, asset.Options)
|
||||
case optionsOrdersChannel:
|
||||
return g.processOptionsOrderPushData(respRaw)
|
||||
case optionsUserTradesChannel:
|
||||
@@ -401,39 +399,32 @@ func (g *Gateio) wsHandleOptionsData(respRaw []byte) error {
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Gateio) processOptionsContractTickers(data []byte) error {
|
||||
var response WsResponse
|
||||
tickerData := OptionsTicker{}
|
||||
response.Result = &tickerData
|
||||
err := json.Unmarshal(data, &response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
currencyPair, err := currency.NewPairFromString(tickerData.Name)
|
||||
func (g *Gateio) processOptionsContractTickers(incoming []byte) error {
|
||||
var data OptionsTicker
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- &ticker.Price{
|
||||
Pair: currencyPair,
|
||||
Last: tickerData.LastPrice.Float64(),
|
||||
Bid: tickerData.Bid1Price,
|
||||
Ask: tickerData.Ask1Price,
|
||||
AskSize: tickerData.Ask1Size,
|
||||
BidSize: tickerData.Bid1Size,
|
||||
Pair: data.Name,
|
||||
Last: data.LastPrice.Float64(),
|
||||
Bid: data.Bid1Price,
|
||||
Ask: data.Ask1Price,
|
||||
AskSize: data.Ask1Size,
|
||||
BidSize: data.Bid1Size,
|
||||
ExchangeName: g.Name,
|
||||
AssetType: asset.Options,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processOptionsUnderlyingTicker(data []byte) error {
|
||||
var response WsResponse
|
||||
response.Result = &WsOptionUnderlyingTicker{}
|
||||
err := json.Unmarshal(data, &response)
|
||||
func (g *Gateio) processOptionsUnderlyingTicker(incoming []byte) error {
|
||||
var data WsOptionUnderlyingTicker
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- &response
|
||||
g.Websocket.DataHandler <- &data
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -455,13 +446,9 @@ func (g *Gateio) processOptionsTradesPushData(data []byte) error {
|
||||
}
|
||||
trades := make([]trade.Data, len(resp.Result))
|
||||
for x := range resp.Result {
|
||||
currencyPair, err := currency.NewPairFromString(resp.Result[x].Contract)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
trades[x] = trade.Data{
|
||||
Timestamp: resp.Result[x].CreateTimeMs.Time(),
|
||||
CurrencyPair: currencyPair,
|
||||
CurrencyPair: resp.Result[x].Contract,
|
||||
AssetType: asset.Options,
|
||||
Exchange: g.Name,
|
||||
Price: resp.Result[x].Price,
|
||||
@@ -472,51 +459,43 @@ func (g *Gateio) processOptionsTradesPushData(data []byte) error {
|
||||
return g.Websocket.Trade.Update(saveTradeData, trades...)
|
||||
}
|
||||
|
||||
func (g *Gateio) processOptionsUnderlyingPricePushData(data []byte) error {
|
||||
var response WsResponse
|
||||
priceD := WsOptionsUnderlyingPrice{}
|
||||
response.Result = &priceD
|
||||
err := json.Unmarshal(data, &response)
|
||||
func (g *Gateio) processOptionsUnderlyingPricePushData(incoming []byte) error {
|
||||
var data WsOptionsUnderlyingPrice
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- &response
|
||||
g.Websocket.DataHandler <- &data
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processOptionsMarkPrice(data []byte) error {
|
||||
var response WsResponse
|
||||
markPrice := WsOptionsMarkPrice{}
|
||||
response.Result = &markPrice
|
||||
err := json.Unmarshal(data, &response)
|
||||
func (g *Gateio) processOptionsMarkPrice(incoming []byte) error {
|
||||
var data WsOptionsMarkPrice
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- &response
|
||||
g.Websocket.DataHandler <- &data
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processOptionsSettlementPushData(data []byte) error {
|
||||
var response WsResponse
|
||||
settlementData := WsOptionsSettlement{}
|
||||
response.Result = &settlementData
|
||||
err := json.Unmarshal(data, &response)
|
||||
func (g *Gateio) processOptionsSettlementPushData(incoming []byte) error {
|
||||
var data WsOptionsSettlement
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- &response
|
||||
g.Websocket.DataHandler <- &data
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processOptionsContractPushData(data []byte) error {
|
||||
var response WsResponse
|
||||
contractData := WsOptionsContract{}
|
||||
response.Result = &contractData
|
||||
err := json.Unmarshal(data, &response)
|
||||
func (g *Gateio) processOptionsContractPushData(incoming []byte) error {
|
||||
var data WsOptionsContract
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- &response
|
||||
g.Websocket.DataHandler <- &data
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -558,83 +537,64 @@ func (g *Gateio) processOptionsCandlestickPushData(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processOrderbookTickerPushData(data []byte) error {
|
||||
var response WsResponse
|
||||
orderbookTicker := WsOptionsOrderbookTicker{}
|
||||
response.Result = &orderbookTicker
|
||||
err := json.Unmarshal(data, &orderbookTicker)
|
||||
func (g *Gateio) processOrderbookTickerPushData(incoming []byte) error {
|
||||
var data WsOptionsOrderbookTicker
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- &response
|
||||
g.Websocket.DataHandler <- &data
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processOptionsOrderbookSnapshotPushData(event string, data []byte) error {
|
||||
func (g *Gateio) processOptionsOrderbookSnapshotPushData(event string, incoming []byte, pushTime int64) error {
|
||||
if event == "all" {
|
||||
var response WsResponse
|
||||
snapshot := WsOptionsOrderbookSnapshot{}
|
||||
response.Result = &snapshot
|
||||
err := json.Unmarshal(data, &response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pair, err := currency.NewPairFromString(snapshot.Contract)
|
||||
var data WsOptionsOrderbookSnapshot
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
base := orderbook.Base{
|
||||
Asset: asset.Options,
|
||||
Exchange: g.Name,
|
||||
Pair: pair,
|
||||
LastUpdated: snapshot.Timestamp.Time(),
|
||||
Pair: data.Contract,
|
||||
LastUpdated: data.Timestamp.Time(),
|
||||
VerifyOrderbook: g.CanVerifyOrderbook,
|
||||
}
|
||||
base.Asks = make([]orderbook.Item, len(snapshot.Asks))
|
||||
base.Bids = make([]orderbook.Item, len(snapshot.Bids))
|
||||
for x := range base.Asks {
|
||||
base.Asks[x] = orderbook.Item{
|
||||
Amount: snapshot.Asks[x].Size,
|
||||
Price: snapshot.Asks[x].Price,
|
||||
}
|
||||
base.Asks = make([]orderbook.Item, len(data.Asks))
|
||||
for x := range data.Asks {
|
||||
base.Asks[x].Amount = data.Asks[x].Size
|
||||
base.Asks[x].Price = data.Asks[x].Price
|
||||
}
|
||||
for x := range base.Bids {
|
||||
base.Bids[x] = orderbook.Item{
|
||||
Amount: snapshot.Bids[x].Size,
|
||||
Price: snapshot.Bids[x].Price,
|
||||
}
|
||||
base.Bids = make([]orderbook.Item, len(data.Bids))
|
||||
for x := range data.Bids {
|
||||
base.Bids[x].Amount = data.Bids[x].Size
|
||||
base.Bids[x].Price = data.Bids[x].Price
|
||||
}
|
||||
return g.Websocket.Orderbook.LoadSnapshot(&base)
|
||||
}
|
||||
resp := struct {
|
||||
Time int64 `json:"time"`
|
||||
Channel string `json:"channel"`
|
||||
Event string `json:"event"`
|
||||
Result []WsFuturesOrderbookUpdateEvent `json:"result"`
|
||||
}{}
|
||||
err := json.Unmarshal(data, &resp)
|
||||
var data []WsFuturesOrderbookUpdateEvent
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dataMap := map[string][2][]orderbook.Item{}
|
||||
for x := range resp.Result {
|
||||
ab, ok := dataMap[resp.Result[x].CurrencyPair]
|
||||
for x := range data {
|
||||
ab, ok := dataMap[data[x].CurrencyPair]
|
||||
if !ok {
|
||||
ab = [2][]orderbook.Item{}
|
||||
}
|
||||
if resp.Result[x].Amount > 0 {
|
||||
if data[x].Amount > 0 {
|
||||
ab[1] = append(ab[1], orderbook.Item{
|
||||
Price: resp.Result[x].Price,
|
||||
Amount: resp.Result[x].Amount,
|
||||
Price: data[x].Price, Amount: data[x].Amount,
|
||||
})
|
||||
} else {
|
||||
ab[0] = append(ab[0], orderbook.Item{
|
||||
Price: resp.Result[x].Price,
|
||||
Amount: -resp.Result[x].Amount,
|
||||
Price: data[x].Price, Amount: -data[x].Amount,
|
||||
})
|
||||
}
|
||||
if !ok {
|
||||
dataMap[resp.Result[x].CurrencyPair] = ab
|
||||
dataMap[data[x].CurrencyPair] = ab
|
||||
}
|
||||
}
|
||||
if len(dataMap) == 0 {
|
||||
@@ -651,7 +611,7 @@ func (g *Gateio) processOptionsOrderbookSnapshotPushData(event string, data []by
|
||||
Asset: asset.Options,
|
||||
Exchange: g.Name,
|
||||
Pair: currencyPair,
|
||||
LastUpdated: time.Unix(resp.Time, 0),
|
||||
LastUpdated: time.Unix(pushTime, 0),
|
||||
VerifyOrderbook: g.CanVerifyOrderbook,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -674,10 +634,6 @@ func (g *Gateio) processOptionsOrderPushData(data []byte) error {
|
||||
}
|
||||
orderDetails := make([]order.Detail, len(resp.Result))
|
||||
for x := range resp.Result {
|
||||
currencyPair, err := currency.NewPairFromString(resp.Result[x].Contract)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
status, err := order.StringToOrderStatus(func() string {
|
||||
if resp.Result[x].Status == "finished" {
|
||||
return "cancelled"
|
||||
@@ -692,7 +648,7 @@ func (g *Gateio) processOptionsOrderPushData(data []byte) error {
|
||||
Exchange: g.Name,
|
||||
OrderID: strconv.FormatInt(resp.Result[x].ID, 10),
|
||||
Status: status,
|
||||
Pair: currencyPair,
|
||||
Pair: resp.Result[x].Contract,
|
||||
Date: resp.Result[x].CreationTimeMs.Time(),
|
||||
ExecutedAmount: resp.Result[x].Size - resp.Result[x].Left,
|
||||
Price: resp.Result[x].Price,
|
||||
@@ -717,14 +673,10 @@ func (g *Gateio) processOptionsUserTradesPushData(data []byte) error {
|
||||
}
|
||||
fills := make([]fill.Data, len(resp.Result))
|
||||
for x := range resp.Result {
|
||||
currencyPair, err := currency.NewPairFromString(resp.Result[x].Contract)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fills[x] = fill.Data{
|
||||
Timestamp: resp.Result[x].CreateTimeMs.Time(),
|
||||
Exchange: g.Name,
|
||||
CurrencyPair: currencyPair,
|
||||
CurrencyPair: resp.Result[x].Contract,
|
||||
OrderID: resp.Result[x].OrderID,
|
||||
TradeID: resp.Result[x].ID,
|
||||
Price: resp.Result[x].Price,
|
||||
|
||||
@@ -853,7 +853,7 @@ func (ok *Okx) ModifyOrder(ctx context.Context, action *order.Modify) (*order.Mo
|
||||
return nil, err
|
||||
}
|
||||
var err error
|
||||
if math.Mod(action.Amount, 1) != 0 {
|
||||
if math.Trunc(action.Amount) != action.Amount {
|
||||
return nil, errors.New("okx contract amount can not be decimal")
|
||||
}
|
||||
format, err := ok.GetPairFormat(action.AssetType, false)
|
||||
|
||||
Reference in New Issue
Block a user