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

@@ -10,8 +10,10 @@ import (
"strconv"
"strings"
"sync"
"time"
"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"
@@ -214,46 +216,59 @@ func (k *Kraken) GetOHLC(ctx context.Context, symbol currency.Pair, interval str
Data map[string]interface{} `json:"result"`
}
var OHLC []OpenHighLowClose
var result Response
path := fmt.Sprintf("/%s/public/%s?%s", krakenAPIVersion, krakenOHLC, values.Encode())
err = k.SendHTTPRequest(ctx, exchange.RestSpot, path, &result)
if err != nil {
return OHLC, err
return nil, err
}
if len(result.Error) != 0 {
return OHLC, fmt.Errorf("getOHLC error: %s", result.Error)
return nil, fmt.Errorf("getOHLC error: %s", result.Error)
}
_, ok := result.Data[translatedAsset].([]interface{})
ohlcData, ok := result.Data[translatedAsset].([]interface{})
if !ok {
return nil, errors.New("invalid data returned")
}
for _, y := range result.Data[translatedAsset].([]interface{}) {
o := OpenHighLowClose{}
for i, x := range y.([]interface{}) {
switch i {
case 0:
o.Time = x.(float64)
case 1:
o.Open, _ = strconv.ParseFloat(x.(string), 64)
case 2:
o.High, _ = strconv.ParseFloat(x.(string), 64)
case 3:
o.Low, _ = strconv.ParseFloat(x.(string), 64)
case 4:
o.Close, _ = strconv.ParseFloat(x.(string), 64)
case 5:
o.VolumeWeightedAveragePrice, _ = strconv.ParseFloat(x.(string), 64)
case 6:
o.Volume, _ = strconv.ParseFloat(x.(string), 64)
case 7:
o.Count = x.(float64)
}
var OHLC []OpenHighLowClose
for x := range ohlcData {
subData, ok := ohlcData[x].([]interface{})
if !ok {
return nil, errors.New("unable to type assert subData")
}
if len(subData) < 8 {
return nil, errors.New("unexpected data length returned")
}
var o OpenHighLowClose
if o.Time, ok = subData[0].(float64); !ok {
return nil, errors.New("unable to type assert time")
}
if o.Open, err = convert.FloatFromString(subData[1]); err != nil {
return nil, err
}
if o.High, err = convert.FloatFromString(subData[2]); err != nil {
return nil, err
}
if o.Low, err = convert.FloatFromString(subData[3]); err != nil {
return nil, err
}
if o.Close, err = convert.FloatFromString(subData[4]); err != nil {
return nil, err
}
if o.VolumeWeightedAveragePrice, err = convert.FloatFromString(subData[5]); err != nil {
return nil, err
}
if o.Volume, err = convert.FloatFromString(subData[6]); err != nil {
return nil, err
}
if o.Count, ok = subData[7].(float64); !ok {
return nil, errors.New("unable to type assert count")
}
OHLC = append(OHLC, o)
}
@@ -280,24 +295,40 @@ func (k *Kraken) GetDepth(ctx context.Context, symbol currency.Pair) (Orderbook,
return orderBook, fmt.Errorf("%s GetDepth result is nil", k.Name)
}
data := result.(map[string]interface{})
if data["result"] == nil {
data, ok := result.(map[string]interface{})
if !ok {
return orderBook, errors.New("unable to type assert data")
}
orderbookData, ok := data["result"].(map[string]interface{})
if !ok {
return orderBook, fmt.Errorf("%s GetDepth data[result] is nil", k.Name)
}
orderbookData := data["result"].(map[string]interface{})
var bidsData []interface{}
var asksData []interface{}
for _, y := range orderbookData {
yData := y.(map[string]interface{})
bidsData = yData["bids"].([]interface{})
asksData = yData["asks"].([]interface{})
yData, ok := y.(map[string]interface{})
if !ok {
return orderBook, errors.New("unable to type assert yData")
}
if bidsData, ok = yData["bids"].([]interface{}); !ok {
return orderBook, errors.New("unable to type assert bidsData")
}
if asksData, ok = yData["asks"].([]interface{}); !ok {
return orderBook, errors.New("unable to type assert asksData")
}
}
processOrderbook := func(data []interface{}) ([]OrderbookBase, error) {
var result []OrderbookBase
for x := range data {
entry := data[x].([]interface{})
entry, ok := data[x].([]interface{})
if !ok {
return nil, errors.New("unable to type assert entry")
}
if len(entry) < 2 {
return nil, errors.New("unexpected entry length")
}
price, priceErr := strconv.ParseFloat(entry[0].(string), 64)
if priceErr != nil {
@@ -439,30 +470,48 @@ func (k *Kraken) GetSpread(ctx context.Context, symbol currency.Pair) ([]Spread,
}
values.Set("pair", symbolValue)
var peanutButter []Spread
var response interface{}
resp := struct {
SpreadData map[string]interface{} `json:"result"`
}{}
path := fmt.Sprintf("/%s/public/%s?%s", krakenAPIVersion, krakenSpread, values.Encode())
err = k.SendHTTPRequest(ctx, exchange.RestSpot, path, &response)
err = k.SendHTTPRequest(ctx, exchange.RestSpot, path, &resp)
if err != nil {
return peanutButter, err
return nil, err
}
data := response.(map[string]interface{})
result := data["result"].(map[string]interface{})
data, ok := resp.SpreadData[symbolValue]
if !ok {
return nil, fmt.Errorf("unable to find %s in spread data", symbolValue)
}
for _, x := range result[symbolValue].([]interface{}) {
s := Spread{}
for i, y := range x.([]interface{}) {
switch i {
case 0:
s.Time = y.(float64)
case 1:
s.Bid, _ = strconv.ParseFloat(y.(string), 64)
case 2:
s.Ask, _ = strconv.ParseFloat(y.(string), 64)
}
spreadData, ok := data.([]interface{})
if !ok {
return nil, errors.New("unable to type assert spreadData")
}
var peanutButter []Spread
for x := range spreadData {
subData, ok := spreadData[x].([]interface{})
if !ok {
return nil, errors.New("unable to type assert subData")
}
if len(subData) < 3 {
return nil, errors.New("unexpected data length")
}
var s Spread
timeData, ok := subData[0].(float64)
if !ok {
return nil, errors.New("unable to type assert timeData")
}
s.Time = time.Unix(int64(timeData), 0)
if s.Bid, err = convert.FloatFromString(subData[1]); err != nil {
return nil, err
}
if s.Ask, err = convert.FloatFromString(subData[2]); err != nil {
return nil, err
}
peanutButter = append(peanutButter, s)
}
@@ -1203,8 +1252,7 @@ func (a *assetTranslatorStore) Seed(orig, alt string) {
a.Assets = make(map[string]string)
}
_, ok := a.Assets[orig]
if ok {
if _, ok := a.Assets[orig]; ok {
a.l.Unlock()
return
}

View File

@@ -275,7 +275,7 @@ func (k *Kraken) SendFuturesAuthRequest(ctx context.Context, method, path string
interim := json.RawMessage{}
newRequest := func() (*request.Item, error) {
nonce := strconv.FormatInt(time.Now().UnixNano()/1000000, 10)
nonce := strconv.FormatInt(time.Now().UnixMilli(), 10)
reqData := ""
if len(data) > 0 {
temp, err := json.Marshal(data)

View File

@@ -1128,6 +1128,7 @@ func TestWithdrawCancel(t *testing.T) {
// ---------------------------- Websocket tests -----------------------------------------
func setupWsTests(t *testing.T) {
t.Helper()
if wsSetupRan {
return
}
@@ -1205,16 +1206,14 @@ func TestWsAddOrder(t *testing.T) {
func TestWsCancelOrder(t *testing.T) {
setupWsTests(t)
err := k.wsCancelOrders([]string{"1337"})
if err != nil {
if err := k.wsCancelOrders([]string{"1337"}); err != nil {
t.Error(err)
}
}
func TestWsCancelAllOrders(t *testing.T) {
setupWsTests(t)
_, err := k.wsCancelAllOrders()
if err != nil {
if _, err := k.wsCancelAllOrders(); err != nil {
t.Error(err)
}
}
@@ -1994,6 +1993,7 @@ func Test_FormatExchangeKlineInterval(t *testing.T) {
test := testCases[x]
t.Run(test.name, func(t *testing.T) {
t.Parallel()
ret := k.FormatExchangeKlineInterval(test.interval)
if ret != test.output {

View File

@@ -188,7 +188,7 @@ type Orderbook struct {
// Spread holds the spread between trades
type Spread struct {
Time float64
Time time.Time
Bid float64
Ask float64
}

View File

@@ -717,16 +717,38 @@ func (k *Kraken) wsProcessTickers(channelData *WebsocketChannelData, data map[st
// wsProcessSpread converts spread/orderbook data and sends it to the datahandler
func (k *Kraken) wsProcessSpread(channelData *WebsocketChannelData, data []interface{}) {
bestBid := data[0].(string)
bestAsk := data[1].(string)
if len(data) < 5 {
k.Websocket.DataHandler <- fmt.Errorf("%s unexpected wsProcessSpread data length", k.Name)
return
}
bestBid, ok := data[0].(string)
if !ok {
k.Websocket.DataHandler <- fmt.Errorf("%s wsProcessSpread: unable to type assert bestBid", k.Name)
return
}
bestAsk, ok := data[1].(string)
if !ok {
k.Websocket.DataHandler <- fmt.Errorf("%s wsProcessSpread: unable to type assert bestAsk", k.Name)
return
}
timeData, err := strconv.ParseFloat(data[2].(string), 64)
if err != nil {
k.Websocket.DataHandler <- err
k.Websocket.DataHandler <- fmt.Errorf("%s wsProcessSpread: unable to parse timeData. Error: %s",
k.Name,
err)
return
}
bidVolume, ok := data[3].(string)
if !ok {
k.Websocket.DataHandler <- fmt.Errorf("%s wsProcessSpread: unable to type assert bidVolume", k.Name)
return
}
askVolume, ok := data[4].(string)
if !ok {
k.Websocket.DataHandler <- fmt.Errorf("%s wsProcessSpread: unable to type assert askVolume", k.Name)
return
}
bidVolume := data[3].(string)
askVolume := data[4].(string)
if k.Verbose {
log.Debugf(log.ExchangeSys,
"%v Spread data for '%v' received. Best bid: '%v' Best ask: '%v' Time: '%v', Bid volume '%v', Ask volume '%v'",
@@ -839,7 +861,13 @@ func (k *Kraken) wsProcessOrderBookPartial(channelData *WebsocketChannelData, as
// to respect both within a reasonable degree
var highestLastUpdate time.Time
for i := range askData {
asks := askData[i].([]interface{})
asks, ok := askData[i].([]interface{})
if !ok {
return errors.New("unable to type assert asks")
}
if len(asks) < 3 {
return errors.New("unexpected asks length")
}
price, err := strconv.ParseFloat(asks[0].(string), 64)
if err != nil {
return err
@@ -863,7 +891,13 @@ func (k *Kraken) wsProcessOrderBookPartial(channelData *WebsocketChannelData, as
}
for i := range bidData {
bids := bidData[i].([]interface{})
bids, ok := bidData[i].([]interface{})
if !ok {
return errors.New("unable to type assert bids")
}
if len(bids) < 3 {
return errors.New("unexpected bids length")
}
price, err := strconv.ParseFloat(bids[0].(string), 64)
if err != nil {
return err
@@ -906,7 +940,10 @@ func (k *Kraken) wsProcessOrderBookUpdate(channelData *WebsocketChannelData, ask
var highestLastUpdate time.Time
// Ask data is not always sent
for i := range askData {
asks := askData[i].([]interface{})
asks, ok := askData[i].([]interface{})
if !ok {
return errors.New("asks type assertion failure")
}
priceStr, ok := asks[0].(string)
if !ok {
@@ -966,7 +1003,10 @@ func (k *Kraken) wsProcessOrderBookUpdate(channelData *WebsocketChannelData, ask
// Bid data is not always sent
for i := range bidData {
bids := bidData[i].([]interface{})
bids, ok := bidData[i].([]interface{})
if !ok {
return errors.New("unable to type assert bids")
}
priceStr, ok := bids[0].(string)
if !ok {

View File

@@ -487,8 +487,7 @@ func (k *Kraken) UpdateTickers(ctx context.Context, a asset.Item) error {
// UpdateTicker updates and returns the ticker for a currency pair
func (k *Kraken) UpdateTicker(ctx context.Context, p currency.Pair, a asset.Item) (*ticker.Price, error) {
err := k.UpdateTickers(ctx, a)
if err != nil {
if err := k.UpdateTickers(ctx, a); err != nil {
return nil, err
}
return ticker.GetTicker(k.Name, p, a)
@@ -615,8 +614,7 @@ func (k *Kraken) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (a
})
}
}
err := account.Process(&info)
if err != nil {
if err := account.Process(&info); err != nil {
return account.Holdings{}, err
}
return info, nil
@@ -698,8 +696,7 @@ func (k *Kraken) GetHistoricTrades(_ context.Context, _ currency.Pair, _ asset.I
// SubmitOrder submits a new order
func (k *Kraken) SubmitOrder(ctx context.Context, s *order.Submit) (order.SubmitResponse, error) {
var submitOrderResponse order.SubmitResponse
err := s.Validate()
if err != nil {
if err := s.Validate(); err != nil {
return submitOrderResponse, err
}
switch s.AssetType {
@@ -707,7 +704,7 @@ func (k *Kraken) SubmitOrder(ctx context.Context, s *order.Submit) (order.Submit
if k.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
var resp string
s.Pair.Delimiter = "/" // required pair format: ISO 4217-A3
resp, err = k.wsAddOrder(&WsAddOrderRequest{
resp, err := k.wsAddOrder(&WsAddOrderRequest{
OrderType: s.Type.Lower(),
OrderSide: s.Side.Lower(),
Pair: s.Pair.String(),
@@ -721,7 +718,7 @@ func (k *Kraken) SubmitOrder(ctx context.Context, s *order.Submit) (order.Submit
submitOrderResponse.IsOrderPlaced = true
} else {
var response AddOrderResponse
response, err = k.AddOrder(ctx,
response, err := k.AddOrder(ctx,
s.Pair,
s.Side.String(),
s.Type.String(),