mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-06-02 15:10:46 +00:00
golangci-lint/CI: Bump versions and introduce new linters (#798)
* golangci-lint/CI: Bump versions
Fix remaining linter issues
* Specifically set AppVeyor version
* Fix the infamous typos 👀
* Add go env cmd to AppVeyor
* Add go version cmd to AppVeyor
* Specify AppVeyor image, adjust linters
* Update go get to go install due to deprecation
* Bump golangci-lint timeout time for AppVeyor
* Change NW contract to NQ
* Address nitters
* GetRandomPair -> Pair{}
* Address nits
* Address time nitterinos plus additional tweaks
* More time inception upgrades!
* Bending time and space
This commit is contained in:
@@ -319,16 +319,18 @@ func (b *Bitfinex) GetV2FundingInfo(ctx context.Context, key string) (MarginFund
|
||||
if len(fundingData) < 4 {
|
||||
return response, fmt.Errorf("%v GetV2FundingInfo: invalid length of fundingData", b.Name)
|
||||
}
|
||||
for x := 0; x < 3; x++ {
|
||||
_, ok := fundingData[x].(float64)
|
||||
if !ok {
|
||||
return response, fmt.Errorf("type conversion failed for x = %d", x)
|
||||
}
|
||||
if response.Data.YieldLoan, ok = fundingData[0].(float64); !ok {
|
||||
return response, errors.New("type conversion failed for YieldLoan")
|
||||
}
|
||||
if response.Data.YieldLend, ok = fundingData[1].(float64); !ok {
|
||||
return response, errors.New("type conversion failed for YieldLend")
|
||||
}
|
||||
if response.Data.DurationLoan, ok = fundingData[2].(float64); !ok {
|
||||
return response, errors.New("type conversion failed for DurationLoan")
|
||||
}
|
||||
if response.Data.DurationLend, ok = fundingData[3].(float64); !ok {
|
||||
return response, errors.New("type conversion failed for DurationLend")
|
||||
}
|
||||
response.Data.YieldLoan = fundingData[0].(float64)
|
||||
response.Data.YieldLend = fundingData[1].(float64)
|
||||
response.Data.DurationLoan = fundingData[2].(float64)
|
||||
response.Data.DurationLend = fundingData[3].(float64)
|
||||
return response, nil
|
||||
}
|
||||
|
||||
@@ -637,7 +639,10 @@ func (b *Bitfinex) GetTrades(ctx context.Context, currencyPair string, limit, ti
|
||||
|
||||
var history []Trade
|
||||
for i := range resp {
|
||||
amount := resp[i][2].(float64)
|
||||
amount, ok := resp[i][2].(float64)
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert amount")
|
||||
}
|
||||
side := order.Buy.String()
|
||||
if amount < 0 {
|
||||
side = order.Sell.String()
|
||||
@@ -693,10 +698,21 @@ func (b *Bitfinex) GetOrderbook(ctx context.Context, symbol, precision string, l
|
||||
var b Book
|
||||
if len(response[x]) > 3 {
|
||||
// Funding currency
|
||||
b.Amount = response[x][3].(float64)
|
||||
b.Rate = response[x][2].(float64)
|
||||
b.Period = response[x][1].(float64)
|
||||
b.OrderID = int64(response[x][0].(float64))
|
||||
var ok bool
|
||||
if b.Amount, ok = response[x][3].(float64); !ok {
|
||||
return Orderbook{}, errors.New("unable to type assert amount")
|
||||
}
|
||||
if b.Rate, ok = response[x][2].(float64); !ok {
|
||||
return Orderbook{}, errors.New("unable to type assert rate")
|
||||
}
|
||||
if b.Period, ok = response[x][1].(float64); !ok {
|
||||
return Orderbook{}, errors.New("unable to type assert period")
|
||||
}
|
||||
orderID, ok := response[x][0].(float64)
|
||||
if !ok {
|
||||
return Orderbook{}, errors.New("unable to type assert orderID")
|
||||
}
|
||||
b.OrderID = int64(orderID)
|
||||
if b.Amount > 0 {
|
||||
o.Asks = append(o.Asks, b)
|
||||
} else {
|
||||
@@ -705,9 +721,18 @@ func (b *Bitfinex) GetOrderbook(ctx context.Context, symbol, precision string, l
|
||||
}
|
||||
} else {
|
||||
// Trading currency
|
||||
b.Amount = response[x][2].(float64)
|
||||
b.Price = response[x][1].(float64)
|
||||
b.OrderID = int64(response[x][0].(float64))
|
||||
var ok bool
|
||||
if b.Amount, ok = response[x][2].(float64); !ok {
|
||||
return Orderbook{}, errors.New("unable to type assert amount")
|
||||
}
|
||||
if b.Price, ok = response[x][1].(float64); !ok {
|
||||
return Orderbook{}, errors.New("unable to type assert price")
|
||||
}
|
||||
orderID, ok := response[x][0].(float64)
|
||||
if !ok {
|
||||
return Orderbook{}, errors.New("unable to type assert order ID")
|
||||
}
|
||||
b.OrderID = int64(orderID)
|
||||
if b.Amount > 0 {
|
||||
o.Bids = append(o.Bids, b)
|
||||
} else {
|
||||
@@ -721,10 +746,21 @@ func (b *Bitfinex) GetOrderbook(ctx context.Context, symbol, precision string, l
|
||||
var b Book
|
||||
if len(response[x]) > 3 {
|
||||
// Funding currency
|
||||
b.Amount = response[x][3].(float64)
|
||||
b.Count = int64(response[x][2].(float64))
|
||||
b.Period = response[x][1].(float64)
|
||||
b.Rate = response[x][0].(float64)
|
||||
var ok bool
|
||||
if b.Amount, ok = response[x][3].(float64); !ok {
|
||||
return Orderbook{}, errors.New("unable to type assert amount")
|
||||
}
|
||||
count, ok := response[x][2].(float64)
|
||||
if !ok {
|
||||
return Orderbook{}, errors.New("unable to type assert count")
|
||||
}
|
||||
b.Count = int64(count)
|
||||
if b.Period, ok = response[x][1].(float64); !ok {
|
||||
return Orderbook{}, errors.New("unable to type assert period")
|
||||
}
|
||||
if b.Rate, ok = response[x][0].(float64); !ok {
|
||||
return Orderbook{}, errors.New("unable to type assert rate")
|
||||
}
|
||||
if b.Amount > 0 {
|
||||
o.Asks = append(o.Asks, b)
|
||||
} else {
|
||||
@@ -733,9 +769,18 @@ func (b *Bitfinex) GetOrderbook(ctx context.Context, symbol, precision string, l
|
||||
}
|
||||
} else {
|
||||
// Trading currency
|
||||
b.Amount = response[x][2].(float64)
|
||||
b.Count = int64(response[x][1].(float64))
|
||||
b.Price = response[x][0].(float64)
|
||||
var ok bool
|
||||
if b.Amount, ok = response[x][2].(float64); !ok {
|
||||
return Orderbook{}, errors.New("unable to type assert amount")
|
||||
}
|
||||
count, ok := response[x][1].(float64)
|
||||
if !ok {
|
||||
return Orderbook{}, errors.New("unable to type assert count")
|
||||
}
|
||||
b.Count = int64(count)
|
||||
if b.Price, ok = response[x][0].(float64); !ok {
|
||||
return Orderbook{}, errors.New("unable to type assert price")
|
||||
}
|
||||
if b.Amount > 0 {
|
||||
o.Bids = append(o.Bids, b)
|
||||
} else {
|
||||
@@ -940,12 +985,34 @@ func (b *Bitfinex) GetLeaderboard(ctx context.Context, key, timeframe, symbol st
|
||||
|
||||
var result []LeaderboardEntry
|
||||
for x := range resp {
|
||||
r := resp[x].([]interface{})
|
||||
r, ok := resp[x].([]interface{})
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert leaderboard")
|
||||
}
|
||||
if len(r) < 10 {
|
||||
return nil, errors.New("unexpected leaderboard data length")
|
||||
}
|
||||
tm, ok := r[0].(float64)
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert time")
|
||||
}
|
||||
username, ok := r[2].(string)
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert username")
|
||||
}
|
||||
ranking, ok := r[3].(float64)
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert ranking")
|
||||
}
|
||||
value, ok := r[6].(float64)
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert value")
|
||||
}
|
||||
result = append(result, LeaderboardEntry{
|
||||
Timestamp: time.Unix(0, int64(r[0].(float64))*int64(time.Millisecond)),
|
||||
Username: r[2].(string),
|
||||
Ranking: int(r[3].(float64)),
|
||||
Value: r[6].(float64),
|
||||
Timestamp: time.UnixMilli(int64(tm)),
|
||||
Username: username,
|
||||
Ranking: int(ranking),
|
||||
Value: value,
|
||||
TwitterHandle: parseTwitterHandle(r[9]),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1067,9 +1067,9 @@ func TestWsAuth(t *testing.T) {
|
||||
}
|
||||
|
||||
func runAuth(t *testing.T) {
|
||||
t.Helper()
|
||||
setupWs()
|
||||
err := b.WsSendAuth()
|
||||
if err != nil {
|
||||
if err := b.WsSendAuth(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
timer := time.NewTimer(sharedtestvalues.WebsocketResponseDefaultTimeout)
|
||||
@@ -1118,8 +1118,7 @@ func TestWsCancelOrder(t *testing.T) {
|
||||
if !wsAuthExecuted {
|
||||
runAuth(t)
|
||||
}
|
||||
err := b.WsCancelOrder(1234)
|
||||
if err != nil {
|
||||
if err := b.WsCancelOrder(1234); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -1150,8 +1149,7 @@ func TestWsCancelAllOrders(t *testing.T) {
|
||||
if !wsAuthExecuted {
|
||||
runAuth(t)
|
||||
}
|
||||
err := b.WsCancelAllOrders()
|
||||
if err != nil {
|
||||
if err := b.WsCancelAllOrders(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -1198,8 +1196,7 @@ func TestWsCancelOffer(t *testing.T) {
|
||||
if !wsAuthExecuted {
|
||||
runAuth(t)
|
||||
}
|
||||
err := b.WsCancelOffer(1234)
|
||||
if err != nil {
|
||||
if err := b.WsCancelOffer(1234); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
@@ -159,7 +160,10 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
|
||||
)
|
||||
}
|
||||
case "auth":
|
||||
status := d["status"].(string)
|
||||
status, ok := d["status"].(string)
|
||||
if !ok {
|
||||
return errors.New("unable to type assert status")
|
||||
}
|
||||
if status == "OK" {
|
||||
b.Websocket.DataHandler <- d
|
||||
b.WsAddSubscriptionChannel(0, "account", "N/A")
|
||||
@@ -266,24 +270,27 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
|
||||
switch id := obSnapBundle[0].(type) {
|
||||
case []interface{}:
|
||||
for i := range obSnapBundle {
|
||||
data := obSnapBundle[i].([]interface{})
|
||||
data, ok := obSnapBundle[i].([]interface{})
|
||||
if !ok {
|
||||
return errors.New("type assertion failed for orderbok item data")
|
||||
}
|
||||
id, okAssert := data[0].(float64)
|
||||
if !okAssert {
|
||||
return errors.New("type assertion failed for orderbook item data")
|
||||
return errors.New("type assertion failed for orderbook id data")
|
||||
}
|
||||
pricePeriod, okAssert := data[1].(float64)
|
||||
if !okAssert {
|
||||
return errors.New("type assertion failed for orderbook item data")
|
||||
return errors.New("type assertion failed for orderbook price data")
|
||||
}
|
||||
rateAmount, okAssert := data[2].(float64)
|
||||
if !okAssert {
|
||||
return errors.New("type assertion failed for orderbook item data")
|
||||
return errors.New("type assertion failed for orderbook rate data")
|
||||
}
|
||||
if len(data) == 4 {
|
||||
fundingRate = true
|
||||
amount, okFunding := data[3].(float64)
|
||||
if !okFunding {
|
||||
return errors.New("type assertion failed for orderbook item data")
|
||||
return errors.New("type assertion failed for orderbook funding data")
|
||||
}
|
||||
newOrderbook = append(newOrderbook, WebsocketBook{
|
||||
ID: int64(id),
|
||||
@@ -297,26 +304,25 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
|
||||
Amount: rateAmount})
|
||||
}
|
||||
}
|
||||
err := b.WsInsertSnapshot(pair, chanAsset, newOrderbook, fundingRate)
|
||||
if err != nil {
|
||||
if err = b.WsInsertSnapshot(pair, chanAsset, newOrderbook, fundingRate); err != nil {
|
||||
return fmt.Errorf("inserting snapshot error: %s",
|
||||
err)
|
||||
}
|
||||
case float64:
|
||||
pricePeriod, okSnap := obSnapBundle[1].(float64)
|
||||
if !okSnap {
|
||||
return errors.New("type assertion failed for orderbook snapshot data")
|
||||
return errors.New("type assertion failed for orderbook price snapshot data")
|
||||
}
|
||||
amountRate, okSnap := obSnapBundle[2].(float64)
|
||||
if !okSnap {
|
||||
return errors.New("type assertion failed for orderbook snapshot data")
|
||||
return errors.New("type assertion failed for orderbook amount snapshot data")
|
||||
}
|
||||
if len(obSnapBundle) == 4 {
|
||||
fundingRate = true
|
||||
var amount float64
|
||||
amount, okSnap = obSnapBundle[3].(float64)
|
||||
if !okSnap {
|
||||
return errors.New("type assertion failed for orderbook snapshot data")
|
||||
return errors.New("type assertion failed for orderbook amount snapshot data")
|
||||
}
|
||||
newOrderbook = append(newOrderbook, WebsocketBook{
|
||||
ID: int64(id),
|
||||
@@ -330,8 +336,7 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
|
||||
Amount: amountRate})
|
||||
}
|
||||
|
||||
err := b.WsUpdateOrderbook(pair, chanAsset, newOrderbook, chanID, int64(sequenceNo), fundingRate)
|
||||
if err != nil {
|
||||
if err = b.WsUpdateOrderbook(pair, chanAsset, newOrderbook, chanID, int64(sequenceNo), fundingRate); err != nil {
|
||||
return fmt.Errorf("updating orderbook error: %s",
|
||||
err)
|
||||
}
|
||||
@@ -347,37 +352,73 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
|
||||
switch candleData := candleBundle[0].(type) {
|
||||
case []interface{}:
|
||||
for i := range candleBundle {
|
||||
element := candleBundle[i].([]interface{})
|
||||
b.Websocket.DataHandler <- stream.KlineData{
|
||||
Timestamp: time.Unix(0, int64(element[0].(float64))*int64(time.Millisecond)),
|
||||
Exchange: b.Name,
|
||||
AssetType: chanAsset,
|
||||
Pair: pair,
|
||||
OpenPrice: element[1].(float64),
|
||||
ClosePrice: element[2].(float64),
|
||||
HighPrice: element[3].(float64),
|
||||
LowPrice: element[4].(float64),
|
||||
Volume: element[5].(float64),
|
||||
var element []interface{}
|
||||
element, ok = candleBundle[i].([]interface{})
|
||||
if !ok {
|
||||
return errors.New("type assertion for element data")
|
||||
}
|
||||
if len(element) < 6 {
|
||||
return errors.New("invalid candleBundle length")
|
||||
}
|
||||
var klineData stream.KlineData
|
||||
if klineData.Timestamp, err = convert.TimeFromUnixTimestampFloat(element[0]); err != nil {
|
||||
return fmt.Errorf("unable to convert timestamp: %w", err)
|
||||
}
|
||||
if klineData.OpenPrice, ok = element[1].(float64); !ok {
|
||||
return errors.New("unable to type assert OpenPrice")
|
||||
}
|
||||
if klineData.ClosePrice, ok = element[2].(float64); !ok {
|
||||
return errors.New("unable to type assert ClosePrice")
|
||||
}
|
||||
if klineData.HighPrice, ok = element[3].(float64); !ok {
|
||||
return errors.New("unable to type assert HighPrice")
|
||||
}
|
||||
if klineData.LowPrice, ok = element[4].(float64); !ok {
|
||||
return errors.New("unable to type assert LowPrice")
|
||||
}
|
||||
if klineData.Volume, ok = element[5].(float64); !ok {
|
||||
return errors.New("unable to type assert volume")
|
||||
}
|
||||
klineData.Exchange = b.Name
|
||||
klineData.AssetType = chanAsset
|
||||
klineData.Pair = pair
|
||||
b.Websocket.DataHandler <- klineData
|
||||
}
|
||||
|
||||
case float64:
|
||||
b.Websocket.DataHandler <- stream.KlineData{
|
||||
Timestamp: time.Unix(0, int64(candleData)*int64(time.Millisecond)),
|
||||
Exchange: b.Name,
|
||||
AssetType: chanAsset,
|
||||
Pair: pair,
|
||||
OpenPrice: candleBundle[1].(float64),
|
||||
ClosePrice: candleBundle[2].(float64),
|
||||
HighPrice: candleBundle[3].(float64),
|
||||
LowPrice: candleBundle[4].(float64),
|
||||
Volume: candleBundle[5].(float64),
|
||||
if len(candleBundle) < 6 {
|
||||
return errors.New("invalid candleBundle length")
|
||||
}
|
||||
var klineData stream.KlineData
|
||||
if klineData.Timestamp, err = convert.TimeFromUnixTimestampFloat(candleData); err != nil {
|
||||
return fmt.Errorf("unable to convert timestamp: %w", err)
|
||||
}
|
||||
if klineData.OpenPrice, ok = candleBundle[1].(float64); !ok {
|
||||
return errors.New("unable to type assert OpenPrice")
|
||||
}
|
||||
if klineData.ClosePrice, ok = candleBundle[2].(float64); !ok {
|
||||
return errors.New("unable to type assert ClosePrice")
|
||||
}
|
||||
if klineData.HighPrice, ok = candleBundle[3].(float64); !ok {
|
||||
return errors.New("unable to type assert HighPrice")
|
||||
}
|
||||
if klineData.LowPrice, ok = candleBundle[4].(float64); !ok {
|
||||
return errors.New("unable to type assert LowPrice")
|
||||
}
|
||||
if klineData.Volume, ok = candleBundle[5].(float64); !ok {
|
||||
return errors.New("unable to type assert volume")
|
||||
}
|
||||
klineData.Exchange = b.Name
|
||||
klineData.AssetType = chanAsset
|
||||
klineData.Pair = pair
|
||||
b.Websocket.DataHandler <- klineData
|
||||
}
|
||||
}
|
||||
return nil
|
||||
case wsTicker:
|
||||
tickerData := d[1].([]interface{})
|
||||
tickerData, ok := d[1].([]interface{})
|
||||
if !ok {
|
||||
return errors.New("type assertion for tickerData")
|
||||
}
|
||||
if len(tickerData) == 10 {
|
||||
b.Websocket.DataHandler <- &ticker.Price{
|
||||
ExchangeName: b.Name,
|
||||
@@ -421,9 +462,15 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
|
||||
var tradeHolder []WebsocketTrade
|
||||
switch len(d) {
|
||||
case 2:
|
||||
snapshot := d[1].([]interface{})
|
||||
snapshot, ok := d[1].([]interface{})
|
||||
if !ok {
|
||||
return errors.New("unable to type assert snapshot data")
|
||||
}
|
||||
for i := range snapshot {
|
||||
elem := snapshot[i].([]interface{})
|
||||
elem, ok := snapshot[i].([]interface{})
|
||||
if !ok {
|
||||
return errors.New("unable to type assert snapshot element data")
|
||||
}
|
||||
if len(elem) == 5 {
|
||||
tradeHolder = append(tradeHolder, WebsocketTrade{
|
||||
ID: int64(elem[0].(float64)),
|
||||
@@ -446,7 +493,10 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
|
||||
d[1].(string) != wsTradeExecutionUpdate {
|
||||
return nil
|
||||
}
|
||||
data := d[2].([]interface{})
|
||||
data, ok := d[2].([]interface{})
|
||||
if !ok {
|
||||
return errors.New("data type assertion error")
|
||||
}
|
||||
if len(data) == 5 {
|
||||
tradeHolder = append(tradeHolder, WebsocketTrade{
|
||||
ID: int64(data[0].(float64)),
|
||||
@@ -479,7 +529,7 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
|
||||
trades = append(trades, trade.Data{
|
||||
TID: strconv.FormatInt(tradeHolder[i].ID, 10),
|
||||
CurrencyPair: pair,
|
||||
Timestamp: time.Unix(0, tradeHolder[i].Timestamp*int64(time.Millisecond)),
|
||||
Timestamp: time.UnixMilli(tradeHolder[i].Timestamp),
|
||||
Price: price,
|
||||
Amount: newAmount,
|
||||
Exchange: b.Name,
|
||||
@@ -496,9 +546,15 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
|
||||
case wsHeartbeat, pong:
|
||||
return nil
|
||||
case wsNotification:
|
||||
notification := d[2].([]interface{})
|
||||
notification, ok := d[2].([]interface{})
|
||||
if !ok {
|
||||
return errors.New("unable to type assert notification data")
|
||||
}
|
||||
if data, ok := notification[4].([]interface{}); ok {
|
||||
channelName := notification[1].(string)
|
||||
channelName, ok := notification[1].(string)
|
||||
if !ok {
|
||||
return errors.New("unable to type assert channelName")
|
||||
}
|
||||
switch {
|
||||
case strings.Contains(channelName, wsFundingOrderNewRequest),
|
||||
strings.Contains(channelName, wsFundingOrderUpdateRequest),
|
||||
@@ -527,18 +583,26 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
|
||||
respRaw)
|
||||
}
|
||||
}
|
||||
if notification[5] != nil &&
|
||||
strings.EqualFold(notification[5].(string), wsError) {
|
||||
return fmt.Errorf("%s - Error %s",
|
||||
b.Name,
|
||||
notification[6].(string))
|
||||
if notification[5] != nil {
|
||||
if wsErr, ok := notification[5].(string); ok {
|
||||
if strings.EqualFold(wsErr, wsError) {
|
||||
if errMsg, ok := notification[6].(string); ok {
|
||||
return fmt.Errorf("%s - Error %s",
|
||||
b.Name,
|
||||
errMsg)
|
||||
}
|
||||
return fmt.Errorf("%s - unhandled error message: %v", b.Name,
|
||||
notification[6])
|
||||
}
|
||||
}
|
||||
}
|
||||
case wsOrderSnapshot:
|
||||
if snapBundle, ok := d[2].([]interface{}); ok && len(snapBundle) > 0 {
|
||||
if _, ok := snapBundle[0].([]interface{}); ok {
|
||||
for i := range snapBundle {
|
||||
positionData := snapBundle[i].([]interface{})
|
||||
b.wsHandleOrder(positionData)
|
||||
if positionData, ok := snapBundle[i].([]interface{}); ok {
|
||||
b.wsHandleOrder(positionData)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -551,7 +615,10 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
|
||||
if snapBundle, ok := d[2].([]interface{}); ok && len(snapBundle) > 0 {
|
||||
if _, ok := snapBundle[0].([]interface{}); ok {
|
||||
for i := range snapBundle {
|
||||
positionData := snapBundle[i].([]interface{})
|
||||
positionData, ok := snapBundle[i].([]interface{})
|
||||
if !ok {
|
||||
return errors.New("unable to type assert wsPositionSnapshot positionData")
|
||||
}
|
||||
position := WebsocketPosition{
|
||||
Pair: positionData[0].(string),
|
||||
Status: positionData[1].(string),
|
||||
@@ -606,7 +673,10 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
|
||||
if snapBundle, ok := d[2].([]interface{}); ok && len(snapBundle) > 0 {
|
||||
if _, ok := snapBundle[0].([]interface{}); ok {
|
||||
for i := range snapBundle {
|
||||
data := snapBundle[i].([]interface{})
|
||||
data, ok := snapBundle[i].([]interface{})
|
||||
if !ok {
|
||||
return errors.New("unable to type assert wsFundingOrderSnapshot snapBundle data")
|
||||
}
|
||||
offer := WsFundingOffer{
|
||||
ID: int64(data[0].(float64)),
|
||||
Symbol: data[1].(string),
|
||||
@@ -639,7 +709,10 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
|
||||
if snapBundle, ok := d[2].([]interface{}); ok && len(snapBundle) > 0 {
|
||||
if _, ok := snapBundle[0].([]interface{}); ok {
|
||||
for i := range snapBundle {
|
||||
data := snapBundle[i].([]interface{})
|
||||
data, ok := snapBundle[i].([]interface{})
|
||||
if !ok {
|
||||
return errors.New("unable to type assert wsFundingCreditSnapshot snapBundle data")
|
||||
}
|
||||
credit := WsCredit{
|
||||
ID: int64(data[0].(float64)),
|
||||
Symbol: data[1].(string),
|
||||
@@ -695,7 +768,10 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
|
||||
if snapBundle, ok := d[2].([]interface{}); ok && len(snapBundle) > 0 {
|
||||
if _, ok := snapBundle[0].([]interface{}); ok {
|
||||
for i := range snapBundle {
|
||||
data := snapBundle[i].([]interface{})
|
||||
data, ok := snapBundle[i].([]interface{})
|
||||
if !ok {
|
||||
return errors.New("unable to type assert wsFundingLoanSnapshot snapBundle data")
|
||||
}
|
||||
credit := WsCredit{
|
||||
ID: int64(data[0].(float64)),
|
||||
Symbol: data[1].(string),
|
||||
@@ -749,10 +825,13 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
|
||||
if snapBundle, ok := d[2].([]interface{}); ok && len(snapBundle) > 0 {
|
||||
if _, ok := snapBundle[0].([]interface{}); ok {
|
||||
for i := range snapBundle {
|
||||
data := snapBundle[i].([]interface{})
|
||||
data, ok := snapBundle[i].([]interface{})
|
||||
if !ok {
|
||||
return errors.New("unable to type assert wsWalletSnapshot snapBundle data")
|
||||
}
|
||||
var balanceAvailable float64
|
||||
if _, ok := data[4].(float64); ok {
|
||||
balanceAvailable = data[4].(float64)
|
||||
if v, ok := data[4].(float64); ok {
|
||||
balanceAvailable = v
|
||||
}
|
||||
wallet := WsWallet{
|
||||
Type: data[0].(string),
|
||||
@@ -769,8 +848,8 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
|
||||
case wsWalletUpdate:
|
||||
if data, ok := d[2].([]interface{}); ok && len(data) > 0 {
|
||||
var balanceAvailable float64
|
||||
if _, ok := data[4].(float64); ok {
|
||||
balanceAvailable = data[4].(float64)
|
||||
if v, ok := data[4].(float64); ok {
|
||||
balanceAvailable = v
|
||||
}
|
||||
b.Websocket.DataHandler <- WsWallet{
|
||||
Type: data[0].(string),
|
||||
@@ -791,7 +870,10 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
|
||||
if data, ok := d[2].([]interface{}); ok && len(data) > 0 {
|
||||
if data[0].(string) == "base" {
|
||||
if infoBase, ok := d[2].([]interface{}); ok && len(infoBase) > 0 {
|
||||
baseData := data[1].([]interface{})
|
||||
baseData, ok := data[1].([]interface{})
|
||||
if !ok {
|
||||
return errors.New("unable to type assert wsMarginInfoUpdate baseData")
|
||||
}
|
||||
b.Websocket.DataHandler <- WsMarginInfoBase{
|
||||
UserProfitLoss: baseData[0].(float64),
|
||||
UserSwaps: baseData[1].(float64),
|
||||
@@ -804,7 +886,10 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
|
||||
case wsFundingInfoUpdate:
|
||||
if data, ok := d[2].([]interface{}); ok && len(data) > 0 {
|
||||
if data[0].(string) == "sym" {
|
||||
symbolData := data[1].([]interface{})
|
||||
symbolData, ok := data[1].([]interface{})
|
||||
if !ok {
|
||||
return errors.New("unable to type assert wsFundingInfoUpdate symbolData")
|
||||
}
|
||||
b.Websocket.DataHandler <- WsFundingInfo{
|
||||
YieldLoan: symbolData[0].(float64),
|
||||
YieldLend: symbolData[1].(float64),
|
||||
@@ -839,53 +924,86 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
|
||||
|
||||
func (b *Bitfinex) wsHandleFundingOffer(data []interface{}) {
|
||||
var fo WsFundingOffer
|
||||
|
||||
if data[0] != nil {
|
||||
fo.ID = int64(data[0].(float64))
|
||||
if id, ok := data[0].(float64); ok {
|
||||
fo.ID = int64(id)
|
||||
}
|
||||
}
|
||||
if data[1] != nil {
|
||||
fo.Symbol = data[1].(string)[1:]
|
||||
if sym, ok := data[1].(string); ok {
|
||||
fo.Symbol = sym[1:]
|
||||
}
|
||||
}
|
||||
if data[2] != nil {
|
||||
fo.Created = int64(data[2].(float64))
|
||||
if created, ok := data[2].(float64); ok {
|
||||
fo.Created = int64(created)
|
||||
}
|
||||
}
|
||||
if data[3] != nil {
|
||||
fo.Updated = int64(data[0].(float64))
|
||||
if updated, ok := data[3].(float64); ok {
|
||||
fo.Updated = int64(updated)
|
||||
}
|
||||
}
|
||||
if data[15] != nil {
|
||||
fo.Period = int64(data[15].(float64))
|
||||
if period, ok := data[15].(float64); ok {
|
||||
fo.Period = int64(period)
|
||||
}
|
||||
}
|
||||
if data[4] != nil {
|
||||
fo.Amount = data[4].(float64)
|
||||
if amount, ok := data[4].(float64); ok {
|
||||
fo.Amount = amount
|
||||
}
|
||||
}
|
||||
if data[5] != nil {
|
||||
fo.OriginalAmount = data[5].(float64)
|
||||
if origAmount, ok := data[5].(float64); ok {
|
||||
fo.OriginalAmount = origAmount
|
||||
}
|
||||
}
|
||||
if data[6] != nil {
|
||||
fo.Type = data[6].(string)
|
||||
if fType, ok := data[6].(string); ok {
|
||||
fo.Type = fType
|
||||
}
|
||||
}
|
||||
if data[9] != nil {
|
||||
fo.Flags = data[9].(float64)
|
||||
if flags, ok := data[9].(float64); ok {
|
||||
fo.Flags = flags
|
||||
}
|
||||
}
|
||||
if data[9] != nil {
|
||||
fo.Status = data[10].(string)
|
||||
if data[9] != nil && data[10] != nil {
|
||||
if status, ok := data[10].(string); ok {
|
||||
fo.Status = status
|
||||
}
|
||||
}
|
||||
if data[9] != nil {
|
||||
fo.Rate = data[14].(float64)
|
||||
if data[9] != nil && data[14] != nil {
|
||||
if rate, ok := data[14].(float64); ok {
|
||||
fo.Rate = rate
|
||||
}
|
||||
}
|
||||
if data[16] != nil {
|
||||
fo.Notify = data[16].(float64) == 1
|
||||
if notify, ok := data[16].(float64); ok {
|
||||
fo.Notify = notify == 1
|
||||
}
|
||||
}
|
||||
if data[17] != nil {
|
||||
fo.Hidden = data[17].(float64) == 1
|
||||
if hidden, ok := data[17].(float64); ok {
|
||||
fo.Hidden = hidden == 1
|
||||
}
|
||||
}
|
||||
if data[18] != nil {
|
||||
fo.Insure = data[18].(float64) == 1
|
||||
if insure, ok := data[18].(float64); ok {
|
||||
fo.Insure = insure == 1
|
||||
}
|
||||
}
|
||||
if data[19] != nil {
|
||||
fo.Renew = data[19].(float64) == 1
|
||||
if renew, ok := data[19].(float64); ok {
|
||||
fo.Renew = renew == 1
|
||||
}
|
||||
}
|
||||
if data[20] != nil {
|
||||
fo.RateReal = data[20].(float64)
|
||||
if rateReal, ok := data[20].(float64); ok {
|
||||
fo.RateReal = rateReal
|
||||
}
|
||||
}
|
||||
|
||||
b.Websocket.DataHandler <- fo
|
||||
@@ -896,54 +1014,74 @@ func (b *Bitfinex) wsHandleOrder(data []interface{}) {
|
||||
var err error
|
||||
od.Exchange = b.Name
|
||||
if data[0] != nil {
|
||||
od.ID = strconv.FormatFloat(data[0].(float64), 'f', -1, 64)
|
||||
if id, ok := data[0].(float64); ok {
|
||||
od.ID = strconv.FormatFloat(id, 'f', -1, 64)
|
||||
}
|
||||
}
|
||||
if data[16] != nil {
|
||||
od.Price = data[16].(float64)
|
||||
if price, ok := data[16].(float64); ok {
|
||||
od.Price = price
|
||||
}
|
||||
}
|
||||
if data[7] != nil {
|
||||
od.Amount = data[7].(float64)
|
||||
if amount, ok := data[7].(float64); ok {
|
||||
od.Amount = amount
|
||||
}
|
||||
}
|
||||
if data[6] != nil {
|
||||
od.RemainingAmount = data[6].(float64)
|
||||
if remainingAmount, ok := data[6].(float64); ok {
|
||||
od.RemainingAmount = remainingAmount
|
||||
}
|
||||
}
|
||||
if data[7] != nil && data[6] != nil {
|
||||
od.ExecutedAmount = data[7].(float64) - data[6].(float64)
|
||||
if executedAmount, ok := data[7].(float64); ok {
|
||||
od.ExecutedAmount = executedAmount - od.RemainingAmount
|
||||
}
|
||||
}
|
||||
if data[4] != nil {
|
||||
od.Date = time.Unix(int64(data[4].(float64))*1000, 0)
|
||||
if date, ok := data[4].(float64); ok {
|
||||
od.Date = time.Unix(int64(date)*1000, 0)
|
||||
}
|
||||
}
|
||||
if data[5] != nil {
|
||||
od.LastUpdated = time.Unix(int64(data[5].(float64))*1000, 0)
|
||||
if lastUpdated, ok := data[5].(float64); ok {
|
||||
od.LastUpdated = time.Unix(int64(lastUpdated)*1000, 0)
|
||||
}
|
||||
}
|
||||
if data[2] != nil {
|
||||
od.Pair, od.AssetType, err = b.GetRequestFormattedPairAndAssetType(data[3].(string)[1:])
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- err
|
||||
return
|
||||
if p, ok := data[3].(string); ok {
|
||||
od.Pair, od.AssetType, err = b.GetRequestFormattedPairAndAssetType(p[1:])
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
if data[8] != nil {
|
||||
oType, err := order.StringToOrderType(data[8].(string))
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- order.ClassificationError{
|
||||
Exchange: b.Name,
|
||||
OrderID: od.ID,
|
||||
Err: err,
|
||||
if ordType, ok := data[8].(string); ok {
|
||||
oType, err := order.StringToOrderType(ordType)
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- order.ClassificationError{
|
||||
Exchange: b.Name,
|
||||
OrderID: od.ID,
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
od.Type = oType
|
||||
}
|
||||
od.Type = oType
|
||||
}
|
||||
if data[13] != nil {
|
||||
oStatus, err := order.StringToOrderStatus(data[13].(string))
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- order.ClassificationError{
|
||||
Exchange: b.Name,
|
||||
OrderID: od.ID,
|
||||
Err: err,
|
||||
if ordStatus, ok := data[13].(string); ok {
|
||||
oStatus, err := order.StringToOrderStatus(ordStatus)
|
||||
if err != nil {
|
||||
b.Websocket.DataHandler <- order.ClassificationError{
|
||||
Exchange: b.Name,
|
||||
OrderID: od.ID,
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
od.Status = oStatus
|
||||
}
|
||||
od.Status = oStatus
|
||||
}
|
||||
b.Websocket.DataHandler <- &od
|
||||
}
|
||||
@@ -1242,19 +1380,45 @@ func (b *Bitfinex) WsNewOrder(data *WsNewOrderRequest) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
responseDataDetail := respData[2].([]interface{})
|
||||
responseOrderDetail := responseDataDetail[4].([]interface{})
|
||||
var orderID string
|
||||
if responseOrderDetail[0] != nil && responseOrderDetail[0].(float64) > 0 {
|
||||
orderID = strconv.FormatFloat(responseOrderDetail[0].(float64), 'f', -1, 64)
|
||||
}
|
||||
errCode := responseDataDetail[6].(string)
|
||||
errorMessage := responseDataDetail[7].(string)
|
||||
|
||||
if len(respData) < 3 {
|
||||
return "", errors.New("unexpected respData length")
|
||||
}
|
||||
responseDataDetail, ok := respData[2].([]interface{})
|
||||
if !ok {
|
||||
return "", errors.New("unable to type assert respData")
|
||||
}
|
||||
|
||||
if len(responseDataDetail) < 4 {
|
||||
return "", errors.New("invalid responseDataDetail length")
|
||||
}
|
||||
|
||||
responseOrderDetail, ok := responseDataDetail[4].([]interface{})
|
||||
if !ok {
|
||||
return "", errors.New("unable to type assert responseOrderDetail")
|
||||
}
|
||||
var orderID string
|
||||
if responseOrderDetail[0] != nil {
|
||||
if ordID, ordOK := responseOrderDetail[0].(float64); ordOK && ordID > 0 {
|
||||
orderID = strconv.FormatFloat(ordID, 'f', -1, 64)
|
||||
}
|
||||
}
|
||||
var errorMessage, errCode string
|
||||
if len(responseDataDetail) > 6 {
|
||||
errCode, ok = responseDataDetail[6].(string)
|
||||
if !ok {
|
||||
return "", errors.New("unable to type assert errCode")
|
||||
}
|
||||
}
|
||||
if len(responseDataDetail) > 7 {
|
||||
errorMessage, ok = responseDataDetail[7].(string)
|
||||
if !ok {
|
||||
return "", errors.New("unable to type assert errorMessage")
|
||||
}
|
||||
}
|
||||
if strings.EqualFold(errCode, wsError) {
|
||||
return orderID, errors.New(b.Name + " - " + errCode + ": " + errorMessage)
|
||||
}
|
||||
|
||||
return orderID, nil
|
||||
}
|
||||
|
||||
@@ -1274,13 +1438,29 @@ func (b *Bitfinex) WsModifyOrder(data *WsUpdateOrderRequest) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
responseOrderData := responseData[2].([]interface{})
|
||||
errCode := responseOrderData[6].(string)
|
||||
errorMessage := responseOrderData[7].(string)
|
||||
if len(responseData) < 3 {
|
||||
return errors.New("unexpected responseData length")
|
||||
}
|
||||
responseOrderData, ok := responseData[2].([]interface{})
|
||||
if !ok {
|
||||
return errors.New("unable to type assert responseOrderData")
|
||||
}
|
||||
var errorMessage, errCode string
|
||||
if len(responseOrderData) > 6 {
|
||||
errCode, ok = responseOrderData[6].(string)
|
||||
if !ok {
|
||||
return errors.New("unable to type assert errCode")
|
||||
}
|
||||
}
|
||||
if len(responseOrderData) > 7 {
|
||||
errorMessage, ok = responseOrderData[7].(string)
|
||||
if !ok {
|
||||
return errors.New("unable to type assert errorMessage")
|
||||
}
|
||||
}
|
||||
if strings.EqualFold(errCode, wsError) {
|
||||
return errors.New(b.Name + " - " + errCode + ": " + errorMessage)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1311,13 +1491,29 @@ func (b *Bitfinex) WsCancelOrder(orderID int64) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
responseOrderData := responseData[2].([]interface{})
|
||||
errCode := responseOrderData[6].(string)
|
||||
errorMessage := responseOrderData[7].(string)
|
||||
if len(responseData) < 3 {
|
||||
return errors.New("unexpected responseData length")
|
||||
}
|
||||
responseOrderData, ok := responseData[2].([]interface{})
|
||||
if !ok {
|
||||
return errors.New("unable to type assert responseOrderData")
|
||||
}
|
||||
var errorMessage, errCode string
|
||||
if len(responseOrderData) > 6 {
|
||||
errCode, ok = responseOrderData[6].(string)
|
||||
if !ok {
|
||||
return errors.New("unable to type assert errCode")
|
||||
}
|
||||
}
|
||||
if len(responseOrderData) > 7 {
|
||||
errorMessage, ok = responseOrderData[7].(string)
|
||||
if !ok {
|
||||
return errors.New("unable to type assert errorMessage")
|
||||
}
|
||||
}
|
||||
if strings.EqualFold(errCode, wsError) {
|
||||
return errors.New(b.Name + " - " + errCode + ": " + errorMessage)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1352,11 +1548,25 @@ func (b *Bitfinex) WsCancelOffer(orderID int64) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
responseOrderData := responseData[2].([]interface{})
|
||||
errCode := responseOrderData[6].(string)
|
||||
var errorMessage string
|
||||
if responseOrderData[7] != nil {
|
||||
errorMessage = responseOrderData[7].(string)
|
||||
if len(responseData) < 3 {
|
||||
return errors.New("unexpected responseData length")
|
||||
}
|
||||
responseOrderData, ok := responseData[2].([]interface{})
|
||||
if !ok {
|
||||
return errors.New("unable to type assert responseOrderData")
|
||||
}
|
||||
var errorMessage, errCode string
|
||||
if len(responseOrderData) > 6 {
|
||||
errCode, ok = responseOrderData[6].(string)
|
||||
if !ok {
|
||||
return errors.New("unable to type assert errCode")
|
||||
}
|
||||
}
|
||||
if len(responseOrderData) > 7 {
|
||||
errorMessage, ok = responseOrderData[7].(string)
|
||||
if !ok {
|
||||
return errors.New("unable to type assert errorMessage")
|
||||
}
|
||||
}
|
||||
if strings.EqualFold(errCode, wsError) {
|
||||
return errors.New(b.Name + " - " + errCode + ": " + errorMessage)
|
||||
|
||||
@@ -365,8 +365,7 @@ func (b *Bitfinex) UpdateTickers(ctx context.Context, a asset.Item) error {
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (b *Bitfinex) UpdateTicker(ctx context.Context, p currency.Pair, a asset.Item) (*ticker.Price, error) {
|
||||
err := b.UpdateTickers(ctx, a)
|
||||
if err != nil {
|
||||
if err := b.UpdateTickers(ctx, a); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ticker.GetTicker(b.Name, p, a)
|
||||
@@ -567,7 +566,7 @@ allTrades:
|
||||
return nil, err
|
||||
}
|
||||
for i := range tradeData {
|
||||
tradeTS := time.Unix(0, tradeData[i].Timestamp*int64(time.Millisecond))
|
||||
tradeTS := time.UnixMilli(tradeData[i].Timestamp)
|
||||
if tradeTS.Before(timestampStart) && !timestampStart.IsZero() {
|
||||
break allTrades
|
||||
}
|
||||
@@ -579,7 +578,7 @@ allTrades:
|
||||
AssetType: assetType,
|
||||
Price: tradeData[i].Price,
|
||||
Amount: tradeData[i].Amount,
|
||||
Timestamp: time.Unix(0, tradeData[i].Timestamp*int64(time.Millisecond)),
|
||||
Timestamp: time.UnixMilli(tradeData[i].Timestamp),
|
||||
})
|
||||
if i == len(tradeData)-1 {
|
||||
if ts.Equal(tradeTS) {
|
||||
|
||||
Reference in New Issue
Block a user