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:
Adrian Gallagher
2021-10-14 16:38:53 +11:00
committed by GitHub
parent 0a91af0f2e
commit f0d45aa1d2
194 changed files with 1506 additions and 1233 deletions

View File

@@ -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]),
})
}

View File

@@ -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)
}
}

View File

@@ -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)

View File

@@ -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) {